Browse Source

Add `-disable-assert` to disable the code generation of the built-in run-time 'assert' procedure

gingerBill 5 years ago
parent
commit
2252d992d7
8 changed files with 48 additions and 2 deletions
  1. 5 2
      core/runtime/core.odin
  2. 1 0
      src/build_settings.cpp
  3. 10 0
      src/check_decl.cpp
  4. 11 0
      src/checker.cpp
  5. 2 0
      src/checker.hpp
  6. 3 0
      src/entity.cpp
  7. 6 0
      src/ir.cpp
  8. 10 0
      src/main.cpp

+ 5 - 2
core/runtime/core.odin

@@ -922,7 +922,8 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int {
 
 
 @builtin
-assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool {
+@(disabled=ODIN_DISABLE_ASSERT)
+assert :: proc(condition: bool, message := "", loc := #caller_location) {
 	if !condition {
 		proc(message: string, loc: Source_Code_Location) {
 			p := context.assertion_failure_proc;
@@ -932,10 +933,10 @@ assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool
 			p("runtime assertion", message, loc);
 		}(message, loc);
 	}
-	return condition;
 }
 
 @builtin
+@(disabled=ODIN_DISABLE_ASSERT)
 panic :: proc(message: string, loc := #caller_location) -> ! {
 	p := context.assertion_failure_proc;
 	if p == nil {
@@ -945,6 +946,7 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
 }
 
 @builtin
+@(disabled=ODIN_DISABLE_ASSERT)
 unimplemented :: proc(message := "", loc := #caller_location) -> ! {
 	p := context.assertion_failure_proc;
 	if p == nil {
@@ -954,6 +956,7 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! {
 }
 
 @builtin
+@(disabled=ODIN_DISABLE_ASSERT)
 unreachable :: proc(message := "", loc := #caller_location) -> ! {
 	p := context.assertion_failure_proc;
 	if p == nil {

+ 1 - 0
src/build_settings.cpp

@@ -91,6 +91,7 @@ struct BuildContext {
 	String ODIN_VERSION; // compiler version
 	String ODIN_ROOT;    // Odin ROOT
 	bool   ODIN_DEBUG;   // Odin in debug mode
+	bool   ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
 
 	TargetEndianKind endian_kind;
 

+ 10 - 0
src/check_decl.cpp

@@ -675,6 +675,16 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
 	e->Procedure.is_export = ac.is_export;
 	e->deprecated_message = ac.deprecated_message;
 	ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix);
+	if (ac.has_disabled_proc) {
+		if (ac.disabled_proc) {
+			e->flags |= EntityFlag_Disabled;
+		}
+		Type *t = base_type(e->type);
+		GB_ASSERT(t->kind == Type_Proc);
+		if (t->Proc.result_count != 0) {
+			error(e->token, "Procedure with the 'disabled' attribute may not have any return values");
+		}
+	}
 
 	bool is_foreign         = e->Procedure.is_foreign;
 	bool is_export          = e->Procedure.is_export;

+ 11 - 0
src/checker.cpp

@@ -710,6 +710,7 @@ void init_universal(void) {
 	add_global_string_constant(str_lit("ODIN_VERSION"), bc->ODIN_VERSION);
 	add_global_string_constant(str_lit("ODIN_ROOT"),    bc->ODIN_ROOT);
 	add_global_constant(str_lit("ODIN_DEBUG"), t_untyped_bool, exact_value_bool(bc->ODIN_DEBUG));
+	add_global_constant(str_lit("ODIN_DISABLE_ASSERT"), t_untyped_bool, exact_value_bool(bc->ODIN_DISABLE_ASSERT));
 
 
 // Builtin Procedures
@@ -2273,6 +2274,16 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
 		}
 		ac->require_results = true;
 		return true;
+	} else if (name == "disabled") {
+		ExactValue ev = check_decl_attribute_value(c, value);
+
+		if (ev.kind == ExactValue_Bool) {
+			ac->has_disabled_proc = true;
+			ac->disabled_proc = ev.value_bool;
+		} else {
+			error(elem, "Expected a boolean value for '%.*s'", LIT(name));
+		}
+		return true;
 	}
 	return false;
 }

+ 2 - 0
src/checker.hpp

@@ -99,6 +99,8 @@ struct AttributeContext {
 	bool    is_static;
 	bool    require_results;
 	bool    force_foreign_import;
+	bool    has_disabled_proc;
+	bool    disabled_proc;
 	String  link_name;
 	String  link_prefix;
 	isize   init_expr_list_count;

+ 3 - 0
src/entity.cpp

@@ -55,6 +55,9 @@ enum EntityFlag {
 
 	EntityFlag_CVarArg       = 1<<21,
 	EntityFlag_AutoCast      = 1<<22,
+
+	EntityFlag_Disabled      = 1<<24,
+
 };
 
 enum EntityState {

+ 6 - 0
src/ir.cpp

@@ -3109,6 +3109,12 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> const &ar
 	GB_ASSERT(pt->kind == Type_Proc);
 	Type *results = pt->Proc.results;
 
+	if (p->entity != nullptr) {
+		if (p->entity->flags & EntityFlag_Disabled) {
+			return nullptr;
+		}
+	}
+
 	irValue *context_ptr = nullptr;
 	if (pt->Proc.calling_convention == ProcCC_Odin) {
 		context_ptr = ir_find_or_generate_context_ptr(p);

+ 10 - 0
src/main.cpp

@@ -229,6 +229,7 @@ enum BuildFlagKind {
 	BuildFlag_BuildMode,
 	BuildFlag_Target,
 	BuildFlag_Debug,
+	BuildFlag_DisableAssert,
 	BuildFlag_NoBoundsCheck,
 	BuildFlag_NoCRT,
 	BuildFlag_UseLLD,
@@ -318,6 +319,7 @@ bool parse_build_flags(Array<String> args) {
 	add_flag(&build_flags, BuildFlag_BuildMode,         str_lit("build-mode"),        BuildFlagParam_String);
 	add_flag(&build_flags, BuildFlag_Target,            str_lit("target"),            BuildFlagParam_String);
 	add_flag(&build_flags, BuildFlag_Debug,             str_lit("debug"),             BuildFlagParam_None);
+	add_flag(&build_flags, BuildFlag_DisableAssert,     str_lit("disable-assert"),    BuildFlagParam_None);
 	add_flag(&build_flags, BuildFlag_NoBoundsCheck,     str_lit("no-bounds-check"),   BuildFlagParam_None);
 	add_flag(&build_flags, BuildFlag_NoCRT,             str_lit("no-crt"),            BuildFlagParam_None);
 	add_flag(&build_flags, BuildFlag_UseLLD,            str_lit("lld"),               BuildFlagParam_None);
@@ -669,6 +671,10 @@ bool parse_build_flags(Array<String> args) {
 							build_context.ODIN_DEBUG = true;
 							break;
 
+						case BuildFlag_DisableAssert:
+							build_context.ODIN_DISABLE_ASSERT = true;
+							break;
+
 						case BuildFlag_NoBoundsCheck:
 							build_context.no_bounds_check = true;
 							break;
@@ -1031,6 +1037,10 @@ void print_show_help(String const arg0, String const &command) {
 		print_usage_line(2, "Enabled debug information, and defines the global constant ODIN_DEBUG to be 'true'");
 		print_usage_line(0, "");
 
+		print_usage_line(1, "-disable-assert");
+		print_usage_line(2, "Disable the code generation of the built-in run-time 'assert' procedure, and defines the global constant ODIN_DISABLE_ASSERT to be 'true'");
+		print_usage_line(0, "");
+
 		print_usage_line(1, "-no-bounds-check");
 		print_usage_line(2, "Disables bounds checking program wide");
 		print_usage_line(0, "");