Sfoglia il codice sorgente

Restrict `swizzle` to a power of two for #simd

gingerBill 3 anni fa
parent
commit
1549d01bf7
3 ha cambiato i file con 44 aggiunte e 3 eliminazioni
  1. 35 0
      src/check_builtin.cpp
  2. 5 1
      src/check_expr.cpp
  3. 4 2
      src/check_type.cpp

+ 35 - 0
src/check_builtin.cpp

@@ -694,6 +694,36 @@ bool check_builtin_simd_operation(CheckerContext *c, Operand *operand, Ast *call
 			return true;
 		}
 		break;
+
+	// case BuiltinProc_simd_rotate_left:
+	// 	{
+	// 		Operand x = {};
+	// 		check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) { return false; }
+
+	// 		if (!is_type_simd_vector(x.type)) {
+	// 			error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name));
+	// 			return false;
+	// 		}
+	// 		Type *elem = base_array_type(x.type);
+	// 		if (!is_type_integer(elem) && !is_type_float(elem)) {
+	// 			gbString xs = type_to_string(x.type);
+	// 			error(x.expr, "'%.*s' expected a #simd type with an integer or floating-point element, got '%s'", LIT(builtin_name), xs);
+	// 			gb_string_free(xs);
+	// 			return false;
+	// 		}
+
+	// 		Operand offset = {};
+	// 		check_expr_with_type_hint(c, &offset, ce->args[1]); if (x.mode == Addressing_Invalid) { return false; }
+	// 		convert_to_typed(c, &offset, t_int);
+	// 		if (offset.mode != Addressing_Constant) {
+	// 			error(offset.expr, "'%.*s' expected a constant integer for the offset", LIT(builtin_name));
+	// 			return false;
+	// 		}
+
+	// 		operand->mode = Addressing_Value;
+	// 		operand->type = x.type;
+	// 		return true
+	// 	}
 	default:
 		GB_PANIC("Unhandled simd intrinsic: %.*s", LIT(builtin_name));
 	}
@@ -1749,6 +1779,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			operand->mode = Addressing_Value;
 		}
 
+		if (is_type_simd_vector(type) && !is_power_of_two(arg_count)) {
+			error(call, "'swizzle' with a #simd vector must have a power of two arguments, got %lld", cast(long long)arg_count);
+			return false;
+		}
+
 		operand->type = determine_swizzle_array_type(original_type, type_hint, arg_count);
 		break;
 	}

+ 5 - 1
src/check_expr.cpp

@@ -4119,7 +4119,11 @@ ExactValue get_constant_field(CheckerContext *c, Operand const *operand, Selecti
 
 Type *determine_swizzle_array_type(Type *original_type, Type *type_hint, isize new_count) {
 	Type *array_type = base_type(type_deref(original_type));
-	GB_ASSERT(array_type->kind == Type_Array);
+	GB_ASSERT(array_type->kind == Type_Array || array_type->kind == Type_SimdVector);
+	if (array_type->kind == Type_SimdVector) {
+		Type *elem_type = array_type->SimdVector.elem;
+		return alloc_type_simd_vector(new_count, elem_type);
+	}
 	Type *elem_type = array_type->Array.elem;
 
 	Type *swizzle_array_type = nullptr;

+ 4 - 2
src/check_type.cpp

@@ -2795,14 +2795,16 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
 				if (name == "soa") {
 					*type = make_soa_struct_fixed(ctx, e, at->elem, elem, count, generic_type);
 				} else if (name == "simd") {
-					if (!is_type_valid_vector_elem(elem)) {
+					if (!is_type_valid_vector_elem(elem) && !is_type_polymorphic(elem)) {
 						gbString str = type_to_string(elem);
 						error(at->elem, "Invalid element type for 'intrinsics.simd_vector', expected an integer or float with no specific endianness, got '%s'", str);
 						gb_string_free(str);
 						*type = alloc_type_array(elem, count, generic_type);
 						goto array_end;
 					}
-					if (count < 1 || !is_power_of_two(count)) {
+					if (is_type_polymorphic(elem)) {
+						count = 1;
+					} else if (count < 1 || !is_power_of_two(count)) {
 						error(at->count, "Invalid length for 'intrinsics.simd_vector', expected a power of two length, got '%lld'", cast(long long)count);
 						*type = alloc_type_array(elem, count, generic_type);
 						goto array_end;