xref: /netbsd-src/external/apache2/llvm/dist/llvm/tools/llvm-ml/llvm-ml.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
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