TestBasicFunc

This commit is contained in:
xushiwei
2024-04-18 15:03:10 +08:00
parent 4fcffa46e1
commit 3a8ce26c6f
9 changed files with 215 additions and 96 deletions

2
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/aykevl/go-wasm v0.0.1 github.com/aykevl/go-wasm v0.0.1
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/goplus/gop v1.2.6 github.com/goplus/gop v1.2.6
github.com/goplus/llvm v0.7.1-0.20240417171659-4fb15c5dc82a github.com/goplus/llvm v0.7.1-0.20240418070213-5013f6a4299b
github.com/qiniu/x v1.13.10 github.com/qiniu/x v1.13.10
golang.org/x/tools v0.19.0 golang.org/x/tools v0.19.0
) )

2
go.sum
View File

@@ -10,6 +10,8 @@ github.com/goplus/llvm v0.7.0 h1:b8XzmRA97U0V0BPSaYuZ2vw+lLO2JSpRLMtR6dAenIo=
github.com/goplus/llvm v0.7.0/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4= github.com/goplus/llvm v0.7.0/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
github.com/goplus/llvm v0.7.1-0.20240417171659-4fb15c5dc82a h1:pKOqI/f4lyPAlto2MT0JJsDCNMvRyF8jBT2saegwIK8= github.com/goplus/llvm v0.7.1-0.20240417171659-4fb15c5dc82a h1:pKOqI/f4lyPAlto2MT0JJsDCNMvRyF8jBT2saegwIK8=
github.com/goplus/llvm v0.7.1-0.20240417171659-4fb15c5dc82a/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4= github.com/goplus/llvm v0.7.1-0.20240417171659-4fb15c5dc82a/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
github.com/goplus/llvm v0.7.1-0.20240418070213-5013f6a4299b h1:sRVmYXGgKjqgaoVQ1bshnw9Ar77stDtjHC4A/PDJ0fk=
github.com/goplus/llvm v0.7.1-0.20240418070213-5013f6a4299b/go.mod h1:PeVK8GgzxwAYCiMiUAJb5wJR6xbhj989tu9oulKLLT4=
github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE= github.com/goplus/mod v0.13.10 h1:5Om6KOvo31daN7N30kWU1vC5zhsJPM+uPbcEN/FnlzE=
github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c= github.com/goplus/mod v0.13.10/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE= github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE=

View File

