mirror of
https://github.com/rui314/chibicc
synced 2024-11-26 08:09:41 +03:00
Initialize excess array elements with zero
This commit is contained in:
parent
22dd560ecf
commit
ae0a37dc4b
@ -131,6 +131,7 @@ typedef enum {
|
||||
ND_VAR, // Variable
|
||||
ND_NUM, // Integer
|
||||
ND_CAST, // Type cast
|
||||
ND_MEMZERO, // Zero-clear a stack variable
|
||||
} NodeKind;
|
||||
|
||||
// AST node type
|
||||
|
@ -212,6 +212,13 @@ static void gen_expr(Node *node) {
|
||||
gen_expr(node->lhs);
|
||||
cast(node->lhs->ty, node->ty);
|
||||
return;
|
||||
case ND_MEMZERO:
|
||||
// `rep stosb` is equivalent to `memset(%rdi, %al, %rcx)`.
|
||||
println(" mov $%d, %%rcx", node->var->ty->size);
|
||||
println(" lea %d(%%rbp), %%rdi", node->var->offset);
|
||||
println(" mov $0, %%al");
|
||||
println(" rep stosb");
|
||||
return;
|
||||
case ND_COND: {
|
||||
int c = count();
|
||||
gen_expr(node->cond);
|
||||
|
19
parse.c
19
parse.c
@ -609,7 +609,7 @@ static void initializer2(Token **rest, Token *tok, Initializer *init) {
|
||||
if (init->ty->kind == TY_ARRAY) {
|
||||
tok = skip(tok, "{");
|
||||
|
||||
for (int i = 0; i < init->ty->array_len; i++) {
|
||||
for (int i = 0; i < init->ty->array_len && !equal(tok, "}"); i++) {
|
||||
if (i > 0)
|
||||
tok = skip(tok, ",");
|
||||
initializer2(&tok, tok, init->children[i]);
|
||||
@ -647,9 +647,11 @@ static Node *create_lvar_init(Initializer *init, Type *ty, InitDesg *desg, Token
|
||||
return node;
|
||||
}
|
||||
|
||||
if (!init->expr)
|
||||
return new_node(ND_NULL_EXPR, tok);
|
||||
|
||||
Node *lhs = init_desg_expr(desg, tok);
|
||||
Node *rhs = init->expr;
|
||||
return new_binary(ND_ASSIGN, lhs, rhs, tok);
|
||||
return new_binary(ND_ASSIGN, lhs, init->expr, tok);
|
||||
}
|
||||
|
||||
// A variable definition with an initializer is a shorthand notation
|
||||
@ -665,7 +667,16 @@ static Node *create_lvar_init(Initializer *init, Type *ty, InitDesg *desg, Token
|
||||
static Node *lvar_initializer(Token **rest, Token *tok, Obj *var) {
|
||||
Initializer *init = initializer(rest, tok, var->ty);
|
||||
InitDesg desg = {NULL, 0, var};
|
||||
return create_lvar_init(init, var->ty, &desg, tok);
|
||||
|
||||
// If a partial initializer list is given, the standard requires
|
||||
// that unspecified elements are set to 0. Here, we simply
|
||||
// zero-initialize the entire memory region of a variable before
|
||||
// initializing it with user-supplied values.
|
||||
Node *lhs = new_node(ND_MEMZERO, tok);
|
||||
lhs->var = var;
|
||||
|
||||
Node *rhs = create_lvar_init(init, var->ty, &desg, tok);
|
||||
return new_binary(ND_COMMA, lhs, rhs, tok);
|
||||
}
|
||||
|
||||
// Returns true if a given token represents a type.
|
||||
|
@ -10,6 +10,14 @@ int main() {
|
||||
ASSERT(4, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[1][0]; }));
|
||||
ASSERT(6, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[1][2]; }));
|
||||
|
||||
ASSERT(0, ({ int x[3]={}; x[0]; }));
|
||||
ASSERT(0, ({ int x[3]={}; x[1]; }));
|
||||
ASSERT(0, ({ int x[3]={}; x[2]; }));
|
||||
|
||||
ASSERT(2, ({ int x[2][3]={{1,2}}; x[0][1]; }));
|
||||
ASSERT(0, ({ int x[2][3]={{1,2}}; x[1][0]; }));
|
||||
ASSERT(0, ({ int x[2][3]={{1,2}}; x[1][2]; }));
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user