aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compiler/channel.go2
-rw-r--r--compiler/compiler.go66
-rw-r--r--compiler/defer.go8
-rw-r--r--compiler/func-lowering.go2
-rw-r--r--compiler/func.go4
-rw-r--r--compiler/goroutine-lowering.go2
-rw-r--r--compiler/interface-lowering.go4
-rw-r--r--compiler/interface.go10
-rw-r--r--ir/ir.go16
9 files changed, 51 insertions, 63 deletions
diff --git a/compiler/channel.go b/compiler/channel.go
index b5bcd95b9..8098ea99a 100644
--- a/compiler/channel.go
+++ b/compiler/channel.go
@@ -12,7 +12,7 @@ import (
// emitMakeChan returns a new channel value for the given channel type.
func (c *Compiler) emitMakeChan(expr *ssa.MakeChan) (llvm.Value, error) {
- chanType := c.mod.GetTypeByName("runtime.channel")
+ chanType := c.getLLVMType(c.getRuntimeType("channel"))
size := c.targetData.TypeAllocSize(chanType)
sizeValue := llvm.ConstInt(c.uintptrType, size, false)
ptr := c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "chan.alloc")
diff --git a/compiler/compiler.go b/compiler/compiler.go
index 821b6270c..1c22208cc 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -275,25 +275,6 @@ func (c *Compiler) Compile(mainPath string) []error {
var frames []*Frame
- // Declare all named struct types.
- for _, t := range c.ir.NamedTypes {
- if named, ok := t.Type.Type().(*types.Named); ok {
- if _, ok := named.Underlying().(*types.Struct); ok {
- t.LLVMType = c.ctx.StructCreateNamed(named.Obj().Pkg().Path() + "." + named.Obj().Name())
- }
- }
- }
-
- // Define all named struct types.
- for _, t := range c.ir.NamedTypes {
- if named, ok := t.Type.Type().(*types.Named); ok {
- if st, ok := named.Underlying().(*types.Struct); ok {
- llvmType := c.getLLVMType(st)
- t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false)
- }
- }
- }
-
// Declare all globals.
for _, g := range c.ir.Globals {
typ := g.Type().(*types.Pointer).Elem()
@@ -413,6 +394,22 @@ func (c *Compiler) Compile(mainPath string) []error {
return c.diagnostics
}
+// getRuntimeType obtains a named type from the runtime package and returns it
+// as a Go type.
+func (c *Compiler) getRuntimeType(name string) types.Type {
+ return c.ir.Program.ImportedPackage("runtime").Type(name).Type()
+}
+
+// getLLVMRuntimeType obtains a named type from the runtime package and returns
+// it as a LLVM type, creating it if necessary. It is a shorthand for
+// getLLVMType(getRuntimeType(name)).
+func (c *Compiler) getLLVMRuntimeType(name string) llvm.Type {
+ return c.getLLVMType(c.getRuntimeType(name))
+}
+
+// getLLVMType creates and returns a LLVM type for a Go type. In the case of
+// named struct types (or Go types implemented as named LLVM structs such as
+// strings) it also creates it first if necessary.
func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
switch typ := goType.(type) {
case *types.Array:
@@ -441,7 +438,7 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
case types.Complex128:
return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)
case types.String, types.UntypedString:
- return c.mod.GetTypeByName("runtime._string")
+ return c.getLLVMRuntimeType("_string")
case types.Uintptr:
return c.uintptrType
case types.UnsafePointer:
@@ -450,16 +447,23 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
panic("unknown basic type: " + typ.String())
}
case *types.Chan:
- return llvm.PointerType(c.mod.GetTypeByName("runtime.channel"), 0)
+ return llvm.PointerType(c.getLLVMRuntimeType("channel"), 0)
case *types.Interface:
- return c.mod.GetTypeByName("runtime._interface")
+ return c.getLLVMRuntimeType("_interface")
case *types.Map:
- return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0)
+ return llvm.PointerType(c.getLLVMRuntimeType("hashmap"), 0)
case *types.Named:
- if _, ok := typ.Underlying().(*types.Struct); ok {
- llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
+ if st, ok := typ.Underlying().(*types.Struct); ok {
+ // Structs are a special case. While other named types are ignored
+ // in LLVM IR, named structs are implemented as named structs in
+ // LLVM. This is because it is otherwise impossible to create
+ // self-referencing types such as linked lists.
+ llvmName := typ.Obj().Pkg().Path() + "." + typ.Obj().Name()
+ llvmType := c.mod.GetTypeByName(llvmName)
if llvmType.IsNil() {
- panic("underlying type not found: " + typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
+ llvmType = c.ctx.StructCreateNamed(llvmName)
+ underlying := c.getLLVMType(st)
+ llvmType.StructSetBody(underlying.StructElementTypes(), false)
}
return llvmType
}
@@ -1693,9 +1697,9 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
var iteratorType llvm.Type
switch typ := expr.X.Type().Underlying().(type) {
case *types.Basic: // string
- iteratorType = c.mod.GetTypeByName("runtime.stringIterator")
+ iteratorType = c.getLLVMRuntimeType("stringIterator")
case *types.Map:
- iteratorType = c.mod.GetTypeByName("runtime.hashmapIterator")
+ iteratorType = c.getLLVMRuntimeType("hashmapIterator")
default:
panic("unknown type in range: " + typ.String())
}
@@ -1855,7 +1859,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
newPtr := c.builder.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "")
newLen := c.builder.CreateSub(high, low, "")
- str := llvm.Undef(c.mod.GetTypeByName("runtime._string"))
+ str := llvm.Undef(c.getLLVMRuntimeType("_string"))
str = c.builder.CreateInsertValue(str, newPtr, 0, "")
str = c.builder.CreateInsertValue(str, newLen, 1, "")
return str, nil
@@ -2234,7 +2238,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value {
global.SetUnnamedAddr(true)
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
strPtr := c.builder.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "")
- strObj := llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._string"), []llvm.Value{strPtr, strLen})
+ strObj := llvm.ConstNamedStruct(c.getLLVMRuntimeType("_string"), []llvm.Value{strPtr, strLen})
return strObj
} else if typ.Kind() == types.UnsafePointer {
if !expr.IsNil() {
@@ -2287,7 +2291,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value {
llvm.ConstInt(c.uintptrType, 0, false),
llvm.ConstPointerNull(c.i8ptrType),
}
- return llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._interface"), fields)
+ return llvm.ConstNamedStruct(c.getLLVMRuntimeType("_interface"), fields)
case *types.Pointer:
if expr.Value != nil {
panic("expected nil pointer constant")
diff --git a/compiler/defer.go b/compiler/defer.go
index 1246f03a0..21fff3aad 100644
--- a/compiler/defer.go
+++ b/compiler/defer.go
@@ -29,7 +29,7 @@ func (c *Compiler) deferInitFunc(frame *Frame) {
frame.deferClosureFuncs = make(map[*ir.Function]int)
// Create defer list pointer.
- deferType := llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)
+ deferType := llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0)
frame.deferPtr = c.builder.CreateAlloca(deferType, "deferPtr")
c.builder.CreateStore(llvm.ConstPointerNull(deferType), frame.deferPtr)
}
@@ -200,7 +200,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
}
// Get the real defer struct type and cast to it.
- valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0), c.i8ptrType}
+ valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0), c.i8ptrType}
for _, arg := range callback.Args {
valueTypes = append(valueTypes, c.getLLVMType(arg.Type()))
}
@@ -231,7 +231,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
// Direct call.
// Get the real defer struct type and cast to it.
- valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)}
+ valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0)}
for _, param := range callback.Params {
valueTypes = append(valueTypes, c.getLLVMType(param.Type()))
}
@@ -260,7 +260,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
case *ssa.MakeClosure:
// Get the real defer struct type and cast to it.
fn := c.ir.GetFunction(callback.Fn.(*ssa.Function))
- valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)}
+ valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.getLLVMRuntimeType("_defer"), 0)}
params := fn.Signature.Params()
for i := 0; i < params.Len(); i++ {
valueTypes = append(valueTypes, c.getLLVMType(params.At(i).Type()))
diff --git a/compiler/func-lowering.go b/compiler/func-lowering.go
index a774b23ac..2d67e2a5f 100644
--- a/compiler/func-lowering.go
+++ b/compiler/func-lowering.go
@@ -51,7 +51,7 @@ func (c *Compiler) LowerFuncValues() {
}
// Find all func values used in the program with their signatures.
- funcValueWithSignaturePtr := llvm.PointerType(c.mod.GetTypeByName("runtime.funcValueWithSignature"), 0)
+ funcValueWithSignaturePtr := llvm.PointerType(c.getLLVMRuntimeType("funcValueWithSignature"), 0)
signatures := map[string]*funcSignatureInfo{}
for global := c.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
if global.Type() != funcValueWithSignaturePtr {
diff --git a/compiler/func.go b/compiler/func.go
index 8a2e1ab39..c4806a09d 100644
--- a/compiler/func.go
+++ b/compiler/func.go
@@ -52,7 +52,7 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa
funcValueWithSignatureGlobalName := funcPtr.Name() + "$withSignature"
funcValueWithSignatureGlobal := c.mod.NamedGlobal(funcValueWithSignatureGlobalName)
if funcValueWithSignatureGlobal.IsNil() {
- funcValueWithSignatureType := c.mod.GetTypeByName("runtime.funcValueWithSignature")
+ funcValueWithSignatureType := c.getLLVMRuntimeType("funcValueWithSignature")
funcValueWithSignature := llvm.ConstNamedStruct(funcValueWithSignatureType, []llvm.Value{
llvm.ConstPtrToInt(funcPtr, c.uintptrType),
sigGlobal,
@@ -126,7 +126,7 @@ func (c *Compiler) getFuncType(typ *types.Signature) llvm.Type {
rawPtr := c.getRawFuncType(typ)
return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false)
case funcValueSwitch:
- return c.mod.GetTypeByName("runtime.funcValue")
+ return c.getLLVMRuntimeType("funcValue")
default:
panic("unimplemented func value variant")
}
diff --git a/compiler/goroutine-lowering.go b/compiler/goroutine-lowering.go
index c493bf48c..3aa72e938 100644
--- a/compiler/goroutine-lowering.go
+++ b/compiler/goroutine-lowering.go
@@ -321,7 +321,7 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
// Coroutine setup.
c.builder.SetInsertPointBefore(f.EntryBasicBlock().FirstInstruction())
- taskState := c.builder.CreateAlloca(c.mod.GetTypeByName("runtime.taskState"), "task.state")
+ taskState := c.builder.CreateAlloca(c.getLLVMRuntimeType("taskState"), "task.state")
stateI8 := c.builder.CreateBitCast(taskState, c.i8ptrType, "task.state.i8")
id := c.builder.CreateCall(coroIdFunc, []llvm.Value{
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
diff --git a/compiler/interface-lowering.go b/compiler/interface-lowering.go
index 3df1c6443..6a756410c 100644
--- a/compiler/interface-lowering.go
+++ b/compiler/interface-lowering.go
@@ -163,8 +163,8 @@ func (c *Compiler) LowerInterfaces() {
// run runs the pass itself.
func (p *lowerInterfacesPass) run() {
// Collect all type codes.
- typecodeIDPtr := llvm.PointerType(p.mod.GetTypeByName("runtime.typecodeID"), 0)
- typeInInterfacePtr := llvm.PointerType(p.mod.GetTypeByName("runtime.typeInInterface"), 0)
+ typecodeIDPtr := llvm.PointerType(p.getLLVMRuntimeType("typecodeID"), 0)
+ typeInInterfacePtr := llvm.PointerType(p.getLLVMRuntimeType("typeInInterface"), 0)
var typesInInterfaces []llvm.Value
for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
switch global.Type() {
diff --git a/compiler/interface.go b/compiler/interface.go
index 3d2014f31..d91b8063f 100644
--- a/compiler/interface.go
+++ b/compiler/interface.go
@@ -28,14 +28,14 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, pos token.
itfMethodSetGlobal := c.getTypeMethodSet(typ)
itfConcreteTypeGlobal := c.mod.NamedGlobal("typeInInterface:" + itfTypeCodeGlobal.Name())
if itfConcreteTypeGlobal.IsNil() {
- typeInInterface := c.mod.GetTypeByName("runtime.typeInInterface")
+ typeInInterface := c.getLLVMRuntimeType("typeInInterface")
itfConcreteTypeGlobal = llvm.AddGlobal(c.mod, typeInInterface, "typeInInterface:"+itfTypeCodeGlobal.Name())
itfConcreteTypeGlobal.SetInitializer(llvm.ConstNamedStruct(typeInInterface, []llvm.Value{itfTypeCodeGlobal, itfMethodSetGlobal}))
itfConcreteTypeGlobal.SetGlobalConstant(true)
itfConcreteTypeGlobal.SetLinkage(llvm.PrivateLinkage)
}
itfTypeCode := c.builder.CreatePtrToInt(itfConcreteTypeGlobal, c.uintptrType, "")
- itf := llvm.Undef(c.mod.GetTypeByName("runtime._interface"))
+ itf := llvm.Undef(c.getLLVMRuntimeType("_interface"))
itf = c.builder.CreateInsertValue(itf, itfTypeCode, 0, "")
itf = c.builder.CreateInsertValue(itf, itfValue, 1, "")
return itf
@@ -48,7 +48,7 @@ func (c *Compiler) getTypeCode(typ types.Type) llvm.Value {
globalName := "type:" + getTypeCodeName(typ)
global := c.mod.NamedGlobal(globalName)
if global.IsNil() {
- global = llvm.AddGlobal(c.mod, c.mod.GetTypeByName("runtime.typecodeID"), globalName)
+ global = llvm.AddGlobal(c.mod, c.getLLVMRuntimeType("typecodeID"), globalName)
global.SetGlobalConstant(true)
}
return global
@@ -163,11 +163,11 @@ func (c *Compiler) getTypeMethodSet(typ types.Type) llvm.Value {
ms := c.ir.Program.MethodSets.MethodSet(typ)
if ms.Len() == 0 {
// no methods, so can leave that one out
- return llvm.ConstPointerNull(llvm.PointerType(c.mod.GetTypeByName("runtime.interfaceMethodInfo"), 0))
+ return llvm.ConstPointerNull(llvm.PointerType(c.getLLVMRuntimeType("interfaceMethodInfo"), 0))
}
methods := make([]llvm.Value, ms.Len())
- interfaceMethodInfoType := c.mod.GetTypeByName("runtime.interfaceMethodInfo")
+ interfaceMethodInfoType := c.getLLVMRuntimeType("interfaceMethodInfo")
for i := 0; i < ms.Len(); i++ {
method := ms.At(i)
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
diff --git a/ir/ir.go b/ir/ir.go
index 1556330ef..5f73b90e1 100644
--- a/ir/ir.go
+++ b/ir/ir.go
@@ -26,7 +26,6 @@ type Program struct {
Globals []*Global
globalMap map[*ssa.Global]*Global
comments map[string]*ast.CommentGroup
- NamedTypes []*NamedType
}
// Function or method.
@@ -50,19 +49,6 @@ type Global struct {
extern bool // go:extern
}
-// Type with a name and possibly methods.
-type NamedType struct {
- *ssa.Type
- LLVMType llvm.Type
-}
-
-// Type that is at some point put in an interface.
-type TypeWithMethods struct {
- t types.Type
- Num int
- Methods map[string]*types.Selection
-}
-
// Interface type that is at some point used in a type assert (to check whether
// it implements another interface).
type Interface struct {
@@ -210,8 +196,6 @@ func (p *Program) AddPackage(pkg *ssa.Package) {
case *ssa.Function:
p.addFunction(member)
case *ssa.Type:
- t := &NamedType{Type: member}
- p.NamedTypes = append(p.NamedTypes, t)
methods := getAllMethods(pkg.Prog, member.Type())
if !types.IsInterface(member.Type()) {
// named type