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