compiler: refactor named types to create them lazily
This commit refactors named types to be created lazily. Instead of defining all types in advance, do it only when necessary.
Этот коммит содержится в:
родитель
88bb61f287
коммит
6b5b4a681d
9 изменённых файлов: 51 добавлений и 63 удалений
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
// emitMakeChan returns a new channel value for the given channel type.
|
// emitMakeChan returns a new channel value for the given channel type.
|
||||||
func (c *Compiler) emitMakeChan(expr *ssa.MakeChan) (llvm.Value, error) {
|
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)
|
size := c.targetData.TypeAllocSize(chanType)
|
||||||
sizeValue := llvm.ConstInt(c.uintptrType, size, false)
|
sizeValue := llvm.ConstInt(c.uintptrType, size, false)
|
||||||
ptr := c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "chan.alloc")
|
ptr := c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "chan.alloc")
|
||||||
|
|
|
@ -275,25 +275,6 @@ func (c *Compiler) Compile(mainPath string) []error {
|
||||||
|
|
||||||
var frames []*Frame
|
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.
|
// Declare all globals.
|
||||||
for _, g := range c.ir.Globals {
|
for _, g := range c.ir.Globals {
|
||||||
typ := g.Type().(*types.Pointer).Elem()
|
typ := g.Type().(*types.Pointer).Elem()
|
||||||
|
@ -413,6 +394,22 @@ func (c *Compiler) Compile(mainPath string) []error {
|
||||||
return c.diagnostics
|
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 {
|
func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
|
||||||
switch typ := goType.(type) {
|
switch typ := goType.(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
|
@ -441,7 +438,7 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
|
||||||
case types.Complex128:
|
case types.Complex128:
|
||||||
return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)
|
return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)
|
||||||
case types.String, types.UntypedString:
|
case types.String, types.UntypedString:
|
||||||
return c.mod.GetTypeByName("runtime._string")
|
return c.getLLVMRuntimeType("_string")
|
||||||
case types.Uintptr:
|
case types.Uintptr:
|
||||||
return c.uintptrType
|
return c.uintptrType
|
||||||
case types.UnsafePointer:
|
case types.UnsafePointer:
|
||||||
|
@ -450,16 +447,23 @@ func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
|
||||||
panic("unknown basic type: " + typ.String())
|
panic("unknown basic type: " + typ.String())
|
||||||
}
|
}
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
return llvm.PointerType(c.mod.GetTypeByName("runtime.channel"), 0)
|
return llvm.PointerType(c.getLLVMRuntimeType("channel"), 0)
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
return c.mod.GetTypeByName("runtime._interface")
|
return c.getLLVMRuntimeType("_interface")
|
||||||
case *types.Map:
|
case *types.Map:
|
||||||
return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0)
|
return llvm.PointerType(c.getLLVMRuntimeType("hashmap"), 0)
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
if _, ok := typ.Underlying().(*types.Struct); ok {
|
if st, ok := typ.Underlying().(*types.Struct); ok {
|
||||||
llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
|
// 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() {
|
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
|
return llvmType
|
||||||
}
|
}
|
||||||
|
@ -1693,9 +1697,9 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
|
||||||
var iteratorType llvm.Type
|
var iteratorType llvm.Type
|
||||||
switch typ := expr.X.Type().Underlying().(type) {
|
switch typ := expr.X.Type().Underlying().(type) {
|
||||||
case *types.Basic: // string
|
case *types.Basic: // string
|
||||||
iteratorType = c.mod.GetTypeByName("runtime.stringIterator")
|
iteratorType = c.getLLVMRuntimeType("stringIterator")
|
||||||
case *types.Map:
|
case *types.Map:
|
||||||
iteratorType = c.mod.GetTypeByName("runtime.hashmapIterator")
|
iteratorType = c.getLLVMRuntimeType("hashmapIterator")
|
||||||
default:
|
default:
|
||||||
panic("unknown type in range: " + typ.String())
|
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}, "")
|
newPtr := c.builder.CreateInBoundsGEP(oldPtr, []llvm.Value{low}, "")
|
||||||
newLen := c.builder.CreateSub(high, 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, newPtr, 0, "")
|
||||||
str = c.builder.CreateInsertValue(str, newLen, 1, "")
|
str = c.builder.CreateInsertValue(str, newLen, 1, "")
|
||||||
return str, nil
|
return str, nil
|
||||||
|
@ -2234,7 +2238,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) llvm.Value {
|
||||||
global.SetUnnamedAddr(true)
|
global.SetUnnamedAddr(true)
|
||||||
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
||||||
strPtr := c.builder.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "")
|
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
|
return strObj
|
||||||
} else if typ.Kind() == types.UnsafePointer {
|
} else if typ.Kind() == types.UnsafePointer {
|
||||||
if !expr.IsNil() {
|
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.ConstInt(c.uintptrType, 0, false),
|
||||||
llvm.ConstPointerNull(c.i8ptrType),
|
llvm.ConstPointerNull(c.i8ptrType),
|
||||||
}
|
}
|
||||||
return llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._interface"), fields)
|
return llvm.ConstNamedStruct(c.getLLVMRuntimeType("_interface"), fields)
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
if expr.Value != nil {
|
if expr.Value != nil {
|
||||||
panic("expected nil pointer constant")
|
panic("expected nil pointer constant")
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (c *Compiler) deferInitFunc(frame *Frame) {
|
||||||
frame.deferClosureFuncs = make(map[*ir.Function]int)
|
frame.deferClosureFuncs = make(map[*ir.Function]int)
|
||||||
|
|
||||||
// Create defer list pointer.
|
// 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")
|
frame.deferPtr = c.builder.CreateAlloca(deferType, "deferPtr")
|
||||||
c.builder.CreateStore(llvm.ConstPointerNull(deferType), frame.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.
|
// 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 {
|
for _, arg := range callback.Args {
|
||||||
valueTypes = append(valueTypes, c.getLLVMType(arg.Type()))
|
valueTypes = append(valueTypes, c.getLLVMType(arg.Type()))
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
||||||
// Direct call.
|
// Direct call.
|
||||||
|
|
||||||
// Get the real defer struct type and cast to it.
|
// 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 {
|
for _, param := range callback.Params {
|
||||||
valueTypes = append(valueTypes, c.getLLVMType(param.Type()))
|
valueTypes = append(valueTypes, c.getLLVMType(param.Type()))
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) {
|
||||||
case *ssa.MakeClosure:
|
case *ssa.MakeClosure:
|
||||||
// Get the real defer struct type and cast to it.
|
// Get the real defer struct type and cast to it.
|
||||||
fn := c.ir.GetFunction(callback.Fn.(*ssa.Function))
|
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()
|
params := fn.Signature.Params()
|
||||||
for i := 0; i < params.Len(); i++ {
|
for i := 0; i < params.Len(); i++ {
|
||||||
valueTypes = append(valueTypes, c.getLLVMType(params.At(i).Type()))
|
valueTypes = append(valueTypes, c.getLLVMType(params.At(i).Type()))
|
||||||
|
|
|
@ -51,7 +51,7 @@ func (c *Compiler) LowerFuncValues() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all func values used in the program with their signatures.
|
// 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{}
|
signatures := map[string]*funcSignatureInfo{}
|
||||||
for global := c.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
for global := c.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
||||||
if global.Type() != funcValueWithSignaturePtr {
|
if global.Type() != funcValueWithSignaturePtr {
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa
|
||||||
funcValueWithSignatureGlobalName := funcPtr.Name() + "$withSignature"
|
funcValueWithSignatureGlobalName := funcPtr.Name() + "$withSignature"
|
||||||
funcValueWithSignatureGlobal := c.mod.NamedGlobal(funcValueWithSignatureGlobalName)
|
funcValueWithSignatureGlobal := c.mod.NamedGlobal(funcValueWithSignatureGlobalName)
|
||||||
if funcValueWithSignatureGlobal.IsNil() {
|
if funcValueWithSignatureGlobal.IsNil() {
|
||||||
funcValueWithSignatureType := c.mod.GetTypeByName("runtime.funcValueWithSignature")
|
funcValueWithSignatureType := c.getLLVMRuntimeType("funcValueWithSignature")
|
||||||
funcValueWithSignature := llvm.ConstNamedStruct(funcValueWithSignatureType, []llvm.Value{
|
funcValueWithSignature := llvm.ConstNamedStruct(funcValueWithSignatureType, []llvm.Value{
|
||||||
llvm.ConstPtrToInt(funcPtr, c.uintptrType),
|
llvm.ConstPtrToInt(funcPtr, c.uintptrType),
|
||||||
sigGlobal,
|
sigGlobal,
|
||||||
|
@ -126,7 +126,7 @@ func (c *Compiler) getFuncType(typ *types.Signature) llvm.Type {
|
||||||
rawPtr := c.getRawFuncType(typ)
|
rawPtr := c.getRawFuncType(typ)
|
||||||
return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false)
|
return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false)
|
||||||
case funcValueSwitch:
|
case funcValueSwitch:
|
||||||
return c.mod.GetTypeByName("runtime.funcValue")
|
return c.getLLVMRuntimeType("funcValue")
|
||||||
default:
|
default:
|
||||||
panic("unimplemented func value variant")
|
panic("unimplemented func value variant")
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
|
||||||
|
|
||||||
// Coroutine setup.
|
// Coroutine setup.
|
||||||
c.builder.SetInsertPointBefore(f.EntryBasicBlock().FirstInstruction())
|
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")
|
stateI8 := c.builder.CreateBitCast(taskState, c.i8ptrType, "task.state.i8")
|
||||||
id := c.builder.CreateCall(coroIdFunc, []llvm.Value{
|
id := c.builder.CreateCall(coroIdFunc, []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
|
||||||
|
|
|
@ -163,8 +163,8 @@ func (c *Compiler) LowerInterfaces() {
|
||||||
// run runs the pass itself.
|
// run runs the pass itself.
|
||||||
func (p *lowerInterfacesPass) run() {
|
func (p *lowerInterfacesPass) run() {
|
||||||
// Collect all type codes.
|
// Collect all type codes.
|
||||||
typecodeIDPtr := llvm.PointerType(p.mod.GetTypeByName("runtime.typecodeID"), 0)
|
typecodeIDPtr := llvm.PointerType(p.getLLVMRuntimeType("typecodeID"), 0)
|
||||||
typeInInterfacePtr := llvm.PointerType(p.mod.GetTypeByName("runtime.typeInInterface"), 0)
|
typeInInterfacePtr := llvm.PointerType(p.getLLVMRuntimeType("typeInInterface"), 0)
|
||||||
var typesInInterfaces []llvm.Value
|
var typesInInterfaces []llvm.Value
|
||||||
for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
for global := p.mod.FirstGlobal(); !global.IsNil(); global = llvm.NextGlobal(global) {
|
||||||
switch global.Type() {
|
switch global.Type() {
|
||||||
|
|
|
@ -28,14 +28,14 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, pos token.
|
||||||
itfMethodSetGlobal := c.getTypeMethodSet(typ)
|
itfMethodSetGlobal := c.getTypeMethodSet(typ)
|
||||||
itfConcreteTypeGlobal := c.mod.NamedGlobal("typeInInterface:" + itfTypeCodeGlobal.Name())
|
itfConcreteTypeGlobal := c.mod.NamedGlobal("typeInInterface:" + itfTypeCodeGlobal.Name())
|
||||||
if itfConcreteTypeGlobal.IsNil() {
|
if itfConcreteTypeGlobal.IsNil() {
|
||||||
typeInInterface := c.mod.GetTypeByName("runtime.typeInInterface")
|
typeInInterface := c.getLLVMRuntimeType("typeInInterface")
|
||||||
itfConcreteTypeGlobal = llvm.AddGlobal(c.mod, typeInInterface, "typeInInterface:"+itfTypeCodeGlobal.Name())
|
itfConcreteTypeGlobal = llvm.AddGlobal(c.mod, typeInInterface, "typeInInterface:"+itfTypeCodeGlobal.Name())
|
||||||
itfConcreteTypeGlobal.SetInitializer(llvm.ConstNamedStruct(typeInInterface, []llvm.Value{itfTypeCodeGlobal, itfMethodSetGlobal}))
|
itfConcreteTypeGlobal.SetInitializer(llvm.ConstNamedStruct(typeInInterface, []llvm.Value{itfTypeCodeGlobal, itfMethodSetGlobal}))
|
||||||
itfConcreteTypeGlobal.SetGlobalConstant(true)
|
itfConcreteTypeGlobal.SetGlobalConstant(true)
|
||||||
itfConcreteTypeGlobal.SetLinkage(llvm.PrivateLinkage)
|
itfConcreteTypeGlobal.SetLinkage(llvm.PrivateLinkage)
|
||||||
}
|
}
|
||||||
itfTypeCode := c.builder.CreatePtrToInt(itfConcreteTypeGlobal, c.uintptrType, "")
|
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, itfTypeCode, 0, "")
|
||||||
itf = c.builder.CreateInsertValue(itf, itfValue, 1, "")
|
itf = c.builder.CreateInsertValue(itf, itfValue, 1, "")
|
||||||
return itf
|
return itf
|
||||||
|
@ -48,7 +48,7 @@ func (c *Compiler) getTypeCode(typ types.Type) llvm.Value {
|
||||||
globalName := "type:" + getTypeCodeName(typ)
|
globalName := "type:" + getTypeCodeName(typ)
|
||||||
global := c.mod.NamedGlobal(globalName)
|
global := c.mod.NamedGlobal(globalName)
|
||||||
if global.IsNil() {
|
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)
|
global.SetGlobalConstant(true)
|
||||||
}
|
}
|
||||||
return global
|
return global
|
||||||
|
@ -163,11 +163,11 @@ func (c *Compiler) getTypeMethodSet(typ types.Type) llvm.Value {
|
||||||
ms := c.ir.Program.MethodSets.MethodSet(typ)
|
ms := c.ir.Program.MethodSets.MethodSet(typ)
|
||||||
if ms.Len() == 0 {
|
if ms.Len() == 0 {
|
||||||
// no methods, so can leave that one out
|
// 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())
|
methods := make([]llvm.Value, ms.Len())
|
||||||
interfaceMethodInfoType := c.mod.GetTypeByName("runtime.interfaceMethodInfo")
|
interfaceMethodInfoType := c.getLLVMRuntimeType("interfaceMethodInfo")
|
||||||
for i := 0; i < ms.Len(); i++ {
|
for i := 0; i < ms.Len(); i++ {
|
||||||
method := ms.At(i)
|
method := ms.At(i)
|
||||||
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
|
signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func))
|
||||||
|
|
16
ir/ir.go
16
ir/ir.go
|
@ -26,7 +26,6 @@ type Program struct {
|
||||||
Globals []*Global
|
Globals []*Global
|
||||||
globalMap map[*ssa.Global]*Global
|
globalMap map[*ssa.Global]*Global
|
||||||
comments map[string]*ast.CommentGroup
|
comments map[string]*ast.CommentGroup
|
||||||
NamedTypes []*NamedType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function or method.
|
// Function or method.
|
||||||
|
@ -50,19 +49,6 @@ type Global struct {
|
||||||
extern bool // go:extern
|
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
|
// Interface type that is at some point used in a type assert (to check whether
|
||||||
// it implements another interface).
|
// it implements another interface).
|
||||||
type Interface struct {
|
type Interface struct {
|
||||||
|
@ -210,8 +196,6 @@ func (p *Program) AddPackage(pkg *ssa.Package) {
|
||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
p.addFunction(member)
|
p.addFunction(member)
|
||||||
case *ssa.Type:
|
case *ssa.Type:
|
||||||
t := &NamedType{Type: member}
|
|
||||||
p.NamedTypes = append(p.NamedTypes, t)
|
|
||||||
methods := getAllMethods(pkg.Prog, member.Type())
|
methods := getAllMethods(pkg.Prog, member.Type())
|
||||||
if !types.IsInterface(member.Type()) {
|
if !types.IsInterface(member.Type()) {
|
||||||
// named type
|
// named type
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче