Sections are now top-level nodes (which contain TLCs)
Previously, `@section` was a statement inside a top-level chunk, which caused issues when the TLC allocated stack memory (the prologue was generated before the `@section`). This way, Nectar source code is now defined as a list of sections, first and foremost.
This commit is contained in:
parent
7a8b14308b
commit
f406b2a032
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
22
src/ntc.c
22
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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
72
src/parse.c
72
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);
|
||||
}
|
||||
|
||||
73
src/x86/cg.c
73
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user