|
@@ -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;
|