mirror of
https://git.wuffs.org/MWCC
synced 2025-12-16 08:27:17 +00:00
218 lines
5.7 KiB
C
218 lines
5.7 KiB
C
#include "compiler/Registers.h"
|
|
#include "compiler/RegisterInfo.h"
|
|
#include "compiler/CParser.h"
|
|
#include "compiler/PCode.h"
|
|
#include "compiler/CompilerTools.h"
|
|
#include "compiler/objects.h"
|
|
|
|
int used_virtual_registers[RegClassMax];
|
|
int used_nonvolatile_registers[RegClassMax];
|
|
int assignable_registers[RegClassMax];
|
|
int n_real_registers[RegClassMax];
|
|
int n_scratch_registers[RegClassMax];
|
|
int scratch_registers[RegClassMax][RegisterMax];
|
|
int n_nonvolatile_registers[RegClassMax];
|
|
int nonvolatile_registers[RegClassMax][RegisterMax];
|
|
UInt8 reg_state[RegClassMax][RegisterMax];
|
|
int first_temporary_register[RegClassMax];
|
|
int last_temporary_register[RegClassMax];
|
|
char *register_class_name[RegClassMax];
|
|
char *register_class_format[RegClassMax];
|
|
int coloring;
|
|
int optimizing;
|
|
|
|
typedef struct ModifiedRegisters {
|
|
struct ModifiedRegisters *next;
|
|
Object *obj;
|
|
UInt32 mask[RegClassMax];
|
|
} ModifiedRegisters;
|
|
static ModifiedRegisters *mod_regs_table[128];
|
|
|
|
void init_registers(void) {
|
|
RegClass rclass;
|
|
int j;
|
|
|
|
for (rclass = 0; rclass < RegClassMax; rclass++) {
|
|
for (j = 0; j < RegisterMax; j++)
|
|
reg_state[rclass][j] = RegState0;
|
|
}
|
|
|
|
for (rclass = 0; rclass < RegClassMax; rclass++)
|
|
used_nonvolatile_registers[rclass] = 0;
|
|
|
|
optimizing = 1;
|
|
|
|
init_target_registers();
|
|
for (rclass = 0; rclass < RegClassMax; rclass++)
|
|
used_virtual_registers[rclass] = n_real_registers[rclass];
|
|
|
|
coloring = 1;
|
|
}
|
|
|
|
void assign_register_to_variable(Object *obj, RegClass rclass) {
|
|
VarInfo *vi;
|
|
short reg;
|
|
|
|
vi = Registers_GetVarInfo(obj);
|
|
if (optimizing) {
|
|
reg = used_virtual_registers[rclass]++;
|
|
} else {
|
|
reg = obtain_nonvolatile_register(rclass);
|
|
retain_register(obj, rclass, reg);
|
|
}
|
|
|
|
vi->flags |= VarInfoFlag2;
|
|
vi->rclass = rclass;
|
|
vi->reg = reg;
|
|
}
|
|
|
|
void retain_register_for_argument(Object *obj, RegClass rclass, short reg) {
|
|
VarInfo *vi = obj->u.var.info;
|
|
reg_state[rclass][reg] = RegState1;
|
|
vi->flags |= VarInfoFlag2;
|
|
vi->rclass = rclass;
|
|
vi->reg = reg;
|
|
}
|
|
|
|
int available_registers(RegClass rclass) {
|
|
int i;
|
|
int count = 0;
|
|
|
|
for (i = 0; i < n_real_registers[rclass]; i++) {
|
|
if (reg_state[rclass][i] == RegState0)
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
UInt32 volatile_registers(RegClass rclass) {
|
|
UInt32 mask = 0;
|
|
int i;
|
|
int reg;
|
|
|
|
for (i = 0; i < n_scratch_registers[rclass]; i++) {
|
|
reg = scratch_registers[rclass][i];
|
|
if (reg_state[rclass][reg] == RegState0)
|
|
mask |= 1 << reg;
|
|
}
|
|
|
|
return mask;
|
|
}
|
|
|
|
short obtain_nonvolatile_register(RegClass rclass) {
|
|
int best = -1;
|
|
|
|
while (used_nonvolatile_registers[rclass] < n_nonvolatile_registers[rclass]) {
|
|
int tmp = nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]++];
|
|
if (reg_state[rclass][tmp] == RegState0) {
|
|
best = tmp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return best;
|
|
}
|
|
|
|
void open_temp_registers(void) {
|
|
RegClass rclass;
|
|
|
|
for (rclass = 0; rclass < RegClassMax; rclass++) {
|
|
int r = used_virtual_registers[rclass];
|
|
first_temporary_register[rclass] = last_temporary_register[rclass] = r;
|
|
}
|
|
}
|
|
|
|
void check_temp_registers(void) {
|
|
RegClass rclass;
|
|
|
|
if (!optimizing) {
|
|
for (rclass = 0; rclass < RegClassMax; rclass++) {
|
|
if (used_virtual_registers[rclass] > last_temporary_register[rclass])
|
|
last_temporary_register[rclass] = used_virtual_registers[rclass];
|
|
if (used_virtual_registers[rclass] > 256)
|
|
used_virtual_registers[rclass] = first_temporary_register[rclass];
|
|
}
|
|
}
|
|
}
|
|
|
|
void close_temp_registers(void) {
|
|
RegClass rclass;
|
|
|
|
for (rclass = 0; rclass < RegClassMax; rclass++) {
|
|
if (used_virtual_registers[rclass] < last_temporary_register[rclass])
|
|
used_virtual_registers[rclass] = last_temporary_register[rclass];
|
|
else
|
|
last_temporary_register[rclass] = used_virtual_registers[rclass];
|
|
}
|
|
}
|
|
|
|
int count_scratch_registers(void) {
|
|
RegClass rclass;
|
|
int count;
|
|
|
|
count = 0;
|
|
for (rclass = 0; rclass < RegClassMax; rclass++)
|
|
count += n_scratch_registers[rclass];
|
|
return count;
|
|
}
|
|
|
|
void init_modified_registers(void) {
|
|
int i = 0;
|
|
|
|
for (i = 0; i < 128; i++)
|
|
mod_regs_table[i] = NULL;
|
|
}
|
|
|
|
static void compute_modified_registers(UInt32 *masks) {
|
|
RegClass rclass;
|
|
PCodeBlock *block;
|
|
PCode *pcode;
|
|
PCodeArg *op;
|
|
int i;
|
|
|
|
for (rclass = 0; rclass < RegClassMax; rclass++)
|
|
masks[rclass] = 0;
|
|
|
|
for (block = pcbasicblocks; block; block = block->nextBlock) {
|
|
for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) {
|
|
op = pcode->args;
|
|
i = pcode->argCount;
|
|
while (i--) {
|
|
if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite))
|
|
masks[op->arg] |= 1 << op->data.reg.reg;
|
|
op++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void note_modified_registers(Object *obj) {
|
|
ModifiedRegisters *mr;
|
|
|
|
mr = galloc(sizeof(ModifiedRegisters));
|
|
mr->obj = obj;
|
|
compute_modified_registers(mr->mask);
|
|
mr->next = mod_regs_table[obj->name->hashval & 127];
|
|
mod_regs_table[obj->name->hashval & 127] = mr;
|
|
}
|
|
|
|
void find_modified_registers(Object *obj, UInt32 *masks) {
|
|
RegClass rclass;
|
|
ModifiedRegisters *scan;
|
|
|
|
for (rclass = 0; rclass < RegClassMax; rclass++)
|
|
masks[rclass] = 0xFFFFFFFF;
|
|
|
|
if (CParser_HasInternalLinkage(obj)) {
|
|
for (scan = mod_regs_table[obj->name->hashval & 127]; scan; scan = scan->next) {
|
|
if (scan->obj == obj)
|
|
break;
|
|
}
|
|
if (scan) {
|
|
for (rclass = 0; rclass < RegClassMax; rclass++)
|
|
masks[rclass] = scan->mask[rclass];
|
|
}
|
|
}
|
|
}
|