diff --git a/common/build_target.c2 b/common/build_target.c2 index a2c684370..d5f678367 100644 --- a/common/build_target.c2 +++ b/common/build_target.c2 @@ -106,6 +106,7 @@ public type Target struct @(opaque) { Kind kind; bool disable_asserts; + bool force_initializers; bool no_libc; BackEndKind backend; bool backend_no_build; @@ -179,6 +180,10 @@ public fn void Target.disableAsserts(Target* t) { t.disable_asserts = true; } public fn bool Target.hasAsserts(const Target* t) { return !t.disable_asserts; } +public fn void Target.enableForceInitializers(Target* t) { t.force_initializers = true; } + +public fn bool Target.hasForceInitializers(const Target* t) { return t.force_initializers; } + public fn void Target.visitLibs(const Target* t, library_list.Visitor visitor, void* arg) { t.libs.visit(visitor, arg); } diff --git a/compiler/c2recipe_parser.c2 b/compiler/c2recipe_parser.c2 index 38a97e79e..25ba9d365 100644 --- a/compiler/c2recipe_parser.c2 +++ b/compiler/c2recipe_parser.c2 @@ -43,6 +43,7 @@ type Kind enum u8 { Warnings, Backend, DisableAsserts, + ForceInitializers, NoLibc, Config, Export, @@ -65,6 +66,7 @@ const char*[] kind_names = { "$warnings", "$backend", "$disable-asserts", + "$force-initializers", "$nolibc", "$config", "$export", @@ -200,7 +202,6 @@ fn void Parser.error(Parser* p, const char* format @(printf_format), ...) @(nore char[256] locstr; p.sm.loc2str(p.token.loc, locstr, elemsof(locstr)); - if (color.useColor()) { fprintf(stderr, "%s: %serror:%s %s\n", locstr, color.Red, color.Normal, msg); } else { @@ -436,6 +437,9 @@ fn void Parser.lex_option(Parser* p, Token* result) { case "disable-asserts": result.kind = Kind.DisableAsserts; break; + case "force-initializers": + result.kind = Kind.ForceInitializers; + break; case "nolibc": result.kind = Kind.NoLibc; break; @@ -495,6 +499,7 @@ fn void Parser.parseTop(Parser* p) { case Warnings: case Backend: case DisableAsserts: + case ForceInitializers: case NoLibc: p.error("must be inside target"); break; @@ -737,6 +742,11 @@ fn void Parser.parseTarget(Parser* p) { p.consumeToken(); p.target.disableAsserts(); break; + case ForceInitializers: + if (files_started) p.error("$force-initializers must come before files"); + p.consumeToken(); + p.target.enableForceInitializers(); + break; case NoLibc: if (files_started) p.error("$nolibc must come before files"); p.consumeToken(); diff --git a/compiler/compiler.c2 b/compiler/compiler.c2 index 918c92b2c..77015167f 100644 --- a/compiler/compiler.c2 +++ b/compiler/compiler.c2 @@ -519,6 +519,7 @@ fn void Compiler.build(Compiler* c, c.mainFunc, &asm_files, c.target.hasAsserts(), + c.target.hasForceInitializers(), c.target.getFastBuild() | c.opts.fast_build, c.opts.asan, c.opts.msan, c.opts.ubsan, c.opts.test_mode, c.opts.trace_calls); diff --git a/generator/c/c_generator.c2 b/generator/c/c_generator.c2 index 0496c9fd1..dc1ab0640 100644 --- a/generator/c/c_generator.c2 +++ b/generator/c/c_generator.c2 @@ -75,6 +75,7 @@ type Generator struct { const build_file.Info* build_info; const target_info.Info* targetInfo; bool enable_asserts; + bool force_initializers; bool fast_build; bool asan; bool msan; @@ -610,13 +611,16 @@ fn bool Generator.emitGlobalVarDecl(Generator* gen, string_buffer.Buf* out, Decl // generate definition to c file if (!d.isExported() && !emit_header) out.add("static "); gen.emitGlobalVarDeclCommon(out, d); - out.add(" = "); Expr* ie = vd.getInit(); if (ie) { + out.add(" = "); gen.emitConstExpr(out, ie, Assignment); } else { // auto-initialize (only required for embedded targets) - gen.emitAutoInit(out, d.getType()); + if (gen.force_initializers) { + out.add(" = "); + gen.emitAutoInit(out, d.getType()); + } } out.add(";\n"); } @@ -1272,6 +1276,7 @@ public fn void generate(string_pool.Pool* astPool, Decl* mainFunc, string_list.List* asm_files, bool enable_asserts, + bool force_initializers, bool fast_build, bool asan, bool msan, bool ubsan, bool test_mode, bool trace_calls) { @@ -1286,6 +1291,7 @@ public fn void generate(string_pool.Pool* astPool, gen.init(astPool, target, kind, output_dir, dir, diags, sm, build_info, mainFunc); gen.auxPool = auxPool; gen.enable_asserts = enable_asserts; + gen.force_initializers = force_initializers; gen.fast_build = fast_build; gen.asan = asan; gen.msan = msan; diff --git a/test/c_generator/attributes/exported_not_static.c2t b/test/c_generator/attributes/exported_not_static.c2t index b1a0f917e..82a4dc72f 100644 --- a/test/c_generator/attributes/exported_not_static.c2t +++ b/test/c_generator/attributes/exported_not_static.c2t @@ -20,9 +20,9 @@ public fn i32 main(i32 argc, const i8** argv) // @expect{atleast, cgen/build.c} -static int32_t file1_a = 0; -int32_t file1_b = 0; -static int32_t file1_c = 0; +static int32_t file1_a; +int32_t file1_b; +static int32_t file1_c; static void file1_f(void); void file1_g(void); diff --git a/test/c_generator/constants/string_literals.c2t b/test/c_generator/constants/string_literals.c2t index fa4fdf689..53da10a54 100644 --- a/test/c_generator/constants/string_literals.c2t +++ b/test/c_generator/constants/string_literals.c2t @@ -35,7 +35,7 @@ static const char test1_BBB[4] = "bbb"; static char test1_ddd[4] = "ddd"; static char test1_eee[4] = "eee"; static const char* test1_fff = "fff"; -static const char* test1_ggg = NULL; -static char test1_hhh[3] = { }; -static char* test1_iii = NULL; +static const char* test1_ggg; +static char test1_hhh[3]; +static char* test1_iii; diff --git a/test/c_generator/functions/struct_functions/global.c2t b/test/c_generator/functions/struct_functions/global.c2t index 88cf90697..25d6a9c4b 100644 --- a/test/c_generator/functions/struct_functions/global.c2t +++ b/test/c_generator/functions/struct_functions/global.c2t @@ -25,7 +25,7 @@ struct test_Type_ { int32_t member; }; -static test_Type test_t = { }; +static test_Type test_t; static void test_Type_init(test_Type* _arg0) { diff --git a/test/c_generator/module/static_single_module.c2t b/test/c_generator/module/static_single_module.c2t index cfd0f8ed3..9c486a714 100644 --- a/test/c_generator/module/static_single_module.c2t +++ b/test/c_generator/module/static_single_module.c2t @@ -17,8 +17,8 @@ public i32 y2; // @expect{atleast, cgen/build.c} -static int32_t test1_x1 = 0; -int32_t test1_y1 = 0; +static int32_t test1_x1; +int32_t test1_y1; // test2 symbols are not generated, because they are unused diff --git a/test/c_generator/module/variable_fast_build.c2t b/test/c_generator/module/variable_fast_build.c2t index 3e6dc0f2a..41e8f135f 100644 --- a/test/c_generator/module/variable_fast_build.c2t +++ b/test/c_generator/module/variable_fast_build.c2t @@ -13,8 +13,8 @@ public char[] y2 = { 1, 2, 3, 4 } // @expect{atleast, cgen/test1.c} #include "test1.h" -static int32_t test1_x1 = 0; -int32_t test1_y1 = 0; +static int32_t test1_x1; +int32_t test1_y1; char test1_y2[4] = { 1, 2, 3, 4 }; // @expect{atleast, cgen/test1.h} diff --git a/test/c_generator/stmts/local_array_decl.c2t b/test/c_generator/stmts/local_array_decl.c2t index 0b1392169..c8286c09c 100644 --- a/test/c_generator/stmts/local_array_decl.c2t +++ b/test/c_generator/stmts/local_array_decl.c2t @@ -20,7 +20,7 @@ public fn i32 main() { #define test_Size 20 -static int32_t test_board[20][20] = { }; +static int32_t test_board[20][20]; static void test_func1(void); diff --git a/test/c_generator/types/const_pointer_type.c2t b/test/c_generator/types/const_pointer_type.c2t index 0c45439dd..3bc749720 100644 --- a/test/c_generator/types/const_pointer_type.c2t +++ b/test/c_generator/types/const_pointer_type.c2t @@ -13,5 +13,5 @@ const Struct* p; // @expect{atleast, cgen/build.c} -static const test_Struct* test_p = NULL; +static const test_Struct* test_p; diff --git a/test/c_generator/types/qualifiers.c2t b/test/c_generator/types/qualifiers.c2t index 918355397..a452963ed 100644 --- a/test/c_generator/types/qualifiers.c2t +++ b/test/c_generator/types/qualifiers.c2t @@ -12,6 +12,6 @@ const volatile u32 C = 2; // @expect{atleast, cgen/build.c} #define test_A 1 -static volatile uint16_t test_b = 0; +static volatile uint16_t test_b; static const volatile uint32_t test_C = 2; diff --git a/test/c_generator/variables/initialize_2d_array.c2t b/test/c_generator/variables/initialize_2d_array.c2t index a84dc208d..1565d3f08 100644 --- a/test/c_generator/variables/initialize_2d_array.c2t +++ b/test/c_generator/variables/initialize_2d_array.c2t @@ -8,5 +8,5 @@ module test; i32[3][2] a; // @expect{atleast, cgen/build.c} -static int32_t test_a[3][2] = { }; +static int32_t test_a[3][2]; diff --git a/test/c_generator/variables/should_initalize_globals.c2t b/test/c_generator/variables/should_initalize_globals.c2t index e396e6bde..6683c1824 100644 --- a/test/c_generator/variables/should_initalize_globals.c2t +++ b/test/c_generator/variables/should_initalize_globals.c2t @@ -27,11 +27,11 @@ struct test_Foo_ { _Bool b; }; -static test_Foo test_f = { }; +static test_Foo test_f; -static int32_t test_i = 0; +static int32_t test_i; -static test_Foo test_fs[2] = { }; +static test_Foo test_fs[2]; -static int32_t test_is[2] = { }; +static int32_t test_is[2];