compiler: refactor IR parts into separate package

This commit is contained in:
Ayke van Laethem
2018-09-22 20:25:50 +02:00
parent 473e71b573
commit b75a02e66d
5 changed files with 182 additions and 169 deletions
+103 -126
View File
@@ -14,6 +14,7 @@ import (
"strings"
"github.com/aykevl/llvm/bindings/go/llvm"
"github.com/aykevl/tinygo/ir"
"go/parser"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/ssa"
@@ -53,12 +54,12 @@ type Compiler struct {
coroEndFunc llvm.Value
coroFreeFunc llvm.Value
initFuncs []llvm.Value
deferFuncs []*Function
ir *Program
deferFuncs []*ir.Function
ir *ir.Program
}
type Frame struct {
fn *Function
fn *ir.Function
params map[*ssa.Parameter]int // arguments to the function
locals map[ssa.Value]llvm.Value // local variables
blocks map[*ssa.BasicBlock]llvm.BasicBlock
@@ -77,8 +78,6 @@ type Phi struct {
llvm llvm.Value
}
var cgoWrapperError = errors.New("tinygo internal: cgo wrapper")
func NewCompiler(pkgName, triple string, dumpSSA bool) (*Compiler, error) {
c := &Compiler{
dumpSSA: dumpSSA,
@@ -178,7 +177,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
}
}
c.ir = NewProgram(lprogram, mainPath)
c.ir = ir.NewProgram(lprogram, mainPath)
// Make a list of packages in import order.
packageList := []*ssa.Package{}
@@ -186,7 +185,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
worklist := []string{"runtime", mainPath}
for len(worklist) != 0 {
pkgPath := worklist[0]
pkg := c.ir.program.ImportedPackage(pkgPath)
pkg := c.ir.Program.ImportedPackage(pkgPath)
if pkg == nil {
// Non-SSA package (e.g. cgo).
packageSet[pkgPath] = struct{}{}
@@ -244,22 +243,22 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Declare all named struct types.
for _, t := range c.ir.NamedTypes {
if named, ok := t.t.Type().(*types.Named); ok {
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())
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.t.Type().(*types.Named); ok {
if named, ok := t.Type.Type().(*types.Named); ok {
if st, ok := named.Underlying().(*types.Struct); ok {
llvmType, err := c.getLLVMType(st)
if err != nil {
return err
}
t.llvmType.StructSetBody(llvmType.StructElementTypes(), false)
t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false)
}
}
}
@@ -267,7 +266,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Declare all globals. These will get an initializer when parsing "package
// initializer" functions.
for _, g := range c.ir.Globals {
typ := g.g.Type().(*types.Pointer).Elem()
typ := g.Type().(*types.Pointer).Elem()
llvmType, err := c.getLLVMType(typ)
if err != nil {
return err
@@ -276,7 +275,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
if global.IsNil() {
global = llvm.AddGlobal(c.mod, llvmType, g.LinkName())
}
g.llvmGlobal = global
g.LLVMGlobal = global
if !g.IsExtern() {
global.SetLinkage(llvm.InternalLinkage)
initializer, err := getZeroValue(llvmType)
@@ -298,9 +297,9 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Find and interpret package initializers.
for _, frame := range frames {
if frame.fn.fn.Synthetic == "package initializer" {
c.initFuncs = append(c.initFuncs, frame.fn.llvmFn)
if len(frame.fn.fn.Blocks) != 1 {
if frame.fn.Synthetic == "package initializer" {
c.initFuncs = append(c.initFuncs, frame.fn.LLVMFn)
if len(frame.fn.Blocks) != 1 {
panic("unexpected number of basic blocks in package initializer")
}
// Try to interpret as much as possible of the init() function.
@@ -309,7 +308,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// continues at runtime).
// This should only happen when it hits a function call or the end
// of the block, ideally.
err := c.ir.Interpret(frame.fn.fn.Blocks[0], c.dumpSSA)
err := c.ir.Interpret(frame.fn.Blocks[0], c.dumpSSA)
if err != nil {
return err
}
@@ -322,7 +321,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Set values for globals (after package initializer has been interpreted).
for _, g := range c.ir.Globals {
if g.initializer == nil {
if g.Initializer() == nil {
continue
}
err := c.parseGlobalInitializer(g)
@@ -336,11 +335,11 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
if frame.fn.CName() != "" {
continue
}
if frame.fn.fn.Blocks == nil {
if frame.fn.Blocks == nil {
continue // external function
}
var err error
if frame.fn.fn.Synthetic == "package initializer" {
if frame.fn.Synthetic == "package initializer" {
continue // already done
} else {
err = c.parseFunc(frame)
@@ -364,7 +363,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Get the real param type and cast to it.
valueTypes := []llvm.Type{llvmFn.Type(), llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)}
for _, param := range fn.fn.Params {
for _, param := range fn.Params {
llvmType, err := c.getLLVMType(param.Type())
if err != nil {
return err
@@ -377,14 +376,14 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
// Extract the params from the struct.
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(llvm.Int32Type(), 0, false)
for i := range fn.fn.Params {
for i := range fn.Params {
gep := c.builder.CreateGEP(contextPtr, []llvm.Value{zero, llvm.ConstInt(llvm.Int32Type(), uint64(i+2), false)}, "gep")
forwardParam := c.builder.CreateLoad(gep, "param")
forwardParams = append(forwardParams, forwardParam)
}
// Call real function (of which this is a wrapper).
c.builder.CreateCall(fn.llvmFn, forwardParams, "")
c.builder.CreateCall(fn.LLVMFn, forwardParams, "")
c.builder.CreateRetVoid()
}
@@ -400,7 +399,7 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
c.builder.CreateRetVoid()
// Adjust main function.
realMain := c.mod.NamedFunction(c.ir.mainPkg.Pkg.Path() + ".main")
realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main")
if c.ir.NeedsScheduler() {
c.mod.NamedFunction("runtime.main_mainAsync").ReplaceAllUsesWith(realMain)
} else {
@@ -441,11 +440,11 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
}
c.ir.SortMethods(methods)
for _, method := range methods {
f := c.ir.GetFunction(c.ir.program.MethodValue(method))
if f.llvmFn.IsNil() {
f := c.ir.GetFunction(c.ir.Program.MethodValue(method))
if f.LLVMFn.IsNil() {
return errors.New("cannot find function: " + f.LinkName())
}
fn := llvm.ConstBitCast(f.llvmFn, c.i8ptrType)
fn := llvm.ConstBitCast(f.LLVMFn, c.i8ptrType)
funcPointers = append(funcPointers, fn)
signatureNum := c.ir.MethodNum(method.Obj().(*types.Func))
signature := llvm.ConstInt(llvm.Int16Type(), uint64(signatureNum), false)
@@ -780,29 +779,7 @@ func (c *Compiler) getDIType(typ types.Type) (llvm.Metadata, error) {
}
}
// Get all methods of a type.
func getAllMethods(prog *ssa.Program, typ types.Type) []*types.Selection {
ms := prog.MethodSets.MethodSet(typ)
methods := make([]*types.Selection, ms.Len())
for i := 0; i < ms.Len(); i++ {
methods[i] = ms.At(i)
}
return methods
}
// Return true if this is a CGo-internal function that can be ignored.
func isCGoInternal(name string) bool {
if strings.HasPrefix(name, "_Cgo_") || strings.HasPrefix(name, "_cgo") {
// _Cgo_ptr, _Cgo_use, _cgoCheckResult, _cgo_runtime_cgocall
return true // CGo-internal functions
}
if strings.HasPrefix(name, "__cgofn__cgo_") {
return true // CGo function pointer in global scope
}
return false
}
func (c *Compiler) parseFuncDecl(f *Function) (*Frame, error) {
func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) {
frame := &Frame{
fn: f,
params: make(map[*ssa.Parameter]int),
@@ -813,22 +790,22 @@ func (c *Compiler) parseFuncDecl(f *Function) (*Frame, error) {
var retType llvm.Type
if frame.blocking {
if f.fn.Signature.Results() != nil {
if f.Signature.Results() != nil {
return nil, errors.New("todo: return values in blocking function")
}
retType = c.i8ptrType
} else if f.fn.Signature.Results() == nil {
} else if f.Signature.Results() == nil {
retType = llvm.VoidType()
} else if f.fn.Signature.Results().Len() == 1 {
} else if f.Signature.Results().Len() == 1 {
var err error
retType, err = c.getLLVMType(f.fn.Signature.Results().At(0).Type())
retType, err = c.getLLVMType(f.Signature.Results().At(0).Type())
if err != nil {
return nil, err
}
} else {
results := make([]llvm.Type, 0, f.fn.Signature.Results().Len())
for i := 0; i < f.fn.Signature.Results().Len(); i++ {
typ, err := c.getLLVMType(f.fn.Signature.Results().At(i).Type())
results := make([]llvm.Type, 0, f.Signature.Results().Len())
for i := 0; i < f.Signature.Results().Len(); i++ {
typ, err := c.getLLVMType(f.Signature.Results().At(i).Type())
if err != nil {
return nil, err
}
@@ -841,7 +818,7 @@ func (c *Compiler) parseFuncDecl(f *Function) (*Frame, error) {
if frame.blocking {
paramTypes = append(paramTypes, c.i8ptrType) // parent coroutine
}
for i, param := range f.fn.Params {
for i, param := range f.Params {
paramType, err := c.getLLVMType(param.Type())
if err != nil {
return nil, err
@@ -859,22 +836,22 @@ func (c *Compiler) parseFuncDecl(f *Function) (*Frame, error) {
fnType := llvm.FunctionType(retType, paramTypes, false)
name := f.LinkName()
frame.fn.llvmFn = c.mod.NamedFunction(name)
if frame.fn.llvmFn.IsNil() {
frame.fn.llvmFn = llvm.AddFunction(c.mod, name, fnType)
frame.fn.LLVMFn = c.mod.NamedFunction(name)
if frame.fn.LLVMFn.IsNil() {
frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType)
}
if c.debug && f.fn.Syntax() != nil && len(f.fn.Blocks) != 0 {
if c.debug && f.Syntax() != nil && len(f.Blocks) != 0 {
// Create debug info file if needed.
pos := c.ir.program.Fset.Position(f.fn.Syntax().Pos())
pos := c.ir.Program.Fset.Position(f.Syntax().Pos())
if _, ok := c.difiles[pos.Filename]; !ok {
dir, file := filepath.Split(pos.Filename)
c.difiles[pos.Filename] = c.dibuilder.CreateFile(file, dir[:len(dir)-1])
}
// Debug info for this function.
diparams := make([]llvm.Metadata, 0, len(f.fn.Params))
for _, param := range f.fn.Params {
diparams := make([]llvm.Metadata, 0, len(f.Params))
for _, param := range f.Params {
ditype, err := c.getDIType(param.Type())
if err != nil {
return nil, err
@@ -887,7 +864,7 @@ func (c *Compiler) parseFuncDecl(f *Function) (*Frame, error) {
Flags: 0, // ?
})
frame.difunc = c.dibuilder.CreateFunction(c.difiles[pos.Filename], llvm.DIFunction{
Name: f.fn.RelString(nil),
Name: f.RelString(nil),
LinkageName: f.LinkName(),
File: c.difiles[pos.Filename],
Line: pos.Line,
@@ -898,7 +875,7 @@ func (c *Compiler) parseFuncDecl(f *Function) (*Frame, error) {
Flags: llvm.FlagPrototyped,
Optimized: true,
})
frame.fn.llvmFn.SetSubprogram(frame.difunc)
frame.fn.LLVMFn.SetSubprogram(frame.difunc)
}
return frame, nil
@@ -932,24 +909,24 @@ func (c *Compiler) initMapNewBucket(prefix string, mapType *types.Map) (llvm.Val
return bucket, keySize, valueSize, nil
}
func (c *Compiler) parseGlobalInitializer(g *Global) error {
func (c *Compiler) parseGlobalInitializer(g *ir.Global) error {
if g.IsExtern() {
return nil
}
llvmValue, err := c.getInterpretedValue(g.LinkName(), g.initializer)
llvmValue, err := c.getInterpretedValue(g.LinkName(), g.Initializer())
if err != nil {
return err
}
g.llvmGlobal.SetInitializer(llvmValue)
g.LLVMGlobal.SetInitializer(llvmValue)
return nil
}
// Turn a computed Value type (ConstValue, ArrayValue, etc.) into a LLVM value.
// This is used to set the initializer of globals after they have been
// calculated by the package initializer interpreter.
func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value, error) {
func (c *Compiler) getInterpretedValue(prefix string, value ir.Value) (llvm.Value, error) {
switch value := value.(type) {
case *ArrayValue:
case *ir.ArrayValue:
vals := make([]llvm.Value, len(value.Elems))
for i, elem := range value.Elems {
val, err := c.getInterpretedValue(prefix+"$arrayval", elem)
@@ -964,10 +941,10 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
}
return llvm.ConstArray(subTyp, vals), nil
case *ConstValue:
case *ir.ConstValue:
return c.parseConst(prefix, value.Expr)
case *FunctionValue:
case *ir.FunctionValue:
if value.Elem == nil {
llvmType, err := c.getLLVMType(value.Type)
if err != nil {
@@ -976,19 +953,19 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
return getZeroValue(llvmType)
}
fn := c.ir.GetFunction(value.Elem)
ptr := fn.llvmFn
if c.ir.SignatureNeedsContext(fn.fn.Signature) {
ptr := fn.LLVMFn
if c.ir.SignatureNeedsContext(fn.Signature) {
// Create closure value: {context, function pointer}
ptr = llvm.ConstStruct([]llvm.Value{llvm.ConstPointerNull(c.i8ptrType), ptr}, false)
}
return ptr, nil
case *GlobalValue:
case *ir.GlobalValue:
zero := llvm.ConstInt(llvm.Int32Type(), 0, false)
ptr := llvm.ConstInBoundsGEP(value.Global.llvmGlobal, []llvm.Value{zero})
ptr := llvm.ConstInBoundsGEP(value.Global.LLVMGlobal, []llvm.Value{zero})
return ptr, nil
case *InterfaceValue:
case *ir.InterfaceValue:
underlying := llvm.ConstPointerNull(c.i8ptrType) // could be any 0 value
if value.Elem != nil {
elem, err := c.getInterpretedValue(prefix, value.Elem)
@@ -999,7 +976,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
}
return c.parseMakeInterface(underlying, value.Type, prefix)
case *MapValue:
case *ir.MapValue:
// Create initial bucket.
firstBucketGlobal, keySize, valueSize, err := c.initMapNewBucket(prefix, value.Type)
if err != nil {
@@ -1018,7 +995,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
return llvm.Value{}, nil
}
constVal := key.(*ConstValue).Expr
constVal := key.(*ir.ConstValue).Expr
var keyBuf []byte
switch constVal.Type().Underlying().(*types.Basic).Kind() {
case types.String:
@@ -1079,7 +1056,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
hashmapPtr.SetLinkage(llvm.InternalLinkage)
return llvm.ConstInBoundsGEP(hashmapPtr, []llvm.Value{zero}), nil
case *PointerBitCastValue:
case *ir.PointerBitCastValue:
elem, err := c.getInterpretedValue(prefix, value.Elem)
if err != nil {
return llvm.Value{}, err
@@ -1090,14 +1067,14 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
}
return llvm.ConstBitCast(elem, llvmType), nil
case *PointerToUintptrValue:
case *ir.PointerToUintptrValue:
elem, err := c.getInterpretedValue(prefix, value.Elem)
if err != nil {
return llvm.Value{}, err
}
return llvm.ConstPtrToInt(elem, c.uintptrType), nil
case *PointerValue:
case *ir.PointerValue:
if value.Elem == nil {
typ, err := c.getLLVMType(value.Type)
if err != nil {
@@ -1119,7 +1096,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
ptr := llvm.ConstInBoundsGEP(elem, []llvm.Value{zero})
return ptr, nil
case *SliceValue:
case *ir.SliceValue:
var globalPtr llvm.Value
var arrayLength uint64
if value.Array == nil {
@@ -1159,7 +1136,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
})
return slice, nil
case *StructValue:
case *ir.StructValue:
fields := make([]llvm.Value, len(value.Fields))
for i, elem := range value.Fields {
field, err := c.getInterpretedValue(prefix, elem)
@@ -1181,7 +1158,7 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
return llvm.Value{}, errors.New("init: unknown struct type: " + value.Type.String())
}
case *ZeroBasicValue:
case *ir.ZeroBasicValue:
llvmType, err := c.getLLVMType(value.Type)
if err != nil {
return llvm.Value{}, err
@@ -1195,36 +1172,36 @@ func (c *Compiler) getInterpretedValue(prefix string, value Value) (llvm.Value,
func (c *Compiler) parseFunc(frame *Frame) error {
if c.dumpSSA {
fmt.Printf("\nfunc %s:\n", frame.fn.fn)
fmt.Printf("\nfunc %s:\n", frame.fn.Function)
}
if !frame.fn.IsExported() {
frame.fn.llvmFn.SetLinkage(llvm.InternalLinkage)
frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage)
}
if c.debug {
pos := c.ir.program.Fset.Position(frame.fn.fn.Pos())
pos := c.ir.Program.Fset.Position(frame.fn.Pos())
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
}
// Pre-create all basic blocks in the function.
for _, block := range frame.fn.fn.DomPreorder() {
llvmBlock := c.ctx.AddBasicBlock(frame.fn.llvmFn, block.Comment)
for _, block := range frame.fn.DomPreorder() {
llvmBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, block.Comment)
frame.blocks[block] = llvmBlock
}
if frame.blocking {
frame.cleanupBlock = c.ctx.AddBasicBlock(frame.fn.llvmFn, "task.cleanup")
frame.suspendBlock = c.ctx.AddBasicBlock(frame.fn.llvmFn, "task.suspend")
frame.cleanupBlock = c.ctx.AddBasicBlock(frame.fn.LLVMFn, "task.cleanup")
frame.suspendBlock = c.ctx.AddBasicBlock(frame.fn.LLVMFn, "task.suspend")
}
entryBlock := frame.blocks[frame.fn.fn.Blocks[0]]
entryBlock := frame.blocks[frame.fn.Blocks[0]]
// Load function parameters
for i, param := range frame.fn.fn.Params {
llvmParam := frame.fn.llvmFn.Param(frame.params[param])
for i, param := range frame.fn.Params {
llvmParam := frame.fn.LLVMFn.Param(frame.params[param])
frame.locals[param] = llvmParam
// Add debug information to this parameter (if available)
if c.debug && frame.fn.fn.Syntax() != nil {
pos := c.ir.program.Fset.Position(frame.fn.fn.Syntax().Pos())
if c.debug && frame.fn.Syntax() != nil {
pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos())
dityp, err := c.getDIType(param.Type())
if err != nil {
return err
@@ -1243,16 +1220,16 @@ func (c *Compiler) parseFunc(frame *Frame) error {
// Load free variables from the context. This is a closure (or bound
// method).
if len(frame.fn.fn.FreeVars) != 0 {
if len(frame.fn.FreeVars) != 0 {
if !c.ir.FunctionNeedsContext(frame.fn) {
panic("free variables on function without context")
}
c.builder.SetInsertPointAtEnd(entryBlock)
context := frame.fn.llvmFn.Param(len(frame.fn.fn.Params))
context := frame.fn.LLVMFn.Param(len(frame.fn.Params))
// Determine the context type. It's a struct containing all variables.
freeVarTypes := make([]llvm.Type, 0, len(frame.fn.fn.FreeVars))
for _, freeVar := range frame.fn.fn.FreeVars {
freeVarTypes := make([]llvm.Type, 0, len(frame.fn.FreeVars))
for _, freeVar := range frame.fn.FreeVars {
typ, err := c.getLLVMType(freeVar.Type())
if err != nil {
return err
@@ -1279,7 +1256,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
// A free variable is always a pointer when this is a closure, but it
// can be another type when it is a wrapper for a bound method (these
// wrappers are generated by the ssa package).
for i, freeVar := range frame.fn.fn.FreeVars {
for i, freeVar := range frame.fn.FreeVars {
indices := []llvm.Value{
llvm.ConstInt(llvm.Int32Type(), 0, false),
llvm.ConstInt(llvm.Int32Type(), uint64(i), false),
@@ -1291,7 +1268,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
c.builder.SetInsertPointAtEnd(entryBlock)
if frame.fn.fn.Recover != nil {
if frame.fn.Recover != nil {
// Create defer list pointer.
deferType := llvm.PointerType(c.mod.GetTypeByName("runtime._defer"), 0)
frame.deferPtr = c.builder.CreateAlloca(deferType, "deferPtr")
@@ -1322,7 +1299,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
mem := c.builder.CreateCall(c.coroFreeFunc, []llvm.Value{id, frame.taskHandle}, "task.data.free")
c.builder.CreateCall(c.freeFunc, []llvm.Value{mem}, "")
// re-insert parent coroutine
c.builder.CreateCall(c.mod.NamedFunction("runtime.yieldToScheduler"), []llvm.Value{frame.fn.llvmFn.FirstParam()}, "")
c.builder.CreateCall(c.mod.NamedFunction("runtime.yieldToScheduler"), []llvm.Value{frame.fn.LLVMFn.FirstParam()}, "")
c.builder.CreateBr(frame.suspendBlock)
// Coroutine suspend. A call to llvm.coro.suspend() will branch here.
@@ -1332,7 +1309,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
}
// Fill blocks with instructions.
for _, block := range frame.fn.fn.DomPreorder() {
for _, block := range frame.fn.DomPreorder() {
if c.dumpSSA {
fmt.Printf("%s:\n", block.Comment)
}
@@ -1354,7 +1331,7 @@ func (c *Compiler) parseFunc(frame *Frame) error {
return err
}
}
if frame.fn.fn.Name() == "init" && len(block.Instrs) == 0 {
if frame.fn.Name() == "init" && len(block.Instrs) == 0 {
c.builder.CreateRetVoid()
}
}
@@ -1377,14 +1354,14 @@ func (c *Compiler) parseFunc(frame *Frame) error {
func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
if c.debug {
pos := c.ir.program.Fset.Position(instr.Pos())
pos := c.ir.Program.Fset.Position(instr.Pos())
c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{})
}
switch instr := instr.(type) {
case ssa.Value:
value, err := c.parseExpr(frame, instr)
if err == cgoWrapperError {
if err == ir.ErrCGoWrapper {
// Ignore CGo global variables which we don't use.
return nil
}
@@ -1551,7 +1528,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
return nil
} else {
// Multiple return values. Put them all in a struct.
retVal, err := getZeroValue(frame.fn.llvmFn.Type().ElementType().ReturnType())
retVal, err := getZeroValue(frame.fn.LLVMFn.Type().ElementType().ReturnType())
if err != nil {
return err
}
@@ -1573,7 +1550,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
return nil
case *ssa.Store:
llvmAddr, err := c.parseExpr(frame, instr.Addr)
if err == cgoWrapperError {
if err == ir.ErrCGoWrapper {
// Ignore CGo global variables which we don't use.
return nil
}
@@ -1854,7 +1831,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon, parentHandle l
}
}
targetFunc := c.ir.GetFunction(fn)
if targetFunc.llvmFn.IsNil() {
if targetFunc.LLVMFn.IsNil() {
return llvm.Value{}, errors.New("undefined function: " + targetFunc.LinkName())
}
var context llvm.Value
@@ -1877,7 +1854,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon, parentHandle l
}
}
}
return c.parseFunctionCall(frame, instr.Args, targetFunc.llvmFn, context, c.ir.IsBlocking(targetFunc), parentHandle)
return c.parseFunctionCall(frame, instr.Args, targetFunc.LLVMFn, context, c.ir.IsBlocking(targetFunc), parentHandle)
}
// Builtin or function pointer.
@@ -1903,7 +1880,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon, parentHandle l
}
func (c *Compiler) emitBoundsCheck(frame *Frame, arrayLen, index llvm.Value) {
if frame.fn.nobounds {
if frame.fn.IsNoBounds() {
// The //go:nobounds pragma was added to the function to avoid bounds
// checking.
return
@@ -2016,7 +1993,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return c.builder.CreateGEP(val, indices, ""), nil
case *ssa.Function:
fn := c.ir.GetFunction(expr)
ptr := fn.llvmFn
ptr := fn.LLVMFn
if c.ir.FunctionNeedsContext(fn) {
// Create closure for function pointer.
// Closure is: {context, function pointer}
@@ -2029,9 +2006,9 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
case *ssa.Global:
if strings.HasPrefix(expr.Name(), "__cgofn__cgo_") || strings.HasPrefix(expr.Name(), "_cgo_") {
// Ignore CGo global variables which we don't use.
return llvm.Value{}, cgoWrapperError
return llvm.Value{}, ir.ErrCGoWrapper
}
value := c.ir.GetGlobal(expr).llvmGlobal
value := c.ir.GetGlobal(expr).LLVMGlobal
if value.IsNil() {
return llvm.Value{}, errors.New("global not found: " + c.ir.GetGlobal(expr).LinkName())
}
@@ -2209,7 +2186,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
elemSize := c.targetData.TypeAllocSize(llvmElemType)
// Bounds checking.
if !frame.fn.nobounds {
if !frame.fn.IsNoBounds() {
sliceBoundsCheck := c.mod.NamedFunction("runtime.sliceBoundsCheckMake")
c.builder.CreateCall(sliceBoundsCheck, []llvm.Value{sliceLen, sliceCap}, "")
}
@@ -2343,7 +2320,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
sliceCap := c.builder.CreateSub(llvmLenInt, low, "slice.cap")
// This check is optimized away in most cases.
if !frame.fn.nobounds {
if !frame.fn.IsNoBounds() {
sliceBoundsCheck := c.mod.NamedFunction("runtime.sliceBoundsCheck")
c.builder.CreateCall(sliceBoundsCheck, []llvm.Value{llvmLen, low, high}, "")
}
@@ -2372,7 +2349,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
high = oldLen
}
if !frame.fn.nobounds {
if !frame.fn.IsNoBounds() {
sliceBoundsCheck := c.mod.NamedFunction("runtime.sliceBoundsCheck")
c.builder.CreateCall(sliceBoundsCheck, []llvm.Value{oldLen, low, high}, "")
}
@@ -2408,7 +2385,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
high = oldLen
}
if !frame.fn.nobounds {
if !frame.fn.IsNoBounds() {
sliceBoundsCheck := c.mod.NamedFunction("runtime.sliceBoundsCheck")
c.builder.CreateCall(sliceBoundsCheck, []llvm.Value{oldLen, low, high}, "")
}
@@ -2491,8 +2468,8 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
// value.
prevBlock := c.builder.GetInsertBlock()
okBlock := c.ctx.AddBasicBlock(frame.fn.llvmFn, "typeassert.ok")
nextBlock := c.ctx.AddBasicBlock(frame.fn.llvmFn, "typeassert.next")
okBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "typeassert.ok")
nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "typeassert.next")
frame.blocks[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
c.builder.CreateCondBr(commaOk, okBlock, nextBlock)
@@ -3034,7 +3011,7 @@ func (c *Compiler) parseMakeClosure(frame *Frame, expr *ssa.MakeClosure) (llvm.V
// Get the function signature type, which is a closure type.
// A closure is a tuple of {context, function pointer}.
typ, err := c.getLLVMType(f.fn.Signature)
typ, err := c.getLLVMType(f.Signature)
if err != nil {
return llvm.Value{}, err
}
@@ -3044,7 +3021,7 @@ func (c *Compiler) parseMakeClosure(frame *Frame, expr *ssa.MakeClosure) (llvm.V
if err != nil {
return llvm.Value{}, err
}
closure = c.builder.CreateInsertValue(closure, f.llvmFn, 1, "")
closure = c.builder.CreateInsertValue(closure, f.LLVMFn, 1, "")
closure = c.builder.CreateInsertValue(closure, context, 0, "")
return closure, nil
}