X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCDisassembler%2FDisassembler.cpp;h=ecc7aff382f35ea00ffb1e6d199ee76d5be31b61;hb=edd08f74289c6ba3b3f8e730e4ab825ef9bd6492;hp=ced57e8ca2de190a1e65417a00f408c9b9891316;hpb=7a2bdde0a0eebcd2125055e0eacaca040f0b766c;p=oota-llvm.git diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index ced57e8ca2d..ecc7aff382f 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -1,4 +1,4 @@ -//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface -*- C -*-===// +//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===// // // The LLVM Compiler Infrastructure // @@ -6,95 +6,111 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// + #include "Disassembler.h" -#include #include "llvm-c/Disassembler.h" - -#include #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetAsmInfo.h" // FIXME. -#include "llvm/Target/TargetMachine.h" // FIXME. -#include "llvm/Target/TargetSelect.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" +#include "llvm/Support/TargetRegistry.h" namespace llvm { class Target; } // namespace llvm using namespace llvm; -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// // LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic // disassembly is supported by passing a block of information in the DisInfo -// parameter and specifing the TagType and call back functions as described in +// parameter and specifying the TagType and callback functions as described in // the header llvm-c/Disassembler.h . The pointer to the block and the -// functions can all be passed as NULL. If successful this returns a -// disassembler context if not it returns NULL. +// functions can all be passed as NULL. If successful, this returns a +// disassembler context. If not, it returns NULL. // -LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, - int TagType, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp) { - // Initialize targets and assembly printers/parsers. - llvm::InitializeAllTargetInfos(); - // FIXME: We shouldn't need to initialize the Target(Machine)s. - llvm::InitializeAllTargets(); - llvm::InitializeAllAsmPrinters(); - llvm::InitializeAllAsmParsers(); - llvm::InitializeAllDisassemblers(); - +LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, + void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp){ // Get the target. std::string Error; - const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); - assert(TheTarget && "Unable to create target!"); + const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); + if (!TheTarget) + return 0; + + const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple); + if (!MRI) + return 0; // Get the assembler info needed to setup the MCContext. - const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName); - assert(MAI && "Unable to create target asm info!"); + const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(*MRI, Triple); + if (!MAI) + return 0; + + const MCInstrInfo *MII = TheTarget->createMCInstrInfo(); + if (!MII) + return 0; // Package up features to be passed to target/subtarget std::string FeaturesStr; - // FIXME: We shouldn't need to do this (and link in codegen). - // When we split this out, we should do it in a way that makes - // it straightforward to switch subtargets on the fly. - TargetMachine *TM = TheTarget->createTargetMachine(TripleName, FeaturesStr); - assert(TM && "Unable to create target machine!"); - - // Get the target assembler info needed to setup the context. - const TargetAsmInfo *tai = new TargetAsmInfo(*TM); - assert(tai && "Unable to create target assembler!"); + const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU, + FeaturesStr); + if (!STI) + return 0; // Set up the MCContext for creating symbols and MCExpr's. - MCContext *Ctx = new MCContext(*MAI, tai); - assert(Ctx && "Unable to create MCContext!"); + MCContext *Ctx = new MCContext(MAI, MRI, 0); + if (!Ctx) + return 0; // Set up disassembler. - MCDisassembler *DisAsm = TheTarget->createMCDisassembler(); - assert(DisAsm && "Unable to create disassembler!"); - DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx); + MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI); + if (!DisAsm) + return 0; + OwningPtr RelInfo( + TheTarget->createMCRelocationInfo(Triple, *Ctx)); + if (!RelInfo) + return 0; + + OwningPtr 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(*TM, AsmPrinterVariant, - *MAI); - assert(IP && "Unable to create instruction printer!"); + MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant, + *MAI, *MII, *MRI, *STI); + if (!IP) + return 0; - LLVMDisasmContext *DC = new LLVMDisasmContext(TripleName, DisInfo, TagType, + LLVMDisasmContext *DC = new LLVMDisasmContext(Triple, DisInfo, TagType, GetOpInfo, SymbolLookUp, - TheTarget, MAI, TM, tai, Ctx, - DisAsm, IP); - assert(DC && "Allocation failure!"); + TheTarget, MAI, MRI, + STI, MII, Ctx, DisAsm, IP); + if (!DC) + return 0; + return DC; } +LLVMDisasmContextRef LLVMCreateDisasm(const char *Triple, void *DisInfo, + int TagType, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp) { + return LLVMCreateDisasmCPU(Triple, "", DisInfo, TagType, GetOpInfo, + SymbolLookUp); +} + // // LLVMDisasmDispose() disposes of the disassembler specified by the context. // @@ -108,7 +124,6 @@ namespace { // The memory object created by LLVMDisasmInstruction(). // class DisasmMemoryObject : public MemoryObject { -private: uint8_t *Bytes; uint64_t Size; uint64_t BasePC; @@ -126,7 +141,7 @@ public: return 0; } }; -} // namespace +} // end anonymous namespace // // LLVMDisasmInstruction() disassembles a single instruction using the @@ -151,21 +166,71 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, MCInst Inst; const MCDisassembler *DisAsm = DC->getDisAsm(); MCInstPrinter *IP = DC->getIP(); - if (!DisAsm->getInstruction(Inst, Size, MemoryObject, PC, /*REMOVE*/ nulls())) + MCDisassembler::DecodeStatus S; + S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC, + /*REMOVE*/ nulls(), DC->CommentStream); + switch (S) { + case MCDisassembler::Fail: + case MCDisassembler::SoftFail: + // FIXME: Do something different for soft failure modes? return 0; - std::string InsnStr; - raw_string_ostream OS(InsnStr); - IP->printInst(&Inst, OS); - OS.flush(); + case MCDisassembler::Success: { + DC->CommentStream.flush(); + StringRef Comments = DC->CommentsToEmit.str(); - size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); - std::memcpy(OutString, InsnStr.data(), OutputSize); - OutString[OutputSize] = '\0'; // Terminate string. + SmallVector InsnStr; + raw_svector_ostream OS(InsnStr); + IP->printInst(&Inst, OS, Comments); + OS.flush(); - return Size; + // Tell the comment stream that the vector changed underneath it. + DC->CommentsToEmit.clear(); + DC->CommentStream.resync(); + + assert(OutStringSize != 0 && "Output buffer cannot be zero size"); + size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); + std::memcpy(OutString, InsnStr.data(), OutputSize); + OutString[OutputSize] = '\0'; // Terminate string. + + return Size; + } + } + llvm_unreachable("Invalid DecodeStatus!"); } -#ifdef __cplusplus +// +// LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it +// can set all the Options and 0 otherwise. +// +int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ + if (Options & LLVMDisassembler_Option_UseMarkup){ + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + MCInstPrinter *IP = DC->getIP(); + IP->setUseMarkup(1); + Options &= ~LLVMDisassembler_Option_UseMarkup; + } + if (Options & LLVMDisassembler_Option_PrintImmHex){ + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + MCInstPrinter *IP = DC->getIP(); + IP->setPrintImmHex(1); + Options &= ~LLVMDisassembler_Option_PrintImmHex; + } + if (Options & LLVMDisassembler_Option_AsmPrinterVariant){ + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + // Try to set up the new instruction printer. + const MCAsmInfo *MAI = DC->getAsmInfo(); + const MCInstrInfo *MII = DC->getInstrInfo(); + const MCRegisterInfo *MRI = DC->getRegisterInfo(); + const MCSubtargetInfo *STI = DC->getSubtargetInfo(); + int AsmPrinterVariant = MAI->getAssemblerDialect(); + AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0; + MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter( + AsmPrinterVariant, *MAI, *MII, *MRI, *STI); + if (IP) { + DC->setIP(IP); + Options &= ~LLVMDisassembler_Option_AsmPrinterVariant; + } + } + return (Options == 0); } -#endif // __cplusplus