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
+13 -11
View File
@@ -47,20 +47,15 @@ func (b *builder) createGo(instr *ssa.Go) {
return
}
// Get all function parameters to pass to the goroutine.
var params []llvm.Value
for _, param := range instr.Call.Args {
params = append(params, b.getGoroutineCallArgument(param)...)
}
var prefix string
var funcPtr llvm.Value
var funcType llvm.Type
var context llvm.Value
hasContext := false
if callee := instr.Call.StaticCallee(); callee != nil {
// Static callee is known. This makes it easier to start a new
// goroutine.
var context llvm.Value
switch value := instr.Call.Value.(type) {
case *ssa.Function:
// Goroutine call is regular function call. No context is necessary.
@@ -73,7 +68,6 @@ func (b *builder) createGo(instr *ssa.Go) {
panic("StaticCallee returned an unexpected value")
}
if !context.IsNil() {
params = append(params, context) // context parameter
hasContext = true
}
funcType, funcPtr = b.getFunction(callee)
@@ -84,22 +78,30 @@ func (b *builder) createGo(instr *ssa.Go) {
itfValue := b.CreateExtractValue(itf, 1, "")
funcPtr = b.getInvokeFunction(&instr.Call)
funcType = funcPtr.GlobalValueType()
params = append([]llvm.Value{itfValue}, params...) // start with receiver
params = append(params, itfTypeCode) // end with typecode
params = append(params, itfValue)
context = itfTypeCode
} else {
// This is a function pointer.
// At the moment, two extra params are passed to the newly started
// goroutine:
// * The function context, for closures.
// * The function pointer (for tasks).
var context llvm.Value
funcPtr, context = b.decodeFuncValue(b.getValue(instr.Call.Value, getPos(instr)))
funcType = b.getLLVMFunctionType(instr.Call.Value.Type().Underlying().(*types.Signature))
params = append(params, context, funcPtr)
hasContext = true
prefix = b.getFunctionInfo(b.fn).linkName
}
for _, param := range instr.Call.Args {
params = append(params, b.getGoroutineCallArgument(param)...)
}
if !context.IsNil() {
params = append(params, context)
}
if hasContext && instr.Call.StaticCallee() == nil {
params = append(params, funcPtr)
}
paramBundle := b.emitPointerPack(params, instr.Pos())
var stackSize llvm.Value
callee := b.createGoroutineStartWrapper(funcType, funcPtr, prefix, hasContext, false, instr.Pos())