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