void EpiphanyAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Do any auto-generated pseudo lowerings. if (emitPseudoExpansionLowering(*OutStreamer, MI)) return; switch (MI->getOpcode()) { case Epiphany::DBG_VALUE: { if (isVerbose() && OutStreamer->hasRawTextSupport()) { SmallString<128> TmpStr; raw_svector_ostream OS(TmpStr); PrintDebugValueComment(MI, OS); OutStreamer->EmitRawText(StringRef(OS.str())); } return; } case Epiphany::MOVT32ri: { EmitToStreamer(*OutStreamer, MCInstBuilder(Epiphany::MOVT32ri) .addReg(MI->getOperand(0).getReg()) .addReg(MI->getOperand(0).getReg()) .addImm(MI->getOperand(1).getImm())); return; } } // Generic way MachineBasicBlock::const_instr_iterator I = MI; MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); do { MCInst TmpInst; MCInstLowering.Lower(I, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); } while ((++I != E) && I->isInsideBundle()); }
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { AMDGPUMCInstLower MCInstLowering; // Ignore placeholder instructions: if (MI->getOpcode() == AMDGPU::MASK_WRITE) { return; } if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = MI; ++I; while (I != MBB->end() && I->isInsideBundle()) { MCInst MCBundleInst; const MachineInstr *BundledInst = I; MCInstLowering.lower(BundledInst, MCBundleInst); OutStreamer.EmitInstruction(MCBundleInst); ++I; } } else { MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); OutStreamer.EmitInstruction(TmpInst); } }
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { const AMDGPUSubtarget &STI = MF->getSubtarget<AMDGPUSubtarget>(); AMDGPUMCInstLower MCInstLowering(OutContext, STI); #ifdef _DEBUG StringRef Err; if (!STI.getInstrInfo()->verifyInstruction(MI, Err)) { errs() << "Warning: Illegal instruction detected: " << Err << "\n"; MI->dump(); } #endif if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = MI; ++I; while (I != MBB->end() && I->isInsideBundle()) { EmitInstruction(I); ++I; } } else { MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); EmitToStreamer(OutStreamer, TmpInst); if (STI.dumpCode()) { // Disassemble instruction/operands to text. DisasmLines.resize(DisasmLines.size() + 1); std::string &DisasmLine = DisasmLines.back(); raw_string_ostream DisasmStream(DisasmLine); AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *MF->getSubtarget().getInstrInfo(), *MF->getSubtarget().getRegisterInfo()); InstPrinter.printInst(&TmpInst, DisasmStream, StringRef()); // Disassemble instruction/operands to hex representation. SmallVector<MCFixup, 4> Fixups; SmallVector<char, 16> CodeBytes; raw_svector_ostream CodeStream(CodeBytes); MCObjectStreamer &ObjStreamer = (MCObjectStreamer &)OutStreamer; MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter(); InstEmitter.EncodeInstruction(TmpInst, CodeStream, Fixups, MF->getSubtarget<MCSubtargetInfo>()); CodeStream.flush(); HexLines.resize(HexLines.size() + 1); std::string &HexLine = HexLines.back(); raw_string_ostream HexStream(HexLine); for (size_t i = 0; i < CodeBytes.size(); i += 4) { unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); } DisasmStream.flush(); DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); } } }
const Function *PatmosInstrInfo::getCallee(const MachineInstr *MI) const { const Function *F = NULL; if (MI->isBundle()) { MachineBasicBlock::const_instr_iterator it = MI; while ((++it)->isBundledWithPred()) { if (!it->isCall()) continue; if (F) return NULL; F = getCallee(it); if (!F) return NULL; } return F; } // get target const MachineOperand &MO(MI->getOperand(2)); // try to find the target of the call if (MO.isGlobal()) { // is the global value a function? F = dyn_cast<Function>(MO.getGlobal()); } else if (MO.isSymbol()) { // find the function in the current module const Module &M = *MI->getParent()->getParent()->getFunction()->getParent(); F = dyn_cast_or_null<Function>(M.getNamedValue(MO.getSymbolName())); } return F; }
unsigned int PatmosInstrInfo::getInstrSize(const MachineInstr *MI) const { if (MI->isInlineAsm()) { // TODO is there a way to get the current context? MCContext Ctx(PTM.getMCAsmInfo(), PTM.getRegisterInfo(), PTM.getInstrInfo(), 0); // PIA is deleted by AsmPrinter PatmosInstrAnalyzer *PIA = createPatmosInstrAnalyzer(Ctx); PatmosAsmPrinter PAP(PTM, *PIA); PAP.EmitInlineAsm(MI); return PIA->getSize(); } else if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = MI, E = MBB->instr_end(); unsigned Size = 0; while ((++I != E) && I->isInsideBundle()) { Size += getInstrSize(I); } return Size; } else if (MI->isPseudo()) { return 0; } else { // trust the desc.. return MI->getDesc().getSize(); } }
/// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to /// the current output stream. /// void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst MCB = HexagonMCInstrInfo::createBundle(); const MCInstrInfo &MCII = *Subtarget->getInstrInfo(); if (MI->isBundle()) { const MachineBasicBlock* MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator MII = MI->getIterator(); unsigned IgnoreCount = 0; for (++MII; MII != MBB->instr_end() && MII->isInsideBundle(); ++MII) if (MII->getOpcode() == TargetOpcode::DBG_VALUE || MII->getOpcode() == TargetOpcode::IMPLICIT_DEF) ++IgnoreCount; else HexagonLowerToMC(MCII, &*MII, MCB, *this); } else HexagonLowerToMC(MCII, MI, MCB, *this); bool Ok = HexagonMCInstrInfo::canonicalizePacket( MCII, *Subtarget, OutStreamer->getContext(), MCB, nullptr); assert(Ok); (void)Ok; if(HexagonMCInstrInfo::bundleSize(MCB) == 0) return; OutStreamer->EmitInstruction(MCB, getSubtargetInfo()); }
bool PatmosInstrInfo::isPseudo(const MachineInstr *MI) const { if (MI->isBundle()) { MachineBasicBlock::const_instr_iterator II = MI; ++II; const MachineBasicBlock *MBB = MI->getParent(); while (II != MBB->instr_end() && II->isBundledWithPred()) { if (!isPseudo(II)) return false; II++; } return true; } if (MI->isDebugValue()) return true; // We must emit inline assembly if (MI->isInlineAsm()) return false; // We check if MI has any functional units mapped to it. // If it doesn't, we ignore the instruction. const MCInstrDesc& TID = MI->getDesc(); unsigned SchedClass = TID.getSchedClass(); const InstrStage* IS = PST.getInstrItineraryData().beginStage(SchedClass); unsigned FuncUnits = IS->getUnits(); return !FuncUnits; }
PatmosII::MemType PatmosInstrInfo::getMemType(const MachineInstr *MI) const { assert(MI->mayLoad() || MI->mayStore()); if (MI->isBundle()) { // find mem instruction in bundle (does not need to be the first // instruction, they might be sorted later!) MachineBasicBlock::const_instr_iterator II = MI; ++II; while (II->isInsideBundle() && !II->mayLoad() && !II->mayStore()) { ++II; } return getMemType(II); } // FIXME: Maybe there is a better way to get this info directly from // the instruction definitions in the .td files using namespace Patmos; unsigned opc = MI->getOpcode(); switch (opc) { case LWS: case LHS: case LBS: case LHUS: case LBUS: case SWS: case SHS: case SBS: return PatmosII::MEM_S; case LWL: case LHL: case LBL: case LHUL: case LBUL: case SWL: case SHL: case SBL: return PatmosII::MEM_L; case LWC: case LHC: case LBC: case LHUC: case LBUC: case SWC: case SHC: case SBC: return PatmosII::MEM_C; case LWM: case LHM: case LBM: case LHUM: case LBUM: case SWM: case SHM: case SBM: return PatmosII::MEM_M; default: llvm_unreachable("Unexpected memory access instruction!"); } }
bool PatmosInstrInfo::getCallees(const MachineInstr *MI, SmallSet<const Function*,2> &Callees) const { if (MI->isBundle()) { MachineBasicBlock::const_instr_iterator it = MI; bool safe = true; while ((++it)->isBundledWithPred()) { if (!it->isCall() && !it->isInlineAsm()) continue; safe = getCallees(it, Callees) && safe; } return safe; } if (MI->isCall()) { const Function *F = getCallee(MI); if (F) { Callees.insert(F); return true; } else { // Could be an indirect call.. return false; } } else if (MI->isInlineAsm()) { // We can skip the first operand as this should be the asm string. for (unsigned int i = 1; i < MI->getNumOperands(); i++) { const MachineOperand &MO(MI->getOperand(i)); const Function *F = NULL; // try to find the target of the call if (MO.isGlobal()) { // is the global value a function? F = dyn_cast_or_null<Function>(MO.getGlobal()); } else if (MO.isSymbol()) { // find the function in the current module const Module &M = *MI->getParent()->getParent()->getFunction()->getParent(); F = dyn_cast_or_null<Function>(M.getNamedValue(MO.getSymbolName())); } if (F) { // We are assuming here that if inline-asm uses a function reference // as operand, then it is probably used for a call. Callees.insert(F); } } // TODO for now we assume that inline asm does not contain CALLR and // that all callees are passed as asm operands. We should do a check // similar to hasCall() here. return true; } else { // No other instruction should do a call. return true; } }
void OR1KAsmPrinter::EmitInstruction(const MachineInstr *MI) { MachineBasicBlock::const_instr_iterator I = MI; MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); do { customEmitInstruction(I++); } while ((I != E) && I->isInsideBundle()); }
unsigned AArch64InstrInfo::getInstBundleLength(const MachineInstr &MI) const { unsigned Size = 0; MachineBasicBlock::const_instr_iterator I = MI; MachineBasicBlock::const_instr_iterator E = MI.getParent()->instr_end(); while (++I != E && I->isInsideBundle()) { assert(!I->isBundle() && "No nested bundle!"); Size += getInstSizeInBytes(*I); } return Size; }
void NyuziAsmPrinter::EmitInstruction(const MachineInstr *MI) { MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); do { MCInst TmpInst; MCInstLowering.Lower(MI, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); if (MI->getOpcode() == Nyuzi::JUMP_TABLE) { EmitInlineJumpTable(MI); } } while ((I != E) && I->isInsideBundle()); }
void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) { MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); do { if (I->isCall()) { emitCallInstruction(&*I); continue; } customEmitInstruction(&*I); } while ((++I != E) && I->isInsideBundle()); }
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { AMDGPUMCInstLower MCInstLowering(OutContext); if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = MI; ++I; while (I != MBB->end() && I->isInsideBundle()) { EmitInstruction(I); ++I; } } else { MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); OutStreamer.EmitInstruction(TmpInst); if (DisasmEnabled) { // Disassemble instruction/operands to text. DisasmLines.resize(DisasmLines.size() + 1); std::string &DisasmLine = DisasmLines.back(); raw_string_ostream DisasmStream(DisasmLine); AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *TM.getInstrInfo(), *TM.getRegisterInfo()); InstPrinter.printInst(&TmpInst, DisasmStream, StringRef()); // Disassemble instruction/operands to hex representation. SmallVector<MCFixup, 4> Fixups; SmallVector<char, 16> CodeBytes; raw_svector_ostream CodeStream(CodeBytes); MCObjectStreamer &ObjStreamer = (MCObjectStreamer &)OutStreamer; MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter(); InstEmitter.EncodeInstruction(TmpInst, CodeStream, Fixups); CodeStream.flush(); HexLines.resize(HexLines.size() + 1); std::string &HexLine = HexLines.back(); raw_string_ostream HexStream(HexLine); for (size_t i = 0; i < CodeBytes.size(); i += 4) { unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); } DisasmStream.flush(); DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); } } }
void PatmosAsmPrinter::EmitInstruction(const MachineInstr *MI) { SmallVector<const MachineInstr*, 2> BundleMIs; unsigned Size = 1; // Unpack BUNDLE instructions if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator MII = MI; ++MII; while (MII != MBB->end() && MII->isInsideBundle()) { const MachineInstr *MInst = MII; if (MInst->isPseudo()) { // DBG_VALUE and IMPLICIT_DEFs outside of bundles are handled in // AsmPrinter::EmitFunctionBody() MInst->dump(); report_fatal_error("Pseudo instructions must not be bundled!"); } BundleMIs.push_back(MInst); ++MII; } Size = BundleMIs.size(); assert(Size == MI->getBundleSize() && "Corrupt Bundle!"); } else { if (MI->getOpcode() == Patmos::PSEUDO_LOOPBOUND) { int LoopBoundMin = MI->getOperand(0).getImm(); int LoopBoundMax = MI->getOperand(1).getImm(); OutStreamer.GetCommentOS() << "Loop bound: [" << LoopBoundMin << ", " << LoopBoundMax << "]\n"; return; } BundleMIs.push_back(MI); } // Emit all instructions in the bundle. for (unsigned Index = 0; Index < Size; Index++) { MCInst MCI; MCInstLowering.Lower(BundleMIs[Index], MCI); // Set bundle marker bool isBundled = (Index < Size - 1); MCI.addOperand(MCOperand::CreateImm(isBundled)); OutStreamer.EmitInstruction(MCI); } }
const MachineInstr *PatmosInstrInfo::hasOpcode(const MachineInstr *MI, int Opcode) const { if (MI->isBundle()) { MachineBasicBlock::const_instr_iterator II = MI; ++II; while (II->isInsideBundle()) { if (II->getOpcode() == Opcode) return II; II++; } return 0; } else { return MI->getOpcode() == Opcode ? MI : 0; } }
bool PatmosInstrInfo::mayStall(const MachineInstr *MI) const { if (MI->isInlineAsm()) { // Being conservative here.. return MI->mayLoad() || MI->mayStore(); } else if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = MI, E = MBB->instr_end(); while ((++I != E) && I->isInsideBundle()) { if (mayStall(I)) return true; } return false; } else if (MI->isPseudo()) { return false; } // We could check for load instructions if they are always-hit. return isPatmosMayStall(MI->getDesc().TSFlags); }
/// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to /// the current output stream. /// void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (MI->isBundle()) { std::vector<MachineInstr const *> BundleMIs; const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator MII = MI; ++MII; unsigned int IgnoreCount = 0; while (MII != MBB->end() && MII->isInsideBundle()) { const MachineInstr *MInst = MII; if (MInst->getOpcode() == TargetOpcode::DBG_VALUE || MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) { IgnoreCount++; ++MII; continue; } // BundleMIs.push_back(&*MII); BundleMIs.push_back(MInst); ++MII; } unsigned Size = BundleMIs.size(); assert((Size + IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!"); for (unsigned Index = 0; Index < Size; Index++) { MCInst MCI; HexagonLowerToMC(BundleMIs[Index], MCI, *this); HexagonMCInstrInfo::AppendImplicitOperands(MCI); HexagonMCInstrInfo::setPacketBegin(MCI, Index == 0); HexagonMCInstrInfo::setPacketEnd(MCI, Index == (Size - 1)); EmitToStreamer(*OutStreamer, MCI); } } else { MCInst MCI; HexagonLowerToMC(MI, MCI, *this); HexagonMCInstrInfo::AppendImplicitOperands(MCI); if (MI->getOpcode() == Hexagon::ENDLOOP0) { HexagonMCInstrInfo::setPacketBegin(MCI, true); HexagonMCInstrInfo::setPacketEnd(MCI, true); } EmitToStreamer(*OutStreamer, MCI); } return; }
bool PatmosInstrInfo::isPredicated(const MachineInstr *MI) const { if (MI->isBundle()) { MachineBasicBlock::const_instr_iterator II = MI; while (II->isBundledWithSucc()) { ++II; if (isPredicated(&*II)) return true; } return false; } int i = MI->findFirstPredOperandIdx(); if (i != -1) { unsigned preg = MI->getOperand(i).getReg(); int flag = MI->getOperand(++i).getImm(); return (preg!=Patmos::NoRegister && preg!=Patmos::P0) || flag; } // no predicates at all return false; }
MachineInstr &MachineFunction::CloneMachineInstrBundle(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) { MachineInstr *FirstClone = nullptr; MachineBasicBlock::const_instr_iterator I = Orig.getIterator(); for (;;) { MachineInstr *Cloned = CloneMachineInstr(&*I); MBB.insert(InsertBefore, Cloned); if (FirstClone == nullptr) { FirstClone = Cloned; } else { Cloned->bundleWithPred(); } if (!I->isBundledWithSucc()) break; ++I; } return *FirstClone; }
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { AMDGPUMCInstLower MCInstLowering(OutContext); if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = MI; ++I; while (I != MBB->end() && I->isInsideBundle()) { MCInst MCBundleInst; const MachineInstr *BundledInst = I; MCInstLowering.lower(BundledInst, MCBundleInst); OutStreamer.EmitInstruction(MCBundleInst); ++I; } } else { MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); OutStreamer.EmitInstruction(TmpInst); } }
void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) { switch (MI->getOpcode()) { default: break; case TargetOpcode::DBG_VALUE: // FIXME: Debug Value. return; case SP::GETPCX: LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo()); return; } MachineBasicBlock::const_instr_iterator I = MI; MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); do { MCInst TmpInst; LowerSparcMachineInstrToMCInst(I, TmpInst, *this); EmitToStreamer(OutStreamer, TmpInst); } while ((++I != E) && I->isInsideBundle()); // Delay slot check. }
bool PatmosInstrInfo::getPredicateOperands(const MachineInstr* MI, SmallVectorImpl<MachineOperand> &Pred) const { if (!isPredicated(MI)) return false; if (MI->isBundle()) { MachineBasicBlock::const_instr_iterator II = MI; while (II->isBundledWithSucc()) { ++II; getPredicateOperands(&*II, Pred); } return true; } if (!MI->getDesc().isPredicable()) return false; unsigned Pos = MI->getDesc().getNumDefs(); Pred.push_back(MI->getOperand(Pos)); Pred.push_back(MI->getOperand(Pos+1)); return true; }
/// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to /// the current output stream. /// void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst MCB; MCB.setOpcode(Hexagon::BUNDLE); MCB.addOperand(MCOperand::createImm(0)); if (MI->isBundle()) { const MachineBasicBlock* MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator MII = MI; unsigned IgnoreCount = 0; for (++MII; MII != MBB->end() && MII->isInsideBundle(); ++MII) { if (MII->getOpcode() == TargetOpcode::DBG_VALUE || MII->getOpcode() == TargetOpcode::IMPLICIT_DEF) ++IgnoreCount; else { HexagonLowerToMC(MII, MCB, *this); } } } else { HexagonLowerToMC(MI, MCB, *this); HexagonMCInstrInfo::padEndloop(MCB); } // Examine the packet and try to find instructions that can be converted // to compounds. HexagonMCInstrInfo::tryCompound(*Subtarget->getInstrInfo(), OutStreamer->getContext(), MCB); // Examine the packet and convert pairs of instructions to duplex // instructions when possible. SmallVector<DuplexCandidate, 8> possibleDuplexes; possibleDuplexes = HexagonMCInstrInfo::getDuplexPossibilties( *Subtarget->getInstrInfo(), MCB); HexagonMCShuffle(*Subtarget->getInstrInfo(), *Subtarget, OutStreamer->getContext(), MCB, possibleDuplexes); EmitToStreamer(*OutStreamer, MCB); }
void R600AsmPrinter::EmitInstruction(const MachineInstr *MI) { const R600Subtarget &STI = MF->getSubtarget<R600Subtarget>(); R600MCInstLower MCInstLowering(OutContext, STI, *this); StringRef Err; if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) { LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); C.emitError("Illegal instruction detected: " + Err); MI->print(errs()); } if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); while (I != MBB->instr_end() && I->isInsideBundle()) { EmitInstruction(&*I); ++I; } } else { MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); } }
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { const AMDGPUSubtarget &STI = MF->getSubtarget<AMDGPUSubtarget>(); AMDGPUMCInstLower MCInstLowering(OutContext, STI); StringRef Err; if (!STI.getInstrInfo()->verifyInstruction(MI, Err)) { LLVMContext &C = MI->getParent()->getParent()->getFunction()->getContext(); C.emitError("Illegal instruction detected: " + Err); MI->dump(); } if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); while (I != MBB->instr_end() && I->isInsideBundle()) { EmitInstruction(&*I); ++I; } } else { // We don't want SI_MASK_BRANCH/SI_RETURN encoded. They are placeholder // terminator instructions and should only be printed as comments. if (MI->getOpcode() == AMDGPU::SI_MASK_BRANCH) { if (isVerbose()) { SmallVector<char, 16> BBStr; raw_svector_ostream Str(BBStr); const MachineBasicBlock *MBB = MI->getOperand(1).getMBB(); const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); Expr->print(Str, MAI); OutStreamer->emitRawComment(" mask branch " + BBStr); } return; } if (MI->getOpcode() == AMDGPU::SI_RETURN) { if (isVerbose()) OutStreamer->emitRawComment(" return"); return; } MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); if (STI.dumpCode()) { // Disassemble instruction/operands to text. DisasmLines.resize(DisasmLines.size() + 1); std::string &DisasmLine = DisasmLines.back(); raw_string_ostream DisasmStream(DisasmLine); AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *STI.getInstrInfo(), *STI.getRegisterInfo()); InstPrinter.printInst(&TmpInst, DisasmStream, StringRef(), STI); // Disassemble instruction/operands to hex representation. SmallVector<MCFixup, 4> Fixups; SmallVector<char, 16> CodeBytes; raw_svector_ostream CodeStream(CodeBytes); auto &ObjStreamer = static_cast<MCObjectStreamer&>(*OutStreamer); MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter(); InstEmitter.encodeInstruction(TmpInst, CodeStream, Fixups, MF->getSubtarget<MCSubtargetInfo>()); HexLines.resize(HexLines.size() + 1); std::string &HexLine = HexLines.back(); raw_string_ostream HexStream(HexLine); for (size_t i = 0; i < CodeBytes.size(); i += 4) { unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); } DisasmStream.flush(); DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); } } }
bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) { raw_ostream *OutFile = 0; if (OutFileName) { std::string ErrorInfo; OutFile = new raw_fd_ostream(OutFileName, ErrorInfo, raw_fd_ostream::F_Append); if (!ErrorInfo.empty()) { errs() << "Error opening '" << OutFileName << "': " << ErrorInfo << '\n'; exit(1); } OS = OutFile; } else { OS = &errs(); } foundErrors = 0; this->MF = &MF; TM = &MF.getTarget(); TII = TM->getInstrInfo(); TRI = TM->getRegisterInfo(); MRI = &MF.getRegInfo(); LiveVars = NULL; LiveInts = NULL; LiveStks = NULL; Indexes = NULL; if (PASS) { LiveInts = PASS->getAnalysisIfAvailable<LiveIntervals>(); // We don't want to verify LiveVariables if LiveIntervals is available. if (!LiveInts) LiveVars = PASS->getAnalysisIfAvailable<LiveVariables>(); LiveStks = PASS->getAnalysisIfAvailable<LiveStacks>(); Indexes = PASS->getAnalysisIfAvailable<SlotIndexes>(); } visitMachineFunctionBefore(); for (MachineFunction::const_iterator MFI = MF.begin(), MFE = MF.end(); MFI!=MFE; ++MFI) { visitMachineBasicBlockBefore(MFI); for (MachineBasicBlock::const_instr_iterator MBBI = MFI->instr_begin(), MBBE = MFI->instr_end(); MBBI != MBBE; ++MBBI) { if (MBBI->getParent() != MFI) { report("Bad instruction parent pointer", MFI); *OS << "Instruction: " << *MBBI; continue; } // Skip BUNDLE instruction for now. FIXME: We should add code to verify // the BUNDLE's specifically. if (MBBI->isBundle()) continue; visitMachineInstrBefore(MBBI); for (unsigned I = 0, E = MBBI->getNumOperands(); I != E; ++I) visitMachineOperand(&MBBI->getOperand(I), I); visitMachineInstrAfter(MBBI); } visitMachineBasicBlockAfter(MFI); } visitMachineFunctionAfter(); if (OutFile) delete OutFile; else if (foundErrors) report_fatal_error("Found "+Twine(foundErrors)+" machine code errors."); // Clean up. regsLive.clear(); regsDefined.clear(); regsDead.clear(); regsKilled.clear(); regsLiveInButUnused.clear(); MBBInfoMap.clear(); return false; // no changes }
void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsTargetStreamer &TS = getTargetStreamer(); TS.forbidModuleDirective(); if (MI->isDebugValue()) { SmallString<128> Str; raw_svector_ostream OS(Str); PrintDebugValueComment(MI, OS); return; } // If we just ended a constant pool, mark it as such. if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); InConstantPool = false; } if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { // CONSTPOOL_ENTRY - This instruction represents a floating //constant pool in the function. The first operand is the ID# // for this instruction, the second is the index into the // MachineConstantPool that this is, the third is the size in // bytes of this constant pool entry. // The required alignment is specified on the basic block holding this MI. // unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); // If this is the first entry of the pool, mark it. if (!InConstantPool) { OutStreamer->EmitDataRegion(MCDR_DataRegion); InConstantPool = true; } OutStreamer->EmitLabel(GetCPISymbol(LabelId)); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; if (MCPE.isMachineConstantPoolEntry()) EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); else EmitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal); return; } MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); do { // Do any auto-generated pseudo lowerings. if (emitPseudoExpansionLowering(*OutStreamer, &*I)) continue; if (I->getOpcode() == Mips::PseudoReturn || I->getOpcode() == Mips::PseudoReturn64 || I->getOpcode() == Mips::PseudoIndirectBranch || I->getOpcode() == Mips::PseudoIndirectBranch64) { emitPseudoIndirectBranch(*OutStreamer, &*I); continue; } // The inMips16Mode() test is not permanent. // Some instructions are marked as pseudo right now which // would make the test fail for the wrong reason but // that will be fixed soon. We need this here because we are // removing another test for this situation downstream in the // callchain. // if (I->isPseudo() && !Subtarget->inMips16Mode() && !isLongBranchPseudo(I->getOpcode())) llvm_unreachable("Pseudo opcode found in EmitInstruction()"); MCInst TmpInst0; MCInstLowering.Lower(&*I, TmpInst0); EmitToStreamer(*OutStreamer, TmpInst0); } while ((++I != E) && I->isInsideBundle()); // Delay slot check }
void AMDGPUAsmPrinter::EmitInstruction(const MachineInstr *MI) { if (emitPseudoExpansionLowering(*OutStreamer, MI)) return; const GCNSubtarget &STI = MF->getSubtarget<GCNSubtarget>(); AMDGPUMCInstLower MCInstLowering(OutContext, STI, *this); StringRef Err; if (!STI.getInstrInfo()->verifyInstruction(*MI, Err)) { LLVMContext &C = MI->getParent()->getParent()->getFunction().getContext(); C.emitError("Illegal instruction detected: " + Err); MI->print(errs()); } if (MI->isBundle()) { const MachineBasicBlock *MBB = MI->getParent(); MachineBasicBlock::const_instr_iterator I = ++MI->getIterator(); while (I != MBB->instr_end() && I->isInsideBundle()) { EmitInstruction(&*I); ++I; } } else { // We don't want SI_MASK_BRANCH/SI_RETURN_TO_EPILOG encoded. They are // placeholder terminator instructions and should only be printed as // comments. if (MI->getOpcode() == AMDGPU::SI_MASK_BRANCH) { if (isVerbose()) { SmallVector<char, 16> BBStr; raw_svector_ostream Str(BBStr); const MachineBasicBlock *MBB = MI->getOperand(0).getMBB(); const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); Expr->print(Str, MAI); OutStreamer->emitRawComment(Twine(" mask branch ") + BBStr); } return; } if (MI->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG) { if (isVerbose()) OutStreamer->emitRawComment(" return to shader part epilog"); return; } if (MI->getOpcode() == AMDGPU::WAVE_BARRIER) { if (isVerbose()) OutStreamer->emitRawComment(" wave barrier"); return; } if (MI->getOpcode() == AMDGPU::SI_MASKED_UNREACHABLE) { if (isVerbose()) OutStreamer->emitRawComment(" divergent unreachable"); return; } MCInst TmpInst; MCInstLowering.lower(MI, TmpInst); EmitToStreamer(*OutStreamer, TmpInst); #ifdef EXPENSIVE_CHECKS // Sanity-check getInstSizeInBytes on explicitly specified CPUs (it cannot // work correctly for the generic CPU). // // The isPseudo check really shouldn't be here, but unfortunately there are // some negative lit tests that depend on being able to continue through // here even when pseudo instructions haven't been lowered. if (!MI->isPseudo() && STI.isCPUStringValid(STI.getCPU())) { SmallVector<MCFixup, 4> Fixups; SmallVector<char, 16> CodeBytes; raw_svector_ostream CodeStream(CodeBytes); std::unique_ptr<MCCodeEmitter> InstEmitter(createSIMCCodeEmitter( *STI.getInstrInfo(), *OutContext.getRegisterInfo(), OutContext)); InstEmitter->encodeInstruction(TmpInst, CodeStream, Fixups, STI); assert(CodeBytes.size() == STI.getInstrInfo()->getInstSizeInBytes(*MI)); } #endif if (STI.dumpCode()) { // Disassemble instruction/operands to text. DisasmLines.resize(DisasmLines.size() + 1); std::string &DisasmLine = DisasmLines.back(); raw_string_ostream DisasmStream(DisasmLine); AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *STI.getInstrInfo(), *STI.getRegisterInfo()); InstPrinter.printInst(&TmpInst, DisasmStream, StringRef(), STI); // Disassemble instruction/operands to hex representation. SmallVector<MCFixup, 4> Fixups; SmallVector<char, 16> CodeBytes; raw_svector_ostream CodeStream(CodeBytes); auto &ObjStreamer = static_cast<MCObjectStreamer&>(*OutStreamer); MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter(); InstEmitter.encodeInstruction(TmpInst, CodeStream, Fixups, MF->getSubtarget<MCSubtargetInfo>()); HexLines.resize(HexLines.size() + 1); std::string &HexLine = HexLines.back(); raw_string_ostream HexStream(HexLine); for (size_t i = 0; i < CodeBytes.size(); i += 4) { unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i]; HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord); } DisasmStream.flush(); DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size()); } } }