aboutsummaryrefslogtreecommitdiff
path: root/src/check_builtin.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-05-21 12:58:48 +0100
committergingerBill <bill@gingerbill.org>2022-05-21 12:58:48 +0100
commite48f41165c54913e07d1ab21bebb6a439524cf7c (patch)
tree904cce7fd75a4e72d34ad3f679bb0d8f9477e145 /src/check_builtin.cpp
parent9eb4cbcbd2e382a48cd612a3a22eb3ecdcff7df6 (diff)
Begin work on Atomics for wasm32 (wait and notify intrinsics)
Diffstat (limited to 'src/check_builtin.cpp')
-rw-r--r--src/check_builtin.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 9a5d1c554..65983423b 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -4473,6 +4473,99 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
}
break;
+ case BuiltinProc_wasm_memory_atomic_wait32:
+ {
+ if (!is_arch_wasm()) {
+ error(call, "'%.*s' is only allowed on wasm targets", LIT(builtin_name));
+ return false;
+ }
+
+ Operand ptr = {};
+ Operand expected = {};
+ Operand timeout = {};
+ check_expr(c, &ptr, ce->args[0]); if (ptr.mode == Addressing_Invalid) return false;
+ check_expr(c, &expected, ce->args[1]); if (expected.mode == Addressing_Invalid) return false;
+ check_expr(c, &timeout, ce->args[2]); if (timeout.mode == Addressing_Invalid) return false;
+
+ Type *t_u32_ptr = alloc_type_pointer(t_u32);
+ convert_to_typed(c, &ptr, t_u32_ptr); if (ptr.mode == Addressing_Invalid) return false;
+ convert_to_typed(c, &expected, t_u32); if (expected.mode == Addressing_Invalid) return false;
+ convert_to_typed(c, &timeout, t_i64); if (timeout.mode == Addressing_Invalid) return false;
+
+ if (!is_operand_value(ptr) || !check_is_assignable_to(c, &ptr, t_u32_ptr)) {
+ gbString e = expr_to_string(ptr.expr);
+ gbString t = type_to_string(ptr.type);
+ error(ptr.expr, "'%.*s' expected ^u32 for the memory pointer, got '%s' of type %s", LIT(builtin_name), e, t);
+ gb_string_free(t);
+ gb_string_free(e);
+ return false;
+ }
+
+ if (!is_operand_value(expected) || !check_is_assignable_to(c, &expected, t_u32)) {
+ gbString e = expr_to_string(expected.expr);
+ gbString t = type_to_string(expected.type);
+ error(expected.expr, "'%.*s' expected u32 for the 'expected' value, got '%s' of type %s", LIT(builtin_name), e, t);
+ gb_string_free(t);
+ gb_string_free(e);
+ return false;
+ }
+
+ if (!is_operand_value(timeout) || !check_is_assignable_to(c, &timeout, t_i64)) {
+ gbString e = expr_to_string(timeout.expr);
+ gbString t = type_to_string(timeout.type);
+ error(timeout.expr, "'%.*s' expected i64 for the timeout, got '%s' of type %s", LIT(builtin_name), e, t);
+ gb_string_free(t);
+ gb_string_free(e);
+ return false;
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = t_u32;
+ operand->value = {};
+ break;
+ }
+ break;
+ case BuiltinProc_wasm_memory_atomic_notify32:
+ {
+ if (!is_arch_wasm()) {
+ error(call, "'%.*s' is only allowed on wasm targets", LIT(builtin_name));
+ return false;
+ }
+
+ Operand ptr = {};
+ Operand waiters = {};
+ check_expr(c, &ptr, ce->args[0]); if (ptr.mode == Addressing_Invalid) return false;
+ check_expr(c, &waiters, ce->args[1]); if (waiters.mode == Addressing_Invalid) return false;
+
+ Type *t_u32_ptr = alloc_type_pointer(t_u32);
+ convert_to_typed(c, &ptr, t_u32_ptr); if (ptr.mode == Addressing_Invalid) return false;
+ convert_to_typed(c, &waiters, t_u32); if (waiters.mode == Addressing_Invalid) return false;
+
+ if (!is_operand_value(ptr) || !check_is_assignable_to(c, &ptr, t_u32_ptr)) {
+ gbString e = expr_to_string(ptr.expr);
+ gbString t = type_to_string(ptr.type);
+ error(ptr.expr, "'%.*s' expected ^u32 for the memory pointer, got '%s' of type %s", LIT(builtin_name), e, t);
+ gb_string_free(t);
+ gb_string_free(e);
+ return false;
+ }
+
+ if (!is_operand_value(waiters) || !check_is_assignable_to(c, &waiters, t_u32)) {
+ gbString e = expr_to_string(waiters.expr);
+ gbString t = type_to_string(waiters.type);
+ error(waiters.expr, "'%.*s' expected u32 for the 'waiters' value, got '%s' of type %s", LIT(builtin_name), e, t);
+ gb_string_free(t);
+ gb_string_free(e);
+ return false;
+ }
+
+ operand->mode = Addressing_Value;
+ operand->type = t_u32;
+ operand->value = {};
+ break;
+ }
+ break;
+
}
return true;