Add tentative definition

This commit is contained in:
Rui Ueyama 2020-09-04 17:29:15 +09:00
parent 1b99badce4
commit 85e46b1071
5 changed files with 58 additions and 0 deletions

View File

@ -140,6 +140,7 @@ struct Obj {
bool is_static;
// Global variable
bool is_tentative;
char *init_data;
Relocation *rel;

View File

@ -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
View File

@ -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;
}

View File

@ -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; }

19
test/commonsym.c Normal file
View File

@ -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;
}