@@ -38,6 +38,8 @@ type Program struct {
|
|||||||
int16Type llvm.Type
|
int16Type llvm.Type
|
||||||
int32Type llvm.Type
|
int32Type llvm.Type
|
||||||
int64Type llvm.Type
|
int64Type llvm.Type
|
||||||
|
voidType llvm.Type
|
||||||
|
voidPtrTy llvm.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProgram(target *Target) *Program {
|
func NewProgram(target *Target) *Program {
|
||||||
@@ -73,10 +75,6 @@ func (p *Package) NewConst(name string, val constant.Value) *NamedConst {
|
|||||||
return &NamedConst{}
|
return &NamedConst{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Package) NewType(name string, typ types.Type) *Type {
|
|
||||||
return &Type{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Package) 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)
|
gbl := llvm.AddGlobal(p.mod, p.prog.llvmType(typ), name)
|
||||||
return &Global{gbl}
|
return &Global{gbl}
|
||||||
|
|||||||
@@ -49,3 +49,32 @@ source_filename = "foo/bar"
|
|||||||
@a = external global i64
|
@a = external global i64
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStruct(t *testing.T) {
|
||||||
|
empty := types.NewStruct(nil, nil)
|
||||||
|
|
||||||
|
prog := NewProgram(nil)
|
||||||
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
|
pkg.NewVar("a", empty)
|
||||||
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
|
@a = external global {}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNamedStruct(t *testing.T) {
|
||||||
|
src := types.NewPackage("bar", "foo/bar")
|
||||||
|
empty := types.NewNamed(types.NewTypeName(0, src, "Empty", nil), types.NewStruct(nil, nil), nil)
|
||||||
|
|
||||||
|
prog := NewProgram(nil)
|
||||||
|
pkg := prog.NewPackage("bar", "foo/bar")
|
||||||
|
pkg.NewVar("a", empty)
|
||||||
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
|
%Empty = type {}
|
||||||
|
|
||||||
|
@a = external global %Empty
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|||||||
100
ssa/type.go
100
ssa/type.go
@@ -22,19 +22,36 @@ import (
|
|||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
// A Type is a Member of a Package representing a package-level named type.
|
// A Type is a Member of a Package representing a package-level named type.
|
||||||
type Type struct {
|
type Type struct {
|
||||||
|
impl llvm.Type
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (p *Program) llvmType(typ types.Type) llvm.Type {
|
func (p *Program) llvmType(typ types.Type) llvm.Type {
|
||||||
if v := p.typs.At(typ); v != nil {
|
if v := p.typs.At(typ); v != nil {
|
||||||
return v.(llvm.Type)
|
return v.(llvm.Type)
|
||||||
}
|
}
|
||||||
ret := p.toLLVMType(p.ctx, typ)
|
ret := p.toLLVMType(typ)
|
||||||
p.typs.Set(typ, ret)
|
p.typs.Set(typ, ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Program) tyVoidPtr() llvm.Type {
|
||||||
|
if p.voidPtrTy.IsNil() {
|
||||||
|
p.voidPtrTy = llvm.PointerType(p.tyVoid(), 0)
|
||||||
|
}
|
||||||
|
return p.voidPtrTy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Program) tyVoid() llvm.Type {
|
||||||
|
if p.voidType.IsNil() {
|
||||||
|
p.voidType = p.ctx.VoidType()
|
||||||
|
}
|
||||||
|
return p.voidType
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Program) tyInt() llvm.Type {
|
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())
|
||||||
@@ -70,7 +87,7 @@ func (p *Program) tyInt64() llvm.Type {
|
|||||||
return p.int64Type
|
return p.int64Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Program) toLLVMType(ctx llvm.Context, typ types.Type) llvm.Type {
|
func (p *Program) toLLVMType(typ types.Type) llvm.Type {
|
||||||
switch t := typ.(type) {
|
switch t := typ.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
@@ -85,15 +102,30 @@ func (p *Program) toLLVMType(ctx llvm.Context, typ types.Type) llvm.Type {
|
|||||||
case types.Int64, types.Uint64:
|
case types.Int64, types.Uint64:
|
||||||
return p.tyInt64()
|
return p.tyInt64()
|
||||||
case types.Float32:
|
case types.Float32:
|
||||||
return ctx.FloatType()
|
return p.ctx.FloatType()
|
||||||
case types.Float64:
|
case types.Float64:
|
||||||
return ctx.DoubleType()
|
return p.ctx.DoubleType()
|
||||||
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 llvm.PointerType(ctx.VoidType(), 0)
|
return p.tyVoidPtr()
|
||||||
}
|
}
|
||||||
|
case *types.Pointer:
|
||||||
|
elem := p.llvmType(t.Elem())
|
||||||
|
return llvm.PointerType(elem, 0)
|
||||||
|
case *types.Slice:
|
||||||
|
case *types.Map:
|
||||||
|
case *types.Struct:
|
||||||
|
return p.toLLVMStruct(t)
|
||||||
|
case *types.Named:
|
||||||
|
return p.toLLVMNamed(t)
|
||||||
|
case *types.Signature:
|
||||||
|
return p.toLLVMFunc(t)
|
||||||
|
case *types.Array:
|
||||||
|
elem := p.llvmType(t.Elem())
|
||||||
|
return llvm.ArrayType(elem, int(t.Len()))
|
||||||
|
case *types.Chan:
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
@@ -104,3 +136,61 @@ func llvmIntType(ctx llvm.Context, size int) llvm.Type {
|
|||||||
}
|
}
|
||||||
return ctx.Int64Type()
|
return ctx.Int64Type()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 *Program) toLLVMStruct(typ *types.Struct) llvm.Type {
|
||||||
|
fields := p.toLLVMFields(typ)
|
||||||
|
return p.ctx.StructType(fields, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Program) toLLVMTuple(t *types.Tuple) llvm.Type {
|
||||||
|
return p.ctx.StructType(p.toLLVMTypes(t), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Program) toLLVMFunc(sig *types.Signature) llvm.Type {
|
||||||
|
params := p.toLLVMTypes(sig.Params())
|
||||||
|
results := sig.Results()
|
||||||
|
var ret llvm.Type
|
||||||
|
switch nret := results.Len(); nret {
|
||||||
|
case 0:
|
||||||
|
ret = p.tyVoid()
|
||||||
|
case 1:
|
||||||
|
ret = p.llvmType(results.At(0).Type())
|
||||||
|
default:
|
||||||
|
ret = p.toLLVMTuple(results)
|
||||||
|
}
|
||||||
|
return llvm.FunctionType(ret, params, sig.Variadic())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Program) toLLVMNamed(typ *types.Named) llvm.Type {
|
||||||
|
name := typ.Obj().Name()
|
||||||
|
switch typ := typ.Underlying().(type) {
|
||||||
|
case *types.Struct:
|
||||||
|
return p.toLLVMNamedStruct(name, typ)
|
||||||
|
}
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user