xref: /llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp (revision dd647e3e608ed0b2bac7c588d5859b80ef4a5976)
15f6dfa80SEric Astor //===-- llvm-ml.cpp - masm-compatible assembler -----------------*- C++ -*-===//
25f6dfa80SEric Astor //
35f6dfa80SEric Astor // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f6dfa80SEric Astor // See https://llvm.org/LICENSE.txt for license information.
55f6dfa80SEric Astor // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f6dfa80SEric Astor //
75f6dfa80SEric Astor //===----------------------------------------------------------------------===//
85f6dfa80SEric Astor //
95f6dfa80SEric Astor // A simple driver around MasmParser; based on llvm-mc.
105f6dfa80SEric Astor //
115f6dfa80SEric Astor //===----------------------------------------------------------------------===//
125f6dfa80SEric Astor 
138fee2ee9SEric Astor #include "llvm/ADT/StringSwitch.h"
145f6dfa80SEric Astor #include "llvm/MC/MCAsmBackend.h"
155f6dfa80SEric Astor #include "llvm/MC/MCAsmInfo.h"
165f6dfa80SEric Astor #include "llvm/MC/MCCodeEmitter.h"
175f6dfa80SEric Astor #include "llvm/MC/MCContext.h"
185f6dfa80SEric Astor #include "llvm/MC/MCInstPrinter.h"
195f6dfa80SEric Astor #include "llvm/MC/MCInstrInfo.h"
205f6dfa80SEric Astor #include "llvm/MC/MCObjectFileInfo.h"
215f6dfa80SEric Astor #include "llvm/MC/MCObjectWriter.h"
225f6dfa80SEric Astor #include "llvm/MC/MCParser/AsmLexer.h"
235f6dfa80SEric Astor #include "llvm/MC/MCParser/MCTargetAsmParser.h"
245f6dfa80SEric Astor #include "llvm/MC/MCRegisterInfo.h"
255f6dfa80SEric Astor #include "llvm/MC/MCStreamer.h"
265f6dfa80SEric Astor #include "llvm/MC/MCSubtargetInfo.h"
27ef736a1cSserge-sans-paille #include "llvm/MC/MCSymbol.h"
28ac1d23edSserge-sans-paille #include "llvm/MC/MCTargetOptionsCommandFlags.h"
2989b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
308fee2ee9SEric Astor #include "llvm/Option/Arg.h"
318fee2ee9SEric Astor #include "llvm/Option/ArgList.h"
328fee2ee9SEric Astor #include "llvm/Option/Option.h"
335f6dfa80SEric Astor #include "llvm/Support/Compression.h"
345f6dfa80SEric Astor #include "llvm/Support/FileUtilities.h"
358fee2ee9SEric Astor #include "llvm/Support/FormatVariadic.h"
365f6dfa80SEric Astor #include "llvm/Support/FormattedStream.h"
37d5ca9004SAndrés Villegas #include "llvm/Support/LLVMDriver.h"
385f6dfa80SEric Astor #include "llvm/Support/MemoryBuffer.h"
398fee2ee9SEric Astor #include "llvm/Support/Path.h"
404b5317e9SEric Astor #include "llvm/Support/Process.h"
415f6dfa80SEric Astor #include "llvm/Support/SourceMgr.h"
425f6dfa80SEric Astor #include "llvm/Support/TargetSelect.h"
435f6dfa80SEric Astor #include "llvm/Support/ToolOutputFile.h"
445f6dfa80SEric Astor #include "llvm/Support/WithColor.h"
45d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
465fba6058SEric Astor #include <ctime>
473c255f67SKrzysztof Parzyszek #include <optional>
485f6dfa80SEric Astor 
495f6dfa80SEric Astor using namespace llvm;
508fee2ee9SEric Astor using namespace llvm::opt;
515f6dfa80SEric Astor 
528fee2ee9SEric Astor namespace {
53ac1d23edSserge-sans-paille 
548fee2ee9SEric Astor enum ID {
558fee2ee9SEric Astor   OPT_INVALID = 0, // This is not an option ID.
563f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
578fee2ee9SEric Astor #include "Opts.inc"
588fee2ee9SEric Astor #undef OPTION
595f6dfa80SEric Astor };
605f6dfa80SEric Astor 
61*dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
628fee2ee9SEric Astor #include "Opts.inc"
63*dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
64*dd647e3eSChandler Carruth 
65*dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
66*dd647e3eSChandler Carruth #include "Opts.inc"
67*dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
685f6dfa80SEric Astor 
6907d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info InfoTable[] = {
703f092f37SJan Svoboda #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
718fee2ee9SEric Astor #include "Opts.inc"
728fee2ee9SEric Astor #undef OPTION
738fee2ee9SEric Astor };
748fee2ee9SEric Astor 
7507bb29d8Sserge-sans-paille class MLOptTable : public opt::GenericOptTable {
768fee2ee9SEric Astor public:
77*dd647e3eSChandler Carruth   MLOptTable()
78*dd647e3eSChandler Carruth       : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,
79*dd647e3eSChandler Carruth                              /*IgnoreCase=*/false) {}
808fee2ee9SEric Astor };
818fee2ee9SEric Astor } // namespace
828fee2ee9SEric Astor 
838fee2ee9SEric Astor static Triple GetTriple(StringRef ProgName, opt::InputArgList &Args) {
845f6dfa80SEric Astor   // Figure out the target triple.
858fee2ee9SEric Astor   StringRef DefaultBitness = "32";
868fee2ee9SEric Astor   SmallString<255> Program = ProgName;
878fee2ee9SEric Astor   sys::path::replace_extension(Program, "");
88cc4ecfd6SKazu Hirata   if (Program.ends_with("ml64"))
898fee2ee9SEric Astor     DefaultBitness = "64";
905f6dfa80SEric Astor 
918fee2ee9SEric Astor   StringRef TripleName =
928fee2ee9SEric Astor       StringSwitch<StringRef>(Args.getLastArgValue(OPT_bitness, DefaultBitness))
938fee2ee9SEric Astor           .Case("32", "i386-pc-windows")
948fee2ee9SEric Astor           .Case("64", "x86_64-pc-windows")
958fee2ee9SEric Astor           .Default("");
968fee2ee9SEric Astor   return Triple(Triple::normalize(TripleName));
975f6dfa80SEric Astor }
985f6dfa80SEric Astor 
995f6dfa80SEric Astor static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path) {
1005f6dfa80SEric Astor   std::error_code EC;
101518d955fSDuncan P. N. Exon Smith   auto Out = std::make_unique<ToolOutputFile>(Path, EC, sys::fs::OF_None);
1025f6dfa80SEric Astor   if (EC) {
1035f6dfa80SEric Astor     WithColor::error() << EC.message() << '\n';
1045f6dfa80SEric Astor     return nullptr;
1055f6dfa80SEric Astor   }
1065f6dfa80SEric Astor 
1075f6dfa80SEric Astor   return Out;
1085f6dfa80SEric Astor }
1095f6dfa80SEric Astor 
1105f6dfa80SEric Astor static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, raw_ostream &OS) {
1115f6dfa80SEric Astor   AsmLexer Lexer(MAI);
1125f6dfa80SEric Astor   Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer());
1135b4744b2SEric Astor   Lexer.setLexMasmIntegers(true);
1146b70a83dSEric Astor   Lexer.useMasmDefaultRadix(true);
115c65e9e71SEric Astor   Lexer.setLexMasmHexFloats(true);
11607c4f1d1SEric Astor   Lexer.setLexMasmStrings(true);
1175f6dfa80SEric Astor 
1185f6dfa80SEric Astor   bool Error = false;
1195f6dfa80SEric Astor   while (Lexer.Lex().isNot(AsmToken::Eof)) {
1205f6dfa80SEric Astor     Lexer.getTok().dump(OS);
1215f6dfa80SEric Astor     OS << "\n";
1225f6dfa80SEric Astor     if (Lexer.getTok().getKind() == AsmToken::Error)
1235f6dfa80SEric Astor       Error = true;
1245f6dfa80SEric Astor   }
1255f6dfa80SEric Astor 
1265f6dfa80SEric Astor   return Error;
1275f6dfa80SEric Astor }
1285f6dfa80SEric Astor 
1298fee2ee9SEric Astor static int AssembleInput(StringRef ProgName, const Target *TheTarget,
1305f6dfa80SEric Astor                          SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
1315f6dfa80SEric Astor                          MCAsmInfo &MAI, MCSubtargetInfo &STI,
1328fee2ee9SEric Astor                          MCInstrInfo &MCII, MCTargetOptions &MCOptions,
1338fee2ee9SEric Astor                          const opt::ArgList &InputArgs) {
1345fba6058SEric Astor   struct tm TM;
1355fba6058SEric Astor   time_t Timestamp;
1365fba6058SEric Astor   if (InputArgs.hasArg(OPT_timestamp)) {
1375fba6058SEric Astor     StringRef TimestampStr = InputArgs.getLastArgValue(OPT_timestamp);
1385fba6058SEric Astor     int64_t IntTimestamp;
1395fba6058SEric Astor     if (TimestampStr.getAsInteger(10, IntTimestamp)) {
1405fba6058SEric Astor       WithColor::error(errs(), ProgName)
1415fba6058SEric Astor           << "invalid timestamp '" << TimestampStr
1425fba6058SEric Astor           << "'; must be expressed in seconds since the UNIX epoch.\n";
1435fba6058SEric Astor       return 1;
1445fba6058SEric Astor     }
1455fba6058SEric Astor     Timestamp = IntTimestamp;
1465fba6058SEric Astor   } else {
1475fba6058SEric Astor     Timestamp = time(nullptr);
1485fba6058SEric Astor   }
1495fba6058SEric Astor   if (InputArgs.hasArg(OPT_utc)) {
1505fba6058SEric Astor     // Not thread-safe.
1515fba6058SEric Astor     TM = *gmtime(&Timestamp);
1525fba6058SEric Astor   } else {
1535fba6058SEric Astor     // Not thread-safe.
1545fba6058SEric Astor     TM = *localtime(&Timestamp);
1555fba6058SEric Astor   }
1565fba6058SEric Astor 
157ee2c0f76SEric Astor   std::unique_ptr<MCAsmParser> Parser(
1585fba6058SEric Astor       createMCMasmParser(SrcMgr, Ctx, Str, MAI, TM, 0));
1595f6dfa80SEric Astor   std::unique_ptr<MCTargetAsmParser> TAP(
1605f6dfa80SEric Astor       TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
1615f6dfa80SEric Astor 
1625f6dfa80SEric Astor   if (!TAP) {
1635f6dfa80SEric Astor     WithColor::error(errs(), ProgName)
1645f6dfa80SEric Astor         << "this target does not support assembly parsing.\n";
1655f6dfa80SEric Astor     return 1;
1665f6dfa80SEric Astor   }
1675f6dfa80SEric Astor 
1688fee2ee9SEric Astor   Parser->setShowParsedOperands(InputArgs.hasArg(OPT_show_inst_operands));
1695f6dfa80SEric Astor   Parser->setTargetParser(*TAP);
1705f6dfa80SEric Astor   Parser->getLexer().setLexMasmIntegers(true);
1716b70a83dSEric Astor   Parser->getLexer().useMasmDefaultRadix(true);
172c65e9e71SEric Astor   Parser->getLexer().setLexMasmHexFloats(true);
17307c4f1d1SEric Astor   Parser->getLexer().setLexMasmStrings(true);
1745f6dfa80SEric Astor 
175c64037b7SEric Astor   auto Defines = InputArgs.getAllArgValues(OPT_define);
176c64037b7SEric Astor   for (StringRef Define : Defines) {
177c64037b7SEric Astor     const auto NameValue = Define.split('=');
178c64037b7SEric Astor     StringRef Name = NameValue.first, Value = NameValue.second;
179c64037b7SEric Astor     if (Parser->defineMacro(Name, Value)) {
180c64037b7SEric Astor       WithColor::error(errs(), ProgName)
181c64037b7SEric Astor           << "can't define macro '" << Name << "' = '" << Value << "'\n";
182c64037b7SEric Astor       return 1;
183c64037b7SEric Astor     }
184c64037b7SEric Astor   }
185c64037b7SEric Astor 
1865f6dfa80SEric Astor   int Res = Parser->Run(/*NoInitialTextSection=*/true);
1875f6dfa80SEric Astor 
1885f6dfa80SEric Astor   return Res;
1895f6dfa80SEric Astor }
1905f6dfa80SEric Astor 
191d5ca9004SAndrés Villegas int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) {
1928fee2ee9SEric Astor   StringRef ProgName = sys::path::filename(Argv[0]);
1935f6dfa80SEric Astor 
1945f6dfa80SEric Astor   // Initialize targets and assembly printers/parsers.
1955f6dfa80SEric Astor   llvm::InitializeAllTargetInfos();
1965f6dfa80SEric Astor   llvm::InitializeAllTargetMCs();
1975f6dfa80SEric Astor   llvm::InitializeAllAsmParsers();
1985f6dfa80SEric Astor   llvm::InitializeAllDisassemblers();
1995f6dfa80SEric Astor 
2008fee2ee9SEric Astor   MLOptTable T;
2018fee2ee9SEric Astor   unsigned MissingArgIndex, MissingArgCount;
20238818b60Sserge-sans-paille   ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
2038fee2ee9SEric Astor   opt::InputArgList InputArgs =
2048fee2ee9SEric Astor       T.ParseArgs(ArgsArr, MissingArgIndex, MissingArgCount);
2055f6dfa80SEric Astor 
2068fee2ee9SEric Astor   std::string InputFilename;
2078fee2ee9SEric Astor   for (auto *Arg : InputArgs.filtered(OPT_INPUT)) {
2088fee2ee9SEric Astor     std::string ArgString = Arg->getAsString(InputArgs);
209ae38e488SAlan Zhao     bool IsFile = false;
210ae38e488SAlan Zhao     std::error_code IsFileEC =
211ae38e488SAlan Zhao         llvm::sys::fs::is_regular_file(ArgString, IsFile);
212ae38e488SAlan Zhao     if (ArgString == "-" || IsFile) {
2138fee2ee9SEric Astor       if (!InputFilename.empty()) {
2148fee2ee9SEric Astor         WithColor::warning(errs(), ProgName)
2158fee2ee9SEric Astor             << "does not support multiple assembly files in one command; "
2168fee2ee9SEric Astor             << "ignoring '" << InputFilename << "'\n";
2178fee2ee9SEric Astor       }
2188fee2ee9SEric Astor       InputFilename = ArgString;
2198fee2ee9SEric Astor     } else {
2208fee2ee9SEric Astor       std::string Diag;
2218fee2ee9SEric Astor       raw_string_ostream OS(Diag);
222ae38e488SAlan Zhao       OS << ArgString << ": " << IsFileEC.message();
2238fee2ee9SEric Astor 
2248fee2ee9SEric Astor       std::string Nearest;
2258fee2ee9SEric Astor       if (T.findNearest(ArgString, Nearest) < 2)
2268fee2ee9SEric Astor         OS << ", did you mean '" << Nearest << "'?";
2278fee2ee9SEric Astor 
2288fee2ee9SEric Astor       WithColor::error(errs(), ProgName) << OS.str() << '\n';
2298fee2ee9SEric Astor       exit(1);
2308fee2ee9SEric Astor     }
2318fee2ee9SEric Astor   }
2328fee2ee9SEric Astor   for (auto *Arg : InputArgs.filtered(OPT_assembly_file)) {
2338fee2ee9SEric Astor     if (!InputFilename.empty()) {
2348fee2ee9SEric Astor       WithColor::warning(errs(), ProgName)
2358fee2ee9SEric Astor           << "does not support multiple assembly files in one command; "
2368fee2ee9SEric Astor           << "ignoring '" << InputFilename << "'\n";
2378fee2ee9SEric Astor     }
23865fd1e91SAlan Zhao     InputFilename = Arg->getValue();
2398fee2ee9SEric Astor   }
2408fee2ee9SEric Astor 
2418fee2ee9SEric Astor   for (auto *Arg : InputArgs.filtered(OPT_unsupported_Group)) {
2428fee2ee9SEric Astor     WithColor::warning(errs(), ProgName)
2438fee2ee9SEric Astor         << "ignoring unsupported '" << Arg->getOption().getName()
2448fee2ee9SEric Astor         << "' option\n";
2458fee2ee9SEric Astor   }
2468fee2ee9SEric Astor 
24782ecf9a0SEric Astor   if (InputArgs.hasArg(OPT_debug)) {
24882ecf9a0SEric Astor     DebugFlag = true;
24982ecf9a0SEric Astor   }
25082ecf9a0SEric Astor   for (auto *Arg : InputArgs.filtered(OPT_debug_only)) {
25182ecf9a0SEric Astor     setCurrentDebugTypes(Arg->getValues().data(), Arg->getNumValues());
25282ecf9a0SEric Astor   }
25382ecf9a0SEric Astor 
2548fee2ee9SEric Astor   if (InputArgs.hasArg(OPT_help)) {
2558fee2ee9SEric Astor     std::string Usage = llvm::formatv("{0} [ /options ] file", ProgName).str();
256f1e2d585SFangrui Song     T.printHelp(outs(), Usage.c_str(), "LLVM MASM Assembler",
2578fee2ee9SEric Astor                 /*ShowHidden=*/false);
2588fee2ee9SEric Astor     return 0;
2598fee2ee9SEric Astor   } else if (InputFilename.empty()) {
2608fee2ee9SEric Astor     outs() << "USAGE: " << ProgName << " [ /options ] file\n"
2618fee2ee9SEric Astor            << "Run \"" << ProgName << " /?\" or \"" << ProgName
2628fee2ee9SEric Astor            << " /help\" for more info.\n";
2638fee2ee9SEric Astor     return 0;
2648fee2ee9SEric Astor   }
2658fee2ee9SEric Astor 
2668fee2ee9SEric Astor   MCTargetOptions MCOptions;
267ee2c0f76SEric Astor   MCOptions.AssemblyLanguage = "masm";
2680499a9d6SEric Astor   MCOptions.MCFatalWarnings = InputArgs.hasArg(OPT_fatal_warnings);
269ca91538cSFangrui Song   MCOptions.MCSaveTempLabels = InputArgs.hasArg(OPT_save_temp_labels);
2707f17b6b7SFangrui Song   MCOptions.ShowMCInst = InputArgs.hasArg(OPT_show_inst);
27152e79ed1SFangrui Song   MCOptions.AsmVerbose = true;
2725f6dfa80SEric Astor 
2738fee2ee9SEric Astor   Triple TheTriple = GetTriple(ProgName, InputArgs);
2748fee2ee9SEric Astor   std::string Error;
2758fee2ee9SEric Astor   const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple, Error);
2768fee2ee9SEric Astor   if (!TheTarget) {
2778fee2ee9SEric Astor     WithColor::error(errs(), ProgName) << Error;
2785f6dfa80SEric Astor     return 1;
2798fee2ee9SEric Astor   }
2808fee2ee9SEric Astor   const std::string &TripleName = TheTriple.getTriple();
2815f6dfa80SEric Astor 
2828fee2ee9SEric Astor   bool SafeSEH = InputArgs.hasArg(OPT_safeseh);
28313f701b9SEric Astor   if (SafeSEH && !(TheTriple.isArch32Bit() && TheTriple.isX86())) {
28413f701b9SEric Astor     WithColor::warning()
28513f701b9SEric Astor         << "/safeseh applies only to 32-bit X86 platforms; ignoring.\n";
28613f701b9SEric Astor     SafeSEH = false;
28713f701b9SEric Astor   }
28813f701b9SEric Astor 
2895f6dfa80SEric Astor   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
2905f6dfa80SEric Astor       MemoryBuffer::getFileOrSTDIN(InputFilename);
2915f6dfa80SEric Astor   if (std::error_code EC = BufferPtr.getError()) {
2925f6dfa80SEric Astor     WithColor::error(errs(), ProgName)
2935f6dfa80SEric Astor         << InputFilename << ": " << EC.message() << '\n';
2945f6dfa80SEric Astor     return 1;
2955f6dfa80SEric Astor   }
2965f6dfa80SEric Astor 
2975f6dfa80SEric Astor   SourceMgr SrcMgr;
2985f6dfa80SEric Astor 
2995f6dfa80SEric Astor   // Tell SrcMgr about this buffer, which is what the parser will pick up.
3005f6dfa80SEric Astor   SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
3015f6dfa80SEric Astor 
3025f6dfa80SEric Astor   // Record the location of the include directories so that the lexer can find
3034b5317e9SEric Astor   // included files later.
3044b5317e9SEric Astor   std::vector<std::string> IncludeDirs =
3054b5317e9SEric Astor       InputArgs.getAllArgValues(OPT_include_path);
3064b5317e9SEric Astor   if (!InputArgs.hasArg(OPT_ignore_include_envvar)) {
3073c255f67SKrzysztof Parzyszek     if (std::optional<std::string> IncludeEnvVar =
3084b5317e9SEric Astor             llvm::sys::Process::GetEnv("INCLUDE")) {
3094b5317e9SEric Astor       SmallVector<StringRef, 8> Dirs;
3104b5317e9SEric Astor       StringRef(*IncludeEnvVar)
3114b5317e9SEric Astor           .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
3124b5317e9SEric Astor       IncludeDirs.reserve(IncludeDirs.size() + Dirs.size());
3134b5317e9SEric Astor       for (StringRef Dir : Dirs)
3144b5317e9SEric Astor         IncludeDirs.push_back(Dir.str());
3154b5317e9SEric Astor     }
3164b5317e9SEric Astor   }
3174b5317e9SEric Astor   SrcMgr.setIncludeDirs(IncludeDirs);
3185f6dfa80SEric Astor 
3195f6dfa80SEric Astor   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
3205f6dfa80SEric Astor   assert(MRI && "Unable to create target register info!");
3215f6dfa80SEric Astor 
3225f6dfa80SEric Astor   std::unique_ptr<MCAsmInfo> MAI(
3235f6dfa80SEric Astor       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
3245f6dfa80SEric Astor   assert(MAI && "Unable to create target asm info!");
3255f6dfa80SEric Astor 
3268fee2ee9SEric Astor   MAI->setPreserveAsmComments(InputArgs.hasArg(OPT_preserve_comments));
3275f6dfa80SEric Astor 
328632ebc4aSPhilipp Krones   std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(
329632ebc4aSPhilipp Krones       TripleName, /*CPU=*/"", /*Features=*/""));
330632ebc4aSPhilipp Krones   assert(STI && "Unable to create subtarget info!");
331632ebc4aSPhilipp Krones 
3325f6dfa80SEric Astor   // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
3335f6dfa80SEric Astor   // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
334c2f819afSPhilipp Krones   MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
335c2f819afSPhilipp Krones   std::unique_ptr<MCObjectFileInfo> MOFI(TheTarget->createMCObjectFileInfo(
336c2f819afSPhilipp Krones       Ctx, /*PIC=*/false, /*LargeCodeModel=*/true));
337c2f819afSPhilipp Krones   Ctx.setObjectFileInfo(MOFI.get());
3385f6dfa80SEric Astor 
3398fee2ee9SEric Astor   // Set compilation information.
3405f6dfa80SEric Astor   SmallString<128> CWD;
3415f6dfa80SEric Astor   if (!sys::fs::current_path(CWD))
3425f6dfa80SEric Astor     Ctx.setCompilationDir(CWD);
3438fee2ee9SEric Astor   Ctx.setMainFileName(InputFilename);
3445f6dfa80SEric Astor 
3458fee2ee9SEric Astor   StringRef FileType = InputArgs.getLastArgValue(OPT_filetype, "obj");
3468fee2ee9SEric Astor   SmallString<255> DefaultOutputFilename;
3478fee2ee9SEric Astor   if (InputArgs.hasArg(OPT_as_lex)) {
3488fee2ee9SEric Astor     DefaultOutputFilename = "-";
3498fee2ee9SEric Astor   } else {
3508fee2ee9SEric Astor     DefaultOutputFilename = InputFilename;
3518fee2ee9SEric Astor     sys::path::replace_extension(DefaultOutputFilename, FileType);
3528fee2ee9SEric Astor   }
3538fee2ee9SEric Astor   const StringRef OutputFilename =
3548fee2ee9SEric Astor       InputArgs.getLastArgValue(OPT_output_file, DefaultOutputFilename);
3555f6dfa80SEric Astor   std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename);
3565f6dfa80SEric Astor   if (!Out)
3575f6dfa80SEric Astor     return 1;
3585f6dfa80SEric Astor 
3595f6dfa80SEric Astor   std::unique_ptr<buffer_ostream> BOS;
3605f6dfa80SEric Astor   raw_pwrite_stream *OS = &Out->os();
3615f6dfa80SEric Astor   std::unique_ptr<MCStreamer> Str;
3625f6dfa80SEric Astor 
3635f6dfa80SEric Astor   std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
3641756d679SElla Ma   assert(MCII && "Unable to create instruction info!");
3651756d679SElla Ma 
3665f6dfa80SEric Astor   MCInstPrinter *IP = nullptr;
3678fee2ee9SEric Astor   if (FileType == "s") {
3688fee2ee9SEric Astor     const bool OutputATTAsm = InputArgs.hasArg(OPT_output_att_asm);
3695f6dfa80SEric Astor     const unsigned OutputAsmVariant = OutputATTAsm ? 0U   // ATT dialect
3705f6dfa80SEric Astor                                                    : 1U;  // Intel dialect
3718fee2ee9SEric Astor     IP = TheTarget->createMCInstPrinter(TheTriple, OutputAsmVariant, *MAI,
3728fee2ee9SEric Astor                                         *MCII, *MRI);
3735f6dfa80SEric Astor 
3745f6dfa80SEric Astor     if (!IP) {
3755f6dfa80SEric Astor       WithColor::error()
3765f6dfa80SEric Astor           << "unable to create instruction printer for target triple '"
3775f6dfa80SEric Astor           << TheTriple.normalize() << "' with "
3785f6dfa80SEric Astor           << (OutputATTAsm ? "ATT" : "Intel") << " assembly variant.\n";
3795f6dfa80SEric Astor       return 1;
3805f6dfa80SEric Astor     }
3815f6dfa80SEric Astor 
3825f6dfa80SEric Astor     // Set the display preference for hex vs. decimal immediates.
3838fee2ee9SEric Astor     IP->setPrintImmHex(InputArgs.hasArg(OPT_print_imm_hex));
3845f6dfa80SEric Astor 
3855f6dfa80SEric Astor     // Set up the AsmStreamer.
3865f6dfa80SEric Astor     std::unique_ptr<MCCodeEmitter> CE;
3878fee2ee9SEric Astor     if (InputArgs.hasArg(OPT_show_encoding))
3882aed07e9SShao-Ce SUN       CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
3895f6dfa80SEric Astor 
3905f6dfa80SEric Astor     std::unique_ptr<MCAsmBackend> MAB(
3915f6dfa80SEric Astor         TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
3925f6dfa80SEric Astor     auto FOut = std::make_unique<formatted_raw_ostream>(*OS);
3937f17b6b7SFangrui Song     Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), IP,
3947f17b6b7SFangrui Song                                            std::move(CE), std::move(MAB)));
3955f6dfa80SEric Astor 
3968fee2ee9SEric Astor   } else if (FileType == "null") {
3975f6dfa80SEric Astor     Str.reset(TheTarget->createNullStreamer(Ctx));
3988fee2ee9SEric Astor   } else if (FileType == "obj") {
3995f6dfa80SEric Astor     if (!Out->os().supportsSeeking()) {
4005f6dfa80SEric Astor       BOS = std::make_unique<buffer_ostream>(Out->os());
4015f6dfa80SEric Astor       OS = BOS.get();
4025f6dfa80SEric Astor     }
4035f6dfa80SEric Astor 
4042aed07e9SShao-Ce SUN     MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, Ctx);
4055f6dfa80SEric Astor     MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
4065f6dfa80SEric Astor     Str.reset(TheTarget->createMCObjectStreamer(
4075f6dfa80SEric Astor         TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
408b8220b98SFangrui Song         MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(CE),
409b8220b98SFangrui Song         *STI));
4108fee2ee9SEric Astor   } else {
4118fee2ee9SEric Astor     llvm_unreachable("Invalid file type!");
4125f6dfa80SEric Astor   }
4135f6dfa80SEric Astor 
41413f701b9SEric Astor   if (TheTriple.isOSBinFormatCOFF()) {
41513f701b9SEric Astor     // Emit an absolute @feat.00 symbol. This is a features bitfield read by
41613f701b9SEric Astor     // link.exe.
41713f701b9SEric Astor     int64_t Feat00Flags = 0x2;
41813f701b9SEric Astor     if (SafeSEH) {
41913f701b9SEric Astor       // According to the PE-COFF spec, the LSB of this value marks the object
42013f701b9SEric Astor       // for "registered SEH".  This means that all SEH handler entry points
42113f701b9SEric Astor       // must be registered in .sxdata.  Use of any unregistered handlers will
42213f701b9SEric Astor       // cause the process to terminate immediately.
42313f701b9SEric Astor       Feat00Flags |= 0x1;
42413f701b9SEric Astor     }
42513f701b9SEric Astor     MCSymbol *Feat00Sym = Ctx.getOrCreateSymbol("@feat.00");
42613f701b9SEric Astor     Feat00Sym->setRedefinable(true);
42713f701b9SEric Astor     Str->emitSymbolAttribute(Feat00Sym, MCSA_Global);
42813f701b9SEric Astor     Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx));
42913f701b9SEric Astor   }
43013f701b9SEric Astor 
4315f6dfa80SEric Astor   int Res = 1;
4328fee2ee9SEric Astor   if (InputArgs.hasArg(OPT_as_lex)) {
4338fee2ee9SEric Astor     // -as-lex; Lex only, and output a stream of tokens
4345f6dfa80SEric Astor     Res = AsLexInput(SrcMgr, *MAI, Out->os());
4358fee2ee9SEric Astor   } else {
4365f6dfa80SEric Astor     Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI,
4378fee2ee9SEric Astor                         *MCII, MCOptions, InputArgs);
4385f6dfa80SEric Astor   }
4395f6dfa80SEric Astor 
4405f6dfa80SEric Astor   // Keep output if no errors.
4415f6dfa80SEric Astor   if (Res == 0)
4425f6dfa80SEric Astor     Out->keep();
4435f6dfa80SEric Astor   return Res;
4445f6dfa80SEric Astor }
445