Răsfoiți Sursa

Add `intrinsics.simd_indices`

gingerBill 4 luni în urmă
părinte
comite
36945079f8
3 a modificat fișierele cu 53 adăugiri și 0 ștergeri
  1. 31 0
      src/check_builtin.cpp
  2. 5 0
      src/checker_builtin_procs.hpp
  3. 17 0
      src/llvm_backend_proc.cpp

+ 31 - 0
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;
 

+ 5 - 0
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},

+ 17 - 0
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]);