LCOV - code coverage report
Current view: top level - lib/MC/MCDisassembler - Disassembler.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 49 106 46.2 %
Date: 2018-10-20 13:21:21 Functions: 5 10 50.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13