#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]; } } }