1*0b57cec5SDimitry Andric //===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "Disassembler.h" 10*0b57cec5SDimitry Andric #include "llvm-c/Disassembler.h" 11*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 12*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 13*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 14*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 15*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 16*0b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h" 17*0b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCRelocationInfo.h" 18*0b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCSymbolizer.h" 19*0b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 20*0b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h" 21*0b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 22*0b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 23*0b57cec5SDimitry Andric #include "llvm/MC/MCInstrItineraries.h" 24*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 25*0b57cec5SDimitry Andric #include "llvm/MC/MCSchedule.h" 26*0b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 27*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 28*0b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 29*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 30*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 31*0b57cec5SDimitry Andric #include <cassert> 32*0b57cec5SDimitry Andric #include <cstddef> 33*0b57cec5SDimitry Andric #include <cstring> 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric using namespace llvm; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric // LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic 38*0b57cec5SDimitry Andric // disassembly is supported by passing a block of information in the DisInfo 39*0b57cec5SDimitry Andric // parameter and specifying the TagType and callback functions as described in 40*0b57cec5SDimitry Andric // the header llvm-c/Disassembler.h . The pointer to the block and the 41*0b57cec5SDimitry Andric // functions can all be passed as NULL. If successful, this returns a 42*0b57cec5SDimitry Andric // disassembler context. If not, it returns NULL. 43*0b57cec5SDimitry Andric // 44*0b57cec5SDimitry Andric LLVMDisasmContextRef 45*0b57cec5SDimitry Andric LLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU, 46*0b57cec5SDimitry Andric const char *Features, void *DisInfo, int TagType, 47*0b57cec5SDimitry Andric LLVMOpInfoCallback GetOpInfo, 48*0b57cec5SDimitry Andric LLVMSymbolLookupCallback SymbolLookUp) { 49*0b57cec5SDimitry Andric // Get the target. 50*0b57cec5SDimitry Andric std::string Error; 51*0b57cec5SDimitry Andric const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 52*0b57cec5SDimitry Andric if (!TheTarget) 53*0b57cec5SDimitry Andric return nullptr; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric std::unique_ptr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 56*0b57cec5SDimitry Andric if (!MRI) 57*0b57cec5SDimitry Andric return nullptr; 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric // Get the assembler info needed to setup the MCContext. 60*0b57cec5SDimitry Andric std::unique_ptr<const MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); 61*0b57cec5SDimitry Andric if (!MAI) 62*0b57cec5SDimitry Andric return nullptr; 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); 65*0b57cec5SDimitry Andric if (!MII) 66*0b57cec5SDimitry Andric return nullptr; 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric std::unique_ptr<const MCSubtargetInfo> STI( 69*0b57cec5SDimitry Andric TheTarget->createMCSubtargetInfo(TT, CPU, Features)); 70*0b57cec5SDimitry Andric if (!STI) 71*0b57cec5SDimitry Andric return nullptr; 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric // Set up the MCContext for creating symbols and MCExpr's. 74*0b57cec5SDimitry Andric std::unique_ptr<MCContext> Ctx(new MCContext(MAI.get(), MRI.get(), nullptr)); 75*0b57cec5SDimitry Andric if (!Ctx) 76*0b57cec5SDimitry Andric return nullptr; 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric // Set up disassembler. 79*0b57cec5SDimitry Andric std::unique_ptr<MCDisassembler> DisAsm( 80*0b57cec5SDimitry Andric TheTarget->createMCDisassembler(*STI, *Ctx)); 81*0b57cec5SDimitry Andric if (!DisAsm) 82*0b57cec5SDimitry Andric return nullptr; 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric std::unique_ptr<MCRelocationInfo> RelInfo( 85*0b57cec5SDimitry Andric TheTarget->createMCRelocationInfo(TT, *Ctx)); 86*0b57cec5SDimitry Andric if (!RelInfo) 87*0b57cec5SDimitry Andric return nullptr; 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer( 90*0b57cec5SDimitry Andric TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx.get(), std::move(RelInfo))); 91*0b57cec5SDimitry Andric DisAsm->setSymbolizer(std::move(Symbolizer)); 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric // Set up the instruction printer. 94*0b57cec5SDimitry Andric int AsmPrinterVariant = MAI->getAssemblerDialect(); 95*0b57cec5SDimitry Andric std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 96*0b57cec5SDimitry Andric Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI)); 97*0b57cec5SDimitry Andric if (!IP) 98*0b57cec5SDimitry Andric return nullptr; 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric LLVMDisasmContext *DC = new LLVMDisasmContext( 101*0b57cec5SDimitry Andric TT, DisInfo, TagType, GetOpInfo, SymbolLookUp, TheTarget, std::move(MAI), 102*0b57cec5SDimitry Andric std::move(MRI), std::move(STI), std::move(MII), std::move(Ctx), 103*0b57cec5SDimitry Andric std::move(DisAsm), std::move(IP)); 104*0b57cec5SDimitry Andric if (!DC) 105*0b57cec5SDimitry Andric return nullptr; 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric DC->setCPU(CPU); 108*0b57cec5SDimitry Andric return DC; 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric LLVMDisasmContextRef 112*0b57cec5SDimitry Andric LLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType, 113*0b57cec5SDimitry Andric LLVMOpInfoCallback GetOpInfo, 114*0b57cec5SDimitry Andric LLVMSymbolLookupCallback SymbolLookUp) { 115*0b57cec5SDimitry Andric return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo, 116*0b57cec5SDimitry Andric SymbolLookUp); 117*0b57cec5SDimitry Andric } 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric LLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo, 120*0b57cec5SDimitry Andric int TagType, LLVMOpInfoCallback GetOpInfo, 121*0b57cec5SDimitry Andric LLVMSymbolLookupCallback SymbolLookUp) { 122*0b57cec5SDimitry Andric return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo, 123*0b57cec5SDimitry Andric SymbolLookUp); 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric // 127*0b57cec5SDimitry Andric // LLVMDisasmDispose() disposes of the disassembler specified by the context. 128*0b57cec5SDimitry Andric // 129*0b57cec5SDimitry Andric void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ 130*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 131*0b57cec5SDimitry Andric delete DC; 132*0b57cec5SDimitry Andric } 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric /// Emits the comments that are stored in \p DC comment stream. 135*0b57cec5SDimitry Andric /// Each comment in the comment stream must end with a newline. 136*0b57cec5SDimitry Andric static void emitComments(LLVMDisasmContext *DC, 137*0b57cec5SDimitry Andric formatted_raw_ostream &FormattedOS) { 138*0b57cec5SDimitry Andric // Flush the stream before taking its content. 139*0b57cec5SDimitry Andric StringRef Comments = DC->CommentsToEmit.str(); 140*0b57cec5SDimitry Andric // Get the default information for printing a comment. 141*0b57cec5SDimitry Andric const MCAsmInfo *MAI = DC->getAsmInfo(); 142*0b57cec5SDimitry Andric StringRef CommentBegin = MAI->getCommentString(); 143*0b57cec5SDimitry Andric unsigned CommentColumn = MAI->getCommentColumn(); 144*0b57cec5SDimitry Andric bool IsFirst = true; 145*0b57cec5SDimitry Andric while (!Comments.empty()) { 146*0b57cec5SDimitry Andric if (!IsFirst) 147*0b57cec5SDimitry Andric FormattedOS << '\n'; 148*0b57cec5SDimitry Andric // Emit a line of comments. 149*0b57cec5SDimitry Andric FormattedOS.PadToColumn(CommentColumn); 150*0b57cec5SDimitry Andric size_t Position = Comments.find('\n'); 151*0b57cec5SDimitry Andric FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position); 152*0b57cec5SDimitry Andric // Move after the newline character. 153*0b57cec5SDimitry Andric Comments = Comments.substr(Position+1); 154*0b57cec5SDimitry Andric IsFirst = false; 155*0b57cec5SDimitry Andric } 156*0b57cec5SDimitry Andric FormattedOS.flush(); 157*0b57cec5SDimitry Andric 158*0b57cec5SDimitry Andric // Tell the comment stream that the vector changed underneath it. 159*0b57cec5SDimitry Andric DC->CommentsToEmit.clear(); 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric /// Gets latency information for \p Inst from the itinerary 163*0b57cec5SDimitry Andric /// scheduling model, based on \p DC information. 164*0b57cec5SDimitry Andric /// \return The maximum expected latency over all the operands or -1 165*0b57cec5SDimitry Andric /// if no information is available. 166*0b57cec5SDimitry Andric static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) { 167*0b57cec5SDimitry Andric const int NoInformationAvailable = -1; 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric // Check if we have a CPU to get the itinerary information. 170*0b57cec5SDimitry Andric if (DC->getCPU().empty()) 171*0b57cec5SDimitry Andric return NoInformationAvailable; 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric // Get itinerary information. 174*0b57cec5SDimitry Andric const MCSubtargetInfo *STI = DC->getSubtargetInfo(); 175*0b57cec5SDimitry Andric InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU()); 176*0b57cec5SDimitry Andric // Get the scheduling class of the requested instruction. 177*0b57cec5SDimitry Andric const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); 178*0b57cec5SDimitry Andric unsigned SCClass = Desc.getSchedClass(); 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric int Latency = 0; 181*0b57cec5SDimitry Andric for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd; 182*0b57cec5SDimitry Andric ++OpIdx) 183*0b57cec5SDimitry Andric Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx)); 184*0b57cec5SDimitry Andric 185*0b57cec5SDimitry Andric return Latency; 186*0b57cec5SDimitry Andric } 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andric /// Gets latency information for \p Inst, based on \p DC information. 189*0b57cec5SDimitry Andric /// \return The maximum expected latency over all the definitions or -1 190*0b57cec5SDimitry Andric /// if no information is available. 191*0b57cec5SDimitry Andric static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { 192*0b57cec5SDimitry Andric // Try to compute scheduling information. 193*0b57cec5SDimitry Andric const MCSubtargetInfo *STI = DC->getSubtargetInfo(); 194*0b57cec5SDimitry Andric const MCSchedModel SCModel = STI->getSchedModel(); 195*0b57cec5SDimitry Andric const int NoInformationAvailable = -1; 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric // Check if we have a scheduling model for instructions. 198*0b57cec5SDimitry Andric if (!SCModel.hasInstrSchedModel()) 199*0b57cec5SDimitry Andric // Try to fall back to the itinerary model if the scheduling model doesn't 200*0b57cec5SDimitry Andric // have a scheduling table. Note the default does not have a table. 201*0b57cec5SDimitry Andric return getItineraryLatency(DC, Inst); 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric // Get the scheduling class of the requested instruction. 204*0b57cec5SDimitry Andric const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); 205*0b57cec5SDimitry Andric unsigned SCClass = Desc.getSchedClass(); 206*0b57cec5SDimitry Andric const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass); 207*0b57cec5SDimitry Andric // Resolving the variant SchedClass requires an MI to pass to 208*0b57cec5SDimitry Andric // SubTargetInfo::resolveSchedClass. 209*0b57cec5SDimitry Andric if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant()) 210*0b57cec5SDimitry Andric return NoInformationAvailable; 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric // Compute output latency. 213*0b57cec5SDimitry Andric int16_t Latency = 0; 214*0b57cec5SDimitry Andric for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries; 215*0b57cec5SDimitry Andric DefIdx != DefEnd; ++DefIdx) { 216*0b57cec5SDimitry Andric // Lookup the definition's write latency in SubtargetInfo. 217*0b57cec5SDimitry Andric const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc, 218*0b57cec5SDimitry Andric DefIdx); 219*0b57cec5SDimitry Andric Latency = std::max(Latency, WLEntry->Cycles); 220*0b57cec5SDimitry Andric } 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric return Latency; 223*0b57cec5SDimitry Andric } 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric /// Emits latency information in DC->CommentStream for \p Inst, based 226*0b57cec5SDimitry Andric /// on the information available in \p DC. 227*0b57cec5SDimitry Andric static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) { 228*0b57cec5SDimitry Andric int Latency = getLatency(DC, Inst); 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric // Report only interesting latencies. 231*0b57cec5SDimitry Andric if (Latency < 2) 232*0b57cec5SDimitry Andric return; 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric DC->CommentStream << "Latency: " << Latency << '\n'; 235*0b57cec5SDimitry Andric } 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric // 238*0b57cec5SDimitry Andric // LLVMDisasmInstruction() disassembles a single instruction using the 239*0b57cec5SDimitry Andric // disassembler context specified in the parameter DC. The bytes of the 240*0b57cec5SDimitry Andric // instruction are specified in the parameter Bytes, and contains at least 241*0b57cec5SDimitry Andric // BytesSize number of bytes. The instruction is at the address specified by 242*0b57cec5SDimitry Andric // the PC parameter. If a valid instruction can be disassembled its string is 243*0b57cec5SDimitry Andric // returned indirectly in OutString which whos size is specified in the 244*0b57cec5SDimitry Andric // parameter OutStringSize. This function returns the number of bytes in the 245*0b57cec5SDimitry Andric // instruction or zero if there was no valid instruction. If this function 246*0b57cec5SDimitry Andric // returns zero the caller will have to pick how many bytes they want to step 247*0b57cec5SDimitry Andric // over by printing a .byte, .long etc. to continue. 248*0b57cec5SDimitry Andric // 249*0b57cec5SDimitry Andric size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, 250*0b57cec5SDimitry Andric uint64_t BytesSize, uint64_t PC, char *OutString, 251*0b57cec5SDimitry Andric size_t OutStringSize){ 252*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 253*0b57cec5SDimitry Andric // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. 254*0b57cec5SDimitry Andric ArrayRef<uint8_t> Data(Bytes, BytesSize); 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric uint64_t Size; 257*0b57cec5SDimitry Andric MCInst Inst; 258*0b57cec5SDimitry Andric const MCDisassembler *DisAsm = DC->getDisAsm(); 259*0b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 260*0b57cec5SDimitry Andric MCDisassembler::DecodeStatus S; 261*0b57cec5SDimitry Andric SmallVector<char, 64> InsnStr; 262*0b57cec5SDimitry Andric raw_svector_ostream Annotations(InsnStr); 263*0b57cec5SDimitry Andric S = DisAsm->getInstruction(Inst, Size, Data, PC, 264*0b57cec5SDimitry Andric /*REMOVE*/ nulls(), Annotations); 265*0b57cec5SDimitry Andric switch (S) { 266*0b57cec5SDimitry Andric case MCDisassembler::Fail: 267*0b57cec5SDimitry Andric case MCDisassembler::SoftFail: 268*0b57cec5SDimitry Andric // FIXME: Do something different for soft failure modes? 269*0b57cec5SDimitry Andric return 0; 270*0b57cec5SDimitry Andric 271*0b57cec5SDimitry Andric case MCDisassembler::Success: { 272*0b57cec5SDimitry Andric StringRef AnnotationsStr = Annotations.str(); 273*0b57cec5SDimitry Andric 274*0b57cec5SDimitry Andric SmallVector<char, 64> InsnStr; 275*0b57cec5SDimitry Andric raw_svector_ostream OS(InsnStr); 276*0b57cec5SDimitry Andric formatted_raw_ostream FormattedOS(OS); 277*0b57cec5SDimitry Andric IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo()); 278*0b57cec5SDimitry Andric 279*0b57cec5SDimitry Andric if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency) 280*0b57cec5SDimitry Andric emitLatency(DC, Inst); 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric emitComments(DC, FormattedOS); 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric assert(OutStringSize != 0 && "Output buffer cannot be zero size"); 285*0b57cec5SDimitry Andric size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); 286*0b57cec5SDimitry Andric std::memcpy(OutString, InsnStr.data(), OutputSize); 287*0b57cec5SDimitry Andric OutString[OutputSize] = '\0'; // Terminate string. 288*0b57cec5SDimitry Andric 289*0b57cec5SDimitry Andric return Size; 290*0b57cec5SDimitry Andric } 291*0b57cec5SDimitry Andric } 292*0b57cec5SDimitry Andric llvm_unreachable("Invalid DecodeStatus!"); 293*0b57cec5SDimitry Andric } 294*0b57cec5SDimitry Andric 295*0b57cec5SDimitry Andric // 296*0b57cec5SDimitry Andric // LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it 297*0b57cec5SDimitry Andric // can set all the Options and 0 otherwise. 298*0b57cec5SDimitry Andric // 299*0b57cec5SDimitry Andric int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ 300*0b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_UseMarkup){ 301*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 302*0b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 303*0b57cec5SDimitry Andric IP->setUseMarkup(true); 304*0b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_UseMarkup); 305*0b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_UseMarkup; 306*0b57cec5SDimitry Andric } 307*0b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_PrintImmHex){ 308*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 309*0b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 310*0b57cec5SDimitry Andric IP->setPrintImmHex(true); 311*0b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_PrintImmHex); 312*0b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_PrintImmHex; 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_AsmPrinterVariant){ 315*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 316*0b57cec5SDimitry Andric // Try to set up the new instruction printer. 317*0b57cec5SDimitry Andric const MCAsmInfo *MAI = DC->getAsmInfo(); 318*0b57cec5SDimitry Andric const MCInstrInfo *MII = DC->getInstrInfo(); 319*0b57cec5SDimitry Andric const MCRegisterInfo *MRI = DC->getRegisterInfo(); 320*0b57cec5SDimitry Andric int AsmPrinterVariant = MAI->getAssemblerDialect(); 321*0b57cec5SDimitry Andric AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0; 322*0b57cec5SDimitry Andric MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter( 323*0b57cec5SDimitry Andric Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI); 324*0b57cec5SDimitry Andric if (IP) { 325*0b57cec5SDimitry Andric DC->setIP(IP); 326*0b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant); 327*0b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_AsmPrinterVariant; 328*0b57cec5SDimitry Andric } 329*0b57cec5SDimitry Andric } 330*0b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_SetInstrComments) { 331*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 332*0b57cec5SDimitry Andric MCInstPrinter *IP = DC->getIP(); 333*0b57cec5SDimitry Andric IP->setCommentStream(DC->CommentStream); 334*0b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_SetInstrComments); 335*0b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_SetInstrComments; 336*0b57cec5SDimitry Andric } 337*0b57cec5SDimitry Andric if (Options & LLVMDisassembler_Option_PrintLatency) { 338*0b57cec5SDimitry Andric LLVMDisasmContext *DC = static_cast<LLVMDisasmContext *>(DCR); 339*0b57cec5SDimitry Andric DC->addOptions(LLVMDisassembler_Option_PrintLatency); 340*0b57cec5SDimitry Andric Options &= ~LLVMDisassembler_Option_PrintLatency; 341*0b57cec5SDimitry Andric } 342*0b57cec5SDimitry Andric return (Options == 0); 343*0b57cec5SDimitry Andric } 344