TestBasicFunc
This commit is contained in:
2
go.mod
2
go.mod
@@ -6,7 +6,7 @@ require (
|
||||
github.com/aykevl/go-wasm v0.0.1
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
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
|
||||
golang.org/x/tools v0.19.0
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -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.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.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/go.mod h1:HDuPZgpWiaTp3PUolFgsiX+Q77cbUWB/mikVHfYND3c=
|
||||
github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE=
|
||||
|
||||
@@ -20,13 +20,35 @@ import (
|
||||
"github.com/goplus/llvm"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
impl llvm.Builder
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/*
|
||||
type BasicBlock struct {
|
||||
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
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
21
ssa/decl.go
21
ssa/decl.go
@@ -20,6 +20,8 @@ import (
|
||||
"github.com/goplus/llvm"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// A NamedConst is a Member of a Package representing a package-level
|
||||
// named constant.
|
||||
//
|
||||
@@ -33,6 +35,8 @@ type aNamedConst struct {
|
||||
|
||||
type NamedConst = *aNamedConst
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// A Global is a named Value holding the address of a package-level
|
||||
// variable.
|
||||
//
|
||||
@@ -40,10 +44,13 @@ type NamedConst = *aNamedConst
|
||||
// identifier.
|
||||
type aGlobal struct {
|
||||
impl llvm.Value
|
||||
Type
|
||||
}
|
||||
|
||||
type Global = *aGlobal
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Function represents the parameters, results, and code of a function
|
||||
// or method.
|
||||
//
|
||||
@@ -95,12 +102,20 @@ type Global = *aGlobal
|
||||
// respectively, and is nil in the generic method.
|
||||
type aFunction struct {
|
||||
impl llvm.Value
|
||||
Type
|
||||
|
||||
prog Program
|
||||
}
|
||||
|
||||
type Function = *aFunction
|
||||
|
||||
func (p *aFunction) BodyStart() *BasicBlock {
|
||||
body := llvm.AddBasicBlock(p.impl, "entry")
|
||||
return &BasicBlock{body}
|
||||
func (p *aFunction) MakeBody(label string) Builder {
|
||||
body := llvm.AddBasicBlock(p.impl, label)
|
||||
prog := p.prog
|
||||
b := prog.ctx.NewBuilder()
|
||||
b.Finalize()
|
||||
b.SetInsertPointAtEnd(body)
|
||||
return &aBuilder{b, prog}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
18
ssa/expr.go
18
ssa/expr.go
@@ -15,3 +15,21 @@
|
||||
*/
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import (
|
||||
|
||||
type valueKind = int
|
||||
|
||||
type Value struct {
|
||||
type Expr struct {
|
||||
impl llvm.Value
|
||||
kind valueKind
|
||||
Type
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -42,6 +42,7 @@ const (
|
||||
vkComplex
|
||||
vkString
|
||||
vkBool
|
||||
vkFunc
|
||||
)
|
||||
|
||||
var mathOpToLLVM = []llvm.Opcode{
|
||||
@@ -134,45 +135,44 @@ func isPredOp(op token.Token) bool {
|
||||
// ADD SUB MUL QUO REM + - * / %
|
||||
// AND OR XOR SHL SHR AND_NOT & | ^ << >> &^
|
||||
// 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 {
|
||||
case isMathOp(op): // op: + - * / %
|
||||
switch x.kind {
|
||||
kind := x.kind
|
||||
switch kind {
|
||||
case vkString, vkComplex:
|
||||
panic("todo")
|
||||
}
|
||||
idx := mathOpIdx(op, x.kind)
|
||||
idx := mathOpIdx(op, kind)
|
||||
if llop := mathOpToLLVM[idx]; llop != 0 {
|
||||
v.impl = llvm.CreateBinOp(b.impl, llop, x.impl, y.impl)
|
||||
return
|
||||
return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
|
||||
}
|
||||
case isLogicOp(op): // op: & | ^ << >> &^
|
||||
if op == token.AND_NOT {
|
||||
panic("todo")
|
||||
}
|
||||
kind := x.kind
|
||||
llop := logicOpToLLVM[op-logicOpBase]
|
||||
if op == token.SHR && x.kind == vkUnsigned {
|
||||
if op == token.SHR && kind == vkUnsigned {
|
||||
llop = llvm.AShr
|
||||
}
|
||||
v.impl = llvm.CreateBinOp(b.impl, llop, x.impl, y.impl)
|
||||
return
|
||||
return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type}
|
||||
case isPredOp(op): // op: == != < <= < >=
|
||||
switch x.kind {
|
||||
tret := b.prog.Bool()
|
||||
kind := x.kind
|
||||
switch kind {
|
||||
case vkSigned:
|
||||
pred := intPredOpToLLVM[op-predOpBase]
|
||||
v.impl = llvm.CreateICmp(b.impl, pred, x.impl, y.impl)
|
||||
return
|
||||
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
||||
case vkUnsigned:
|
||||
pred := uintPredOpToLLVM[op-predOpBase]
|
||||
v.impl = llvm.CreateICmp(b.impl, pred, x.impl, y.impl)
|
||||
return
|
||||
return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret}
|
||||
case vkFloat:
|
||||
pred := floatPredOpToLLVM[op-predOpBase]
|
||||
v.impl = llvm.ConstFCmp(pred, x.impl, y.impl)
|
||||
return
|
||||
return Expr{llvm.ConstFCmp(pred, x.impl, y.impl), tret}
|
||||
case vkString, vkComplex, vkBool:
|
||||
panic("todo")
|
||||
}
|
||||
}
|
||||
return
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
// A Program is a partial or complete Go program converted to SSA form.
|
||||
type aProgram struct {
|
||||
ctx llvm.Context
|
||||
b Builder
|
||||
typs typeutil.Map
|
||||
|
||||
target *Target
|
||||
@@ -35,12 +34,17 @@ type aProgram struct {
|
||||
// tm llvm.TargetMachine
|
||||
|
||||
intType llvm.Type
|
||||
int1Type llvm.Type
|
||||
int8Type llvm.Type
|
||||
int16Type llvm.Type
|
||||
int32Type llvm.Type
|
||||
int64Type llvm.Type
|
||||
voidType llvm.Type
|
||||
voidPtrTy llvm.Type
|
||||
|
||||
boolTy Type
|
||||
intTy Type
|
||||
f64Ty Type
|
||||
}
|
||||
|
||||
type Program = *aProgram
|
||||
@@ -51,20 +55,35 @@ func NewProgram(target *Target) Program {
|
||||
}
|
||||
ctx := llvm.NewContext()
|
||||
ctx.Finalize()
|
||||
b := ctx.NewBuilder()
|
||||
b.Finalize()
|
||||
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.Finalize()
|
||||
return &aPackage{mod, p}
|
||||
}
|
||||
|
||||
func (p *aProgram) Builder() Builder {
|
||||
return p.b
|
||||
func (p Program) Bool() Type {
|
||||
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
|
||||
@@ -82,21 +101,23 @@ type aPackage struct {
|
||||
|
||||
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{}
|
||||
}
|
||||
|
||||
func (p *aPackage) NewVar(name string, typ types.Type) Global {
|
||||
gbl := llvm.AddGlobal(p.mod, p.prog.llvmType(typ), name)
|
||||
return &aGlobal{gbl}
|
||||
func (p Package) NewVar(name string, typ types.Type) Global {
|
||||
t := p.prog.llvmType(typ)
|
||||
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
||||
return &aGlobal{gbl, t}
|
||||
}
|
||||
|
||||
func (p *aPackage) NewFunc(name string, sig *types.Signature) Function {
|
||||
fn := llvm.AddFunction(p.mod, name, p.prog.llvmSignature(sig))
|
||||
return &aFunction{fn, p.prog}
|
||||
func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
||||
t := p.prog.llvmSignature(sig)
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ source_filename = "foo/bar"
|
||||
`)
|
||||
}
|
||||
|
||||
func TestFunc(t *testing.T) {
|
||||
func TestDeclFunc(t *testing.T) {
|
||||
prog := NewProgram(nil)
|
||||
pkg := prog.NewPackage("bar", "foo/bar")
|
||||
params := types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int]))
|
||||
@@ -91,3 +91,19 @@ source_filename = "foo/bar"
|
||||
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
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
131
ssa/type.go
131
ssa/type.go
@@ -22,107 +22,136 @@ import (
|
||||
"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 {
|
||||
return v.(llvm.Type)
|
||||
return v.(Type)
|
||||
}
|
||||
ret := p.toLLVMType(typ)
|
||||
p.typs.Set(typ, 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 {
|
||||
return v.(llvm.Type)
|
||||
return v.(Type)
|
||||
}
|
||||
ret := p.toLLVMFunc(sig)
|
||||
p.typs.Set(sig, ret)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *aProgram) tyVoidPtr() llvm.Type {
|
||||
func (p Program) tyVoidPtr() llvm.Type {
|
||||
if p.voidPtrTy.IsNil() {
|
||||
p.voidPtrTy = llvm.PointerType(p.tyVoid(), 0)
|
||||
}
|
||||
return p.voidPtrTy
|
||||
}
|
||||
|
||||
func (p *aProgram) tyVoid() llvm.Type {
|
||||
func (p Program) tyVoid() llvm.Type {
|
||||
if p.voidType.IsNil() {
|
||||
p.voidType = p.ctx.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() {
|
||||
p.intType = llvmIntType(p.ctx, p.td.PointerSize())
|
||||
}
|
||||
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() {
|
||||
p.int8Type = p.ctx.Int8Type()
|
||||
}
|
||||
return p.int8Type
|
||||
}
|
||||
|
||||
func (p *aProgram) tyInt16() llvm.Type {
|
||||
func (p Program) tyInt16() llvm.Type {
|
||||
if p.int16Type.IsNil() {
|
||||
p.int16Type = p.ctx.Int16Type()
|
||||
}
|
||||
return p.int16Type
|
||||
}
|
||||
|
||||
func (p *aProgram) tyInt32() llvm.Type {
|
||||
func (p Program) tyInt32() llvm.Type {
|
||||
if p.int32Type.IsNil() {
|
||||
p.int32Type = p.ctx.Int32Type()
|
||||
}
|
||||
return p.int32Type
|
||||
}
|
||||
|
||||
func (p *aProgram) tyInt64() llvm.Type {
|
||||
func (p Program) tyInt64() llvm.Type {
|
||||
if p.int64Type.IsNil() {
|
||||
p.int64Type = p.ctx.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) {
|
||||
case *types.Basic:
|
||||
switch t.Kind() {
|
||||
case types.Int, types.Uint, types.Uintptr:
|
||||
return p.tyInt()
|
||||
case types.Bool, types.Uint8, types.Int8:
|
||||
return p.tyInt8()
|
||||
case types.Int16, types.Uint16:
|
||||
return p.tyInt16()
|
||||
case types.Int32, types.Uint32:
|
||||
return p.tyInt32()
|
||||
case types.Int64, types.Uint64:
|
||||
return p.tyInt64()
|
||||
case types.Int:
|
||||
return &aType{p.tyInt(), typ, vkSigned}
|
||||
case types.Uint, types.Uintptr:
|
||||
return &aType{p.tyInt(), typ, vkUnsigned}
|
||||
case types.Bool:
|
||||
return &aType{p.tyInt1(), typ, vkBool}
|
||||
case types.Uint8:
|
||||
return &aType{p.tyInt8(), typ, vkUnsigned}
|
||||
case types.Int8:
|
||||
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:
|
||||
return p.ctx.FloatType()
|
||||
return &aType{p.ctx.FloatType(), typ, vkFloat}
|
||||
case types.Float64:
|
||||
return p.ctx.DoubleType()
|
||||
return &aType{p.ctx.DoubleType(), typ, vkFloat}
|
||||
case types.Complex64:
|
||||
case types.Complex128:
|
||||
case types.String:
|
||||
case types.UnsafePointer:
|
||||
return p.tyVoidPtr()
|
||||
return &aType{p.tyVoidPtr(), typ, vkInvalid}
|
||||
}
|
||||
case *types.Pointer:
|
||||
elem := p.llvmType(t.Elem())
|
||||
return llvm.PointerType(elem, 0)
|
||||
return &aType{llvm.PointerType(elem.ll, 0), typ, vkInvalid}
|
||||
case *types.Slice:
|
||||
case *types.Map:
|
||||
case *types.Struct:
|
||||
@@ -133,54 +162,47 @@ func (p *aProgram) toLLVMType(typ types.Type) llvm.Type {
|
||||
return p.toLLVMFunc(t)
|
||||
case *types.Array:
|
||||
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:
|
||||
}
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
func llvmIntType(ctx llvm.Context, size int) llvm.Type {
|
||||
if size <= 4 {
|
||||
return ctx.Int32Type()
|
||||
}
|
||||
return ctx.Int64Type()
|
||||
}
|
||||
|
||||
func (p *aProgram) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
|
||||
func (p Program) toLLVMNamedStruct(name string, typ *types.Struct) llvm.Type {
|
||||
t := p.ctx.StructCreateNamed(name)
|
||||
fields := p.toLLVMFields(typ)
|
||||
t.StructSetBody(fields, false)
|
||||
return t
|
||||
}
|
||||
|
||||
func (p *aProgram) toLLVMStruct(typ *types.Struct) llvm.Type {
|
||||
func (p Program) toLLVMStruct(typ *types.Struct) Type {
|
||||
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()
|
||||
fields := make([]llvm.Type, n)
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (p *aProgram) toLLVMTypes(t *types.Tuple) []llvm.Type {
|
||||
func (p Program) toLLVMTypes(t *types.Tuple) []llvm.Type {
|
||||
n := t.Len()
|
||||
ret := make([]llvm.Type, n)
|
||||
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
|
||||
}
|
||||
|
||||
func (p *aProgram) toLLVMFunc(sig *types.Signature) llvm.Type {
|
||||
func (p Program) toLLVMFunc(sig *types.Signature) Type {
|
||||
params := p.toLLVMTypes(sig.Params())
|
||||
results := sig.Results()
|
||||
var ret llvm.Type
|
||||
@@ -188,18 +210,21 @@ func (p *aProgram) toLLVMFunc(sig *types.Signature) llvm.Type {
|
||||
case 0:
|
||||
ret = p.tyVoid()
|
||||
case 1:
|
||||
ret = p.llvmType(results.At(0).Type())
|
||||
ret = p.llvmType(results.At(0).Type()).ll
|
||||
default:
|
||||
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()
|
||||
switch typ := typ.Underlying().(type) {
|
||||
case *types.Struct:
|
||||
return p.toLLVMNamedStruct(name, typ)
|
||||
return &aType{p.toLLVMNamedStruct(name, typ), typ, vkInvalid}
|
||||
}
|
||||
panic("todo")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user