Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
"Register allocation"
// AAPCS64 (procedure call standard) stuff
uint32_t ngrn = 0; // "Next General-Purpose Register Number (NGRN)"
uint32_t reg_avail = ~((1u << 18) | (1u << 29) | (1u << 30) | (1u << 31)); // available regs
bool regs_assigned = false;
Var *new_arg(const std::string &name)
{
assert(ngrn < 8); // not handling stack args for now
assert(reg_avail & (1u << ngrn)); // reg must be free
Var *v = new_var(name);
v->reg = Reg(ngrn);
reg_avail &= ~(1u << ngrn);
++ngrn;
return v;
}
// Args get assigned regs immediately; we delay assigning regs to temps until
// we've seen all args.
void assign_temp_regs()
{
Var *spills[32];
int spill_count = 0;
for (auto &v : vars)
{
if (v->reg.valid)
continue;
if (!reg_avail)
errorf("%s: No register left to assign to variable '%s'.\n", name.c_str(), v->name.c_str());
// assign first free reg
uint32_t i = 0;
while ((reg_avail & (1u << i)) == 0)
++i;
v->reg = Reg(i);
reg_avail &= ~(1u << i);
// If it's a callee-save register, we need to generate prologue/epilogue code for it!
if (i >= 19)
spills[spill_count++] = v.get();
}
// Generate prologue/epilogue code
if (spill_count)
{
int frame_size = (spill_count*8 + 15) & ~15; // SP must stay 16-byte aligned
for (uint32_t i = 0; i < spill_count; )
{
Addr store_addr = (i == 0) ? Addr::pre_idx(SP, -frame_size) : Addr::base(SP, i*8);
Addr load_addr = (i == 0) ? Addr::post_idx(SP, frame_size) : Addr::base(SP, i*8);
if (i + 1 < spill_count) // use a pair!
{
bb_entry->append(STP(spills[i+0], spills[i+1], store_addr));
bb_exit->prepend(LDP(spills[i+0], spills[i+1], load_addr));
i += 2;
}
else
{
bb_entry->append(STR(spills[i], store_addr));
bb_exit->prepend(LDR(spills[i], load_addr));
i += 1;
}
}
}
regs_assigned = true;
}
void validate()
{
// Verify that all vars have been assigned registers
for (auto &v : vars)
{
if (!v->reg.valid)
errorf("%s: Variable '%s' has no assigned register.\n", name.c_str(), v->name.c_str());
}
// Validate all basic blocks
for (auto &bb : blocks)
bb->validate(name.c_str());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment