llgo/ssa: vkFuncDecl/vkFuncPtr/vkClosure

This commit is contained in:
xushiwei
2024-05-03 15:40:24 +08:00
parent 85da86a4f1
commit afd3d40348
5 changed files with 95 additions and 24 deletions

View File

@@ -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

View 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}
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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)
}