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