mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-22 23:47:51 +00:00
Mock out simd intrinsics
This commit is contained in:
+207
-2
@@ -246,7 +246,7 @@ bool is_constant_string(CheckerContext *c, String const &builtin_name, Ast *expr
|
||||
}
|
||||
|
||||
bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
|
||||
String builtin_name = builtin_procs[id].name;
|
||||
String const &builtin_name = builtin_procs[id].name;
|
||||
|
||||
if (build_context.metrics.os != TargetOs_darwin) {
|
||||
// allow on doc generation (e.g. Metal stuff)
|
||||
@@ -409,6 +409,194 @@ bool check_atomic_memory_order_argument(CheckerContext *c, Ast *expr, String con
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool check_builtin_simd_operation(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
|
||||
ast_node(ce, CallExpr, call);
|
||||
|
||||
String const &builtin_name = builtin_procs[id].name;
|
||||
switch (id) {
|
||||
// Any numeric
|
||||
case BuiltinProc_simd_add:
|
||||
case BuiltinProc_simd_sub:
|
||||
case BuiltinProc_simd_mul:
|
||||
case BuiltinProc_simd_div:
|
||||
case BuiltinProc_simd_min:
|
||||
case BuiltinProc_simd_max:
|
||||
{
|
||||
Operand x = {};
|
||||
Operand y = {};
|
||||
check_expr(c, &x, ce->args[0]);
|
||||
check_expr(c, &y, ce->args[1]);
|
||||
if (x.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (y.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;
|
||||
}
|
||||
if (!is_type_simd_vector(y.type)) {
|
||||
error(y.expr, "'%.*s' expected a simd vector type", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
if (!are_types_identical(x.type, y.type)) {
|
||||
gbString xs = type_to_string(x.type);
|
||||
gbString ys = type_to_string(y.type);
|
||||
error(x.expr, "'%.*s' expected 2 arguments of the same type, got '%s' vs '%s'", LIT(builtin_name), xs, ys);
|
||||
gb_string_free(ys);
|
||||
gb_string_free(xs);
|
||||
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->mode = Addressing_Value;
|
||||
operand->type = x.type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Integer only
|
||||
case BuiltinProc_simd_rem:
|
||||
case BuiltinProc_simd_shl:
|
||||
case BuiltinProc_simd_shr:
|
||||
case BuiltinProc_simd_shl_masked:
|
||||
case BuiltinProc_simd_shr_masked:
|
||||
case BuiltinProc_simd_and:
|
||||
case BuiltinProc_simd_or:
|
||||
case BuiltinProc_simd_xor:
|
||||
{
|
||||
Operand x = {};
|
||||
Operand y = {};
|
||||
check_expr(c, &x, ce->args[0]);
|
||||
check_expr(c, &y, ce->args[1]);
|
||||
if (x.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (y.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;
|
||||
}
|
||||
if (!is_type_simd_vector(y.type)) {
|
||||
error(y.expr, "'%.*s' expected a simd vector type", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
if (!are_types_identical(x.type, y.type)) {
|
||||
gbString xs = type_to_string(x.type);
|
||||
gbString ys = type_to_string(y.type);
|
||||
error(x.expr, "'%.*s' expected 2 arguments of the same type, got '%s' vs '%s'", LIT(builtin_name), xs, ys);
|
||||
gb_string_free(ys);
|
||||
gb_string_free(xs);
|
||||
return false;
|
||||
}
|
||||
Type *elem = base_array_type(x.type);
|
||||
if (!is_type_integer(elem)) {
|
||||
gbString xs = type_to_string(x.type);
|
||||
error(x.expr, "'%.*s' expected a #simd type with an integer element, got '%s'", LIT(builtin_name), xs);
|
||||
gb_string_free(xs);
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = x.type;
|
||||
return true;
|
||||
}
|
||||
// Unary
|
||||
case BuiltinProc_simd_neg:
|
||||
case BuiltinProc_simd_abs:
|
||||
{
|
||||
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->mode = Addressing_Value;
|
||||
operand->type = x.type;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return integer masks
|
||||
case BuiltinProc_simd_eq:
|
||||
case BuiltinProc_simd_ne:
|
||||
case BuiltinProc_simd_lt:
|
||||
case BuiltinProc_simd_le:
|
||||
case BuiltinProc_simd_gt:
|
||||
case BuiltinProc_simd_ge:
|
||||
{
|
||||
// op(#simd[N]T, #simd[N]T) -> #simd[N]V
|
||||
// where `V` is an integer, `size_of(T) == size_of(V)`
|
||||
// `V` will all 0s if false and all 1s if true (e.g. 0x00 and 0xff for false and true, respectively)
|
||||
|
||||
Operand x = {};
|
||||
Operand y = {};
|
||||
check_expr(c, &x, ce->args[0]);
|
||||
check_expr(c, &y, ce->args[1]);
|
||||
if (x.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (y.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;
|
||||
}
|
||||
Type *vt = base_type(x.type);
|
||||
GB_ASSERT(vt->kind == Type_SimdVector);
|
||||
i64 count = vt->SimdVector.count;
|
||||
|
||||
i64 sz = type_size_of(elem);
|
||||
Type *new_elem = nullptr;
|
||||
|
||||
switch (sz) {
|
||||
case 1: new_elem = t_u8; break;
|
||||
case 2: new_elem = t_u16; break;
|
||||
case 4: new_elem = t_u32; break;
|
||||
case 8: new_elem = t_u64; break;
|
||||
case 16:
|
||||
error(x.expr, "'%.*s' not supported 128-bit integer backed simd vector types", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = alloc_type_simd_vector(count, new_elem);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
GB_PANIC("Unhandled simd intrinsic: %.*s", LIT(builtin_name));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
|
||||
ast_node(ce, CallExpr, call);
|
||||
if (ce->inlining != ProcInlining_none) {
|
||||
@@ -479,7 +667,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
break;
|
||||
}
|
||||
|
||||
String builtin_name = builtin_procs[id].name;
|
||||
String const &builtin_name = builtin_procs[id].name;
|
||||
|
||||
|
||||
if (ce->args.count > 0) {
|
||||
@@ -491,6 +679,16 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
}
|
||||
}
|
||||
|
||||
if (BuiltinProc__simd_begin < id && id < BuiltinProc__simd_end) {
|
||||
bool ok = check_builtin_simd_operation(c, operand, call, id, type_hint);
|
||||
if (!ok) {
|
||||
operand->type = t_invalid;
|
||||
}
|
||||
operand->mode = Addressing_Value;
|
||||
operand->value = {};
|
||||
return ok;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
default:
|
||||
GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name));
|
||||
@@ -2720,6 +2918,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count < 1 || !is_power_of_two(count)) {
|
||||
error(call, "Invalid length for 'intrinsics.simd_vector', expected a power of two length, got '%lld'", cast(long long)count);
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = alloc_type_simd_vector(count, elem);
|
||||
break;
|
||||
|
||||
+1
-1
@@ -2803,7 +2803,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
|
||||
goto array_end;
|
||||
}
|
||||
if (count < 1 || !is_power_of_two(count)) {
|
||||
error(at->elem, "Invalid length for 'intrinsics.simd_vector', expected a power of two length, got '%lld'", cast(long long)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;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,35 @@ enum BuiltinProcId {
|
||||
BuiltinProc_fixed_point_div_sat,
|
||||
|
||||
BuiltinProc_expect,
|
||||
|
||||
BuiltinProc__simd_begin,
|
||||
BuiltinProc_simd_add,
|
||||
BuiltinProc_simd_sub,
|
||||
BuiltinProc_simd_mul,
|
||||
BuiltinProc_simd_div,
|
||||
BuiltinProc_simd_rem,
|
||||
BuiltinProc_simd_shl, // Odin logic
|
||||
BuiltinProc_simd_shr, // Odin logic
|
||||
BuiltinProc_simd_shl_masked, // C logic
|
||||
BuiltinProc_simd_shr_masked, // C logic
|
||||
|
||||
BuiltinProc_simd_and,
|
||||
BuiltinProc_simd_or,
|
||||
BuiltinProc_simd_xor,
|
||||
|
||||
BuiltinProc_simd_neg,
|
||||
BuiltinProc_simd_abs,
|
||||
|
||||
BuiltinProc_simd_min,
|
||||
BuiltinProc_simd_max,
|
||||
|
||||
BuiltinProc_simd_eq,
|
||||
BuiltinProc_simd_ne,
|
||||
BuiltinProc_simd_lt,
|
||||
BuiltinProc_simd_le,
|
||||
BuiltinProc_simd_gt,
|
||||
BuiltinProc_simd_ge,
|
||||
BuiltinProc__simd_end,
|
||||
|
||||
// Platform specific intrinsics
|
||||
BuiltinProc_syscall,
|
||||
@@ -342,7 +371,33 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("fixed_point_div_sat"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("expect"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
|
||||
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_add"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_sub"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_mul"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_div"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_rem"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_shl"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_shr"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_shl_masked"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_shr_masked"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_and"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_or"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_xor"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_neg"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_abs"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_min"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_max"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_eq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_ne"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_lt"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_le"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_gt"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_ge"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
|
||||
|
||||
{STR_LIT("syscall"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1932,7 +1932,7 @@ bool is_type_valid_vector_elem(Type *t) {
|
||||
return false;
|
||||
}
|
||||
if (is_type_integer(t)) {
|
||||
return true;
|
||||
return !is_type_integer_128bit(t);
|
||||
}
|
||||
if (is_type_float(t)) {
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user