compiler: Do not pre-define runtime functions by the compiler

Этот коммит содержится в:
Ayke van Laethem 2018-05-03 21:15:29 +02:00
родитель b11a618d99
коммит b0cb51bdd8

59
tgo.go
Просмотреть файл

@ -43,16 +43,6 @@ type Compiler struct {
stringType llvm.Type stringType llvm.Type
interfaceType llvm.Type interfaceType llvm.Type
typeassertType llvm.Type typeassertType llvm.Type
panicFunc llvm.Value
boundsCheckFunc llvm.Value
printstringFunc llvm.Value
printint32Func llvm.Value
printuint32Func llvm.Value
printint64Func llvm.Value
printuint64Func llvm.Value
printbyteFunc llvm.Value
printspaceFunc llvm.Value
printnlFunc llvm.Value
itfTypeNumbers map[types.Type]uint64 itfTypeNumbers map[types.Type]uint64
itfTypes []types.Type itfTypes []types.Type
initFuncs []llvm.Value initFuncs []llvm.Value
@ -109,27 +99,6 @@ func NewCompiler(pkgName, triple string) (*Compiler, error) {
// Go typeassert result: tuple of (ptr, bool) // Go typeassert result: tuple of (ptr, bool)
c.typeassertType = llvm.StructType([]llvm.Type{llvm.PointerType(llvm.Int8Type(), 0), llvm.Int1Type()}, false) c.typeassertType = llvm.StructType([]llvm.Type{llvm.PointerType(llvm.Int8Type(), 0), llvm.Int1Type()}, false)
panicType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{c.interfaceType}, false)
c.panicFunc = llvm.AddFunction(c.mod, "runtime._panic", panicType)
boundsCheckType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{llvm.Int1Type()}, false)
c.boundsCheckFunc = llvm.AddFunction(c.mod, "runtime.boundsCheck", boundsCheckType)
printstringType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{c.stringType}, false)
c.printstringFunc = llvm.AddFunction(c.mod, "runtime.printstring", printstringType)
printi32Type := llvm.FunctionType(llvm.VoidType(), []llvm.Type{llvm.Int32Type()}, false)
c.printint32Func = llvm.AddFunction(c.mod, "runtime.printint32", printi32Type)
c.printuint32Func = llvm.AddFunction(c.mod, "runtime.printuint32", printi32Type)
printi64Type := llvm.FunctionType(llvm.VoidType(), []llvm.Type{llvm.Int64Type()}, false)
c.printint64Func = llvm.AddFunction(c.mod, "runtime.printint64", printi64Type)
c.printuint64Func = llvm.AddFunction(c.mod, "runtime.printuint64", printi64Type)
printbyteType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{llvm.Int8Type()}, false)
c.printbyteFunc = llvm.AddFunction(c.mod, "runtime.printbyte", printbyteType)
printspaceType := llvm.FunctionType(llvm.VoidType(), nil, false)
c.printspaceFunc = llvm.AddFunction(c.mod, "runtime.printspace", printspaceType)
printnlType := llvm.FunctionType(llvm.VoidType(), nil, false)
c.printnlFunc = llvm.AddFunction(c.mod, "runtime.printnl", printnlType)
return c, nil return c, nil
} }
@ -183,7 +152,11 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
} }
unsatisfiedImports := make([]string, 0) unsatisfiedImports := make([]string, 0)
for _, pkg := range pkg.Pkg.Imports() { imports := pkg.Pkg.Imports()
if pkgPath != "runtime" && pkgPath != "unsafe" && pkgPath != "runtime/cgo" && pkgPath != "syscall" {
imports = append(imports, program.ImportedPackage("runtime").Pkg)
}
for _, pkg := range imports {
if _, ok := packageSet[pkg.Path()]; ok { if _, ok := packageSet[pkg.Path()]; ok {
continue continue
} }
@ -557,7 +530,7 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
if err != nil { if err != nil {
return err return err
} }
c.builder.CreateCall(c.panicFunc, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime._panic"), []llvm.Value{value}, "")
c.builder.CreateUnreachable() c.builder.CreateUnreachable()
return nil return nil
case *ssa.Return: case *ssa.Return:
@ -601,7 +574,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
case "print", "println": case "print", "println":
for i, arg := range args { for i, arg := range args {
if i >= 1 { if i >= 1 {
c.builder.CreateCall(c.printspaceFunc, nil, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printspace"), nil, "")
} }
fmt.Printf(" arg: %s\n", arg); fmt.Printf(" arg: %s\n", arg);
value, err := c.parseExpr(frame, arg) value, err := c.parseExpr(frame, arg)
@ -616,17 +589,17 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
case *types.Basic: case *types.Basic:
switch typ.Kind() { switch typ.Kind() {
case types.Uint8: case types.Uint8:
c.builder.CreateCall(c.printbyteFunc, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printbyte"), []llvm.Value{value}, "")
case types.Int, types.Int32: // TODO: assumes a 32-bit int type case types.Int, types.Int32: // TODO: assumes a 32-bit int type
c.builder.CreateCall(c.printint32Func, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printint32"), []llvm.Value{value}, "")
case types.Uint, types.Uint32: case types.Uint, types.Uint32:
c.builder.CreateCall(c.printuint32Func, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint32"), []llvm.Value{value}, "")
case types.Int64: case types.Int64:
c.builder.CreateCall(c.printint64Func, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printint64"), []llvm.Value{value}, "")
case types.Uint64: case types.Uint64:
c.builder.CreateCall(c.printuint64Func, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint64"), []llvm.Value{value}, "")
case types.String: case types.String:
c.builder.CreateCall(c.printstringFunc, []llvm.Value{value}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printstring"), []llvm.Value{value}, "")
default: default:
return llvm.Value{}, errors.New("unknown basic arg type: " + fmt.Sprintf("%#v", typ)) return llvm.Value{}, errors.New("unknown basic arg type: " + fmt.Sprintf("%#v", typ))
} }
@ -635,7 +608,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
} }
} }
if callName == "println" { if callName == "println" {
c.builder.CreateCall(c.printnlFunc, nil, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.printnl"), nil, "")
} }
return llvm.Value{}, nil // print() or println() returns void return llvm.Value{}, nil // print() or println() returns void
case "len": case "len":
@ -792,7 +765,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
isNegative := c.builder.CreateICmp(llvm.IntSLT, index, constZero, "") // index < 0 isNegative := c.builder.CreateICmp(llvm.IntSLT, index, constZero, "") // index < 0
isTooBig := c.builder.CreateICmp(llvm.IntSGE, index, buflen, "") // index >= len(value) isTooBig := c.builder.CreateICmp(llvm.IntSGE, index, buflen, "") // index >= len(value)
isOverflow := c.builder.CreateOr(isNegative, isTooBig, "") isOverflow := c.builder.CreateOr(isNegative, isTooBig, "")
c.builder.CreateCall(c.boundsCheckFunc, []llvm.Value{isOverflow}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.boundsCheck"), []llvm.Value{isOverflow}, "")
indices := []llvm.Value{ indices := []llvm.Value{
llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), 0, false),
@ -830,7 +803,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
} }
isTooBig := c.builder.CreateICmp(llvm.IntSGE, index, strlen, "") // index >= len(value) isTooBig := c.builder.CreateICmp(llvm.IntSGE, index, strlen, "") // index >= len(value)
isOverflow := c.builder.CreateOr(isNegative, isTooBig, "") isOverflow := c.builder.CreateOr(isNegative, isTooBig, "")
c.builder.CreateCall(c.boundsCheckFunc, []llvm.Value{isOverflow}, "") c.builder.CreateCall(c.mod.NamedFunction("runtime.boundsCheck"), []llvm.Value{isOverflow}, "")
} }
// Lookup byte // Lookup byte