def make_int_graph(cfg): liveouts = flow.get_lives(cfg) g = {} for n in cfg.vertices.keys(): inst = cfg.inst(n) if type(inst) != IR: continue defed = cfg.def_(n) uninterfered = [defed] if defed is None: continue if inst.opcode == 'move': uninterfered.append(inst.rs) if defed.typ != 'virtual': continue if defed not in g: g[defed] = set() for reg in liveouts[n]: if reg in uninterfered or reg.typ != 'virtual': continue g[defed].add(reg) if reg not in g: g[reg] = set() g[reg].add(defed) return g, liveouts
def remove_placeholders(self): ''' replace Prolog/Epilog/SaveRegisters/RestoreRegisters with real instructions now that we know what registers are used ''' cfg = flow.make_cfg(self.insts) outs = flow.get_lives(cfg) # t registers that need to be saved tregs = [] for node in sorted(cfg.get_calls()): tregs.append(sorted({reg for reg in outs[node] if reg.typ == 't'})) space = (max(len(regs) for regs in tregs) * 4 if len(tregs) > 0 else 0) t_offset = self.alloc(size=space) s_offset = self.alloc(size=len(self.sregs)*4+4) # replace prologs/epilogs with stores and loads insts = [] i = 0 if i < len(tregs): regs = tregs[i] i += 1 for inst in self.insts: inst_type = type(inst) if inst_type == Call: store_regs(regs, t_offset, insts) insts.append( new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(-mulof4(inst.extra)))) insts.append(new_ir('jal', rs=funcname_to_branch(inst.name), rt=None, rd=None)) insts.append( new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(mulof4(inst.extra)))) load_regs(regs, t_offset, insts) if i < len(tregs): regs = tregs[i] i += 1 elif inst_type == Prolog: # grow stack and store needed s registers grow = new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(-self.stack_size())) insts.extend([ new_ir('move', rd=REG_FP, rs=REG_SP, rt=None), grow ]) store_regs(self.sregs+[REG_RA], s_offset, insts) elif inst_type == Epilog: # restore used registers load_regs(self.sregs+[REG_RA], s_offset, insts) shrink = new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(self.stack_size())) insts.extend([ shrink, new_ir('jr', rs=Register('ra', None), rt=None, rd=None) ]) else: insts.append(inst) self.insts = insts
def remove_placeholders(self): ''' replace Prolog/Epilog/SaveRegisters/RestoreRegisters with real instructions now that we know what registers are used ''' cfg = flow.make_cfg(self.insts) outs = flow.get_lives(cfg) # t registers that need to be saved tregs = [] for node in sorted(cfg.get_calls()): tregs.append(sorted({reg for reg in outs[node] if reg.typ == 't'})) space = (max(len(regs) for regs in tregs) * 4 if len(tregs) > 0 else 0) t_offset = self.alloc(size=space) s_offset = self.alloc(size=len(self.sregs) * 4 + 4) # replace prologs/epilogs with stores and loads insts = [] i = 0 if i < len(tregs): regs = tregs[i] i += 1 for inst in self.insts: inst_type = type(inst) if inst_type == Call: store_regs(regs, t_offset, insts) insts.append( new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(-mulof4(inst.extra)))) insts.append( new_ir('jal', rs=funcname_to_branch(inst.name), rt=None, rd=None)) insts.append( new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(mulof4(inst.extra)))) load_regs(regs, t_offset, insts) if i < len(tregs): regs = tregs[i] i += 1 elif inst_type == Prolog: # grow stack and store needed s registers grow = new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(-self.stack_size())) insts.extend( [new_ir('move', rd=REG_FP, rs=REG_SP, rt=None), grow]) store_regs(self.sregs + [REG_RA], s_offset, insts) elif inst_type == Epilog: # restore used registers load_regs(self.sregs + [REG_RA], s_offset, insts) shrink = new_ir('add', rd=REG_SP, rs=REG_SP, rt=grammar.Int(self.stack_size())) insts.extend([ shrink, new_ir('jr', rs=Register('ra', None), rt=None, rd=None) ]) else: insts.append(inst) self.insts = insts