1*82d56013Sjoerg //===-- llvm-ml.cpp - masm-compatible assembler -----------------*- C++ -*-===//
2*82d56013Sjoerg //
3*82d56013Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*82d56013Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*82d56013Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*82d56013Sjoerg //
7*82d56013Sjoerg //===----------------------------------------------------------------------===//
8*82d56013Sjoerg //
9*82d56013Sjoerg // A simple driver around MasmParser; based on llvm-mc.
10*82d56013Sjoerg //
11*82d56013Sjoerg //===----------------------------------------------------------------------===//
12*82d56013Sjoerg
13*82d56013Sjoerg #include "llvm/ADT/StringSwitch.h"
14*82d56013Sjoerg #include "llvm/MC/MCAsmBackend.h"
15*82d56013Sjoerg #include "llvm/MC/MCAsmInfo.h"
16*82d56013Sjoerg #include "llvm/MC/MCCodeEmitter.h"
17*82d56013Sjoerg #include "llvm/MC/MCContext.h"
18*82d56013Sjoerg #include "llvm/MC/MCInstPrinter.h"
19*82d56013Sjoerg #include "llvm/MC/MCInstrInfo.h"
20*82d56013Sjoerg #include "llvm/MC/MCObjectFileInfo.h"
21*82d56013Sjoerg #include "llvm/MC/MCObjectWriter.h"
22*82d56013Sjoerg #include "llvm/MC/MCParser/AsmLexer.h"
23*82d56013Sjoerg #include "llvm/MC/MCParser/MCTargetAsmParser.h"
24*82d56013Sjoerg #include "llvm/MC/MCRegisterInfo.h"
25*82d56013Sjoerg #include "llvm/MC/MCStreamer.h"
26*82d56013Sjoerg #include "llvm/MC/MCSubtargetInfo.h"
27*82d56013Sjoerg #include "llvm/MC/MCTargetOptionsCommandFlags.h"
28*82d56013Sjoerg #include "llvm/Option/Arg.h"
29*82d56013Sjoerg #include "llvm/Option/ArgList.h"
30*82d56013Sjoerg #include "llvm/Option/Option.h"
31*82d56013Sjoerg #include "llvm/Support/Compression.h"
32*82d56013Sjoerg #include "llvm/Support/FileUtilities.h"
33*82d56013Sjoerg #include "llvm/Support/FormatVariadic.h"
34*82d56013Sjoerg #include "llvm/Support/FormattedStream.h"
35*82d56013Sjoerg #include "llvm/Support/Host.h"
36*82d56013Sjoerg #include "llvm/Support/InitLLVM.h"
37*82d56013Sjoerg #include "llvm/Support/MemoryBuffer.h"
38*82d56013Sjoerg #include "llvm/Support/Path.h"
39*82d56013Sjoerg #include "llvm/Support/SourceMgr.h"
40*82d56013Sjoerg #include "llvm/Support/TargetRegistry.h"
41*82d56013Sjoerg #include "llvm/Support/TargetSelect.h"
42*82d56013Sjoerg #include "llvm/Support/ToolOutputFile.h"
43*82d56013Sjoerg #include "llvm/Support/WithColor.h"
44*82d56013Sjoerg
45*82d56013Sjoerg using namespace llvm;
46*82d56013Sjoerg using namespace llvm::opt;
47*82d56013Sjoerg
48*82d56013Sjoerg namespace {
49*82d56013Sjoerg
50*82d56013Sjoerg enum ID {
51*82d56013Sjoerg OPT_INVALID = 0, // This is not an option ID.
52*82d56013Sjoerg #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
53*82d56013Sjoerg HELPTEXT, METAVAR, VALUES) \
54*82d56013Sjoerg OPT_##ID,
55*82d56013Sjoerg #include "Opts.inc"
56*82d56013Sjoerg #undef OPTION
57*82d56013Sjoerg };
58*82d56013Sjoerg
59*82d56013Sjoerg #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
60*82d56013Sjoerg #include "Opts.inc"
61*82d56013Sjoerg #undef PREFIX
62*82d56013Sjoerg
63*82d56013Sjoerg static const opt::OptTable::Info InfoTable[] = {
64*82d56013Sjoerg #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
65*82d56013Sjoerg HELPTEXT, METAVAR, VALUES) \
66*82d56013Sjoerg { \
67*82d56013Sjoerg PREFIX, NAME, HELPTEXT, \
68*82d56013Sjoerg METAVAR, OPT_##ID, opt::Option::KIND##Class, \
69*82d56013Sjoerg PARAM, FLAGS, OPT_##GROUP, \
70*82d56013Sjoerg OPT_##ALIAS, ALIASARGS, VALUES},
71*82d56013Sjoerg #include "Opts.inc"
72*82d56013Sjoerg #undef OPTION
73*82d56013Sjoerg };
74*82d56013Sjoerg
75*82d56013Sjoerg class MLOptTable : public opt::OptTable {
76*82d56013Sjoerg public:
MLOptTable()77*82d56013Sjoerg MLOptTable() : OptTable(InfoTable, /*IgnoreCase=*/false) {}
78*82d56013Sjoerg };
79*82d56013Sjoerg } // namespace
80*82d56013Sjoerg
GetTriple(StringRef ProgName,opt::InputArgList & Args)81*82d56013Sjoerg static Triple GetTriple(StringRef ProgName, opt::InputArgList &Args) {
82*82d56013Sjoerg // Figure out the target triple.
83*82d56013Sjoerg StringRef DefaultBitness = "32";
84*82d56013Sjoerg SmallString<255> Program = ProgName;
85*82d56013Sjoerg sys::path::replace_extension(Program, "");
86*82d56013Sjoerg if (Program.endswith("ml64"))
87*82d56013Sjoerg DefaultBitness = "64";
88*82d56013Sjoerg
89*82d56013Sjoerg StringRef TripleName =
90*82d56013Sjoerg StringSwitch<StringRef>(Args.getLastArgValue(OPT_bitness, DefaultBitness))
91*82d56013Sjoerg .Case("32", "i386-pc-windows")
92*82d56013Sjoerg .Case("64", "x86_64-pc-windows")
93*82d56013Sjoerg .Default("");
94*82d56013Sjoerg return Triple(Triple::normalize(TripleName));
95*82d56013Sjoerg }
96*82d56013Sjoerg
GetOutputStream(StringRef Path)97*82d56013Sjoerg static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path) {
98*82d56013Sjoerg std::error_code EC;
99*82d56013Sjoerg auto Out = std::make_unique<ToolOutputFile>(Path, EC, sys::fs::OF_None);
100*82d56013Sjoerg if (EC) {
101*82d56013Sjoerg WithColor::error() << EC.message() << '\n';
102*82d56013Sjoerg return nullptr;
103*82d56013Sjoerg }
104*82d56013Sjoerg
105*82d56013Sjoerg return Out;
106*82d56013Sjoerg }
107*82d56013Sjoerg
AsLexInput(SourceMgr & SrcMgr,MCAsmInfo & MAI,raw_ostream & OS)108*82d56013Sjoerg static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, raw_ostream &OS) {
109*82d56013Sjoerg AsmLexer Lexer(MAI);
110*82d56013Sjoerg Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer());
111*82d56013Sjoerg Lexer.setLexMasmIntegers(true);
112*82d56013Sjoerg Lexer.useMasmDefaultRadix(true);
113*82d56013Sjoerg Lexer.setLexMasmHexFloats(true);
114*82d56013Sjoerg Lexer.setLexMasmStrings(true);
115*82d56013Sjoerg
116*82d56013Sjoerg bool Error = false;
117*82d56013Sjoerg while (Lexer.Lex().isNot(AsmToken::Eof)) {
118*82d56013Sjoerg Lexer.getTok().dump(OS);
119*82d56013Sjoerg OS << "\n";
120*82d56013Sjoerg if (Lexer.getTok().getKind() == AsmToken::Error)
121*82d56013Sjoerg Error = true;
122*82d56013Sjoerg }
123*82d56013Sjoerg
124*82d56013Sjoerg return Error;
125*82d56013Sjoerg }
126*82d56013Sjoerg
AssembleInput(StringRef ProgName,const Target * TheTarget,SourceMgr & SrcMgr,MCContext & Ctx,MCStreamer & Str,MCAsmInfo & MAI,MCSubtargetInfo & STI,MCInstrInfo & MCII,MCTargetOptions & MCOptions,const opt::ArgList & InputArgs)127*82d56013Sjoerg static int AssembleInput(StringRef ProgName, const Target *TheTarget,
128*82d56013Sjoerg SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
129*82d56013Sjoerg MCAsmInfo &MAI, MCSubtargetInfo &STI,
130*82d56013Sjoerg MCInstrInfo &MCII, MCTargetOptions &MCOptions,
131*82d56013Sjoerg const opt::ArgList &InputArgs) {
132*82d56013Sjoerg std::unique_ptr<MCAsmParser> Parser(
133*82d56013Sjoerg createMCMasmParser(SrcMgr, Ctx, Str, MAI, 0));
134*82d56013Sjoerg std::unique_ptr<MCTargetAsmParser> TAP(
135*82d56013Sjoerg TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
136*82d56013Sjoerg
137*82d56013Sjoerg if (!TAP) {
138*82d56013Sjoerg WithColor::error(errs(), ProgName)
139*82d56013Sjoerg << "this target does not support assembly parsing.\n";
140*82d56013Sjoerg return 1;
141*82d56013Sjoerg }
142*82d56013Sjoerg
143*82d56013Sjoerg Parser->setShowParsedOperands(InputArgs.hasArg(OPT_show_inst_operands));
144*82d56013Sjoerg Parser->setTargetParser(*TAP);
145*82d56013Sjoerg Parser->getLexer().setLexMasmIntegers(true);
146*82d56013Sjoerg Parser->getLexer().useMasmDefaultRadix(true);
147*82d56013Sjoerg Parser->getLexer().setLexMasmHexFloats(true);
148*82d56013Sjoerg Parser->getLexer().setLexMasmStrings(true);
149*82d56013Sjoerg
150*82d56013Sjoerg auto Defines = InputArgs.getAllArgValues(OPT_define);
151*82d56013Sjoerg for (StringRef Define : Defines) {
152*82d56013Sjoerg const auto NameValue = Define.split('=');
153*82d56013Sjoerg StringRef Name = NameValue.first, Value = NameValue.second;
154*82d56013Sjoerg if (Parser->defineMacro(Name, Value)) {
155*82d56013Sjoerg WithColor::error(errs(), ProgName)
156*82d56013Sjoerg << "can't define macro '" << Name << "' = '" << Value << "'\n";
157*82d56013Sjoerg return 1;
158*82d56013Sjoerg }
159*82d56013Sjoerg }
160*82d56013Sjoerg
161*82d56013Sjoerg int Res = Parser->Run(/*NoInitialTextSection=*/true);
162*82d56013Sjoerg
163*82d56013Sjoerg return Res;
164*82d56013Sjoerg }
165*82d56013Sjoerg
main(int Argc,char ** Argv)166*82d56013Sjoerg int main(int Argc, char **Argv) {
167*82d56013Sjoerg InitLLVM X(Argc, Argv);
168*82d56013Sjoerg StringRef ProgName = sys::path::filename(Argv[0]);
169*82d56013Sjoerg
170*82d56013Sjoerg // Initialize targets and assembly printers/parsers.
171*82d56013Sjoerg llvm::InitializeAllTargetInfos();
172*82d56013Sjoerg llvm::InitializeAllTargetMCs();
173*82d56013Sjoerg llvm::InitializeAllAsmParsers();
174*82d56013Sjoerg llvm::InitializeAllDisassemblers();
175*82d56013Sjoerg
176*82d56013Sjoerg MLOptTable T;
177*82d56013Sjoerg unsigned MissingArgIndex, MissingArgCount;
178*82d56013Sjoerg ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, Argc - 1);
179*82d56013Sjoerg opt::InputArgList InputArgs =
180*82d56013Sjoerg T.ParseArgs(ArgsArr, MissingArgIndex, MissingArgCount);
181*82d56013Sjoerg
182*82d56013Sjoerg std::string InputFilename;
183*82d56013Sjoerg for (auto *Arg : InputArgs.filtered(OPT_INPUT)) {
184*82d56013Sjoerg std::string ArgString = Arg->getAsString(InputArgs);
185*82d56013Sjoerg if (ArgString == "-" || StringRef(ArgString).endswith(".asm")) {
186*82d56013Sjoerg if (!InputFilename.empty()) {
187*82d56013Sjoerg WithColor::warning(errs(), ProgName)
188*82d56013Sjoerg << "does not support multiple assembly files in one command; "
189*82d56013Sjoerg << "ignoring '" << InputFilename << "'\n";
190*82d56013Sjoerg }
191*82d56013Sjoerg InputFilename = ArgString;
192*82d56013Sjoerg } else {
193*82d56013Sjoerg std::string Diag;
194*82d56013Sjoerg raw_string_ostream OS(Diag);
195*82d56013Sjoerg OS << "invalid option '" << ArgString << "'";
196*82d56013Sjoerg
197*82d56013Sjoerg std::string Nearest;
198*82d56013Sjoerg if (T.findNearest(ArgString, Nearest) < 2)
199*82d56013Sjoerg OS << ", did you mean '" << Nearest << "'?";
200*82d56013Sjoerg
201*82d56013Sjoerg WithColor::error(errs(), ProgName) << OS.str() << '\n';
202*82d56013Sjoerg exit(1);
203*82d56013Sjoerg }
204*82d56013Sjoerg }
205*82d56013Sjoerg for (auto *Arg : InputArgs.filtered(OPT_assembly_file)) {
206*82d56013Sjoerg if (!InputFilename.empty()) {
207*82d56013Sjoerg WithColor::warning(errs(), ProgName)
208*82d56013Sjoerg << "does not support multiple assembly files in one command; "
209*82d56013Sjoerg << "ignoring '" << InputFilename << "'\n";
210*82d56013Sjoerg }
211*82d56013Sjoerg InputFilename = Arg->getAsString(InputArgs);
212*82d56013Sjoerg }
213*82d56013Sjoerg
214*82d56013Sjoerg for (auto *Arg : InputArgs.filtered(OPT_unsupported_Group)) {
215*82d56013Sjoerg WithColor::warning(errs(), ProgName)
216*82d56013Sjoerg << "ignoring unsupported '" << Arg->getOption().getName()
217*82d56013Sjoerg << "' option\n";
218*82d56013Sjoerg }
219*82d56013Sjoerg
220*82d56013Sjoerg if (InputArgs.hasArg(OPT_help)) {
221*82d56013Sjoerg std::string Usage = llvm::formatv("{0} [ /options ] file", ProgName).str();
222*82d56013Sjoerg T.PrintHelp(outs(), Usage.c_str(), "LLVM MASM Assembler",
223*82d56013Sjoerg /*ShowHidden=*/false);
224*82d56013Sjoerg return 0;
225*82d56013Sjoerg } else if (InputFilename.empty()) {
226*82d56013Sjoerg outs() << "USAGE: " << ProgName << " [ /options ] file\n"
227*82d56013Sjoerg << "Run \"" << ProgName << " /?\" or \"" << ProgName
228*82d56013Sjoerg << " /help\" for more info.\n";
229*82d56013Sjoerg return 0;
230*82d56013Sjoerg }
231*82d56013Sjoerg
232*82d56013Sjoerg MCTargetOptions MCOptions;
233*82d56013Sjoerg MCOptions.AssemblyLanguage = "masm";
234*82d56013Sjoerg MCOptions.MCFatalWarnings = InputArgs.hasArg(OPT_fatal_warnings);
235*82d56013Sjoerg
236*82d56013Sjoerg Triple TheTriple = GetTriple(ProgName, InputArgs);
237*82d56013Sjoerg std::string Error;
238*82d56013Sjoerg const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple, Error);
239*82d56013Sjoerg if (!TheTarget) {
240*82d56013Sjoerg WithColor::error(errs(), ProgName) << Error;
241*82d56013Sjoerg return 1;
242*82d56013Sjoerg }
243*82d56013Sjoerg const std::string &TripleName = TheTriple.getTriple();
244*82d56013Sjoerg
245*82d56013Sjoerg bool SafeSEH = InputArgs.hasArg(OPT_safeseh);
246*82d56013Sjoerg if (SafeSEH && !(TheTriple.isArch32Bit() && TheTriple.isX86())) {
247*82d56013Sjoerg WithColor::warning()
248*82d56013Sjoerg << "/safeseh applies only to 32-bit X86 platforms; ignoring.\n";
249*82d56013Sjoerg SafeSEH = false;
250*82d56013Sjoerg }
251*82d56013Sjoerg
252*82d56013Sjoerg ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
253*82d56013Sjoerg MemoryBuffer::getFileOrSTDIN(InputFilename);
254*82d56013Sjoerg if (std::error_code EC = BufferPtr.getError()) {
255*82d56013Sjoerg WithColor::error(errs(), ProgName)
256*82d56013Sjoerg << InputFilename << ": " << EC.message() << '\n';
257*82d56013Sjoerg return 1;
258*82d56013Sjoerg }
259*82d56013Sjoerg
260*82d56013Sjoerg SourceMgr SrcMgr;
261*82d56013Sjoerg
262*82d56013Sjoerg // Tell SrcMgr about this buffer, which is what the parser will pick up.
263*82d56013Sjoerg SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
264*82d56013Sjoerg
265*82d56013Sjoerg // Record the location of the include directories so that the lexer can find
266*82d56013Sjoerg // it later.
267*82d56013Sjoerg SrcMgr.setIncludeDirs(InputArgs.getAllArgValues(OPT_include_path));
268*82d56013Sjoerg
269*82d56013Sjoerg std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
270*82d56013Sjoerg assert(MRI && "Unable to create target register info!");
271*82d56013Sjoerg
272*82d56013Sjoerg std::unique_ptr<MCAsmInfo> MAI(
273*82d56013Sjoerg TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
274*82d56013Sjoerg assert(MAI && "Unable to create target asm info!");
275*82d56013Sjoerg
276*82d56013Sjoerg MAI->setPreserveAsmComments(InputArgs.hasArg(OPT_preserve_comments));
277*82d56013Sjoerg
278*82d56013Sjoerg std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(
279*82d56013Sjoerg TripleName, /*CPU=*/"", /*Features=*/""));
280*82d56013Sjoerg assert(STI && "Unable to create subtarget info!");
281*82d56013Sjoerg
282*82d56013Sjoerg // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
283*82d56013Sjoerg // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
284*82d56013Sjoerg MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
285*82d56013Sjoerg std::unique_ptr<MCObjectFileInfo> MOFI(TheTarget->createMCObjectFileInfo(
286*82d56013Sjoerg Ctx, /*PIC=*/false, /*LargeCodeModel=*/true));
287*82d56013Sjoerg Ctx.setObjectFileInfo(MOFI.get());
288*82d56013Sjoerg
289*82d56013Sjoerg if (InputArgs.hasArg(OPT_save_temp_labels))
290*82d56013Sjoerg Ctx.setAllowTemporaryLabels(false);
291*82d56013Sjoerg
292*82d56013Sjoerg // Set compilation information.
293*82d56013Sjoerg SmallString<128> CWD;
294*82d56013Sjoerg if (!sys::fs::current_path(CWD))
295*82d56013Sjoerg Ctx.setCompilationDir(CWD);
296*82d56013Sjoerg Ctx.setMainFileName(InputFilename);
297*82d56013Sjoerg
298*82d56013Sjoerg StringRef FileType = InputArgs.getLastArgValue(OPT_filetype, "obj");
299*82d56013Sjoerg SmallString<255> DefaultOutputFilename;
300*82d56013Sjoerg if (InputArgs.hasArg(OPT_as_lex)) {
301*82d56013Sjoerg DefaultOutputFilename = "-";
302*82d56013Sjoerg } else {
303*82d56013Sjoerg DefaultOutputFilename = InputFilename;
304*82d56013Sjoerg sys::path::replace_extension(DefaultOutputFilename, FileType);
305*82d56013Sjoerg }
306*82d56013Sjoerg const StringRef OutputFilename =
307*82d56013Sjoerg InputArgs.getLastArgValue(OPT_output_file, DefaultOutputFilename);
308*82d56013Sjoerg std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename);
309*82d56013Sjoerg if (!Out)
310*82d56013Sjoerg return 1;
311*82d56013Sjoerg
312*82d56013Sjoerg std::unique_ptr<buffer_ostream> BOS;
313*82d56013Sjoerg raw_pwrite_stream *OS = &Out->os();
314*82d56013Sjoerg std::unique_ptr<MCStreamer> Str;
315*82d56013Sjoerg
316*82d56013Sjoerg std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
317*82d56013Sjoerg assert(MCII && "Unable to create instruction info!");
318*82d56013Sjoerg
319*82d56013Sjoerg MCInstPrinter *IP = nullptr;
320*82d56013Sjoerg if (FileType == "s") {
321*82d56013Sjoerg const bool OutputATTAsm = InputArgs.hasArg(OPT_output_att_asm);
322*82d56013Sjoerg const unsigned OutputAsmVariant = OutputATTAsm ? 0U // ATT dialect
323*82d56013Sjoerg : 1U; // Intel dialect
324*82d56013Sjoerg IP = TheTarget->createMCInstPrinter(TheTriple, OutputAsmVariant, *MAI,
325*82d56013Sjoerg *MCII, *MRI);
326*82d56013Sjoerg
327*82d56013Sjoerg if (!IP) {
328*82d56013Sjoerg WithColor::error()
329*82d56013Sjoerg << "unable to create instruction printer for target triple '"
330*82d56013Sjoerg << TheTriple.normalize() << "' with "
331*82d56013Sjoerg << (OutputATTAsm ? "ATT" : "Intel") << " assembly variant.\n";
332*82d56013Sjoerg return 1;
333*82d56013Sjoerg }
334*82d56013Sjoerg
335*82d56013Sjoerg // Set the display preference for hex vs. decimal immediates.
336*82d56013Sjoerg IP->setPrintImmHex(InputArgs.hasArg(OPT_print_imm_hex));
337*82d56013Sjoerg
338*82d56013Sjoerg // Set up the AsmStreamer.
339*82d56013Sjoerg std::unique_ptr<MCCodeEmitter> CE;
340*82d56013Sjoerg if (InputArgs.hasArg(OPT_show_encoding))
341*82d56013Sjoerg CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
342*82d56013Sjoerg
343*82d56013Sjoerg std::unique_ptr<MCAsmBackend> MAB(
344*82d56013Sjoerg TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
345*82d56013Sjoerg auto FOut = std::make_unique<formatted_raw_ostream>(*OS);
346*82d56013Sjoerg Str.reset(TheTarget->createAsmStreamer(
347*82d56013Sjoerg Ctx, std::move(FOut), /*asmverbose*/ true,
348*82d56013Sjoerg /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
349*82d56013Sjoerg InputArgs.hasArg(OPT_show_inst)));
350*82d56013Sjoerg
351*82d56013Sjoerg } else if (FileType == "null") {
352*82d56013Sjoerg Str.reset(TheTarget->createNullStreamer(Ctx));
353*82d56013Sjoerg } else if (FileType == "obj") {
354*82d56013Sjoerg if (!Out->os().supportsSeeking()) {
355*82d56013Sjoerg BOS = std::make_unique<buffer_ostream>(Out->os());
356*82d56013Sjoerg OS = BOS.get();
357*82d56013Sjoerg }
358*82d56013Sjoerg
359*82d56013Sjoerg MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
360*82d56013Sjoerg MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
361*82d56013Sjoerg Str.reset(TheTarget->createMCObjectStreamer(
362*82d56013Sjoerg TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
363*82d56013Sjoerg MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(CE), *STI,
364*82d56013Sjoerg MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
365*82d56013Sjoerg /*DWARFMustBeAtTheEnd*/ false));
366*82d56013Sjoerg } else {
367*82d56013Sjoerg llvm_unreachable("Invalid file type!");
368*82d56013Sjoerg }
369*82d56013Sjoerg
370*82d56013Sjoerg if (TheTriple.isOSBinFormatCOFF()) {
371*82d56013Sjoerg // Emit an absolute @feat.00 symbol. This is a features bitfield read by
372*82d56013Sjoerg // link.exe.
373*82d56013Sjoerg int64_t Feat00Flags = 0x2;
374*82d56013Sjoerg if (SafeSEH) {
375*82d56013Sjoerg // According to the PE-COFF spec, the LSB of this value marks the object
376*82d56013Sjoerg // for "registered SEH". This means that all SEH handler entry points
377*82d56013Sjoerg // must be registered in .sxdata. Use of any unregistered handlers will
378*82d56013Sjoerg // cause the process to terminate immediately.
379*82d56013Sjoerg Feat00Flags |= 0x1;
380*82d56013Sjoerg }
381*82d56013Sjoerg MCSymbol *Feat00Sym = Ctx.getOrCreateSymbol("@feat.00");
382*82d56013Sjoerg Feat00Sym->setRedefinable(true);
383*82d56013Sjoerg Str->emitSymbolAttribute(Feat00Sym, MCSA_Global);
384*82d56013Sjoerg Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx));
385*82d56013Sjoerg }
386*82d56013Sjoerg
387*82d56013Sjoerg // Use Assembler information for parsing.
388*82d56013Sjoerg Str->setUseAssemblerInfoForParsing(true);
389*82d56013Sjoerg
390*82d56013Sjoerg int Res = 1;
391*82d56013Sjoerg if (InputArgs.hasArg(OPT_as_lex)) {
392*82d56013Sjoerg // -as-lex; Lex only, and output a stream of tokens
393*82d56013Sjoerg Res = AsLexInput(SrcMgr, *MAI, Out->os());
394*82d56013Sjoerg } else {
395*82d56013Sjoerg Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI,
396*82d56013Sjoerg *MCII, MCOptions, InputArgs);
397*82d56013Sjoerg }
398*82d56013Sjoerg
399*82d56013Sjoerg // Keep output if no errors.
400*82d56013Sjoerg if (Res == 0)
401*82d56013Sjoerg Out->keep();
402*82d56013Sjoerg return Res;
403*82d56013Sjoerg }
404