Skip to content

Commit 7ccbc8a

Browse files
committed
Compiler: force zero initialization of local variables
* make all local variables zero-initialized except if tagged as `@(noinit)` * update tests
1 parent adb108a commit 7ccbc8a

34 files changed

+102
-69
lines changed

ast/ast_evaluator.c2

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,17 +278,17 @@ fn Value Evaluator.eval_call(Evaluator* caller, const CallExpr* c) {
278278

279279
// Create a new stack frame and link it to the caller's
280280
// TODO: handle Stack frames as separate allocated objects
281-
Evaluator eval;
282-
283-
if (num_args > elemsof(eval.args)) {
284-
return Value.error("too many arguments in pure function evaluation");
285-
}
281+
Evaluator eval /*@(noinit)*/;
286282
eval.prev = caller;
287283
eval.fd = fd;
288284
eval.num_args = num_args;
289285
eval.depth = caller.depth + 1;
290286
eval.complexity = caller.complexity + 1;
291287

288+
if (num_args > elemsof(eval.args)) {
289+
return Value.error("too many arguments in pure function evaluation");
290+
}
291+
292292
//VarDecl** params = fd.getParams();
293293

294294
for (u32 i = 0; i < num_args; i++) {

ast/value.c2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,7 @@ fn f64 fabs(f64 d) {
804804
// string and trying to avoid using exponential notation
805805
// TODO: should be in the C2 library as a type function f64.str()
806806
public fn char *ftoa(char *dest, usize size, f64 d) {
807-
char[32] buf;
807+
char[32] buf /*@(noinit)*/;
808808
usize pos = 0;
809809

810810
if (size < 2) {

ast/var_decl.c2

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type VarDeclBits struct {
5151
u32 has_init_call : 1; // local variables only
5252
u32 attr_weak : 1; // globals only
5353
u32 addr_used : 1;
54+
u32 attr_noinit : 1;
5455
u32 auto_attr : 2; // AutoAttr, for parameters only
5556
u32 printf_format : 1; // for parameters only
5657
}
@@ -301,6 +302,14 @@ public fn bool VarDecl.hasInitCall(const VarDecl* d) {
301302
return d.base.varDeclBits.has_init_call;
302303
}
303304

305+
public fn void VarDecl.setAttrNoInit(VarDecl* d) {
306+
d.base.varDeclBits.attr_noinit = 1;
307+
}
308+
309+
public fn bool VarDecl.hasAttrNoInit(const VarDecl* d) {
310+
return d.base.varDeclBits.attr_noinit;
311+
}
312+
304313
public fn void VarDecl.setAttrWeak(VarDecl* d) {
305314
d.base.varDeclBits.attr_weak = 1;
306315
}

ast_utils/attr.c2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public type AttrKind enum u8 {
4242
AutoLine, // Var, function param only
4343
AutoFunc, // Var, function param only
4444
Embed, // Var, globals only
45+
NoInit, // Var
4546
}
4647

4748
const char*[] attrKind_names = {
@@ -67,6 +68,7 @@ const char*[] attrKind_names = {
6768
"auto_line",
6869
"auto_func",
6970
"embed",
71+
"noinit",
7072
}
7173

7274
static_assert(elemsof(AttrKind), elemsof(attrKind_names));
@@ -146,6 +148,7 @@ const AttrReq[] Required_arg = {
146148
[AttrKind.AutoLine] = AttrReq.NoArg,
147149
[AttrKind.AutoFunc] = AttrReq.NoArg,
148150
[AttrKind.Embed] = AttrReq.String,
151+
[AttrKind.NoInit] = AttrReq.NoArg,
149152
}
150153
static_assert(elemsof(AttrKind), elemsof(Required_arg));
151154

ast_utils/string_buffer.c2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public fn void Buf.lparen(Buf* buf) { buf.add1('('); }
160160
public fn void Buf.rparen(Buf* buf) { buf.add1(')'); }
161161

162162
public fn void Buf.print(Buf* buf, const char* format @(printf_format), ...) {
163-
char[4096] tmp;
163+
char[4096] tmp /*@(noinit)*/;
164164
// NOTE: no growing
165165
va_list args;
166166
va_start(args, format);
@@ -171,7 +171,7 @@ public fn void Buf.print(Buf* buf, const char* format @(printf_format), ...) {
171171
}
172172

173173
public fn void Buf.vprintf(Buf* buf, const char* format, va_list args) {
174-
char[4096] tmp;
174+
char[4096] tmp /*@(noinit)*/;
175175
// NOTE: no growing
176176
i32 len = vsnprintf(tmp, sizeof(tmp), format, args);
177177
assert(len < sizeof(tmp));

common/file/file_utils.c2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public fn const char* make_path3(char *buf, usize size, const char* dir, const c
116116
// returns 0 on success, errno on failure
117117
// create a directory path, OK if exists already
118118
public fn i32 create_path(const char* path) {
119-
char[file_utils.Max_path] tmp;
119+
char[file_utils.Max_path] tmp /*@(noinit)*/;
120120
char *p = tmp;
121121
if (!*path) return 0;
122122
*p++ = *path++;

generator/c/c_generator.c2

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,8 +1282,7 @@ public fn void generate(string_pool.Pool* astPool,
12821282
return;
12831283
}
12841284

1285-
Generator gen;
1286-
gen.init(astPool, target, kind, output_dir, dir, diags, sm, build_info, mainFunc);
1285+
Generator gen.init(astPool, target, kind, output_dir, dir, diags, sm, build_info, mainFunc);
12871286
gen.auxPool = auxPool;
12881287
gen.enable_asserts = enable_asserts;
12891288
gen.fast_build = fast_build;

generator/c/c_generator_special.c2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ fn void Generator.createMakefile(Generator* gen,
6363
out.print("CC=%s\n", cc);
6464

6565
out.add("CFLAGS=-Wall -Wextra -Wno-unused -Wno-switch\n");
66-
out.add("CFLAGS+=-Wno-unused-parameter -Wno-missing-field-initializers -Wno-format-zero-length\n");
66+
out.add("CFLAGS+=-Wno-unused-parameter -Wno-missing-field-initializers -Wno-missing-braces -Wno-format-zero-length\n");
6767
out.add("CFLAGS+=-pipe -std=c99 -funsigned-char\n");
6868
if (gen.fast_build)
6969
out.add("CFLAGS+=-O0 -g\n");

generator/c/c_generator_stmt.c2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ fn void Generator.emitVarDecl(Generator* gen, VarDecl* vd, string_buffer.Buf* ou
4040
out.add(" = ");
4141
}
4242
gen.emitExpr(out, ie);
43+
} else {
44+
if (!vd.hasAttrNoInit()) {
45+
out.add(" = { 0 }");
46+
}
4347
}
4448
}
4549

parser/ast_builder.c2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,9 @@ fn void Builder.actOnVarAttr(Builder* b, Decl* d, const Attr* a) {
522522
case Embed:
523523
b.storeAttr(d, a);
524524
break;
525+
case NoInit:
526+
vd.setAttrNoInit();
527+
break;
525528
default:
526529
b.diags.error(a.loc, "attribute '%s' is not applicable to variables",
527530
kind2name(a.kind));

0 commit comments

Comments
 (0)