Support negation, parentheses. Always zero-extend registers for bugless memory operand usage
This commit is contained in:
parent
fa40a78546
commit
012320569e
54
src/cg.c
54
src/cg.c
@ -5,6 +5,8 @@
|
|||||||
#include<string.h>
|
#include<string.h>
|
||||||
#include<assert.h>
|
#include<assert.h>
|
||||||
|
|
||||||
|
#include"x86.h"
|
||||||
|
|
||||||
#define REGS 4
|
#define REGS 4
|
||||||
static const char *regs[REGS][3] = {{"al", "ax", "eax"}, {"bl", "bx", "ebx"}, {"cl", "cx", "ecx"}, {"dl", "dx", "edx"}};
|
static const char *regs[REGS][3] = {{"al", "ax", "eax"}, {"bl", "bx", "ebx"}, {"cl", "cx", "ecx"}, {"dl", "dx", "edx"}};
|
||||||
|
|
||||||
@ -51,7 +53,7 @@ static const char *specexpr(AST *e) {
|
|||||||
return spec(type_size(e->expression.type));
|
return spec(type_size(e->expression.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *xv(VarTableEntry *v) {
|
static const char *xv_sz(VarTableEntry *v, int sz) {
|
||||||
assert(v->kind == VARTABLEENTRY_VAR);
|
assert(v->kind == VARTABLEENTRY_VAR);
|
||||||
|
|
||||||
#define XVBUFS 8
|
#define XVBUFS 8
|
||||||
@ -64,7 +66,7 @@ static const char *xv(VarTableEntry *v) {
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
snprintf(ret, XVBUFSZ, "@%i", v->data.var.color);
|
snprintf(ret, XVBUFSZ, "@%i", v->data.var.color);
|
||||||
#else
|
#else
|
||||||
snprintf(ret, XVBUFSZ, "%s", regs[v->data.var.color][log_size(type_size(v->type))]);
|
snprintf(ret, XVBUFSZ, "%s", regs[v->data.var.color][log_size(sz)]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bufidx = (bufidx + 1) % XVBUFS;
|
bufidx = (bufidx + 1) % XVBUFS;
|
||||||
@ -72,6 +74,10 @@ static const char *xv(VarTableEntry *v) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *xv(VarTableEntry *v) {
|
||||||
|
return xv_sz(v, type_size(v->type));
|
||||||
|
}
|
||||||
|
|
||||||
static const char *xj(BinaryOp op) {
|
static const char *xj(BinaryOp op) {
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case BINOP_EQUAL: return "e";
|
case BINOP_EQUAL: return "e";
|
||||||
@ -80,7 +86,7 @@ static const char *xj(BinaryOp op) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *xop(AST *e) {
|
static const char *xop_sz(AST *e, int sz) {
|
||||||
#define XOPBUFS 16
|
#define XOPBUFS 16
|
||||||
#define XOPBUFSZ 24
|
#define XOPBUFSZ 24
|
||||||
static char bufs[XOPBUFS][XOPBUFSZ];
|
static char bufs[XOPBUFS][XOPBUFSZ];
|
||||||
@ -92,25 +98,32 @@ static const char *xop(AST *e) {
|
|||||||
VarTableEntry *v = e->exprVar.thing;
|
VarTableEntry *v = e->exprVar.thing;
|
||||||
|
|
||||||
if(v->kind == VARTABLEENTRY_VAR) {
|
if(v->kind == VARTABLEENTRY_VAR) {
|
||||||
return xv(v);
|
return xv_sz(v, sz);
|
||||||
} else if(v->kind == VARTABLEENTRY_SYMBOL) {
|
} else if(v->kind == VARTABLEENTRY_SYMBOL) {
|
||||||
snprintf(ret, XOPBUFSZ, "[%s]", v->data.symbol.name);
|
snprintf(ret, XOPBUFSZ, "[%s]", v->data.symbol.name);
|
||||||
} else abort();
|
} else abort();
|
||||||
} else if(e->nodeKind == AST_EXPR_PRIMITIVE) {
|
} else if(e->nodeKind == AST_EXPR_PRIMITIVE) {
|
||||||
snprintf(ret, XOPBUFSZ, "%i", e->exprPrim.val);
|
snprintf(ret, XOPBUFSZ, "%i", e->exprPrim.val);
|
||||||
|
} 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) {
|
||||||
|
snprintf(ret, XOPBUFSZ, "%s [%s + %s]",
|
||||||
|
spec(sz),
|
||||||
|
xv_sz(e->exprUnOp.operand->exprBinOp.operands[0]->exprVar.thing, 4),
|
||||||
|
xv_sz(e->exprUnOp.operand->exprBinOp.operands[1]->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 == BINOP_ADD && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL && 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 && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL && e->exprUnOp.operand->exprBinOp.operands[1]->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
||||||
snprintf(ret, XOPBUFSZ, "[%s + %s]",
|
snprintf(ret, XOPBUFSZ, "%s [%s + %s]",
|
||||||
|
spec(sz),
|
||||||
e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
||||||
xv(e->exprUnOp.operand->exprBinOp.operands[1]->exprVar.thing));
|
xv_sz(e->exprUnOp.operand->exprBinOp.operands[1]->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 == BINOP_ADD && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operator == BINOP_MUL && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && e->exprUnOp.operand->exprBinOp.operands[1]->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 && e->exprUnOp.operand->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operand->exprBinOp.operands[1]->nodeKind == AST_EXPR_BINARY_OP && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operator == BINOP_MUL && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[1]->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
||||||
snprintf(ret, XOPBUFSZ, "[%s + %i * %s]",
|
snprintf(ret, XOPBUFSZ, "%s [%s + %i * %s]",
|
||||||
|
spec(sz),
|
||||||
e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
e->exprUnOp.operand->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
||||||
e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val,
|
e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val,
|
||||||
xv(e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[1]->exprVar.thing));
|
xv_sz(e->exprUnOp.operand->exprBinOp.operands[1]->exprBinOp.operands[1]->exprVar.thing, 4));
|
||||||
} 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) {
|
||||||
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]", xv(e->exprUnOp.operand->exprVar.thing));
|
snprintf(ret, XOPBUFSZ, "%s [%s]", spec(sz), xv_sz(e->exprUnOp.operand->exprVar.thing, 4));
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -120,6 +133,10 @@ static const char *xop(AST *e) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *xop(AST *e) {
|
||||||
|
return xop_sz(e, type_size(e->expression.type));
|
||||||
|
}
|
||||||
|
|
||||||
void cg_chunk(AST *a) {
|
void cg_chunk(AST *a) {
|
||||||
AST *s = a->chunk.statementFirst;
|
AST *s = a->chunk.statementFirst;
|
||||||
|
|
||||||
@ -201,9 +218,24 @@ void cg_chunk(AST *a) {
|
|||||||
s->stmtAssign.to->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
s->stmtAssign.to->exprBinOp.operands[0]->exprUnOp.operand->exprVar.thing->data.symbol.name,
|
||||||
xv(s->stmtAssign.to->exprBinOp.operands[1]->exprVar.thing));
|
xv(s->stmtAssign.to->exprBinOp.operands[1]->exprVar.thing));
|
||||||
|
|
||||||
|
} else if(s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_BINARY_OP && s->stmtAssign.to->exprBinOp.operator == BINOP_ADD && s->stmtAssign.to->exprBinOp.operands[0]->nodeKind == AST_EXPR_VAR && s->stmtAssign.to->exprBinOp.operands[1]->nodeKind == AST_EXPR_PRIMITIVE && s->stmtAssign.to->exprBinOp.operands[0]->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
||||||
|
|
||||||
|
printf("lea %s, [%s + %i]\n",
|
||||||
|
xv_sz(s->stmtAssign.what->exprVar.thing, 4),
|
||||||
|
xv_sz(s->stmtAssign.to->exprBinOp.operands[0]->exprVar.thing, 4),
|
||||||
|
s->stmtAssign.to->exprBinOp.operands[1]->exprPrim.val);
|
||||||
|
|
||||||
|
} else if(is_xop(s->stmtAssign.what) != NULL && 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)) {
|
||||||
|
|
||||||
|
printf("neg %s\n", xop(s->stmtAssign.what));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
printf("mov %s, %s\n", xop(s->stmtAssign.what), xop(s->stmtAssign.to));
|
if(is_xop(s->stmtAssign.to) == XOP_MEM && type_size(s->stmtAssign.what->expression.type) != type_size(s->stmtAssign.to->expression.type)) {
|
||||||
|
printf("movzx %s, %s\n", xop_sz(s->stmtAssign.what, 4), xop_sz(s->stmtAssign.to, type_size(s->stmtAssign.what->expression.type)));
|
||||||
|
} else {
|
||||||
|
printf("mov %s, %s\n", xop(s->stmtAssign.what), xop_sz(s->stmtAssign.to, type_size(s->stmtAssign.what->expression.type)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,7 +273,7 @@ void cg_chunk(AST *a) {
|
|||||||
|
|
||||||
size_t lbl = nextLocalLabel++;
|
size_t lbl = nextLocalLabel++;
|
||||||
|
|
||||||
printf("cmp %s %s, %s\n", specexpr(s->stmtIf.expression->exprBinOp.operands[0]), xop(s->stmtIf.expression->exprBinOp.operands[0]), xop(s->stmtIf.expression->exprBinOp.operands[1]));
|
printf("cmp %s, %s\n", xop(s->stmtIf.expression->exprBinOp.operands[0]), xop(s->stmtIf.expression->exprBinOp.operands[1]));
|
||||||
printf("j%s .L%lu\n", xj(binop_comp_opposite(s->stmtIf.expression->exprBinOp.operator)), lbl);
|
printf("j%s .L%lu\n", xj(binop_comp_opposite(s->stmtIf.expression->exprBinOp.operator)), lbl);
|
||||||
|
|
||||||
cg_chunk(s->stmtIf.then);
|
cg_chunk(s->stmtIf.then);
|
||||||
|
@ -11,37 +11,7 @@
|
|||||||
// This pass, along with CG is strictly dependent on x86 and will fail for
|
// This pass, along with CG is strictly dependent on x86 and will fail for
|
||||||
// any other architecture.
|
// any other architecture.
|
||||||
|
|
||||||
// Can expression be expressed as a single x86 operand?
|
#include"x86.h"
|
||||||
#define XOP_NOT_XOP 0
|
|
||||||
#define XOP_NOT_MEM 1
|
|
||||||
#define XOP_MEM 2
|
|
||||||
static int is_xop(AST *e) {
|
|
||||||
if(e->nodeKind == AST_EXPR_PRIMITIVE) {
|
|
||||||
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_REF && e->exprUnOp.operand->nodeKind == AST_EXPR_VAR && e->exprUnOp.operand->exprVar.thing->kind == VARTABLEENTRY_SYMBOL) {
|
|
||||||
return XOP_NOT_MEM;
|
|
||||||
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_DEREF) {
|
|
||||||
AST *c = e->exprUnOp.operand;
|
|
||||||
|
|
||||||
if(c->nodeKind == AST_EXPR_VAR && c->exprVar.thing->kind == VARTABLEENTRY_VAR) {
|
|
||||||
return XOP_MEM;
|
|
||||||
} else if(c->nodeKind == AST_EXPR_BINARY_OP && c->exprBinOp.operator == BINOP_ADD && c->exprBinOp.operands[0]->nodeKind == AST_EXPR_UNARY_OP && c->exprBinOp.operands[0]->exprUnOp.operator == UNOP_REF && c->exprBinOp.operands[0]->exprUnOp.operand->nodeKind == AST_EXPR_VAR) {
|
|
||||||
if(c->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR) {
|
|
||||||
return XOP_MEM;
|
|
||||||
} else if(c->exprBinOp.operands[1]->nodeKind == AST_EXPR_BINARY_OP && c->exprBinOp.operands[1]->exprBinOp.operator == BINOP_MUL && c->exprBinOp.operands[1]->exprBinOp.operands[0]->nodeKind == AST_EXPR_PRIMITIVE && c->exprBinOp.operands[1]->exprBinOp.operands[1]->nodeKind == AST_EXPR_VAR) {
|
|
||||||
int scale = c->exprBinOp.operands[1]->exprBinOp.operands[0]->exprPrim.val;
|
|
||||||
|
|
||||||
if(scale == 1 || scale == 2 || scale == 4 || scale == 8) {
|
|
||||||
return XOP_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return XOP_NOT_XOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void varify_change_usedefs(AST *e, AST *oldStmt, AST *newStmt) {
|
static void varify_change_usedefs(AST *e, AST *oldStmt, AST *newStmt) {
|
||||||
if(e->nodeKind == AST_EXPR_VAR) {
|
if(e->nodeKind == AST_EXPR_VAR) {
|
||||||
@ -185,6 +155,28 @@ static AST *xopify(AST *tlc, AST *chunk, AST *stmtPrev, AST *stmt, AST *e) {
|
|||||||
return varify(tlc, chunk, stmtPrev, stmt, e);
|
return varify(tlc, chunk, stmtPrev, stmt, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UseDef *get_last_usedef_before_stmt(AST *tlc, VarTableEntry *v, AST *stmt) {
|
||||||
|
assert(v->kind == VARTABLEENTRY_VAR);
|
||||||
|
|
||||||
|
UseDef *ud = v->data.var.usedefFirst;
|
||||||
|
|
||||||
|
if(!ud) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UseDef *udPrev = NULL;
|
||||||
|
|
||||||
|
while(ud) {
|
||||||
|
if(ast_stmt_is_after(tlc, ud->stmt, stmt)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
udPrev = ud;
|
||||||
|
ud = ud->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return udPrev;
|
||||||
|
}
|
||||||
|
|
||||||
static int dumben_chunk(AST *tlc, AST *chu) {
|
static int dumben_chunk(AST *tlc, AST *chu) {
|
||||||
AST *sPrev = NULL;
|
AST *sPrev = NULL;
|
||||||
AST *s = chu->chunk.statementFirst;
|
AST *s = chu->chunk.statementFirst;
|
||||||
@ -238,6 +230,59 @@ static int dumben_chunk(AST *tlc, AST *chu) {
|
|||||||
effective = 1;
|
effective = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(s->stmtAssign.what->nodeKind == AST_EXPR_VAR && s->stmtAssign.what->exprVar.thing->kind == VARTABLEENTRY_VAR && s->stmtAssign.to->nodeKind == AST_EXPR_UNARY_OP && s->stmtAssign.to->exprUnOp.operator == UNOP_NEGATE && (s->stmtAssign.to->exprUnOp.operand->nodeKind != AST_EXPR_VAR || s->stmtAssign.what->exprVar.thing != s->stmtAssign.to->exprUnOp.operand->exprVar.thing)) {
|
||||||
|
// Turn this:
|
||||||
|
// a = -b
|
||||||
|
// into
|
||||||
|
// a = b
|
||||||
|
// a = -a
|
||||||
|
// While keeping UD-chain valid.
|
||||||
|
|
||||||
|
// Currently only for variables. While this could work for any XOP, it requires the ability to deep-copy `a`, which is not trivial when taking into account UD-chains.
|
||||||
|
// TODO: Scrap incremental UD-chain modifications. Simply rebuild them after each pass.
|
||||||
|
|
||||||
|
ASTExprVar *ev[2];
|
||||||
|
for(int i = 0; i < 2; i++) {
|
||||||
|
ev[i] = malloc(sizeof(ASTExprVar));
|
||||||
|
ev[i]->nodeKind = AST_EXPR_VAR;
|
||||||
|
ev[i]->type = s->stmtAssign.what->expression.type;
|
||||||
|
ev[i]->thing = s->stmtAssign.what->exprVar.thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
UseDef *link = get_last_usedef_before_stmt(tlc, ev[0]->thing, assign2->statement.next);
|
||||||
|
|
||||||
|
UseDef *ud[2];
|
||||||
|
ud[0] = malloc(sizeof(UseDef));
|
||||||
|
ud[1] = malloc(sizeof(UseDef));
|
||||||
|
|
||||||
|
ud[0]->stmt = assign2;
|
||||||
|
ud[0]->use = (AST*) ev[1];
|
||||||
|
ud[0]->def = s;
|
||||||
|
ud[0]->next = ud[1];
|
||||||
|
|
||||||
|
ud[1]->stmt = assign2;
|
||||||
|
ud[1]->use = (AST*) ev[0];
|
||||||
|
ud[1]->def = s;
|
||||||
|
ud[1]->next = link->next;
|
||||||
|
|
||||||
|
link->next = ud[0];
|
||||||
|
|
||||||
|
effective = 1;
|
||||||
|
}
|
||||||
|
|
||||||
} else if(s->nodeKind == AST_STMT_EXPR && s->stmtExpr.expr->nodeKind == AST_EXPR_CALL) {
|
} 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;
|
int argCount = s->stmtExpr.expr->exprCall.what->expression.type->function.argCount;
|
||||||
|
@ -285,6 +285,10 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
ret->length = tok.length;
|
ret->length = tok.length;
|
||||||
|
|
||||||
return (AST*) ret;
|
return (AST*) ret;
|
||||||
|
} else if(maybe(P, TOKEN_PAREN_L)) {
|
||||||
|
AST *e = nct_parse_expression(P, 0);
|
||||||
|
expect(P, TOKEN_PAREN_R);
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
} else if(lOP == 4) {
|
} else if(lOP == 4) {
|
||||||
if(maybe(P, TOKEN_STAR)) {
|
if(maybe(P, TOKEN_STAR)) {
|
||||||
|
@ -1,2 +1,6 @@
|
|||||||
u32 x: 123;
|
u32 x: 123;
|
||||||
u33 y: 5;
|
u33 y: 5;
|
||||||
|
|
||||||
|
u3 *o = 5000;
|
||||||
|
u3 z = *o;
|
||||||
|
u3 p = *(o + z);
|
||||||
|
@ -2,7 +2,8 @@ u16 x: 5;
|
|||||||
loop {
|
loop {
|
||||||
u16* y = 257;
|
u16* y = 257;
|
||||||
u9 w = -4;
|
u9 w = -4;
|
||||||
u4 z = 3 + *y;
|
u16 p = *y;
|
||||||
|
u4 z = p + 3;
|
||||||
u2 o = -w;
|
u2 o = -w;
|
||||||
|
|
||||||
if(x != 0) {
|
if(x != 0) {
|
||||||
|
@ -4,4 +4,6 @@ loop {
|
|||||||
a = 3;
|
a = 3;
|
||||||
|
|
||||||
u8 b = 1;
|
u8 b = 1;
|
||||||
|
|
||||||
|
u8 c = 2;
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
u8 a = 5;
|
u8 a = 5;
|
||||||
if(a) {
|
if(a != 0) {
|
||||||
u8 a = 10; /* Should not cause scoping errors. */
|
u8 a = 10; /* Should not cause scoping errors. */
|
||||||
}
|
}
|
||||||
u8 b = 15; /* `a` in the if statement scope should be free'd. */
|
u8 b = 15; /* `a` in the if statement scope should be free'd. */
|
Loading…
Reference in New Issue
Block a user