//===----------------------------------------------------------------------===// // Print Spiller Implementation. // This spiller will print the register allocation directives in the smira // format, so that it can be debugged. // // To use it, copy and paste this code into the VirtRegMap.cpp file, and add // the following changes: // // Method createSpiller: // llvm::Spiller* llvm::createSpiller() { // switch (SpillerOpt) { // default: assert(0 && "Unreachable!"); // case local: // return new LocalSpiller(); // case simple: // return new SimpleSpiller(); // case print: // return new PrintSpiller(); // } // } // // Declaration of the spiller: // enum SpillerName { simple, local, print }; // // static cl::opt // SpillerOpt("spiller", // cl::desc("Spiller to use: (default: local)"), // cl::Prefix, // cl::values(clEnumVal(simple, " simple spiller"), // clEnumVal(print, " print spiller"), // clEnumVal(local, " local spiller"), // clEnumValEnd), // cl::init(local)); //===----------------------------------------------------------------------===// namespace { struct VISIBILITY_HIDDEN PrintSpiller : public Spiller { bool runOnMachineFunction(MachineFunction& mf, VirtRegMap &VRM); }; } //===-------------------------------------------------------------------------- // This method prints a register and its location in a notation like // (loc, reg). //===-------------------------------------------------------------------------- void print_reg(unsigned loc, unsigned reg) { std::cout << "(R" << loc << ", " << "P" << reg << ") "; } //===-------------------------------------------------------------------------- // This method prints the definition of a virtual register. In addition of // printing the pair (p_reg, v_reg), the method prints a binding pair for each // alias of p_reg. //===-------------------------------------------------------------------------- void print_def(MachineFunction & mf, unsigned p_reg, unsigned v_reg) { print_reg(p_reg, v_reg); const TargetMachine & target_machine = mf.getTarget(); const MRegisterInfo * reg_info = target_machine.getRegisterInfo(); for (const unsigned *a = reg_info->getAliasSet(p_reg); *a; ++a) { std::cout << " "; print_reg(*a, v_reg); } } //===-------------------------------------------------------------------------- // This method prints an instruction in the smira format. The instruction is // printed as (R1, P1) ... (Rn, Pn) = (Rm, Pm) ... (Rz, Pz), where the // bindings // (R_, P_) are described in the maps "def_map" and "use_map". //===-------------------------------------------------------------------------- void print_bindings( MachineFunction & mf, MachineInstr & mi, std::map def_map, std::map use_map ) { const TargetMachine & target_machine = mf.getTarget(); const TargetInstrInfo & tii = * (target_machine.getInstrInfo()); const TargetInstrDescriptor & tid = tii.get(mi.getOpcode()); // print the implict definitions: if(tid.ImplicitDefs) { for (const unsigned *implicit_def = tid.ImplicitDefs; *implicit_def; ++implicit_def) { print_reg(* implicit_def, * implicit_def); } } std::map::iterator i, e; for(i = def_map.begin(), e = def_map.end(); i != e; i++) { print_def(mf, i->second, i->first); } std::cout << " = "; // print the explicit uses: for(i = use_map.begin(), e = use_map.end(); i != e; i++) { print_reg(i->second, i->first); } // print the implicit uses: if(tid.ImplicitUses) { for(const unsigned *implicit_use = tid.ImplicitUses; *implicit_use; implicit_use++) { print_reg(* implicit_use, * implicit_use); } } std::cout << " ;\n"; } bool PrintSpiller::runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM) { const TargetMachine &TM = MF.getTarget(); const MRegisterInfo &MRI = *TM.getRegisterInfo(); bool *PhysRegsUsed = MF.getUsedPhysregs(); unsigned store_p=0, store_v=0; const Function * f = MF.getFunction(); // Prints the header comments of the smira file. std::cout << "/*\n"; std::cout << " * Function name: " << f->getName() << std::endl; std::cout << " * Number of basic blocks: " << MF.size() << std::endl; std::cout << " */\n\n"; // LoadedRegs - Keep track of which vregs are loaded, so that we only load // each vreg once (in the case where a spilled vreg is used by multiple // operands). This is always smaller than the number of operands to the // current machine instr, so it should be small. std::vector LoadedRegs; for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); MBBI != E; ++MBBI) { DEBUG(std::cerr << MBBI->getBasicBlock()->getName() << ":\n"); MachineBasicBlock &MBB = *MBBI; // prints the label of the basic block MBB: std::cout << "L" << MBB.getNumber() << std::endl; for (MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end(); MII != E; ++MII) { MachineInstr &MI = *MII; // The mappings def_map and use_map will map virtual variables to // physical registers. std::map def_map; std::map use_map; for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); if (MO.isRegister() && MO.getReg()) if (MRegisterInfo::isVirtualRegister(MO.getReg())) { unsigned VirtReg = MO.getReg(); unsigned PhysReg = VRM.getPhys(VirtReg); if (VRM.hasStackSlot(VirtReg)) { int StackSlot = VRM.getStackSlot(VirtReg); const TargetRegisterClass* RC = MF.getSSARegMap()->getRegClass(VirtReg); if (MO.isUse() && std::find(LoadedRegs.begin(), LoadedRegs.end(), VirtReg) == LoadedRegs.end()) { MRI.loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC); // Prints the code for a load. Memory addresses are also in the // format R, but memory addresses are much bigger than // register numbers, which go from 1 to : print_def(MF, PhysReg, VirtReg); std::cout << " = "; print_reg(StackSlot + 100000, StackSlot + 100000); std::cout << " ;\n"; LoadedRegs.push_back(VirtReg); ++NumLoads; DEBUG(std::cerr << '\t' << *prior(MII)); } if (MO.isDef()) { // This variables will be used to feed the use or def mapping. store_v = VirtReg; store_p = PhysReg; MRI.storeRegToStackSlot(MBB, next(MII), PhysReg, StackSlot, RC); ++NumStores; } } PhysRegsUsed[PhysReg] = true; MI.getOperand(i).setReg(PhysReg); // Store the last binding into the right mapping: if(MO.isDef()) { def_map[VirtReg] = PhysReg; } else { use_map[VirtReg] = PhysReg; } } else { PhysRegsUsed[MO.getReg()] = true; unsigned p_reg = MO.getReg(); if(MO.isDef()) { def_map[p_reg] = p_reg; } else { use_map[p_reg] = p_reg; } } } // Calls routine to print the bindings in the instruction. print_bindings(MF, MI, def_map, use_map); // If there is anything to be stored, it must be printed. Notice that we // are assuming that each instruction produces at most one store. This // assumption is reasonable, given the SSA form. if(store_p != 0) { unsigned VirtReg = store_v; unsigned PhysReg = store_p; int StackSlot = VRM.getStackSlot(VirtReg); print_reg(StackSlot + 100000, StackSlot + 100000); print_reg(PhysReg, PhysReg); std::cout << " = "; print_reg(PhysReg, VirtReg); std::cout << " /* STORE */;\n"; store_p = 0; store_v = 0; } DEBUG(std::cerr << '\t' << MI); LoadedRegs.clear(); } // End of the basic block: // If the current basic block is a dead point, that is, it has no // successors, we must print a jump to the last basic block in the function, // else we must print a jump to each of the successor basic blocks. std::cout << "JMP "; if(MBB.succ_begin() == MBB.succ_end()) { std::cout << "L" << MF.getNumBlockIDs(); } else { for(MachineBasicBlock::const_succ_iterator scc = MBB.succ_begin(); scc != MBB.succ_end(); scc++) { std::cout << "L" << (*scc)->getNumber() << " "; } } std::cout << " ;\n\n"; } // End of the machine function. We must print the last basic block of the // function. Every block that is a dead end contains a jump to this block. // This block contains only a jump to itself. unsigned last_label = MF.size(); std::cout << "\nL" << last_label << std::endl; std::cout << "JMP L" << last_label << " ;\n"; return true; }