Add -disassemble support for -show-inst and -show-encode capability llvm-mc. Also refactor so all MC paraphernalia are created once for all uses as much as possible.

The test change is to account for the fact that the default disassembler behaviour has changed with regards to specifying the assembly syntax to use.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154809 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Barton 2012-04-16 11:32:10 +00:00
parent 4d2e9d9a1c
commit d0c478d95f
4 changed files with 81 additions and 175 deletions

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 -x86-asm-syntax=intel | FileCheck %s # RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 --output-asm-variant=1 | FileCheck %s
# CHECK: movsb # CHECK: movsb
0xa4 0xa4

View File

@ -17,21 +17,18 @@
#include "../../lib/MC/MCDisassembler/EDInst.h" #include "../../lib/MC/MCDisassembler/EDInst.h"
#include "../../lib/MC/MCDisassembler/EDOperand.h" #include "../../lib/MC/MCDisassembler/EDOperand.h"
#include "../../lib/MC/MCDisassembler/EDToken.h" #include "../../lib/MC/MCDisassembler/EDToken.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MemoryObject.h" #include "llvm/Support/MemoryObject.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
using namespace llvm; using namespace llvm;
typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy; typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
@ -56,8 +53,9 @@ public:
} }
static bool PrintInsts(const MCDisassembler &DisAsm, static bool PrintInsts(const MCDisassembler &DisAsm,
MCInstPrinter &Printer, const ByteArrayTy &Bytes, const ByteArrayTy &Bytes,
SourceMgr &SM, raw_ostream &Out) { SourceMgr &SM, raw_ostream &Out,
MCStreamer &Streamer) {
// Wrap the vector in a MemoryObject. // Wrap the vector in a MemoryObject.
VectorMemoryObject memoryObject(Bytes); VectorMemoryObject memoryObject(Bytes);
@ -87,8 +85,7 @@ static bool PrintInsts(const MCDisassembler &DisAsm,
// Fall through // Fall through
case MCDisassembler::Success: case MCDisassembler::Success:
Printer.printInst(&Inst, Out, ""); Streamer.EmitInstruction(Inst);
Out << "\n";
break; break;
} }
} }
@ -145,56 +142,22 @@ static bool ByteArrayFromString(ByteArrayTy &ByteArray,
int Disassembler::disassemble(const Target &T, int Disassembler::disassemble(const Target &T,
const std::string &Triple, const std::string &Triple,
const std::string &Cpu, MCSubtargetInfo &STI,
const std::string &FeaturesStr, MCStreamer &Streamer,
MemoryBuffer &Buffer, MemoryBuffer &Buffer,
SourceMgr &SM,
raw_ostream &Out) { raw_ostream &Out) {
// Set up disassembler. OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI));
OwningPtr<const MCAsmInfo> AsmInfo(T.createMCAsmInfo(Triple));
if (!AsmInfo) {
errs() << "error: no assembly info for target " << Triple << "\n";
return -1;
}
OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu,
FeaturesStr));
if (!STI) {
errs() << "error: no subtarget info for target " << Triple << "\n";
return -1;
}
OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(*STI));
if (!DisAsm) { if (!DisAsm) {
errs() << "error: no disassembler for target " << Triple << "\n"; errs() << "error: no disassembler for target " << Triple << "\n";
return -1; return -1;
} }
OwningPtr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); // Set up initial section manually here
if (!MRI) { Streamer.InitSections();
errs() << "error: no register info for target " << Triple << "\n";
return -1;
}
OwningPtr<const MCInstrInfo> MII(T.createMCInstrInfo());
if (!MII) {
errs() << "error: no instruction info for target " << Triple << "\n";
return -1;
}
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, *AsmInfo,
*MII, *MRI, *STI));
if (!IP) {
errs() << "error: no instruction printer for target " << Triple << '\n';
return -1;
}
bool ErrorOccurred = false; bool ErrorOccurred = false;
SourceMgr SM;
SM.AddNewSourceBuffer(&Buffer, SMLoc());
// Convert the input to a vector for disassembly. // Convert the input to a vector for disassembly.
ByteArrayTy ByteArray; ByteArrayTy ByteArray;
StringRef Str = Buffer.getBuffer(); StringRef Str = Buffer.getBuffer();
@ -202,7 +165,7 @@ int Disassembler::disassemble(const Target &T,
ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
if (!ByteArray.empty()) if (!ByteArray.empty())
ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out); ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer);
return ErrorOccurred; return ErrorOccurred;
} }
@ -236,12 +199,10 @@ static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) {
int Disassembler::disassembleEnhanced(const std::string &TS, int Disassembler::disassembleEnhanced(const std::string &TS,
MemoryBuffer &Buffer, MemoryBuffer &Buffer,
SourceMgr &SM,
raw_ostream &Out) { raw_ostream &Out) {
ByteArrayTy ByteArray; ByteArrayTy ByteArray;
StringRef Str = Buffer.getBuffer(); StringRef Str = Buffer.getBuffer();
SourceMgr SM;
SM.AddNewSourceBuffer(&Buffer, SMLoc());
if (ByteArrayFromString(ByteArray, Str, SM)) { if (ByteArrayFromString(ByteArray, Str, SM)) {
return -1; return -1;

View File

@ -22,18 +22,23 @@ namespace llvm {
class MemoryBuffer; class MemoryBuffer;
class Target; class Target;
class raw_ostream; class raw_ostream;
class SourceMgr;
class MCSubtargetInfo;
class MCStreamer;
class Disassembler { class Disassembler {
public: public:
static int disassemble(const Target &target, static int disassemble(const Target &T,
const std::string &tripleString, const std::string &Triple,
const std::string &Cpu, MCSubtargetInfo &STI,
const std::string &FeaturesStr, MCStreamer &Streamer,
MemoryBuffer &buffer, MemoryBuffer &Buffer,
SourceMgr &SM,
raw_ostream &Out); raw_ostream &Out);
static int disassembleEnhanced(const std::string &tripleString, static int disassembleEnhanced(const std::string &tripleString,
MemoryBuffer &buffer, MemoryBuffer &buffer,
SourceMgr &SM,
raw_ostream &Out); raw_ostream &Out);
}; };

View File

@ -243,37 +243,11 @@ static void setDwarfDebugFlags(int argc, char **argv) {
} }
} }
static int AsLexInput(const char *ProgName) { static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) {
OwningPtr<MemoryBuffer> BufferPtr;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) {
errs() << ProgName << ": " << ec.message() << '\n';
return 1;
}
MemoryBuffer *Buffer = BufferPtr.take();
SourceMgr SrcMgr; AsmLexer Lexer(MAI);
// Tell SrcMgr about this buffer, which is what TGParser will pick up.
SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
// Record the location of the include directories so that the lexer can find
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
const Target *TheTarget = GetTarget(ProgName);
if (!TheTarget)
return 1;
llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName));
assert(MAI && "Unable to create target asm info!");
AsmLexer Lexer(*MAI);
Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0));
OwningPtr<tool_output_file> Out(GetOutputStream());
if (!Out)
return 1;
bool Error = false; bool Error = false;
while (Lexer.Lex().isNot(AsmToken::Eof)) { while (Lexer.Lex().isNot(AsmToken::Eof)) {
AsmToken Tok = Lexer.getTok(); AsmToken Tok = Lexer.getTok();
@ -347,13 +321,49 @@ static int AsLexInput(const char *ProgName) {
Out->os() << "\")\n"; Out->os() << "\")\n";
} }
// Keep output if no errors.
if (Error == 0) Out->keep();
return Error; return Error;
} }
static int AssembleInput(const char *ProgName) { static int AssembleInput(const char *ProgName, const Target *TheTarget,
SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
MCAsmInfo &MAI, MCSubtargetInfo &STI) {
OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx,
Str, MAI));
OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(STI, *Parser));
if (!TAP) {
errs() << ProgName
<< ": error: this target does not support assembly parsing.\n";
return 1;
}
Parser->setShowParsedOperands(ShowInstOperands);
Parser->setTargetParser(*TAP.get());
int Res = Parser->Run(NoInitialTextSection);
return Res;
}
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllDisassemblers();
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
TripleName = Triple::normalize(TripleName);
setDwarfDebugFlags(argc, argv);
const char *ProgName = argv[0];
const Target *TheTarget = GetTarget(ProgName); const Target *TheTarget = GetTarget(ProgName);
if (!TheTarget) if (!TheTarget)
return 1; return 1;
@ -414,7 +424,6 @@ static int AssembleInput(const char *ProgName) {
OwningPtr<MCSubtargetInfo> OwningPtr<MCSubtargetInfo>
STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
if (FileType == OFT_AssemblyFile) { if (FileType == OFT_AssemblyFile) {
MCInstPrinter *IP = MCInstPrinter *IP =
TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI);
@ -441,93 +450,24 @@ static int AssembleInput(const char *ProgName) {
NoExecStack)); NoExecStack));
} }
OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, int Res = 1;
*Str.get(), *MAI));
OwningPtr<MCTargetAsmParser> TAP(TheTarget->createMCAsmParser(*STI, *Parser));
if (!TAP) {
errs() << ProgName
<< ": error: this target does not support assembly parsing.\n";
return 1;
}
Parser->setShowParsedOperands(ShowInstOperands);
Parser->setTargetParser(*TAP.get());
int Res = Parser->Run(NoInitialTextSection);
// Keep output if no errors.
if (Res == 0) Out->keep();
return Res;
}
static int DisassembleInput(const char *ProgName, bool Enhanced) {
const Target *TheTarget = GetTarget(ProgName);
if (!TheTarget)
return 0;
OwningPtr<MemoryBuffer> Buffer;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, Buffer)) {
errs() << ProgName << ": " << ec.message() << '\n';
return 1;
}
OwningPtr<tool_output_file> Out(GetOutputStream());
if (!Out)
return 1;
int Res;
if (Enhanced) {
Res =
Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os());
} else {
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
if (MAttrs.size()) {
SubtargetFeatures Features;
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
FeaturesStr = Features.getString();
}
Res = Disassembler::disassemble(*TheTarget, TripleName, MCPU, FeaturesStr,
*Buffer.take(), Out->os());
}
// Keep output if no errors.
if (Res == 0) Out->keep();
return Res;
}
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllDisassemblers();
// Register the target printer for --version.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
TripleName = Triple::normalize(TripleName);
setDwarfDebugFlags(argc, argv);
switch (Action) { switch (Action) {
case AC_AsLex: case AC_AsLex:
return AsLexInput(argv[0]); Res = AsLexInput(SrcMgr, *MAI, Out.get());
break;
case AC_Assemble: case AC_Assemble:
return AssembleInput(argv[0]); Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI);
break;
case AC_Disassemble: case AC_Disassemble:
return DisassembleInput(argv[0], false); Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str,
*Buffer, SrcMgr, Out->os());
break;
case AC_EDisassemble: case AC_EDisassemble:
return DisassembleInput(argv[0], true); Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, SrcMgr, Out->os());
break;
} }
// Keep output if no errors.
if (Res == 0) Out->keep();
return Res;
} }