llgo/ssa: vkFuncDecl/vkFuncPtr/vkClosure
This commit is contained in:
@@ -63,6 +63,9 @@ func Malloc(size uintptr) Pointer
|
|||||||
//go:linkname Memcpy C.memcpy
|
//go:linkname Memcpy C.memcpy
|
||||||
func Memcpy(dst, src Pointer, n uintptr) Pointer
|
func Memcpy(dst, src Pointer, n uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname Memset C.memset
|
||||||
|
func Memset(s Pointer, c Int, n uintptr) Pointer
|
||||||
|
|
||||||
//go:linkname Printf C.printf
|
//go:linkname Printf C.printf
|
||||||
func Printf(format *Char, __llgo_va_list ...any) Int
|
func Printf(format *Char, __llgo_va_list ...any) Int
|
||||||
|
|
||||||
|
|||||||
32
internal/runtime/z_closure.go
Normal file
32
internal/runtime/z_closure.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Closure represents a closure.
|
||||||
|
type Closure struct {
|
||||||
|
f unsafe.Pointer
|
||||||
|
data unsafe.Pointer // means no context if data is nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClosure creates a closure.
|
||||||
|
func NewClosure(f, data unsafe.Pointer) Closure {
|
||||||
|
return Closure{f, data}
|
||||||
|
}
|
||||||
@@ -979,7 +979,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg)
|
return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg)
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Info()&types.IsString != 0 {
|
if t.Kind() == types.String {
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("StringLen"), arg)
|
return b.InlineCall(b.fn.pkg.rtFunc("StringLen"), arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/constant"
|
|
||||||
"go/types"
|
"go/types"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
@@ -116,10 +115,11 @@ type aProgram struct {
|
|||||||
voidType llvm.Type
|
voidType llvm.Type
|
||||||
voidPtrTy llvm.Type
|
voidPtrTy llvm.Type
|
||||||
|
|
||||||
rtStringTy llvm.Type
|
rtClosureTy llvm.Type
|
||||||
rtIfaceTy llvm.Type
|
rtStringTy llvm.Type
|
||||||
rtSliceTy llvm.Type
|
rtIfaceTy llvm.Type
|
||||||
rtMapTy llvm.Type
|
rtSliceTy llvm.Type
|
||||||
|
rtMapTy llvm.Type
|
||||||
|
|
||||||
anyTy Type
|
anyTy Type
|
||||||
voidTy Type
|
voidTy Type
|
||||||
@@ -185,6 +185,13 @@ func (p Program) rtType(name string) Type {
|
|||||||
return p.Type(p.rtNamed(name))
|
return p.Type(p.rtNamed(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Program) rtClosure() llvm.Type {
|
||||||
|
if p.rtClosureTy.IsNil() {
|
||||||
|
p.rtClosureTy = p.rtType("Closure").ll
|
||||||
|
}
|
||||||
|
return p.rtClosureTy
|
||||||
|
}
|
||||||
|
|
||||||
func (p Program) rtIface() llvm.Type {
|
func (p Program) rtIface() llvm.Type {
|
||||||
if p.rtIfaceTy.IsNil() {
|
if p.rtIfaceTy.IsNil() {
|
||||||
p.rtIfaceTy = p.rtType("Interface").ll
|
p.rtIfaceTy = p.rtType("Interface").ll
|
||||||
@@ -305,10 +312,12 @@ type aPackage struct {
|
|||||||
|
|
||||||
type Package = *aPackage
|
type Package = *aPackage
|
||||||
|
|
||||||
|
/*
|
||||||
// NewConst creates a new named constant.
|
// NewConst creates a new named constant.
|
||||||
func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
||||||
return &aNamedConst{}
|
return &aNamedConst{}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// NewVar creates a new global variable.
|
// NewVar creates a new global variable.
|
||||||
func (p Package) NewVar(name string, typ types.Type) Global {
|
func (p Package) NewVar(name string, typ types.Type) Global {
|
||||||
@@ -329,7 +338,7 @@ func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
|||||||
if v, ok := p.fns[name]; ok {
|
if v, ok := p.fns[name]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
t := p.prog.llvmSignature(sig, false)
|
t := p.prog.llvmFuncDecl(sig)
|
||||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||||
ret := newFunction(fn, t, p, p.prog)
|
ret := newFunction(fn, t, p, p.prog)
|
||||||
p.fns[name] = ret
|
p.fns[name] = ret
|
||||||
|
|||||||
61
ssa/type.go
61
ssa/type.go
@@ -40,12 +40,17 @@ const (
|
|||||||
vkString
|
vkString
|
||||||
vkBool
|
vkBool
|
||||||
vkPtr
|
vkPtr
|
||||||
vkFunc
|
vkFuncDecl // func decl
|
||||||
|
vkFuncPtr // func ptr in C
|
||||||
|
vkClosure // func ptr in Go
|
||||||
vkTuple
|
vkTuple
|
||||||
vkDelayExpr = -1
|
vkDelayExpr = -1
|
||||||
vkPhisExpr = -2
|
vkPhisExpr = -2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CFuncPtr represents a C function pointer.
|
||||||
|
type CFuncPtr types.Signature
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -97,10 +102,17 @@ func methodToFunc(sig *types.Signature) *types.Signature {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CType convert a cdecl type into Go type.
|
||||||
|
func CType(typ types.Type) types.Type {
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type aType struct {
|
type aType struct {
|
||||||
ll llvm.Type
|
ll llvm.Type
|
||||||
t types.Type
|
t types.Type
|
||||||
kind valueKind
|
kind valueKind // value kind of llvm.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
type Type = *aType
|
type Type = *aType
|
||||||
@@ -128,9 +140,11 @@ func (p Program) Field(typ Type, i int) Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Type(typ types.Type) Type {
|
func (p Program) Type(typ types.Type) Type {
|
||||||
|
/* TODO(xsw): no need?
|
||||||
if sig, ok := typ.(*types.Signature); ok { // should methodToFunc
|
if sig, ok := typ.(*types.Signature); ok { // should methodToFunc
|
||||||
return p.llvmSignature(sig, true)
|
return p.llvmSignature(sig, true)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if v := p.typs.At(typ); v != nil {
|
if v := p.typs.At(typ); v != nil {
|
||||||
return v.(Type)
|
return v.(Type)
|
||||||
}
|
}
|
||||||
@@ -139,14 +153,9 @@ func (p Program) Type(typ types.Type) Type {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) llvmSignature(sig *types.Signature, isPtr bool) Type {
|
func (p Program) llvmFuncDecl(sig *types.Signature) Type {
|
||||||
sig = methodToFunc(sig)
|
sig = methodToFunc(sig)
|
||||||
if v := p.typs.At(sig); v != nil {
|
return p.toLLVMFunc(sig, false, true) // don't save func decl to cache
|
||||||
return v.(Type)
|
|
||||||
}
|
|
||||||
ret := p.toLLVMFunc(sig, isPtr)
|
|
||||||
p.typs.Set(sig, ret)
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) tyVoidPtr() llvm.Type {
|
func (p Program) tyVoidPtr() llvm.Type {
|
||||||
@@ -262,6 +271,8 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
return p.toLLVMStruct(t)
|
return p.toLLVMStruct(t)
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
return p.toLLVMNamed(t)
|
return p.toLLVMNamed(t)
|
||||||
|
case *types.Signature:
|
||||||
|
return p.toLLVMFunc(t, false, false)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.Type(t.Elem())
|
||||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||||
@@ -307,12 +318,17 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMFunc(sig *types.Signature, isPtr bool) Type {
|
func (p Program) toLLVMFunc(sig *types.Signature, inC, isDecl bool) Type {
|
||||||
|
var hasVArg bool
|
||||||
|
var kind valueKind
|
||||||
|
var ft llvm.Type
|
||||||
tParams := sig.Params()
|
tParams := sig.Params()
|
||||||
n := tParams.Len()
|
n := tParams.Len()
|
||||||
hasVArg := HasVArg(tParams, n)
|
if inC {
|
||||||
if hasVArg {
|
hasVArg = HasVArg(tParams, n)
|
||||||
n--
|
if hasVArg {
|
||||||
|
n--
|
||||||
|
}
|
||||||
}
|
}
|
||||||
params := p.toLLVMTypes(tParams, n)
|
params := p.toLLVMTypes(tParams, n)
|
||||||
out := sig.Results()
|
out := sig.Results()
|
||||||
@@ -325,11 +341,19 @@ func (p Program) toLLVMFunc(sig *types.Signature, isPtr bool) Type {
|
|||||||
default:
|
default:
|
||||||
ret = p.toLLVMTuple(out)
|
ret = p.toLLVMTuple(out)
|
||||||
}
|
}
|
||||||
ft := llvm.FunctionType(ret, params, hasVArg)
|
if inC || isDecl {
|
||||||
if isPtr {
|
ft = llvm.FunctionType(ret, params, hasVArg)
|
||||||
ft = llvm.PointerType(ft, 0)
|
if isDecl {
|
||||||
|
kind = vkFuncDecl
|
||||||
|
} else {
|
||||||
|
ft = llvm.PointerType(ft, 0)
|
||||||
|
kind = vkFuncPtr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ft = p.rtClosure()
|
||||||
|
kind = vkClosure
|
||||||
}
|
}
|
||||||
return &aType{ft, sig, vkFunc}
|
return &aType{ft, sig, kind}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) retType(sig *types.Signature) Type {
|
func (p Program) retType(sig *types.Signature) Type {
|
||||||
@@ -349,6 +373,9 @@ func (p Program) toLLVMNamed(typ *types.Named) Type {
|
|||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
name := NameOf(typ)
|
name := NameOf(typ)
|
||||||
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
|
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
|
||||||
|
case *types.Signature:
|
||||||
|
inC := true // TODO(xsw): how to check in C
|
||||||
|
return p.toLLVMFunc(t, inC, false)
|
||||||
default:
|
default:
|
||||||
return p.Type(t)
|
return p.Type(t)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user