diff --git a/src/ast.c b/src/ast.c index 09a0f28..9e3fe52 100644 --- a/src/ast.c +++ b/src/ast.c @@ -385,7 +385,7 @@ static char *ast_dumpe(AST *e) { return strdup(vte->data.symbol.name); } else abort(); } else if(e->nodeKind == AST_EXPR_UNARY_OP) { - const char *op; + const char *op = NULL; switch(e->exprUnOp.operator) { case UNOP_REF: op = "&"; @@ -399,6 +399,8 @@ static char *ast_dumpe(AST *e) { case UNOP_NEGATE: op = "-"; break; + default: + abort(); } char *c = ast_dumpe(e->exprUnOp.operand); char *r = malp("%s%s", op, c); @@ -433,6 +435,9 @@ static char *ast_dumpe(AST *e) { case BINOP_EQUAL: op = "=="; break; + case BINOP_NEQUAL: + op = "!="; + break; default: abort(); } @@ -440,11 +445,15 @@ static char *ast_dumpe(AST *e) { free(a); free(b); return r; + } else if(e->nodeKind == AST_EXPR_STACK_POINTER) { + return malp("@stack"); } return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]); } +char *ast_dump(AST *tlc); + static char *ast_dumps(AST *s) { if(s->nodeKind == AST_STMT_DECL) { VarTableEntry *vte = s->stmtDecl.thing; @@ -464,6 +473,28 @@ static char *ast_dumps(AST *s) { free(a); free(b); return r; + } else if(s->nodeKind == AST_STMT_LOOP) { + char *inner = ast_dump(s->stmtLoop.body); + char *c = malp("loop {\n%s}\n", inner); + free(inner); + return c; + } else if(s->nodeKind == AST_STMT_IF) { + char *cond = ast_dumpe(s->stmtIf.expression); + char *inner = ast_dump(s->stmtIf.then); + char *c = malp("if(%s) {\n%s}\n", cond, inner); + free(cond); + free(inner); + return c; + } else if(s->nodeKind == AST_STMT_EXPR && s->stmtExpr.expr->nodeKind == AST_EXPR_VAR) { + const char *name; + + if(s->stmtExpr.expr->exprVar.thing->kind == VARTABLEENTRY_VAR) { + name = s->stmtExpr.expr->exprVar.thing->data.var.name; + } else { + name = s->stmtExpr.expr->exprVar.thing->data.symbol.name; + } + + return malp("%s; /* loop guard */\n", name); } return malp("@unimp:%s\n", AST_KIND_STR[s->nodeKind]); diff --git a/src/cg.c b/src/cg.c index b35a1e5..246a320 100644 --- a/src/cg.c +++ b/src/cg.c @@ -8,7 +8,13 @@ #include"x86.h" #define REGS 4 -static const char *regs[][3] = {{"al", "ax", "eax"}, {"bl", "bx", "ebx"}, {"cl", "cx", "ecx"}, {"dl", "dx", "edx"}, {"fu", "fk", "fck"}}; +static const char *regs[][3] = { + [COLOR_EAX] = {"al", "ax", "eax"}, + [COLOR_EBX] = {"bl", "bx", "ebx"}, + [COLOR_ECX] = {"cl", "cx", "ecx"}, + [COLOR_EDX] = {"dl", "dx", "edx"}, + {"fu", "fk", "fck"} +}; static const char *BINOP_SIMPLE_INSTRS[] = {[BINOP_ADD] = "add", [BINOP_SUB] = "sub", [BINOP_BITWISE_AND] = "and", [BINOP_BITWISE_OR] = "or", [BINOP_BITWISE_XOR] = "xor"}; @@ -21,6 +27,7 @@ static size_t loopStackIdx; static const char *direct(int size) { switch(size) { + case 0: case 1: return "db"; case 2: return "dw"; case 4: return "dd"; @@ -31,6 +38,7 @@ static const char *direct(int size) { static const char *spec(int size) { switch(size) { + case 0: case 1: return "byte"; case 2: return "word"; case 4: return "dword"; @@ -41,6 +49,7 @@ static const char *spec(int size) { static int log_size(int size) { switch(size) { + case 0: case 1: return 0; case 2: return 1; case 4: return 2; @@ -126,6 +135,8 @@ static const char *xop_sz(AST *e, int sz) { snprintf(ret, XOPBUFSZ, "%s", e->exprUnOp.operand->exprVar.thing->data.symbol.name); } else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF && e->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_VAR) { snprintf(ret, XOPBUFSZ, "%s [%s]", spec(sz), xv_sz(e->exprUnOp.operand->exprVar.thing, 4)); + } else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF && e->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operator == UNOP_DEREF && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_STACK_POINTER && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE) { + snprintf(ret, XOPBUFSZ, "[esp + %i]", e->exprUnOp.operand->exprBinOp.operands[1]->exprPrim.val); } else { return NULL; } @@ -142,6 +153,10 @@ static const char *xop(AST *e) { void cg_chunk(AST *a) { AST *s = a->chunk.statementFirst; + if(a->chunk.stackReservation) { + printf("sub esp, %lu\n", a->chunk.stackReservation); + } + // Potentially complex pattern matching while(s) { if(s->nodeKind == AST_STMT_EXT_SECTION) { @@ -196,9 +211,37 @@ void cg_chunk(AST *a) { } } + } else if(s->nodeKind == AST_STMT_ASSIGN && s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.what->exprVar.thing->kind == VARTABLEENTRY_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_CALL) { + + AST *e = s->stmtAssign.to; + + puts("push ecx"); + puts("push edx"); + + int argCount = e->exprCall.what->expression.type->function.argCount; + + size_t argSize = 0; + + for(int i = argCount - 1; i >= 0; i--) { + printf("push %s\n", xop_sz(e->exprCall.args[i], 4)); + + argSize += (type_size(e->exprCall.args[i]->expression.type) + 3) & ~3; + } + + assert(e->exprCall.what->nodeKind == AST_EXPR_VAR && e->exprCall.what->exprVar.thing->kind == VARTABLEENTRY_SYMBOL); + + printf("call %s\n", e->exprCall.what->exprVar.thing->data.symbol.name); + + if(argSize) printf("add esp, %lu\n", argSize); + + puts("pop edx"); + puts("pop ecx"); + } else if(s->nodeKind == AST_STMT_ASSIGN) { - if(s->stmtAssign.to) { + if(is_xop(s->stmtAssign.what) == XOP_NOT_MEM && is_xop(s->stmtAssign.to) == XOP_NOT_MEM && !strcmp(xop(s->stmtAssign.what), xop(s->stmtAssign.to))) { + // It's a noop + } else if(s->stmtAssign.to) { if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to->exprBinOp.operands[0]) && (s->stmtAssign.to->exprBinOp.operator == BINOP_ADD || s->stmtAssign.to->exprBinOp.operator == BINOP_SUB) && s->stmtAssign.to->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE && s->stmtAssign.to->exprBinOp.operands[1]->exprPrim.val == 1) { // inc or dec @@ -290,91 +333,84 @@ void cg_chunk(AST *a) { printf(".L%lu:\n", lbl); - } else if(s->nodeKind == AST_STMT_EXPR) { - - AST *e = s->stmtExpr.expr; - - if(e->nodeKind == AST_EXPR_CALL) { - puts("push eax"); - puts("push ecx"); - puts("push edx"); - - int argCount = e->exprCall.what->expression.type->function.argCount; - - size_t argSize = 0; - - for(int i = argCount - 1; i >= 0; i--) { - printf("push %s\n", xop(e->exprCall.args[i])); - - argSize += (type_size(e->exprCall.args[i]->expression.type) + 3) & ~3; - } - - assert(e->exprCall.what->nodeKind == AST_EXPR_VAR && e->exprCall.what->exprVar.thing->kind == VARTABLEENTRY_SYMBOL); - - printf("call %s\n", e->exprCall.what->exprVar.thing->data.symbol.name); - - printf("add esp, %lu\n", argSize); - - puts("pop edx"); - puts("pop ecx"); - puts("pop eax"); - } - } s = s->statement.next; } + + if(a->chunk.stackReservation) { + printf("add esp, %lu\n", a->chunk.stackReservation); + } } -static void spill_pass(AST *tlc, AST *a, VarTableEntry *vte) { +// MUST FIRST CALL with *aptr == tlc SO stackReservation IS UPDATED!! +static void spill_pass(AST *tlc, AST **aptr, VarTableEntry *vte) { + AST *a = *aptr; + if(a->nodeKind == AST_CHUNK) { - for(AST *s = a->chunk.statementFirst; s; s = s->statement.next) { - ast_usedef_pass(tlc, s, s); + for(AST **s = &a->chunk.statementFirst; *s; s = &((*s)->statement.next)) { + spill_pass(tlc, s, vte); } + + tlc->chunk.stackReservation += 4; } else if(a->nodeKind == AST_STMT_IF) { - pushdefsall(tlc); - - ast_usedef_pass(tlc, a->stmtIf.expression, wholestmt); - ast_usedef_pass(tlc, a->stmtIf.then, wholestmt); - - mergedefsall(tlc); + spill_pass(tlc, &a->stmtIf.expression, vte); + spill_pass(tlc, &a->stmtIf.then, vte); } else if(a->nodeKind == AST_STMT_LOOP) { - pushdefsall(tlc); - - ast_usedef_pass(tlc, a->stmtLoop.body, wholestmt); - - mergedefsloopall(tlc, a); + spill_pass(tlc, &a->stmtLoop.body, vte); } else if(a->nodeKind == AST_STMT_ASSIGN) { - if(a->stmtAssign.what->nodeKind == AST_EXPR_VAR && a->stmtAssign.what->exprVar.thing->kind == VARTABLEENTRY_VAR) { - overwritedefs(a->stmtAssign.what->exprVar.thing, a); - } - - ast_usedef_pass(tlc, a->stmtAssign.what, wholestmt); + spill_pass(tlc, &a->stmtAssign.what, vte); if(a->stmtAssign.to) { - ast_usedef_pass(tlc, a->stmtAssign.to, wholestmt); + spill_pass(tlc, &a->stmtAssign.to, vte); } } else if(a->nodeKind == AST_STMT_EXPR) { - ast_usedef_pass(tlc, a->stmtExpr.expr, wholestmt); + spill_pass(tlc, &a->stmtExpr.expr, vte); } else if(a->nodeKind == AST_EXPR_VAR) { - if(a->exprVar.thing->kind == VARTABLEENTRY_VAR) { - adduse(a->exprVar.thing, a, wholestmt); + + if(a->exprVar.thing == vte) { + // FINALLY SPILL + + ASTExprStackPointer *rsp = malloc(sizeof(*rsp)); + rsp->nodeKind = AST_EXPR_STACK_POINTER; + rsp->type = primitive_parse("u32"); + + ASTExprPrimitive *offset = malloc(sizeof(*offset)); + offset->nodeKind = AST_EXPR_PRIMITIVE; + offset->type = rsp->type; + offset->val = -tlc->chunk.stackReservation; + + ASTExprBinaryOp *bop = malloc(sizeof(*bop)); + bop->nodeKind = AST_EXPR_BINARY_OP; + bop->type = rsp->type; + bop->operator = BINOP_ADD; + bop->operands[0] = (AST*) rsp; + bop->operands[1] = (AST*) offset; + + ASTExprUnaryOp *deref = malloc(sizeof(*deref)); + deref->nodeKind = AST_EXPR_UNARY_OP; + deref->type = a->expression.type; + deref->operator = UNOP_DEREF; + deref->operand = (AST*) bop; + + *aptr = (AST*) deref; } + } else if(a->nodeKind == AST_EXPR_BINARY_OP) { - ast_usedef_pass(tlc, a->exprBinOp.operands[0], wholestmt); - ast_usedef_pass(tlc, a->exprBinOp.operands[1], wholestmt); + spill_pass(tlc, &a->exprBinOp.operands[0], vte); + spill_pass(tlc, &a->exprBinOp.operands[1], vte); } else if(a->nodeKind == AST_EXPR_UNARY_OP) { - ast_usedef_pass(tlc, a->exprUnOp.operand, wholestmt); + spill_pass(tlc, &a->exprUnOp.operand, vte); } else if(a->nodeKind == AST_EXPR_CALL) { - ast_usedef_pass(tlc, a->exprCall.what, wholestmt); + spill_pass(tlc, &a->exprCall.what, vte); for(size_t p = 0; p < a->exprCall.what->expression.type->function.argCount; p++) { - ast_usedef_pass(tlc, a->exprCall.args[p], wholestmt); + spill_pass(tlc, &a->exprCall.args[p], vte); } } else if(a->nodeKind == AST_EXPR_PRIMITIVE) { } else if(a->nodeKind == AST_EXPR_STRING_LITERAL) { } else if(a->nodeKind == AST_EXPR_CAST) { - ast_usedef_pass(tlc, a->exprCast.what, wholestmt); + spill_pass(tlc, &a->exprCast.what, vte); } else if(a->nodeKind == AST_EXPR_STACK_POINTER) { } else if(a->nodeKind == AST_STMT_BREAK) { } else if(a->nodeKind == AST_STMT_CONTINUE) { @@ -388,6 +424,13 @@ static void spill_pass(AST *tlc, AST *a, VarTableEntry *vte) { } } +static int ud_empty(VarTableEntry *a) { + assert(a->kind == VARTABLEENTRY_VAR); + assert(!a->data.var.usedefFirst == !a->data.var.usedefLast); + + return !a->data.var.usedefFirst; +} + /* Welsh-Powell graph coloring */ static int comparator(const void *A, const void *B) { VarTableEntry *const *a = A; @@ -400,15 +443,14 @@ int cg_go(AST *a) { ast_usedef_reset(a); size_t adjCount = 0; - Adjacency *adjs = malloc(sizeof(*adjs) * adjCount); + Adjacency *adjs = calloc(adjCount, sizeof(*adjs)); VarTableEntry **vars = a->chunk.vars; for(size_t vi = 0; vi < a->chunk.varCount; vi++) { vars[vi]->data.var.priority = 1; - vars[vi]->data.var.color = 0; + //vars[vi]->data.var.color = 0; vars[vi]->data.var.degree = 0; - vars[vi]->data.var.markedForSpill = 0; } for(size_t v1i = 0; v1i < a->chunk.varCount; v1i++) { @@ -419,15 +461,13 @@ int cg_go(AST *a) { VarTableEntry *v2 = vars[v2i]; /* 1D intersection test */ -// if((v1->data.var.start >= v2->data.var.start && v1->data.var.start <= v2->data.var.end) -// || (v1->data.var.end >= v2->data.var.start && v1->data.var.end <= v2->data.var.end)) { - if( + if(!ud_empty(v1) && !ud_empty(v2) && ( (ast_stmt_is_after(a, v1->data.var.usedefFirst->stmt, v2->data.var.usedefFirst->stmt) == 1 && ast_stmt_is_after(a, v2->data.var.usedefLast->stmt, v1->data.var.usedefFirst->stmt) == 1) || (ast_stmt_is_after(a, v1->data.var.usedefLast->stmt, v2->data.var.usedefFirst->stmt) == 1 && ast_stmt_is_after(a, v2->data.var.usedefLast->stmt, v1->data.var.usedefLast->stmt) == 1) - ) { + )) { VarTableEntry *min = v1 < v2 ? v1 : v2; VarTableEntry *max = v1 < v2 ? v2 : v1; @@ -457,11 +497,16 @@ cont:; /* Welsh plow my ass */ for(int v = 0; v < a->chunk.varCount; v++) { + if(vars[v]->data.var.color != -1) { + // Already assigned. + continue; + } + for(int c = 0;; c++) { for(int a = 0; a < adjCount; a++) { - if(adjs[a][0] == vars[v] && adjs[a][1]->data.var.color == c) { + if(adjs[a][0] == vars[v] && adjs[a][1]->data.var.color != -1 && adjs[a][1]->data.var.color == c) { goto nextColor; - } else if(adjs[a][1] == vars[v] && adjs[a][0]->data.var.color == c) { + } else if(adjs[a][1] == vars[v] && adjs[a][0]->data.var.color != -1 && adjs[a][0]->data.var.color == c) { goto nextColor; } } @@ -481,7 +526,7 @@ nextColor:; if(lastColor >= 4) { // Spill node with highest degree - spill_pass(a, a, vars[a->chunk.varCount - 1]); + spill_pass(a, &a, vars[a->chunk.varCount - 1]); return 0; } diff --git a/src/dumberdowner.c b/src/dumberdowner.c index d3a3166..5a53c9d 100644 --- a/src/dumberdowner.c +++ b/src/dumberdowner.c @@ -22,6 +22,7 @@ static AST *varify(AST *tlc, AST *chunk, AST *stmtPrev, AST *stmt, AST *e) { vte->data.var.degree = 0; vte->data.var.priority = 0; vte->data.var.reachingDefs = NULL; + vte->data.var.name = strdup("googoo"); // Add to var array tlc->chunk.vars = realloc(tlc->chunk.vars, sizeof(*tlc->chunk.vars) * (++tlc->chunk.varCount)); @@ -107,79 +108,84 @@ static int dumben_chunk(AST *tlc, AST *chu) { } else if(s->nodeKind == AST_STMT_ASSIGN) { - if(s->stmtAssign.what->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.what->exprUnOp.operator == UNOP_DEREF - && s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) { - - s->stmtAssign.to = varify(tlc, chu, sPrev, s, s->stmtAssign.to); + if(ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to) && sPrev) { + // Remove this statement from AST + sPrev->statement.next = s->statement.next; effective = 1; - } - - if(s->stmtAssign.to && s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_NEGATE && !ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to->exprUnOp.operand)) { - // Turn this: - // a = -b - // into - // a = b - // a = -a + } else { - AST *ev[2] = { - ast_deep_copy(s->stmtAssign.what), - ast_deep_copy(s->stmtAssign.what) - }; - - AST *negation = s->stmtAssign.to; - - s->stmtAssign.to = negation->exprUnOp.operand; - negation->exprUnOp.operand = ev[0]; - - AST *assign2 = malloc(sizeof(ASTStmtAssign)); - assign2->nodeKind = AST_STMT_ASSIGN; - assign2->stmtAssign.what = ev[1]; - assign2->stmtAssign.to = negation; - - assign2->statement.next = s->statement.next; - s->statement.next = assign2; - - effective = 1; - } - - if(is_xop(s->stmtAssign.to) == XOP_NOT_XOP) { - if(s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) { - s->stmtAssign.to->exprUnOp.operand = varify(tlc, chu, sPrev, s, s->stmtAssign.to->exprUnOp.operand); + if(s->stmtAssign.what->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.what->exprUnOp.operator == UNOP_DEREF + && s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) { + s->stmtAssign.to = varify(tlc, chu, sPrev, s, s->stmtAssign.to); effective = 1; - } else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator < BINOP_SIMPLES && !ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to->exprBinOp.operands[0])) { + } else if(s->stmtAssign.what && s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.what->exprVar.thing->kind == VARTABLEENTRY_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_CALL) { + ASTExprCall *call = &s->stmtAssign.to->exprCall; + + int argCount = call->what->expression.type->function.argCount; + + for(int i = 0; i < argCount; i++) { + if(is_xop(call->args[i]) == XOP_NOT_XOP) { + call->args[i] = xopify(tlc, chu, sPrev, s, call->args[i]); + effective = 1; + } + } + } else if(s->stmtAssign.to && s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_NEGATE && !ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to->exprUnOp.operand)) { // Turn this: - // a = b op c + // a = -b // into // a = b - // a = a op c + // a = -a + + AST *ev[2] = { + ast_deep_copy(s->stmtAssign.what), + ast_deep_copy(s->stmtAssign.what) + }; + + AST *negation = s->stmtAssign.to; + + s->stmtAssign.to = negation->exprUnOp.operand; + negation->exprUnOp.operand = ev[0]; AST *assign2 = malloc(sizeof(ASTStmtAssign)); assign2->nodeKind = AST_STMT_ASSIGN; - assign2->stmtAssign.what = ast_deep_copy(s->stmtAssign.what); - assign2->stmtAssign.to = s->stmtAssign.to->exprBinOp.operands[0]; + assign2->stmtAssign.what = ev[1]; + assign2->stmtAssign.to = negation; - sPrev->statement.next = assign2; - assign2->statement.next = s; - - s->stmtAssign.to->exprBinOp.operands[0] = ast_deep_copy(s->stmtAssign.what); + assign2->statement.next = s->statement.next; + s->statement.next = assign2; effective = 1; - } else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && !is_xop(s->stmtAssign.to->exprBinOp.operands[0])) { - s->stmtAssign.to->exprBinOp.operands[0] = xopify(tlc, chu, sPrev, s, s->stmtAssign.to->exprBinOp.operands[0]); - } else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && !is_xop(s->stmtAssign.to->exprBinOp.operands[1])) { - s->stmtAssign.to->exprBinOp.operands[1] = xopify(tlc, chu, sPrev, s, s->stmtAssign.to->exprBinOp.operands[1]); - } - } - - } else if(s->nodeKind == AST_STMT_EXPR && s->stmtExpr.expr->nodeKind == AST_EXPR_CALL) { - - int argCount = s->stmtExpr.expr->exprCall.what->expression.type->function.argCount; - - for(int i = 0; i < argCount; i++) { - if(is_xop(s->stmtExpr.expr->exprCall.args[i]) == XOP_NOT_XOP) { - s->stmtExpr.expr->exprCall.args[i] = xopify(tlc, chu, sPrev, s, s->stmtExpr.expr->exprCall.args[i]); - effective = 1; + } else if(is_xop(s->stmtAssign.to) == XOP_NOT_XOP) { + if(s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) { + s->stmtAssign.to->exprUnOp.operand = varify(tlc, chu, sPrev, s, s->stmtAssign.to->exprUnOp.operand); + + effective = 1; + } else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator < BINOP_SIMPLES && !ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to->exprBinOp.operands[0])) { + // Turn this: + // a = b op c + // into + // a = b + // a = a op c + + AST *assign2 = malloc(sizeof(ASTStmtAssign)); + assign2->nodeKind = AST_STMT_ASSIGN; + assign2->stmtAssign.what = ast_deep_copy(s->stmtAssign.what); + assign2->stmtAssign.to = s->stmtAssign.to->exprBinOp.operands[0]; + + sPrev->statement.next = assign2; + assign2->statement.next = s; + + s->stmtAssign.to->exprBinOp.operands[0] = ast_deep_copy(s->stmtAssign.what); + + effective = 1; + } else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && !is_xop(s->stmtAssign.to->exprBinOp.operands[0])) { + s->stmtAssign.to->exprBinOp.operands[0] = xopify(tlc, chu, sPrev, s, s->stmtAssign.to->exprBinOp.operands[0]); + effective = 1; + } else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && !is_xop(s->stmtAssign.to->exprBinOp.operands[1])) { + s->stmtAssign.to->exprBinOp.operands[1] = xopify(tlc, chu, sPrev, s, s->stmtAssign.to->exprBinOp.operands[1]); + effective = 1; + } } } @@ -193,5 +199,12 @@ static int dumben_chunk(AST *tlc, AST *chu) { } void dumben_go(AST* tlc) { - while(dumben_chunk(tlc, tlc)); + size_t i = 0; + while(1) { + fprintf(stderr, "// Dumbing down %lu...\n", i++); + + int successful = dumben_chunk(tlc, tlc); + + if(!successful) break; + } } diff --git a/src/lexer.c b/src/lexer.c index 9c906b8..3c5af57 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -36,7 +36,8 @@ char *TOKEN_NAMES[] = { "'?'", "string" "'!='", - "'!'" + "'!'", + "'continue'", }; static int isAlpha(int c) { diff --git a/src/ntc.c b/src/ntc.c index 60245c1..59d141a 100644 --- a/src/ntc.c +++ b/src/ntc.c @@ -37,14 +37,17 @@ int main(int argc_, char **argv_) { free(tokens); + fputs("/* === Original AST === */\n", stderr); + fputs(ast_dump(chunk), stderr); + fputc('\n', stderr); + dumben_go(chunk); - while(!cg_go(chunk)) { - - puts(ast_dump(chunk)); - - dumben_go(chunk); - } + fputs("\n/* === Dumbified === */\n", stderr); + fputs(ast_dump(chunk), stderr); + fputc('\n', stderr); + + while(!cg_go(chunk)); return 0; } diff --git a/src/parse.c b/src/parse.c index a6b2e08..dbf5159 100644 --- a/src/parse.c +++ b/src/parse.c @@ -8,6 +8,7 @@ #include"reporting.h" #include #include +#include"x86.h" #ifndef __GNUC__ static inline int __builtin_clzl(unsigned long x) { @@ -241,7 +242,7 @@ AST *nct_parse_expression(Parser *P, int lOP) { ASTExprStackPointer *ret = malloc(sizeof(*ret)); ret->nodeKind = AST_EXPR_STACK_POINTER; ret->type = primitive_parse("u32"); - return ret; + return (AST*) ret; } return exprvar(P, vartable_find(P->scope, get(P).content)); @@ -297,8 +298,7 @@ AST *nct_parse_expression(Parser *P, int lOP) { AST *child = nct_parse_expression(P, lOP); if(child->nodeKind == AST_EXPR_PRIMITIVE) { - child->exprPrim.val = \ - ~child->exprPrim.val; + child->exprPrim.val = ~child->exprPrim.val; return child; } else { ASTExprUnaryOp *astop = malloc(sizeof(*astop)); @@ -319,12 +319,20 @@ AST *nct_parse_expression(Parser *P, int lOP) { stahp(P->tokens[P->i].row, P->tokens[P->i].column, "Only function types may be called."); } + VarTableEntry *tempo = calloc(1, sizeof(*tempo)); + tempo->kind = VARTABLEENTRY_VAR; + tempo->type = ret->expression.type->function.ret; + tempo->data.var.name = "$temp"; + tempo->data.var.color = COLOR_EAX; + + P->topLevel->vars = realloc(P->topLevel->vars, sizeof(*P->topLevel->vars) * (++P->topLevel->varCount)); + P->topLevel->vars[P->topLevel->varCount - 1] = tempo; + ASTExprCall *call = malloc(sizeof(*call)); call->nodeKind = AST_EXPR_CALL; call->type = ret->expression.type->function.ret; call->what = ret; call->args = NULL; - ret = (AST*) call; int argCount = 0; @@ -341,6 +349,14 @@ AST *nct_parse_expression(Parser *P, int lOP) { } } + ASTStmtAssign *assign = calloc(1, sizeof(*assign)); + assign->nodeKind = AST_STMT_ASSIGN; + assign->what = exprvar(P, tempo); + assign->to = call; + + pushstat(P, assign); + + ret = exprvar(P, tempo); /* TODO: Check argument count. */ } else if(maybe(P, TOKEN_SQUAREN_L)) { ASTExprUnaryOp *ref = malloc(sizeof(*ref)); @@ -366,10 +382,10 @@ AST *nct_parse_expression(Parser *P, int lOP) { ASTExprBinaryOp *mul = malloc(sizeof(*mul)); mul->nodeKind = AST_EXPR_BINARY_OP; mul->operator = BINOP_MUL; - mul->operands[0] = scale; + mul->operands[0] = (AST*) scale; mul->operands[1] = child->operands[1]; - child->operands[1] = mul; + child->operands[1] = (AST*) mul; } ASTExprUnaryOp *unop = malloc(sizeof(*unop)); @@ -631,6 +647,7 @@ static AST *parse_declaration(Parser *P) { entry->kind = VARTABLEENTRY_VAR; entry->data.var.priority = 1; + entry->data.var.color = -1; ASTStmtAssign *assign = malloc(sizeof(*assign)); assign->nodeKind = AST_STMT_ASSIGN; @@ -735,7 +752,7 @@ void nct_parse_statement(Parser *P) { AST *es = calloc(1, sizeof(ASTStmtExpr)); es->nodeKind = AST_STMT_EXPR; - es->stmtExpr.expr = ev; + es->stmtExpr.expr = (AST*) ev; pushstat(P, es); } @@ -863,9 +880,10 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) { ret->chunk.statementFirst = ret->chunk.statementLast = NULL; ret->chunk.varCount = 0; ret->chunk.vars = NULL; + ret->chunk.stackReservation = 0; - AST *oldChunk = P->currentChunk; - P->currentChunk = (AST*) ret; + AST *oldChunk = (AST*) P->currentChunk; + P->currentChunk = &ret->chunk; P->scope = vartable_new(P->scope); @@ -933,7 +951,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) { for(size_t i = 0; i < P->scope->count; i++) { if(P->scope->data[i]->kind == VARTABLEENTRY_VAR) { P->topLevel->vars[P->topLevel->varCount++] = P->scope->data[i]; - P->scope->data[i]->owner = P->topLevel; + //P->scope->data[i]->owner = P->topLevel; // not sure why this line ever existed, it makes no sense } } diff --git a/src/vartable.h b/src/vartable.h index 95385d9..ea81eed 100644 --- a/src/vartable.h +++ b/src/vartable.h @@ -52,7 +52,7 @@ typedef struct VarTableEntry { // vars in loops have higher priority // a more advanced approach would be to use weights for different colors (e.g. multipliers "should" be in eax) uint8_t priority; - uint16_t color, degree; + int16_t color, degree; // Used during parsing diff --git a/src/x86.h b/src/x86.h index 3666d06..8518169 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,5 +1,10 @@ #pragma once +#define COLOR_EAX 0 +#define COLOR_EBX 1 +#define COLOR_ECX 2 +#define COLOR_EDX 3 + // Can expression be expressed as a single x86 operand? #define XOP_NOT_XOP 0 #define XOP_NOT_MEM 1 @@ -9,7 +14,7 @@ static inline int is_xop(AST *e) { return XOP_NOT_MEM; } else if(e->nodeKind == AST_EXPR_VAR) { return e->exprVar.thing->kind == VARTABLEENTRY_VAR ? XOP_NOT_MEM : XOP_MEM; - } else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF && e->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operator == BINOP_ADD && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprVar.thing->kind == VARTABLEENTRY_VAR && e->exprUnOp.operand->exprBinOp.operands[1]->exprVar.thing->kind == VARTABLEENTRY_VAR) { + } else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF && e->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operator == BINOP_ADD && is_xop(e->exprUnOp.operand->exprBinOp.operands[0]) == XOP_NOT_MEM && is_xop(e->exprUnOp.operand->exprBinOp.operands[1]) == XOP_NOT_MEM) { return XOP_MEM; } else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL) { return XOP_NOT_MEM; diff --git a/tests/functions.nct b/tests/functions.nct index 645847d..4ac7695 100644 --- a/tests/functions.nct +++ b/tests/functions.nct @@ -1,9 +1,12 @@ -extern u32() getchar; -extern void(u32) putchar; +extern s32() getchar; +extern u0(s32) putchar; loop { - u8 a = getchar(); - if(a - 48) { - putchar(a); + u8 z = 5; + s32 a = getchar(); + if(a == -1) { + break; } -} \ No newline at end of file + putchar(a); + putchar(z); +}