Browse Source

compiler: do not return an error from getLLVMType

This commit replaces "unknown type" errors in getLLVMType with panics.

The main reason this is done is that it simplifies the code *a lot*.
Many `if err != nil` lines were there just because of type information.
Additionally, simply panicking is probably a better approach as the only
way this error can be produced is either with big new language features
or a serious compiler bug. Panicking is probably a better way to handle
this error anyway.
pull/318/head
Ayke van Laethem 6 years ago
committed by Ron Evans
parent
commit
c25fe609a9
  1. 20
      compiler/channel.go
  2. 274
      compiler/compiler.go
  3. 18
      compiler/defer.go
  4. 53
      compiler/func.go
  5. 24
      compiler/interface.go
  6. 5
      compiler/map.go

20
compiler/channel.go

@ -12,10 +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) {
valueType, err := c.getLLVMType(expr.Type().(*types.Chan).Elem()) valueType := c.getLLVMType(expr.Type().(*types.Chan).Elem())
if err != nil {
return llvm.Value{}, err
}
if c.targetData.TypeAllocSize(valueType) > c.targetData.TypeAllocSize(c.intType) { if c.targetData.TypeAllocSize(valueType) > c.targetData.TypeAllocSize(c.intType) {
// Values bigger than int overflow the data part of the coroutine. // Values bigger than int overflow the data part of the coroutine.
// TODO: make the coroutine data part big enough to hold these bigger // TODO: make the coroutine data part big enough to hold these bigger
@ -33,10 +30,7 @@ func (c *Compiler) emitMakeChan(expr *ssa.MakeChan) (llvm.Value, error) {
// emitChanSend emits a pseudo chan send operation. It is lowered to the actual // emitChanSend emits a pseudo chan send operation. It is lowered to the actual
// channel send operation during goroutine lowering. // channel send operation during goroutine lowering.
func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) error { func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) error {
valueType, err := c.getLLVMType(instr.Chan.Type().(*types.Chan).Elem()) valueType := c.getLLVMType(instr.Chan.Type().(*types.Chan).Elem())
if err != nil {
return err
}
ch, err := c.parseExpr(frame, instr.Chan) ch, err := c.parseExpr(frame, instr.Chan)
if err != nil { if err != nil {
return err return err
@ -56,10 +50,7 @@ func (c *Compiler) emitChanSend(frame *Frame, instr *ssa.Send) error {
// emitChanRecv emits a pseudo chan receive operation. It is lowered to the // emitChanRecv emits a pseudo chan receive operation. It is lowered to the
// actual channel receive operation during goroutine lowering. // actual channel receive operation during goroutine lowering.
func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) { func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) {
valueType, err := c.getLLVMType(unop.X.Type().(*types.Chan).Elem()) valueType := c.getLLVMType(unop.X.Type().(*types.Chan).Elem())
if err != nil {
return llvm.Value{}, err
}
valueSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(valueType), false) valueSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(valueType), false)
ch, err := c.parseExpr(frame, unop.X) ch, err := c.parseExpr(frame, unop.X)
if err != nil { if err != nil {
@ -83,11 +74,8 @@ func (c *Compiler) emitChanRecv(frame *Frame, unop *ssa.UnOp) (llvm.Value, error
// emitChanClose closes the given channel. // emitChanClose closes the given channel.
func (c *Compiler) emitChanClose(frame *Frame, param ssa.Value) error { func (c *Compiler) emitChanClose(frame *Frame, param ssa.Value) error {
valueType, err := c.getLLVMType(param.Type().(*types.Chan).Elem()) valueType := c.getLLVMType(param.Type().(*types.Chan).Elem())
valueSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(valueType), false) valueSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(valueType), false)
if err != nil {
return err
}
ch, err := c.parseExpr(frame, param) ch, err := c.parseExpr(frame, param)
if err != nil { if err != nil {
return err return err

274
compiler/compiler.go

@ -274,10 +274,7 @@ func (c *Compiler) Compile(mainPath string) error {
for _, t := range c.ir.NamedTypes { for _, t := range c.ir.NamedTypes {
if named, ok := t.Type.Type().(*types.Named); ok { if named, ok := t.Type.Type().(*types.Named); ok {
if st, ok := named.Underlying().(*types.Struct); ok { if st, ok := named.Underlying().(*types.Struct); ok {
llvmType, err := c.getLLVMType(st) llvmType := c.getLLVMType(st)
if err != nil {
return err
}
t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false) t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false)
} }
} }
@ -286,10 +283,7 @@ func (c *Compiler) Compile(mainPath string) error {
// 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()
llvmType, err := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
if err != nil {
return err
}
global := c.mod.NamedGlobal(g.LinkName()) global := c.mod.NamedGlobal(g.LinkName())
if global.IsNil() { if global.IsNil() {
global = llvm.AddGlobal(c.mod, llvmType, g.LinkName()) global = llvm.AddGlobal(c.mod, llvmType, g.LinkName())
@ -303,11 +297,7 @@ func (c *Compiler) Compile(mainPath string) error {
// Declare all functions. // Declare all functions.
for _, f := range c.ir.Functions { for _, f := range c.ir.Functions {
frame, err := c.parseFuncDecl(f) frames = append(frames, c.parseFuncDecl(f))
if err != nil {
return err
}
frames = append(frames, frame)
} }
// Add definitions to declarations. // Add definitions to declarations.
@ -330,10 +320,7 @@ func (c *Compiler) Compile(mainPath string) error {
// Define the already declared functions that wrap methods for use in // Define the already declared functions that wrap methods for use in
// interfaces. // interfaces.
for _, state := range c.interfaceInvokeWrappers { for _, state := range c.interfaceInvokeWrappers {
err = c.createInterfaceInvokeWrapper(state) c.createInterfaceInvokeWrapper(state)
if err != nil {
return err
}
} }
// After all packages are imported, add a synthetic initializer function // After all packages are imported, add a synthetic initializer function
@ -342,10 +329,7 @@ func (c *Compiler) Compile(mainPath string) error {
initFn.LLVMFn.SetLinkage(llvm.InternalLinkage) initFn.LLVMFn.SetLinkage(llvm.InternalLinkage)
initFn.LLVMFn.SetUnnamedAddr(true) initFn.LLVMFn.SetUnnamedAddr(true)
if c.Debug { if c.Debug {
difunc, err := c.attachDebugInfo(initFn) difunc := c.attachDebugInfo(initFn)
if err != nil {
return err
}
pos := c.ir.Program.Fset.Position(initFn.Pos()) pos := c.ir.Program.Fset.Position(initFn.Pos())
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{}) c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
} }
@ -411,87 +395,74 @@ func (c *Compiler) Compile(mainPath string) error {
return nil return nil
} }
func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { func (c *Compiler) getLLVMType(goType types.Type) llvm.Type {
switch typ := goType.(type) { switch typ := goType.(type) {
case *types.Array: case *types.Array:
elemType, err := c.getLLVMType(typ.Elem()) elemType := c.getLLVMType(typ.Elem())
if err != nil { return llvm.ArrayType(elemType, int(typ.Len()))
return llvm.Type{}, err
}
return llvm.ArrayType(elemType, int(typ.Len())), nil
case *types.Basic: case *types.Basic:
switch typ.Kind() { switch typ.Kind() {
case types.Bool, types.UntypedBool: case types.Bool, types.UntypedBool:
return c.ctx.Int1Type(), nil return c.ctx.Int1Type()
case types.Int8, types.Uint8: case types.Int8, types.Uint8:
return c.ctx.Int8Type(), nil return c.ctx.Int8Type()
case types.Int16, types.Uint16: case types.Int16, types.Uint16:
return c.ctx.Int16Type(), nil return c.ctx.Int16Type()
case types.Int32, types.Uint32: case types.Int32, types.Uint32:
return c.ctx.Int32Type(), nil return c.ctx.Int32Type()
case types.Int, types.Uint: case types.Int, types.Uint:
return c.intType, nil return c.intType
case types.Int64, types.Uint64: case types.Int64, types.Uint64:
return c.ctx.Int64Type(), nil return c.ctx.Int64Type()
case types.Float32: case types.Float32:
return c.ctx.FloatType(), nil return c.ctx.FloatType()
case types.Float64: case types.Float64:
return c.ctx.DoubleType(), nil return c.ctx.DoubleType()
case types.Complex64: case types.Complex64:
return c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false), nil return c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)
case types.Complex128: case types.Complex128:
return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false), nil 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"), nil return c.mod.GetTypeByName("runtime._string")
case types.Uintptr: case types.Uintptr:
return c.uintptrType, nil return c.uintptrType
case types.UnsafePointer: case types.UnsafePointer:
return c.i8ptrType, nil return c.i8ptrType
default: default:
return llvm.Type{}, errors.New("todo: 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), nil return llvm.PointerType(c.mod.GetTypeByName("runtime.channel"), 0)
case *types.Interface: case *types.Interface:
return c.mod.GetTypeByName("runtime._interface"), nil return c.mod.GetTypeByName("runtime._interface")
case *types.Map: case *types.Map:
return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0), nil return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0)
case *types.Named: case *types.Named:
if _, ok := typ.Underlying().(*types.Struct); ok { if _, ok := typ.Underlying().(*types.Struct); ok {
llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name()) llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
if llvmType.IsNil() { if llvmType.IsNil() {
return llvm.Type{}, errors.New("type not found: " + typ.Obj().Pkg().Path() + "." + typ.Obj().Name()) panic("underlying type not found: " + typ.Obj().Pkg().Path() + "." + typ.Obj().Name())
} }
return llvmType, nil return llvmType
} }
return c.getLLVMType(typ.Underlying()) return c.getLLVMType(typ.Underlying())
case *types.Pointer: case *types.Pointer:
ptrTo, err := c.getLLVMType(typ.Elem()) ptrTo := c.getLLVMType(typ.Elem())
if err != nil { return llvm.PointerType(ptrTo, 0)
return llvm.Type{}, err
}
return llvm.PointerType(ptrTo, 0), nil
case *types.Signature: // function value case *types.Signature: // function value
return c.getFuncType(typ) return c.getFuncType(typ)
case *types.Slice: case *types.Slice:
elemType, err := c.getLLVMType(typ.Elem()) elemType := c.getLLVMType(typ.Elem())
if err != nil {
return llvm.Type{}, err
}
members := []llvm.Type{ members := []llvm.Type{
llvm.PointerType(elemType, 0), llvm.PointerType(elemType, 0),
c.uintptrType, // len c.uintptrType, // len
c.uintptrType, // cap c.uintptrType, // cap
} }
return c.ctx.StructType(members, false), nil return c.ctx.StructType(members, false)
case *types.Struct: case *types.Struct:
members := make([]llvm.Type, typ.NumFields()) members := make([]llvm.Type, typ.NumFields())
for i := 0; i < typ.NumFields(); i++ { for i := 0; i < typ.NumFields(); i++ {
member, err := c.getLLVMType(typ.Field(i).Type()) members[i] = c.getLLVMType(typ.Field(i).Type())
if err != nil {
return llvm.Type{}, err
}
members[i] = member
} }
if len(members) > 2 && typ.Field(0).Name() == "C union" { if len(members) > 2 && typ.Field(0).Name() == "C union" {
// Not a normal struct but a C union emitted by cgo. // Not a normal struct but a C union emitted by cgo.
@ -520,19 +491,15 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
members = append(members, llvm.ArrayType(c.ctx.Int8Type(), int(maxSize-mainTypeSize))) members = append(members, llvm.ArrayType(c.ctx.Int8Type(), int(maxSize-mainTypeSize)))
} }
} }
return c.ctx.StructType(members, false), nil return c.ctx.StructType(members, false)
case *types.Tuple: case *types.Tuple:
members := make([]llvm.Type, typ.Len()) members := make([]llvm.Type, typ.Len())
for i := 0; i < typ.Len(); i++ { for i := 0; i < typ.Len(); i++ {
member, err := c.getLLVMType(typ.At(i).Type()) members[i] = c.getLLVMType(typ.At(i).Type())
if err != nil {
return llvm.Type{}, err
}
members[i] = member
} }
return c.ctx.StructType(members, false), nil return c.ctx.StructType(members, false)
default: default:
return llvm.Type{}, errors.New("todo: unknown type: " + goType.String()) panic("unknown type: " + goType.String())
} }
} }
@ -584,15 +551,12 @@ func isPointer(typ types.Type) bool {
} }
// Get the DWARF type for this Go type. // Get the DWARF type for this Go type.
func (c *Compiler) getDIType(typ types.Type) (llvm.Metadata, error) { func (c *Compiler) getDIType(typ types.Type) llvm.Metadata {
name := typ.String() name := typ.String()
if dityp, ok := c.ditypes[name]; ok { if dityp, ok := c.ditypes[name]; ok {
return dityp, nil return dityp
} else { } else {
llvmType, err := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
if err != nil {
return llvm.Metadata{}, err
}
sizeInBytes := c.targetData.TypeAllocSize(llvmType) sizeInBytes := c.targetData.TypeAllocSize(llvmType)
var encoding llvm.DwarfTypeEncoding var encoding llvm.DwarfTypeEncoding
switch typ := typ.(type) { switch typ := typ.(type) {
@ -620,11 +584,11 @@ func (c *Compiler) getDIType(typ types.Type) (llvm.Metadata, error) {
Encoding: encoding, Encoding: encoding,
}) })
c.ditypes[name] = dityp c.ditypes[name] = dityp
return dityp, nil return dityp
} }
} }
func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) { func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame {
frame := &Frame{ frame := &Frame{
fn: f, fn: f,
locals: make(map[ssa.Value]llvm.Value), locals: make(map[ssa.Value]llvm.Value),
@ -636,29 +600,18 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) {
if f.Signature.Results() == nil { if f.Signature.Results() == nil {
retType = c.ctx.VoidType() retType = c.ctx.VoidType()
} else if f.Signature.Results().Len() == 1 { } else if f.Signature.Results().Len() == 1 {
var err error retType = c.getLLVMType(f.Signature.Results().At(0).Type())
retType, err = c.getLLVMType(f.Signature.Results().At(0).Type())
if err != nil {
return nil, err
}
} else { } else {
results := make([]llvm.Type, 0, f.Signature.Results().Len()) results := make([]llvm.Type, 0, f.Signature.Results().Len())
for i := 0; i < f.Signature.Results().Len(); i++ { for i := 0; i < f.Signature.Results().Len(); i++ {
typ, err := c.getLLVMType(f.Signature.Results().At(i).Type()) results = append(results, c.getLLVMType(f.Signature.Results().At(i).Type()))
if err != nil {
return nil, err
}
results = append(results, typ)
} }
retType = c.ctx.StructType(results, false) retType = c.ctx.StructType(results, false)
} }
var paramTypes []llvm.Type var paramTypes []llvm.Type
for _, param := range f.Params { for _, param := range f.Params {
paramType, err := c.getLLVMType(param.Type()) paramType := c.getLLVMType(param.Type())
if err != nil {
return nil, err
}
paramTypeFragments := c.expandFormalParamType(paramType) paramTypeFragments := c.expandFormalParamType(paramType)
paramTypes = append(paramTypes, paramTypeFragments...) paramTypes = append(paramTypes, paramTypeFragments...)
} }
@ -678,15 +631,15 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) {
frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType) frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType)
} }
return frame, nil return frame
} }
func (c *Compiler) attachDebugInfo(f *ir.Function) (llvm.Metadata, error) { func (c *Compiler) attachDebugInfo(f *ir.Function) llvm.Metadata {
pos := c.ir.Program.Fset.Position(f.Syntax().Pos()) pos := c.ir.Program.Fset.Position(f.Syntax().Pos())
return c.attachDebugInfoRaw(f, f.LLVMFn, "", pos.Filename, pos.Line) return c.attachDebugInfoRaw(f, f.LLVMFn, "", pos.Filename, pos.Line)
} }
func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, filename string, line int) (llvm.Metadata, error) { func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, filename string, line int) llvm.Metadata {
if _, ok := c.difiles[filename]; !ok { if _, ok := c.difiles[filename]; !ok {
dir, file := filepath.Split(filename) dir, file := filepath.Split(filename)
if dir != "" { if dir != "" {
@ -698,11 +651,7 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix,
// Debug info for this function. // Debug info for this function.
diparams := make([]llvm.Metadata, 0, len(f.Params)) diparams := make([]llvm.Metadata, 0, len(f.Params))
for _, param := range f.Params { for _, param := range f.Params {
ditype, err := c.getDIType(param.Type()) diparams = append(diparams, c.getDIType(param.Type()))
if err != nil {
return llvm.Metadata{}, err
}
diparams = append(diparams, ditype)
} }
diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{ diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{
File: c.difiles[filename], File: c.difiles[filename],
@ -722,7 +671,7 @@ func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix,
Optimized: true, Optimized: true,
}) })
llvmFn.SetSubprogram(difunc) llvmFn.SetSubprogram(difunc)
return difunc, nil return difunc
} }
func (c *Compiler) parseFunc(frame *Frame) error { func (c *Compiler) parseFunc(frame *Frame) error {
@ -742,18 +691,10 @@ func (c *Compiler) parseFunc(frame *Frame) error {
if frame.fn.Synthetic == "package initializer" { if frame.fn.Synthetic == "package initializer" {
// Package initializers have no debug info. Create some fake debug // Package initializers have no debug info. Create some fake debug
// info to at least have *something*. // info to at least have *something*.
difunc, err := c.attachDebugInfoRaw(frame.fn, frame.fn.LLVMFn, "", "", 0) frame.difunc = c.attachDebugInfoRaw(frame.fn, frame.fn.LLVMFn, "", "", 0)
if err != nil {
return err
}
frame.difunc = difunc
} else if frame.fn.Syntax() != nil { } else if frame.fn.Syntax() != nil {
// Create debug info file if needed. // Create debug info file if needed.
difunc, err := c.attachDebugInfo(frame.fn) frame.difunc = c.attachDebugInfo(frame.fn)
if err != nil {
return err
}
frame.difunc = difunc
} }
pos := c.ir.Program.Fset.Position(frame.fn.Pos()) pos := c.ir.Program.Fset.Position(frame.fn.Pos())
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{}) c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
@ -771,10 +712,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
// Load function parameters // Load function parameters
llvmParamIndex := 0 llvmParamIndex := 0
for i, param := range frame.fn.Params { for i, param := range frame.fn.Params {
llvmType, err := c.getLLVMType(param.Type()) llvmType := c.getLLVMType(param.Type())
if err != nil {
return err
}
fields := make([]llvm.Value, 0, 1) fields := make([]llvm.Value, 0, 1)
for range c.expandFormalParamType(llvmType) { for range c.expandFormalParamType(llvmType) {
fields = append(fields, frame.fn.LLVMFn.Param(llvmParamIndex)) fields = append(fields, frame.fn.LLVMFn.Param(llvmParamIndex))
@ -785,15 +723,11 @@ func (c *Compiler) parseFunc(frame *Frame) error {
// Add debug information to this parameter (if available) // Add debug information to this parameter (if available)
if c.Debug && frame.fn.Syntax() != nil { if c.Debug && frame.fn.Syntax() != nil {
pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos()) pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos())
dityp, err := c.getDIType(param.Type())
if err != nil {
return err
}
c.dibuilder.CreateParameterVariable(frame.difunc, llvm.DIParameterVariable{ c.dibuilder.CreateParameterVariable(frame.difunc, llvm.DIParameterVariable{
Name: param.Name(), Name: param.Name(),
File: c.difiles[pos.Filename], File: c.difiles[pos.Filename],
Line: pos.Line, Line: pos.Line,
Type: dityp, Type: c.getDIType(param.Type()),
AlwaysPreserve: true, AlwaysPreserve: true,
ArgNo: i + 1, ArgNo: i + 1,
}) })
@ -814,11 +748,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
// Determine the context type. It's a struct containing all variables. // Determine the context type. It's a struct containing all variables.
freeVarTypes := make([]llvm.Type, 0, len(frame.fn.FreeVars)) freeVarTypes := make([]llvm.Type, 0, len(frame.fn.FreeVars))
for _, freeVar := range frame.fn.FreeVars { for _, freeVar := range frame.fn.FreeVars {
typ, err := c.getLLVMType(freeVar.Type()) freeVarTypes = append(freeVarTypes, c.getLLVMType(freeVar.Type()))
if err != nil {
return err
}
freeVarTypes = append(freeVarTypes, typ)
} }
contextType := c.ctx.StructType(freeVarTypes, false) contextType := c.ctx.StructType(freeVarTypes, false)
@ -1346,10 +1276,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
switch expr := expr.(type) { switch expr := expr.(type) {
case *ssa.Alloc: case *ssa.Alloc:
typ, err := c.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem()) typ := c.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
if err != nil {
return llvm.Value{}, err
}
var buf llvm.Value var buf llvm.Value
if expr.Heap { if expr.Heap {
size := c.targetData.TypeAllocSize(typ) size := c.targetData.TypeAllocSize(typ)
@ -1400,10 +1327,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
if err != nil { if err != nil {
return llvm.Value{}, err return llvm.Value{}, err
} }
llvmType, err := c.getLLVMType(expr.Type()) llvmType := c.getLLVMType(expr.Type())
if err != nil {
return llvm.Value{}, err
}
if x.Type() == llvmType { if x.Type() == llvmType {
// Different Go type but same LLVM type (for example, named int). // Different Go type but same LLVM type (for example, named int).
// This is the common case. // This is the common case.
@ -1452,10 +1376,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
// Extract a field from a CGo union. // Extract a field from a CGo union.
// This could be done directly, but as this is a very infrequent // This could be done directly, but as this is a very infrequent
// operation it's much easier to bitcast it through an alloca. // operation it's much easier to bitcast it through an alloca.
resultType, err := c.getLLVMType(expr.Type()) resultType := c.getLLVMType(expr.Type())
if err != nil {
return llvm.Value{}, err
}
alloca := c.builder.CreateAlloca(value.Type(), "") alloca := c.builder.CreateAlloca(value.Type(), "")
c.builder.CreateStore(value, alloca) c.builder.CreateStore(value, alloca)
bitcast := c.builder.CreateBitCast(alloca, llvm.PointerType(resultType, 0), "") bitcast := c.builder.CreateBitCast(alloca, llvm.PointerType(resultType, 0), "")
@ -1477,10 +1398,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
// This is not a regular struct but actually an union. // This is not a regular struct but actually an union.
// That simplifies things, as we can just bitcast the pointer to the // That simplifies things, as we can just bitcast the pointer to the
// right type. // right type.
ptrType, err := c.getLLVMType(expr.Type()) ptrType := c.getLLVMType(expr.Type())
if err != nil {
return llvm.Value{}, nil
}
return c.builder.CreateBitCast(val, ptrType, ""), nil return c.builder.CreateBitCast(val, ptrType, ""), nil
} else { } else {
// Do a GEP on the pointer to get the field address. // Do a GEP on the pointer to get the field address.
@ -1495,7 +1413,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
if fn.IsExported() { if fn.IsExported() {
return llvm.Value{}, c.makeError(expr.Pos(), "cannot use an exported function as value") return llvm.Value{}, c.makeError(expr.Pos(), "cannot use an exported function as value")
} }
return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature) return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature), nil
case *ssa.Global: case *ssa.Global:
value := c.ir.GetGlobal(expr).LLVMGlobal value := c.ir.GetGlobal(expr).LLVMGlobal
if value.IsNil() { if value.IsNil() {
@ -1620,14 +1538,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return c.parseMakeInterface(val, expr.X.Type(), expr.Pos()) return c.parseMakeInterface(val, expr.X.Type(), expr.Pos())
case *ssa.MakeMap: case *ssa.MakeMap:
mapType := expr.Type().Underlying().(*types.Map) mapType := expr.Type().Underlying().(*types.Map)
llvmKeyType, err := c.getLLVMType(mapType.Key().Underlying()) llvmKeyType := c.getLLVMType(mapType.Key().Underlying())
if err != nil { llvmValueType := c.getLLVMType(mapType.Elem().Underlying())
return llvm.Value{}, err
}
llvmValueType, err := c.getLLVMType(mapType.Elem().Underlying())
if err != nil {
return llvm.Value{}, err
}
keySize := c.targetData.TypeAllocSize(llvmKeyType) keySize := c.targetData.TypeAllocSize(llvmKeyType)
valueSize := c.targetData.TypeAllocSize(llvmValueType) valueSize := c.targetData.TypeAllocSize(llvmValueType)
llvmKeySize := llvm.ConstInt(c.ctx.Int8Type(), keySize, false) llvmKeySize := llvm.ConstInt(c.ctx.Int8Type(), keySize, false)
@ -1644,10 +1556,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return llvm.Value{}, nil return llvm.Value{}, nil
} }
sliceType := expr.Type().Underlying().(*types.Slice) sliceType := expr.Type().Underlying().(*types.Slice)
llvmElemType, err := c.getLLVMType(sliceType.Elem()) llvmElemType := c.getLLVMType(sliceType.Elem())
if err != nil {
return llvm.Value{}, nil
}
elemSize := c.targetData.TypeAllocSize(llvmElemType) elemSize := c.targetData.TypeAllocSize(llvmElemType)
elemSizeValue := llvm.ConstInt(c.uintptrType, elemSize, false) elemSizeValue := llvm.ConstInt(c.uintptrType, elemSize, false)
@ -1707,14 +1616,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
if expr.IsString { if expr.IsString {
return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
} else { // map } else { // map
llvmKeyType, err := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key()) llvmKeyType := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key())
if err != nil { llvmValueType := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Elem())
return llvm.Value{}, err
}
llvmValueType, err := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Elem())
if err != nil {
return llvm.Value{}, err
}
mapKeyAlloca := c.builder.CreateAlloca(llvmKeyType, "range.key") mapKeyAlloca := c.builder.CreateAlloca(llvmKeyType, "range.key")
mapKeyPtr := c.builder.CreateBitCast(mapKeyAlloca, c.i8ptrType, "range.keyptr") mapKeyPtr := c.builder.CreateBitCast(mapKeyAlloca, c.i8ptrType, "range.keyptr")
@ -1729,11 +1632,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return tuple, nil return tuple, nil
} }
case *ssa.Phi: case *ssa.Phi:
t, err := c.getLLVMType(expr.Type()) phi := c.builder.CreatePHI(c.getLLVMType(expr.Type()), "")
if err != nil {
return llvm.Value{}, err
}
phi := c.builder.CreatePHI(t, "")
frame.phis = append(frame.phis, Phi{expr, phi}) frame.phis = append(frame.phis, Phi{expr, phi})
return phi, nil return phi, nil
case *ssa.Range: case *ssa.Range:
@ -1752,10 +1651,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
case *ssa.Select: case *ssa.Select:
if len(expr.States) == 0 { if len(expr.States) == 0 {
// Shortcuts for some simple selects. // Shortcuts for some simple selects.
llvmType, err := c.getLLVMType(expr.Type()) llvmType := c.getLLVMType(expr.Type())
if err != nil {
return llvm.Value{}, err
}
if expr.Blocking { if expr.Blocking {
// Blocks forever: // Blocks forever:
// select {} // select {}
@ -2225,10 +2121,7 @@ func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value, p
func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error) { func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error) {
switch typ := expr.Type().Underlying().(type) { switch typ := expr.Type().Underlying().(type) {
case *types.Basic: case *types.Basic:
llvmType, err := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
if err != nil {
return llvm.Value{}, err
}
if typ.Info()&types.IsBoolean != 0 { if typ.Info()&types.IsBoolean != 0 {
b := constant.BoolVal(expr.Value) b := constant.BoolVal(expr.Value)
n := uint64(0) n := uint64(0)
@ -2294,20 +2187,12 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String()) return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String())
} }
case *types.Chan: case *types.Chan:
sig, err := c.getLLVMType(expr.Type()) return c.getZeroValue(c.getLLVMType(expr.Type())), nil
if err != nil {
return llvm.Value{}, err
}
return c.getZeroValue(sig), nil
case *types.Signature: case *types.Signature:
if expr.Value != nil { if expr.Value != nil {
return llvm.Value{}, errors.New("non-nil signature constant") return llvm.Value{}, errors.New("non-nil signature constant")
} }
sig, err := c.getLLVMType(expr.Type()) return c.getZeroValue(c.getLLVMType(expr.Type())), nil
if err != nil {
return llvm.Value{}, err
}
return c.getZeroValue(sig), nil
case *types.Interface: case *types.Interface:
if expr.Value != nil { if expr.Value != nil {
return llvm.Value{}, errors.New("non-nil interface constant") return llvm.Value{}, errors.New("non-nil interface constant")
@ -2323,19 +2208,12 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
if expr.Value != nil { if expr.Value != nil {
return llvm.Value{}, errors.New("non-nil pointer constant") return llvm.Value{}, errors.New("non-nil pointer constant")
} }
llvmType, err := c.getLLVMType(typ) return llvm.ConstPointerNull(c.getLLVMType(typ)), nil
if err != nil {
return llvm.Value{}, err
}
return llvm.ConstPointerNull(llvmType), nil
case *types.Slice: case *types.Slice:
if expr.Value != nil { if expr.Value != nil {
return llvm.Value{}, errors.New("non-nil slice constant") return llvm.Value{}, errors.New("non-nil slice constant")
} }
elemType, err := c.getLLVMType(typ.Elem()) elemType := c.getLLVMType(typ.Elem())
if err != nil {
return llvm.Value{}, err
}
llvmPtr := llvm.ConstPointerNull(llvm.PointerType(elemType, 0)) llvmPtr := llvm.ConstPointerNull(llvm.PointerType(elemType, 0))
llvmLen := llvm.ConstInt(c.uintptrType, 0, false) llvmLen := llvm.ConstInt(c.uintptrType, 0, false)
slice := c.ctx.ConstStruct([]llvm.Value{ slice := c.ctx.ConstStruct([]llvm.Value{
@ -2349,10 +2227,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
// I believe this is not allowed by the Go spec. // I believe this is not allowed by the Go spec.
panic("non-nil map constant") panic("non-nil map constant")
} }
llvmType, err := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
if err != nil {
return llvm.Value{}, err
}
return c.getZeroValue(llvmType), nil return c.getZeroValue(llvmType), nil
default: default:
return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String()) return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String())
@ -2361,10 +2236,7 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) { func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) {
llvmTypeFrom := value.Type() llvmTypeFrom := value.Type()
llvmTypeTo, err := c.getLLVMType(typeTo) llvmTypeTo := c.getLLVMType(typeTo)
if err != nil {
return llvm.Value{}, err
}
// Conversion between unsafe.Pointer and uintptr. // Conversion between unsafe.Pointer and uintptr.
isPtrFrom := isPointer(typeFrom.Underlying()) isPtrFrom := isPointer(typeFrom.Underlying())

18
compiler/defer.go

@ -217,11 +217,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) error {
// 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.mod.GetTypeByName("runtime._defer"), 0), c.i8ptrType}
for _, arg := range callback.Args { for _, arg := range callback.Args {
llvmType, err := c.getLLVMType(arg.Type()) valueTypes = append(valueTypes, c.getLLVMType(arg.Type()))
if err != nil {
return err
}
valueTypes = append(valueTypes, llvmType)
} }
deferFrameType := c.ctx.StructType(valueTypes, false) deferFrameType := c.ctx.StructType(valueTypes, false)
deferFramePtr := c.builder.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame") deferFramePtr := c.builder.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
@ -255,11 +251,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) error {
// 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.mod.GetTypeByName("runtime._defer"), 0)}
for _, param := range callback.Params { for _, param := range callback.Params {
llvmType, err := c.getLLVMType(param.Type()) valueTypes = append(valueTypes, c.getLLVMType(param.Type()))
if err != nil {
return err
}
valueTypes = append(valueTypes, llvmType)
} }
deferFrameType := c.ctx.StructType(valueTypes, false) deferFrameType := c.ctx.StructType(valueTypes, false)
deferFramePtr := c.builder.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame") deferFramePtr := c.builder.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
@ -289,11 +281,7 @@ func (c *Compiler) emitRunDefers(frame *Frame) error {
valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)} valueTypes := []llvm.Type{c.uintptrType, llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)}
params := fn.Signature.Params() params := fn.Signature.Params()
for i := 0; i < params.Len(); i++ { for i := 0; i < params.Len(); i++ {
llvmType, err := c.getLLVMType(params.At(i).Type()) valueTypes = append(valueTypes, c.getLLVMType(params.At(i).Type()))
if err != nil {
return err
}
valueTypes = append(valueTypes, llvmType)
} }
valueTypes = append(valueTypes, c.i8ptrType) // closure valueTypes = append(valueTypes, c.i8ptrType) // closure
deferFrameType := c.ctx.StructType(valueTypes, false) deferFrameType := c.ctx.StructType(valueTypes, false)

53
compiler/func.go

@ -41,7 +41,7 @@ func (c *Compiler) funcImplementation() funcValueImplementation {
// createFuncValue creates a function value from a raw function pointer with no // createFuncValue creates a function value from a raw function pointer with no
// context. // context.
func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) (llvm.Value, error) { func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
var funcValueScalar llvm.Value var funcValueScalar llvm.Value
switch c.funcImplementation() { switch c.funcImplementation() {
case funcValueDoubleword: case funcValueDoubleword:
@ -66,14 +66,11 @@ func (c *Compiler) createFuncValue(funcPtr, context llvm.Value, sig *types.Signa
default: default:
panic("unimplemented func value variant") panic("unimplemented func value variant")
} }
funcValueType, err := c.getFuncType(sig) funcValueType := c.getFuncType(sig)
if err != nil {
return llvm.Value{}, err
}
funcValue := llvm.Undef(funcValueType) funcValue := llvm.Undef(funcValueType)
funcValue = c.builder.CreateInsertValue(funcValue, context, 0, "") funcValue = c.builder.CreateInsertValue(funcValue, context, 0, "")
funcValue = c.builder.CreateInsertValue(funcValue, funcValueScalar, 1, "") funcValue = c.builder.CreateInsertValue(funcValue, funcValueScalar, 1, "")
return funcValue, nil return funcValue
} }
// getFuncSignature returns a global for identification of a particular function // getFuncSignature returns a global for identification of a particular function
@ -112,10 +109,7 @@ func (c *Compiler) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (
case funcValueDoubleword: case funcValueDoubleword:
funcPtr = c.builder.CreateExtractValue(funcValue, 1, "") funcPtr = c.builder.CreateExtractValue(funcValue, 1, "")
case funcValueSwitch: case funcValueSwitch:
llvmSig, err := c.getRawFuncType(sig) llvmSig := c.getRawFuncType(sig)
if err != nil {
return llvm.Value{}, llvm.Value{}, err
}
sigGlobal := c.getFuncSignature(sig) sigGlobal := c.getFuncSignature(sig)
funcPtr = c.createRuntimeCall("getFuncPtr", []llvm.Value{funcValue, sigGlobal}, "") funcPtr = c.createRuntimeCall("getFuncPtr", []llvm.Value{funcValue, sigGlobal}, "")
funcPtr = c.builder.CreateIntToPtr(funcPtr, llvmSig, "") funcPtr = c.builder.CreateIntToPtr(funcPtr, llvmSig, "")
@ -126,25 +120,21 @@ func (c *Compiler) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (
} }
// getFuncType returns the type of a func value given a signature. // getFuncType returns the type of a func value given a signature.
func (c *Compiler) getFuncType(typ *types.Signature) (llvm.Type, error) { func (c *Compiler) getFuncType(typ *types.Signature) llvm.Type {
switch c.funcImplementation() { switch c.funcImplementation() {
case funcValueDoubleword: case funcValueDoubleword:
rawPtr, err := c.getRawFuncType(typ) rawPtr := c.getRawFuncType(typ)
if err != nil { return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false)
return llvm.Type{}, err
}
return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false), nil
case funcValueSwitch: case funcValueSwitch:
return c.mod.GetTypeByName("runtime.funcValue"), nil return c.mod.GetTypeByName("runtime.funcValue")
default: default:
panic("unimplemented func value variant") panic("unimplemented func value variant")
} }
} }
// getRawFuncType returns a LLVM function pointer type for a given signature. // getRawFuncType returns a LLVM function pointer type for a given signature.
func (c *Compiler) getRawFuncType(typ *types.Signature) (llvm.Type, error) { func (c *Compiler) getRawFuncType(typ *types.Signature) llvm.Type {
// Get the return type. // Get the return type.
var err error
var returnType llvm.Type var returnType llvm.Type
switch typ.Results().Len() { switch typ.Results().Len() {
case 0: case 0:
@ -152,21 +142,14 @@ func (c *Compiler) getRawFuncType(typ *types.Signature) (llvm.Type, error) {
returnType = c.ctx.VoidType() returnType = c.ctx.VoidType()
case 1: case 1:
// Just one return value. // Just one return value.
returnType, err = c.getLLVMType(typ.Results().At(0).Type()) returnType = c.getLLVMType(typ.Results().At(0).Type())
if err != nil {
return llvm.Type{}, err
}
default: default:
// Multiple return values. Put them together in a struct. // Multiple return values. Put them together in a struct.
// This appears to be the common way to handle multiple return values in // This appears to be the common way to handle multiple return values in
// LLVM. // LLVM.
members := make([]llvm.Type, typ.Results().Len()) members := make([]llvm.Type, typ.Results().Len())
for i := 0; i < typ.Results().Len(); i++ { for i := 0; i < typ.Results().Len(); i++ {
returnType, err := c.getLLVMType(typ.Results().At(i).Type()) members[i] = c.getLLVMType(typ.Results().At(i).Type())
if err != nil {
return llvm.Type{}, err
}
members[i] = returnType
} }
returnType = c.ctx.StructType(members, false) returnType = c.ctx.StructType(members, false)
} }
@ -174,10 +157,7 @@ func (c *Compiler) getRawFuncType(typ *types.Signature) (llvm.Type, error) {
// Get the parameter types. // Get the parameter types.
var paramTypes []llvm.Type var paramTypes []llvm.Type
if typ.Recv() != nil { if typ.Recv() != nil {
recv, err := c.getLLVMType(typ.Recv().Type()) recv := c.getLLVMType(typ.Recv().Type())
if err != nil {
return llvm.Type{}, err
}
if recv.StructName() == "runtime._interface" { if recv.StructName() == "runtime._interface" {
// This is a call on an interface, not a concrete type. // This is a call on an interface, not a concrete type.
// The receiver is not an interface, but a i8* type. // The receiver is not an interface, but a i8* type.
@ -186,10 +166,7 @@ func (c *Compiler) getRawFuncType(typ *types.Signature) (llvm.Type, error) {
paramTypes = append(paramTypes, c.expandFormalParamType(recv)...) paramTypes = append(paramTypes, c.expandFormalParamType(recv)...)
} }
for i := 0; i < typ.Params().Len(); i++ { for i := 0; i < typ.Params().Len(); i++ {
subType, err := c.getLLVMType(typ.Params().At(i).Type()) subType := c.getLLVMType(typ.Params().At(i).Type())
if err != nil {
return llvm.Type{}, err
}
paramTypes = append(paramTypes, c.expandFormalParamType(subType)...) paramTypes = append(paramTypes, c.expandFormalParamType(subType)...)
} }
// All functions take these parameters at the end. // All functions take these parameters at the end.
@ -197,7 +174,7 @@ func (c *Compiler) getRawFuncType(typ *types.Signature) (llvm.Type, error) {
paramTypes = append(paramTypes, c.i8ptrType) // parent coroutine paramTypes = append(paramTypes, c.i8ptrType) // parent coroutine
// Make a func type out of the signature. // Make a func type out of the signature.
return llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false), c.funcPtrAddrSpace), nil return llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false), c.funcPtrAddrSpace)
} }
// parseMakeClosure makes a function value (with context) from the given // parseMakeClosure makes a function value (with context) from the given
@ -261,5 +238,5 @@ func (c *Compiler) parseMakeClosure(frame *Frame, expr *ssa.MakeClosure) (llvm.V
} }
// Create the closure. // Create the closure.
return c.createFuncValue(f.LLVMFn, context, f.Signature) return c.createFuncValue(f.LLVMFn, context, f.Signature), nil
} }

24
compiler/interface.go

@ -279,10 +279,7 @@ func (c *Compiler) parseTypeAssert(frame *Frame, expr *ssa.TypeAssert) (llvm.Val
if err != nil { if err != nil {
return llvm.Value{}, err return llvm.Value{}, err
} }
assertedType, err := c.getLLVMType(expr.AssertedType) assertedType := c.getLLVMType(expr.AssertedType)
if err != nil {
return llvm.Value{}, err
}
actualTypeNum := c.builder.CreateExtractValue(itf, 0, "interface.type") actualTypeNum := c.builder.CreateExtractValue(itf, 0, "interface.type")
commaOk := llvm.Value{} commaOk := llvm.Value{}
@ -389,10 +386,7 @@ func (c *Compiler) getInvokeCall(frame *Frame, instr *ssa.CallCommon) (llvm.Valu
return llvm.Value{}, nil, err return llvm.Value{}, nil, err
} }
llvmFnType, err := c.getRawFuncType(instr.Method.Type().(*types.Signature)) llvmFnType := c.getRawFuncType(instr.Method.Type().(*types.Signature))
if err != nil {
return llvm.Value{}, nil, err
}
typecode := c.builder.CreateExtractValue(itf, 0, "invoke.typecode") typecode := c.builder.CreateExtractValue(itf, 0, "invoke.typecode")
values := []llvm.Value{ values := []llvm.Value{
@ -443,10 +437,7 @@ func (c *Compiler) getInterfaceInvokeWrapper(f *ir.Function) (llvm.Value, error)
} }
// Get the expanded receiver type. // Get the expanded receiver type.
receiverType, err := c.getLLVMType(f.Params[0].Type()) receiverType := c.getLLVMType(f.Params[0].Type())
if err != nil {
return llvm.Value{}, err
}
expandedReceiverType := c.expandFormalParamType(receiverType) expandedReceiverType := c.expandFormalParamType(receiverType)
// Does this method even need any wrapping? // Does this method even need any wrapping?
@ -473,7 +464,7 @@ func (c *Compiler) getInterfaceInvokeWrapper(f *ir.Function) (llvm.Value, error)
// createInterfaceInvokeWrapper finishes the work of getInterfaceInvokeWrapper, // createInterfaceInvokeWrapper finishes the work of getInterfaceInvokeWrapper,
// see that function for details. // see that function for details.
func (c *Compiler) createInterfaceInvokeWrapper(state interfaceInvokeWrapper) error { func (c *Compiler) createInterfaceInvokeWrapper(state interfaceInvokeWrapper) {
wrapper := state.wrapper wrapper := state.wrapper
fn := state.fn fn := state.fn
receiverType := state.receiverType receiverType := state.receiverType
@ -483,10 +474,7 @@ func (c *Compiler) createInterfaceInvokeWrapper(state interfaceInvokeWrapper) er
// add debug info if needed // add debug info if needed
if c.Debug { if c.Debug {
pos := c.ir.Program.Fset.Position(fn.Pos()) pos := c.ir.Program.Fset.Position(fn.Pos())
difunc, err := c.attachDebugInfoRaw(fn, wrapper, "$invoke", pos.Filename, pos.Line) difunc := c.attachDebugInfoRaw(fn, wrapper, "$invoke", pos.Filename, pos.Line)
if err != nil {
return err
}
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{}) c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{})
} }
@ -524,6 +512,4 @@ func (c *Compiler) createInterfaceInvokeWrapper(state interfaceInvokeWrapper) er
ret := c.builder.CreateCall(fn.LLVMFn, params, "ret") ret := c.builder.CreateCall(fn.LLVMFn, params, "ret")
c.builder.CreateRet(ret) c.builder.CreateRet(ret)
} }
return nil
} }

5
compiler/map.go

@ -10,10 +10,7 @@ import (
) )
func (c *Compiler) emitMapLookup(keyType, valueType types.Type, m, key llvm.Value, commaOk bool, pos token.Pos) (llvm.Value, error) { func (c *Compiler) emitMapLookup(keyType, valueType types.Type, m, key llvm.Value, commaOk bool, pos token.Pos) (llvm.Value, error) {
llvmValueType, err := c.getLLVMType(valueType) llvmValueType := c.getLLVMType(valueType)
if err != nil {
return llvm.Value{}, err
}
mapValueAlloca := c.builder.CreateAlloca(llvmValueType, "hashmap.value") mapValueAlloca := c.builder.CreateAlloca(llvmValueType, "hashmap.value")
mapValuePtr := c.builder.CreateBitCast(mapValueAlloca, c.i8ptrType, "hashmap.valueptr") mapValuePtr := c.builder.CreateBitCast(mapValueAlloca, c.i8ptrType, "hashmap.valueptr")
var commaOkValue llvm.Value var commaOkValue llvm.Value

Loading…
Cancel
Save