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