1833a003da082ab0db343e0e640069dfc6813e7d6Nick Lewycky//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
293f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
393f79364351650b58172522ae8346153a3c67a5cKevin Enderby//                     The LLVM Compiler Infrastructure
493f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
593f79364351650b58172522ae8346153a3c67a5cKevin Enderby// This file is distributed under the University of Illinois Open Source
693f79364351650b58172522ae8346153a3c67a5cKevin Enderby// License. See LICENSE.TXT for details.
793f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
893f79364351650b58172522ae8346153a3c67a5cKevin Enderby//===----------------------------------------------------------------------===//
997ff42d51dc9e4ec8c4a6c2439b230bba1877553Chris Lattner
1093f79364351650b58172522ae8346153a3c67a5cKevin Enderby#include "Disassembler.h"
1193f79364351650b58172522ae8346153a3c67a5cKevin Enderby#include "llvm-c/Disassembler.h"
1293f79364351650b58172522ae8346153a3c67a5cKevin Enderby#include "llvm/MC/MCAsmInfo.h"
134c8164813c1be51f6797fda6826bdf3665f2a7d1Evan Cheng#include "llvm/MC/MCContext.h"
14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/MC/MCDisassembler/MCDisassembler.h"
15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
1793f79364351650b58172522ae8346153a3c67a5cKevin Enderby#include "llvm/MC/MCInst.h"
1893f79364351650b58172522ae8346153a3c67a5cKevin Enderby#include "llvm/MC/MCInstPrinter.h"
1955e79804226f1da02ec880c120671ff930e3dbe4Sean Callanan#include "llvm/MC/MCInstrInfo.h"
204c8164813c1be51f6797fda6826bdf3665f2a7d1Evan Cheng#include "llvm/MC/MCRegisterInfo.h"
2155e79804226f1da02ec880c120671ff930e3dbe4Sean Callanan#include "llvm/MC/MCSubtargetInfo.h"
22d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/ErrorHandling.h"
2376502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet#include "llvm/Support/FormattedStream.h"
243e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
2593f79364351650b58172522ae8346153a3c67a5cKevin Enderby
2693f79364351650b58172522ae8346153a3c67a5cKevin Enderbyusing namespace llvm;
2793f79364351650b58172522ae8346153a3c67a5cKevin Enderby
2893f79364351650b58172522ae8346153a3c67a5cKevin Enderby// LLVMCreateDisasm() creates a disassembler for the TripleName.  Symbolic
2993f79364351650b58172522ae8346153a3c67a5cKevin Enderby// disassembly is supported by passing a block of information in the DisInfo
3097ff42d51dc9e4ec8c4a6c2439b230bba1877553Chris Lattner// parameter and specifying the TagType and callback functions as described in
3193f79364351650b58172522ae8346153a3c67a5cKevin Enderby// the header llvm-c/Disassembler.h .  The pointer to the block and the
3297ff42d51dc9e4ec8c4a6c2439b230bba1877553Chris Lattner// functions can all be passed as NULL.  If successful, this returns a
3397ff42d51dc9e4ec8c4a6c2439b230bba1877553Chris Lattner// disassembler context.  If not, it returns NULL.
3493f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
3537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesLLVMDisasmContextRef
360c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga NainarLLVMCreateDisasmCPUFeatures(const char *TT, const char *CPU,
3737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                            const char *Features, void *DisInfo, int TagType,
3837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                            LLVMOpInfoCallback GetOpInfo,
3937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                            LLVMSymbolLookupCallback SymbolLookUp) {
4093f79364351650b58172522ae8346153a3c67a5cKevin Enderby  // Get the target.
4193f79364351650b58172522ae8346153a3c67a5cKevin Enderby  std::string Error;
420c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
43b737702efd96d2902c7063152747e8f193aa1fbcKevin Enderby  if (!TheTarget)
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
4593f79364351650b58172522ae8346153a3c67a5cKevin Enderby
460c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(TT);
474a971705bc6030dc2e4338b3cd5cffa2e0f88b7bRafael Espindola  if (!MRI)
48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
494a971705bc6030dc2e4338b3cd5cffa2e0f88b7bRafael Espindola
5093f79364351650b58172522ae8346153a3c67a5cKevin Enderby  // Get the assembler info needed to setup the MCContext.
510c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, TT);
522ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!MAI)
53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
5493f79364351650b58172522ae8346153a3c67a5cKevin Enderby
5517463b3ef1a3d39b10619254f12e806c8c43f9e7Craig Topper  const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
562ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!MII)
57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
5817463b3ef1a3d39b10619254f12e806c8c43f9e7Craig Topper
590c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  const MCSubtargetInfo *STI =
600c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      TheTarget->createMCSubtargetInfo(TT, CPU, Features);
612ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!STI)
62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
63b950585cc5a0d665e9accfe5ce490cd269756f2eJames Molloy
6493f79364351650b58172522ae8346153a3c67a5cKevin Enderby  // Set up the MCContext for creating symbols and MCExpr's.
65dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
662ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!Ctx)
67dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
6893f79364351650b58172522ae8346153a3c67a5cKevin Enderby
6993f79364351650b58172522ae8346153a3c67a5cKevin Enderby  // Set up disassembler.
70dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx);
712ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!DisAsm)
72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
732c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<MCRelocationInfo> RelInfo(
750c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      TheTarget->createMCRelocationInfo(TT, *Ctx));
762c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha  if (!RelInfo)
77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
782c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
800c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo)));
8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  DisAsm->setSymbolizer(std::move(Symbolizer));
82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
8393f79364351650b58172522ae8346153a3c67a5cKevin Enderby  // Set up the instruction printer.
8493f79364351650b58172522ae8346153a3c67a5cKevin Enderby  int AsmPrinterVariant = MAI->getAssemblerDialect();
850c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  MCInstPrinter *IP = TheTarget->createMCInstPrinter(
860c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      Triple(TT), AsmPrinterVariant, *MAI, *MII, *MRI);
872ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!IP)
88dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
8993f79364351650b58172522ae8346153a3c67a5cKevin Enderby
900c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  LLVMDisasmContext *DC =
910c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      new LLVMDisasmContext(TT, DisInfo, TagType, GetOpInfo, SymbolLookUp,
920c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                            TheTarget, MAI, MRI, STI, MII, Ctx, DisAsm, IP);
932ee69f1be6473bef40862f4c55e0b33d141c6380Kevin Enderby  if (!DC)
94dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
958f29e6969eb99410b9914bcb5ee2d9a125f07f88Owen Anderson
964b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  DC->setCPU(CPU);
9793f79364351650b58172522ae8346153a3c67a5cKevin Enderby  return DC;
9893f79364351650b58172522ae8346153a3c67a5cKevin Enderby}
9993f79364351650b58172522ae8346153a3c67a5cKevin Enderby
1000c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga NainarLLVMDisasmContextRef
1010c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga NainarLLVMCreateDisasmCPU(const char *TT, const char *CPU, void *DisInfo, int TagType,
1020c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                    LLVMOpInfoCallback GetOpInfo,
1030c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                    LLVMSymbolLookupCallback SymbolLookUp) {
1040c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  return LLVMCreateDisasmCPUFeatures(TT, CPU, "", DisInfo, TagType, GetOpInfo,
1050c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                     SymbolLookUp);
10637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
10737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
1080c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga NainarLLVMDisasmContextRef LLVMCreateDisasm(const char *TT, void *DisInfo,
10968a590df13f47180abd3022aa75f237ae993770fJim Grosbach                                      int TagType, LLVMOpInfoCallback GetOpInfo,
11068a590df13f47180abd3022aa75f237ae993770fJim Grosbach                                      LLVMSymbolLookupCallback SymbolLookUp) {
1110c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar  return LLVMCreateDisasmCPUFeatures(TT, "", "", DisInfo, TagType, GetOpInfo,
1120c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar                                     SymbolLookUp);
11368a590df13f47180abd3022aa75f237ae993770fJim Grosbach}
11468a590df13f47180abd3022aa75f237ae993770fJim Grosbach
11593f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
11693f79364351650b58172522ae8346153a3c67a5cKevin Enderby// LLVMDisasmDispose() disposes of the disassembler specified by the context.
11793f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
11893f79364351650b58172522ae8346153a3c67a5cKevin Enderbyvoid LLVMDisasmDispose(LLVMDisasmContextRef DCR){
11993f79364351650b58172522ae8346153a3c67a5cKevin Enderby  LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
12093f79364351650b58172522ae8346153a3c67a5cKevin Enderby  delete DC;
12193f79364351650b58172522ae8346153a3c67a5cKevin Enderby}
12293f79364351650b58172522ae8346153a3c67a5cKevin Enderby
12376502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet/// \brief Emits the comments that are stored in \p DC comment stream.
12476502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet/// Each comment in the comment stream must end with a newline.
12576502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombetstatic void emitComments(LLVMDisasmContext *DC,
12676502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet                         formatted_raw_ostream &FormattedOS) {
12776502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  // Flush the stream before taking its content.
12876502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  StringRef Comments = DC->CommentsToEmit.str();
12976502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  // Get the default information for printing a comment.
13076502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  const MCAsmInfo *MAI = DC->getAsmInfo();
13176502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  const char *CommentBegin = MAI->getCommentString();
13276502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  unsigned CommentColumn = MAI->getCommentColumn();
13376502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  bool IsFirst = true;
13476502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  while (!Comments.empty()) {
13576502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    if (!IsFirst)
13676502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet      FormattedOS << '\n';
13776502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    // Emit a line of comments.
13876502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    FormattedOS.PadToColumn(CommentColumn);
13976502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    size_t Position = Comments.find('\n');
14076502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
14176502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    // Move after the newline character.
14276502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    Comments = Comments.substr(Position+1);
14376502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    IsFirst = false;
14476502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  }
14576502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  FormattedOS.flush();
14676502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet
14776502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  // Tell the comment stream that the vector changed underneath it.
14876502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  DC->CommentsToEmit.clear();
14976502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet}
15076502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet
151ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// \brief Gets latency information for \p Inst from the itinerary
1524b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet/// scheduling model, based on \p DC information.
1534b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet/// \return The maximum expected latency over all the operands or -1
154ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// if no information is available.
1554b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombetstatic int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
1564b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  const int NoInformationAvailable = -1;
1574b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet
1584b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  // Check if we have a CPU to get the itinerary information.
1594b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  if (DC->getCPU().empty())
1604b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet    return NoInformationAvailable;
1614b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet
1624b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  // Get itinerary information.
1634b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
1644b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
1654b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  // Get the scheduling class of the requested instruction.
1664b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
1674b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  unsigned SCClass = Desc.getSchedClass();
1684b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet
1694b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  int Latency = 0;
1704b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
1714b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet       ++OpIdx)
1724b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet    Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));
1734b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet
1744b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet  return Latency;
1754b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet}
1764b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet
177797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet/// \brief Gets latency information for \p Inst, based on \p DC information.
178797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet/// \return The maximum expected latency over all the definitions or -1
179ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/// if no information is available.
180797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombetstatic int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
181797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  // Try to compute scheduling information.
182797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  const MCSubtargetInfo *STI = DC->getSubtargetInfo();
18337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const MCSchedModel SCModel = STI->getSchedModel();
184797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  const int NoInformationAvailable = -1;
185797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
186797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  // Check if we have a scheduling model for instructions.
18737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (!SCModel.hasInstrSchedModel())
18837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // Try to fall back to the itinerary model if the scheduling model doesn't
18937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // have a scheduling table.  Note the default does not have a table.
1904b3685de23b4a1b3199a06e4bb2ccd1e316396c3Quentin Colombet    return getItineraryLatency(DC, Inst);
191797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
192797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  // Get the scheduling class of the requested instruction.
193797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
194797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  unsigned SCClass = Desc.getSchedClass();
19537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
1964897e263906aa3c88e0a135f18ea9bd2af2676e5Quentin Colombet  // Resolving the variant SchedClass requires an MI to pass to
1974897e263906aa3c88e0a135f18ea9bd2af2676e5Quentin Colombet  // SubTargetInfo::resolveSchedClass.
1984897e263906aa3c88e0a135f18ea9bd2af2676e5Quentin Colombet  if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
199797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    return NoInformationAvailable;
200797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
201797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  // Compute output latency.
202797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  int Latency = 0;
203797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
204797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet       DefIdx != DefEnd; ++DefIdx) {
205797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    // Lookup the definition's write latency in SubtargetInfo.
206797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
207797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet                                                                   DefIdx);
208797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    Latency = std::max(Latency, WLEntry->Cycles);
209797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  }
210797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
211797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  return Latency;
212797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet}
213797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
214797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
215797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet/// \brief Emits latency information in DC->CommentStream for \p Inst, based
216797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet/// on the information available in \p DC.
217797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombetstatic void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
218797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  int Latency = getLatency(DC, Inst);
219797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
220ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  // Report only interesting latencies.
221797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  if (Latency < 2)
222797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    return;
223797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
224797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  DC->CommentStream << "Latency: " << Latency << '\n';
225797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet}
226797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
22793f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
2285731ff636b87abf648ceea51c404d6ae6b27f65fBenjamin Kramer// LLVMDisasmInstruction() disassembles a single instruction using the
22993f79364351650b58172522ae8346153a3c67a5cKevin Enderby// disassembler context specified in the parameter DC.  The bytes of the
2305731ff636b87abf648ceea51c404d6ae6b27f65fBenjamin Kramer// instruction are specified in the parameter Bytes, and contains at least
23193f79364351650b58172522ae8346153a3c67a5cKevin Enderby// BytesSize number of bytes.  The instruction is at the address specified by
23293f79364351650b58172522ae8346153a3c67a5cKevin Enderby// the PC parameter.  If a valid instruction can be disassembled its string is
23393f79364351650b58172522ae8346153a3c67a5cKevin Enderby// returned indirectly in OutString which whos size is specified in the
23493f79364351650b58172522ae8346153a3c67a5cKevin Enderby// parameter OutStringSize.  This function returns the number of bytes in the
23593f79364351650b58172522ae8346153a3c67a5cKevin Enderby// instruction or zero if there was no valid instruction.  If this function
23693f79364351650b58172522ae8346153a3c67a5cKevin Enderby// returns zero the caller will have to pick how many bytes they want to step
23793f79364351650b58172522ae8346153a3c67a5cKevin Enderby// over by printing a .byte, .long etc. to continue.
23893f79364351650b58172522ae8346153a3c67a5cKevin Enderby//
23993f79364351650b58172522ae8346153a3c67a5cKevin Enderbysize_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
24093f79364351650b58172522ae8346153a3c67a5cKevin Enderby                             uint64_t BytesSize, uint64_t PC, char *OutString,
24193f79364351650b58172522ae8346153a3c67a5cKevin Enderby                             size_t OutStringSize){
24293f79364351650b58172522ae8346153a3c67a5cKevin Enderby  LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
24393f79364351650b58172522ae8346153a3c67a5cKevin Enderby  // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
24437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  ArrayRef<uint8_t> Data(Bytes, BytesSize);
24593f79364351650b58172522ae8346153a3c67a5cKevin Enderby
24693f79364351650b58172522ae8346153a3c67a5cKevin Enderby  uint64_t Size;
24793f79364351650b58172522ae8346153a3c67a5cKevin Enderby  MCInst Inst;
24893f79364351650b58172522ae8346153a3c67a5cKevin Enderby  const MCDisassembler *DisAsm = DC->getDisAsm();
24993f79364351650b58172522ae8346153a3c67a5cKevin Enderby  MCInstPrinter *IP = DC->getIP();
250ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  MCDisassembler::DecodeStatus S;
25176502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  SmallVector<char, 64> InsnStr;
25276502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  raw_svector_ostream Annotations(InsnStr);
25337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  S = DisAsm->getInstruction(Inst, Size, Data, PC,
25476502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet                             /*REMOVE*/ nulls(), Annotations);
255ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  switch (S) {
256ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  case MCDisassembler::Fail:
257ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  case MCDisassembler::SoftFail:
258c047dcade506a5acaccb1548cb83a3f85f52d71dJames Molloy    // FIXME: Do something different for soft failure modes?
25993f79364351650b58172522ae8346153a3c67a5cKevin Enderby    return 0;
260833a003da082ab0db343e0e640069dfc6813e7d6Nick Lewycky
261ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  case MCDisassembler::Success: {
26276502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    StringRef AnnotationsStr = Annotations.str();
2638f29e6969eb99410b9914bcb5ee2d9a125f07f88Owen Anderson
26498c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson    SmallVector<char, 64> InsnStr;
26598c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson    raw_svector_ostream OS(InsnStr);
26676502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    formatted_raw_ostream FormattedOS(OS);
2670c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar    IP->printInst(&Inst, FormattedOS, AnnotationsStr, *DC->getSubtargetInfo());
2688f29e6969eb99410b9914bcb5ee2d9a125f07f88Owen Anderson
269797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
270797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet      emitLatency(DC, Inst);
271797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet
27276502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    emitComments(DC, FormattedOS);
2738f29e6969eb99410b9914bcb5ee2d9a125f07f88Owen Anderson
274ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy    assert(OutStringSize != 0 && "Output buffer cannot be zero size");
275ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy    size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
276ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy    std::memcpy(OutString, InsnStr.data(), OutputSize);
277ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy    OutString[OutputSize] = '\0'; // Terminate string.
278833a003da082ab0db343e0e640069dfc6813e7d6Nick Lewycky
279ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy    return Size;
280ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  }
281ee06443945b4c9f471c9b80c4325075dbc27746eJames Molloy  }
2824d6ccb5f68cd7c6418a209f1fa4dbade569e4493David Blaikie  llvm_unreachable("Invalid DecodeStatus!");
28393f79364351650b58172522ae8346153a3c67a5cKevin Enderby}
2843ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby
2853ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby//
2863ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby// LLVMSetDisasmOptions() sets the disassembler's options.  It returns 1 if it
2873ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby// can set all the Options and 0 otherwise.
2883ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby//
2893ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderbyint LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
2903ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby  if (Options & LLVMDisassembler_Option_UseMarkup){
2913ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
2923ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby      MCInstPrinter *IP = DC->getIP();
2933ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby      IP->setUseMarkup(1);
294797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet      DC->addOptions(LLVMDisassembler_Option_UseMarkup);
2953ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby      Options &= ~LLVMDisassembler_Option_UseMarkup;
2963ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby  }
29714ccc9007a932a23201251ced4be4c898a62d6a5Kevin Enderby  if (Options & LLVMDisassembler_Option_PrintImmHex){
29814ccc9007a932a23201251ced4be4c898a62d6a5Kevin Enderby      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
29914ccc9007a932a23201251ced4be4c898a62d6a5Kevin Enderby      MCInstPrinter *IP = DC->getIP();
30014ccc9007a932a23201251ced4be4c898a62d6a5Kevin Enderby      IP->setPrintImmHex(1);
301797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet      DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
30214ccc9007a932a23201251ced4be4c898a62d6a5Kevin Enderby      Options &= ~LLVMDisassembler_Option_PrintImmHex;
30314ccc9007a932a23201251ced4be4c898a62d6a5Kevin Enderby  }
3045469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby  if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
3055469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
3065469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      // Try to set up the new instruction printer.
3075469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      const MCAsmInfo *MAI = DC->getAsmInfo();
3085469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      const MCInstrInfo *MII = DC->getInstrInfo();
3095469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      const MCRegisterInfo *MRI = DC->getRegisterInfo();
3105469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      int AsmPrinterVariant = MAI->getAssemblerDialect();
3115469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
3125469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter(
3130c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar          Triple(DC->getTripleName()), AsmPrinterVariant, *MAI, *MII, *MRI);
3145469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      if (IP) {
3155469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby        DC->setIP(IP);
316797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet        DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
3175469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby        Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
3185469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby      }
3195469f605fe86edcfb6d3f0e36f3e3ce0254334ccKevin Enderby  }
32076502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  if (Options & LLVMDisassembler_Option_SetInstrComments) {
32176502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
32276502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    MCInstPrinter *IP = DC->getIP();
32376502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    IP->setCommentStream(DC->CommentStream);
324797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
32576502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet    Options &= ~LLVMDisassembler_Option_SetInstrComments;
32676502a756da8fbc3cf6f2f26bc09cce598a9fc03Quentin Colombet  }
327797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  if (Options & LLVMDisassembler_Option_PrintLatency) {
328797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
329797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    DC->addOptions(LLVMDisassembler_Option_PrintLatency);
330797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet    Options &= ~LLVMDisassembler_Option_PrintLatency;
331797f06e19b6f17217a69dea4d6ce900625432595Quentin Colombet  }
3323ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby  return (Options == 0);
3333ed0316f756e2f1730f46654776fcf77f5ace7aaKevin Enderby}
334