From 5ec263246169998b52bfee8b9ca408ea534aca74 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 14 Jul 2026 06:22:02 -0700 Subject: [PATCH] compiler: share LLVM function type construction getFunction and getLLVMFunctionType duplicate the construction of LLVM result types for functions with zero, one, or multiple results. Move this code to getLLVMResultType. Also split the existing parameter expansion code into expandDirectFormalParamType so callers can request the current flattened parameter types directly. --- compiler/calls.go | 4 ++++ compiler/func.go | 35 ++++++++++++++++------------------- compiler/symbol.go | 13 +------------ 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/compiler/calls.go b/compiler/calls.go index 08952c4db..fb8238062 100644 --- a/compiler/calls.go +++ b/compiler/calls.go @@ -102,6 +102,10 @@ func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Valu // Expand an argument type to a list that can be used in a function call // parameter list. func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo { + return c.expandDirectFormalParamType(t, name, goType) +} + +func (c *compilerContext) expandDirectFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo { switch t.TypeKind() { case llvm.StructTypeKind: fieldInfos := c.flattenAggregateType(t, name, goType) diff --git a/compiler/func.go b/compiler/func.go index ed5808c72..c5a48a7fe 100644 --- a/compiler/func.go +++ b/compiler/func.go @@ -10,6 +10,21 @@ import ( "tinygo.org/x/go-llvm" ) +func (c *compilerContext) getLLVMResultType(sig *types.Signature) llvm.Type { + switch sig.Results().Len() { + case 0: + return c.ctx.VoidType() + case 1: + return c.getLLVMType(sig.Results().At(0).Type()) + default: + results := make([]llvm.Type, sig.Results().Len()) + for i := range results { + results[i] = c.getLLVMType(sig.Results().At(i).Type()) + } + return c.ctx.StructType(results, false) + } +} + // createFuncValue creates a function value from a raw function pointer with no // context. func (b *builder) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value { @@ -48,25 +63,7 @@ func (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type { // getLLVMFunctionType returns a LLVM function type for a given signature. func (c *compilerContext) getLLVMFunctionType(typ *types.Signature) llvm.Type { - // Get the return type. - var returnType llvm.Type - switch typ.Results().Len() { - case 0: - // No return values. - returnType = c.ctx.VoidType() - case 1: - // Just one return value. - returnType = c.getLLVMType(typ.Results().At(0).Type()) - default: - // Multiple return values. Put them together in a struct. - // This appears to be the common way to handle multiple return values in - // LLVM. - members := make([]llvm.Type, typ.Results().Len()) - for i := 0; i < typ.Results().Len(); i++ { - members[i] = c.getLLVMType(typ.Results().At(i).Type()) - } - returnType = c.ctx.StructType(members, false) - } + returnType := c.getLLVMResultType(typ) // Get the parameter types. var paramTypes []llvm.Type diff --git a/compiler/symbol.go b/compiler/symbol.go index 90dfc0d08..891981fb5 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -79,18 +79,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) return llvmFn.GlobalValueType(), llvmFn } - var retType llvm.Type - if fn.Signature.Results() == nil { - retType = c.ctx.VoidType() - } else if fn.Signature.Results().Len() == 1 { - retType = c.getLLVMType(fn.Signature.Results().At(0).Type()) - } else { - results := make([]llvm.Type, 0, fn.Signature.Results().Len()) - for v := range fn.Signature.Results().Variables() { - results = append(results, c.getLLVMType(v.Type())) - } - retType = c.ctx.StructType(results, false) - } + retType := c.getLLVMResultType(fn.Signature) var paramInfos []paramInfo for _, param := range getParams(fn.Signature) {