Browse Source

Add extra checks to atomic intrinsics

gingerBill 3 years ago
parent
commit
1ec997461d
1 changed files with 45 additions and 0 deletions
  1. 45 0
      src/check_builtin.cpp

+ 45 - 0
src/check_builtin.cpp

@@ -3392,6 +3392,21 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			check_expr_with_type_hint(c, &x, ce->args[1], elem);
 			check_expr_with_type_hint(c, &x, ce->args[1], elem);
 			check_assignment(c, &x, elem, builtin_name);
 			check_assignment(c, &x, elem, builtin_name);
 
 
+			Type *t = type_deref(operand->type);
+			switch (id) {
+			case BuiltinProc_atomic_add:
+			case BuiltinProc_atomic_sub:
+				if (!is_type_numeric(t)) {
+					gbString str = type_to_string(t);
+					error(operand->expr, "Expected a numeric type for '%.*s', got %s", LIT(builtin_name), str);
+					gb_string_free(str);
+				} else if (is_type_different_to_arch_endianness(t)) {
+					gbString str = type_to_string(t);
+					error(operand->expr, "Expected a numeric type of the same platform endianness for '%.*s', got %s", LIT(builtin_name), str);
+					gb_string_free(str);
+				}
+			}
+
 			operand->type = elem;
 			operand->type = elem;
 			operand->mode = Addressing_Value;
 			operand->mode = Addressing_Value;
 			break;
 			break;
@@ -3419,6 +3434,22 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 				return false;
 				return false;
 			}
 			}
 
 
+			Type *t = type_deref(operand->type);
+			switch (id) {
+			case BuiltinProc_atomic_add_explicit:
+			case BuiltinProc_atomic_sub_explicit:
+				if (!is_type_numeric(t)) {
+					gbString str = type_to_string(t);
+					error(operand->expr, "Expected a numeric type for '%.*s', got %s", LIT(builtin_name), str);
+					gb_string_free(str);
+				} else if (is_type_different_to_arch_endianness(t)) {
+					gbString str = type_to_string(t);
+					error(operand->expr, "Expected a numeric type of the same platform endianness for '%.*s', got %s", LIT(builtin_name), str);
+					gb_string_free(str);
+				}
+				break;
+			}
+
 			operand->type = elem;
 			operand->type = elem;
 			operand->mode = Addressing_Value;
 			operand->mode = Addressing_Value;
 			break;
 			break;
@@ -3439,6 +3470,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			check_assignment(c, &x, elem, builtin_name);
 			check_assignment(c, &x, elem, builtin_name);
 			check_assignment(c, &y, elem, builtin_name);
 			check_assignment(c, &y, elem, builtin_name);
 
 
+			Type *t = type_deref(operand->type);
+			if (!is_type_comparable(t)) {
+				gbString str = type_to_string(t);
+				error(operand->expr, "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), str);
+				gb_string_free(str);
+			}
+
 			operand->mode = Addressing_OptionalOk;
 			operand->mode = Addressing_OptionalOk;
 			operand->type = elem;
 			operand->type = elem;
 			break;
 			break;
@@ -3468,6 +3506,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 				return false;
 				return false;
 			}
 			}
 
 
+			Type *t = type_deref(operand->type);
+			if (!is_type_comparable(t)) {
+				gbString str = type_to_string(t);
+				error(operand->expr, "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), str);
+				gb_string_free(str);
+			}
+
 			bool invalid_combination = false;
 			bool invalid_combination = false;
 
 
 			switch (success_memory_order) {
 			switch (success_memory_order) {