brintos

brintos / llvm-project-archived public Read only

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