@@ -20,13 +20,35 @@ import (
"github.com/goplus/llvm" "github.com/goplus/llvm"
) )
type Builder struct { // -----------------------------------------------------------------------------
impl llvm.Builder /*
}
type BasicBlock struct { type BasicBlock struct {
impl llvm.BasicBlock impl llvm.BasicBlock
} }
*/
// -----------------------------------------------------------------------------
func (p BasicBlock) End() { type aBuilder struct {
impl llvm.Builder
prog Program
} }
type Builder = *aBuilder
func (b Builder) Return(results ...Expr) Builder {
switch n := len(results); n {
case 0:
b.impl.CreateRetVoid()
case 1:
b.impl.CreateRet(results[0].impl)
default:
rets := make([]llvm.Value, n)
for i, v := range results {
rets[i] = v.impl
}
b.impl.CreateAggregateRet(rets)
}
return b
}
// -----------------------------------------------------------------------------

View File

@@ -20,6 +20,8 @@ import (
"github.com/goplus/llvm" "github.com/goplus/llvm"
) )
// -----------------------------------------------------------------------------
// A NamedConst is a Member of a Package representing a package-level // A NamedConst is a Member of a Package representing a package-level
// named constant. // named constant.
// //
@@ -33,6 +35,8 @@ type aNamedConst struct {
type NamedConst = *aNamedConst type NamedConst = *aNamedConst
// -----------------------------------------------------------------------------
// A Global is a named Value holding the address of a package-level // A Global is a named Value holding the address of a package-level
// variable. // variable.
// //
@@ -40,10 +44,13 @@ type NamedConst = *aNamedConst
// identifier. // identifier.
type aGlobal struct { type aGlobal struct {
impl llvm.Value impl llvm.Value
Type
} }
type Global = *aGlobal type Global = *aGlobal
// -----------------------------------------------------------------------------
// Function represents the parameters, results, and code of a function // Function represents the parameters, results, and code of a function
// or method. // or method.
// //
@@ -95,12 +102,20 @@ type Global = *aGlobal
// respectively, and is nil in the generic method. // respectively, and is nil in the generic method.
type aFunction struct { type aFunction struct {
impl llvm.Value impl llvm.Value
Type
prog Program prog Program
} }
type Function = *aFunction type Function = *aFunction
func (p *aFunction) BodyStart() *BasicBlock { func (p *aFunction) MakeBody(label string) Builder {
body := llvm.AddBasicBlock(p.impl, "entry") body := llvm.AddBasicBlock(p.impl, label)
return &BasicBlock{body} prog := p.prog
b := prog.ctx.NewBuilder()
b.Finalize()
b.SetInsertPointAtEnd(body)
return &aBuilder{b, prog}
} }
// -----------------------------------------------------------------------------

View File

@@ -15,3 +15,21 @@
*/ */
package ssa package ssa
import (
"github.com/goplus/llvm"
)
func (p Program) Val(v interface{}) Expr {
switch v := v.(type) {
case int:
t := p.Int()
ret := llvm.ConstInt(t.ll, uint64(v), false)
return Expr{ret, t}
case float64:
t := p.Float64()
ret := llvm.ConstFloat(t.ll, v)
return Expr{ret, t}
}
panic("todo")
}

View File

@@ -24,9 +24,9 @@ import (
type valueKind = int type valueKind = int
type Value struct { type Expr struct {
impl llvm.Value impl llvm.Value
kind valueKind Type
} }
const ( const (
@@ -42,6 +42,7 @@ const (
vkComplex vkComplex
vkString vkString
vkBool vkBool
vkFunc
) )
var mathOpToLLVM = []llvm.Opcode{ var mathOpToLLVM = []llvm.Opcode{
@@ -134,45 +135,44 @@ func isPredOp(op token.Token) bool {
// ADD SUB MUL QUO REM + - * / % // ADD SUB MUL QUO REM + - * / %
// AND OR XOR SHL SHR AND_NOT & | ^ << >> &^ // AND OR XOR SHL SHR AND_NOT & | ^ << >> &^
// EQL NEQ LSS LEQ GTR GEQ == != < <= < >= // EQL NEQ LSS LEQ GTR GEQ == != < <= < >=
func (b Builder) BinOp(op token.Token, x, y Value) (v Value) { func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
switch { switch {
case isMathOp(op): // op: + - * / % case isMathOp(op): // op: + - * / %
switch x.kind { kind := x.kind
switch kind {
case vkString, vkComplex: case vkString, vkComplex:
panic("todo") panic("todo")
} }
idx := mathOpIdx(op, x.kind) idx := mathOpIdx(op, kind)
if llop := mathOpToLLVM[idx]; llop != 0 { if llop := mathOpToLLVM[idx]; llop != 0 {
v.impl = llvm.CreateBinOp(b.impl, llop, x.impl, y.impl) return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
return
} }
case isLogicOp(op): // op: & | ^ << >> &^ case isLogicOp(op): // op: & | ^ << >> &^
if op == token.AND_NOT { if op == token.AND_NOT {
panic("todo") panic("todo")
} }
kind := x.kind
llop := logicOpToLLVM[op-logicOpBase] llop := logicOpToLLVM[op-logicOpBase]
if op == token.SHR && x.kind == vkUnsigned { if op == token.SHR && kind == vkUnsigned {
llop = llvm.AShr llop = llvm.AShr
} }
v.impl = llvm.CreateBinOp(b.impl, llop, x.impl, y.impl) return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
return
case isPredOp(op): // op: == != < <= < >= case isPredOp(op): // op: == != < <= < >=
switch x.kind { tret := b.prog.Bool()
kind := x.kind
switch kind {
case vkSigned: case vkSigned:
pred := intPredOpToLLVM[op-predOpBase] pred := intPredOpToLLVM[op-predOpBase]
v.impl = llvm.CreateICmp(b.impl, pred, x.impl, y.impl) return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
return
case vkUnsigned: case vkUnsigned:
pred := uintPredOpToLLVM[op-predOpBase] pred := uintPredOpToLLVM[op-predOpBase]
v.impl = llvm.CreateICmp(b.impl, pred, x.impl, y.impl) return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
return
case vkFloat: case vkFloat:
pred := floatPredOpToLLVM[op-predOpBase] pred := floatPredOpToLLVM[op-predOpBase]
v.impl = llvm.ConstFCmp(pred, x.impl, y.impl) return Expr{llvm.ConstFCmp(pred, x.impl, y.impl), tret}
return
case vkString, vkComplex, vkBool: case vkString, vkComplex, vkBool:
panic("todo") panic("todo")
} }
} }
return panic("todo")
} }

View File

@@ -27,7 +27,6 @@ import (
// A Program is a partial or complete Go program converted to SSA form. // A Program is a partial or complete Go program converted to SSA form.
type aProgram struct { type aProgram struct {
ctx llvm.Context ctx llvm.Context
b Builder
typs typeutil.Map typs typeutil.Map
target *Target target *Target
@@ -35,12 +34,17 @@ type aProgram struct {
// tm llvm.TargetMachine // tm llvm.TargetMachine
intType llvm.Type intType llvm.Type
int1Type llvm.Type
int8Type llvm.Type int8Type llvm.Type
int16Type llvm.Type int16Type llvm.Type
int32Type llvm.Type int32Type llvm.Type
int64Type llvm.Type int64Type llvm.Type
voidType llvm.Type voidType llvm.Type
voidPtrTy llvm.Type voidPtrTy llvm.Type
boolTy Type
intTy Type
f64Ty Type
} }
type Program = *aProgram type Program = *aProgram
@@ -51,20 +55,35 @@ func NewProgram(target *Target) Program {
} }
ctx := llvm.NewContext() ctx := llvm.NewContext()
ctx.Finalize() ctx.Finalize()
b := ctx.NewBuilder()
b.Finalize()
td := llvm.NewTargetData("") // TODO(xsw): target config td := llvm.NewTargetData("") // TODO(xsw): target config
return &aProgram{ctx: ctx, b: Builder{b}, target: target, td: td} return &aProgram{ctx: ctx, target: target, td: td}
} }
func (p *aProgram) NewPackage(name, pkgPath string) Package { func (p Program) NewPackage(name, pkgPath string) Package {
mod := p.ctx.NewModule(pkgPath) mod := p.ctx.NewModule(pkgPath)
mod.Finalize() mod.Finalize()
return &aPackage{mod, p} return &aPackage{mod, p}
} }
func (p *aProgram) Builder() Builder { func (p Program) Bool() Type {
return p.b if p.boolTy == nil {
p.boolTy = p.llvmType(types.Typ[types.Bool])
}
return p.boolTy
}
func (p Program) Int() Type {
if p.intTy == nil {
p.intTy = p.llvmType(types.Typ[types.Int])
}
return p.intTy
}
func (p Program) Float64() Type {
if p.f64Ty == nil {
p.f64Ty = p.llvmType(types.Typ[types.Float64])
}
return p.f64Ty
} }
// A Package is a single analyzed Go package containing Members for // A Package is a single analyzed Go package containing Members for
@@ -82,21 +101,23 @@ type aPackage struct {
type Package = *aPackage type Package = *aPackage
func (p *aPackage) NewConst(name string, val constant.Value) NamedConst { func (p Package) NewConst(name string, val constant.Value) NamedConst {
return &aNamedConst{} return &aNamedConst{}
} }
func (p *aPackage) NewVar(name string, typ types.Type) Global { func (p Package) NewVar(name string, typ types.Type) Global {
gbl := llvm.AddGlobal(p.mod, p.prog.llvmType(typ), name) t := p.prog.llvmType(typ)
return &aGlobal{gbl} gbl := llvm.AddGlobal(p.mod, t.ll, name)
return &aGlobal{gbl, t}
} }
func (p *aPackage) NewFunc(name string, sig *types.Signature) Function { func (p Package) NewFunc(name string, sig *types.Signature) Function {
fn := llvm.AddFunction(p.mod, name, p.prog.llvmSignature(sig)) t := p.prog.llvmSignature(sig)
return &aFunction{fn, p.prog} fn := llvm.AddFunction(p.mod, name, t.ll)
return &aFunction{fn, t, p.prog}
} }
func (p *aPackage) String() string { func (p Package) String() string {
return p.mod.String() return p.mod.String()
} }

View File

@@ -79,7 +79,7 @@ source_filename = "foo/bar"
`) `)
} }
func TestFunc(t *testing.T) { func TestDeclFunc(t *testing.T) {
prog := NewProgram(nil) prog := NewProgram(nil)
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]))
@@ -91,3 +91,19 @@ source_filename = "foo/bar"
declare void @fn(i64) declare void @fn(i64)
`) `)
} }
func TestBasicFunc(t *testing.T) {
prog := NewProgram(nil)
pkg := prog.NewPackage("bar", "foo/bar")
rets := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
sig := types.NewSignatureType(nil, nil, nil, nil, rets, false)
b := pkg.NewFunc("fn", sig).MakeBody("")
b.Return(prog.Val(1))
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
source_filename = "foo/bar"
define i64 @fn() {
ret i64 1
}
`)
}

View File

@@ -22,107 +22,136 @@ import (
"github.com/goplus/llvm" "github.com/goplus/llvm"
) )
/* // -----------------------------------------------------------------------------
// A Type is a Member of a Package representing a package-level named type.
type Type struct {
impl llvm.Type
}
*/
func (p *aProgram) llvmType(typ types.Type) llvm.Type { type aType struct {
ll llvm.Type
t types.Type
kind valueKind
}
type Type = *aType
func (p Program) llvmType(typ types.Type) Type {
if v := p.typs.At(typ); v != nil { if v := p.typs.At(typ); v != nil {
return v.(llvm.Type) return v.(Type)
} }
ret := p.toLLVMType(typ) ret := p.toLLVMType(typ)
p.typs.Set(typ, ret) p.typs.Set(typ, ret)
return ret return ret
} }
func (p *aProgram) llvmSignature(sig *types.Signature) llvm.Type { func (p Program) llvmSignature(sig *types.Signature) Type {
if v := p.typs.At(sig); v != nil { if v := p.typs.At(sig); v != nil {
return v.(llvm.Type) return v.(Type)
} }
ret := p.toLLVMFunc(sig) ret := p.toLLVMFunc(sig)
p.typs.Set(sig, ret) p.typs.Set(sig, ret)
return ret return ret
} }
func (p *aProgram) 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)
} }
return p.voidPtrTy return p.voidPtrTy
} }
func (p *aProgram) tyVoid() llvm.Type { func (p Program) tyVoid() llvm.Type {
if p.voidType.IsNil() { if p.voidType.IsNil() {
p.voidType = p.ctx.VoidType() p.voidType = p.ctx.VoidType()
} }
return p.voidType return p.voidType
} }
func (p *aProgram) tyInt() llvm.Type { func (p Program) tyInt1() llvm.Type {
if p.int1Type.IsNil() {
p.int1Type = p.ctx.Int1Type()
}
return p.int1Type
}
func (p Program) tyInt() llvm.Type {
if p.intType.IsNil() { if p.intType.IsNil() {
p.intType = llvmIntType(p.ctx, p.td.PointerSize()) p.intType = llvmIntType(p.ctx, p.td.PointerSize())
} }
return p.intType return p.intType
} }
func (p *aProgram) tyInt8() llvm.Type { func llvmIntType(ctx llvm.Context, size int) llvm.Type {
if size <= 4 {
return ctx.Int32Type()
}
return ctx.Int64Type()
}
func (p Program) tyInt8() llvm.Type {
if p.int8Type.IsNil() { if p.int8Type.IsNil() {
p.int8Type = p.ctx.Int8Type() p.int8Type = p.ctx.Int8Type()
} }
return p.int8Type return p.int8Type
} }
func (p *aProgram) tyInt16() llvm.Type { func (p Program) tyInt16() llvm.Type {
if p.int16Type.IsNil() { if p.int16Type.IsNil() {
p.int16Type = p.ctx.Int16Type() p.int16Type = p.ctx.Int16Type()
} }
return p.int16Type return p.int16Type
} }
func (p *aProgram) tyInt32() llvm.Type { func (p Program) tyInt32() llvm.Type {
if p.int32Type.IsNil() { if p.int32Type.IsNil() {
p.int32Type = p.ctx.Int32Type() p.int32Type = p.ctx.Int32Type()
} }
return p.int32Type return p.int32Type
} }
func (p *aProgram) tyInt64() llvm.Type { func (p Program) tyInt64() llvm.Type {
if p.int64Type.IsNil() { if p.int64Type.IsNil() {
p.int64Type = p.ctx.Int64Type() p.int64Type = p.ctx.Int64Type()
} }
return p.int64Type return p.int64Type
} }
func (p *aProgram) toLLVMType(typ types.Type) llvm.Type { func (p Program) toLLVMType(typ types.Type) Type {
switch t := typ.(type) { switch t := typ.(type) {
case *types.Basic: case *types.Basic:
switch t.Kind() { switch t.Kind() {
case types.Int, types.Uint, types.Uintptr: case types.Int:
return p.tyInt() return &aType{p.tyInt(), typ, vkSigned}
case types.Bool, types.Uint8, types.Int8: case types.Uint, types.Uintptr:
return p.tyInt8() return &aType{p.tyInt(), typ, vkUnsigned}
case types.Int16, types.Uint16: case types.Bool:
return p.tyInt16() return &aType{p.tyInt1(), typ, vkBool}
case types.Int32, types.Uint32: case types.Uint8:
return p.tyInt32() return &aType{p.tyInt8(), typ, vkUnsigned}
case types.Int64, types.Uint64: case types.Int8:
return p.tyInt64() return &aType{p.tyInt8(), typ, vkSigned}
case types.Int16:
return &aType{p.tyInt16(), typ, vkSigned}
case types.Uint16:
return &aType{p.tyInt16(), typ, vkUnsigned}
case types.Int32:
return &aType{p.tyInt32(), typ, vkSigned}
case types.Uint32:
return &aType{p.tyInt32(), typ, vkUnsigned}
case types.Int64:
return &aType{p.tyInt64(), typ, vkSigned}
case types.Uint64:
return &aType{p.tyInt64(), typ, vkUnsigned}
case types.Float32: case types.Float32:
return p.ctx.FloatType() return &aType{p.ctx.FloatType(), typ, vkFloat}
case types.Float64: case types.Float64:
return p.ctx.DoubleType() return &aType{p.ctx.DoubleType(), typ, vkFloat}
case types.Complex64: case types.Complex64:
case types.Complex128: case types.Complex128:
case types.String: case types.String:
case types.UnsafePointer: case types.UnsafePointer:
return p.tyVoidPtr() return &aType{p.tyVoidPtr(), typ, vkInvalid}
} }
case *types.Pointer: case *types.Pointer:
elem := p.llvmType(t.Elem()) elem := p.llvmType(t.Elem())
return llvm.PointerType(elem, 0) return &aType{llvm.PointerType(elem.ll, 0), typ, vkInvalid}
case *types.Slice: case *types.Slice:
case *types.Map: case *types.Map:
case *types.Struct: case *types.Struct:
@@ -133,54 +162,47 @@ func (p *aProgram) toLLVMType(typ types.Type) llvm.Type {
return p.toLLVMFunc(t) return p.toLLVMFunc(t)
case *types.Array: case *types.Array:
elem := p.llvmType(t.Elem()) elem := p.llvmType(t.Elem())
return llvm.ArrayType(elem, int(t.Len())) return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
case *types.Chan: case *types.Chan:
} }
panic("todo") panic("todo")
} }
func llvmIntType(ctx llvm.Context, size int) llvm.Type { func (p Program) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
if size <= 4 {
return ctx.Int32Type()
}
return ctx.Int64Type()
}
func (p *aProgram) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
t := p.ctx.StructCreateNamed(name) t := p.ctx.StructCreateNamed(name)
fields := p.toLLVMFields(typ) fields := p.toLLVMFields(typ)
t.StructSetBody(fields, false) t.StructSetBody(fields, false)
return t return t
} }
func (p *aProgram) toLLVMStruct(typ *types.Struct) llvm.Type { func (p Program) toLLVMStruct(typ *types.Struct) Type {
fields := p.toLLVMFields(typ) fields := p.toLLVMFields(typ)
return p.ctx.StructType(fields, false) return &aType{p.ctx.StructType(fields, false), typ, vkInvalid}
} }
func (p *aProgram) toLLVMFields(typ *types.Struct) []llvm.Type { func (p Program) toLLVMFields(typ *types.Struct) []llvm.Type {
n := typ.NumFields() n := typ.NumFields()
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.llvmType(typ.Field(i).Type()) fields[i] = p.llvmType(typ.Field(i).Type()).ll
} }
return fields return fields
} }
func (p *aProgram) toLLVMTuple(t *types.Tuple) llvm.Type { func (p Program) toLLVMTuple(t *types.Tuple) llvm.Type {
return p.ctx.StructType(p.toLLVMTypes(t), false) return p.ctx.StructType(p.toLLVMTypes(t), false)
} }
func (p *aProgram) toLLVMTypes(t *types.Tuple) []llvm.Type { func (p Program) toLLVMTypes(t *types.Tuple) []llvm.Type {
n := t.Len() n := t.Len()
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.llvmType(t.At(i).Type()) ret[i] = p.llvmType(t.At(i).Type()).ll
} }
return ret return ret
} }
func (p *aProgram) toLLVMFunc(sig *types.Signature) llvm.Type { func (p Program) toLLVMFunc(sig *types.Signature) Type {
params := p.toLLVMTypes(sig.Params()) params := p.toLLVMTypes(sig.Params())
results := sig.Results() results := sig.Results()
var ret llvm.Type var ret llvm.Type
@@ -188,18 +210,21 @@ func (p *aProgram) toLLVMFunc(sig *types.Signature) llvm.Type {
case 0: case 0:
ret = p.tyVoid() ret = p.tyVoid()
case 1: case 1:
ret = p.llvmType(results.At(0).Type()) ret = p.llvmType(results.At(0).Type()).ll
default: default:
ret = p.toLLVMTuple(results) ret = p.toLLVMTuple(results)
} }
return llvm.FunctionType(ret, params, sig.Variadic()) ft := llvm.FunctionType(ret, params, sig.Variadic())
return &aType{ft, sig, vkFunc}
} }
func (p *aProgram) toLLVMNamed(typ *types.Named) llvm.Type { func (p Program) toLLVMNamed(typ *types.Named) Type {
name := typ.Obj().Name() name := typ.Obj().Name()
switch typ := typ.Underlying().(type) { switch typ := typ.Underlying().(type) {
case *types.Struct: case *types.Struct:
return p.toLLVMNamedStruct(name, typ) return &aType{p.toLLVMNamedStruct(name, typ), typ, vkInvalid}
} }
panic("todo") panic("todo")
} }
// -----------------------------------------------------------------------------