diff options
-rw-r--r-- | builder/build.go | 2 | ||||
-rw-r--r-- | compiler/alias.go | 2 | ||||
-rw-r--r-- | compiler/atomic.go | 4 | ||||
-rw-r--r-- | compiler/calls.go | 14 | ||||
-rw-r--r-- | compiler/compiler.go | 25 | ||||
-rw-r--r-- | compiler/defer.go | 16 | ||||
-rw-r--r-- | compiler/func.go | 8 | ||||
-rw-r--r-- | compiler/goroutine.go | 33 | ||||
-rw-r--r-- | compiler/inlineasm.go | 16 | ||||
-rw-r--r-- | compiler/interface.go | 17 | ||||
-rw-r--r-- | compiler/interrupt.go | 4 | ||||
-rw-r--r-- | compiler/intrinsics.go | 6 | ||||
-rw-r--r-- | compiler/llvm.go | 2 | ||||
-rw-r--r-- | compiler/llvmutil/llvm.go | 24 | ||||
-rw-r--r-- | compiler/llvmutil/wordpack.go | 4 | ||||
-rw-r--r-- | compiler/symbol.go | 6 | ||||
-rw-r--r-- | compiler/syscall.go | 14 | ||||
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 4 | ||||
-rw-r--r-- | interp/interp.go | 2 | ||||
-rw-r--r-- | interp/interpreter.go | 2 | ||||
-rw-r--r-- | transform/interface-lowering.go | 7 | ||||
-rw-r--r-- | transform/interrupt.go | 2 | ||||
-rw-r--r-- | transform/panic.go | 2 | ||||
-rw-r--r-- | transform/rtcalls.go | 2 | ||||
-rw-r--r-- | transform/wasm-abi.go | 6 |
26 files changed, 123 insertions, 103 deletions
diff --git a/builder/build.go b/builder/build.go index 8095a6b60..bb2d634a9 100644 --- a/builder/build.go +++ b/builder/build.go @@ -516,7 +516,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe if pkgInit.IsNil() { panic("init not found for " + pkg.Pkg.Path()) } - irbuilder.CreateCall(pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "") + irbuilder.CreateCall(pkgInit.GlobalValueType(), pkgInit, []llvm.Value{llvm.Undef(i8ptrType)}, "") } irbuilder.CreateRetVoid() diff --git a/compiler/alias.go b/compiler/alias.go index 9e88e3c6a..b16cbce86 100644 --- a/compiler/alias.go +++ b/compiler/alias.go @@ -52,7 +52,7 @@ func (b *builder) createAlias(alias llvm.Value) { b.CreateUnreachable() return } - result := b.CreateCall(alias, b.llvmFn.Params(), "") + result := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(), "") if result.Type().TypeKind() == llvm.VoidTypeKind { b.CreateRetVoid() } else { diff --git a/compiler/atomic.go b/compiler/atomic.go index f12c6d117..6ba3849c4 100644 --- a/compiler/atomic.go +++ b/compiler/atomic.go @@ -25,7 +25,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value { if fn.IsNil() { fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(), vType}, false)) } - oldVal := b.createCall(fn, []llvm.Value{ptr, val}, "") + oldVal := b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val}, "") // Return the new value, not the original value returned. return b.CreateAdd(oldVal, val, "") } @@ -78,7 +78,7 @@ func (b *builder) createAtomicOp(name string) llvm.Value { if fn.IsNil() { fn = llvm.AddFunction(b.mod, name, llvm.FunctionType(vType, []llvm.Type{ptr.Type(), vType, b.uintptrType}, false)) } - b.createCall(fn, []llvm.Value{ptr, val, llvm.ConstInt(b.uintptrType, 5, false)}, "") + b.createCall(fn.GlobalValueType(), fn, []llvm.Value{ptr, val, llvm.ConstInt(b.uintptrType, 5, false)}, "") return llvm.Value{} } store := b.CreateStore(val, ptr) diff --git a/compiler/calls.go b/compiler/calls.go index aeca518a5..b38d770f9 100644 --- a/compiler/calls.go +++ b/compiler/calls.go @@ -37,15 +37,15 @@ const ( // createRuntimeInvoke instead. func (b *builder) createRuntimeCallCommon(fnName string, args []llvm.Value, name string, isInvoke bool) llvm.Value { fn := b.program.ImportedPackage("runtime").Members[fnName].(*ssa.Function) - llvmFn := b.getFunction(fn) + fnType, llvmFn := b.getFunction(fn) if llvmFn.IsNil() { panic("trying to call non-existent function: " + fn.RelString(nil)) } args = append(args, llvm.Undef(b.i8ptrType)) // unused context parameter if isInvoke { - return b.createInvoke(llvmFn, args, name) + return b.createInvoke(fnType, llvmFn, args, name) } - return b.createCall(llvmFn, args, name) + return b.createCall(fnType, llvmFn, args, name) } // createRuntimeCall creates a new call to runtime.<fnName> with the given @@ -65,22 +65,22 @@ func (b *builder) createRuntimeInvoke(fnName string, args []llvm.Value, name str // createCall creates a call to the given function with the arguments possibly // expanded. -func (b *builder) createCall(fn llvm.Value, args []llvm.Value, name string) llvm.Value { +func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value { expanded := make([]llvm.Value, 0, len(args)) for _, arg := range args { fragments := b.expandFormalParam(arg) expanded = append(expanded, fragments...) } - return b.CreateCall(fn, expanded, name) + return b.CreateCall(fnType, fn, expanded, name) } // createInvoke is like createCall but continues execution at the landing pad if // the call resulted in a panic. -func (b *builder) createInvoke(fn llvm.Value, args []llvm.Value, name string) llvm.Value { +func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value { if b.hasDeferFrame() { b.createInvokeCheckpoint() } - return b.createCall(fn, args, name) + return b.createCall(fnType, fn, args, name) } // Expand an argument type to a list that can be used in a function call diff --git a/compiler/compiler.go b/compiler/compiler.go index bbaf6432f..b64fddcc1 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -131,6 +131,7 @@ type builder struct { *compilerContext llvm.Builder fn *ssa.Function + llvmFnType llvm.Type llvmFn llvm.Value info functionInfo locals map[ssa.Value]llvm.Value // local variables @@ -155,11 +156,13 @@ type builder struct { } func newBuilder(c *compilerContext, irbuilder llvm.Builder, f *ssa.Function) *builder { + fnType, fn := c.getFunction(f) return &builder{ compilerContext: c, Builder: irbuilder, fn: f, - llvmFn: c.getFunction(f), + llvmFnType: fnType, + llvmFn: fn, info: c.getFunctionInfo(f), locals: make(map[ssa.Value]llvm.Value), dilocals: make(map[*types.Var]llvm.Metadata), @@ -711,7 +714,8 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata { // DISubprogram metadata node. func (c *compilerContext) attachDebugInfo(f *ssa.Function) llvm.Metadata { pos := c.program.Fset.Position(f.Syntax().Pos()) - return c.attachDebugInfoRaw(f, c.getFunction(f), "", pos.Filename, pos.Line) + _, fn := c.getFunction(f) + return c.attachDebugInfoRaw(f, fn, "", pos.Filename, pos.Line) } // attachDebugInfo adds debug info to a function declaration. It returns the @@ -1654,6 +1658,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) // Try to call the function directly for trivially static calls. var callee, context llvm.Value + var calleeType llvm.Type exported := false if fn := instr.StaticCallee(); fn != nil { // Direct function call, either to a named or anonymous (directly @@ -1684,7 +1689,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) return b.createInterruptGlobal(instr) } - callee = b.getFunction(fn) + calleeType, callee = b.getFunction(fn) info := b.getFunctionInfo(fn) if callee.IsNil() { return llvm.Value{}, b.makeError(instr.Pos(), "undefined function: "+info.linkName) @@ -1698,8 +1703,8 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) // Eventually we might be able to eliminate this special case // entirely. For details, see: // https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521 - fnType := llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false) - callee = llvm.ConstBitCast(callee, llvm.PointerType(fnType, b.funcPtrAddrSpace)) + calleeType = llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false) + callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType, b.funcPtrAddrSpace)) } case *ssa.MakeClosure: // A call on a func value, but the callee is trivial to find. For @@ -1726,13 +1731,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) params = append([]llvm.Value{value}, params...) params = append(params, typecode) callee = b.getInvokeFunction(instr) + calleeType = callee.GlobalValueType() context = llvm.Undef(b.i8ptrType) } else { // Function pointer. value := b.getValue(instr.Value) // This is a func value, which cannot be called directly. We have to // extract the function pointer and context first from the func value. - callee, context = b.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature)) + calleeType, callee, context = b.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature)) b.createNilCheck(instr.Value, callee, "fpcall") } @@ -1742,7 +1748,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) params = append(params, context) } - return b.createInvoke(callee, params, ""), nil + return b.createInvoke(calleeType, callee, params, ""), nil } // getValue returns the LLVM value of a constant, function value, global, or @@ -1756,7 +1762,8 @@ func (b *builder) getValue(expr ssa.Value) llvm.Value { b.addError(expr.Pos(), "cannot use an exported function as value: "+expr.String()) return llvm.Undef(b.getLLVMType(expr.Type())) } - return b.createFuncValue(b.getFunction(expr), llvm.Undef(b.i8ptrType), expr.Signature) + _, fn := b.getFunction(expr) + return b.createFuncValue(fn, llvm.Undef(b.i8ptrType), expr.Signature) case *ssa.Global: value := b.getGlobal(expr) if value.IsNil() { @@ -3080,7 +3087,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) { // Instead of a load from the global, create a bitcast of the // function pointer itself. name := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), "$funcaddr") - fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function)) + _, fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function)) if fn.IsNil() { return llvm.Value{}, b.makeError(unop.Pos(), "cgo function not found: "+name) } diff --git a/compiler/defer.go b/compiler/defer.go index 75c1be3d5..e82370fa5 100644 --- a/compiler/defer.go +++ b/compiler/defer.go @@ -201,7 +201,7 @@ li a0, 0 } asmType := llvm.FunctionType(resultType, []llvm.Type{b.deferFrame.Type()}, false) asm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false) - result := b.CreateCall(asm, []llvm.Value{b.deferFrame}, "setjmp") + result := b.CreateCall(asmType, asm, []llvm.Value{b.deferFrame}, "setjmp") result.AddCallSiteAttribute(-1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("returns_twice"), 0)) isZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false), "setjmp.result") continueBB := b.insertBasicBlock("") @@ -492,6 +492,7 @@ func (b *builder) createRunDefers() { } var fnPtr llvm.Value + var fnType llvm.Type if !callback.IsInvoke() { // Isolate the func value. @@ -499,8 +500,8 @@ func (b *builder) createRunDefers() { forwardParams = forwardParams[1:] //Get function pointer and context - fp, context := b.decodeFuncValue(funcValue, callback.Signature()) - fnPtr = fp + var context llvm.Value + fnType, fnPtr, context = b.decodeFuncValue(funcValue, callback.Signature()) //Pass context forwardParams = append(forwardParams, context) @@ -509,6 +510,7 @@ func (b *builder) createRunDefers() { // parameters. forwardParams = append(forwardParams[1:], forwardParams[0]) fnPtr = b.getInvokeFunction(callback) + fnType = fnPtr.GlobalValueType() // Add the context parameter. An interface call cannot also be a // closure but we have to supply the parameter anyway for platforms @@ -516,7 +518,7 @@ func (b *builder) createRunDefers() { forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType)) } - b.createCall(fnPtr, forwardParams, "") + b.createCall(fnType, fnPtr, forwardParams, "") case *ssa.Function: // Direct call. @@ -547,7 +549,8 @@ func (b *builder) createRunDefers() { } // Call real function. - b.createInvoke(b.getFunction(callback), forwardParams, "") + fnType, fn := b.getFunction(callback) + b.createInvoke(fnType, fn, forwardParams, "") case *ssa.MakeClosure: // Get the real defer struct type and cast to it. @@ -571,7 +574,8 @@ func (b *builder) createRunDefers() { } // Call deferred function. - b.createCall(b.getFunction(fn), forwardParams, "") + fnType, llvmFn := b.getFunction(fn) + b.createCall(fnType, llvmFn, forwardParams, "") case *ssa.Builtin: db := b.deferBuiltinFuncs[callback] diff --git a/compiler/func.go b/compiler/func.go index a8b2874eb..c6a8802d7 100644 --- a/compiler/func.go +++ b/compiler/func.go @@ -55,14 +55,15 @@ func (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value { // decodeFuncValue extracts the context and the function pointer from this func // value. This may be an expensive operation. -func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcPtr, context llvm.Value) { +func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcType llvm.Type, funcPtr, context llvm.Value) { context = b.CreateExtractValue(funcValue, 0, "") bitcast := b.CreateExtractValue(funcValue, 1, "") if !bitcast.IsAConstantExpr().IsNil() && bitcast.Opcode() == llvm.BitCast { funcPtr = bitcast.Operand(0) return } - llvmSig := llvm.PointerType(b.getRawFuncType(sig), b.funcPtrAddrSpace) + funcType = b.getRawFuncType(sig) + llvmSig := llvm.PointerType(funcType, b.funcPtrAddrSpace) funcPtr = b.CreateBitCast(bitcast, llvmSig, "") return } @@ -141,5 +142,6 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) { context := b.emitPointerPack(boundVars) // Create the closure. - return b.createFuncValue(b.getFunction(f), context, f.Signature), nil + _, fn := b.getFunction(f) + return b.createFuncValue(fn, context, f.Signature), nil } diff --git a/compiler/goroutine.go b/compiler/goroutine.go index 8d76c89f1..ba8ec0f46 100644 --- a/compiler/goroutine.go +++ b/compiler/goroutine.go @@ -22,6 +22,7 @@ func (b *builder) createGo(instr *ssa.Go) { var prefix string var funcPtr llvm.Value + var funcPtrType llvm.Type hasContext := false if callee := instr.Call.StaticCallee(); callee != nil { // Static callee is known. This makes it easier to start a new @@ -42,7 +43,7 @@ func (b *builder) createGo(instr *ssa.Go) { params = append(params, context) // context parameter hasContext = true } - funcPtr = b.getFunction(callee) + funcPtrType, funcPtr = b.getFunction(callee) } else if builtin, ok := instr.Call.Value.(*ssa.Builtin); ok { // We cheat. None of the builtins do any long or blocking operation, so // we might as well run these builtins right away without the program @@ -80,6 +81,7 @@ func (b *builder) createGo(instr *ssa.Go) { itfTypeCode := b.CreateExtractValue(itf, 0, "") itfValue := b.CreateExtractValue(itf, 1, "") funcPtr = b.getInvokeFunction(&instr.Call) + funcPtrType = funcPtr.GlobalValueType() params = append([]llvm.Value{itfValue}, params...) // start with receiver params = append(params, itfTypeCode) // end with typecode } else { @@ -89,7 +91,7 @@ func (b *builder) createGo(instr *ssa.Go) { // * The function context, for closures. // * The function pointer (for tasks). var context llvm.Value - funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value), instr.Call.Value.Type().Underlying().(*types.Signature)) + funcPtrType, funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value), instr.Call.Value.Type().Underlying().(*types.Signature)) params = append(params, context, funcPtr) hasContext = true prefix = b.fn.RelString(nil) @@ -97,14 +99,14 @@ func (b *builder) createGo(instr *ssa.Go) { paramBundle := b.emitPointerPack(params) var stackSize llvm.Value - callee := b.createGoroutineStartWrapper(funcPtr, prefix, hasContext, instr.Pos()) + callee := b.createGoroutineStartWrapper(funcPtrType, funcPtr, prefix, hasContext, instr.Pos()) if b.AutomaticStackSize { // The stack size is not known until after linking. Call a dummy // function that will be replaced with a load from a special ELF // section that contains the stack size (and is modified after // linking). - stackSizeFn := b.getFunction(b.program.ImportedPackage("internal/task").Members["getGoroutineStackSize"].(*ssa.Function)) - stackSize = b.createCall(stackSizeFn, []llvm.Value{callee, llvm.Undef(b.i8ptrType)}, "stacksize") + stackSizeFnType, stackSizeFn := b.getFunction(b.program.ImportedPackage("internal/task").Members["getGoroutineStackSize"].(*ssa.Function)) + stackSize = b.createCall(stackSizeFnType, stackSizeFn, []llvm.Value{callee, llvm.Undef(b.i8ptrType)}, "stacksize") } else { // The stack size is fixed at compile time. By emitting it here as a // constant, it can be optimized. @@ -113,8 +115,8 @@ func (b *builder) createGo(instr *ssa.Go) { } stackSize = llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false) } - start := b.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function)) - b.createCall(start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.i8ptrType)}, "") + fnType, start := b.getFunction(b.program.ImportedPackage("internal/task").Members["start"].(*ssa.Function)) + b.createCall(fnType, start, []llvm.Value{callee, paramBundle, stackSize, llvm.Undef(b.i8ptrType)}, "") } // createGoroutineStartWrapper creates a wrapper for the task-based @@ -140,15 +142,16 @@ func (b *builder) createGo(instr *ssa.Go) { // to last parameter of the function) is used for this wrapper. If hasContext is // false, the parameter bundle is assumed to have no context parameter and undef // is passed instead. -func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix string, hasContext bool, pos token.Pos) llvm.Value { +func (c *compilerContext) createGoroutineStartWrapper(fnType llvm.Type, fn llvm.Value, prefix string, hasContext bool, pos token.Pos) llvm.Value { var wrapper llvm.Value builder := c.ctx.NewBuilder() defer builder.Dispose() var deadlock llvm.Value + var deadlockType llvm.Type if c.Scheduler == "asyncify" { - deadlock = c.getFunction(c.program.ImportedPackage("runtime").Members["deadlock"].(*ssa.Function)) + deadlockType, deadlock = c.getFunction(c.program.ImportedPackage("runtime").Members["deadlock"].(*ssa.Function)) } if !fn.IsAFunction().IsNil() { @@ -192,7 +195,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri } // Create the list of params for the call. - paramTypes := fn.Type().ElementType().ParamTypes() + paramTypes := fnType.ParamTypes() if !hasContext { paramTypes = paramTypes[:len(paramTypes)-1] // strip context parameter } @@ -202,10 +205,10 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri } // Create the call. - builder.CreateCall(fn, params, "") + builder.CreateCall(fnType, fn, params, "") if c.Scheduler == "asyncify" { - builder.CreateCall(deadlock, []llvm.Value{ + builder.CreateCall(deadlockType, deadlock, []llvm.Value{ llvm.Undef(c.i8ptrType), }, "") } @@ -261,7 +264,7 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri } // Get the list of parameters, with the extra parameters at the end. - paramTypes := fn.Type().ElementType().ParamTypes() + paramTypes := fnType.ParamTypes() paramTypes = append(paramTypes, fn.Type()) // the last element is the function pointer params := llvmutil.EmitPointerUnpack(builder, c.mod, wrapper.Param(0), paramTypes) @@ -270,10 +273,10 @@ func (c *compilerContext) createGoroutineStartWrapper(fn llvm.Value, prefix stri params = params[:len(params)-1] // Create the call. - builder.CreateCall(fnPtr, params, "") + builder.CreateCall(fnType, fnPtr, params, "") if c.Scheduler == "asyncify" { - builder.CreateCall(deadlock, []llvm.Value{ + builder.CreateCall(deadlockType, deadlock, []llvm.Value{ llvm.Undef(c.i8ptrType), }, "") } diff --git a/compiler/inlineasm.go b/compiler/inlineasm.go index 27b0492bc..2afb0a161 100644 --- a/compiler/inlineasm.go +++ b/compiler/inlineasm.go @@ -25,7 +25,7 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) { fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{}, false) asm := constant.StringVal(args[0].(*ssa.Const).Value) target := llvm.InlineAsm(fnType, asm, "", true, false, 0, false) - return b.CreateCall(target, nil, ""), nil + return b.CreateCall(fnType, target, nil, ""), nil } // This is a compiler builtin, which allows assembly to be called in a flexible @@ -120,7 +120,7 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) } fnType := llvm.FunctionType(outputType, argTypes, false) target := llvm.InlineAsm(fnType, asmString, strings.Join(constraints, ","), true, false, 0, false) - result := b.CreateCall(target, args, "") + result := b.CreateCall(fnType, target, args, "") if hasOutput { return result, nil } else { @@ -163,7 +163,7 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) { constraints += ",~{r1},~{r2},~{r3}" fnType := llvm.FunctionType(b.uintptrType, argTypes, false) target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false) - return b.CreateCall(target, llvmArgs, ""), nil + return b.CreateCall(fnType, target, llvmArgs, ""), nil } // This is a compiler builtin which emits an inline SVCall instruction. It can @@ -201,7 +201,7 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) { constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}" fnType := llvm.FunctionType(b.uintptrType, argTypes, false) target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0, false) - return b.CreateCall(target, llvmArgs, ""), nil + return b.CreateCall(fnType, target, llvmArgs, ""), nil } // This is a compiler builtin which emits CSR instructions. It can be one of: @@ -226,24 +226,24 @@ func (b *builder) emitCSROperation(call *ssa.CallCommon) (llvm.Value, error) { fnType := llvm.FunctionType(b.uintptrType, nil, false) asm := fmt.Sprintf("csrr $0, %d", csr) target := llvm.InlineAsm(fnType, asm, "=r", true, false, 0, false) - return b.CreateCall(target, nil, ""), nil + return b.CreateCall(fnType, target, nil, ""), nil case "Set": fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.uintptrType}, false) asm := fmt.Sprintf("csrw %d, $0", csr) target := llvm.InlineAsm(fnType, asm, "r", true, false, 0, false) - return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil + return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil case "SetBits": // Note: it may be possible to optimize this to csrrsi in many cases. fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false) asm := fmt.Sprintf("csrrs $0, %d, $1", csr) target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0, false) - return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil + return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil case "ClearBits": // Note: it may be possible to optimize this to csrrci in many cases. fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType}, false) asm := fmt.Sprintf("csrrc $0, %d, $1", csr) target := llvm.InlineAsm(fnType, asm, "=r,r", true, false, 0, false) - return b.CreateCall(target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil + return b.CreateCall(fnType, target, []llvm.Value{b.getValue(call.Args[1])}, ""), nil default: return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name) } diff --git a/compiler/interface.go b/compiler/interface.go index b0ea71e3f..72f8952d0 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -254,12 +254,12 @@ func (c *compilerContext) getTypeMethodSet(typ types.Type) llvm.Value { method := ms.At(i) signatureGlobal := c.getMethodSignature(method.Obj().(*types.Func)) fn := c.program.MethodValue(method) - llvmFn := c.getFunction(fn) + llvmFnType, llvmFn := c.getFunction(fn) if llvmFn.IsNil() { // compiler error, so panic panic("cannot find function: " + c.getFunctionInfo(fn).linkName) } - wrapper := c.getInterfaceInvokeWrapper(fn, llvmFn) + wrapper := c.getInterfaceInvokeWrapper(fn, llvmFnType, llvmFn) methodInfo := llvm.ConstNamedStruct(interfaceMethodInfoType, []llvm.Value{ signatureGlobal, llvm.ConstPtrToInt(wrapper, c.uintptrType), @@ -361,7 +361,7 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value { // implements each method of the interface. See: // https://research.swtch.com/interfaces fn := b.getInterfaceImplementsFunc(expr.AssertedType) - commaOk = b.CreateCall(fn, []llvm.Value{actualTypeNum}, "") + commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "") } else { globalName := "reflect/types.typeid:" + getTypeCodeName(expr.AssertedType) @@ -480,7 +480,7 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value { // value, dereferences or unpacks it if necessary, and calls the real method. // If the method to wrap has a pointer receiver, no wrapping is necessary and // the function is returned directly. -func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llvm.Value) llvm.Value { +func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFnType llvm.Type, llvmFn llvm.Value) llvm.Value { wrapperName := llvmFn.Name() + "$invoke" wrapper := c.mod.NamedFunction(wrapperName) if !wrapper.IsNil() { @@ -505,9 +505,8 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv } // create wrapper function - fnType := llvmFn.Type().ElementType() - paramTypes := append([]llvm.Type{c.i8ptrType}, fnType.ParamTypes()[len(expandedReceiverType):]...) - wrapFnType := llvm.FunctionType(fnType.ReturnType(), paramTypes, false) + paramTypes := append([]llvm.Type{c.i8ptrType}, llvmFnType.ParamTypes()[len(expandedReceiverType):]...) + wrapFnType := llvm.FunctionType(llvmFnType.ReturnType(), paramTypes, false) wrapper = llvm.AddFunction(c.mod, wrapperName, wrapFnType) c.addStandardAttributes(wrapper) @@ -535,10 +534,10 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0] params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...) if llvmFn.Type().ElementType().ReturnType().TypeKind() == llvm.VoidTypeKind { - b.CreateCall(llvmFn, params, "") + b.CreateCall(llvmFnType, llvmFn, params, "") b.CreateRetVoid() } else { - ret := b.CreateCall(llvmFn, params, "ret") + ret := b.CreateCall(llvmFnType, llvmFn, params, "ret") b.CreateRet(ret) } diff --git a/compiler/interrupt.go b/compiler/interrupt.go index bcd407cd1..45c7d0748 100644 --- a/compiler/interrupt.go +++ b/compiler/interrupt.go @@ -36,7 +36,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro // Fall back to a generic error. return llvm.Value{}, b.makeError(instr.Pos(), "interrupt function must be constant") } - funcRawPtr, funcContext := b.decodeFuncValue(funcValue, nil) + _, funcRawPtr, funcContext := b.decodeFuncValue(funcValue, nil) funcPtr := llvm.ConstPtrToInt(funcRawPtr, b.uintptrType) // Create a new global of type runtime/interrupt.handle. Globals of this @@ -85,7 +85,7 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro useFnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{interrupt.Type()}, false) useFn = llvm.AddFunction(b.mod, "runtime/interrupt.use", useFnType) } - b.CreateCall(useFn, []llvm.Value{interrupt}, "") + b.CreateCall(useFn.GlobalValueType(), useFn, []llvm.Value{interrupt}, "") } return interrupt, nil diff --git a/compiler/intrinsics.go b/compiler/intrinsics.go index 0203d441b..9fedfbd67 100644 --- a/compiler/intrinsics.go +++ b/compiler/intrinsics.go @@ -55,7 +55,7 @@ func (b *builder) createMemoryCopyImpl() { params = append(params, b.getValue(param)) } params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false)) - b.CreateCall(llvmFn, params, "") + b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "") b.CreateRetVoid() } @@ -76,7 +76,7 @@ func (b *builder) createMemoryZeroImpl() { b.getValue(b.fn.Params[1]), llvm.ConstInt(b.ctx.Int1Type(), 0, false), } - b.CreateCall(llvmFn, params, "") + b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "") b.CreateRetVoid() } @@ -119,6 +119,6 @@ func (b *builder) defineMathOp() { for i, param := range b.fn.Params { args[i] = b.getValue(param) } - result := b.CreateCall(llvmFn, args, "") + result := b.CreateCall(llvmFn.GlobalValueType(), llvmFn, args, "") b.CreateRet(result) } diff --git a/compiler/llvm.go b/compiler/llvm.go index 0d2ba9da7..9540bcc63 100644 --- a/compiler/llvm.go +++ b/compiler/llvm.go @@ -312,5 +312,5 @@ func (b *builder) readStackPointer() llvm.Value { fnType := llvm.FunctionType(b.i8ptrType, nil, false) stacksave = llvm.AddFunction(b.mod, "llvm.stacksave", fnType) } - return b.CreateCall(stacksave, nil, "") + return b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, "") } diff --git a/compiler/llvmutil/llvm.go b/compiler/llvmutil/llvm.go index 74404a3e9..e73b68dad 100644 --- a/compiler/llvmutil/llvm.go +++ b/compiler/llvmutil/llvm.go @@ -39,7 +39,8 @@ func CreateTemporaryAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, n alloca = CreateEntryBlockAlloca(builder, t, name) bitcast = builder.CreateBitCast(alloca, i8ptrType, name+".bitcast") size = llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false) - builder.CreateCall(getLifetimeStartFunc(mod), []llvm.Value{size, bitcast}, "") + fnType, fn := getLifetimeStartFunc(mod) + builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "") return } @@ -54,13 +55,15 @@ func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, builder.SetInsertPointBefore(inst) bitcast := builder.CreateBitCast(alloca, i8ptrType, name+".bitcast") size := llvm.ConstInt(ctx.Int64Type(), targetData.TypeAllocSize(t), false) - builder.CreateCall(getLifetimeStartFunc(mod), []llvm.Value{size, bitcast}, "") + fnType, fn := getLifetimeStartFunc(mod) + builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "") if next := llvm.NextInstruction(inst); !next.IsNil() { builder.SetInsertPointBefore(next) } else { builder.SetInsertPointAtEnd(inst.InstructionParent()) } - builder.CreateCall(getLifetimeEndFunc(mod), []llvm.Value{size, bitcast}, "") + fnType, fn = getLifetimeEndFunc(mod) + builder.CreateCall(fnType, fn, []llvm.Value{size, bitcast}, "") return alloca } @@ -68,33 +71,34 @@ func CreateInstructionAlloca(builder llvm.Builder, mod llvm.Module, t llvm.Type, // llvm.lifetime.end intrinsic. It is commonly used together with // createTemporaryAlloca. func EmitLifetimeEnd(builder llvm.Builder, mod llvm.Module, ptr, size llvm.Value) { - builder.CreateCall(getLifetimeEndFunc(mod), []llvm.Value{size, ptr}, "") + fnType, fn := getLifetimeEndFunc(mod) + builder.CreateCall(fnType, fn, []llvm.Value{size, ptr}, "") } // getLifetimeStartFunc returns the llvm.lifetime.start intrinsic and creates it // first if it doesn't exist yet. -func getLifetimeStartFunc(mod llvm.Module) llvm.Value { +func getLifetimeStartFunc(mod llvm.Module) (llvm.Type, llvm.Value) { fn := mod.NamedFunction("llvm.lifetime.start.p0i8") ctx := mod.Context() i8ptrType := llvm.PointerType(ctx.Int8Type(), 0) + fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false) if fn.IsNil() { - fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false) fn = llvm.AddFunction(mod, "llvm.lifetime.start.p0i8", fnType) } - return fn + return fnType, fn } // getLifetimeEndFunc returns the llvm.lifetime.end intrinsic and creates it // first if it doesn't exist yet. -func getLifetimeEndFunc(mod llvm.Module) llvm.Value { +func getLifetimeEndFunc(mod llvm.Module) (llvm.Type, llvm.Value) { fn := mod.NamedFunction("llvm.lifetime.end.p0i8") ctx := mod.Context() i8ptrType := llvm.PointerType(ctx.Int8Type(), 0) + fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false) if fn.IsNil() { - fnType := llvm.FunctionType(ctx.VoidType(), []llvm.Type{ctx.Int64Type(), i8ptrType}, false) fn = llvm.AddFunction(mod, "llvm.lifetime.end.p0i8", fnType) } - return fn + return fnType, fn } // SplitBasicBlock splits a LLVM basic block into two parts. All instructions diff --git a/compiler/llvmutil/wordpack.go b/compiler/llvmutil/wordpack.go index 41d4c581d..73b1e27e2 100644 --- a/compiler/llvmutil/wordpack.go +++ b/compiler/llvmutil/wordpack.go @@ -95,14 +95,14 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, prefix string, needs // Packed data is bigger than a pointer, so allocate it on the heap. sizeValue := llvm.ConstInt(uintptrType, size, false) alloc := mod.NamedFunction("runtime.alloc") - packedHeapAlloc := builder.CreateCall(alloc, []llvm.Value{ + packedHeapAlloc := builder.CreateCall(alloc.GlobalValueType(), alloc, []llvm.Value{ sizeValue, llvm.ConstNull(i8ptrType), llvm.Undef(i8ptrType), // unused context parameter }, "") if needsStackObjects { trackPointer := mod.NamedFunction("runtime.trackPointer") - builder.CreateCall(trackPointer, []llvm.Value{ + builder.CreateCall(trackPointer.GlobalValueType(), trackPointer, []llvm.Value{ packedHeapAlloc, llvm.Undef(i8ptrType), // unused context parameter }, "") diff --git a/compiler/symbol.go b/compiler/symbol.go index c4ce6f21d..83fe050bc 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -53,11 +53,11 @@ const ( // getFunction returns the LLVM function for the given *ssa.Function, creating // it if needed. It can later be filled with compilerContext.createFunction(). -func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value { +func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) { info := c.getFunctionInfo(fn) llvmFn := c.mod.NamedFunction(info.linkName) if !llvmFn.IsNil() { - return llvmFn + return llvmFn.GlobalValueType(), llvmFn } var retType llvm.Type @@ -202,7 +202,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value { llvmFn.SetUnnamedAddr(true) } - return llvmFn + return fnType, llvmFn } // getFunctionInfo returns information about a function that is not directly diff --git a/compiler/syscall.go b/compiler/syscall.go index 0c5f1246e..66baf8260 100644 --- a/compiler/syscall.go +++ b/compiler/syscall.go @@ -44,7 +44,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { constraints += ",~{rcx},~{r11}" fnType := llvm.FunctionType(b.uintptrType, argTypes, false) target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel, false) - return b.CreateCall(target, args, ""), nil + return b.CreateCall(fnType, target, args, ""), nil case b.GOARCH == "386" && b.GOOS == "linux": // Sources: // syscall(2) man page @@ -70,7 +70,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { } fnType := llvm.FunctionType(b.uintptrType, argTypes, false) target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel, false) - return b.CreateCall(target, args, ""), nil + return b.CreateCall(fnType, target, args, ""), nil case b.GOARCH == "arm" && b.GOOS == "linux": // Implement the EABI system call convention for Linux. // Source: syscall(2) man page. @@ -102,7 +102,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { } fnType := llvm.FunctionType(b.uintptrType, argTypes, false) target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false) - return b.CreateCall(target, args, ""), nil + return b.CreateCall(fnType, target, args, ""), nil case b.GOARCH == "arm64" && b.GOOS == "linux": // Source: syscall(2) man page. args := []llvm.Value{} @@ -134,7 +134,7 @@ func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) { constraints += ",~{x16},~{x17}" // scratch registers fnType := llvm.FunctionType(b.uintptrType, argTypes, false) target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0, false) - return b.CreateCall(target, args, ""), nil + return b.CreateCall(fnType, target, args, ""), nil default: return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH) } @@ -205,9 +205,9 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) { // Note that SetLastError/GetLastError could be replaced with direct // access to the thread control block, which is probably smaller and // faster. The Go runtime does this in assembly. - b.CreateCall(setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "") - syscallResult := b.CreateCall(fnPtr, params, "") - errResult := b.CreateCall(getLastError, nil, "err") + b.CreateCall(setLastError.GlobalValueType(), setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "") + syscallResult := b.CreateCall(llvmType, fnPtr, params, "") + errResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil, "err") if b.uintptrType != b.ctx.Int32Type() { errResult = b.CreateZExt(errResult, b.uintptrType, "err.uintptr") } @@ -17,7 +17,7 @@ require ( golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 golang.org/x/tools v0.1.11 gopkg.in/yaml.v2 v2.4.0 - tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 + tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636 ) require ( @@ -64,5 +64,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc= -tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= +tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636 h1:JxtI6P/lyWHAcs/4QJWeWIbh4HntxPFONMVWvx7wf8Y= +tinygo.org/x/go-llvm v0.0.0-20220921144613-dcf4836fe636/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= diff --git a/interp/interp.go b/interp/interp.go index a1f5f507a..856f08b18 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -127,7 +127,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error { // Create a call to the package initializer (which was // previously deleted). i8undef := llvm.Undef(r.i8ptrType) - r.builder.CreateCall(fn, []llvm.Value{i8undef}, "") + r.builder.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{i8undef}, "") // Make sure that any globals touched by the package // initializer, won't be accessed by later package initializers. err := r.markExternalLoad(fn) diff --git a/interp/interpreter.go b/interp/interpreter.go index 7cee14bf4..4a4553f88 100644 --- a/interp/interpreter.go +++ b/interp/interpreter.go @@ -977,7 +977,7 @@ func (r *runner) runAtRuntime(fn *function, inst instruction, locals []value, me } } } - result = r.builder.CreateCall(llvmFn, args, inst.name) + result = r.builder.CreateCall(inst.llvmInst.CalledFunctionType(), llvmFn, args, inst.name) case llvm.Load: err := mem.markExternalLoad(operands[0]) if err != nil { diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go index 7a01c2ea7..f5b29e301 100644 --- a/transform/interface-lowering.go +++ b/transform/interface-lowering.go @@ -493,12 +493,13 @@ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *inte paramTypes = append(paramTypes, param.Type()) } calledFunctionType := function.Type() - sig := llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false), calledFunctionType.PointerAddressSpace()) + functionType := llvm.FunctionType(returnType, paramTypes, false) + sig := llvm.PointerType(functionType, calledFunctionType.PointerAddressSpace()) if sig != function.Type() { function = p.builder.CreateBitCast(function, sig, "") } - retval := p.builder.CreateCall(function, append([]llvm.Value{receiver}, params...), "") + retval := p.builder.CreateCall(functionType, function, append([]llvm.Value{receiver}, params...), "") if retval.Type().TypeKind() == llvm.VoidTypeKind { p.builder.CreateRetVoid() } else { @@ -518,7 +519,7 @@ func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *inte // importantly, it avoids undefined behavior when accidentally calling a // method on a nil interface. nilPanic := p.mod.NamedFunction("runtime.nilPanic") - p.builder.CreateCall(nilPanic, []llvm.Value{ + p.builder.CreateCall(nilPanic.GlobalValueType(), nilPanic, []llvm.Value{ llvm.Undef(llvm.PointerType(p.ctx.Int8Type(), 0)), }, "") p.builder.CreateUnreachable() diff --git a/transform/interrupt.go b/transform/interrupt.go index 3ffe7048c..2c301be01 100644 --- a/transform/interrupt.go +++ b/transform/interrupt.go @@ -91,7 +91,7 @@ func LowerInterrupts(mod llvm.Module) []error { initializer := handler.Initializer() context := llvm.ConstExtractValue(initializer, []uint32{0}) funcPtr := llvm.ConstExtractValue(initializer, []uint32{1}).Operand(0) - builder.CreateCall(funcPtr, []llvm.Value{ + builder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{ num, context, }, "") diff --git a/transform/panic.go b/transform/panic.go index e8e9a1fe9..dee3bae06 100644 --- a/transform/panic.go +++ b/transform/panic.go @@ -27,7 +27,7 @@ func ReplacePanicsWithTrap(mod llvm.Module) { panic("expected use of a panic function to be a call") } builder.SetInsertPointBefore(use) - builder.CreateCall(trap, nil, "") + builder.CreateCall(trap.GlobalValueType(), trap, nil, "") } } } diff --git a/transform/rtcalls.go b/transform/rtcalls.go index 2edfd6554..2f17f815b 100644 --- a/transform/rtcalls.go +++ b/transform/rtcalls.go @@ -165,7 +165,7 @@ func OptimizeReflectImplements(mod llvm.Module) { // Replace Implements call with the type assert call. builder.SetInsertPointBefore(call) - implements := builder.CreateCall(typeAssertFunction, []llvm.Value{ + implements := builder.CreateCall(typeAssertFunction.GlobalValueType(), typeAssertFunction, []llvm.Value{ builder.CreatePtrToInt(call.Operand(0), uintptrType, ""), // typecode to check }, "") call.ReplaceAllUsesWith(implements) diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go index aeba713d9..aedad71d0 100644 --- a/transform/wasm-abi.go +++ b/transform/wasm-abi.go @@ -124,12 +124,12 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error { // Pass a stack-allocated pointer as the first parameter // where the return value should be stored, instead of using // the regular return value. - builder.CreateCall(externalFn, callParams, callName) + builder.CreateCall(externalFnType, externalFn, callParams, callName) returnValue := builder.CreateLoad(retvalAlloca, "retval") call.ReplaceAllUsesWith(returnValue) call.EraseFromParentAsInstruction() } else { - newCall := builder.CreateCall(externalFn, callParams, callName) + newCall := builder.CreateCall(externalFnType, externalFn, callParams, callName) call.ReplaceAllUsesWith(newCall) call.EraseFromParentAsInstruction() } @@ -156,7 +156,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error { } callParams = append(callParams, paramValue) } - retval := builder.CreateCall(fn, callParams, "") + retval := builder.CreateCall(fn.GlobalValueType(), fn, callParams, "") if retval.Type().TypeKind() == llvm.VoidTypeKind { builder.CreateRetVoid() } else { |