mirror of https://github.com/rui314/chibicc
Add tentative definition
This commit is contained in:
parent
1b99badce4
commit
85e46b1071
|
@ -140,6 +140,7 @@ struct Obj {
|
|||
bool is_static;
|
||||
|
||||
// Global variable
|
||||
bool is_tentative;
|
||||
char *init_data;
|
||||
Relocation *rel;
|
||||
|
||||
|
|
|
@ -1136,6 +1136,11 @@ static void emit_data(Obj *prog) {
|
|||
? MAX(16, var->align) : var->align;
|
||||
println(" .align %d", align);
|
||||
|
||||
if (var->is_tentative) {
|
||||
println(" .comm %s, %d, %d", var->name, var->ty->size, align);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var->init_data) {
|
||||
println(" .data");
|
||||
println("%s:", var->name);
|
||||
|
|
31
parse.c
31
parse.c
|
@ -2947,6 +2947,8 @@ static Token *global_variable(Token *tok, Type *basety, VarAttr *attr) {
|
|||
|
||||
if (equal(tok, "="))
|
||||
gvar_initializer(&tok, tok->next, var);
|
||||
else if (!attr->is_extern)
|
||||
var->is_tentative = true;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
@ -2962,6 +2964,33 @@ static bool is_function(Token *tok) {
|
|||
return ty->kind == TY_FUNC;
|
||||
}
|
||||
|
||||
// Remove redundant tentative definitions.
|
||||
static void scan_globals(void) {
|
||||
Obj head;
|
||||
Obj *cur = &head;
|
||||
|
||||
for (Obj *var = globals; var; var = var->next) {
|
||||
if (!var->is_tentative) {
|
||||
cur = cur->next = var;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find another definition of the same identifier.
|
||||
Obj *var2 = globals;
|
||||
for (; var2; var2 = var2->next)
|
||||
if (var != var2 && var2->is_definition && !strcmp(var->name, var2->name))
|
||||
break;
|
||||
|
||||
// If there's another definition, the tentative definition
|
||||
// is redundant
|
||||
if (!var2)
|
||||
cur = cur->next = var;
|
||||
}
|
||||
|
||||
cur->next = NULL;
|
||||
globals = head.next;
|
||||
}
|
||||
|
||||
// program = (typedef | function-definition | global-variable)*
|
||||
Obj *parse(Token *tok) {
|
||||
globals = NULL;
|
||||
|
@ -2990,5 +3019,7 @@ Obj *parse(Token *tok) {
|
|||
if (var->is_root)
|
||||
mark_live(var);
|
||||
|
||||
// Remove redundant tentative definitions.
|
||||
scan_globals();
|
||||
return globals;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ int *ext2 = &ext1;
|
|||
int ext3 = 7;
|
||||
int ext_fn1(int x) { return x; }
|
||||
int ext_fn2(int x) { return x; }
|
||||
int common_ext2 = 3;
|
||||
static int common_local;
|
||||
|
||||
int false_fn() { return 512; }
|
||||
int true_fn() { return 513; }
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include "test.h"
|
||||
|
||||
int x;
|
||||
int x = 5;
|
||||
int y = 7;
|
||||
int y;
|
||||
int common_ext1;
|
||||
int common_ext2;
|
||||
static int common_local;
|
||||
|
||||
int main() {
|
||||
ASSERT(5, x);
|
||||
ASSERT(7, y);
|
||||
ASSERT(0, common_ext1);
|
||||
ASSERT(3, common_ext2);
|
||||
|
||||
printf("OK\n");
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue