llgo/ssa: introduce rawType
This commit is contained in:
@@ -21,10 +21,11 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
|
|||||||
br i1 %8, label %_llgo_2, label %_llgo_3
|
br i1 %8, label %_llgo_2, label %_llgo_3
|
||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_llgo_2: ; preds = %_llgo_1
|
||||||
%9 = extractvalue { ptr, ptr } %1, 0
|
%9 = extractvalue { i32 ()*, ptr } %1, 0
|
||||||
%10 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
%10 = call i32 ()* %9()
|
||||||
%11 = getelementptr inbounds i32, ptr %10, i64 %7
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
||||||
store i32 0, ptr %11, align 4
|
%12 = getelementptr inbounds i32, ptr %11, i64 %7
|
||||||
|
store ptr %10, ptr %12, align 8
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_1
|
_llgo_3: ; preds = %_llgo_1
|
||||||
@@ -184,10 +184,7 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewVar", name, typ)
|
log.Println("==> NewVar", name, typ)
|
||||||
}
|
}
|
||||||
if vtype == cVar {
|
g := pkg.NewVar(name, typ, llssa.Background(vtype))
|
||||||
typ = llssa.CType(typ)
|
|
||||||
}
|
|
||||||
g := pkg.NewVar(name, typ)
|
|
||||||
if vtype == goVar {
|
if vtype == goVar {
|
||||||
g.Init(p.prog.Null(g.Type))
|
g.Init(p.prog.Null(g.Type))
|
||||||
}
|
}
|
||||||
@@ -196,13 +193,13 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
|||||||
func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function, closure bool) llssa.Function {
|
func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function, closure bool) llssa.Function {
|
||||||
var sig = f.Signature
|
var sig = f.Signature
|
||||||
var name string
|
var name string
|
||||||
|
var ftype int
|
||||||
if closure {
|
if closure {
|
||||||
name = funcName(pkgTypes, f)
|
name, ftype = funcName(pkgTypes, f), goFunc
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewClosure", name, "type:", sig)
|
log.Println("==> NewClosure", name, "type:", sig)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var ftype int
|
|
||||||
name, ftype = p.funcName(pkgTypes, f, true)
|
name, ftype = p.funcName(pkgTypes, f, true)
|
||||||
switch ftype {
|
switch ftype {
|
||||||
case ignoredFunc, llgoInstr: // llgo extended instructions
|
case ignoredFunc, llgoInstr: // llgo extended instructions
|
||||||
@@ -211,11 +208,8 @@ func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
|
||||||
}
|
}
|
||||||
if ftype == cFunc {
|
|
||||||
sig = llssa.CFuncDecl(sig)
|
|
||||||
}
|
}
|
||||||
}
|
fn := pkg.NewFunc(name, sig, llssa.Background(ftype))
|
||||||
fn := pkg.NewFunc(name, sig)
|
|
||||||
p.inits = append(p.inits, func() {
|
p.inits = append(p.inits, func() {
|
||||||
p.fn = fn
|
p.fn = fn
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -265,7 +259,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
func callRuntimeInit(b llssa.Builder, pkg llssa.Package) {
|
||||||
fn := pkg.NewFunc(RuntimeInit, types.NewSignatureType(nil, nil, nil, nil, nil, false))
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
|
fn := pkg.NewFunc(RuntimeInit, sig, llssa.InC) // don't need to convert runtime.init
|
||||||
b.Call(fn.Expr)
|
b.Call(fn.Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +367,7 @@ func (p *context) compilePhis(b llssa.Builder, instrs []ssa.Instruction) []ssa.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
|
func (p *context) compilePhi(b llssa.Builder, v *ssa.Phi) (ret llssa.Expr) {
|
||||||
phi := b.Phi(p.prog.Type(v.Type()))
|
phi := b.Phi(p.prog.Type(v.Type(), llssa.InGo))
|
||||||
ret = phi.Expr
|
ret = phi.Expr
|
||||||
p.phis = append(p.phis, func() {
|
p.phis = append(p.phis, func() {
|
||||||
preds := v.Block().Preds
|
preds := v.Block().Preds
|
||||||
@@ -451,11 +446,11 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
case *ssa.ChangeType:
|
case *ssa.ChangeType:
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.ChangeType(p.prog.Type(t), x)
|
ret = b.ChangeType(p.prog.Type(t, llssa.InGo), x)
|
||||||
case *ssa.Convert:
|
case *ssa.Convert:
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.Convert(p.prog.Type(t), x)
|
ret = b.Convert(p.prog.Type(t, llssa.InGo), x)
|
||||||
case *ssa.FieldAddr:
|
case *ssa.FieldAddr:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.FieldAddr(x, v.Field)
|
ret = b.FieldAddr(x, v.Field)
|
||||||
@@ -464,7 +459,8 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ret = b.Alloc(t, v.Heap)
|
elem := p.prog.Type(t.Elem(), llssa.InGo)
|
||||||
|
ret = b.Alloc(elem, v.Heap)
|
||||||
case *ssa.IndexAddr:
|
case *ssa.IndexAddr:
|
||||||
vx := v.X
|
vx := v.X
|
||||||
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
||||||
@@ -505,24 +501,24 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
const (
|
const (
|
||||||
delayExpr = true // varargs: don't need to convert an expr to any
|
delayExpr = true // varargs: don't need to convert an expr to any
|
||||||
)
|
)
|
||||||
t := v.Type()
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.MakeInterface(t, x, delayExpr)
|
ret = b.MakeInterface(t, x, delayExpr)
|
||||||
case *ssa.MakeSlice:
|
case *ssa.MakeSlice:
|
||||||
var nCap llssa.Expr
|
var nCap llssa.Expr
|
||||||
t := v.Type()
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
nLen := p.compileValue(b, v.Len)
|
nLen := p.compileValue(b, v.Len)
|
||||||
if v.Cap != nil {
|
if v.Cap != nil {
|
||||||
nCap = p.compileValue(b, v.Cap)
|
nCap = p.compileValue(b, v.Cap)
|
||||||
}
|
}
|
||||||
ret = b.MakeSlice(p.prog.Type(t), nLen, nCap)
|
ret = b.MakeSlice(t, nLen, nCap)
|
||||||
case *ssa.MakeMap:
|
case *ssa.MakeMap:
|
||||||
var nReserve llssa.Expr
|
var nReserve llssa.Expr
|
||||||
t := v.Type()
|
t := p.prog.Type(v.Type(), llssa.InGo)
|
||||||
if v.Reserve != nil {
|
if v.Reserve != nil {
|
||||||
nReserve = p.compileValue(b, v.Reserve)
|
nReserve = p.compileValue(b, v.Reserve)
|
||||||
}
|
}
|
||||||
ret = b.MakeMap(p.prog.Type(t), nReserve)
|
ret = b.MakeMap(t, nReserve)
|
||||||
/*
|
/*
|
||||||
case *ssa.MakeClosure:
|
case *ssa.MakeClosure:
|
||||||
fn := p.compileValue(b, v.Fn)
|
fn := p.compileValue(b, v.Fn)
|
||||||
@@ -531,7 +527,8 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
*/
|
*/
|
||||||
case *ssa.TypeAssert:
|
case *ssa.TypeAssert:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.TypeAssert(x, p.prog.Type(v.AssertedType), v.CommaOk)
|
t := p.prog.Type(v.AssertedType, llssa.InGo)
|
||||||
|
ret = b.TypeAssert(x, t, v.CommaOk)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv))
|
panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv))
|
||||||
}
|
}
|
||||||
@@ -622,7 +619,7 @@ func (p *context) compileValue(b llssa.Builder, v ssa.Value) llssa.Expr {
|
|||||||
return g.Expr
|
return g.Expr
|
||||||
case *ssa.Const:
|
case *ssa.Const:
|
||||||
t := types.Default(v.Type())
|
t := types.Default(v.Type())
|
||||||
return b.Const(v.Value, p.prog.Type(t))
|
return b.Const(v.Value, p.prog.Type(t, llssa.InGo))
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("compileValue: unknown value - %T\n", v))
|
panic(fmt.Sprintf("compileValue: unknown value - %T\n", v))
|
||||||
}
|
}
|
||||||
|
|||||||
15
cl/import.go
15
cl/import.go
@@ -191,8 +191,8 @@ func checkCgo(fnName string) bool {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ignoredFunc = iota
|
ignoredFunc = iota
|
||||||
goFunc
|
goFunc = int(llssa.InGo)
|
||||||
cFunc
|
cFunc = int(llssa.InC)
|
||||||
llgoInstr = -1
|
llgoInstr = -1
|
||||||
|
|
||||||
llgoInstrBase = 0x80
|
llgoInstrBase = 0x80
|
||||||
@@ -222,8 +222,8 @@ func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (s
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ignoredVar = iota
|
ignoredVar = iota
|
||||||
goVar
|
goVar = int(llssa.InGo)
|
||||||
cVar
|
cVar = int(llssa.InC)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
func (p *context) varName(pkg *types.Package, v *ssa.Global) (vName string, vtype int) {
|
||||||
@@ -256,7 +256,8 @@ func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
|
|||||||
panic("unknown llgo instruction: " + name)
|
panic("unknown llgo instruction: " + name)
|
||||||
}
|
}
|
||||||
} else if ret = pkg.FuncOf(name); ret == nil {
|
} else if ret = pkg.FuncOf(name); ret == nil {
|
||||||
ret = pkg.NewFunc(name, fn.Signature)
|
sig := fn.Signature
|
||||||
|
ret = pkg.NewFunc(name, sig, llssa.Background(ftype))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -264,9 +265,9 @@ func (p *context) funcOf(fn *ssa.Function) (ret llssa.Function, ftype int) {
|
|||||||
func (p *context) varOf(v *ssa.Global) (ret llssa.Global) {
|
func (p *context) varOf(v *ssa.Global) (ret llssa.Global) {
|
||||||
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
|
pkgTypes := p.ensureLoaded(v.Pkg.Pkg)
|
||||||
pkg := p.pkg
|
pkg := p.pkg
|
||||||
name, _ := p.varName(pkgTypes, v)
|
name, vtype := p.varName(pkgTypes, v)
|
||||||
if ret = pkg.VarOf(name); ret == nil {
|
if ret = pkg.VarOf(name); ret == nil {
|
||||||
ret = pkg.NewVar(name, v.Type())
|
ret = pkg.NewVar(name, v.Type(), llssa.Background(vtype))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,9 @@
|
|||||||
package ssa_test
|
package ssa_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/types"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goplus/llgo/cl/cltest"
|
"github.com/goplus/llgo/cl/cltest"
|
||||||
"github.com/goplus/llgo/internal/typeutil"
|
|
||||||
"github.com/goplus/llgo/ssa"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
@@ -38,6 +35,7 @@ func TestRuntime(t *testing.T) {
|
|||||||
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
|
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
var m typeutil.Map
|
var m typeutil.Map
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
@@ -51,3 +49,4 @@ func TestMap(t *testing.T) {
|
|||||||
t.Fatal("At(csig):", v)
|
t.Fatal("At(csig):", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
22
ssa/decl.go
22
ssa/decl.go
@@ -25,6 +25,24 @@ import (
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
NameValist = "__llgo_va_list"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VArg() *types.Var {
|
||||||
|
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsVArg(arg *types.Var) bool {
|
||||||
|
return arg.Name() == NameValist
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasVArg(t *types.Tuple, n int) bool {
|
||||||
|
return n > 0 && IsVArg(t.At(n-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
type aNamedConst struct {
|
type aNamedConst struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +141,7 @@ func newFunction(fn llvm.Value, t Type, pkg Package, prog Program) Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
||||||
sig := fn.t.(*types.Signature)
|
sig := fn.raw.Type.(*types.Signature)
|
||||||
in := sig.Params()
|
in := sig.Params()
|
||||||
if n := in.Len(); n > 0 {
|
if n := in.Len(); n > 0 {
|
||||||
if hasVArg = HasVArg(in, n); hasVArg {
|
if hasVArg = HasVArg(in, n); hasVArg {
|
||||||
@@ -131,7 +149,7 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
|
|||||||
}
|
}
|
||||||
params = make([]Type, n)
|
params = make([]Type, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
params[i] = prog.Type(in.At(i).Type())
|
params[i] = prog.rawType(in.At(i).Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
107
ssa/expr.go
107
ssa/expr.go
@@ -41,20 +41,13 @@ func (v Expr) IsNil() bool {
|
|||||||
return v.Type == nil
|
return v.Type == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// TypeOf returns the type of the expression.
|
|
||||||
func (v Expr) TypeOf() types.Type {
|
|
||||||
return v.t
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Do evaluates the delay expression and returns the result.
|
// Do evaluates the delay expression and returns the result.
|
||||||
func (v Expr) Do(b Builder) Expr {
|
func (v Expr) Do(b Builder) Expr {
|
||||||
switch vt := v.Type; vt.kind {
|
switch vt := v.Type; vt.kind {
|
||||||
case vkDelayExpr:
|
case vkDelayExpr:
|
||||||
return vt.t.(delayExprTy)()
|
return vt.raw.Type.(delayExprTy)()
|
||||||
case vkPhisExpr:
|
case vkPhisExpr:
|
||||||
e := vt.t.(*phisExprTy)
|
e := vt.raw.Type.(*phisExprTy)
|
||||||
return b.aggregateValue(e.Type, e.phis...)
|
return b.aggregateValue(e.Type, e.phis...)
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
@@ -64,7 +57,7 @@ func (v Expr) Do(b Builder) Expr {
|
|||||||
|
|
||||||
// DelayExpr returns a delay expression.
|
// DelayExpr returns a delay expression.
|
||||||
func DelayExpr(f func() Expr) Expr {
|
func DelayExpr(f func() Expr) Expr {
|
||||||
return Expr{Type: &aType{t: delayExprTy(f), kind: vkDelayExpr}}
|
return Expr{Type: &aType{raw: rawType{delayExprTy(f)}, kind: vkDelayExpr}}
|
||||||
}
|
}
|
||||||
|
|
||||||
type delayExprTy func() Expr
|
type delayExprTy func() Expr
|
||||||
@@ -93,7 +86,7 @@ func (p phisExprTy) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func phisExpr(t Type, phis []llvm.Value) Expr {
|
func phisExpr(t Type, phis []llvm.Value) Expr {
|
||||||
return Expr{Type: &aType{t: &phisExprTy{phis, t}, kind: vkPhisExpr}}
|
return Expr{Type: &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -148,7 +141,8 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
|
|||||||
if v == nil {
|
if v == nil {
|
||||||
return prog.Null(typ)
|
return prog.Null(typ)
|
||||||
}
|
}
|
||||||
switch t := typ.t.(type) {
|
raw := typ.raw.Type
|
||||||
|
switch t := raw.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := t.Kind()
|
kind := t.Kind()
|
||||||
switch {
|
switch {
|
||||||
@@ -170,7 +164,7 @@ func (b Builder) Const(v constant.Value, typ Type) Expr {
|
|||||||
return b.Str(constant.StringVal(v))
|
return b.Str(constant.StringVal(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("unsupported Const: %v, %v", v, typ.t))
|
panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SizeOf returns the size of a type.
|
// SizeOf returns the size of a type.
|
||||||
@@ -362,11 +356,11 @@ func (b Builder) UnOp(op token.Token, x Expr) Expr {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
func checkExpr(v Expr, t types.Type, b Builder) Expr {
|
func checkExpr(v Expr, t types.Type, b Builder) Expr {
|
||||||
if _, ok := t.(*types.Signature); ok {
|
if _, ok := t.(*types.Struct); ok {
|
||||||
if v.kind != vkClosure {
|
if v.kind != vkClosure {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
nilVal := prog.Null(prog.VoidPtr()).impl
|
nilVal := prog.Null(prog.VoidPtr()).impl
|
||||||
return b.aggregateValue(prog.Type(t), v.impl, nilVal)
|
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
@@ -413,7 +407,7 @@ func (p Phi) AddIncoming(b Builder, bblks []BasicBlock, f func(i int) Expr) {
|
|||||||
p.impl.AddIncoming(vs, bs)
|
p.impl.AddIncoming(vs, bs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := p.t.(*phisExprTy)
|
e := p.raw.Type.(*phisExprTy)
|
||||||
phis := e.phis
|
phis := e.phis
|
||||||
vals := make([][]llvm.Value, len(phis))
|
vals := make([][]llvm.Value, len(phis))
|
||||||
for iblk, blk := range bblks {
|
for iblk, blk := range bblks {
|
||||||
@@ -436,7 +430,7 @@ func (p Phi) AddIncoming(b Builder, bblks []BasicBlock, f func(i int) Expr) {
|
|||||||
// Phi returns a phi node.
|
// Phi returns a phi node.
|
||||||
func (b Builder) Phi(t Type) Phi {
|
func (b Builder) Phi(t Type) Phi {
|
||||||
impl := b.impl
|
impl := b.impl
|
||||||
switch tund := t.t.Underlying().(type) {
|
switch tund := t.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := tund.Kind()
|
kind := tund.Kind()
|
||||||
switch kind {
|
switch kind {
|
||||||
@@ -447,6 +441,8 @@ func (b Builder) Phi(t Type) Phi {
|
|||||||
phis[1] = llvm.CreatePHI(impl, prog.tyInt())
|
phis[1] = llvm.CreatePHI(impl, prog.tyInt())
|
||||||
return Phi{phisExpr(t, phis)}
|
return Phi{phisExpr(t, phis)}
|
||||||
}
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
panic("todo")
|
||||||
}
|
}
|
||||||
phi := llvm.CreatePHI(impl, t.ll)
|
phi := llvm.CreatePHI(impl, t.ll)
|
||||||
return Phi{Expr{phi, t}}
|
return Phi{Expr{phi, t}}
|
||||||
@@ -484,7 +480,7 @@ func (b Builder) Store(ptr, val Expr) Builder {
|
|||||||
// aggregateValue yields the value of the aggregate X with the fields
|
// aggregateValue yields the value of the aggregate X with the fields
|
||||||
func (b Builder) aggregateValue(t Type, flds ...llvm.Value) Expr {
|
func (b Builder) aggregateValue(t Type, flds ...llvm.Value) Expr {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("AggregateValue %v, %v\n", t.t, flds)
|
log.Printf("AggregateValue %v, %v\n", t.RawType(), flds)
|
||||||
}
|
}
|
||||||
impl := b.impl
|
impl := b.impl
|
||||||
tll := t.ll
|
tll := t.ll
|
||||||
@@ -542,8 +538,9 @@ func (b Builder) Field(x Expr, idx int) Expr {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Field %v, %d\n", x.impl, idx)
|
log.Printf("Field %v, %d\n", x.impl, idx)
|
||||||
}
|
}
|
||||||
telem := b.Prog.Field(x.Type, idx)
|
tfld := b.Prog.Field(x.Type, idx)
|
||||||
return Expr{llvm.CreateExtractValue(b.impl, x.impl, idx), telem}
|
fld := llvm.CreateExtractValue(b.impl, x.impl, idx)
|
||||||
|
return Expr{fld, tfld}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IndexAddr instruction yields the address of the element at
|
// The IndexAddr instruction yields the address of the element at
|
||||||
@@ -565,7 +562,7 @@ func (b Builder) IndexAddr(x, idx Expr) Expr {
|
|||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
telem := prog.Index(x.Type)
|
telem := prog.Index(x.Type)
|
||||||
pt := prog.Pointer(telem)
|
pt := prog.Pointer(telem)
|
||||||
switch x.t.Underlying().(type) {
|
switch x.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
||||||
@@ -591,12 +588,12 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr {
|
|||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
var telem Type
|
var telem Type
|
||||||
var ptr Expr
|
var ptr Expr
|
||||||
switch t := x.t.Underlying().(type) {
|
switch t := x.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Info()&types.IsString == 0 {
|
if t.Info()&types.IsString == 0 {
|
||||||
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
||||||
}
|
}
|
||||||
telem = prog.Type(types.Typ[types.Byte])
|
telem = prog.rawType(types.Typ[types.Byte])
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
@@ -639,7 +636,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
if low.IsNil() {
|
if low.IsNil() {
|
||||||
low = prog.IntVal(0, prog.Int())
|
low = prog.IntVal(0, prog.Int())
|
||||||
}
|
}
|
||||||
switch t := x.t.Underlying().(type) {
|
switch t := x.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Kind() != types.String {
|
if t.Kind() != types.String {
|
||||||
panic(fmt.Errorf("invalid operation: cannot slice %v", t))
|
panic(fmt.Errorf("invalid operation: cannot slice %v", t))
|
||||||
@@ -662,7 +659,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
telem := t.Elem()
|
telem := t.Elem()
|
||||||
switch te := telem.Underlying().(type) {
|
switch te := telem.Underlying().(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := prog.Type(te.Elem())
|
elem := prog.rawType(te.Elem())
|
||||||
ret.Type = prog.Slice(elem)
|
ret.Type = prog.Slice(elem)
|
||||||
nEltSize = b.SizeOf(elem)
|
nEltSize = b.SizeOf(elem)
|
||||||
nCap = prog.IntVal(uint64(te.Len()), prog.Int())
|
nCap = prog.IntVal(uint64(te.Len()), prog.Int())
|
||||||
@@ -692,7 +689,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
// t1 = make StringIntMap t0
|
// t1 = make StringIntMap t0
|
||||||
func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeMap %v, %v\n", t, nReserve.impl)
|
log.Printf("MakeMap %v, %v\n", t.RawType(), nReserve.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
ret.Type = t
|
ret.Type = t
|
||||||
@@ -717,7 +714,7 @@ func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
|||||||
// t1 = make StringSlice 1:int t0
|
// t1 = make StringSlice 1:int t0
|
||||||
func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeSlice %v, %v, %v\n", t, len.impl, cap.impl)
|
log.Printf("MakeSlice %v, %v, %v\n", t.RawType(), len.impl, cap.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
if cap.IsNil() {
|
if cap.IsNil() {
|
||||||
@@ -752,13 +749,12 @@ func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
|||||||
//
|
//
|
||||||
// t0 = local int
|
// t0 = local int
|
||||||
// t1 = new int
|
// t1 = new int
|
||||||
func (b Builder) Alloc(t *types.Pointer, heap bool) (ret Expr) {
|
func (b Builder) Alloc(elem Type, heap bool) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Alloc %v, %v\n", t, heap)
|
log.Printf("Alloc %v, %v\n", elem.RawType(), heap)
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
elem := prog.Type(t.Elem())
|
|
||||||
size := b.SizeOf(elem)
|
size := b.SizeOf(elem)
|
||||||
if heap {
|
if heap {
|
||||||
ret = b.InlineCall(pkg.rtFunc("AllocZ"), size)
|
ret = b.InlineCall(pkg.rtFunc("AllocZ"), size)
|
||||||
@@ -766,7 +762,7 @@ func (b Builder) Alloc(t *types.Pointer, heap bool) (ret Expr) {
|
|||||||
ret = Expr{llvm.CreateAlloca(b.impl, elem.ll), prog.VoidPtr()}
|
ret = Expr{llvm.CreateAlloca(b.impl, elem.ll), prog.VoidPtr()}
|
||||||
ret.impl = b.InlineCall(pkg.rtFunc("Zeroinit"), ret, size).impl
|
ret.impl = b.InlineCall(pkg.rtFunc("Zeroinit"), ret, size).impl
|
||||||
}
|
}
|
||||||
ret.Type = prog.Type(t)
|
ret.Type = prog.Pointer(elem)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,7 +774,7 @@ func (b Builder) Alloca(n Expr) (ret Expr) {
|
|||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
telem := prog.tyInt8()
|
telem := prog.tyInt8()
|
||||||
ret.impl = llvm.CreateArrayAlloca(b.impl, telem, n.impl)
|
ret.impl = llvm.CreateArrayAlloca(b.impl, telem, n.impl)
|
||||||
ret.Type = &aType{prog.tyVoidPtr(), types.Typ[types.UnsafePointer], vkPtr}
|
ret.Type = prog.VoidPtr()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,13 +829,14 @@ func (b Builder) AllocaCStr(gostr Expr) (ret Expr) {
|
|||||||
// t1 = changetype *int <- IntPtr (t0)
|
// t1 = changetype *int <- IntPtr (t0)
|
||||||
func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("ChangeType %v, %v\n", t.t, x.impl)
|
log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl)
|
||||||
}
|
}
|
||||||
typ := t.t
|
typ := t.raw.Type
|
||||||
switch typ.(type) {
|
switch typ.(type) {
|
||||||
default:
|
default:
|
||||||
|
// TODO(xsw): remove instr name
|
||||||
ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast")
|
ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast")
|
||||||
ret.Type = b.Prog.Type(typ)
|
ret.Type = b.Prog.rawType(typ)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,8 +868,8 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
|
|||||||
//
|
//
|
||||||
// t1 = convert []byte <- string (t0)
|
// t1 = convert []byte <- string (t0)
|
||||||
func (b Builder) Convert(t Type, x Expr) (ret Expr) {
|
func (b Builder) Convert(t Type, x Expr) (ret Expr) {
|
||||||
typ := t.t
|
typ := t.raw.Type
|
||||||
ret.Type = b.Prog.Type(typ)
|
ret.Type = b.Prog.rawType(typ)
|
||||||
switch und := typ.Underlying().(type) {
|
switch und := typ.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := und.Kind()
|
kind := und.Kind()
|
||||||
@@ -923,17 +920,17 @@ func castPtr(b llvm.Builder, x llvm.Value, t llvm.Type) llvm.Value {
|
|||||||
//
|
//
|
||||||
// t1 = make interface{} <- int (42:int)
|
// t1 = make interface{} <- int (42:int)
|
||||||
// t2 = make Stringer <- t0
|
// t2 = make Stringer <- t0
|
||||||
func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Expr) {
|
func (b Builder) MakeInterface(tinter Type, x Expr, mayDelay bool) (ret Expr) {
|
||||||
|
raw := tinter.raw.Type
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeInterface %v, %v\n", inter, x.impl)
|
log.Printf("MakeInterface %v, %v\n", raw, x.impl)
|
||||||
}
|
}
|
||||||
tiund := inter.Underlying().(*types.Interface)
|
tiund := raw.Underlying().(*types.Interface)
|
||||||
isAny := tiund.Empty()
|
isAny := tiund.Empty()
|
||||||
fnDo := func() Expr {
|
fnDo := func() Expr {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.fn.pkg
|
||||||
tinter := prog.Type(inter)
|
switch tx := x.raw.Type.Underlying().(type) {
|
||||||
switch tx := x.t.Underlying().(type) {
|
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := tx.Kind()
|
kind := tx.Kind()
|
||||||
switch {
|
switch {
|
||||||
@@ -995,7 +992,7 @@ func (b Builder) MakeInterface(inter types.Type, x Expr, mayDelay bool) (ret Exp
|
|||||||
// t3 = typeassert,ok t2.(T)
|
// t3 = typeassert,ok t2.(T)
|
||||||
func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.t, commaOk)
|
log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.raw.Type, commaOk)
|
||||||
}
|
}
|
||||||
switch assertedTyp.kind {
|
switch assertedTyp.kind {
|
||||||
case vkSigned, vkUnsigned, vkFloat:
|
case vkSigned, vkUnsigned, vkFloat:
|
||||||
@@ -1006,7 +1003,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
|||||||
}
|
}
|
||||||
fn := pkg.rtFunc(fnName)
|
fn := pkg.rtFunc(fnName)
|
||||||
var kind types.BasicKind
|
var kind types.BasicKind
|
||||||
switch t := assertedTyp.t.(type) {
|
switch t := assertedTyp.raw.Type.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind = t.Kind()
|
kind = t.Kind()
|
||||||
default:
|
default:
|
||||||
@@ -1044,7 +1041,7 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
if name == "" {
|
if name == "" {
|
||||||
name = "closure"
|
name = "closure"
|
||||||
}
|
}
|
||||||
fmt.Fprint(&b, "Call ", fn.t, " ", name)
|
fmt.Fprint(&b, "Call ", fn.raw.Type, " ", name)
|
||||||
sep := ": "
|
sep := ": "
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
fmt.Fprint(&b, sep, arg.impl)
|
fmt.Fprint(&b, sep, arg.impl)
|
||||||
@@ -1053,25 +1050,19 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
log.Println(b.String())
|
log.Println(b.String())
|
||||||
}
|
}
|
||||||
var sig *types.Signature
|
var sig *types.Signature
|
||||||
var t = fn.t
|
var raw = fn.raw.Type
|
||||||
normal := true
|
|
||||||
switch fn.kind {
|
switch fn.kind {
|
||||||
case vkClosure:
|
case vkClosure:
|
||||||
fn = b.Field(fn, 0)
|
fn := b.Field(fn, 0)
|
||||||
t = fn.t
|
raw = fn.raw.Type
|
||||||
normal = false
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case vkFuncDecl, vkFuncPtr:
|
case vkFunc:
|
||||||
sig = t.(*types.Signature)
|
sig = raw.(*types.Signature)
|
||||||
ret.Type = prog.retType(sig)
|
ret.Type = prog.retType(sig)
|
||||||
default:
|
default:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
if normal {
|
|
||||||
ret.impl = llvm.CreateCall(b.impl, fn.ll, fn.impl, llvmValues(args, sig.Params(), b))
|
ret.impl = llvm.CreateCall(b.impl, fn.ll, fn.impl, llvmValues(args, sig.Params(), b))
|
||||||
} else {
|
|
||||||
ret = prog.IntVal(0, prog.Type(types.Typ[types.Int32]))
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,7 +1077,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
case "len":
|
case "len":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch t := arg.t.Underlying().(type) {
|
switch t := arg.raw.Type.Underlying().(type) {
|
||||||
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:
|
||||||
@@ -1098,7 +1089,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
case "cap":
|
case "cap":
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch arg.t.Underlying().(type) {
|
switch arg.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceCap"), arg)
|
return b.InlineCall(b.fn.pkg.rtFunc("SliceCap"), arg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package ssa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/typeutil"
|
"github.com/goplus/llgo/internal/typeutil"
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
@@ -95,8 +96,8 @@ func Initialize(flags InitFlags) {
|
|||||||
|
|
||||||
type aProgram struct {
|
type aProgram struct {
|
||||||
ctx llvm.Context
|
ctx llvm.Context
|
||||||
typs typeutil.Map
|
typs typeutil.Map // rawType -> Type
|
||||||
// sizs types.Sizes
|
gocvt goTypes
|
||||||
|
|
||||||
rt *types.Package
|
rt *types.Package
|
||||||
rtget func() *types.Package
|
rtget func() *types.Package
|
||||||
@@ -152,7 +153,7 @@ func NewProgram(target *Target) Program {
|
|||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
ctx.Finalize()
|
ctx.Finalize()
|
||||||
*/
|
*/
|
||||||
return &aProgram{ctx: ctx, target: target, td: td}
|
return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRuntime sets the runtime.
|
// SetRuntime sets the runtime.
|
||||||
@@ -180,11 +181,13 @@ func (p Program) runtime() *types.Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) rtNamed(name string) *types.Named {
|
func (p Program) rtNamed(name string) *types.Named {
|
||||||
return p.runtime().Scope().Lookup(name).Type().(*types.Named)
|
t := p.runtime().Scope().Lookup(name).Type().(*types.Named)
|
||||||
|
t, _ = p.gocvt.cvtNamed(t)
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) rtType(name string) Type {
|
func (p Program) rtType(name string) Type {
|
||||||
return p.Type(p.rtNamed(name))
|
return p.rawType(p.rtNamed(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) rtIface() llvm.Type {
|
func (p Program) rtIface() llvm.Type {
|
||||||
@@ -229,14 +232,14 @@ func (p Program) NewPackage(name, pkgPath string) Package {
|
|||||||
// Void returns void type.
|
// Void returns void type.
|
||||||
func (p Program) Void() Type {
|
func (p Program) Void() Type {
|
||||||
if p.voidTy == nil {
|
if p.voidTy == nil {
|
||||||
p.voidTy = &aType{p.tyVoid(), types.Typ[types.Invalid], vkInvalid}
|
p.voidTy = &aType{p.tyVoid(), rawType{types.Typ[types.Invalid]}, vkInvalid}
|
||||||
}
|
}
|
||||||
return p.voidTy
|
return p.voidTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) VoidPtr() Type {
|
func (p Program) VoidPtr() Type {
|
||||||
if p.voidPtr == nil {
|
if p.voidPtr == nil {
|
||||||
p.voidPtr = p.Type(types.Typ[types.UnsafePointer])
|
p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
|
||||||
}
|
}
|
||||||
return p.voidPtr
|
return p.voidPtr
|
||||||
}
|
}
|
||||||
@@ -244,21 +247,21 @@ func (p Program) VoidPtr() Type {
|
|||||||
// Bool returns bool type.
|
// Bool returns bool type.
|
||||||
func (p Program) Bool() Type {
|
func (p Program) Bool() Type {
|
||||||
if p.boolTy == nil {
|
if p.boolTy == nil {
|
||||||
p.boolTy = p.Type(types.Typ[types.Bool])
|
p.boolTy = p.rawType(types.Typ[types.Bool])
|
||||||
}
|
}
|
||||||
return p.boolTy
|
return p.boolTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) CStr() Type {
|
func (p Program) CStr() Type {
|
||||||
if p.cstrTy == nil { // *int8
|
if p.cstrTy == nil { // *int8
|
||||||
p.cstrTy = p.Type(types.NewPointer(types.Typ[types.Int8]))
|
p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
|
||||||
}
|
}
|
||||||
return p.cstrTy
|
return p.cstrTy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) String() Type {
|
func (p Program) String() Type {
|
||||||
if p.stringTy == nil {
|
if p.stringTy == nil {
|
||||||
p.stringTy = p.Type(types.Typ[types.String])
|
p.stringTy = p.rawType(types.Typ[types.String])
|
||||||
}
|
}
|
||||||
return p.stringTy
|
return p.stringTy
|
||||||
}
|
}
|
||||||
@@ -266,7 +269,7 @@ func (p Program) String() Type {
|
|||||||
// Any returns any type.
|
// Any returns any type.
|
||||||
func (p Program) Any() Type {
|
func (p Program) Any() Type {
|
||||||
if p.anyTy == nil {
|
if p.anyTy == nil {
|
||||||
p.anyTy = p.Type(tyAny)
|
p.anyTy = p.rawType(tyAny)
|
||||||
}
|
}
|
||||||
return p.anyTy
|
return p.anyTy
|
||||||
}
|
}
|
||||||
@@ -274,7 +277,7 @@ func (p Program) Any() Type {
|
|||||||
// Int returns int type.
|
// Int returns int type.
|
||||||
func (p Program) Int() Type {
|
func (p Program) Int() Type {
|
||||||
if p.intTy == nil {
|
if p.intTy == nil {
|
||||||
p.intTy = p.Type(types.Typ[types.Int])
|
p.intTy = p.rawType(types.Typ[types.Int])
|
||||||
}
|
}
|
||||||
return p.intTy
|
return p.intTy
|
||||||
}
|
}
|
||||||
@@ -282,7 +285,7 @@ func (p Program) Int() Type {
|
|||||||
// Uintptr returns uintptr type.
|
// Uintptr returns uintptr type.
|
||||||
func (p Program) Uintptr() Type {
|
func (p Program) Uintptr() Type {
|
||||||
if p.uintptrTy == nil {
|
if p.uintptrTy == nil {
|
||||||
p.uintptrTy = p.Type(types.Typ[types.Uintptr])
|
p.uintptrTy = p.rawType(types.Typ[types.Uintptr])
|
||||||
}
|
}
|
||||||
return p.uintptrTy
|
return p.uintptrTy
|
||||||
}
|
}
|
||||||
@@ -290,7 +293,7 @@ func (p Program) Uintptr() Type {
|
|||||||
// Float64 returns float64 type.
|
// Float64 returns float64 type.
|
||||||
func (p Program) Float64() Type {
|
func (p Program) Float64() Type {
|
||||||
if p.f64Ty == nil {
|
if p.f64Ty == nil {
|
||||||
p.f64Ty = p.Type(types.Typ[types.Float64])
|
p.f64Ty = p.rawType(types.Typ[types.Float64])
|
||||||
}
|
}
|
||||||
return p.f64Ty
|
return p.f64Ty
|
||||||
}
|
}
|
||||||
@@ -322,8 +325,8 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// 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, bg Background) Global {
|
||||||
t := p.prog.Type(typ)
|
t := p.prog.Type(typ, bg)
|
||||||
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
||||||
ret := &aGlobal{Expr{gbl, t}}
|
ret := &aGlobal{Expr{gbl, t}}
|
||||||
p.vars[name] = ret
|
p.vars[name] = ret
|
||||||
@@ -336,26 +339,30 @@ func (p Package) VarOf(name string) Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewFunc creates a new function.
|
// NewFunc creates a new function.
|
||||||
func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Function {
|
||||||
if v, ok := p.fns[name]; ok {
|
if v, ok := p.fns[name]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
t := p.prog.llvmFuncDecl(sig)
|
t := p.prog.FuncDecl(sig, bg)
|
||||||
|
if debugInstr {
|
||||||
|
log.Println("NewFunc", name, t.raw.Type)
|
||||||
|
}
|
||||||
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
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncOf returns a function by name.
|
|
||||||
func (p Package) FuncOf(name string) Function {
|
|
||||||
return p.fns[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Package) rtFunc(fnName string) Expr {
|
func (p Package) rtFunc(fnName string) Expr {
|
||||||
fn := p.prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
fn := p.prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
||||||
name := FullName(fn.Pkg(), fnName)
|
name := FullName(fn.Pkg(), fnName)
|
||||||
return p.NewFunc(name, fn.Type().(*types.Signature)).Expr
|
sig := fn.Type().(*types.Signature)
|
||||||
|
return p.NewFunc(name, sig, InGo).Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncOf returns a function by name.
|
||||||
|
func (p Package) FuncOf(name string) Function {
|
||||||
|
return p.fns[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ func TestIndexType(t *testing.T) {
|
|||||||
indexType(types.Typ[types.Int])
|
indexType(types.Typ[types.Int])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func TestCvtCType(t *testing.T) {
|
func TestCvtCType(t *testing.T) {
|
||||||
test := func(typ types.Type) {
|
test := func(typ types.Type) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -59,7 +60,7 @@ func TestCvtCType(t *testing.T) {
|
|||||||
t.Log("cvtCType: no error?")
|
t.Log("cvtCType: no error?")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
cvtCType(typ)
|
cvtGoType(typ)
|
||||||
}
|
}
|
||||||
test(types.NewInterfaceType(nil, nil))
|
test(types.NewInterfaceType(nil, nil))
|
||||||
|
|
||||||
@@ -77,6 +78,7 @@ func TestCFuncPtr(t *testing.T) {
|
|||||||
t.Fatal("TestCFuncPtr failed")
|
t.Fatal("TestCFuncPtr failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func TestUserdefExpr(t *testing.T) {
|
func TestUserdefExpr(t *testing.T) {
|
||||||
a := delayExprTy(nil)
|
a := delayExprTy(nil)
|
||||||
@@ -118,9 +120,9 @@ func assertPkg(t *testing.T, p Package, expected string) {
|
|||||||
func TestVar(t *testing.T) {
|
func TestVar(t *testing.T) {
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
a := pkg.NewVar("a", types.Typ[types.Int])
|
a := pkg.NewVar("a", types.Typ[types.Int], InGo)
|
||||||
a.Init(prog.Val(100))
|
a.Init(prog.Val(100))
|
||||||
b := pkg.NewVar("b", types.Typ[types.Int])
|
b := pkg.NewVar("b", types.Typ[types.Int], InGo)
|
||||||
b.Init(a.Expr)
|
b.Init(a.Expr)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -135,7 +137,7 @@ func TestConst(t *testing.T) {
|
|||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Bool]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Bool]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, rets, false)
|
||||||
b := pkg.NewFunc("fn", sig).MakeBody(1)
|
b := pkg.NewFunc("fn", sig, InGo).MakeBody(1)
|
||||||
b.Return(b.Const(constant.MakeBool(true), prog.Bool()))
|
b.Return(b.Const(constant.MakeBool(true), prog.Bool()))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -152,7 +154,7 @@ func TestStruct(t *testing.T) {
|
|||||||
|
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
pkg.NewVar("a", empty)
|
pkg.NewVar("a", empty, InGo)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
@@ -169,7 +171,7 @@ func TestNamedStruct(t *testing.T) {
|
|||||||
|
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
pkg.NewVar("a", empty)
|
pkg.NewVar("a", empty, InGo)
|
||||||
if pkg.VarOf("a") == nil {
|
if pkg.VarOf("a") == nil {
|
||||||
t.Fatal("VarOf failed")
|
t.Fatal("VarOf failed")
|
||||||
}
|
}
|
||||||
@@ -187,7 +189,7 @@ func TestDeclFunc(t *testing.T) {
|
|||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, nil, false)
|
||||||
pkg.NewFunc("fn", sig)
|
pkg.NewFunc("fn", sig, InGo)
|
||||||
if pkg.FuncOf("fn") == nil {
|
if pkg.FuncOf("fn") == nil {
|
||||||
t.Fatal("FuncOf failed")
|
t.Fatal("FuncOf failed")
|
||||||
}
|
}
|
||||||
@@ -209,7 +211,7 @@ func TestBasicFunc(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
pkg.NewFunc("fn", sig).MakeBody(1).
|
pkg.NewFunc("fn", sig, InGo).MakeBody(1).
|
||||||
Return(prog.Val(1))
|
Return(prog.Val(1))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -229,7 +231,7 @@ func TestFuncParam(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
fn.MakeBody(1).Return(fn.Param(0))
|
fn.MakeBody(1).Return(fn.Param(0))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
@@ -250,12 +252,12 @@ func TestFuncCall(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
fn.MakeBody(1).
|
fn.MakeBody(1).
|
||||||
Return(prog.Val(1))
|
Return(prog.Val(1))
|
||||||
|
|
||||||
sigMain := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sigMain := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
b := pkg.NewFunc("main", sigMain).MakeBody(1)
|
b := pkg.NewFunc("main", sigMain, InGo).MakeBody(1)
|
||||||
b.Call(fn.Expr, prog.Val(1), prog.Val(1.2))
|
b.Call(fn.Expr, prog.Val(1), prog.Val(1.2))
|
||||||
b.Return()
|
b.Return()
|
||||||
|
|
||||||
@@ -284,8 +286,8 @@ func TestFuncMultiRet(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "c", types.Typ[types.Int]),
|
types.NewVar(0, nil, "c", types.Typ[types.Int]),
|
||||||
types.NewVar(0, nil, "d", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "d", types.Typ[types.Float64]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
a := pkg.NewVar("a", types.Typ[types.Int])
|
a := pkg.NewVar("a", types.Typ[types.Int], InGo)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
b.Return(a.Expr, fn.Param(0))
|
b.Return(a.Expr, fn.Param(0))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
@@ -305,7 +307,7 @@ func TestJump(t *testing.T) {
|
|||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
|
||||||
fn := pkg.NewFunc("loop", sig)
|
fn := pkg.NewFunc("loop", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
b.Jump(fn.Block(0))
|
b.Jump(fn.Block(0))
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
@@ -324,7 +326,7 @@ func TestIf(t *testing.T) {
|
|||||||
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(3)
|
b := fn.MakeBody(3)
|
||||||
iftrue := fn.Block(1)
|
iftrue := fn.Block(1)
|
||||||
iffalse := fn.Block(2)
|
iffalse := fn.Block(2)
|
||||||
@@ -359,7 +361,7 @@ func TestPrintf(t *testing.T) {
|
|||||||
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
|
params := types.NewTuple(types.NewVar(0, nil, "format", pchar), VArg())
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int32]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
pkg.NewFunc("printf", sig)
|
pkg.NewFunc("printf", sig, InGo)
|
||||||
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
@@ -375,7 +377,7 @@ func TestBinOp(t *testing.T) {
|
|||||||
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
types.NewVar(0, nil, "b", types.Typ[types.Float64]))
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
ret := b.BinOp(token.ADD, fn.Param(0), prog.Val(1))
|
ret := b.BinOp(token.ADD, fn.Param(0), prog.Val(1))
|
||||||
b.Return(ret)
|
b.Return(ret)
|
||||||
@@ -398,7 +400,7 @@ func TestUnOp(t *testing.T) {
|
|||||||
)
|
)
|
||||||
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
rets := types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int]))
|
||||||
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
sig := types.NewSignatureType(nil, nil, nil, params, rets, false)
|
||||||
fn := pkg.NewFunc("fn", sig)
|
fn := pkg.NewFunc("fn", sig, InGo)
|
||||||
b := fn.MakeBody(1)
|
b := fn.MakeBody(1)
|
||||||
ptr := fn.Param(0)
|
ptr := fn.Param(0)
|
||||||
val := b.UnOp(token.MUL, ptr)
|
val := b.UnOp(token.MUL, ptr)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func (b Builder) Return(results ...Expr) {
|
|||||||
case 1:
|
case 1:
|
||||||
b.impl.CreateRet(results[0].impl)
|
b.impl.CreateRet(results[0].impl)
|
||||||
default:
|
default:
|
||||||
tret := b.fn.t.(*types.Signature).Results()
|
tret := b.fn.raw.Type.(*types.Signature).Results()
|
||||||
b.impl.CreateAggregateRet(llvmValues(results, tret, b))
|
b.impl.CreateAggregateRet(llvmValues(results, tret, b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
143
ssa/type.go
143
ssa/type.go
@@ -18,7 +18,6 @@ package ssa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
@@ -41,9 +40,8 @@ const (
|
|||||||
vkString
|
vkString
|
||||||
vkBool
|
vkBool
|
||||||
vkPtr
|
vkPtr
|
||||||
vkFuncDecl // func decl
|
vkFunc
|
||||||
vkFuncPtr // func ptr in C
|
vkClosure
|
||||||
vkClosure // func ptr in Go
|
|
||||||
vkTuple
|
vkTuple
|
||||||
vkDelayExpr = -1
|
vkDelayExpr = -1
|
||||||
vkPhisExpr = -2
|
vkPhisExpr = -2
|
||||||
@@ -66,32 +64,25 @@ func indexType(t types.Type) types.Type {
|
|||||||
panic("index: type doesn't support index - " + t.String())
|
panic("index: type doesn't support index - " + t.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert method to func
|
|
||||||
func methodToFunc(sig *types.Signature) *types.Signature {
|
|
||||||
if recv := sig.Recv(); recv != nil {
|
|
||||||
tParams := sig.Params()
|
|
||||||
nParams := tParams.Len()
|
|
||||||
params := make([]*types.Var, nParams+1)
|
|
||||||
params[0] = recv
|
|
||||||
for i := 0; i < nParams; i++ {
|
|
||||||
params[i+1] = tParams.At(i)
|
|
||||||
}
|
|
||||||
return types.NewSignatureType(
|
|
||||||
nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
|
|
||||||
}
|
|
||||||
return sig
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type rawType struct {
|
||||||
|
types.Type
|
||||||
|
}
|
||||||
|
|
||||||
type aType struct {
|
type aType struct {
|
||||||
ll llvm.Type
|
ll llvm.Type
|
||||||
t types.Type
|
raw rawType
|
||||||
kind valueKind // value kind of llvm.Type
|
kind valueKind // value kind of llvm.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
type Type = *aType
|
type Type = *aType
|
||||||
|
|
||||||
|
// RawType returns the raw type.
|
||||||
|
func (t Type) RawType() types.Type {
|
||||||
|
return t.raw.Type
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(xsw):
|
// TODO(xsw):
|
||||||
// how to generate platform independent code?
|
// how to generate platform independent code?
|
||||||
func (p Program) SizeOf(typ Type, n ...int64) uint64 {
|
func (p Program) SizeOf(typ Type, n ...int64) uint64 {
|
||||||
@@ -103,42 +94,37 @@ func (p Program) SizeOf(typ Type, n ...int64) uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Slice(typ Type) Type {
|
func (p Program) Slice(typ Type) Type {
|
||||||
return p.Type(types.NewSlice(typ.t))
|
return p.rawType(types.NewSlice(typ.raw.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Pointer(typ Type) Type {
|
func (p Program) Pointer(typ Type) Type {
|
||||||
return p.Type(types.NewPointer(typ.t))
|
return p.rawType(types.NewPointer(typ.raw.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Elem(typ Type) Type {
|
func (p Program) Elem(typ Type) Type {
|
||||||
elem := typ.t.(*types.Pointer).Elem()
|
elem := typ.raw.Type.(*types.Pointer).Elem()
|
||||||
return p.Type(elem)
|
return p.rawType(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Index(typ Type) Type {
|
func (p Program) Index(typ Type) Type {
|
||||||
return p.Type(indexType(typ.t))
|
return p.rawType(indexType(typ.raw.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Field(typ Type, i int) Type {
|
func (p Program) Field(typ Type, i int) Type {
|
||||||
tunder := typ.t.Underlying()
|
tunder := typ.raw.Type.Underlying()
|
||||||
tfld := tunder.(*types.Struct).Field(i).Type()
|
tfld := tunder.(*types.Struct).Field(i).Type()
|
||||||
return p.Type(tfld)
|
return p.rawType(tfld)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) Type(typ types.Type) Type {
|
func (p Program) rawType(raw types.Type) Type {
|
||||||
if v := p.typs.At(typ); v != nil {
|
if v := p.typs.At(raw); v != nil {
|
||||||
return v.(Type)
|
return v.(Type)
|
||||||
}
|
}
|
||||||
ret := p.toLLVMType(typ)
|
ret := p.toType(raw)
|
||||||
p.typs.Set(typ, ret)
|
p.typs.Set(raw, ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) llvmFuncDecl(sig *types.Signature) Type {
|
|
||||||
sig = methodToFunc(sig)
|
|
||||||
return p.toLLVMFunc(sig, false, true) // don't save func decl to cache
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Program) tyVoidPtr() llvm.Type {
|
func (p Program) tyVoidPtr() llvm.Type {
|
||||||
if p.voidPtrTy.IsNil() {
|
if p.voidPtrTy.IsNil() {
|
||||||
p.voidPtrTy = llvm.PointerType(p.tyVoid(), 0)
|
p.voidPtrTy = llvm.PointerType(p.tyVoid(), 0)
|
||||||
@@ -202,8 +188,9 @@ func (p Program) tyInt64() llvm.Type {
|
|||||||
return p.int64Type
|
return p.int64Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMType(typ types.Type) Type {
|
func (p Program) toType(raw types.Type) Type {
|
||||||
switch t := typ.(type) {
|
typ := rawType{raw}
|
||||||
|
switch t := raw.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case types.Int:
|
case types.Int:
|
||||||
@@ -240,7 +227,7 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
return &aType{p.tyVoidPtr(), typ, vkPtr}
|
return &aType{p.tyVoidPtr(), typ, vkPtr}
|
||||||
}
|
}
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.rawType(t.Elem())
|
||||||
return &aType{llvm.PointerType(elem.ll, 0), typ, vkPtr}
|
return &aType{llvm.PointerType(elem.ll, 0), typ, vkPtr}
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
return &aType{p.rtIface(), typ, vkInvalid}
|
return &aType{p.rtIface(), typ, vkInvalid}
|
||||||
@@ -249,39 +236,37 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
case *types.Map:
|
case *types.Map:
|
||||||
return &aType{p.rtMap(), typ, vkInvalid}
|
return &aType{p.rtMap(), typ, vkInvalid}
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
return p.toLLVMStruct(t)
|
return &aType{p.toLLVMStruct(t), typ, vkInvalid}
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
return p.toLLVMNamed(t)
|
return p.toNamed(t)
|
||||||
case *types.Signature:
|
case *types.Signature: // represents a C function pointer in raw type
|
||||||
return p.toLLVMFunc(t, false, false)
|
return &aType{p.toLLVMFuncPtr(t), typ, vkFunc}
|
||||||
case *CFuncPtr:
|
|
||||||
return p.toLLVMFunc((*types.Signature)(t), true, false)
|
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := p.Type(t.Elem())
|
elem := p.rawType(t.Elem())
|
||||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("toLLVMType: todo - %T\n", typ))
|
panic(fmt.Sprintf("toLLVMType: todo - %T\n", typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
|
func (p Program) toLLVMNamedStruct(name string, raw *types.Struct) llvm.Type {
|
||||||
t := p.ctx.StructCreateNamed(name)
|
t := p.ctx.StructCreateNamed(name)
|
||||||
fields := p.toLLVMFields(typ)
|
fields := p.toLLVMFields(raw)
|
||||||
t.StructSetBody(fields, false)
|
t.StructSetBody(fields, false)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMStruct(typ *types.Struct) Type {
|
func (p Program) toLLVMStruct(raw *types.Struct) llvm.Type {
|
||||||
fields := p.toLLVMFields(typ)
|
fields := p.toLLVMFields(raw)
|
||||||
return &aType{p.ctx.StructType(fields, false), typ, vkInvalid}
|
return p.ctx.StructType(fields, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMFields(typ *types.Struct) (fields []llvm.Type) {
|
func (p Program) toLLVMFields(raw *types.Struct) (fields []llvm.Type) {
|
||||||
n := typ.NumFields()
|
n := raw.NumFields()
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
fields = make([]llvm.Type, n)
|
fields = make([]llvm.Type, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
fields[i] = p.Type(typ.Field(i).Type()).ll
|
fields[i] = p.rawType(raw.Field(i).Type()).ll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -295,14 +280,13 @@ func (p Program) toLLVMTypes(t *types.Tuple, n int) (ret []llvm.Type) {
|
|||||||
if n > 0 {
|
if n > 0 {
|
||||||
ret = make([]llvm.Type, n)
|
ret = make([]llvm.Type, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
ret[i] = p.Type(t.At(i).Type()).ll
|
ret[i] = p.rawType(t.At(i).Type()).ll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMFunc(sig *types.Signature, inC, isDecl bool) Type {
|
func (p Program) toLLVMFunc(sig *types.Signature) llvm.Type {
|
||||||
if isDecl || inC {
|
|
||||||
tParams := sig.Params()
|
tParams := sig.Params()
|
||||||
n := tParams.Len()
|
n := tParams.Len()
|
||||||
hasVArg := HasVArg(tParams, n)
|
hasVArg := HasVArg(tParams, n)
|
||||||
@@ -312,52 +296,41 @@ func (p Program) toLLVMFunc(sig *types.Signature, inC, isDecl bool) Type {
|
|||||||
params := p.toLLVMTypes(tParams, n)
|
params := p.toLLVMTypes(tParams, n)
|
||||||
out := sig.Results()
|
out := sig.Results()
|
||||||
var ret llvm.Type
|
var ret llvm.Type
|
||||||
var kind valueKind
|
|
||||||
switch nret := out.Len(); nret {
|
switch nret := out.Len(); nret {
|
||||||
case 0:
|
case 0:
|
||||||
ret = p.tyVoid()
|
ret = p.tyVoid()
|
||||||
case 1:
|
case 1:
|
||||||
ret = p.Type(out.At(0).Type()).ll
|
ret = p.rawType(out.At(0).Type()).ll
|
||||||
default:
|
default:
|
||||||
ret = p.toLLVMTuple(out)
|
ret = p.toLLVMTuple(out)
|
||||||
}
|
}
|
||||||
ft := llvm.FunctionType(ret, params, hasVArg)
|
return llvm.FunctionType(ret, params, hasVArg)
|
||||||
if isDecl {
|
|
||||||
kind = vkFuncDecl
|
|
||||||
} else {
|
|
||||||
ft = llvm.PointerType(ft, 0)
|
|
||||||
kind = vkFuncPtr
|
|
||||||
}
|
|
||||||
return &aType{ft, sig, kind}
|
|
||||||
}
|
|
||||||
flds := []*types.Var{
|
|
||||||
types.NewField(token.NoPos, nil, "f", (*CFuncPtr)(sig), false),
|
|
||||||
types.NewField(token.NoPos, nil, "data", types.Typ[types.UnsafePointer], false),
|
|
||||||
}
|
|
||||||
t := types.NewStruct(flds, nil)
|
|
||||||
ll := p.ctx.StructType(p.toLLVMFields(t), false)
|
|
||||||
return &aType{ll, t, vkClosure}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) retType(sig *types.Signature) Type {
|
func (p Program) toLLVMFuncPtr(sig *types.Signature) llvm.Type {
|
||||||
out := sig.Results()
|
ft := p.toLLVMFunc(sig)
|
||||||
|
return llvm.PointerType(ft, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Program) retType(raw *types.Signature) Type {
|
||||||
|
out := raw.Results()
|
||||||
switch n := out.Len(); n {
|
switch n := out.Len(); n {
|
||||||
case 0:
|
case 0:
|
||||||
return p.Void()
|
return p.Void()
|
||||||
case 1:
|
case 1:
|
||||||
return p.Type(out.At(0).Type())
|
return p.rawType(out.At(0).Type())
|
||||||
default:
|
default:
|
||||||
return &aType{p.toLLVMTuple(out), out, vkTuple}
|
return &aType{p.toLLVMTuple(out), rawType{out}, vkTuple}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Program) toLLVMNamed(typ *types.Named) Type {
|
func (p Program) toNamed(raw *types.Named) Type {
|
||||||
switch t := typ.Underlying().(type) {
|
switch t := raw.Underlying().(type) {
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
name := NameOf(typ)
|
name := NameOf(raw)
|
||||||
return &aType{p.toLLVMNamedStruct(name, t), typ, vkInvalid}
|
return &aType{p.toLLVMNamedStruct(name, t), rawType{raw}, vkInvalid}
|
||||||
default:
|
default:
|
||||||
return p.Type(t)
|
return p.rawType(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
140
ssa/type_c.go
140
ssa/type_c.go
@@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 ssa
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/types"
|
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/typeutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const (
|
|
||||||
NameValist = "__llgo_va_list"
|
|
||||||
)
|
|
||||||
|
|
||||||
func VArg() *types.Var {
|
|
||||||
return types.NewParam(0, nil, NameValist, types.Typ[types.Invalid])
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsVArg(arg *types.Var) bool {
|
|
||||||
return arg.Name() == NameValist
|
|
||||||
}
|
|
||||||
|
|
||||||
func HasVArg(t *types.Tuple, n int) bool {
|
|
||||||
return n > 0 && IsVArg(t.At(n-1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// CFuncPtr represents a C function pointer.
|
|
||||||
type CFuncPtr types.Signature
|
|
||||||
|
|
||||||
func (t *CFuncPtr) String() string { return (*types.Signature)(t).String() }
|
|
||||||
func (t *CFuncPtr) Underlying() types.Type { return (*types.Signature)(t) }
|
|
||||||
|
|
||||||
func (t *CFuncPtr) Hash(h typeutil.Hasher) uint32 {
|
|
||||||
return typeutil.HashSig(h, (*types.Signature)(t))*13 + 97
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// CType convert a C type into Go.
|
|
||||||
func CType(typ types.Type) types.Type {
|
|
||||||
t, _ := cvtCType(typ)
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// CFuncDecl convert a C function decl into Go signature.
|
|
||||||
func CFuncDecl(sig *types.Signature) *types.Signature {
|
|
||||||
hasVArg := sig.Variadic()
|
|
||||||
params, cvt1 := cvtTuple(sig.Params(), hasVArg)
|
|
||||||
results, cvt2 := cvtTuple(sig.Results(), false)
|
|
||||||
if cvt1 || cvt2 {
|
|
||||||
return types.NewSignatureType(nil, nil, nil, params, results, hasVArg)
|
|
||||||
}
|
|
||||||
return sig
|
|
||||||
}
|
|
||||||
|
|
||||||
func cvtCType(typ types.Type) (types.Type, bool) {
|
|
||||||
switch t := typ.(type) {
|
|
||||||
case *types.Basic:
|
|
||||||
case *types.Pointer:
|
|
||||||
if elem, cvt := cvtCType(t.Elem()); cvt {
|
|
||||||
return types.NewPointer(elem), true
|
|
||||||
}
|
|
||||||
case *types.Struct:
|
|
||||||
return cvtCStruct(t)
|
|
||||||
case *types.Named:
|
|
||||||
if _, cvt := cvtCType(t.Underlying()); cvt {
|
|
||||||
panic("don't define named type")
|
|
||||||
}
|
|
||||||
case *types.Signature:
|
|
||||||
t = CFuncDecl(t)
|
|
||||||
return (*CFuncPtr)(t), true
|
|
||||||
case *types.Array:
|
|
||||||
if elem, cvt := cvtCType(t.Elem()); cvt {
|
|
||||||
return types.NewArray(elem, t.Len()), true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
return typ, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func cvtTuple(t *types.Tuple, hasVArg bool) (*types.Tuple, bool) {
|
|
||||||
n := t.Len()
|
|
||||||
vars := make([]*types.Var, n)
|
|
||||||
needcvt := false
|
|
||||||
if hasVArg {
|
|
||||||
n--
|
|
||||||
vars[n] = t.At(n)
|
|
||||||
}
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
v := t.At(i)
|
|
||||||
if t, cvt := cvtCType(v.Type()); cvt {
|
|
||||||
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t)
|
|
||||||
needcvt = true
|
|
||||||
}
|
|
||||||
vars[i] = v
|
|
||||||
}
|
|
||||||
if needcvt {
|
|
||||||
return types.NewTuple(vars...), true
|
|
||||||
}
|
|
||||||
return t, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func cvtCStruct(typ *types.Struct) (*types.Struct, bool) {
|
|
||||||
n := typ.NumFields()
|
|
||||||
flds := make([]*types.Var, n)
|
|
||||||
needcvt := false
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
f := typ.Field(i)
|
|
||||||
if t, cvt := cvtCType(f.Type()); cvt {
|
|
||||||
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous())
|
|
||||||
needcvt = true
|
|
||||||
}
|
|
||||||
flds[i] = f
|
|
||||||
}
|
|
||||||
if needcvt {
|
|
||||||
return types.NewStruct(flds, nil), true
|
|
||||||
}
|
|
||||||
return typ, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
255
ssa/type_cvt.go
Normal file
255
ssa/type_cvt.go
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* 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 ssa
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type goTypes struct {
|
||||||
|
typs map[unsafe.Pointer]unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGoTypes() goTypes {
|
||||||
|
typs := make(map[unsafe.Pointer]unsafe.Pointer)
|
||||||
|
return goTypes{typs}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Background int
|
||||||
|
|
||||||
|
const (
|
||||||
|
inUnknown Background = iota
|
||||||
|
InGo
|
||||||
|
InC
|
||||||
|
)
|
||||||
|
|
||||||
|
// Type convert a Go/C type into raw type.
|
||||||
|
// C type = raw type
|
||||||
|
// Go type: convert to raw type (because of closure)
|
||||||
|
func (p Program) Type(typ types.Type, bg Background) Type {
|
||||||
|
if bg == InGo {
|
||||||
|
typ, _ = p.gocvt.cvtType(typ)
|
||||||
|
}
|
||||||
|
return p.rawType(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncDecl converts a Go/C function declaration into raw type.
|
||||||
|
func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
|
||||||
|
if bg == InGo {
|
||||||
|
sig = p.gocvt.cvtFunc(sig, true)
|
||||||
|
}
|
||||||
|
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFunc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) {
|
||||||
|
switch t := typ.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
case *types.Pointer:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewPointer(elem), true
|
||||||
|
}
|
||||||
|
case *types.Interface:
|
||||||
|
return p.cvtInterface(t)
|
||||||
|
case *types.Slice:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewSlice(elem), true
|
||||||
|
}
|
||||||
|
case *types.Map:
|
||||||
|
key, cvt1 := p.cvtType(t.Key())
|
||||||
|
elem, cvt2 := p.cvtType(t.Elem())
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewMap(key, elem), true
|
||||||
|
}
|
||||||
|
case *types.Struct:
|
||||||
|
return p.cvtStruct(t)
|
||||||
|
case *types.Named:
|
||||||
|
return p.cvtNamed(t)
|
||||||
|
case *types.Signature:
|
||||||
|
return p.cvtClosure(t), true
|
||||||
|
case *types.Array:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewArray(elem, t.Len()), true
|
||||||
|
}
|
||||||
|
case *types.Chan:
|
||||||
|
if elem, cvt := p.cvtType(t.Elem()); cvt {
|
||||||
|
return types.NewChan(t.Dir(), elem), true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(t)]; ok {
|
||||||
|
raw = (*types.Named)(v)
|
||||||
|
cvt = t != raw
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(t)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
if tund, cvt := p.cvtType(t.Underlying()); cvt {
|
||||||
|
old := t.Obj()
|
||||||
|
obj := types.NewTypeName(old.Pos(), old.Pkg(), old.Name(), nil)
|
||||||
|
return types.NewNamed(obj, tund, nil), true
|
||||||
|
}
|
||||||
|
return t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtClosure(sig *types.Signature) *types.Struct {
|
||||||
|
raw := p.cvtFunc(sig, false)
|
||||||
|
flds := []*types.Var{
|
||||||
|
types.NewField(token.NoPos, nil, "f", raw, false),
|
||||||
|
types.NewField(token.NoPos, nil, "data", types.Typ[types.UnsafePointer], false),
|
||||||
|
}
|
||||||
|
return types.NewStruct(flds, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtFunc(sig *types.Signature, hasRecv bool) (raw *types.Signature) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(sig)]; ok {
|
||||||
|
return (*types.Signature)(v)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(sig)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
if hasRecv {
|
||||||
|
sig = methodToFunc(sig)
|
||||||
|
}
|
||||||
|
params, cvt1 := p.cvtTuple(sig.Params())
|
||||||
|
results, cvt2 := p.cvtTuple(sig.Results())
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewSignatureType(nil, nil, nil, params, results, sig.Variadic())
|
||||||
|
}
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtTuple(t *types.Tuple) (*types.Tuple, bool) {
|
||||||
|
n := t.Len()
|
||||||
|
vars := make([]*types.Var, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
v := t.At(i)
|
||||||
|
if t, cvt := p.cvtType(v.Type()); cvt {
|
||||||
|
v = types.NewParam(v.Pos(), v.Pkg(), v.Name(), t)
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
vars[i] = v
|
||||||
|
}
|
||||||
|
if needcvt {
|
||||||
|
return types.NewTuple(vars...), true
|
||||||
|
}
|
||||||
|
return t, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtExplicitMethods(typ *types.Interface) ([]*types.Func, bool) {
|
||||||
|
n := typ.NumExplicitMethods()
|
||||||
|
methods := make([]*types.Func, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
m := typ.ExplicitMethod(i)
|
||||||
|
sig := m.Type().(*types.Signature)
|
||||||
|
if raw := p.cvtFunc(sig, false); sig != raw {
|
||||||
|
m = types.NewFunc(m.Pos(), m.Pkg(), m.Name(), raw)
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
methods[i] = m
|
||||||
|
}
|
||||||
|
return methods, needcvt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtEmbeddedTypes(typ *types.Interface) ([]types.Type, bool) {
|
||||||
|
n := typ.NumEmbeddeds()
|
||||||
|
embeddeds := make([]types.Type, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
t := typ.EmbeddedType(i)
|
||||||
|
if raw, cvt := p.cvtType(t); cvt {
|
||||||
|
t = raw
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
embeddeds[i] = t
|
||||||
|
}
|
||||||
|
return embeddeds, needcvt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtInterface(typ *types.Interface) (raw *types.Interface, cvt bool) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(typ)]; ok {
|
||||||
|
raw = (*types.Interface)(v)
|
||||||
|
cvt = typ != raw
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
methods, cvt1 := p.cvtExplicitMethods(typ)
|
||||||
|
embeddeds, cvt2 := p.cvtEmbeddedTypes(typ)
|
||||||
|
if cvt1 || cvt2 {
|
||||||
|
return types.NewInterfaceType(methods, embeddeds), true
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p goTypes) cvtStruct(typ *types.Struct) (raw *types.Struct, cvt bool) {
|
||||||
|
if v, ok := p.typs[unsafe.Pointer(typ)]; ok {
|
||||||
|
raw = (*types.Struct)(v)
|
||||||
|
cvt = typ != raw
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
p.typs[unsafe.Pointer(typ)] = unsafe.Pointer(raw)
|
||||||
|
}()
|
||||||
|
n := typ.NumFields()
|
||||||
|
flds := make([]*types.Var, n)
|
||||||
|
needcvt := false
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
f := typ.Field(i)
|
||||||
|
if t, cvt := p.cvtType(f.Type()); cvt {
|
||||||
|
f = types.NewField(f.Pos(), f.Pkg(), f.Name(), t, f.Anonymous())
|
||||||
|
needcvt = true
|
||||||
|
}
|
||||||
|
flds[i] = f
|
||||||
|
}
|
||||||
|
if needcvt {
|
||||||
|
return types.NewStruct(flds, nil), true
|
||||||
|
}
|
||||||
|
return typ, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// convert method to func
|
||||||
|
func methodToFunc(sig *types.Signature) *types.Signature {
|
||||||
|
if recv := sig.Recv(); recv != nil {
|
||||||
|
tParams := sig.Params()
|
||||||
|
nParams := tParams.Len()
|
||||||
|
params := make([]*types.Var, nParams+1)
|
||||||
|
params[0] = recv
|
||||||
|
for i := 0; i < nParams; i++ {
|
||||||
|
params[i+1] = tParams.At(i)
|
||||||
|
}
|
||||||
|
return types.NewSignatureType(
|
||||||
|
nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
|
||||||
|
}
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
Reference in New Issue
Block a user