From cb5a6b531a1742125cdab2a4fae00a32d418e2ab Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 2 Apr 2022 15:31:50 +0200 Subject: Allow optional message for `#assert`. --- src/check_builtin.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 8b8814176..b537e407a 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -830,8 +830,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } } else if (name == "assert") { - if (ce->args.count != 1) { - error(call, "'#assert' expects 1 argument, got %td", ce->args.count); + if (ce->args.count != 1 && ce->args.count != 2) { + error(call, "'#assert' expects either 1 or 2 arguments, got %td", ce->args.count); return false; } if (!is_type_boolean(operand->type) || operand->mode != Addressing_Constant) { @@ -840,15 +840,37 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 gb_string_free(str); return false; } + if (ce->args.count == 2) { + Ast *arg = unparen_expr(ce->args[1]); + if (arg == nullptr || arg->kind != Ast_BasicLit || arg->BasicLit.token.kind != Token_String) { + gbString str = expr_to_string(arg); + error(call, "'%s' is not a constant string", str); + gb_string_free(str); + return false; + } + } + if (!operand->value.value_bool) { - gbString arg = expr_to_string(ce->args[0]); - error(call, "Compile time assertion: %s", arg); + gbString arg1 = expr_to_string(ce->args[0]); + gbString arg2 = {}; + + if (ce->args.count == 1) { + error(call, "Compile time assertion: %s", arg1); + } else { + arg2 = expr_to_string(ce->args[1]); + error(call, "Compile time assertion: %s (%s)", arg1, arg2); + } + if (c->proc_name != "") { gbString str = type_to_string(c->curr_proc_sig); error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); gb_string_free(str); } - gb_string_free(arg); + + gb_string_free(arg1); + if (ce->args.count == 2) { + gb_string_free(arg2); + } } operand->type = t_untyped_bool; -- cgit v1.2.3 From a232c0888c4b711ceb94563defdeef514eafb28a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Apr 2022 14:38:42 +0100 Subject: `intrinsics.atomic_type_is_lock_free` --- core/c/libc/stdatomic.odin | 2 +- core/intrinsics/intrinsics.odin | 2 ++ src/check_builtin.cpp | 30 ++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 2 ++ src/entity.cpp | 6 +++--- src/llvm_backend_proc.cpp | 2 +- src/types.cpp | 11 +++++++++++ 7 files changed, 50 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/core/c/libc/stdatomic.odin b/core/c/libc/stdatomic.odin index 9de3c4678..6e1581c58 100644 --- a/core/c/libc/stdatomic.odin +++ b/core/c/libc/stdatomic.odin @@ -70,7 +70,7 @@ atomic_signal_fence :: #force_inline proc(order: memory_order) { // 7.17.5 Lock-free property atomic_is_lock_free :: #force_inline proc(obj: ^$T) -> bool { - return size_of(T) <= 8 && (intrinsics.type_is_integer(T) || intrinsics.type_is_pointer(T)) + return intrinsics.atomic_type_is_lock_free(T) } // 7.17.6 Atomic integer types diff --git a/core/intrinsics/intrinsics.odin b/core/intrinsics/intrinsics.odin index ce8fd96ea..a25e9783d 100644 --- a/core/intrinsics/intrinsics.odin +++ b/core/intrinsics/intrinsics.odin @@ -71,6 +71,8 @@ Atomic_Memory_Order :: enum { Seq_Cst = 5, } +atomic_type_is_lock_free :: proc($T: typeid) -> bool --- + atomic_thread_fence :: proc(order: Atomic_Memory_Order) --- atomic_signal_fence :: proc(order: Atomic_Memory_Order) --- diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 8b8814176..abe58855b 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -449,6 +449,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_objc_find_class: case BuiltinProc_objc_register_selector: case BuiltinProc_objc_register_class: + case BuiltinProc_atomic_type_is_lock_free: // NOTE(bill): The first arg may be a Type, this will be checked case by case break; @@ -3232,6 +3233,35 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; + case BuiltinProc_atomic_type_is_lock_free: + { + Ast *expr = ce->args[0]; + Operand o = {}; + check_expr_or_type(c, &o, expr); + + if (o.mode == Addressing_Invalid || o.mode == Addressing_Builtin) { + return false; + } + if (o.type == nullptr || o.type == t_invalid || is_type_asm_proc(o.type)) { + error(o.expr, "Invalid argument to '%.*s'", LIT(builtin_name)); + return false; + } + if (is_type_polymorphic(o.type)) { + error(o.expr, "'%.*s' of polymorphic type cannot be determined", LIT(builtin_name)); + return false; + } + if (is_type_untyped(o.type)) { + error(o.expr, "'%.*s' of untyped type is not allowed", LIT(builtin_name)); + return false; + } + Type *t = o.type; + bool is_lock_free = is_type_lock_free(t); + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + operand->value = exact_value_bool(is_lock_free); + break; + } case BuiltinProc_atomic_thread_fence: case BuiltinProc_atomic_signal_fence: diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index c6b0afee0..fe14ae372 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -86,6 +86,7 @@ enum BuiltinProcId { BuiltinProc_prefetch_write_instruction, BuiltinProc_prefetch_write_data, + BuiltinProc_atomic_type_is_lock_free, BuiltinProc_atomic_thread_fence, BuiltinProc_atomic_signal_fence, BuiltinProc_atomic_store, @@ -305,6 +306,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("prefetch_write_instruction"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("prefetch_write_data"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_type_is_lock_free"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("atomic_thread_fence"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("atomic_signal_fence"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("atomic_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, diff --git a/src/entity.cpp b/src/entity.cpp index 17fa884e1..1f87f7af6 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -45,9 +45,9 @@ enum EntityFlag : u64 { EntityFlag_NoAlias = 1ull<<9, EntityFlag_TypeField = 1ull<<10, EntityFlag_Value = 1ull<<11, - EntityFlag_Sret = 1ull<<12, - EntityFlag_ByVal = 1ull<<13, - EntityFlag_BitFieldValue = 1ull<<14, + + + EntityFlag_PolyConst = 1ull<<15, EntityFlag_NotExported = 1ull<<16, EntityFlag_ConstInput = 1ull<<17, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 4de2af9d8..96ff19d10 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -447,7 +447,7 @@ void lb_begin_procedure_body(lbProcedure *p) { Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(p->type->Proc.results)); Entity *e = alloc_entity_param(nullptr, make_token_ident(name), ptr_type, false, false); - e->flags |= EntityFlag_Sret | EntityFlag_NoAlias; + e->flags |= EntityFlag_NoAlias; return_ptr_value.value = LLVMGetParam(p->value, 0); LLVMSetValueName2(return_ptr_value.value, cast(char const *)name.text, name.len); diff --git a/src/types.cpp b/src/types.cpp index e10dae1ed..b4dc17256 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2218,6 +2218,17 @@ bool elem_type_can_be_constant(Type *t) { return true; } +bool is_type_lock_free(Type *t) { + t = core_type(t); + if (t == t_invalid) { + return false; + } + i64 sz = type_size_of(t); + // TODO(bill): Figure this out correctly + return sz <= build_context.max_align; +} + + bool is_type_comparable(Type *t) { t = base_type(t); -- cgit v1.2.3 From 1ec997461d52a4d847e702ea33b40773719a592a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Apr 2022 15:00:28 +0100 Subject: Add extra checks to atomic intrinsics --- src/check_builtin.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'src') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index abe58855b..24025f08c 100644 --- a/src/check_builtin.cpp +++ b/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_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->mode = Addressing_Value; break; @@ -3419,6 +3434,22 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 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->mode = Addressing_Value; 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, &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->type = elem; break; @@ -3468,6 +3506,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 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; switch (success_memory_order) { -- cgit v1.2.3 From 2e6ad2a711a6dd47cac0462498d3c8b629f646fc Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 3 Apr 2022 21:06:06 +0200 Subject: Add extra help line for define/config. --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 9e470923d..52177e326 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2009,6 +2009,7 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-define:="); print_usage_line(2, "Defines a global constant with a value"); print_usage_line(2, "Example: -define:SPAM=123"); + print_usage_line(2, "To use: #config(SPAM, default_value)"); print_usage_line(0, ""); } -- cgit v1.2.3