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