compiler: resolve callees before lowering arguments

createFunctionCall and createGo currently lower arguments before they
determine whether the call is direct, an interface invoke, or through a
function value.

Resolve the callee, function type, and context first, then append the
arguments in the same order as before. This does not change the
generated LLVM IR.
This commit is contained in:
Jake Bailey
2026-07-14 06:22:20 -07:00
committed by Damian Gryski
parent 5ec2632461
commit deaf532d61
2 changed files with 27 additions and 21 deletions
+14 -10
View File
@@ -2090,14 +2090,10 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
}
}
var params []llvm.Value
for _, param := range instr.Args {
params = append(params, b.getValue(param, getPos(instr)))
}
// Try to call the function directly for trivially static calls.
var callee, context llvm.Value
var calleeType llvm.Type
var invokeTypecode, invokeReceiver llvm.Value
exported := false
if fn := instr.StaticCallee(); fn != nil {
calleeType, callee = b.getFunction(fn)
@@ -2127,19 +2123,18 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
exported = info.exported
} else if call, ok := instr.Value.(*ssa.Builtin); ok {
// Builtin function (append, close, delete, etc.).)
var params []llvm.Value
var argTypes []types.Type
for _, arg := range instr.Args {
argTypes = append(argTypes, arg.Type())
params = append(params, b.getValue(arg, getPos(instr)))
}
return b.createBuiltin(argTypes, params, call.Name(), instr.Pos())
} else if instr.IsInvoke() {
// Interface method call (aka invoke call).
itf := b.getValue(instr.Value, getPos(instr)) // interface value (runtime._interface)
typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode")
value := b.CreateExtractValue(itf, 1, "invoke.func.value") // receiver
// Prefix the params with receiver value and suffix with typecode.
params = append([]llvm.Value{value}, params...)
params = append(params, typecode)
invokeTypecode = b.CreateExtractValue(itf, 0, "invoke.func.typecode")
invokeReceiver = b.CreateExtractValue(itf, 1, "invoke.func.value")
callee = b.getInvokeFunction(instr)
calleeType = callee.GlobalValueType()
context = llvm.Undef(b.dataPtrType)
@@ -2153,6 +2148,15 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
b.createNilCheck(instr.Value, callee, "fpcall")
}
var params []llvm.Value
for _, param := range instr.Args {
params = append(params, b.getValue(param, getPos(instr)))
}
if instr.IsInvoke() {
params = append([]llvm.Value{invokeReceiver}, params...)
params = append(params, invokeTypecode)
}
if !exported {
// This function takes a context parameter.
// Add it to the end of the parameter list.