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