aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2025-05-05 11:41:54 +0100
committergingerBill <bill@gingerbill.org>2025-05-05 11:41:54 +0100
commit36945079f8131973abb9e59bf642ab13c1c602be (patch)
tree9efa04de9b288285fb342bc91f5990f0d35183a0 /src
parentbc2a4dfe9dabdf55d63eddc540385b942d8b6810 (diff)
Add `intrinsics.simd_indices`
Diffstat (limited to 'src')
-rw-r--r--src/check_builtin.cpp31
-rw-r--r--src/checker_builtin_procs.hpp5
-rw-r--r--src/llvm_backend_proc.cpp17
3 files changed, 53 insertions, 0 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index f66a8605c..9d07de2b6 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -760,6 +760,36 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
return true;
}
+ case BuiltinProc_simd_indices:
+ {
+ Operand x = {};
+ check_expr_or_type(c, &x, ce->args[0], nullptr);
+ if (x.mode == Addressing_Invalid) return false;
+ if (x.mode != Addressing_Type) {
+ gbString s = expr_to_string(x.expr);
+ error(x.expr, "'%.*s' expected a simd vector type, got '%s'", LIT(builtin_name), s);
+ gb_string_free(s);
+ return false;
+ }
+ if (!is_type_simd_vector(x.type)) {
+ gbString s = type_to_string(x.type);
+ error(x.expr, "'%.*s' expected a simd vector type, got '%s'", LIT(builtin_name), s);
+ gb_string_free(s);
+ return false;
+ }
+
+ Type *elem = base_array_type(x.type);
+ if (!is_type_numeric(elem)) {
+ gbString s = type_to_string(x.type);
+ error(x.expr, "'%.*s' expected a simd vector type with a numeric element type, got '%s'", LIT(builtin_name), s);
+ gb_string_free(s);
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = x.type;
+ return true;
+ }
+
case BuiltinProc_simd_extract:
{
Operand x = {};
@@ -2059,6 +2089,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case BuiltinProc_atomic_type_is_lock_free:
case BuiltinProc_has_target_feature:
case BuiltinProc_procedure_of:
+ case BuiltinProc_simd_indices:
// NOTE(bill): The first arg may be a Type, this will be checked case by case
break;
diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp
index 40dde8240..d8ac10b11 100644
--- a/src/checker_builtin_procs.hpp
+++ b/src/checker_builtin_procs.hpp
@@ -205,6 +205,9 @@ BuiltinProc__simd_begin,
BuiltinProc_simd_masked_expand_load,
BuiltinProc_simd_masked_compress_store,
+ BuiltinProc_simd_indices,
+
+
// Platform specific SIMD intrinsics
BuiltinProc_simd_x86__MM_SHUFFLE,
BuiltinProc__simd_end,
@@ -551,6 +554,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("simd_masked_expand_load"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_masked_compress_store"), 3, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+ {STR_LIT("simd_indices"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
{STR_LIT("simd_x86__MM_SHUFFLE"), 4, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index be51f529d..7bd8dea59 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -1293,6 +1293,23 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn
lbValue res = {};
res.type = tv.type;
+ switch (builtin_id) {
+ case BuiltinProc_simd_indices: {
+ Type *type = base_type(res.type);
+ GB_ASSERT(type->kind == Type_SimdVector);
+ Type *elem = type->SimdVector.elem;
+
+ i64 count = type->SimdVector.count;
+ LLVMValueRef *scalars = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
+ for (i64 i = 0; i < count; i++) {
+ scalars[i] = lb_const_value(m, elem, exact_value_i64(i)).value;
+ }
+
+ res.value = LLVMConstVector(scalars, cast(unsigned)count);
+ return res;
+ }
+ }
+
lbValue arg0 = {}; if (ce->args.count > 0) arg0 = lb_build_expr(p, ce->args[0]);
lbValue arg1 = {}; if (ce->args.count > 1) arg1 = lb_build_expr(p, ce->args[1]);
lbValue arg2 = {}; if (ce->args.count > 2) arg2 = lb_build_expr(p, ce->args[2]);