diff --git a/src/ast/ast.c b/src/ast/ast.c index 8e597f0..70b2931 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -49,7 +49,11 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v } else if(n->nodeKind == AST_STMT_EXPR) { generic_visitor(&n->stmtExpr.expr, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); } else if(n->nodeKind == AST_STMT_EXT_ORG) { - } else if(n->nodeKind == AST_STMT_EXT_SECTION) { + } else if(n->nodeKind == AST_SECTION) { + generic_visitor(&n->section.tlc, stmt, stmtPrev, n->section.tlc, n->section.tlc, ud, preHandler, postHandler); + if(n->section.next) { + generic_visitor(&n->section.next, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); + } } else if(n->nodeKind == AST_STMT_RETURN) { if(n->stmtReturn.val) { generic_visitor(&n->stmtReturn.val, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); diff --git a/src/ast/ast.h b/src/ast/ast.h index 07b9e31..366b4c6 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -38,7 +38,7 @@ K(AST_EXPR_ARRAY) \ K(AST_EXPR_FUNC) \ K(AST_STMT_EXT_ORG) \ - K(AST_STMT_EXT_SECTION) \ + K(AST_SECTION) \ K(AST_STMT_RETURN) \ K(AST_EXPR_EXT_SALLOC) \ K(AST_EXPR_DOT) \ @@ -204,7 +204,17 @@ typedef struct { union AST *expression; } ASTStmtDecl; -typedef struct { +struct ASTChunk; +typedef struct ASTSection { + ASTBase; + + Token name; + struct ASTChunk *tlc; + + struct ASTSection *next; +} ASTSection; + +typedef struct ASTChunk { ASTBase; /* Flattened variable array for global register allocation */ @@ -300,12 +310,6 @@ typedef struct { size_t val; } ASTStmtExtOrg; -typedef struct { - ASTStmt; - - Token name; -} ASTStmtExtSection; - typedef struct { ASTStmt; @@ -364,7 +368,7 @@ typedef union AST { ASTExprDot exprDot; ASTExprExtSalloc exprExtSalloc; ASTStmtExtOrg stmtExtOrg; - ASTStmtExtSection stmtExtSection; + ASTSection section; ASTExprExtSizeOf exprExtSizeOf; ASTStmtJump stmtJump; ASTStmtLabel stmtLabel; diff --git a/src/ntc.c b/src/ntc.c index 3c10c9e..2a2a4bf 100644 --- a/src/ntc.c +++ b/src/ntc.c @@ -86,28 +86,30 @@ int main(int argc_, char **argv_) { if(in) fclose(f); - AST *chunk = nct_parse(tokens); + AST *sects = nct_parse(tokens); free(tokens); if(ntc_get_int("pdbg")) { - char *astdump = ast_dump(chunk); + char *astdump = ast_dump(sects); fprintf(stderr, "### ORIGINAL ###\n%s\n", astdump); free(astdump); } - ast_segmented_dereference(chunk); - ast_secondclass_record(chunk); - ast_sroa(chunk); + ast_segmented_dereference(sects); + ast_secondclass_record(sects); + ast_sroa(sects); - ast_linearize(chunk); + ast_linearize(sects); - arch_normalize_pre(chunk); + arch_normalize_pre(sects); - arch_normalize(chunk); - while(!cg_go(chunk)) { - arch_normalize(chunk); + arch_normalize(sects); + while(!cg_attempt_sections(sects)) { + arch_normalize(sects); } + cg_go_sections(sects); + return 0; } diff --git a/src/ntc.h b/src/ntc.h index 1a83298..91ce6b8 100644 --- a/src/ntc.h +++ b/src/ntc.h @@ -18,6 +18,7 @@ bool arch_verify_target(); int arch_ptr_size(); void arch_normalize_pre(union AST *tlc); void arch_normalize(union AST *tlc); -int cg_go(union AST *tlc); +int cg_attempt_sections(union AST *tlc); +void cg_go_sections(union AST *tlc); #endif diff --git a/src/parse.c b/src/parse.c index d801015..881f953 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1236,21 +1236,6 @@ static void nct_parse_statement(Parser *P) { expect(P, TOKEN_SEMICOLON); - pushstat(P, ret); - return; - } else if(!strcmp(peek(P, 0).content, "@section")) { - ASTStmtExtSection *ret = alloc_node(P, sizeof(*ret)); - ret->nodeKind = AST_STMT_EXT_SECTION; - ret->next = NULL; - - get(P); - - expect(P, TOKEN_PAREN_L); - ret->name = expect(P, TOKEN_STRING); - expect(P, TOKEN_PAREN_R); - - expect(P, TOKEN_SEMICOLON); - pushstat(P, ret); return; } else if(!strcmp(peek(P, 0).content, "@instantiate")) { @@ -1516,9 +1501,12 @@ Type *nct_parse_record_definition(Parser *P) { return tr; } -static void skim_chunk(Parser *P, int isTopLevel) { - /* Find all symbol names and struct types ahead of time. Searches for colons as those can only mean symbol declarations */ - +/* + * Find all symbol names and struct types ahead of time. + * Searches for colons as they can only mean symbol declarations. + * This function abuses Nectar's grammar to work, so malformed source + * code can fuck it up. */ +static void skim_tokens(Parser *P, int isTopLevel) { P->skimMode++; { intmax_t oldIdx = P->i; @@ -1606,7 +1594,7 @@ static void skim_chunk(Parser *P, int isTopLevel) { free(path); Parser subp = {.tokens = nct_lex(f), .scope = scope_new(NULL), .externalify = 1}; - skim_chunk(&subp, 1); + skim_tokens(&subp, 1); // Copy all extern symbols from the scope into our TLC's externs array for(size_t i = 0; i < subp.scope->count; i++) { @@ -1650,8 +1638,6 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t P->topLevel = &ret->chunk; } - skim_chunk(P, isTopLevel); - /* Arguments */ if(ft && isTopLevel) { P->topLevel->functionType = ft; @@ -1676,7 +1662,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t arch_add_hidden_variables(P->scope); - while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R) { + while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R && !(peek(P, 0).type == TOKEN_IDENTIFIER && !strcmp(peek(P, 0).content, "@section"))) { nct_parse_statement(P); } @@ -1711,9 +1697,49 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize, Scope *t return &ret->chunk; } +ASTSection *nct_parse_sections(Parser *P) { + ASTSection *start = alloc_node(P, sizeof(*start)); + start->nodeKind = AST_SECTION; + + ASTSection *current = start; + while(1) { + current->tlc = nct_parse_chunk(P, 1, 0, P->scope, NULL); + + if(peek(P, 0).type == TOKEN_EOF) { + break; + } + + if(!(peek(P, 0).type == TOKEN_IDENTIFIER && !strcmp(peek(P, 0).content, "@section"))) { + stahp_token(&P->tokens[P->i - 1], "Expected @section."); + } + + ASTSection *next = alloc_node(P, sizeof(*next)); + next->nodeKind = AST_SECTION; + + get(P); + expect(P, TOKEN_PAREN_L); + + next->name = expect(P, TOKEN_STRING); + + expect(P, TOKEN_PAREN_R); + expect(P, TOKEN_SEMICOLON); + + current->next = next; + current = next; + } + + return start; +} + AST *nct_parse(Token *tokens) { + Scope *scope = scope_new(NULL); + Parser P; memset(&P, 0, sizeof(P)); P.tokens = tokens; - return (AST*) nct_parse_chunk(&P, 1, 0, scope_new(NULL), NULL); + P.scope = scope; + + skim_tokens(&P, 1); + + return (AST*) nct_parse_sections(&P); } diff --git a/src/x86/cg.c b/src/x86/cg.c index f782961..9c3edf9 100644 --- a/src/x86/cg.c +++ b/src/x86/cg.c @@ -337,15 +337,6 @@ void cg_chunk(CGState *cg, AST *a) { printf("jmp .%s\n", s->stmtJump.label); } - } else if(s->nodeKind == AST_STMT_EXT_SECTION) { - - Token t = s->stmtExtSection.name; - printf("section %.*s\n", (int) t.length, t.content); - - } else if(s->nodeKind == AST_STMT_EXT_ORG) { - - printf("org %lu\n", s->stmtExtOrg.val); - } else if(s->nodeKind == AST_STMT_EXT_ALIGN) { uint32_t val = s->stmtExtAlign.val; @@ -401,13 +392,13 @@ void cg_chunk(CGState *cg, AST *a) { ast_linearize(s->stmtDecl.expression->exprFunc.chunk); - arch_normalize_pre(s->stmtDecl.expression->exprFunc.chunk); - arch_normalize(s->stmtDecl.expression->exprFunc.chunk); - while(!cg_go(s->stmtDecl.expression->exprFunc.chunk)) { + while(!cg_attempt_sections(s->stmtDecl.expression->exprFunc.chunk)) { arch_normalize(s->stmtDecl.expression->exprFunc.chunk); } + cg_go_sections(s->stmtDecl.expression->exprFunc.chunk); + } } else abort(); @@ -800,7 +791,7 @@ nextColor:; return mustSpillRegisterClass; } -int cg_go(AST *a) { +int cg_tlc(AST *a) { assert(a->nodeKind == AST_CHUNK); for(size_t e = 0; e < a->chunk.externCount; e++) { @@ -810,6 +801,23 @@ int cg_go(AST *a) { printf("extern %s\n", a->chunk.externs[e]->data.symbol.name); } + struct CalleeSavedState calleeSaved = {}; + if(a->chunk.functionType) { + callee_saved(a, &calleeSaved); + } + + CGState cg; + memset(&cg, 0, sizeof(cg)); + cg.tlc = a; + cg.isFunction = !!a->chunk.functionType; + cg.calleeSaved = calleeSaved; + + cg_chunk(&cg, a); + + return 1; +} + +static int cg_attempt(AST *a) { ast_usedef_reset(a); size_t adjCount = 0; @@ -899,19 +907,36 @@ cont:; return 0; } - struct CalleeSavedState calleeSaved = {}; - if(a->chunk.functionType) { - callee_saved(a, &calleeSaved); + return 1; +} + +int cg_attempt_sections(AST *a) { + assert(a->nodeKind == AST_SECTION); + + ASTSection *current = &a->section; + while(current) { + if(!cg_attempt(current->tlc)) { + return 0; + } + + current = current->next; } - CGState cg; - memset(&cg, 0, sizeof(cg)); - cg.tlc = a; - cg.isFunction = !!a->chunk.functionType; - cg.calleeSaved = calleeSaved; - - cg_chunk(&cg, a); - return 1; } +void cg_go_sections(AST *a) { + assert(a->nodeKind == AST_SECTION); + + ASTSection *current = &a->section; + while(current) { + if(current->name.content) { + printf("section %s\n", current->name.content); + } + + cg_tlc(current->tlc); + + current = current->next; + } +} + diff --git a/src/x86/normalize.c b/src/x86/normalize.c index 89b41a9..d79c681 100644 --- a/src/x86/normalize.c +++ b/src/x86/normalize.c @@ -107,8 +107,6 @@ struct NormState { static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, void *ud) { struct NormState *this = ud; - if(this->targetTLC != tlc) return; - AST *s = *nptr; if(s->nodeKind == AST_STMT_JUMP && s->stmtJump.condition) { @@ -477,8 +475,8 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) { AST *n = *nptr; - if(n == ud) { - if(tlc->chunk.functionType) { + if(n->nodeKind == AST_CHUNK) { + if(n->chunk.functionType) { size_t argCount = n->chunk.functionType->function.argCount; // First argCount vtes in list are the arguments @@ -533,8 +531,6 @@ static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A } static void decompose_symbol_record_field_access(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) { - if(tlc != (AST*) ud) return; - AST *n = *nptr; if(n->nodeKind == AST_EXPR_DOT) { @@ -593,8 +589,6 @@ struct DenoopState { static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) { struct DenoopState *state = ud; - if(state->targetTLC != tlc) return; - AST *n = *nptr; bool *success = &state->success; @@ -755,10 +749,6 @@ void ast_denoop(AST *tlc, AST **node) { * TODO: convert records to proper form also. */ static void convention_correctness_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) { - if(tlc != ud) { - return; - } - AST *n = *nptr; if(n->nodeKind == AST_EXPR_CALL) {