Handle certain precoloring collisions
This commit is contained in:
parent
17a0c9d902
commit
5b3991e81c
@ -100,6 +100,7 @@ int ast_expression_equal(AST *a, AST *b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function may return three values: YES (1), NO (0) or UNKNOWN (-1).
|
||||
// ... Ew
|
||||
int ast_stmt_is_after(const AST *chunk, const AST *s1, const AST *s2) {
|
||||
const AST *s = chunk->chunk.statementFirst;
|
||||
|
66
src/cg.c
66
src/cg.c
@ -165,6 +165,13 @@ static const char *xop(AST *tlc, AST *e) {
|
||||
return xop_sz(tlc, e, type_size(e->expression.type));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void cg_chunk(CGState *cg, AST *a) {
|
||||
AST *s = a->chunk.statementFirst;
|
||||
|
||||
@ -383,15 +390,9 @@ void cg_chunk(CGState *cg, AST *a) {
|
||||
}
|
||||
}
|
||||
|
||||
struct Spill2StackState {
|
||||
AST *targetTLC;
|
||||
VarTableEntry *target;
|
||||
};
|
||||
|
||||
struct Spill2VarState {
|
||||
VarTableEntry *target;
|
||||
};
|
||||
|
||||
static void spill2var_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||
static size_t vidx = 0;
|
||||
|
||||
@ -476,6 +477,10 @@ static void spill2var_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk,
|
||||
}
|
||||
}
|
||||
|
||||
struct Spill2StackState {
|
||||
AST *targetTLC;
|
||||
VarTableEntry *target;
|
||||
};
|
||||
static void spill2stack_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||
struct Spill2StackState *this = ud;
|
||||
|
||||
@ -521,14 +526,17 @@ static void spill2stack_visitor(AST **aptr, AST *stmt, AST *stmtPrev, AST *chunk
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
struct PrecolorState {
|
||||
ASTExprVar *mustBeSpilled;
|
||||
};
|
||||
static void precolor_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||
struct PrecolorState *this = ud;
|
||||
|
||||
if(this->mustBeSpilled) {
|
||||
/* Since something must be spilled first, we can't do anything else. Quit ASAP. */
|
||||
return;
|
||||
}
|
||||
|
||||
AST *n = *nptr;
|
||||
|
||||
if(n == tlc) {
|
||||
@ -544,9 +552,15 @@ static void precolor_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
|
||||
|
||||
VarTableEntry *vte = n->stmtReturn.val->exprVar.thing;
|
||||
|
||||
assert(!vte->data.var.precolored);
|
||||
const int requiredColor = COLOR_EAX;
|
||||
|
||||
vte->data.var.color = COLOR_EAX;
|
||||
if(vte->data.var.precolored && vte->data.var.color != requiredColor) {
|
||||
// Precoloring collision!
|
||||
this->mustBeSpilled = vte;
|
||||
return;
|
||||
}
|
||||
|
||||
vte->data.var.color = requiredColor;
|
||||
vte->data.var.precolored = true;
|
||||
}
|
||||
} else if(n->nodeKind == AST_STMT_ASSIGN && n->stmtAssign.to->nodeKind == AST_EXPR_CALL) {
|
||||
@ -554,9 +568,15 @@ static void precolor_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
|
||||
|
||||
VarTableEntry *vte = n->stmtAssign.what->exprVar.thing;
|
||||
|
||||
assert(!vte->data.var.precolored);
|
||||
const int requiredColor = COLOR_EAX;
|
||||
|
||||
vte->data.var.color = COLOR_EAX;
|
||||
if(vte->data.var.precolored && vte->data.var.color != requiredColor) {
|
||||
// Precoloring collision!
|
||||
this->mustBeSpilled = vte;
|
||||
return;
|
||||
}
|
||||
|
||||
vte->data.var.color = requiredColor;
|
||||
vte->data.var.precolored = true;
|
||||
}
|
||||
}
|
||||
@ -626,7 +646,6 @@ struct CalleeSavedState {
|
||||
// To make sure we don't process the same return statement to infinity
|
||||
AST *lastProcessedReturn;
|
||||
};
|
||||
|
||||
static void callee_saved_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST *tlc, void *ud) {
|
||||
struct CalleeSavedState *this = ud;
|
||||
|
||||
@ -753,11 +772,18 @@ static int comparator(const void *A, const void *B) {
|
||||
}
|
||||
int cg_go(AST *a) {
|
||||
do {
|
||||
generic_visitor(&a, NULL, NULL, a, a, NULL, precolor_visitor);
|
||||
struct PrecolorState state = {};
|
||||
generic_visitor(&a, NULL, NULL, a, a, &state, precolor_visitor);
|
||||
|
||||
ast_usedef_reset(a);
|
||||
|
||||
VarTableEntry *vte = get_precolor_spill_candidate(a);
|
||||
// Spill?
|
||||
VarTableEntry *vte = state.mustBeSpilled; // set if precoloring demands DIFFERENT colors for the same variable
|
||||
if(!vte) {
|
||||
// Find variables with the same color
|
||||
vte = get_precolor_spill_candidate(a);
|
||||
}
|
||||
|
||||
if(vte) {
|
||||
struct Spill2VarState state;
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
Loading…
Reference in New Issue
Block a user