Compare commits

...

5 Commits

Author SHA1 Message Date
Mid
8c4754b563 Joe expansion 2025-10-15 14:11:41 +03:00
Mid
9d975eeceb Force assign declaration statement for all virtual/temp variables 2025-10-15 14:11:24 +03:00
Mid
ecab77f9e9 Holy fucking bug omg 2025-10-15 14:11:02 +03:00
Mid
132cedff09 ebp is also callee-saved 2025-10-15 14:10:54 +03:00
Mid
f978b66662 Conditionally save volatile regs 2025-10-15 14:10:42 +03:00
4 changed files with 75 additions and 17 deletions

View File

@ -46,8 +46,28 @@ MapDQCOaLDhS_try_add: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this, K* key, V* value)
};
MapDQCOaLDhS_expand: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this) -> {
/* Unimplemented. */
return 0;
S capacity = this.capacity;
KVPair[K, V][?]* old_data = this.data;
u8[?]* old_occupied = this.occupied;
S new_capacity = capacity * 2;
this.capacity = new_capacity;
this.data = calloc(new_capacity, @sizeof KVPair[K, V]);
this.occupied = calloc(new_capacity, @sizeof((*this.occupied)[0]));
S i = 0;
loop {
if(i == capacity) {
break;
}
if((*old_occupied)[i] != 0) {
KVPair[K, V]* pair = &((*old_data)[i]);
MapDQCOaLDhS_try_add[K, V, S](this, &pair.key, &pair.value);
}
i = i + 1;
}
return 1;
};
MapDQCOaLDhS_add: [K, V, S]u1(MapDQCOaLDhS[K, V, S]* this, K* key, V* value) -> {

View File

@ -204,6 +204,8 @@ void ast_usedef_reset(AST *chu) {
for(size_t sii = 0; sii < chu->chunk.varCount; sii++) {
ScopeItem *si = chu->chunk.vars[sii];
assert(si->data.var.declaration != NULL && "All local vars must have defined declaration location");
if(ast_stmt_is_after(chu, si->data.var.liveRangeEnd, s) == 0 && ast_stmt_is_after(chu, target, si->data.var.liveRangeEnd) == 0 && ast_stmt_is_after(chu, si->data.var.declaration, target) == 0) {
si->data.var.liveRangeEnd = s;

View File

@ -260,6 +260,27 @@ static int lr_empty(ScopeItem *a) {
return !a->data.var.liveRangeStart;
}
static bool is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(AST *tlc, AST *statement, size_t resource) {
for(size_t vi = 0; vi < tlc->chunk.varCount; vi++) {
ScopeItem *si = tlc->chunk.vars[vi];
if((REG_CLASSES[si->data.var.registerClass].rs[si->data.var.color] & resource) == 0) {
continue;
}
if(ast_stmt_is_after(tlc, statement, si->data.var.liveRangeEnd) == 1 || statement == si->data.var.liveRangeEnd) {
continue;
}
if(si->data.var.usedefFirst == NULL) {
// Even if the resource is in use, the variable itself isn't so we don't care
continue;
}
if(!lr_empty(si) && (ast_stmt_is_after(tlc, statement, si->data.var.liveRangeStart) == 1
&& ast_stmt_is_after(tlc, si->data.var.liveRangeEnd, statement) == 1)) {
return true;
}
}
return false;
}
void cg_chunk(CGState *cg, AST *a) {
AST *s = a->chunk.statementFirst;
@ -390,12 +411,14 @@ void cg_chunk(CGState *cg, AST *a) {
AST *e = s->stmtAssign.to;
if(x86_ia16()) {
puts("push cx");
puts("push dx");
} else {
puts("push ecx");
puts("push edx");
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_ECX)) {
puts(x86_ia16() ? "push cx" : "push ecx");
}
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EDX)) {
puts(x86_ia16() ? "push dx" : "push edx");
}
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EAX)) {
puts(x86_ia16() ? "push ax" : "push eax");
}
int argCount = e->exprCall.what->expression.type->pointer.of->function.argCount;
@ -422,12 +445,14 @@ void cg_chunk(CGState *cg, AST *a) {
}
}
if(x86_ia16()) {
puts("pop dx");
puts("pop cx");
} else {
puts("pop edx");
puts("pop ecx");
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EAX)) {
puts(x86_ia16() ? "pop ax" : "pop eax");
}
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EDX)) {
puts(x86_ia16() ? "pop dx" : "pop edx");
}
if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_ECX)) {
puts(x86_ia16() ? "pop cx" : "pop ecx");
}
} else if(s->nodeKind == AST_STMT_ASSIGN) {
@ -583,9 +608,9 @@ void cg_chunk(CGState *cg, AST *a) {
if(a->chunk.stackReservation) {
for(int i = 0; i < MAX_REGS_PER_CLASS && cg->calleeSaved.reg[i]; i++) {
if(x86_ia16()) {
printf("mov [bp + %li], %s\n", cg->calleeSaved.stackOffset[i] - a->chunk.stackReservation, cg->calleeSaved.reg[i]);
printf("mov %s, [bp + %li]\n", cg->calleeSaved.reg[i], cg->calleeSaved.stackOffset[i] - a->chunk.stackReservation);
} else {
printf("mov [esp + %li], %s\n", cg->calleeSaved.stackOffset[i], cg->calleeSaved.reg[i]);
printf("mov %s, [esp + %li]\n", cg->calleeSaved.reg[i], cg->calleeSaved.stackOffset[i]);
}
}
@ -643,7 +668,7 @@ static bool var_collision(AST *tlc, ScopeItem *v1, ScopeItem *v2) {
}
static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
bool ebxused = false, ediused = false, esiused = false;
bool ebxused = false, ediused = false, esiused = false, ebpused = false;
for(size_t v = 0; v < tlc->chunk.varCount; v++) {
size_t resource = REG_CLASSES[tlc->chunk.vars[v]->data.var.registerClass].rs[tlc->chunk.vars[v]->data.var.color];
@ -657,6 +682,9 @@ static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
if(resource & HWR_ESI) {
esiused = true;
}
if(resource & HWR_EBP) {
ebpused = true;
}
}
size_t nextUser = 0;
@ -675,6 +703,11 @@ static void callee_saved(AST *tlc, struct CalleeSavedState *state) {
state->reg[nextUser] = x86_ia16() ? "di" : "edi";
nextUser++;
}
if(ebpused) {
state->stackOffset[nextUser] = nextUser * x86_max_gpr_size();
state->reg[nextUser] = x86_ia16() ? "bp" : "ebp";
nextUser++;
}
ast_grow_stack_frame(tlc, nextUser * x86_max_gpr_size());
}

View File

@ -35,6 +35,7 @@ static AST *varify(AST *tlc, AST *chunk, AST *stmtPrev, AST *stmt, AST *e) {
assign->nodeKind = AST_STMT_ASSIGN;
assign->what = (AST*) ev[0];
assign->to = e;
vte->data.var.declaration = (AST*) assign;
if(stmtPrev) {
stmtPrev->statement.next = (AST*) assign;
@ -297,6 +298,7 @@ static void normalize_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AS
assign2->nodeKind = AST_STMT_ASSIGN;
assign2->what = (AST*) s->stmtAssign.what;
assign2->to = (AST*) ev[0];
tmp->data.var.declaration = (AST*) s;
s->stmtAssign.what = (AST*) ev[1];
@ -517,6 +519,7 @@ static void pre_norm_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, A
ass->what = (AST*) evar;
ass->to = ast_cast_expr((AST*) deref, vte->type); // Must cast because of "convention correctness"
ass->next = n->chunk.statementFirst;
vte->data.var.declaration = (AST*) ass;
if(n->chunk.statementFirst) {
n->chunk.statementFirst = ass;