llgo/ssa: vkFuncDecl/vkFuncPtr/vkClosure
This commit is contained in:
@@ -63,6 +63,9 @@ func Malloc(size uintptr) Pointer
|
||||
//go:linkname Memcpy C.memcpy
|
||||
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
|
||||
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:
|
||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg)
|
||||
case *types.Basic:
|
||||
if t.Info()&types.IsString != 0 {
|
||||
if t.Kind() == types.String {
|
||||
return b.InlineCall(b.fn.pkg.rtFunc("StringLen"), arg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package ssa
|
||||
|
||||
import (
|
||||
"go/constant"
|
||||
"go/types"
|
||||
"runtime"
|
||||
|
||||
@@ -116,10 +115,11 @@ type aProgram struct {
|
||||
voidType llvm.Type
|
||||
voidPtrTy llvm.Type
|
||||
|
||||
rtStringTy llvm.Type
|
||||
rtIfaceTy llvm.Type
|
||||
rtSliceTy llvm.Type
|
||||
rtMapTy llvm.Type
|
||||
rtClosureTy llvm.Type
|
||||
rtStringTy llvm.Type
|
||||
rtIfaceTy llvm.Type
|
||||
rtSliceTy llvm.Type
|
||||
rtMapTy llvm.Type
|
||||
|
||||
anyTy Type
|
||||
voidTy Type
|
||||
@@ -185,6 +185,13 @@ func (p Program) rtType(name string) Type {
|
||||
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 {
|
||||
if p.rtIfaceTy.IsNil() {
|
||||
p.rtIfaceTy = p.rtType("Interface").ll
|
||||
@@ -305,10 +312,12 @@ type aPackage struct {
|
||||
|
||||
type Package = *aPackage
|
||||
|
||||
/*
|
||||
// NewConst creates a new named constant.
|
||||
func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
||||
return &aNamedConst{}
|
||||
}
|
||||
*/
|
||||
|
||||
// NewVar creates a new global variable.
|
||||
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 {
|
||||
return v
|
||||
}
|
||||
t := p.prog.llvmSignature(sig, false)
|
||||
t := p.prog.llvmFuncDecl(sig)
|
||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||
ret := newFunction(fn, t, p, p.prog)
|
||||
p.fns[name] = ret
|
||||
|
||||
61
ssa/type.go
61
ssa/type.go
@@ -40,12 +40,17 @@ const (
|
||||
vkString
|
||||
vkBool
|
||||
vkPtr
|
||||
vkFunc
|
||||
vkFuncDecl // func decl
|
||||
vkFuncPtr // func ptr in C
|
||||
vkClosure // func ptr in Go
|
||||
vkTuple
|
||||
vkDelayExpr = -1
|
||||
vkPhisExpr = -2
|
||||
)
|
||||
|
||||
// CFuncPtr represents a C function pointer.
|
||||
type CFuncPtr types.Signature
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
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 {
|
||||
ll llvm.Type
|
||||
t types.Type
|
||||
kind valueKind
|
||||
kind valueKind // value kind of llvm.Type
|
||||
}
|
||||
|
||||
type Type = *aType
|
||||
@@ -128,9 +140,11 @@ func (p Program) Field(typ Type, i int) Type {
|
||||
}
|
||||
|
||||
func (p Program) Type(typ types.Type) Type {
|
||||
/* TODO(xsw): no need?
|
||||
if sig, ok := typ.(*types.Signature); ok { // should methodToFunc
|
||||
return p.llvmSignature(sig, true)
|
||||
}
|
||||
*/
|
||||
if v := p.typs.At(typ); v != nil {
|
||||
return v.(Type)
|
||||
}
|
||||
@@ -139,14 +153,9 @@ func (p Program) Type(typ types.Type) Type {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p Program) llvmSignature(sig *types.Signature, isPtr bool) Type {
|
||||
func (p Program) llvmFuncDecl(sig *types.Signature) Type {
|
||||
sig = methodToFunc(sig)
|
||||
if v := p.typs.At(sig); v != nil {
|
||||
return v.(Type)
|
||||
}
|
||||
ret := p.toLLVMFunc(sig, isPtr)
|
||||
p.typs.Set(sig, ret)
|
||||
return ret
|
||||
return p.toLLVMFunc(sig, false, true) // don't save func decl to cache
|
||||
}
|
||||
|
||||
func (p Program) tyVoidPtr() llvm.Type {
|
||||
@@ -262,6 +271,8 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
||||
return p.toLLVMStruct(t)
|
||||
case *types.Named:
|
||||
return p.toLLVMNamed(t)
|
||||
case *types.Signature:
|
||||
return p.toLLVMFunc(t, false, false)
|
||||
case *types.Array:
|
||||
elem := p.Type(t.Elem())
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
n := tParams.Len()
|
||||
hasVArg := HasVArg(tParams, n)
|
||||
if hasVArg {
|
||||
n--
|
||||
if inC {
|
||||
hasVArg = HasVArg(tParams, n)
|
||||
if hasVArg {
|
||||
n--
|
||||
}
|
||||
}
|
||||
params := p.toLLVMTypes(tParams, n)
|
||||
out := sig.Results()
|
||||
@@ -325,11 +341,19 @@ func (p Program) toLLVMFunc(sig *types.Signature, isPtr bool) Type {
|
||||
default:
|
||||
ret = p.toLLVMTuple(out)
|
||||
}
|
||||
ft := llvm.FunctionType(ret, params, hasVArg)
|
||||
if isPtr {
|
||||
ft = llvm.PointerType(ft, 0)
|
||||
if inC || isDecl {
|
||||
ft = llvm.FunctionType(ret, params, hasVArg)
|
||||
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 {
|
||||
@@ -349,6 +373,9 @@ func (p Program) toLLVMNamed(typ *types.Named) Type {
|
||||
case *types.Struct:
|
||||
name := NameOf(typ)
|
||||
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:
|
||||
return p.Type(t)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user