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