From aef401fc9b789e8280048a6e9182d94a26cbf4b9 Mon Sep 17 00:00:00 2001 From: Urjasvi Suthar Date: Sun, 12 Jul 2026 21:29:57 +0530 Subject: [PATCH] Fix arm64 ABI: '#simd' vectors and vector aggregates not passed in registers (fixes #7010) --- src/llvm_abi.cpp | 13 +++ tests/issues/run.sh | 4 + tests/issues/test_issue_7010.c | 51 ++++++++++ tests/issues/test_issue_7010.odin | 164 ++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 tests/issues/test_issue_7010.c create mode 100644 tests/issues/test_issue_7010.odin diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 12c3ff58c..42196c8c4 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1147,6 +1147,10 @@ namespace lbAbiArm64 { case LLVMDoubleTypeKind: case LLVMPointerTypeKind: return true; + case LLVMVectorTypeKind:{ + i32 sz = lb_sizeof(type); + return sz == 8 || sz == 16; + } } return false; } @@ -1228,6 +1232,15 @@ namespace lbAbiArm64 { if (base_type_) *base_type_ = type; if (member_count_) *member_count_ = 1; return true; + case LLVMVectorTypeKind:{ + i64 sz = lb_sizeof(type); + if (sz == 8 || sz == 16){ + if (base_type_) *base_type_ = type; + if (member_count_) *member_count_ = 1; + return true; + } + return false; + } case LLVMArrayTypeKind: return is_homogenous_array(c, type, base_type_, member_count_); case LLVMStructTypeKind: diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 4ab2fbd69..b83cf7cf3 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -81,6 +81,10 @@ else fi $ODIN check ../test_issue_6979.odin -no-entry-point $COMMON + +clang -c ../test_issue_7010.c -o test_issue_7010_c.o +$ODIN test ../test_issue_7010.odin $COMMON + set +x popd diff --git a/tests/issues/test_issue_7010.c b/tests/issues/test_issue_7010.c new file mode 100644 index 000000000..ef8ae2d51 --- /dev/null +++ b/tests/issues/test_issue_7010.c @@ -0,0 +1,51 @@ +// Tests issue: https://github.com/odin-lang/Odin/issues/7010 + +// #include +// #ifdef __APPLE__ +// #include +// #else +typedef __attribute__((__ext_vector_type__(2))) float simd_float2; +typedef __attribute__((__ext_vector_type__(4))) float simd_float4; +typedef __attribute__((__ext_vector_type__(2))) unsigned int simd_uint2; +typedef struct { simd_float4 columns[4]; } simd_float4x4; +typedef struct { simd_float2 columns[4]; } simd_float4x2; +// typedef simd_float4x4 matrix_float4x4; +// #endif + +typedef struct { simd_float4 columns[5]; } simd_float5x4; + +simd_float4 c_add_vec4f32(simd_float4 a, simd_float4 b) { + return a + b; +} + +simd_uint2 c_add_vec2u32(simd_uint2 a, simd_uint2 b) { + return a + b; +} + +simd_float4x4 c_add_matrix4x4(simd_float4x4 a, simd_float4x4 b) { + simd_float4x4 copy_mat = a; + copy_mat.columns[0] += b.columns[0]; + copy_mat.columns[1] += b.columns[1]; + copy_mat.columns[2] += b.columns[2]; + copy_mat.columns[3] += b.columns[3]; + return copy_mat; +} + +simd_float5x4 c_add_matrix5x4(simd_float5x4 a, simd_float5x4 b) { + simd_float5x4 copy_mat = a; + copy_mat.columns[0] += b.columns[0]; + copy_mat.columns[1] += b.columns[1]; + copy_mat.columns[2] += b.columns[2]; + copy_mat.columns[3] += b.columns[3]; + copy_mat.columns[4] += b.columns[4]; + return copy_mat; +} + +simd_float4x2 c_add_matrix4x2(simd_float4x2 a, simd_float4x2 b) { + simd_float4x2 copy_mat = a; + copy_mat.columns[0] += b.columns[0]; + copy_mat.columns[1] += b.columns[1]; + copy_mat.columns[2] += b.columns[2]; + copy_mat.columns[3] += b.columns[3]; + return copy_mat; +} diff --git a/tests/issues/test_issue_7010.odin b/tests/issues/test_issue_7010.odin new file mode 100644 index 000000000..0cf36f7cc --- /dev/null +++ b/tests/issues/test_issue_7010.odin @@ -0,0 +1,164 @@ +// Tests issue: https://github.com/odin-lang/Odin/issues/7010 + +package test_issues + +Matrix4x4 :: struct { + columns: [4]#simd[4]f32, +} + +Matrix5x4 :: struct { + columns: [5]#simd[4]f32, +} + +Matrix4x2 :: struct { + columns: [4]#simd[2]f32, +} + +odin_add_vec4f32 :: proc (a: #simd[4]f32, b: #simd[4]f32) -> #simd[4]f32 { + return a + b +} + +odin_add_vec2u32 :: proc (a: #simd[2]u32, b: #simd[2]u32) -> #simd[2]u32 { + return a + b +} + +odin_add_matrix4x4 :: proc (a: Matrix4x4, b: Matrix4x4) -> Matrix4x4 { + copy_mat := a + copy_mat.columns[0] += b.columns[0] + copy_mat.columns[1] += b.columns[1] + copy_mat.columns[2] += b.columns[2] + copy_mat.columns[3] += b.columns[3] + return copy_mat +} + +odin_add_matrix5x4 :: proc (a: Matrix5x4, b: Matrix5x4) -> Matrix5x4 { + copy_mat := a + copy_mat.columns[0] += b.columns[0] + copy_mat.columns[1] += b.columns[1] + copy_mat.columns[2] += b.columns[2] + copy_mat.columns[3] += b.columns[3] + copy_mat.columns[4] += b.columns[4] + return copy_mat +} + +odin_add_matrix4x2 :: proc (a: Matrix4x2, b: Matrix4x2) -> Matrix4x2 { + copy_mat := a + copy_mat.columns[0] += b.columns[0] + copy_mat.columns[1] += b.columns[1] + copy_mat.columns[2] += b.columns[2] + copy_mat.columns[3] += b.columns[3] + return copy_mat +} + +foreign import ctest "build/test_issue_7010_c.o" +foreign ctest { + c_add_vec4f32 :: proc "c" (a: #simd[4]f32, b: #simd[4]f32) -> #simd[4]f32 --- + c_add_vec2u32 :: proc "c" (a: #simd[2]u32, b: #simd[2]u32) -> #simd[2]u32 --- + c_add_matrix4x4 :: proc "c" (a: Matrix4x4, b: Matrix4x4) -> Matrix4x4 --- + c_add_matrix5x4 :: proc "c" (a: Matrix5x4, b: Matrix5x4) -> Matrix5x4 --- + c_add_matrix4x2 :: proc "c" (a: Matrix4x2, b: Matrix4x2) -> Matrix4x2 --- +} + +import "core:testing" + +@test +test_simd :: proc(t: ^testing.T) { + a_f32 :#simd[4]f32 = {1.0, 2.0, 3.0, 4.0} + b_f32 :#simd[4]f32 = {4.0, 3.0, 2.0, 1.0} + + a_u32 :#simd[2]u32 = {1, 2} + b_u32 :#simd[2]u32 = {4, 3} + + mat_a_4x4: Matrix4x4 = { + {{1.0, 0.0, 0.0, 0.0}, + {0.0, 2.0, 0.0, 0.0}, + {0.0, 0.0, 3.0, 0.0}, + {0.0, 0.0, 0.0, 4.0}}, + } + + mat_b_4x4: Matrix4x4 = { + {{0.0, 0.0, 0.0, 0.0}, + {0.0, 1.0, 2.0, 0.0}, + {0.0, 3.0, 4.0, 0.0}, + {0.0, 0.0, 0.0, 0.0}}, + } + + mat_a_5x4: Matrix5x4 = { + {{1.0, 0.0, 0.0, 0.0}, + {0.0, 2.0, 0.0, 0.0}, + {0.0, 0.0, 3.0, 0.0}, + {0.0, 0.0, 0.0, 4.0}, + {1.0, 0.0, 0.0, 1.0}}, + } + + mat_b_5x4: Matrix5x4 = { + {{0.0, 0.0, 0.0, 0.0}, + {0.0, 1.0, 2.0, 0.0}, + {0.0, 3.0, 4.0, 0.0}, + {0.0, 0.0, 0.0, 0.0}, + {0.0, 1.0, 1.0, 0.0}}, + } + + mat_a_4x2: Matrix4x2 = { + {{1.0, 0.0}, + {0.0, 2.0}, + {0.0, 0.0}, + {0.0, 0.0}}, + } + + mat_b_4x2: Matrix4x2 = { + {{0.0, 0.0}, + {0.0, 1.0}, + {0.0, 3.0}, + {1.0, 0.0}}, + } + + odin_add_vec4_f32_result := odin_add_vec4f32(a_f32, b_f32) + testing.expect(t, odin_add_vec4_f32_result == {5.0, 5.0, 5.0, 5.0}) + + odin_add_vec2_u32_result := odin_add_vec2u32(a_u32, b_u32) + testing.expect(t, odin_add_vec2_u32_result == {5, 5}) + + odin_add_matrix4x4_result := odin_add_matrix4x4(mat_a_4x4, mat_b_4x4) + testing.expect(t, odin_add_matrix4x4_result == { + {{1.0, 0.0, 0.0, 0.0}, + {0.0, 3.0, 2.0, 0.0}, + {0.0, 3.0, 7.0, 0.0}, + {0.0, 0.0, 0.0, 4.0}}, + }) + + odin_add_matrix5x4_result := odin_add_matrix5x4(mat_a_5x4, mat_b_5x4) + testing.expect(t, odin_add_matrix5x4_result == { + {{1.0, 0.0, 0.0, 0.0}, + {0.0, 3.0, 2.0, 0.0}, + {0.0, 3.0, 7.0, 0.0}, + {0.0, 0.0, 0.0, 4.0}, + {1.0, 1.0, 1.0, 1.0}}, + }) + + odin_add_matrix4x2_result := odin_add_matrix4x2(mat_a_4x2, mat_b_4x2) + testing.expect(t, odin_add_matrix4x2_result == { + {{1.0, 0.0}, + {0.0, 3.0}, + {0.0, 3.0}, + {1.0, 0.0}}, + }) + + c_add_vec4_f32_result := c_add_vec4f32(a_f32, b_f32) + testing.expect(t, c_add_vec4_f32_result == odin_add_vec4_f32_result) + + c_add_vec2_u32_result := c_add_vec2u32(a_u32, b_u32) + testing.expect(t, c_add_vec2_u32_result == odin_add_vec2_u32_result) + + c_add_matrix4x4_result := c_add_matrix4x4(mat_a_4x4, mat_b_4x4) + testing.expect(t, c_add_matrix4x4_result == odin_add_matrix4x4_result) + + c_add_matrix5x4_result := c_add_matrix5x4(mat_a_5x4, mat_b_5x4) + testing.expect(t, c_add_matrix5x4_result == odin_add_matrix5x4_result) + + c_add_matrix4x2_result := c_add_matrix4x2(mat_a_4x2, mat_b_4x2) + testing.expect(t, c_add_matrix4x2_result == odin_add_matrix4x2_result) +} + +// clang -c test_issue_7010.c -o test_issue_7010_c.o +// odin test test_issue_7010.odin -file