Spilling
This commit is contained in:
parent
9e04938065
commit
fe0baa26a0
33
src/ast.c
33
src/ast.c
@ -385,7 +385,7 @@ static char *ast_dumpe(AST *e) {
|
|||||||
return strdup(vte->data.symbol.name);
|
return strdup(vte->data.symbol.name);
|
||||||
} else abort();
|
} else abort();
|
||||||
} else if(e->nodeKind == AST_EXPR_UNARY_OP) {
|
} else if(e->nodeKind == AST_EXPR_UNARY_OP) {
|
||||||
const char *op;
|
const char *op = NULL;
|
||||||
switch(e->exprUnOp.operator) {
|
switch(e->exprUnOp.operator) {
|
||||||
case UNOP_REF:
|
case UNOP_REF:
|
||||||
op = "&";
|
op = "&";
|
||||||
@ -399,6 +399,8 @@ static char *ast_dumpe(AST *e) {
|
|||||||
case UNOP_NEGATE:
|
case UNOP_NEGATE:
|
||||||
op = "-";
|
op = "-";
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
char *c = ast_dumpe(e->exprUnOp.operand);
|
char *c = ast_dumpe(e->exprUnOp.operand);
|
||||||
char *r = malp("%s%s", op, c);
|
char *r = malp("%s%s", op, c);
|
||||||
@ -433,6 +435,9 @@ static char *ast_dumpe(AST *e) {
|
|||||||
case BINOP_EQUAL:
|
case BINOP_EQUAL:
|
||||||
op = "==";
|
op = "==";
|
||||||
break;
|
break;
|
||||||
|
case BINOP_NEQUAL:
|
||||||
|
op = "!=";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -440,11 +445,15 @@ static char *ast_dumpe(AST *e) {
|
|||||||
free(a);
|
free(a);
|
||||||
free(b);
|
free(b);
|
||||||
return r;
|
return r;
|
||||||
|
} else if(e->nodeKind == AST_EXPR_STACK_POINTER) {
|
||||||
|
return malp("@stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]);
|
return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *ast_dump(AST *tlc);
|
||||||
|
|
||||||
static char *ast_dumps(AST *s) {
|
static char *ast_dumps(AST *s) {
|
||||||
if(s->nodeKind == AST_STMT_DECL) {
|
if(s->nodeKind == AST_STMT_DECL) {
|
||||||
VarTableEntry *vte = s->stmtDecl.thing;
|
VarTableEntry *vte = s->stmtDecl.thing;
|
||||||
@ -464,6 +473,28 @@ static char *ast_dumps(AST *s) {
|
|||||||
free(a);
|
free(a);
|
||||||
free(b);
|
free(b);
|
||||||
return r;
|
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]);
|
return malp("@unimp:%s\n", AST_KIND_STR[s->nodeKind]);
|
||||||
|
187
src/cg.c
187
src/cg.c
@ -8,7 +8,13 @@
|
|||||||
#include"x86.h"
|
#include"x86.h"
|
||||||
|
|
||||||
#define REGS 4
|
#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"};
|
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) {
|
static const char *direct(int size) {
|
||||||
switch(size) {
|
switch(size) {
|
||||||
|
case 0:
|
||||||
case 1: return "db";
|
case 1: return "db";
|
||||||
case 2: return "dw";
|
case 2: return "dw";
|
||||||
case 4: return "dd";
|
case 4: return "dd";
|
||||||
@ -31,6 +38,7 @@ static const char *direct(int size) {
|
|||||||
|
|
||||||
static const char *spec(int size) {
|
static const char *spec(int size) {
|
||||||
switch(size) {
|
switch(size) {
|
||||||
|
case 0:
|
||||||
case 1: return "byte";
|
case 1: return "byte";
|
||||||
case 2: return "word";
|
case 2: return "word";
|
||||||
case 4: return "dword";
|
case 4: return "dword";
|
||||||
@ -41,6 +49,7 @@ static const char *spec(int size) {
|
|||||||
|
|
||||||
static int log_size(int size) {
|
static int log_size(int size) {
|
||||||
switch(size) {
|
switch(size) {
|
||||||
|
case 0:
|
||||||
case 1: return 0;
|
case 1: return 0;
|
||||||
case 2: return 1;
|
case 2: return 1;
|
||||||
case 4: return 2;
|
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);
|
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) {
|
} 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));
|
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 {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -142,6 +153,10 @@ static const char *xop(AST *e) {
|
|||||||
void cg_chunk(AST *a) {
|
void cg_chunk(AST *a) {
|
||||||
AST *s = a->chunk.statementFirst;
|
AST *s = a->chunk.statementFirst;
|
||||||
|
|
||||||
|
if(a->chunk.stackReservation) {
|
||||||
|
printf("sub esp, %lu\n", a->chunk.stackReservation);
|
||||||
|
}
|
||||||
|
|
||||||
// Potentially complex pattern matching
|
// Potentially complex pattern matching
|
||||||
while(s) {
|
while(s) {
|
||||||
if(s->nodeKind == AST_STMT_EXT_SECTION) {
|
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) {
|
} 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) {
|
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
|
// inc or dec
|
||||||
@ -290,91 +333,84 @@ void cg_chunk(AST *a) {
|
|||||||
|
|
||||||
printf(".L%lu:\n", lbl);
|
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;
|
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) {
|
if(a->nodeKind == AST_CHUNK) {
|
||||||
for(AST *s = a->chunk.statementFirst; s; s = s->statement.next) {
|
for(AST **s = &a->chunk.statementFirst; *s; s = &((*s)->statement.next)) {
|
||||||
ast_usedef_pass(tlc, s, s);
|
spill_pass(tlc, s, vte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlc->chunk.stackReservation += 4;
|
||||||
} else if(a->nodeKind == AST_STMT_IF) {
|
} else if(a->nodeKind == AST_STMT_IF) {
|
||||||
pushdefsall(tlc);
|
spill_pass(tlc, &a->stmtIf.expression, vte);
|
||||||
|
spill_pass(tlc, &a->stmtIf.then, vte);
|
||||||
ast_usedef_pass(tlc, a->stmtIf.expression, wholestmt);
|
|
||||||
ast_usedef_pass(tlc, a->stmtIf.then, wholestmt);
|
|
||||||
|
|
||||||
mergedefsall(tlc);
|
|
||||||
} else if(a->nodeKind == AST_STMT_LOOP) {
|
} else if(a->nodeKind == AST_STMT_LOOP) {
|
||||||
pushdefsall(tlc);
|
spill_pass(tlc, &a->stmtLoop.body, vte);
|
||||||
|
|
||||||
ast_usedef_pass(tlc, a->stmtLoop.body, wholestmt);
|
|
||||||
|
|
||||||
mergedefsloopall(tlc, a);
|
|
||||||
} else if(a->nodeKind == AST_STMT_ASSIGN) {
|
} else if(a->nodeKind == AST_STMT_ASSIGN) {
|
||||||
if(a->stmtAssign.what->nodeKind == AST_EXPR_VAR && a->stmtAssign.what->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
spill_pass(tlc, &a->stmtAssign.what, vte);
|
||||||
overwritedefs(a->stmtAssign.what->exprVar.thing, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
ast_usedef_pass(tlc, a->stmtAssign.what, wholestmt);
|
|
||||||
|
|
||||||
if(a->stmtAssign.to) {
|
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) {
|
} 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) {
|
} 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) {
|
} else if(a->nodeKind == AST_EXPR_BINARY_OP) {
|
||||||
ast_usedef_pass(tlc, a->exprBinOp.operands[0], wholestmt);
|
spill_pass(tlc, &a->exprBinOp.operands[0], vte);
|
||||||
ast_usedef_pass(tlc, a->exprBinOp.operands[1], wholestmt);
|
spill_pass(tlc, &a->exprBinOp.operands[1], vte);
|
||||||
} else if(a->nodeKind == AST_EXPR_UNARY_OP) {
|
} 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) {
|
} 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++) {
|
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_PRIMITIVE) {
|
||||||
} else if(a->nodeKind == AST_EXPR_STRING_LITERAL) {
|
} else if(a->nodeKind == AST_EXPR_STRING_LITERAL) {
|
||||||
} else if(a->nodeKind == AST_EXPR_CAST) {
|
} 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_EXPR_STACK_POINTER) {
|
||||||
} else if(a->nodeKind == AST_STMT_BREAK) {
|
} else if(a->nodeKind == AST_STMT_BREAK) {
|
||||||
} else if(a->nodeKind == AST_STMT_CONTINUE) {
|
} 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 */
|
/* Welsh-Powell graph coloring */
|
||||||
static int comparator(const void *A, const void *B) {
|
static int comparator(const void *A, const void *B) {
|
||||||
VarTableEntry *const *a = A;
|
VarTableEntry *const *a = A;
|
||||||
@ -400,15 +443,14 @@ int cg_go(AST *a) {
|
|||||||
ast_usedef_reset(a);
|
ast_usedef_reset(a);
|
||||||
|
|
||||||
size_t adjCount = 0;
|
size_t adjCount = 0;
|
||||||
Adjacency *adjs = malloc(sizeof(*adjs) * adjCount);
|
Adjacency *adjs = calloc(adjCount, sizeof(*adjs));
|
||||||
|
|
||||||
VarTableEntry **vars = a->chunk.vars;
|
VarTableEntry **vars = a->chunk.vars;
|
||||||
|
|
||||||
for(size_t vi = 0; vi < a->chunk.varCount; vi++) {
|
for(size_t vi = 0; vi < a->chunk.varCount; vi++) {
|
||||||
vars[vi]->data.var.priority = 1;
|
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.degree = 0;
|
||||||
vars[vi]->data.var.markedForSpill = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t v1i = 0; v1i < a->chunk.varCount; v1i++) {
|
for(size_t v1i = 0; v1i < a->chunk.varCount; v1i++) {
|
||||||
@ -419,15 +461,13 @@ int cg_go(AST *a) {
|
|||||||
VarTableEntry *v2 = vars[v2i];
|
VarTableEntry *v2 = vars[v2i];
|
||||||
|
|
||||||
/* 1D intersection test */
|
/* 1D intersection test */
|
||||||
// if((v1->data.var.start >= v2->data.var.start && v1->data.var.start <= v2->data.var.end)
|
if(!ud_empty(v1) && !ud_empty(v2) && (
|
||||||
// || (v1->data.var.end >= v2->data.var.start && v1->data.var.end <= v2->data.var.end)) {
|
|
||||||
if(
|
|
||||||
(ast_stmt_is_after(a, v1->data.var.usedefFirst->stmt, v2->data.var.usedefFirst->stmt) == 1
|
(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, 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, 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)
|
&& ast_stmt_is_after(a, v2->data.var.usedefLast->stmt, v1->data.var.usedefLast->stmt) == 1)
|
||||||
) {
|
)) {
|
||||||
VarTableEntry *min = v1 < v2 ? v1 : v2;
|
VarTableEntry *min = v1 < v2 ? v1 : v2;
|
||||||
VarTableEntry *max = v1 < v2 ? v2 : v1;
|
VarTableEntry *max = v1 < v2 ? v2 : v1;
|
||||||
|
|
||||||
@ -457,11 +497,16 @@ cont:;
|
|||||||
|
|
||||||
/* Welsh plow my ass */
|
/* Welsh plow my ass */
|
||||||
for(int v = 0; v < a->chunk.varCount; v++) {
|
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 c = 0;; c++) {
|
||||||
for(int a = 0; a < adjCount; a++) {
|
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;
|
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;
|
goto nextColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -481,7 +526,7 @@ nextColor:;
|
|||||||
if(lastColor >= 4) {
|
if(lastColor >= 4) {
|
||||||
// Spill node with highest degree
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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.degree = 0;
|
||||||
vte->data.var.priority = 0;
|
vte->data.var.priority = 0;
|
||||||
vte->data.var.reachingDefs = NULL;
|
vte->data.var.reachingDefs = NULL;
|
||||||
|
vte->data.var.name = strdup("googoo");
|
||||||
|
|
||||||
// Add to var array
|
// Add to var array
|
||||||
tlc->chunk.vars = realloc(tlc->chunk.vars, sizeof(*tlc->chunk.vars) * (++tlc->chunk.varCount));
|
tlc->chunk.vars = realloc(tlc->chunk.vars, sizeof(*tlc->chunk.vars) * (++tlc->chunk.varCount));
|
||||||
@ -107,14 +108,29 @@ static int dumben_chunk(AST *tlc, AST *chu) {
|
|||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_ASSIGN) {
|
} else if(s->nodeKind == AST_STMT_ASSIGN) {
|
||||||
|
|
||||||
|
if(ast_expression_equal(s->stmtAssign.what, s->stmtAssign.to) && sPrev) {
|
||||||
|
// Remove this statement from AST
|
||||||
|
sPrev->statement.next = s->statement.next;
|
||||||
|
effective = 1;
|
||||||
|
} else {
|
||||||
|
|
||||||
if(s->stmtAssign.what->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.what->exprUnOp.operator == UNOP_DEREF
|
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->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_DEREF) {
|
||||||
|
|
||||||
s->stmtAssign.to = varify(tlc, chu, sPrev, s, s->stmtAssign.to);
|
s->stmtAssign.to = varify(tlc, chu, sPrev, s, s->stmtAssign.to);
|
||||||
effective = 1;
|
effective = 1;
|
||||||
}
|
} 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;
|
||||||
|
|
||||||
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)) {
|
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:
|
// Turn this:
|
||||||
// a = -b
|
// a = -b
|
||||||
// into
|
// into
|
||||||
@ -140,9 +156,7 @@ static int dumben_chunk(AST *tlc, AST *chu) {
|
|||||||
s->statement.next = assign2;
|
s->statement.next = assign2;
|
||||||
|
|
||||||
effective = 1;
|
effective = 1;
|
||||||
}
|
} else if(is_xop(s->stmtAssign.to) == XOP_NOT_XOP) {
|
||||||
|
|
||||||
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) {
|
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);
|
s->stmtAssign.to->exprUnOp.operand = varify(tlc, chu, sPrev, s, s->stmtAssign.to->exprUnOp.operand);
|
||||||
|
|
||||||
@ -167,21 +181,13 @@ static int dumben_chunk(AST *tlc, AST *chu) {
|
|||||||
effective = 1;
|
effective = 1;
|
||||||
} else if(s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && !is_xop(s->stmtAssign.to->exprBinOp.operands[0])) {
|
} 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]);
|
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])) {
|
} 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]);
|
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;
|
effective = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,5 +199,12 @@ static int dumben_chunk(AST *tlc, AST *chu) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dumben_go(AST* tlc) {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ char *TOKEN_NAMES[] = {
|
|||||||
"'?'",
|
"'?'",
|
||||||
"string"
|
"string"
|
||||||
"'!='",
|
"'!='",
|
||||||
"'!'"
|
"'!'",
|
||||||
|
"'continue'",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int isAlpha(int c) {
|
static int isAlpha(int c) {
|
||||||
|
15
src/ntc.c
15
src/ntc.c
@ -37,14 +37,17 @@ int main(int argc_, char **argv_) {
|
|||||||
|
|
||||||
free(tokens);
|
free(tokens);
|
||||||
|
|
||||||
dumben_go(chunk);
|
fputs("/* === Original AST === */\n", stderr);
|
||||||
|
fputs(ast_dump(chunk), stderr);
|
||||||
while(!cg_go(chunk)) {
|
fputc('\n', stderr);
|
||||||
|
|
||||||
puts(ast_dump(chunk));
|
|
||||||
|
|
||||||
dumben_go(chunk);
|
dumben_go(chunk);
|
||||||
}
|
|
||||||
|
fputs("\n/* === Dumbified === */\n", stderr);
|
||||||
|
fputs(ast_dump(chunk), stderr);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
|
||||||
|
while(!cg_go(chunk));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
38
src/parse.c
38
src/parse.c
@ -8,6 +8,7 @@
|
|||||||
#include"reporting.h"
|
#include"reporting.h"
|
||||||
#include<stdint.h>
|
#include<stdint.h>
|
||||||
#include<signal.h>
|
#include<signal.h>
|
||||||
|
#include"x86.h"
|
||||||
|
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
static inline int __builtin_clzl(unsigned long x) {
|
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));
|
ASTExprStackPointer *ret = malloc(sizeof(*ret));
|
||||||
ret->nodeKind = AST_EXPR_STACK_POINTER;
|
ret->nodeKind = AST_EXPR_STACK_POINTER;
|
||||||
ret->type = primitive_parse("u32");
|
ret->type = primitive_parse("u32");
|
||||||
return ret;
|
return (AST*) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return exprvar(P, vartable_find(P->scope, get(P).content));
|
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);
|
AST *child = nct_parse_expression(P, lOP);
|
||||||
|
|
||||||
if(child->nodeKind == AST_EXPR_PRIMITIVE) {
|
if(child->nodeKind == AST_EXPR_PRIMITIVE) {
|
||||||
child->exprPrim.val = \
|
child->exprPrim.val = ~child->exprPrim.val;
|
||||||
~child->exprPrim.val;
|
|
||||||
return child;
|
return child;
|
||||||
} else {
|
} else {
|
||||||
ASTExprUnaryOp *astop = malloc(sizeof(*astop));
|
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.");
|
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));
|
ASTExprCall *call = malloc(sizeof(*call));
|
||||||
call->nodeKind = AST_EXPR_CALL;
|
call->nodeKind = AST_EXPR_CALL;
|
||||||
call->type = ret->expression.type->function.ret;
|
call->type = ret->expression.type->function.ret;
|
||||||
call->what = ret;
|
call->what = ret;
|
||||||
call->args = NULL;
|
call->args = NULL;
|
||||||
ret = (AST*) call;
|
|
||||||
|
|
||||||
int argCount = 0;
|
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. */
|
/* TODO: Check argument count. */
|
||||||
} else if(maybe(P, TOKEN_SQUAREN_L)) {
|
} else if(maybe(P, TOKEN_SQUAREN_L)) {
|
||||||
ASTExprUnaryOp *ref = malloc(sizeof(*ref));
|
ASTExprUnaryOp *ref = malloc(sizeof(*ref));
|
||||||
@ -366,10 +382,10 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
ASTExprBinaryOp *mul = malloc(sizeof(*mul));
|
ASTExprBinaryOp *mul = malloc(sizeof(*mul));
|
||||||
mul->nodeKind = AST_EXPR_BINARY_OP;
|
mul->nodeKind = AST_EXPR_BINARY_OP;
|
||||||
mul->operator = BINOP_MUL;
|
mul->operator = BINOP_MUL;
|
||||||
mul->operands[0] = scale;
|
mul->operands[0] = (AST*) scale;
|
||||||
mul->operands[1] = child->operands[1];
|
mul->operands[1] = child->operands[1];
|
||||||
|
|
||||||
child->operands[1] = mul;
|
child->operands[1] = (AST*) mul;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTExprUnaryOp *unop = malloc(sizeof(*unop));
|
ASTExprUnaryOp *unop = malloc(sizeof(*unop));
|
||||||
@ -631,6 +647,7 @@ static AST *parse_declaration(Parser *P) {
|
|||||||
|
|
||||||
entry->kind = VARTABLEENTRY_VAR;
|
entry->kind = VARTABLEENTRY_VAR;
|
||||||
entry->data.var.priority = 1;
|
entry->data.var.priority = 1;
|
||||||
|
entry->data.var.color = -1;
|
||||||
|
|
||||||
ASTStmtAssign *assign = malloc(sizeof(*assign));
|
ASTStmtAssign *assign = malloc(sizeof(*assign));
|
||||||
assign->nodeKind = AST_STMT_ASSIGN;
|
assign->nodeKind = AST_STMT_ASSIGN;
|
||||||
@ -735,7 +752,7 @@ void nct_parse_statement(Parser *P) {
|
|||||||
|
|
||||||
AST *es = calloc(1, sizeof(ASTStmtExpr));
|
AST *es = calloc(1, sizeof(ASTStmtExpr));
|
||||||
es->nodeKind = AST_STMT_EXPR;
|
es->nodeKind = AST_STMT_EXPR;
|
||||||
es->stmtExpr.expr = ev;
|
es->stmtExpr.expr = (AST*) ev;
|
||||||
|
|
||||||
pushstat(P, es);
|
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.statementFirst = ret->chunk.statementLast = NULL;
|
||||||
ret->chunk.varCount = 0;
|
ret->chunk.varCount = 0;
|
||||||
ret->chunk.vars = NULL;
|
ret->chunk.vars = NULL;
|
||||||
|
ret->chunk.stackReservation = 0;
|
||||||
|
|
||||||
AST *oldChunk = P->currentChunk;
|
AST *oldChunk = (AST*) P->currentChunk;
|
||||||
P->currentChunk = (AST*) ret;
|
P->currentChunk = &ret->chunk;
|
||||||
|
|
||||||
P->scope = vartable_new(P->scope);
|
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++) {
|
for(size_t i = 0; i < P->scope->count; i++) {
|
||||||
if(P->scope->data[i]->kind == VARTABLEENTRY_VAR) {
|
if(P->scope->data[i]->kind == VARTABLEENTRY_VAR) {
|
||||||
P->topLevel->vars[P->topLevel->varCount++] = P->scope->data[i];
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ typedef struct VarTableEntry {
|
|||||||
// vars in loops have higher priority
|
// 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)
|
// a more advanced approach would be to use weights for different colors (e.g. multipliers "should" be in eax)
|
||||||
uint8_t priority;
|
uint8_t priority;
|
||||||
uint16_t color, degree;
|
int16_t color, degree;
|
||||||
|
|
||||||
// Used during parsing
|
// Used during parsing
|
||||||
|
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
#pragma once
|
#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?
|
// Can expression be expressed as a single x86 operand?
|
||||||
#define XOP_NOT_XOP 0
|
#define XOP_NOT_XOP 0
|
||||||
#define XOP_NOT_MEM 1
|
#define XOP_NOT_MEM 1
|
||||||
@ -9,7 +14,7 @@ static inline int is_xop(AST *e) {
|
|||||||
return XOP_NOT_MEM;
|
return XOP_NOT_MEM;
|
||||||
} else if(e->nodeKind == AST_EXPR_VAR) {
|
} else if(e->nodeKind == AST_EXPR_VAR) {
|
||||||
return e->exprVar.thing->kind == VARTABLEENTRY_VAR ? XOP_NOT_MEM : XOP_MEM;
|
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;
|
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) {
|
} 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;
|
return XOP_NOT_MEM;
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
extern u32() getchar;
|
extern s32() getchar;
|
||||||
extern void(u32) putchar;
|
extern u0(s32) putchar;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
u8 a = getchar();
|
u8 z = 5;
|
||||||
if(a - 48) {
|
s32 a = getchar();
|
||||||
|
if(a == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
putchar(a);
|
putchar(a);
|
||||||
}
|
putchar(z);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user