From 698f10bd8926187063f9b7df84f582a650a453f4 Mon Sep 17 00:00:00 2001 From: Fuad Hasan Date: Tue, 28 Apr 2026 01:09:14 +0600 Subject: [PATCH] llvm: lower array params as aggregate byval --- internal/backend/llvm/link.go | 2 ++ internal/backend/llvm/llvm.go | 5 ++++- internal/backend/llvm/lower_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/backend/llvm/link.go b/internal/backend/llvm/link.go index c4b22690..b65d565c 100644 --- a/internal/backend/llvm/link.go +++ b/internal/backend/llvm/link.go @@ -110,6 +110,8 @@ func FunctionReturnIsScalar(fn *mir.Function) bool { // Returns an error for aggregate (named struct) types. func llvmBaseType(typ typeinfo.Type) (string, error) { switch base := backend.UnwrapNamed(typ).(type) { + case *typeinfo.ApproxType: + return llvmBaseType(base.Inner) case *typeinfo.BuiltinType: if _, bits, ok := tokens.ParseIntegerBuiltin(base.Name); ok { return fmt.Sprintf("i%d", bits), nil diff --git a/internal/backend/llvm/llvm.go b/internal/backend/llvm/llvm.go index 5de0917c..cf5b99a0 100644 --- a/internal/backend/llvm/llvm.go +++ b/internal/backend/llvm/llvm.go @@ -5590,7 +5590,10 @@ func llvmFieldType(state *moduleState, typ typeinfo.Type) (string, error) { // llvmABITypeName returns the LLVM type name for function signatures, calls, globals. func llvmABITypeName(state *moduleState, typ typeinfo.Type) (string, error) { - if _, ok := backend.UnwrapNamed(typ).(*typeinfo.TupleType); ok { + switch t := backend.UnwrapNamed(typ).(type) { + case *typeinfo.ApproxType: + return llvmABITypeName(state, t.Inner) + case *typeinfo.TupleType, *typeinfo.ArrayType: size, _, err := backend.AggregateSizeAlign(aggregateLayoutContext(state), typ) if err != nil { return "", err diff --git a/internal/backend/llvm/lower_test.go b/internal/backend/llvm/lower_test.go index 15238097..99ab19f6 100644 --- a/internal/backend/llvm/lower_test.go +++ b/internal/backend/llvm/lower_test.go @@ -1362,6 +1362,30 @@ fn main(items: []i32) -> usize { } } +func TestLowerProgramFunctionArrayParamUsesByValAggregate(t *testing.T) { + root := t.TempDir() + mustWrite(t, filepath.Join(root, "main.fer"), ` +fn add(values: [2]i32) -> i32 { + return values[0] + values[1] +} + +fn main() -> i32 { + return add([2]i32{1, 2}) +} +`) + result := compiler.ParsePath(filepath.Join(root, "main.fer")) + if result.Diagnostics.HasErrors() { + t.Fatalf("unexpected diagnostics: %#v", result.Diagnostics.Diagnostics()) + } + text, err := llvmbackend.LowerProgram(testUnits(result), false) + if err != nil { + t.Fatalf("lower llvm: %v", err) + } + if !strings.Contains(text, "define i32 @main__add(ptr byval([8 x i8]) align 4 %values)") { + t.Fatalf("expected array parameter lowered as byval aggregate:\n%s", text) + } +} + func TestLowerBuiltinLenStringToLLVM(t *testing.T) { root := t.TempDir() mustWrite(t, filepath.Join(root, "main.fer"), `