#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/TargetRegistry.h"
-namespace llvm {
-class Target;
-} // namespace llvm
using namespace llvm;
// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic
// functions can all be passed as NULL. If successful, this returns a
// disassembler context. If not, it returns NULL.
//
-LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
- void *DisInfo, int TagType,
- LLVMOpInfoCallback GetOpInfo,
- LLVMSymbolLookupCallback SymbolLookUp){
+LLVMDisasmContextRef
+LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU,
+ const char *Features, void *DisInfo, int TagType,
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp) {
// Get the target.
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
if (!TheTarget)
- return 0;
+ return nullptr;
const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple);
if (!MRI)
- return 0;
+ return nullptr;
// Get the assembler info needed to setup the MCContext.
const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, Triple);
if (!MAI)
- return 0;
+ return nullptr;
const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
if (!MII)
- return 0;
-
- // Package up features to be passed to target/subtarget
- std::string FeaturesStr;
+ return nullptr;
const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU,
- FeaturesStr);
+ Features);
if (!STI)
- return 0;
+ return nullptr;
// Set up the MCContext for creating symbols and MCExpr's.
- MCContext *Ctx = new MCContext(MAI, MRI, 0);
+ MCContext *Ctx = new MCContext(MAI, MRI, nullptr);
if (!Ctx)
- return 0;
+ return nullptr;
// Set up disassembler.
- MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI);
+ MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, *Ctx);
if (!DisAsm)
- return 0;
+ return nullptr;
- OwningPtr<MCRelocationInfo> RelInfo(
- TheTarget->createMCRelocationInfo(Triple, *Ctx));
+ std::unique_ptr<MCRelocationInfo> RelInfo(
+ TheTarget->createMCRelocationInfo(Triple, *Ctx));
if (!RelInfo)
- return 0;
+ return nullptr;
+
+ std::unique_ptr<MCSymbolizer> Symbolizer(TheTarget->createMCSymbolizer(
+ Triple, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo.release()));
+ DisAsm->setSymbolizer(std::move(Symbolizer));
- OwningPtr<MCSymbolizer> Symbolizer(
- TheTarget->createMCSymbolizer(Triple, GetOpInfo, SymbolLookUp, DisInfo,
- Ctx, RelInfo.take()));
- DisAsm->setSymbolizer(Symbolizer);
- DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo,
- Ctx, RelInfo);
// Set up the instruction printer.
int AsmPrinterVariant = MAI->getAssemblerDialect();
MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant,
*MAI, *MII, *MRI, *STI);
if (!IP)
- return 0;
+ return nullptr;
LLVMDisasmContext *DC = new LLVMDisasmContext(Triple, DisInfo, TagType,
GetOpInfo, SymbolLookUp,
TheTarget, MAI, MRI,
STI, MII, Ctx, DisAsm, IP);
if (!DC)
- return 0;
+ return nullptr;
+ DC->setCPU(CPU);
return DC;
}
+LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
+ void *DisInfo, int TagType,
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp){
+ return LLVMCreateDisasmCPUFeatures(Triple, CPU, "", DisInfo, TagType,
+ GetOpInfo, SymbolLookUp);
+}
+
LLVMDisasmContextRef LLVMCreateDisasm(const char *Triple, void *DisInfo,
int TagType, LLVMOpInfoCallback GetOpInfo,
LLVMSymbolLookupCallback SymbolLookUp) {
- return LLVMCreateDisasmCPU(Triple, "", DisInfo, TagType, GetOpInfo,
- SymbolLookUp);
+ return LLVMCreateDisasmCPUFeatures(Triple, "", "", DisInfo, TagType,
+ GetOpInfo, SymbolLookUp);
}
//
public:
DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) :
Bytes(bytes), Size(size), BasePC(basePC) {}
-
- uint64_t getBase() const { return BasePC; }
- uint64_t getExtent() const { return Size; }
- int readByte(uint64_t Addr, uint8_t *Byte) const {
+ uint64_t getBase() const override { return BasePC; }
+ uint64_t getExtent() const override { return Size; }
+
+ int readByte(uint64_t Addr, uint8_t *Byte) const override {
if (Addr - BasePC >= Size)
return -1;
*Byte = Bytes[Addr - BasePC];
DC->CommentStream.resync();
}
+/// \brief Gets latency information for \p Inst form the itinerary
+/// scheduling model, based on \p DC information.
+/// \return The maximum expected latency over all the operands or -1
+/// if no information are available.
+static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ const int NoInformationAvailable = -1;
+
+ // Check if we have a CPU to get the itinerary information.
+ if (DC->getCPU().empty())
+ return NoInformationAvailable;
+
+ // Get itinerary information.
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+
+ int Latency = 0;
+ for (unsigned OpIdx = 0, OpIdxEnd = Inst.getNumOperands(); OpIdx != OpIdxEnd;
+ ++OpIdx)
+ Latency = std::max(Latency, IID.getOperandCycle(SCClass, OpIdx));
+
+ return Latency;
+}
+
+/// \brief Gets latency information for \p Inst, based on \p DC information.
+/// \return The maximum expected latency over all the definitions or -1
+/// if no information are available.
+static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ // Try to compute scheduling information.
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ const MCSchedModel SCModel = STI->getSchedModel();
+ const int NoInformationAvailable = -1;
+
+ // Check if we have a scheduling model for instructions.
+ if (!SCModel.hasInstrSchedModel())
+ // Try to fall back to the itinerary model if the scheduling model doesn't
+ // have a scheduling table. Note the default does not have a table.
+ return getItineraryLatency(DC, Inst);
+
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+ const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
+ // Resolving the variant SchedClass requires an MI to pass to
+ // SubTargetInfo::resolveSchedClass.
+ if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
+ return NoInformationAvailable;
+
+ // Compute output latency.
+ int Latency = 0;
+ for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
+ DefIdx != DefEnd; ++DefIdx) {
+ // Lookup the definition's write latency in SubtargetInfo.
+ const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
+ DefIdx);
+ Latency = std::max(Latency, WLEntry->Cycles);
+ }
+
+ return Latency;
+}
+
+
+/// \brief Emits latency information in DC->CommentStream for \p Inst, based
+/// on the information available in \p DC.
+static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+ int Latency = getLatency(DC, Inst);
+
+ // Report only interesting latency.
+ if (Latency < 2)
+ return;
+
+ DC->CommentStream << "Latency: " << Latency << '\n';
+}
+
//
// LLVMDisasmInstruction() disassembles a single instruction using the
// disassembler context specified in the parameter DC. The bytes of the
formatted_raw_ostream FormattedOS(OS);
IP->printInst(&Inst, FormattedOS, AnnotationsStr);
+ if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency)
+ emitLatency(DC, Inst);
+
emitComments(DC, FormattedOS);
+ OS.flush();
assert(OutStringSize != 0 && "Output buffer cannot be zero size");
size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
MCInstPrinter *IP = DC->getIP();
IP->setUseMarkup(1);
+ DC->addOptions(LLVMDisassembler_Option_UseMarkup);
Options &= ~LLVMDisassembler_Option_UseMarkup;
}
if (Options & LLVMDisassembler_Option_PrintImmHex){
LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
MCInstPrinter *IP = DC->getIP();
IP->setPrintImmHex(1);
+ DC->addOptions(LLVMDisassembler_Option_PrintImmHex);
Options &= ~LLVMDisassembler_Option_PrintImmHex;
}
if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
AsmPrinterVariant, *MAI, *MII, *MRI, *STI);
if (IP) {
DC->setIP(IP);
+ DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant);
Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
}
}
LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
MCInstPrinter *IP = DC->getIP();
IP->setCommentStream(DC->CommentStream);
+ DC->addOptions(LLVMDisassembler_Option_SetInstrComments);
Options &= ~LLVMDisassembler_Option_SetInstrComments;
}
+ if (Options & LLVMDisassembler_Option_PrintLatency) {
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ DC->addOptions(LLVMDisassembler_Option_PrintLatency);
+ Options &= ~LLVMDisassembler_Option_PrintLatency;
+ }
return (Options == 0);
}