llvm.org GIT mirror llvm / d0c478d
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 Richard Barton 7 years ago
4 changed file(s) with 84 addition(s) and 178 deletion(s). Raw diff Collapse all Expand all
None # RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 -x86-asm-syntax=intel | FileCheck %s
0 # RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 --output-asm-variant=1 | FileCheck %s
11
22 # CHECK: movsb
33 0xa4
1616 #include "../../lib/MC/MCDisassembler/EDInst.h"
1717 #include "../../lib/MC/MCDisassembler/EDOperand.h"
1818 #include "../../lib/MC/MCDisassembler/EDToken.h"
19 #include "llvm/MC/MCAsmInfo.h"
2019 #include "llvm/MC/MCDisassembler.h"
2120 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstPrinter.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCStreamer.h"
2522 #include "llvm/MC/MCSubtargetInfo.h"
2623 #include "llvm/ADT/OwningPtr.h"
2724 #include "llvm/ADT/Triple.h"
28 #include "llvm/ADT/Twine.h"
2925 #include "llvm/Support/MemoryBuffer.h"
3026 #include "llvm/Support/MemoryObject.h"
3127 #include "llvm/Support/SourceMgr.h"
3228 #include "llvm/Support/TargetRegistry.h"
3329 #include "llvm/Support/raw_ostream.h"
30
3431 using namespace llvm;
3532
3633 typedef std::vector > ByteArrayTy;
5552 }
5653
5754 static bool PrintInsts(const MCDisassembler &DisAsm,
58 MCInstPrinter &Printer, const ByteArrayTy &Bytes,
59 SourceMgr &SM, raw_ostream &Out) {
55 const ByteArrayTy &Bytes,
56 SourceMgr &SM, raw_ostream &Out,
57 MCStreamer &Streamer) {
6058 // Wrap the vector in a MemoryObject.
6159 VectorMemoryObject memoryObject(Bytes);
6260
8684 // Fall through
8785
8886 case MCDisassembler::Success:
89 Printer.printInst(&Inst, Out, "");
90 Out << "\n";
87 Streamer.EmitInstruction(Inst);
9188 break;
9289 }
9390 }
144141
145142 int Disassembler::disassemble(const Target &T,
146143 const std::string &Triple,
147 const std::string &Cpu,
148 const std::string &FeaturesStr,
144 MCSubtargetInfo &STI,
145 MCStreamer &Streamer,
149146 MemoryBuffer &Buffer,
147 SourceMgr &SM,
150148 raw_ostream &Out) {
151 // Set up disassembler.
152 OwningPtr AsmInfo(T.createMCAsmInfo(Triple));
153
154 if (!AsmInfo) {
155 errs() << "error: no assembly info for target " << Triple << "\n";
156 return -1;
157 }
158
159 OwningPtr STI(T.createMCSubtargetInfo(Triple, Cpu,
160 FeaturesStr));
161 if (!STI) {
162 errs() << "error: no subtarget info for target " << Triple << "\n";
163 return -1;
164 }
165
166 OwningPtr DisAsm(T.createMCDisassembler(*STI));
149 OwningPtr DisAsm(T.createMCDisassembler(STI));
167150 if (!DisAsm) {
168151 errs() << "error: no disassembler for target " << Triple << "\n";
169152 return -1;
170153 }
171154
172 OwningPtr MRI(T.createMCRegInfo(Triple));
173 if (!MRI) {
174 errs() << "error: no register info for target " << Triple << "\n";
175 return -1;
176 }
177
178 OwningPtr MII(T.createMCInstrInfo());
179 if (!MII) {
180 errs() << "error: no instruction info for target " << Triple << "\n";
181 return -1;
182 }
183
184 int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
185 OwningPtr IP(T.createMCInstPrinter(AsmPrinterVariant, *AsmInfo,
186 *MII, *MRI, *STI));
187 if (!IP) {
188 errs() << "error: no instruction printer for target " << Triple << '\n';
189 return -1;
190 }
155 // Set up initial section manually here
156 Streamer.InitSections();
191157
192158 bool ErrorOccurred = false;
193
194 SourceMgr SM;
195 SM.AddNewSourceBuffer(&Buffer, SMLoc());
196159
197160 // Convert the input to a vector for disassembly.
198161 ByteArrayTy ByteArray;
201164 ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
202165
203166 if (!ByteArray.empty())
204 ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out);
167 ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer);
205168
206169 return ErrorOccurred;
207170 }
235198
236199 int Disassembler::disassembleEnhanced(const std::string &TS,
237200 MemoryBuffer &Buffer,
201 SourceMgr &SM,
238202 raw_ostream &Out) {
239203 ByteArrayTy ByteArray;
240204 StringRef Str = Buffer.getBuffer();
241 SourceMgr SM;
242
243 SM.AddNewSourceBuffer(&Buffer, SMLoc());
244205
245206 if (ByteArrayFromString(ByteArray, Str, SM)) {
246207 return -1;
2121 class MemoryBuffer;
2222 class Target;
2323 class raw_ostream;
24 class SourceMgr;
25 class MCSubtargetInfo;
26 class MCStreamer;
2427
2528 class Disassembler {
2629 public:
27 static int disassemble(const Target &target,
28 const std::string &tripleString,
29 const std::string &Cpu,
30 const std::string &FeaturesStr,
31 MemoryBuffer &buffer,
30 static int disassemble(const Target &T,
31 const std::string &Triple,
32 MCSubtargetInfo &STI,
33 MCStreamer &Streamer,
34 MemoryBuffer &Buffer,
35 SourceMgr &SM,
3236 raw_ostream &Out);
3337
3438 static int disassembleEnhanced(const std::string &tripleString,
3539 MemoryBuffer &buffer,
40 SourceMgr &SM,
3641 raw_ostream &Out);
3742 };
3843
242242 }
243243 }
244244
245 static int AsLexInput(const char *ProgName) {
246 OwningPtr BufferPtr;
247 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) {
248 errs() << ProgName << ": " << ec.message() << '\n';
249 return 1;
250 }
251 MemoryBuffer *Buffer = BufferPtr.take();
252
253 SourceMgr SrcMgr;
254
255 // Tell SrcMgr about this buffer, which is what TGParser will pick up.
256 SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
257
258 // Record the location of the include directories so that the lexer can find
259 // it later.
260 SrcMgr.setIncludeDirs(IncludeDirs);
261
262 const Target *TheTarget = GetTarget(ProgName);
263 if (!TheTarget)
264 return 1;
265
266 llvm::OwningPtr MAI(TheTarget->createMCAsmInfo(TripleName));
267 assert(MAI && "Unable to create target asm info!");
268
269 AsmLexer Lexer(*MAI);
245 static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) {
246
247 AsmLexer Lexer(MAI);
270248 Lexer.setBuffer(SrcMgr.getMemoryBuffer(0));
271
272 OwningPtr Out(GetOutputStream());
273 if (!Out)
274 return 1;
275249
276250 bool Error = false;
277251 while (Lexer.Lex().isNot(AsmToken::Eof)) {
346320 Out->os() << "\")\n";
347321 }
348322
349 // Keep output if no errors.
350 if (Error == 0) Out->keep();
351
352323 return Error;
353324 }
354325
355 static int AssembleInput(const char *ProgName) {
326 static int AssembleInput(const char *ProgName, const Target *TheTarget,
327 SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
328 MCAsmInfo &MAI, MCSubtargetInfo &STI) {
329 OwningPtr Parser(createMCAsmParser(SrcMgr, Ctx,
330 Str, MAI));
331 OwningPtr TAP(TheTarget->createMCAsmParser(STI, *Parser));
332 if (!TAP) {
333 errs() << ProgName
334 << ": error: this target does not support assembly parsing.\n";
335 return 1;
336 }
337
338 Parser->setShowParsedOperands(ShowInstOperands);
339 Parser->setTargetParser(*TAP.get());
340
341 int Res = Parser->Run(NoInitialTextSection);
342
343 return Res;
344 }
345
346 int main(int argc, char **argv) {
347 // Print a stack trace if we signal out.
348 sys::PrintStackTraceOnErrorSignal();
349 PrettyStackTraceProgram X(argc, argv);
350 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
351
352 // Initialize targets and assembly printers/parsers.
353 llvm::InitializeAllTargetInfos();
354 llvm::InitializeAllTargetMCs();
355 llvm::InitializeAllAsmParsers();
356 llvm::InitializeAllDisassemblers();
357
358 // Register the target printer for --version.
359 cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
360
361 cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
362 TripleName = Triple::normalize(TripleName);
363 setDwarfDebugFlags(argc, argv);
364
365 const char *ProgName = argv[0];
356366 const Target *TheTarget = GetTarget(ProgName);
357367 if (!TheTarget)
358368 return 1;
413423 OwningPtr
414424 STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
415425
416 // FIXME: There is a bit of code duplication with addPassesToEmitFile.
417426 if (FileType == OFT_AssemblyFile) {
418427 MCInstPrinter *IP =
419428 TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI);
440449 NoExecStack));
441450 }
442451
443 OwningPtr Parser(createMCAsmParser(SrcMgr, Ctx,
444 *Str.get(), *MAI));
445 OwningPtr TAP(TheTarget->createMCAsmParser(*STI, *Parser));
446 if (!TAP) {
447 errs() << ProgName
448 << ": error: this target does not support assembly parsing.\n";
449 return 1;
450 }
451
452 Parser->setShowParsedOperands(ShowInstOperands);
453 Parser->setTargetParser(*TAP.get());
454
455 int Res = Parser->Run(NoInitialTextSection);
452 int Res = 1;
453 switch (Action) {
454 case AC_AsLex:
455 Res = AsLexInput(SrcMgr, *MAI, Out.get());
456 break;
457 case AC_Assemble:
458 Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI);
459 break;
460 case AC_Disassemble:
461 Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str,
462 *Buffer, SrcMgr, Out->os());
463 break;
464 case AC_EDisassemble:
465 Res = Disassembler::disassembleEnhanced(TripleName, *Buffer, SrcMgr, Out->os());
466 break;
467 }
456468
457469 // Keep output if no errors.
458470 if (Res == 0) Out->keep();
459
460471 return Res;
461472 }
462
463 static int DisassembleInput(const char *ProgName, bool Enhanced) {
464 const Target *TheTarget = GetTarget(ProgName);
465 if (!TheTarget)
466 return 0;
467
468 OwningPtr Buffer;
469 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, Buffer)) {
470 errs() << ProgName << ": " << ec.message() << '\n';
471 return 1;
472 }
473
474 OwningPtr Out(GetOutputStream());
475 if (!Out)
476 return 1;
477
478 int Res;
479 if (Enhanced) {
480 Res =
481 Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os());
482 } else {
483 // Package up features to be passed to target/subtarget
484 std::string FeaturesStr;
485 if (MAttrs.size()) {
486 SubtargetFeatures Features;
487 for (unsigned i = 0; i != MAttrs.size(); ++i)
488 Features.AddFeature(MAttrs[i]);
489 FeaturesStr = Features.getString();
490 }
491
492 Res = Disassembler::disassemble(*TheTarget, TripleName, MCPU, FeaturesStr,
493 *Buffer.take(), Out->os());
494 }
495
496 // Keep output if no errors.
497 if (Res == 0) Out->keep();
498
499 return Res;
500 }
501
502
503 int main(int argc, char **argv) {
504 // Print a stack trace if we signal out.
505 sys::PrintStackTraceOnErrorSignal();
506 PrettyStackTraceProgram X(argc, argv);
507 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
508
509 // Initialize targets and assembly printers/parsers.
510 llvm::InitializeAllTargetInfos();
511 llvm::InitializeAllTargetMCs();
512 llvm::InitializeAllAsmParsers();
513 llvm::InitializeAllDisassemblers();
514
515 // Register the target printer for --version.
516 cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
517
518 cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
519 TripleName = Triple::normalize(TripleName);
520 setDwarfDebugFlags(argc, argv);
521
522 switch (Action) {
523 case AC_AsLex:
524 return AsLexInput(argv[0]);
525 case AC_Assemble:
526 return AssembleInput(argv[0]);
527 case AC_Disassemble:
528 return DisassembleInput(argv[0], false);
529 case AC_EDisassemble:
530 return DisassembleInput(argv[0], true);
531 }
532 }