From 5f0251fec24dc72eb4331ce4043ff75033fc6e77 Mon Sep 17 00:00:00 2001 From: kalsprite Date: Sat, 15 Aug 2026 22:44:52 -0700 Subject: [PATCH] 5791,6748 --- src/check_builtin.cpp | 13 +++------ tests/internal/test_simd_lane_counts.odin | 33 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index ed35a928a..f67c06dcb 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1305,10 +1305,6 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan if (!check_index_value(c, x.type, false, ce->args[1], max_count, &value)) { return false; } - if (max_count < 0) { - error(ce->args[1], "'%.*s' expected a constant integer index, got '%lld'", LIT(builtin_name), cast(long long)value); - return false; - } operand->mode = Addressing_Value; operand->type = elem; @@ -1330,10 +1326,6 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan if (!check_index_value(c, x.type, false, ce->args[1], max_count, &value)) { return false; } - if (max_count < 0) { - error(ce->args[1], "'%.*s' expected a constant integer index, got '%lld'", LIT(builtin_name), cast(long long)value); - return false; - } Operand y = {}; check_expr_with_type_hint(c, &y, ce->args[2], elem); if (y.mode == Addressing_Invalid) return false; @@ -1801,12 +1793,13 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan } Operand offset = {}; check_expr(c, &offset, ce->args[1]); if (offset.mode == Addressing_Invalid) return false; - convert_to_typed(c, &offset, t_i64); + // `base:intrinsics` declares the offset as `int` and does not mark it #any_int + convert_to_typed(c, &offset, t_int); if (!is_type_integer(offset.type) || offset.mode != Addressing_Constant) { error(offset.expr, "'%.*s' expected a constant integer offset", LIT(builtin_name)); return false; } - check_assignment(c, &offset, t_i64, builtin_name); + check_assignment(c, &offset, t_int, builtin_name); operand->type = x.type; operand->mode = Addressing_Value; diff --git a/tests/internal/test_simd_lane_counts.odin b/tests/internal/test_simd_lane_counts.odin index 1d06790f0..5f5ff6e49 100644 --- a/tests/internal/test_simd_lane_counts.odin +++ b/tests/internal/test_simd_lane_counts.odin @@ -170,3 +170,36 @@ simd_pairwise_aliases_are_distinct :: proc(t: ^testing.T) { testing.expect_value(t, intrinsics.simd_extract(sub, 0), i32(7)) testing.expect_value(t, intrinsics.simd_extract(sub, 1), i32(16)) } + +// The rotate offset is declared `$offset: int`; the checker demanded `i64`, so the declared +// spelling did not compile. Other integer types stay rejected -- the declaration is not #any_int. + +@(test) +simd_lanes_rotate_offset_is_int :: proc(t: ^testing.T) { + rot :: proc(v: #simd[4]u32, $offset: int) -> #simd[4]u32 { + return intrinsics.simd_lanes_rotate_right(v, offset) + } + + v: #simd[4]u32 = {0, 1, 2, 3} + r := rot(v, 1) + testing.expect_value(t, intrinsics.simd_extract(r, 0), u32(3)) + testing.expect_value(t, intrinsics.simd_extract(r, 1), u32(0)) + + l := intrinsics.simd_lanes_rotate_left(v, 1) + testing.expect_value(t, intrinsics.simd_extract(l, 0), u32(1)) + testing.expect_value(t, intrinsics.simd_extract(l, 3), u32(0)) +} + +// `simd_extract` / `simd_replace` declare a plain `idx: uint`, so a runtime index is allowed and +// lowers to a dynamic extractelement. Bounds are enforced only where the index is constant. + +@(test) +simd_extract_accepts_a_runtime_index :: proc(t: ^testing.T) { + v: #simd[4]u32 = {10, 20, 30, 40} + i := 2 + testing.expect_value(t, intrinsics.simd_extract(v, i), u32(30)) + + w := intrinsics.simd_replace(v, i, u32(99)) + testing.expect_value(t, intrinsics.simd_extract(w, 2), u32(99)) + testing.expect_value(t, intrinsics.simd_extract(w, 0), u32(10)) +}