// Insert Defs and Uses of MI into the sets RegDefs and RegUses. void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { // If MI is a call or return, just examine the explicit non-variadic operands. MCInstrDesc MCID = MI->getDesc(); unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() : MI->getNumOperands(); for (unsigned I = 0; I != E; ++I) { const MachineOperand &MO = MI->getOperand(I); unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg())) continue; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); } // Call & return instructions defines SP implicitly. Implicit defines are not // included in the RegDefs set of calls but instructions modifying SP cannot // be inserted in the delay slot of a call/return as these instructions are // expanded to multiple instructions with SP modified before the branch that // has the delay slot. if (MI->isCall() || MI->isReturn()) RegDefs.insert(Lanai::SP); }
// Insert Defs and Uses of MI into the sets RegDefs and RegUses. void Filler::insertDefsUses(MachineBasicBlock::iterator MI, SmallSet<unsigned, 32>& RegDefs, SmallSet<unsigned, 32>& RegUses) { // If MI is a call or return, just examine the explicit non-variadic operands. MCInstrDesc MCID = MI->getDesc(); unsigned e = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() : MI->getNumOperands(); // Add RA to RegDefs to prevent users of RA from going into delay slot. if (MI->isCall()) RegDefs.insert(Mips::RA); for (unsigned i = 0; i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg())) continue; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); } }
// Insert Defs and Uses of MI into the sets RegDefs and RegUses. void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { // If MI is a call or return, just examine the explicit non-variadic operands. MCInstrDesc MCID = MI->getDesc(); unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() : MI->getNumOperands(); for (unsigned I = 0; I != E; ++I) { const MachineOperand &MO = MI->getOperand(I); unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg())) continue; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); } }
unsigned Disassembler::decodeInstruction(unsigned Address, MachineBasicBlock *Block) { // Disassemble instruction const MCDisassembler *DA = MC->getMCDisassembler(); uint64_t InstSize; MCInst *Inst = new MCInst(); StringRef Bytes; if (!(DA->getInstruction(*Inst, InstSize, *CurSectionMemory, Address, nulls(), nulls()))) { printError("Unknown instruction encountered, instruction decode failed!"); return 1; // Instructions[Address] = NULL; // Block->push_back(NULL); // TODO: Replace with default size for each target. // return 1; // outs() << format("%8" PRIx64 ":\t", SectAddr + Index); // Dism->rawBytesToString(StringRef(Bytes.data() + Index, Size)); // outs() << " unkn\n"; } Instructions[Address] = Inst; // Recover Instruction information const MCInstrInfo *MII = MC->getMCInstrInfo(); MCInstrDesc *MCID = new MCInstrDesc(MII->get(Inst->getOpcode())); MCID->Size = InstSize; // Check if the instruction can load to program counter and mark it as a Ret // FIXME: Better analysis would be to see if the PC value references memory // sent as a parameter or set locally in the function, but that would need to // happen after decompilation. In either case, this is definitely a BB // terminator or branch! if (MCID->mayLoad() && MCID->mayAffectControlFlow(*Inst, *MC->getMCRegisterInfo())) { MCID->Flags |= (1 << MCID::Return); MCID->Flags |= (1 << MCID::Terminator); } // Recover MachineInstr representation DebugLoc *Location = setDebugLoc(Address); MachineInstrBuilder MIB = BuildMI(Block, *Location, *MCID); unsigned int numDefs = MCID->getNumDefs(); for (unsigned int i = 0; i < Inst->getNumOperands(); i++) { MCOperand MCO = Inst->getOperand(i); // FIXME: This hack is a workaround for the assert in MachineInstr.cpp:653, // where OpNo >= MCID->getNumOperands()... if (i >= MCID->getNumOperands() && !(MCID->isVariadic())) break; if (MCO.isReg()) { unsigned flags = 0; // Defs always start at the beginning of the operands list, // unfortunately BuildMI doesn't set default define flags so we have // to do it manually here. // NOTE: This should always be true, but might not be if operands list // is not populated correctly by the MC Backend for the target. if (i < numDefs) { flags |= RegState::Define; } // NOTE: No need to worry about imp defs and uses, as these are already // specificed in the MCID attached to the MachineInst object. MIB.addReg(MCO.getReg(), flags); continue; } if (MCO.isImm()) { MIB.addImm(MCO.getImm()); continue; } //else if (MCO.isFPImm()) MIB.addFPImm(MCO.getFPImm()); if (MCO.isExpr()) { MCOperandInfo MCOpInfo = MCID->OpInfo[i]; switch (MCOpInfo.OperandType) { case MCOI::OPERAND_MEMORY: case MCOI::OPERAND_PCREL: case MCOI::OPERAND_UNKNOWN: default: printError("Unknown how to handle this Expression at this time."); } } printError("Unknown how to handle Operand!"); } // NOTE: I tried MCOpInfo here, and it appearst o be NULL // ... at least for ARM. unsigned flags = 0; if (MCID->mayLoad()) flags |= MachineMemOperand::MOLoad; if (MCID->mayStore()) flags |= MachineMemOperand::MOStore; if (flags != 0) { // Constant* cInt = ConstantInt::get(Type::getInt64Ty(ctx), MCO.getImm()); // Value *Val = ConstantExpr::getIntToPtr(cInt, // PointerType::getUnqual(Type::getInt32Ty(ctx))); // FIXME: note size of 4 is known to be bad for // some targets //Copy & paste set getImm to zero MachineMemOperand* MMO = new MachineMemOperand( MachinePointerInfo(), flags, 4, 0); //MCO.getImm() MIB.addMemOperand(MMO); //outs() << "Name: " << MII->getName(Inst->getOpcode()) << " Flags: " << flags << "\n"; } // Note: I don't know why they decided instruction size needed to be 64 bits, // but the following conversion shouldn't be an issue. return ((unsigned)InstSize); }