llvm-mc.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. //===-- llvm-mc.cpp - Machine Code Hacking Driver ---------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This utility is a simple driver that allows command line hacking on machine
  10. // code.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "Disassembler.h"
  14. #include "llvm/MC/MCAsmBackend.h"
  15. #include "llvm/MC/MCAsmInfo.h"
  16. #include "llvm/MC/MCCodeEmitter.h"
  17. #include "llvm/MC/MCContext.h"
  18. #include "llvm/MC/MCInstPrinter.h"
  19. #include "llvm/MC/MCInstrInfo.h"
  20. #include "llvm/MC/MCObjectFileInfo.h"
  21. #include "llvm/MC/MCObjectWriter.h"
  22. #include "llvm/MC/MCParser/AsmLexer.h"
  23. #include "llvm/MC/MCParser/MCTargetAsmParser.h"
  24. #include "llvm/MC/MCRegisterInfo.h"
  25. #include "llvm/MC/MCStreamer.h"
  26. #include "llvm/MC/MCSubtargetInfo.h"
  27. #include "llvm/MC/MCTargetOptionsCommandFlags.h"
  28. #include "llvm/Support/CommandLine.h"
  29. #include "llvm/Support/Compression.h"
  30. #include "llvm/Support/FileUtilities.h"
  31. #include "llvm/Support/FormattedStream.h"
  32. #include "llvm/Support/Host.h"
  33. #include "llvm/Support/InitLLVM.h"
  34. #include "llvm/Support/MemoryBuffer.h"
  35. #include "llvm/Support/SourceMgr.h"
  36. #include "llvm/Support/TargetRegistry.h"
  37. #include "llvm/Support/TargetSelect.h"
  38. #include "llvm/Support/ToolOutputFile.h"
  39. #include "llvm/Support/WithColor.h"
  40. using namespace llvm;
  41. static mc::RegisterMCTargetOptionsFlags MOF;
  42. static cl::opt<std::string>
  43. InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
  44. static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
  45. cl::value_desc("filename"),
  46. cl::init("-"));
  47. static cl::opt<std::string> SplitDwarfFile("split-dwarf-file",
  48. cl::desc("DWO output filename"),
  49. cl::value_desc("filename"));
  50. static cl::opt<bool>
  51. ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
  52. static cl::opt<bool> RelaxELFRel(
  53. "relax-relocations", cl::init(true),
  54. cl::desc("Emit R_X86_64_GOTPCRELX instead of R_X86_64_GOTPCREL"));
  55. static cl::opt<DebugCompressionType> CompressDebugSections(
  56. "compress-debug-sections", cl::ValueOptional,
  57. cl::init(DebugCompressionType::None),
  58. cl::desc("Choose DWARF debug sections compression:"),
  59. cl::values(clEnumValN(DebugCompressionType::None, "none", "No compression"),
  60. clEnumValN(DebugCompressionType::Z, "zlib",
  61. "Use zlib compression"),
  62. clEnumValN(DebugCompressionType::GNU, "zlib-gnu",
  63. "Use zlib-gnu compression (deprecated)")));
  64. static cl::opt<bool>
  65. ShowInst("show-inst", cl::desc("Show internal instruction representation"));
  66. static cl::opt<bool>
  67. ShowInstOperands("show-inst-operands",
  68. cl::desc("Show instructions operands as parsed"));
  69. static cl::opt<unsigned>
  70. OutputAsmVariant("output-asm-variant",
  71. cl::desc("Syntax variant to use for output printing"));
  72. static cl::opt<bool>
  73. PrintImmHex("print-imm-hex", cl::init(false),
  74. cl::desc("Prefer hex format for immediate values"));
  75. static cl::list<std::string>
  76. DefineSymbol("defsym", cl::desc("Defines a symbol to be an integer constant"));
  77. static cl::opt<bool>
  78. PreserveComments("preserve-comments",
  79. cl::desc("Preserve Comments in outputted assembly"));
  80. enum OutputFileType {
  81. OFT_Null,
  82. OFT_AssemblyFile,
  83. OFT_ObjectFile
  84. };
  85. static cl::opt<OutputFileType>
  86. FileType("filetype", cl::init(OFT_AssemblyFile),
  87. cl::desc("Choose an output file type:"),
  88. cl::values(
  89. clEnumValN(OFT_AssemblyFile, "asm",
  90. "Emit an assembly ('.s') file"),
  91. clEnumValN(OFT_Null, "null",
  92. "Don't emit anything (for timing purposes)"),
  93. clEnumValN(OFT_ObjectFile, "obj",
  94. "Emit a native object ('.o') file")));
  95. static cl::list<std::string>
  96. IncludeDirs("I", cl::desc("Directory of include files"),
  97. cl::value_desc("directory"), cl::Prefix);
  98. static cl::opt<std::string>
  99. ArchName("arch", cl::desc("Target arch to assemble for, "
  100. "see -version for available targets"));
  101. static cl::opt<std::string>
  102. TripleName("triple", cl::desc("Target triple to assemble for, "
  103. "see -version for available targets"));
  104. static cl::opt<std::string>
  105. MCPU("mcpu",
  106. cl::desc("Target a specific cpu type (-mcpu=help for details)"),
  107. cl::value_desc("cpu-name"),
  108. cl::init(""));
  109. static cl::list<std::string>
  110. MAttrs("mattr",
  111. cl::CommaSeparated,
  112. cl::desc("Target specific attributes (-mattr=help for details)"),
  113. cl::value_desc("a1,+a2,-a3,..."));
  114. static cl::opt<bool> PIC("position-independent",
  115. cl::desc("Position independent"), cl::init(false));
  116. static cl::opt<bool>
  117. LargeCodeModel("large-code-model",
  118. cl::desc("Create cfi directives that assume the code might "
  119. "be more than 2gb away"));
  120. static cl::opt<bool>
  121. NoInitialTextSection("n", cl::desc("Don't assume assembly file starts "
  122. "in the text section"));
  123. static cl::opt<bool>
  124. GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly "
  125. "source files"));
  126. static cl::opt<std::string>
  127. DebugCompilationDir("fdebug-compilation-dir",
  128. cl::desc("Specifies the debug info's compilation dir"));
  129. static cl::list<std::string>
  130. DebugPrefixMap("fdebug-prefix-map",
  131. cl::desc("Map file source paths in debug info"),
  132. cl::value_desc("= separated key-value pairs"));
  133. static cl::opt<std::string>
  134. MainFileName("main-file-name",
  135. cl::desc("Specifies the name we should consider the input file"));
  136. static cl::opt<bool> SaveTempLabels("save-temp-labels",
  137. cl::desc("Don't discard temporary labels"));
  138. static cl::opt<bool> LexMasmIntegers(
  139. "masm-integers",
  140. cl::desc("Enable binary and hex masm integers (0b110 and 0ABCh)"));
  141. static cl::opt<bool> LexMasmHexFloats(
  142. "masm-hexfloats",
  143. cl::desc("Enable MASM-style hex float initializers (3F800000r)"));
  144. static cl::opt<bool> NoExecStack("no-exec-stack",
  145. cl::desc("File doesn't need an exec stack"));
  146. enum ActionType {
  147. AC_AsLex,
  148. AC_Assemble,
  149. AC_Disassemble,
  150. AC_MDisassemble,
  151. };
  152. static cl::opt<ActionType>
  153. Action(cl::desc("Action to perform:"),
  154. cl::init(AC_Assemble),
  155. cl::values(clEnumValN(AC_AsLex, "as-lex",
  156. "Lex tokens from a .s file"),
  157. clEnumValN(AC_Assemble, "assemble",
  158. "Assemble a .s file (default)"),
  159. clEnumValN(AC_Disassemble, "disassemble",
  160. "Disassemble strings of hex bytes"),
  161. clEnumValN(AC_MDisassemble, "mdis",
  162. "Marked up disassembly of strings of hex bytes")));
  163. static const Target *GetTarget(const char *ProgName) {
  164. // Figure out the target triple.
  165. if (TripleName.empty())
  166. TripleName = sys::getDefaultTargetTriple();
  167. Triple TheTriple(Triple::normalize(TripleName));
  168. // Get the target specific parser.
  169. std::string Error;
  170. const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
  171. Error);
  172. if (!TheTarget) {
  173. WithColor::error(errs(), ProgName) << Error;
  174. return nullptr;
  175. }
  176. // Update the triple name and return the found target.
  177. TripleName = TheTriple.getTriple();
  178. return TheTarget;
  179. }
  180. static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path,
  181. sys::fs::OpenFlags Flags) {
  182. std::error_code EC;
  183. auto Out = std::make_unique<ToolOutputFile>(Path, EC, Flags);
  184. if (EC) {
  185. WithColor::error() << EC.message() << '\n';
  186. return nullptr;
  187. }
  188. return Out;
  189. }
  190. static std::string DwarfDebugFlags;
  191. static void setDwarfDebugFlags(int argc, char **argv) {
  192. if (!getenv("RC_DEBUG_OPTIONS"))
  193. return;
  194. for (int i = 0; i < argc; i++) {
  195. DwarfDebugFlags += argv[i];
  196. if (i + 1 < argc)
  197. DwarfDebugFlags += " ";
  198. }
  199. }
  200. static std::string DwarfDebugProducer;
  201. static void setDwarfDebugProducer() {
  202. if(!getenv("DEBUG_PRODUCER"))
  203. return;
  204. DwarfDebugProducer += getenv("DEBUG_PRODUCER");
  205. }
  206. static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI,
  207. raw_ostream &OS) {
  208. AsmLexer Lexer(MAI);
  209. Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer());
  210. bool Error = false;
  211. while (Lexer.Lex().isNot(AsmToken::Eof)) {
  212. Lexer.getTok().dump(OS);
  213. OS << "\n";
  214. if (Lexer.getTok().getKind() == AsmToken::Error)
  215. Error = true;
  216. }
  217. return Error;
  218. }
  219. static int fillCommandLineSymbols(MCAsmParser &Parser) {
  220. for (auto &I: DefineSymbol) {
  221. auto Pair = StringRef(I).split('=');
  222. auto Sym = Pair.first;
  223. auto Val = Pair.second;
  224. if (Sym.empty() || Val.empty()) {
  225. WithColor::error() << "defsym must be of the form: sym=value: " << I
  226. << "\n";
  227. return 1;
  228. }
  229. int64_t Value;
  230. if (Val.getAsInteger(0, Value)) {
  231. WithColor::error() << "value is not an integer: " << Val << "\n";
  232. return 1;
  233. }
  234. Parser.getContext().setSymbolValue(Parser.getStreamer(), Sym, Value);
  235. }
  236. return 0;
  237. }
  238. static int AssembleInput(const char *ProgName, const Target *TheTarget,
  239. SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
  240. MCAsmInfo &MAI, MCSubtargetInfo &STI,
  241. MCInstrInfo &MCII, MCTargetOptions const &MCOptions) {
  242. std::unique_ptr<MCAsmParser> Parser(
  243. createMCAsmParser(SrcMgr, Ctx, Str, MAI));
  244. std::unique_ptr<MCTargetAsmParser> TAP(
  245. TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
  246. if (!TAP) {
  247. WithColor::error(errs(), ProgName)
  248. << "this target does not support assembly parsing.\n";
  249. return 1;
  250. }
  251. int SymbolResult = fillCommandLineSymbols(*Parser);
  252. if(SymbolResult)
  253. return SymbolResult;
  254. Parser->setShowParsedOperands(ShowInstOperands);
  255. Parser->setTargetParser(*TAP);
  256. Parser->getLexer().setLexMasmIntegers(LexMasmIntegers);
  257. Parser->getLexer().setLexMasmHexFloats(LexMasmHexFloats);
  258. int Res = Parser->Run(NoInitialTextSection);
  259. return Res;
  260. }
  261. int main(int argc, char **argv) {
  262. InitLLVM X(argc, argv);
  263. // Initialize targets and assembly printers/parsers.
  264. llvm::InitializeAllTargetInfos();
  265. llvm::InitializeAllTargetMCs();
  266. llvm::InitializeAllAsmParsers();
  267. llvm::InitializeAllDisassemblers();
  268. // Register the target printer for --version.
  269. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
  270. cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
  271. const MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
  272. setDwarfDebugFlags(argc, argv);
  273. setDwarfDebugProducer();
  274. const char *ProgName = argv[0];
  275. const Target *TheTarget = GetTarget(ProgName);
  276. if (!TheTarget)
  277. return 1;
  278. // Now that GetTarget() has (potentially) replaced TripleName, it's safe to
  279. // construct the Triple object.
  280. Triple TheTriple(TripleName);
  281. ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
  282. MemoryBuffer::getFileOrSTDIN(InputFilename);
  283. if (std::error_code EC = BufferPtr.getError()) {
  284. WithColor::error(errs(), ProgName)
  285. << InputFilename << ": " << EC.message() << '\n';
  286. return 1;
  287. }
  288. MemoryBuffer *Buffer = BufferPtr->get();
  289. SourceMgr SrcMgr;
  290. // Tell SrcMgr about this buffer, which is what the parser will pick up.
  291. SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
  292. // Record the location of the include directories so that the lexer can find
  293. // it later.
  294. SrcMgr.setIncludeDirs(IncludeDirs);
  295. std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
  296. assert(MRI && "Unable to create target register info!");
  297. std::unique_ptr<MCAsmInfo> MAI(
  298. TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
  299. assert(MAI && "Unable to create target asm info!");
  300. MAI->setRelaxELFRelocations(RelaxELFRel);
  301. if (CompressDebugSections != DebugCompressionType::None) {
  302. if (!zlib::isAvailable()) {
  303. WithColor::error(errs(), ProgName)
  304. << "build tools with zlib to enable -compress-debug-sections";
  305. return 1;
  306. }
  307. MAI->setCompressDebugSections(CompressDebugSections);
  308. }
  309. MAI->setPreserveAsmComments(PreserveComments);
  310. // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
  311. // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
  312. MCObjectFileInfo MOFI;
  313. MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr, &MCOptions);
  314. MOFI.InitMCObjectFileInfo(TheTriple, PIC, Ctx, LargeCodeModel);
  315. if (SaveTempLabels)
  316. Ctx.setAllowTemporaryLabels(false);
  317. Ctx.setGenDwarfForAssembly(GenDwarfForAssembly);
  318. // Default to 4 for dwarf version.
  319. unsigned DwarfVersion = MCOptions.DwarfVersion ? MCOptions.DwarfVersion : 4;
  320. if (DwarfVersion < 2 || DwarfVersion > 5) {
  321. errs() << ProgName << ": Dwarf version " << DwarfVersion
  322. << " is not supported." << '\n';
  323. return 1;
  324. }
  325. Ctx.setDwarfVersion(DwarfVersion);
  326. if (MCOptions.Dwarf64) {
  327. // The 64-bit DWARF format was introduced in DWARFv3.
  328. if (DwarfVersion < 3) {
  329. errs() << ProgName
  330. << ": the 64-bit DWARF format is not supported for DWARF versions "
  331. "prior to 3\n";
  332. return 1;
  333. }
  334. // 32-bit targets don't support DWARF64, which requires 64-bit relocations.
  335. if (MAI->getCodePointerSize() < 8) {
  336. errs() << ProgName
  337. << ": the 64-bit DWARF format is only supported for 64-bit "
  338. "targets\n";
  339. return 1;
  340. }
  341. // If needsDwarfSectionOffsetDirective is true, we would eventually call
  342. // MCStreamer::emitSymbolValue() with IsSectionRelative = true, but that
  343. // is supported only for 4-byte long references.
  344. if (MAI->needsDwarfSectionOffsetDirective()) {
  345. errs() << ProgName << ": the 64-bit DWARF format is not supported for "
  346. << TheTriple.normalize() << "\n";
  347. return 1;
  348. }
  349. Ctx.setDwarfFormat(dwarf::DWARF64);
  350. }
  351. if (!DwarfDebugFlags.empty())
  352. Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags));
  353. if (!DwarfDebugProducer.empty())
  354. Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer));
  355. if (!DebugCompilationDir.empty())
  356. Ctx.setCompilationDir(DebugCompilationDir);
  357. else {
  358. // If no compilation dir is set, try to use the current directory.
  359. SmallString<128> CWD;
  360. if (!sys::fs::current_path(CWD))
  361. Ctx.setCompilationDir(CWD);
  362. }
  363. for (const auto &Arg : DebugPrefixMap) {
  364. const auto &KV = StringRef(Arg).split('=');
  365. Ctx.addDebugPrefixMapEntry(std::string(KV.first), std::string(KV.second));
  366. }
  367. if (!MainFileName.empty())
  368. Ctx.setMainFileName(MainFileName);
  369. if (GenDwarfForAssembly)
  370. Ctx.setGenDwarfRootFile(InputFilename, Buffer->getBuffer());
  371. // Package up features to be passed to target/subtarget
  372. std::string FeaturesStr;
  373. if (MAttrs.size()) {
  374. SubtargetFeatures Features;
  375. for (unsigned i = 0; i != MAttrs.size(); ++i)
  376. Features.AddFeature(MAttrs[i]);
  377. FeaturesStr = Features.getString();
  378. }
  379. sys::fs::OpenFlags Flags = (FileType == OFT_AssemblyFile) ? sys::fs::OF_Text
  380. : sys::fs::OF_None;
  381. std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename, Flags);
  382. if (!Out)
  383. return 1;
  384. std::unique_ptr<ToolOutputFile> DwoOut;
  385. if (!SplitDwarfFile.empty()) {
  386. if (FileType != OFT_ObjectFile) {
  387. WithColor::error() << "dwo output only supported with object files\n";
  388. return 1;
  389. }
  390. DwoOut = GetOutputStream(SplitDwarfFile, sys::fs::OF_None);
  391. if (!DwoOut)
  392. return 1;
  393. }
  394. std::unique_ptr<buffer_ostream> BOS;
  395. raw_pwrite_stream *OS = &Out->os();
  396. std::unique_ptr<MCStreamer> Str;
  397. std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
  398. assert(MCII && "Unable to create instruction info!");
  399. std::unique_ptr<MCSubtargetInfo> STI(
  400. TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
  401. assert(STI && "Unable to create subtarget info!");
  402. MCInstPrinter *IP = nullptr;
  403. if (FileType == OFT_AssemblyFile) {
  404. IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant,
  405. *MAI, *MCII, *MRI);
  406. if (!IP) {
  407. WithColor::error()
  408. << "unable to create instruction printer for target triple '"
  409. << TheTriple.normalize() << "' with assembly variant "
  410. << OutputAsmVariant << ".\n";
  411. return 1;
  412. }
  413. // Set the display preference for hex vs. decimal immediates.
  414. IP->setPrintImmHex(PrintImmHex);
  415. // Set up the AsmStreamer.
  416. std::unique_ptr<MCCodeEmitter> CE;
  417. if (ShowEncoding)
  418. CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
  419. std::unique_ptr<MCAsmBackend> MAB(
  420. TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
  421. auto FOut = std::make_unique<formatted_raw_ostream>(*OS);
  422. Str.reset(
  423. TheTarget->createAsmStreamer(Ctx, std::move(FOut), /*asmverbose*/ true,
  424. /*useDwarfDirectory*/ true, IP,
  425. std::move(CE), std::move(MAB), ShowInst));
  426. } else if (FileType == OFT_Null) {
  427. Str.reset(TheTarget->createNullStreamer(Ctx));
  428. } else {
  429. assert(FileType == OFT_ObjectFile && "Invalid file type!");
  430. if (!Out->os().supportsSeeking()) {
  431. BOS = std::make_unique<buffer_ostream>(Out->os());
  432. OS = BOS.get();
  433. }
  434. MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
  435. MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
  436. Str.reset(TheTarget->createMCObjectStreamer(
  437. TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
  438. DwoOut ? MAB->createDwoObjectWriter(*OS, DwoOut->os())
  439. : MAB->createObjectWriter(*OS),
  440. std::unique_ptr<MCCodeEmitter>(CE), *STI, MCOptions.MCRelaxAll,
  441. MCOptions.MCIncrementalLinkerCompatible,
  442. /*DWARFMustBeAtTheEnd*/ false));
  443. if (NoExecStack)
  444. Str->InitSections(true);
  445. }
  446. // Use Assembler information for parsing.
  447. Str->setUseAssemblerInfoForParsing(true);
  448. int Res = 1;
  449. bool disassemble = false;
  450. switch (Action) {
  451. case AC_AsLex:
  452. Res = AsLexInput(SrcMgr, *MAI, Out->os());
  453. break;
  454. case AC_Assemble:
  455. Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI,
  456. *MCII, MCOptions);
  457. break;
  458. case AC_MDisassemble:
  459. assert(IP && "Expected assembly output");
  460. IP->setUseMarkup(true);
  461. disassemble = true;
  462. break;
  463. case AC_Disassemble:
  464. disassemble = true;
  465. break;
  466. }
  467. if (disassemble)
  468. Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer,
  469. SrcMgr, Ctx, Out->os(), MCOptions);
  470. // Keep output if no errors.
  471. if (Res == 0) {
  472. Out->keep();
  473. if (DwoOut)
  474. DwoOut->keep();
  475. }
  476. return Res;
  477. }