Skip to content

Commit 1f33597

Browse files
committed
Global linkage WIP
1 parent 56b9788 commit 1f33597

File tree

9 files changed

+65
-37
lines changed

9 files changed

+65
-37
lines changed

include/mcc/ast.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,8 @@ typedef struct BlockItem {
229229
typedef struct TranslationUnit {
230230
uint32_t decl_count;
231231
Decl* decls;
232-
Scope* global_scope;
233232

234-
// Besides stored in the scopes, the identifiers of functions in a translation
235-
// unit are also refered to in a separate hash table. This is useful because
236-
// each named only map to one instance of a function no matter the scope
237-
HashMap functions;
233+
struct SymbolTable* symbol_table;
238234
} TranslationUnit;
239235

240236
StringView string_from_ast(const TranslationUnit* tu, Arena* permanent_arena);

src/frontend/parser.c

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ typedef struct Parser {
2929

3030
struct ErrorVec errors;
3131

32-
struct Scope* global_scope;
33-
HashMap functions;
32+
SymbolTable* symbol_table;
3433
} Parser;
3534

3635
#pragma region source range operations
@@ -627,8 +626,9 @@ static VariableDecl parse_variable_decl(Parser* parser,
627626
{
628627
const StringView name = str_from_token(parser->src, name_token);
629628
// TODO: handle different linkages
630-
IdentifierInfo* variable = add_identifier(
631-
scope, name, IDENT_OBJECT, LINKAGE_NONE, parser->permanent_arena);
629+
IdentifierInfo* variable =
630+
add_identifier(parser->symbol_table, scope, name, IDENT_OBJECT,
631+
LINKAGE_NONE, parser->permanent_arena);
632632
if (!variable) {
633633
const StringView error_msg =
634634
allocate_printf(parser->permanent_arena, "redefinition of '%.*s'",
@@ -937,8 +937,9 @@ static IdentifierInfo* parse_parameter(Parser* parser, Scope* scope)
937937
parse_advance(parser);
938938
}
939939

940-
IdentifierInfo* name = add_identifier(
941-
scope, identifier, IDENT_OBJECT, LINKAGE_NONE, parser->permanent_arena);
940+
IdentifierInfo* name =
941+
add_identifier(parser->symbol_table, scope, identifier, IDENT_OBJECT,
942+
LINKAGE_NONE, parser->permanent_arena);
942943
// TODO: error handling
943944
MCC_ASSERT(name != nullptr);
944945
return name;
@@ -1006,8 +1007,9 @@ static FunctionDecl* parse_function_decl(Parser* parser,
10061007
Token name_token, Scope* scope)
10071008
{
10081009
StringView name = str_from_token(parser->src, name_token);
1009-
IdentifierInfo* function_ident = add_identifier(
1010-
scope, name, IDENT_FUNCTION, LINKAGE_EXTERNAL, parser->permanent_arena);
1010+
IdentifierInfo* function_ident =
1011+
add_identifier(parser->symbol_table, scope, name, IDENT_FUNCTION,
1012+
LINKAGE_EXTERNAL, parser->permanent_arena);
10111013

10121014
if (!function_ident) {
10131015
function_ident = lookup_identifier(scope, name);
@@ -1021,11 +1023,8 @@ static FunctionDecl* parse_function_decl(Parser* parser,
10211023
}
10221024
}
10231025

1024-
hashmap_try_insert(&parser->functions, name, function_ident,
1025-
parser->permanent_arena);
1026-
10271026
Scope* function_scope =
1028-
new_scope(parser->global_scope, parser->permanent_arena);
1027+
new_scope(parser->symbol_table->global_scope, parser->permanent_arena);
10291028
const Parameters parameters = parse_parameter_list(parser, function_scope);
10301029

10311030
Block* body = NULL;
@@ -1065,7 +1064,7 @@ static TranslationUnit* parse_translation_unit(Parser* parser)
10651064
struct DeclVec decl_vec = {};
10661065

10671066
while (parser_current_token(parser).tag != TOKEN_EOF) {
1068-
Decl decl = parse_decl(parser, parser->global_scope);
1067+
Decl decl = parse_decl(parser, parser->symbol_table->global_scope);
10691068
DYNARRAY_PUSH_BACK(&decl_vec, Decl, &parser->scratch_arena, decl);
10701069
}
10711070

@@ -1077,12 +1076,9 @@ static TranslationUnit* parse_translation_unit(Parser* parser)
10771076

10781077
TranslationUnit* tu =
10791078
ARENA_ALLOC_OBJECT(parser->permanent_arena, TranslationUnit);
1080-
*tu = (TranslationUnit){
1081-
.decl_count = decl_count,
1082-
.decls = decls,
1083-
.global_scope = parser->global_scope,
1084-
.functions = parser->functions,
1085-
};
1079+
*tu = (TranslationUnit){.decl_count = decl_count,
1080+
.decls = decls,
1081+
.symbol_table = parser->symbol_table};
10861082
parse_consume(parser, TOKEN_EOF, "Expect end of the file");
10871083

10881084
return tu;
@@ -1091,12 +1087,17 @@ static TranslationUnit* parse_translation_unit(Parser* parser)
10911087
ParseResult parse(const char* src, Tokens tokens, Arena* permanent_arena,
10921088
Arena scratch_arena)
10931089
{
1090+
SymbolTable* symbol_table = ARENA_ALLOC_OBJECT(permanent_arena, SymbolTable);
1091+
*symbol_table = (SymbolTable){
1092+
.global_symbols = (HashMap){},
1093+
.global_scope = new_scope(nullptr, permanent_arena),
1094+
};
1095+
10941096
Parser parser = {.src = src,
10951097
.tokens = tokens,
10961098
.permanent_arena = permanent_arena,
10971099
.scratch_arena = scratch_arena,
1098-
.global_scope = new_scope(nullptr, permanent_arena),
1099-
.functions = (HashMap){}};
1100+
.symbol_table = symbol_table};
11001101

11011102
TranslationUnit* tu = parse_translation_unit(&parser);
11021103

src/frontend/symbol_table.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ IdentifierInfo* lookup_identifier(const Scope* scope, StringView name)
2727
return lookup_identifier(scope->parent, name);
2828
}
2929

30-
IdentifierInfo* add_identifier(Scope* scope, StringView name,
31-
IdentifierKind kind, Linkage linkage,
32-
Arena* arena)
30+
IdentifierInfo* add_identifier(SymbolTable* symbol_table, Scope* scope,
31+
StringView name, IdentifierKind kind,
32+
Linkage linkage, Arena* arena)
3333
{
34+
3435
// check variable in current scope
3536
if (hashmap_lookup(&scope->identifiers, name) != nullptr) { return nullptr; }
3637

@@ -64,5 +65,10 @@ IdentifierInfo* add_identifier(Scope* scope, StringView name,
6465
const bool insert_succeed =
6566
hashmap_try_insert(&scope->identifiers, name, variable, arena);
6667
MCC_ASSERT(insert_succeed);
68+
69+
if (linkage != LINKAGE_NONE) {
70+
hashmap_try_insert(&symbol_table->global_symbols, name, variable, arena);
71+
}
72+
6773
return variable;
6874
}

src/frontend/symbol_table.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,26 @@ typedef struct IdentifierInfo {
4545
// Represents a block scope
4646
typedef struct Scope Scope;
4747

48+
// Represents a symbol table in a C translation unit, tracking both scoped and
49+
// global symbols. In C, identifiers with linkage can be referenced across
50+
// multiple scopes while remaining unique within a program. To account for this,
51+
// a pointer to global symbols are stored separately in addition to their
52+
// respective scopes.
53+
typedef struct SymbolTable {
54+
// Tracks globally visible symbols (those with external or internal linkage)
55+
HashMap global_symbols;
56+
// Represents the global scope of the translation unit.
57+
Scope* global_scope;
58+
} SymbolTable;
59+
4860
Scope* new_scope(Scope* parent, Arena* arena);
4961

5062
IdentifierInfo* lookup_identifier(const Scope* scope, StringView name);
5163

5264
// Return nullptr if a variable of the same name already exist in the same scope
5365
// Otherwise we add it to the current scope
54-
IdentifierInfo* add_identifier(Scope* scope, StringView name,
55-
IdentifierKind kind, Linkage linkage,
56-
Arena* arena);
66+
IdentifierInfo* add_identifier(SymbolTable* symbol_table, Scope* scope,
67+
StringView name, IdentifierKind kind,
68+
Linkage linkage, Arena* arena);
5769

5870
#endif // MCC_SYMBOL_TABLE_H

src/frontend/type_check.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct ErrorVec {
1818
typedef struct Context {
1919
struct ErrorVec errors;
2020
Arena* permanent_arena;
21-
HashMap functions;
21+
SymbolTable* symbol_table;
2222
} Context;
2323

2424
#pragma region error reporter
@@ -336,7 +336,7 @@ static bool type_check_function_decl(FunctionDecl* decl, Context* context)
336336
{
337337
StringView function_name = decl->name->name;
338338
IdentifierInfo* function_ident =
339-
hashmap_lookup(&context->functions, function_name);
339+
hashmap_lookup(&context->symbol_table->global_symbols, function_name);
340340

341341
if (function_ident->type == nullptr) {
342342
function_ident->type =
@@ -370,7 +370,7 @@ static bool type_check_function_decl(FunctionDecl* decl, Context* context)
370370
ErrorsView type_check(TranslationUnit* ast, Arena* permanent_arena)
371371
{
372372
Context context = {.permanent_arena = permanent_arena,
373-
.functions = ast->functions};
373+
.symbol_table = ast->symbol_table};
374374

375375
for (uint32_t i = 0; i < ast->decl_count; ++i) {
376376
type_check_decl(&ast->decls[i], &context);

src/x86/x86.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ static X86FunctionDef x86_generate_function(const IRFunctionDef* ir_function,
4040
X86Program x86_generate_assembly(IRProgram* ir, Arena* permanent_arena,
4141
Arena scratch_arena)
4242
{
43-
// TODO: fix this
44-
4543
const size_t top_level_count = ir->top_level_count;
4644
X86TopLevel* top_levels =
4745
ARENA_ALLOC_ARRAY(permanent_arena, X86TopLevel, top_level_count);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int x = 42;
2+
int x = 42;
3+
4+
int main(void)
5+
{
6+
int foo = 1;
7+
return foo + x;
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{{filename}}:2:5: Error: redefinition of 'x'
2+
2 | int x = 42;
3+
| ^
4+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
command = "{mcc} --parse {filename}"
2+
return_code = 1
3+
snapshot_test_stderr = true

0 commit comments

Comments
 (0)