aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--builder/build.go2
-rw-r--r--compiler/alias.go2
-rw-r--r--compiler/atomic.go4
-rw-r--r--compiler/calls.go14
-rw-r--r--compiler/compiler.go25
-rw-r--r--compiler/defer.go16
-rw-r--r--compiler/func.go8
-rw-r--r--compiler/goroutine.go33
-rw-r--r--compiler/inlineasm.go16
-rw-r--r--compiler/interface.go17
-rw-r--r--compiler/interrupt.go4
-rw-r--r--compiler/intrinsics.go6
-rw-r--r--compiler/llvm.go2
-rw-r--r--compiler/llvmutil/llvm.go24
-rw-r--r--compiler/llvmutil/wordpack.go4
-rw-r--r--compiler/symbol.go6
-rw-r--r--compiler/syscall.go14
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--interp/interp.go2
-rw-r--r--interp/interpreter.go2
-rw-r--r--transform/interface-lowering.go7
-rw-r--r--transform/interrupt.go2
-rw-r--r--transform/panic.go2
-rw-r--r--transform/rtcalls.go2
-rw-r--r--transform/wasm-abi.go6
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")
}
diff --git a/go.mod b/go.mod
index fdf686d4d..4af10427f 100644
--- a/go.mod
+++ b/go.mod
@@ -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 (
diff --git a/go.sum b/go.sum
index 3fc9cac11..401de3be9 100644
--- a/go.sum
+++ b/go.sum
@@ -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 {