10b57cec5SDimitry Andric //===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "Disassembler.h" 100b57cec5SDimitry Andric #include "llvm-c/Disassembler.h" 110b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 120b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCSymbolizer.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCInstrItineraries.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCSchedule.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 26480093f4SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 280b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 290b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 31*06c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 320b57cec5SDimitry Andric #include <cassert> 330b57cec5SDimitry Andric #include <cstring> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace llvm; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic 380b57cec5SDimitry Andric // disassembly is supported by passing a block of information in the DisInfo 390b57cec5SDimitry Andric // parameter and specifying the TagType and callback functions as described in 400b57cec5SDimitry Andric // the header llvm-c/Disassembler.h . The pointer to the block and the 410b57cec5SDimitry Andric // functions can all be passed as NULL. If successful, this returns a 420b57cec5SDimitry Andric // disassembler context. If not, it returns NULL. 430b57cec5SDimitry Andric // 440b57cec5SDimitry Andric LLVMDisasmContextRef 450b57cec5SDimitry Andric LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU, 460b57cec5SDimitry Andric const char *Features, void *DisInfo, int TagType, 470b57cec5SDimitry Andric LLVMOpInfoCallback GetOpInfo, 480b57cec5SDimitry Andric LLVMSymbolLookupCallback SymbolLookUp) { 490b57cec5SDimitry Andric // Get the target. 500b57cec5SDimitry Andric std::string Error; 510b57cec5SDimitry Andric const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 520b57cec5SDimitry Andric if (!TheTarget) 530b57cec5SDimitry Andric return nullptr; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric std::unique_ptr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 560b57cec5SDimitry Andric if (!MRI) 570b57cec5SDimitry Andric return nullptr; 580b57cec5SDimitry Andric 59480093f4SDimitry Andric MCTargetOptions MCOptions; 600b57cec5SDimitry Andric // Get the assembler info needed to setup the MCContext. 61480093f4SDimitry Andric std::unique_ptr<const MCAsmInfo> MAI( 62480093f4SDimitry Andric TheTarget->createMCAsmInfo(*MRI, TT, MCOptions)); 630b57cec5SDimitry Andric if (!MAI) 640b57cec5SDimitry Andric return nullptr; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); 670b57cec5SDimitry Andric if (!MII) 680b57cec5SDimitry Andric return nullptr; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric std::unique_ptr<const MCSubtargetInfo> STI( 710b57cec5SDimitry Andric TheTarget->createMCSubtargetInfo(TT, CPU, Features)); 720b57cec5SDimitry Andric if (!STI) 730b57cec5SDimitry Andric return nullptr; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Set up the MCContext for creating symbols and MCExpr's. 76fe6060f1SDimitry Andric std::unique_ptr<MCContext> Ctx( 77fe6060f1SDimitry Andric new MCContext(Triple(TT), MAI.get(), MRI.get(), STI.get())); 780b57cec5SDimitry Andric if (!Ctx) 790b57cec5SDimitry Andric return nullptr; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric // Set up disassembler. 820b57cec5SDimitry Andric std::unique_ptr<MCDisassembler> DisAsm( 830b57cec5SDimitry Andric TheTarget->createMCDisassembler(*STI, *Ctx)); 840b57cec5SDimitry Andric if (!DisAsm) 850b57cec5SDimitry Andric return nullptr; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric std::unique_ptr<MCRelocationInfo> RelInfo( 880b57cec5SDimitry Andric TheTarget->createMCRelocationInfo(TT, *Ctx)); 890b57cec5SDimitry Andric if (!RelInfo) 900b57cec5SDimitry Andric return nullptr; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer( 930b57cec5SDimitry Andric TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx.get(), std::move(RelInfo))); 940b57cec5SDimitry Andric DisAsm->setSymbolizer(std::move(Symbolizer)); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // Set up the instruction printer. 970b57cec5SDimitry Andric int AsmPrinterVariant = MAI->getAssemblerDialect(); 980b57cec5SDimitry Andric std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 990b57cec5SDimitry Andric Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI)); 1000b57cec5SDimitry Andric if (!IP) 1010b57cec5SDimitry Andric return nullptr; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric LLVMDisasmContext *DC = new LLVMDisasmContext( 1040b57cec5SDimitry Andric TT, DisInfo, TagType, GetOpInfo, SymbolLookUp, TheTarget, std::move(MAI), 1050b57cec5SDimitry Andric std::move(MRI), std::move(STI), std::move(MII), std::move(Ctx), 1060b57cec5SDimitry Andric std::move(DisAsm), std::move(IP)); 1070b57cec5SDimitry Andric if (!DC) 1080b57cec5SDimitry Andric return nullptr; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric DC->setCPU(CPU); 1110b57cec5SDimitry Andric return DC; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric LLVMDisasmContextRef 1150b57cec5SDimitry Andric LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType, 1160b57cec5SDimitry Andric LLVMOpInfoCallback GetOpInfo, 1170b57cec5SDimitry Andric LLVMSymbolLookupCallback SymbolLookUp) { 1180b57cec5SDimitry Andric return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo, 1190b57cec5SDimitry Andric SymbolLookUp); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo, 1230b57cec5SDimitry Andric int TagType, LLVMOpInfoCallback GetOpInfo, 1240b57cec5SDimitry Andric LLVMSymbolLookupCallback SymbolLookUp) { 1250b57cec5SDimitry Andric return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo, 1260b57cec5SDimitry Andric SymbolLookUp); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // 1300b57cec5SDimitry Andric // LLVMDisasmDispose() disposes of the disassembler specified by the context. 1310b57cec5SDimitry Andric // 1320b57cec5SDimitry Andric void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ 1330b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 1340b57cec5SDimitry Andric delete DC; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// Emits the comments that are stored in \p DC comment stream. 1380b57cec5SDimitry Andric /// Each comment in the comment stream must end with a newline. 1390b57cec5SDimitry Andric static void emitComments(LLVMDisasmContext *DC, 1400b57cec5SDimitry Andric formatted_raw_ostream &FormattedOS) { 1410b57cec5SDimitry Andric // Flush the stream before taking its content. 1420b57cec5SDimitry Andric StringRef Comments = DC->CommentsToEmit.str(); 1430b57cec5SDimitry Andric // Get the default information for printing a comment. 1440b57cec5SDimitry Andric const MCAsmInfo *MAI = DC->getAsmInfo(); 1450b57cec5SDimitry Andric StringRef CommentBegin = MAI->getCommentString(); 1460b57cec5SDimitry Andric unsigned CommentColumn = MAI->getCommentColumn(); 1470b57cec5SDimitry Andric bool IsFirst = true; 1480b57cec5SDimitry Andric while (!Comments.empty()) { 1490b57cec5SDimitry Andric if (!IsFirst) 1500b57cec5SDimitry Andric FormattedOS << '\n'; 1510b57cec5SDimitry Andric // Emit a line of comments. 1520b57cec5SDimitry Andric FormattedOS.PadToColumn(CommentColumn); 1530b57cec5SDimitry Andric size_t Position = Comments.find('\n'); 1540b57cec5SDimitry Andric FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 1550b57cec5SDimitry Andric // Move after the newline character. 1560b57cec5SDimitry Andric Comments = Comments.substr(Position+1); 1570b57cec5SDimitry Andric IsFirst = false; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric FormattedOS.flush(); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric // Tell the comment stream that the vector changed underneath it. 1620b57cec5SDimitry Andric DC->CommentsToEmit.clear(); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric /// Gets latency information for \p Inst from the itinerary 1660b57cec5SDimitry Andric /// scheduling model, based on \p DC information. 1670b57cec5SDimitry Andric /// \return The maximum expected latency over all the operands or -1 1680b57cec5SDimitry Andric /// if no information is available. 1690b57cec5SDimitry Andric static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) { 1700b57cec5SDimitry Andric const int NoInformationAvailable = -1; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Check if we have a CPU to get the itinerary information. 1730b57cec5SDimitry Andric if (DC->getCPU().empty()) 1740b57cec5SDimitry Andric return NoInformationAvailable; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // Get itinerary information. 1770b57cec5SDimitry Andric const MCSubtargetInfo *STI = DC->getSubtargetInfo(); 1780b57cec5SDimitry Andric InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU()); 1790b57cec5SDimitry Andric // Get the scheduling class of the requested instruction. 1800b57cec5SDimitry Andric const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); 1810b57cec5SDimitry Andric unsigned SCClass = Desc.getSchedClass(); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric int Latency = 0; 1840b57cec5SDimitry Andric for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd; 1850b57cec5SDimitry Andric ++OpIdx) 1860b57cec5SDimitry Andric Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx)); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric return Latency; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric /// Gets latency information for \p Inst, based on \p DC information. 1920b57cec5SDimitry Andric /// \return The maximum expected latency over all the definitions or -1 1930b57cec5SDimitry Andric /// if no information is available. 1940b57cec5SDimitry Andric static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { 1950b57cec5SDimitry Andric // Try to compute scheduling information. 1960b57cec5SDimitry Andric const MCSubtargetInfo *STI = DC->getSubtargetInfo(); 1970b57cec5SDimitry Andric const MCSchedModel SCModel = STI->getSchedModel(); 1980b57cec5SDimitry Andric const int NoInformationAvailable = -1; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric // Check if we have a scheduling model for instructions. 2010b57cec5SDimitry Andric if (!SCModel.hasInstrSchedModel()) 2020b57cec5SDimitry Andric // Try to fall back to the itinerary model if the scheduling model doesn't 2030b57cec5SDimitry Andric // have a scheduling table. Note the default does not have a table. 2040b57cec5SDimitry Andric return getItineraryLatency(DC, Inst); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // Get the scheduling class of the requested instruction. 2070b57cec5SDimitry Andric const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); 2080b57cec5SDimitry Andric unsigned SCClass = Desc.getSchedClass(); 2090b57cec5SDimitry Andric const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass); 2100b57cec5SDimitry Andric // Resolving the variant SchedClass requires an MI to pass to 2110b57cec5SDimitry Andric // SubTargetInfo::resolveSchedClass. 2120b57cec5SDimitry Andric if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant()) 2130b57cec5SDimitry Andric return NoInformationAvailable; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric // Compute output latency. 2160b57cec5SDimitry Andric int16_t Latency = 0; 2170b57cec5SDimitry Andric for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries; 2180b57cec5SDimitry Andric DefIdx != DefEnd; ++DefIdx) { 2190b57cec5SDimitry Andric // Lookup the definition's write latency in SubtargetInfo. 2200b57cec5SDimitry Andric const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc, 2210b57cec5SDimitry Andric DefIdx); 2220b57cec5SDimitry Andric Latency = std::max(Latency, WLEntry->Cycles); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric return Latency; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric /// Emits latency information in DC->CommentStream for \p Inst, based 2290b57cec5SDimitry Andric /// on the information available in \p DC. 2300b57cec5SDimitry Andric static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) { 2310b57cec5SDimitry Andric int Latency = getLatency(DC, Inst); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // Report only interesting latencies. 2340b57cec5SDimitry Andric if (Latency < 2) 2350b57cec5SDimitry Andric return; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric DC->CommentStream << "Latency: " << Latency << '\n'; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric // 2410b57cec5SDimitry Andric // LLVMDisasmInstruction() disassembles a single instruction using the 2420b57cec5SDimitry Andric // disassembler context specified in the parameter DC. The bytes of the 2430b57cec5SDimitry Andric // instruction are specified in the parameter Bytes, and contains at least 2440b57cec5SDimitry Andric // BytesSize number of bytes. The instruction is at the address specified by 2450b57cec5SDimitry Andric // the PC parameter. If a valid instruction can be disassembled its string is 2460b57cec5SDimitry Andric // returned indirectly in OutString which whos size is specified in the 2470b57cec5SDimitry Andric // parameter OutStringSize. This function returns the number of bytes in the 2480b57cec5SDimitry Andric // instruction or zero if there was no valid instruction. If this function 2490b57cec5SDimitry Andric // returns zero the caller will have to pick how many bytes they want to step 2500b57cec5SDimitry Andric // over by printing a .byte, .long etc. to continue. 2510b57cec5SDimitry Andric // 2520b57cec5SDimitry Andric size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, 2530b57cec5SDimitry Andric uint64_t BytesSize, uint64_t PC, char *OutString, 2540b57cec5SDimitry Andric size_t OutStringSize){ 2550b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 2560b57cec5SDimitry Andric // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. 2570b57cec5SDimitry Andric ArrayRef<uint8_t> Data(Bytes, BytesSize); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric uint64_t Size; 2600b57cec5SDimitry Andric MCInst Inst; 2610b57cec5SDimitry Andric const MCDisassembler *DisAsm = DC->getDisAsm(); 2620b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 2630b57cec5SDimitry Andric MCDisassembler::DecodeStatus S; 2640b57cec5SDimitry Andric SmallVector<char, 64> InsnStr; 2650b57cec5SDimitry Andric raw_svector_ostream Annotations(InsnStr); 266480093f4SDimitry Andric S = DisAsm->getInstruction(Inst, Size, Data, PC, Annotations); 2670b57cec5SDimitry Andric switch (S) { 2680b57cec5SDimitry Andric case MCDisassembler::Fail: 2690b57cec5SDimitry Andric case MCDisassembler::SoftFail: 2700b57cec5SDimitry Andric // FIXME: Do something different for soft failure modes? 2710b57cec5SDimitry Andric return 0; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric case MCDisassembler::Success: { 2740b57cec5SDimitry Andric StringRef AnnotationsStr = Annotations.str(); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric SmallVector<char, 64> InsnStr; 2770b57cec5SDimitry Andric raw_svector_ostream OS(InsnStr); 2780b57cec5SDimitry Andric formatted_raw_ostream FormattedOS(OS); 279480093f4SDimitry Andric IP->printInst(&Inst, PC, AnnotationsStr, *DC->getSubtargetInfo(), 280480093f4SDimitry Andric FormattedOS); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency) 2830b57cec5SDimitry Andric emitLatency(DC, Inst); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric emitComments(DC, FormattedOS); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric assert(OutStringSize != 0 && "Output buffer cannot be zero size"); 2880b57cec5SDimitry Andric size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); 2890b57cec5SDimitry Andric std::memcpy(OutString, InsnStr.data(), OutputSize); 2900b57cec5SDimitry Andric OutString[OutputSize] = '\0'; // Terminate string. 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric return Size; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric llvm_unreachable("Invalid DecodeStatus!"); 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric // 2990b57cec5SDimitry Andric // LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it 3000b57cec5SDimitry Andric // can set all the Options and 0 otherwise. 3010b57cec5SDimitry Andric // 3020b57cec5SDimitry Andric int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ 3030b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_UseMarkup){ 3040b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 3050b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 3060b57cec5SDimitry Andric IP->setUseMarkup(true); 3070b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_UseMarkup); 3080b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_UseMarkup; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_PrintImmHex){ 3110b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 3120b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 3130b57cec5SDimitry Andric IP->setPrintImmHex(true); 3140b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_PrintImmHex); 3150b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_PrintImmHex; 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_AsmPrinterVariant){ 3180b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 3190b57cec5SDimitry Andric // Try to set up the new instruction printer. 3200b57cec5SDimitry Andric const MCAsmInfo *MAI = DC->getAsmInfo(); 3210b57cec5SDimitry Andric const MCInstrInfo *MII = DC->getInstrInfo(); 3220b57cec5SDimitry Andric const MCRegisterInfo *MRI = DC->getRegisterInfo(); 3230b57cec5SDimitry Andric int AsmPrinterVariant = MAI->getAssemblerDialect(); 3240b57cec5SDimitry Andric AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0; 3250b57cec5SDimitry Andric MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter( 3260b57cec5SDimitry Andric Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI); 3270b57cec5SDimitry Andric if (IP) { 3280b57cec5SDimitry Andric DC->setIP(IP); 3290b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant); 3300b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_AsmPrinterVariant; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_SetInstrComments) { 3340b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 3350b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 3360b57cec5SDimitry Andric IP->setCommentStream(DC->CommentStream); 3370b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_SetInstrComments); 3380b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_SetInstrComments; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_PrintLatency) { 3410b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 3420b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_PrintLatency); 3430b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_PrintLatency; 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric return (Options == 0); 3460b57cec5SDimitry Andric } 347