From 019084a17fb179a823a213591b016a43620e47ce Mon Sep 17 00:00:00 2001 From: Jon Lipstate Date: Sat, 5 Jul 2025 13:55:14 -0700 Subject: table lookup intrinsic --- src/check_builtin.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 9f9787b61..c7386a97d 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1150,6 +1150,58 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_table_lookup: + { + if (ce->args.count != 2) { + error(call, "'%.*s' expected 2 arguments, got %td", LIT(builtin_name), ce->args.count); + return false; + } + + Operand table = {}; + Operand indices = {}; + check_expr(c, &table, ce->args[0]); if (table.mode == Addressing_Invalid) return false; + check_expr_with_type_hint(c, &indices, ce->args[1], table.type); if (indices.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(table.type)) { + error(table.expr, "'%.*s' expected a simd vector type for table", LIT(builtin_name)); + return false; + } + if (!is_type_simd_vector(indices.type)) { + error(indices.expr, "'%.*s' expected a simd vector type for indices", LIT(builtin_name)); + return false; + } + + Type *table_elem = base_array_type(table.type); + Type *indices_elem = base_array_type(indices.type); + + if (!is_type_integer(table_elem)) { + gbString table_str = type_to_string(table.type); + error(table.expr, "'%.*s' expected table to be a simd vector of integers, got '%s'", LIT(builtin_name), table_str); + gb_string_free(table_str); + return false; + } + + if (!is_type_integer(indices_elem)) { + gbString indices_str = type_to_string(indices.type); + error(indices.expr, "'%.*s' expected indices to be a simd vector of integers, got '%s'", LIT(builtin_name), indices_str); + gb_string_free(indices_str); + return false; + } + + if (!are_types_identical(table.type, indices.type)) { + gbString table_str = type_to_string(table.type); + gbString indices_str = type_to_string(indices.type); + error(indices.expr, "'%.*s' expected table and indices to have the same type, got '%s' vs '%s'", LIT(builtin_name), table_str, indices_str); + gb_string_free(indices_str); + gb_string_free(table_str); + return false; + } + + operand->mode = Addressing_Value; + operand->type = table.type; + return true; + } + case BuiltinProc_simd_ceil: case BuiltinProc_simd_floor: case BuiltinProc_simd_trunc: -- cgit v1.2.3 From 8cbf75c928e91a93fbd0ab48877c5f32afa3a9f4 Mon Sep 17 00:00:00 2001 From: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com> Date: Fri, 11 Jul 2025 17:03:49 +0200 Subject: Add type_enum_is_contiguous intrinsic --- base/intrinsics/intrinsics.odin | 3 +++ src/check_builtin.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 4 ++++ 3 files changed, 55 insertions(+) (limited to 'src/check_builtin.cpp') diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index c1d16c5e4..20a7f4a84 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -213,6 +213,9 @@ type_is_subtype_of :: proc($T, $U: typeid) -> bool --- type_field_index_of :: proc($T: typeid, $name: string) -> uintptr --- +// Contiguous as in having a set of constants, when sorted, the difference between consecutive values is only 0 or 1 +type_enum_is_contiguous :: proc($T: typeid) -> bool where type_is_enum(T) --- + type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) --- type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) --- diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 9f9787b61..70848cec6 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1,5 +1,11 @@ typedef bool (BuiltinTypeIsProc)(Type *t); +gb_internal int enum_constant_entity_cmp(void const* a, void const* b) { + BigInt bi = (*cast(Entity const **)a)->Constant.value.value_integer; + BigInt bj = (*cast(Entity const **)b)->Constant.value.value_integer; + return big_int_cmp(&bi, &bj); +} + gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_boolean_end - BuiltinProc__type_simple_boolean_begin] = { nullptr, // BuiltinProc__type_simple_boolean_begin @@ -6919,6 +6925,48 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_type_enum_is_contiguous: + { + Operand op = {}; + Type *bt = check_type(c, ce->args[0]); + Type *type = base_type(bt); + if (type == nullptr || type == t_invalid) { + error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + if (!is_type_enum(type)) { + gbString t = type_to_string(type); + error(ce->args[0], "Expected an enum type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + // sort enum fields in place in ascending order + Array enum_constants = type->Enum.fields; + array_sort(enum_constants, enum_constant_entity_cmp); + + BigInt minus_one = big_int_make_i64(-1); + BigInt diff = {}; + + bool contiguous = true; + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + + for (isize i = 0; i < enum_constants.count - 1; i++) { + BigInt curr = enum_constants[i]->Constant.value.value_integer; + BigInt next = enum_constants[i + 1]->Constant.value.value_integer; + big_int_sub(&diff, &curr, &next); + + if (!big_int_is_zero(&diff) && big_int_cmp(&diff, &minus_one) != 0) { + contiguous = false; + break; + } + } + + operand->value = exact_value_bool(contiguous); + break; + } + case BuiltinProc_type_equal_proc: { Operand op = {}; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 90652cb0b..38d49e330 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -325,6 +325,8 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_bit_set_backing_type, + BuiltinProc_type_enum_is_contiguous, + BuiltinProc_type_equal_proc, BuiltinProc_type_hasher_proc, BuiltinProc_type_map_info, @@ -678,6 +680,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_bit_set_backing_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_enum_is_contiguous"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics }, + {STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_map_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, -- cgit v1.2.3 From 64bb0d1c7d03d0ce3a1643401009c528ec9ac296 Mon Sep 17 00:00:00 2001 From: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com> Date: Fri, 11 Jul 2025 19:38:01 +0200 Subject: Allocate temp array instead of sorting in place --- src/check_builtin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 70848cec6..041e89afd 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -6941,8 +6941,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } - // sort enum fields in place in ascending order - Array enum_constants = type->Enum.fields; + auto enum_constants = array_make(temporary_allocator(), type->Enum.fields.count); + array_copy(&enum_constants, type->Enum.fields, 0); array_sort(enum_constants, enum_constant_entity_cmp); BigInt minus_one = big_int_make_i64(-1); -- cgit v1.2.3 From 2dd0b7528926f9ea275bdbd9b6654a3e1600ac54 Mon Sep 17 00:00:00 2001 From: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com> Date: Fri, 11 Jul 2025 21:07:28 +0200 Subject: Fix BigInt leaking --- src/check_builtin.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 041e89afd..4223419a5 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -6946,6 +6946,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As array_sort(enum_constants, enum_constant_entity_cmp); BigInt minus_one = big_int_make_i64(-1); + defer (big_int_dealloc(&minus_one)); BigInt diff = {}; bool contiguous = true; @@ -6956,6 +6957,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As BigInt curr = enum_constants[i]->Constant.value.value_integer; BigInt next = enum_constants[i + 1]->Constant.value.value_integer; big_int_sub(&diff, &curr, &next); + defer (big_int_dealloc(&diff)); if (!big_int_is_zero(&diff) && big_int_cmp(&diff, &minus_one) != 0) { contiguous = false; -- cgit v1.2.3 From 980370a24bb4eb5bddd88097ef6afbda452bffa0 Mon Sep 17 00:00:00 2001 From: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com> Date: Fri, 11 Jul 2025 21:23:21 +0200 Subject: Add union kind assertion to enum_constant_entity_cmp --- src/check_builtin.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 4223419a5..b833c7014 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1,9 +1,12 @@ typedef bool (BuiltinTypeIsProc)(Type *t); gb_internal int enum_constant_entity_cmp(void const* a, void const* b) { - BigInt bi = (*cast(Entity const **)a)->Constant.value.value_integer; - BigInt bj = (*cast(Entity const **)b)->Constant.value.value_integer; - return big_int_cmp(&bi, &bj); + Entity const *ea = *(cast(Entity const **)a); + Entity const *eb = *(cast(Entity const **)b); + GB_ASSERT(ea->kind == Entity_Constant && eb->kind == Entity_Constant); + GB_ASSERT(ea->Constant.value.kind == ExactValue_Integer && eb->Constant.value.kind == ExactValue_Integer); + + return big_int_cmp(&ea->Constant.value.value_integer, &eb->Constant.value.value_integer); } gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_boolean_end - BuiltinProc__type_simple_boolean_begin] = { -- cgit v1.2.3 From ecd41b155db7a1ed93923ddc296fab1036e14392 Mon Sep 17 00:00:00 2001 From: Jon Lipstate Date: Wed, 16 Jul 2025 21:54:24 -0700 Subject: rename table_lookup to runtime_swizzle --- base/intrinsics/intrinsics.odin | 2 +- core/simd/simd.odin | 6 +++--- src/check_builtin.cpp | 4 ++-- src/checker_builtin_procs.hpp | 4 ++-- src/llvm_backend_proc.cpp | 20 ++++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 9edf7bcd8..d2ed95ab3 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -310,7 +310,7 @@ simd_indices :: proc($T: typeid/#simd[$N]$E) -> T where type_is_numeric(T) --- simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T --- simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T --- -simd_table_lookup :: proc(table: #simd[N]T, indices: #simd[N]T) -> #simd[N]T where type_is_integer(T) --- +simd_runtime_swizzle :: proc(table: #simd[N]T, indices: #simd[N]T) -> #simd[N]T where type_is_integer(T) --- // Lane-wise operations simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float --- diff --git a/core/simd/simd.odin b/core/simd/simd.odin index eb4912e58..303eceb97 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -2481,15 +2481,15 @@ Example: import "core:simd" import "core:fmt" - table_lookup_example :: proc() { + runtime_swizzle_example :: proc() { table := simd.u8x16{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} indices := simd.u8x16{15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} - result := simd.table_lookup(table, indices) + result := simd.runtime_swizzle(table, indices) fmt.println(result) // Expected: {15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} } */ -table_lookup :: intrinsics.simd_table_lookup +runtime_swizzle :: intrinsics.simd_runtime_swizzle /* Compute the square root of each lane in a SIMD vector. diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index c7386a97d..d786afb8e 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1150,7 +1150,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } - case BuiltinProc_simd_table_lookup: + case BuiltinProc_simd_runtime_swizzle: { if (ce->args.count != 2) { error(call, "'%.*s' expected 2 arguments, got %td", LIT(builtin_name), ce->args.count); @@ -1163,7 +1163,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan check_expr_with_type_hint(c, &indices, ce->args[1], table.type); if (indices.mode == Addressing_Invalid) return false; if (!is_type_simd_vector(table.type)) { - error(table.expr, "'%.*s' expected a simd vector type for table", LIT(builtin_name)); + error(table.expr, "'%.*s' expected a simd vector type for runtime swizzle", LIT(builtin_name)); return false; } if (!is_type_simd_vector(indices.type)) { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 59fc84a4e..8898d4c11 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -191,7 +191,7 @@ BuiltinProc__simd_begin, BuiltinProc_simd_shuffle, BuiltinProc_simd_select, - BuiltinProc_simd_table_lookup, + BuiltinProc_simd_runtime_swizzle, BuiltinProc_simd_ceil, BuiltinProc_simd_floor, @@ -551,7 +551,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_shuffle"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_select"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("simd_table_lookup"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_runtime_swizzle"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_ceil") , 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_floor"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 1fe8a15fe..a7766cab2 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1721,7 +1721,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } - case BuiltinProc_simd_table_lookup: + case BuiltinProc_simd_runtime_swizzle: { LLVMValueRef table = arg0.value; LLVMValueRef indices = lb_build_expr(p, ce->args[1]).value; @@ -1734,11 +1734,11 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn // Determine strategy based on element size and target architecture char const *intrinsic_name = nullptr; - bool use_hardware_table_lookup = false; + bool use_hardware_runtime_swizzle = false; // 8-bit elements: Use dedicated table lookup instructions if (elem_size == 1) { - use_hardware_table_lookup = true; + use_hardware_runtime_swizzle = true; if (build_context.metrics.arch == TargetArch_amd64 || build_context.metrics.arch == TargetArch_i386) { // x86/x86-64: Use pshufb intrinsics @@ -1753,7 +1753,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn intrinsic_name = "llvm.x86.avx512.pshuf.b.512"; break; default: - use_hardware_table_lookup = false; + use_hardware_runtime_swizzle = false; break; } } else if (build_context.metrics.arch == TargetArch_arm64) { @@ -1772,7 +1772,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn intrinsic_name = "llvm.aarch64.neon.tbl4"; break; default: - use_hardware_table_lookup = false; + use_hardware_runtime_swizzle = false; break; } } else if (build_context.metrics.arch == TargetArch_arm32) { @@ -1791,7 +1791,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn intrinsic_name = "llvm.arm.neon.vtbl4"; break; default: - use_hardware_table_lookup = false; + use_hardware_runtime_swizzle = false; break; } } else if (build_context.metrics.arch == TargetArch_wasm32 || build_context.metrics.arch == TargetArch_wasm64p32) { @@ -1799,14 +1799,14 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn if (count == 16) { intrinsic_name = "llvm.wasm.swizzle"; } else { - use_hardware_table_lookup = false; + use_hardware_runtime_swizzle = false; } } else { - use_hardware_table_lookup = false; + use_hardware_runtime_swizzle = false; } } - if (use_hardware_table_lookup && intrinsic_name != nullptr) { + if (use_hardware_runtime_swizzle && intrinsic_name != nullptr) { // Use dedicated hardware table lookup instruction // Check if required target features are enabled @@ -1932,7 +1932,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } else { // Features not enabled, fall back to emulation - use_hardware_table_lookup = false; + use_hardware_runtime_swizzle = false; } } -- cgit v1.2.3 From 3e5de5f705c91812f0cd49df813f75144be6598a Mon Sep 17 00:00:00 2001 From: Jon Lipstate Date: Wed, 16 Jul 2025 23:23:11 -0700 Subject: add did you mean for card/len --- src/check_builtin.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index b833c7014..5baf67135 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2333,7 +2333,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (mode == Addressing_Invalid) { gbString t = type_to_string(operand->type); - error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t); + if (is_type_bit_set(op_type) && id == BuiltinProc_len) { + error(call, "'%.*s' is not supported for '%s', did you mean 'card'?", LIT(builtin_name), t); + } else { + error(call, "'%.*s' is not supported for '%s'", LIT(builtin_name), t); + } return false; } -- cgit v1.2.3 From 6c81df82a68a2e573ed119f6b6ebd4cd98463ae6 Mon Sep 17 00:00:00 2001 From: Jon Lipstate Date: Wed, 16 Jul 2025 23:43:41 -0700 Subject: cleanup langauge / errors about table vs swizzle --- src/check_builtin.cpp | 32 ++++++++++++------------ src/llvm_backend_proc.cpp | 62 +++++++++++++++++++++++------------------------ 2 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index d786afb8e..89dc8fb33 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1157,27 +1157,27 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return false; } - Operand table = {}; + Operand src = {}; Operand indices = {}; - check_expr(c, &table, ce->args[0]); if (table.mode == Addressing_Invalid) return false; - check_expr_with_type_hint(c, &indices, ce->args[1], table.type); if (indices.mode == Addressing_Invalid) return false; + check_expr(c, &src, ce->args[0]); if (src.mode == Addressing_Invalid) return false; + check_expr_with_type_hint(c, &indices, ce->args[1], src.type); if (indices.mode == Addressing_Invalid) return false; - if (!is_type_simd_vector(table.type)) { - error(table.expr, "'%.*s' expected a simd vector type for runtime swizzle", LIT(builtin_name)); + if (!is_type_simd_vector(src.type)) { + error(src.expr, "'%.*s' expected first argument to be a simd vector", LIT(builtin_name)); return false; } if (!is_type_simd_vector(indices.type)) { - error(indices.expr, "'%.*s' expected a simd vector type for indices", LIT(builtin_name)); + error(indices.expr, "'%.*s' expected second argument (indices) to be a simd vector", LIT(builtin_name)); return false; } - Type *table_elem = base_array_type(table.type); + Type *src_elem = base_array_type(src.type); Type *indices_elem = base_array_type(indices.type); - if (!is_type_integer(table_elem)) { - gbString table_str = type_to_string(table.type); - error(table.expr, "'%.*s' expected table to be a simd vector of integers, got '%s'", LIT(builtin_name), table_str); - gb_string_free(table_str); + if (!is_type_integer(src_elem)) { + gbString src_str = type_to_string(src.type); + error(src.expr, "'%.*s' expected first argument to be a simd vector of integers, got '%s'", LIT(builtin_name), src_str); + gb_string_free(src_str); return false; } @@ -1188,17 +1188,17 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return false; } - if (!are_types_identical(table.type, indices.type)) { - gbString table_str = type_to_string(table.type); + if (!are_types_identical(src.type, indices.type)) { + gbString src_str = type_to_string(src.type); gbString indices_str = type_to_string(indices.type); - error(indices.expr, "'%.*s' expected table and indices to have the same type, got '%s' vs '%s'", LIT(builtin_name), table_str, indices_str); + error(indices.expr, "'%.*s' expected both arguments to have the same type, got '%s' vs '%s'", LIT(builtin_name), src_str, indices_str); gb_string_free(indices_str); - gb_string_free(table_str); + gb_string_free(src_str); return false; } operand->mode = Addressing_Value; - operand->type = table.type; + operand->type = src.type; return true; } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index a7766cab2..5894a1844 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1723,7 +1723,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn case BuiltinProc_simd_runtime_swizzle: { - LLVMValueRef table = arg0.value; + LLVMValueRef src = arg0.value; LLVMValueRef indices = lb_build_expr(p, ce->args[1]).value; Type *vt = arg0.type; @@ -1807,7 +1807,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn } if (use_hardware_runtime_swizzle && intrinsic_name != nullptr) { - // Use dedicated hardware table lookup instruction + // Use dedicated hardware swizzle instruction // Check if required target features are enabled bool features_enabled = true; @@ -1834,7 +1834,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn } } } else if (build_context.metrics.arch == TargetArch_arm64 || build_context.metrics.arch == TargetArch_arm32) { - // ARM/ARM64 feature checking - NEON is required for all table lookups + // ARM/ARM64 feature checking - NEON is required for all table/swizzle ops if (!check_target_feature_is_enabled(str_lit("neon"), nullptr)) { features_enabled = false; } @@ -1856,77 +1856,77 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), str_lit("512")); } } else if (build_context.metrics.arch == TargetArch_arm64) { - // ARM64 function attributes - enable NEON for table lookup instructions + // ARM64 function attributes - enable NEON for swizzle instructions lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+neon")); - // Set appropriate vector width for multi-table operations + // Set appropriate vector width for multi-swizzle operations if (count >= 32) { lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("min-legal-vector-width"), str_lit("256")); } } else if (build_context.metrics.arch == TargetArch_arm32) { - // ARM32 function attributes - enable NEON for table lookup instructions + // ARM32 function attributes - enable NEON for swizzle instructions lb_add_attribute_to_proc_with_string(p->module, p->value, str_lit("target-features"), str_lit("+neon")); } - // Handle ARM's multi-table intrinsics by splitting the table vector + // Handle ARM's multi-swizzle intrinsics by splitting the src vector if (build_context.metrics.arch == TargetArch_arm64 && count > 16) { - // ARM64 TBL2/TBL3/TBL4: Split table into multiple 16-byte vectors + // ARM64 TBL2/TBL3/TBL4: Split src into multiple 16-byte vectors int num_tables = cast(int)(count / 16); - GB_ASSERT_MSG(count % 16 == 0, "ARM64 table size must be multiple of 16 bytes, got %lld bytes", count); + GB_ASSERT_MSG(count % 16 == 0, "ARM64 src size must be multiple of 16 bytes, got %lld bytes", count); GB_ASSERT_MSG(num_tables <= 4, "ARM64 NEON supports maximum 4 tables (tbl4), got %d tables for %lld-byte vector", num_tables, count); - LLVMValueRef table_parts[4]; // Max 4 tables for tbl4 + LLVMValueRef src_parts[4]; // Max 4 tables for tbl4 for (int i = 0; i < num_tables; i++) { - // Extract 16-byte slice from the larger table + // Extract 16-byte slice from the larger src LLVMValueRef indices_for_extract[16]; for (int j = 0; j < 16; j++) { indices_for_extract[j] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), i * 16 + j, false); } LLVMValueRef extract_mask = LLVMConstVector(indices_for_extract, 16); - table_parts[i] = LLVMBuildShuffleVector(p->builder, table, LLVMGetUndef(LLVMTypeOf(table)), extract_mask, ""); + src_parts[i] = LLVMBuildShuffleVector(p->builder, src, LLVMGetUndef(LLVMTypeOf(src)), extract_mask, ""); } // Call appropriate ARM64 tbl intrinsic if (count == 32) { - LLVMValueRef args[3] = { table_parts[0], table_parts[1], indices }; + LLVMValueRef args[3] = { src_parts[0], src_parts[1], indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, 3, nullptr, 0); } else if (count == 48) { - LLVMValueRef args[4] = { table_parts[0], table_parts[1], table_parts[2], indices }; + LLVMValueRef args[4] = { src_parts[0], src_parts[1], src_parts[2], indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, 4, nullptr, 0); } else if (count == 64) { - LLVMValueRef args[5] = { table_parts[0], table_parts[1], table_parts[2], table_parts[3], indices }; + LLVMValueRef args[5] = { src_parts[0], src_parts[1], src_parts[2], src_parts[3], indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, 5, nullptr, 0); } } else if (build_context.metrics.arch == TargetArch_arm32 && count > 8) { - // ARM32 VTBL2/VTBL3/VTBL4: Split table into multiple 8-byte vectors + // ARM32 VTBL2/VTBL3/VTBL4: Split src into multiple 8-byte vectors int num_tables = cast(int)count / 8; - GB_ASSERT_MSG(count % 8 == 0, "ARM32 table size must be multiple of 8 bytes, got %lld bytes", count); + GB_ASSERT_MSG(count % 8 == 0, "ARM32 src size must be multiple of 8 bytes, got %lld bytes", count); GB_ASSERT_MSG(num_tables <= 4, "ARM32 NEON supports maximum 4 tables (vtbl4), got %d tables for %lld-byte vector", num_tables, count); - LLVMValueRef table_parts[4]; // Max 4 tables for vtbl4 + LLVMValueRef src_parts[4]; // Max 4 tables for vtbl4 for (int i = 0; i < num_tables; i++) { - // Extract 8-byte slice from the larger table + // Extract 8-byte slice from the larger src LLVMValueRef indices_for_extract[8]; for (int j = 0; j < 8; j++) { indices_for_extract[j] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), i * 8 + j, false); } LLVMValueRef extract_mask = LLVMConstVector(indices_for_extract, 8); - table_parts[i] = LLVMBuildShuffleVector(p->builder, table, LLVMGetUndef(LLVMTypeOf(table)), extract_mask, ""); + src_parts[i] = LLVMBuildShuffleVector(p->builder, src, LLVMGetUndef(LLVMTypeOf(src)), extract_mask, ""); } // Call appropriate ARM32 vtbl intrinsic if (count == 16) { - LLVMValueRef args[3] = { table_parts[0], table_parts[1], indices }; + LLVMValueRef args[3] = { src_parts[0], src_parts[1], indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, 3, nullptr, 0); } else if (count == 24) { - LLVMValueRef args[4] = { table_parts[0], table_parts[1], table_parts[2], indices }; + LLVMValueRef args[4] = { src_parts[0], src_parts[1], src_parts[2], indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, 4, nullptr, 0); } else if (count == 32) { - LLVMValueRef args[5] = { table_parts[0], table_parts[1], table_parts[2], table_parts[3], indices }; + LLVMValueRef args[5] = { src_parts[0], src_parts[1], src_parts[2], src_parts[3], indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, 5, nullptr, 0); } } else { - // Single-table case (x86, WebAssembly, ARM single-table) - LLVMValueRef args[2] = { table, indices }; + // Single runtime swizzle case (x86, WebAssembly, ARM single-table) + LLVMValueRef args[2] = { src, indices }; res.value = lb_call_intrinsic(p, intrinsic_name, args, gb_count_of(args), nullptr, 0); } return res; @@ -1948,16 +1948,16 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn LLVMValueRef index_mask; if (elem_size == 1) { - // 8-bit: mask to table size (like pshufb behavior) + // 8-bit: mask to src size (like pshufb behavior) index_mask = LLVMConstInt(elem_llvm_type, max_index, false); } else if (elem_size == 2) { - // 16-bit: mask to table size + // 16-bit: mask to src size index_mask = LLVMConstInt(elem_llvm_type, max_index, false); } else if (elem_size == 4) { - // 32-bit: mask to table size + // 32-bit: mask to src size index_mask = LLVMConstInt(elem_llvm_type, max_index, false); } else { - // 64-bit: mask to table size + // 64-bit: mask to src size index_mask = LLVMConstInt(elem_llvm_type, max_index, false); } @@ -1978,11 +1978,11 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn index_i32 = masked_index; } - values[i] = LLVMBuildExtractElement(p->builder, table, index_i32, ""); + values[i] = LLVMBuildExtractElement(p->builder, src, index_i32, ""); } // Build result vector - res.value = LLVMGetUndef(LLVMTypeOf(table)); + res.value = LLVMGetUndef(LLVMTypeOf(src)); for (i64 i = 0; i < count; i++) { LLVMValueRef idx_i = LLVMConstInt(i32_type, cast(unsigned)i, false); res.value = LLVMBuildInsertElement(p->builder, res.value, values[i], idx_i, ""); -- cgit v1.2.3