xref: /minix3/external/bsd/llvm/dist/clang/tools/driver/cc1as_main.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This is the entry point to the clang -cc1as functionality, which implements
11f4a2713aSLionel Sambuc // the direct interface to the LLVM MC based assembler.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/DiagnosticOptions.h"
17f4a2713aSLionel Sambuc #include "clang/Driver/DriverDiagnostic.h"
18f4a2713aSLionel Sambuc #include "clang/Driver/Options.h"
19f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendDiagnostic.h"
20f4a2713aSLionel Sambuc #include "clang/Frontend/TextDiagnosticPrinter.h"
21f4a2713aSLionel Sambuc #include "clang/Frontend/Utils.h"
22f4a2713aSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
23f4a2713aSLionel Sambuc #include "llvm/ADT/Triple.h"
24f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h"
25f4a2713aSLionel Sambuc #include "llvm/MC/MCAsmBackend.h"
26f4a2713aSLionel Sambuc #include "llvm/MC/MCAsmInfo.h"
27f4a2713aSLionel Sambuc #include "llvm/MC/MCCodeEmitter.h"
28f4a2713aSLionel Sambuc #include "llvm/MC/MCContext.h"
29f4a2713aSLionel Sambuc #include "llvm/MC/MCInstrInfo.h"
30f4a2713aSLionel Sambuc #include "llvm/MC/MCObjectFileInfo.h"
31f4a2713aSLionel Sambuc #include "llvm/MC/MCParser/MCAsmParser.h"
32f4a2713aSLionel Sambuc #include "llvm/MC/MCRegisterInfo.h"
33f4a2713aSLionel Sambuc #include "llvm/MC/MCStreamer.h"
34f4a2713aSLionel Sambuc #include "llvm/MC/MCSubtargetInfo.h"
35f4a2713aSLionel Sambuc #include "llvm/MC/MCTargetAsmParser.h"
36*0a6a1f1dSLionel Sambuc #include "llvm/MC/MCTargetOptions.h"
37f4a2713aSLionel Sambuc #include "llvm/Option/Arg.h"
38f4a2713aSLionel Sambuc #include "llvm/Option/ArgList.h"
39f4a2713aSLionel Sambuc #include "llvm/Option/OptTable.h"
40f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
41f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
42f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
43f4a2713aSLionel Sambuc #include "llvm/Support/FormattedStream.h"
44f4a2713aSLionel Sambuc #include "llvm/Support/Host.h"
45f4a2713aSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
46f4a2713aSLionel Sambuc #include "llvm/Support/MemoryBuffer.h"
47f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
48f4a2713aSLionel Sambuc #include "llvm/Support/PrettyStackTrace.h"
49f4a2713aSLionel Sambuc #include "llvm/Support/Signals.h"
50f4a2713aSLionel Sambuc #include "llvm/Support/SourceMgr.h"
51f4a2713aSLionel Sambuc #include "llvm/Support/TargetRegistry.h"
52f4a2713aSLionel Sambuc #include "llvm/Support/TargetSelect.h"
53f4a2713aSLionel Sambuc #include "llvm/Support/Timer.h"
54f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
55*0a6a1f1dSLionel Sambuc #include <memory>
56*0a6a1f1dSLionel Sambuc #include <system_error>
57f4a2713aSLionel Sambuc using namespace clang;
58f4a2713aSLionel Sambuc using namespace clang::driver;
59*0a6a1f1dSLionel Sambuc using namespace clang::driver::options;
60f4a2713aSLionel Sambuc using namespace llvm;
61f4a2713aSLionel Sambuc using namespace llvm::opt;
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc namespace {
64f4a2713aSLionel Sambuc 
65f4a2713aSLionel Sambuc /// \brief Helper class for representing a single invocation of the assembler.
66f4a2713aSLionel Sambuc struct AssemblerInvocation {
67f4a2713aSLionel Sambuc   /// @name Target Options
68f4a2713aSLionel Sambuc   /// @{
69f4a2713aSLionel Sambuc 
70f4a2713aSLionel Sambuc   /// The name of the target triple to assemble for.
71f4a2713aSLionel Sambuc   std::string Triple;
72f4a2713aSLionel Sambuc 
73f4a2713aSLionel Sambuc   /// If given, the name of the target CPU to determine which instructions
74f4a2713aSLionel Sambuc   /// are legal.
75f4a2713aSLionel Sambuc   std::string CPU;
76f4a2713aSLionel Sambuc 
77f4a2713aSLionel Sambuc   /// The list of target specific features to enable or disable -- this should
78f4a2713aSLionel Sambuc   /// be a list of strings starting with '+' or '-'.
79f4a2713aSLionel Sambuc   std::vector<std::string> Features;
80f4a2713aSLionel Sambuc 
81f4a2713aSLionel Sambuc   /// @}
82f4a2713aSLionel Sambuc   /// @name Language Options
83f4a2713aSLionel Sambuc   /// @{
84f4a2713aSLionel Sambuc 
85f4a2713aSLionel Sambuc   std::vector<std::string> IncludePaths;
86f4a2713aSLionel Sambuc   unsigned NoInitialTextSection : 1;
87f4a2713aSLionel Sambuc   unsigned SaveTemporaryLabels : 1;
88f4a2713aSLionel Sambuc   unsigned GenDwarfForAssembly : 1;
89*0a6a1f1dSLionel Sambuc   unsigned CompressDebugSections : 1;
90*0a6a1f1dSLionel Sambuc   unsigned DwarfVersion;
91f4a2713aSLionel Sambuc   std::string DwarfDebugFlags;
92f4a2713aSLionel Sambuc   std::string DwarfDebugProducer;
93f4a2713aSLionel Sambuc   std::string DebugCompilationDir;
94f4a2713aSLionel Sambuc   std::string MainFileName;
95f4a2713aSLionel Sambuc 
96f4a2713aSLionel Sambuc   /// @}
97f4a2713aSLionel Sambuc   /// @name Frontend Options
98f4a2713aSLionel Sambuc   /// @{
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc   std::string InputFile;
101f4a2713aSLionel Sambuc   std::vector<std::string> LLVMArgs;
102f4a2713aSLionel Sambuc   std::string OutputPath;
103f4a2713aSLionel Sambuc   enum FileType {
104f4a2713aSLionel Sambuc     FT_Asm,  ///< Assembly (.s) output, transliterate mode.
105f4a2713aSLionel Sambuc     FT_Null, ///< No output, for timing purposes.
106f4a2713aSLionel Sambuc     FT_Obj   ///< Object file output.
107f4a2713aSLionel Sambuc   };
108f4a2713aSLionel Sambuc   FileType OutputType;
109f4a2713aSLionel Sambuc   unsigned ShowHelp : 1;
110f4a2713aSLionel Sambuc   unsigned ShowVersion : 1;
111f4a2713aSLionel Sambuc 
112f4a2713aSLionel Sambuc   /// @}
113f4a2713aSLionel Sambuc   /// @name Transliterate Options
114f4a2713aSLionel Sambuc   /// @{
115f4a2713aSLionel Sambuc 
116f4a2713aSLionel Sambuc   unsigned OutputAsmVariant;
117f4a2713aSLionel Sambuc   unsigned ShowEncoding : 1;
118f4a2713aSLionel Sambuc   unsigned ShowInst : 1;
119f4a2713aSLionel Sambuc 
120f4a2713aSLionel Sambuc   /// @}
121f4a2713aSLionel Sambuc   /// @name Assembler Options
122f4a2713aSLionel Sambuc   /// @{
123f4a2713aSLionel Sambuc 
124f4a2713aSLionel Sambuc   unsigned RelaxAll : 1;
125f4a2713aSLionel Sambuc   unsigned NoExecStack : 1;
126*0a6a1f1dSLionel Sambuc   unsigned FatalWarnings : 1;
127f4a2713aSLionel Sambuc 
128f4a2713aSLionel Sambuc   /// @}
129f4a2713aSLionel Sambuc 
130f4a2713aSLionel Sambuc public:
AssemblerInvocation__anonb83ca9d10111::AssemblerInvocation131f4a2713aSLionel Sambuc   AssemblerInvocation() {
132f4a2713aSLionel Sambuc     Triple = "";
133f4a2713aSLionel Sambuc     NoInitialTextSection = 0;
134f4a2713aSLionel Sambuc     InputFile = "-";
135f4a2713aSLionel Sambuc     OutputPath = "-";
136f4a2713aSLionel Sambuc     OutputType = FT_Asm;
137f4a2713aSLionel Sambuc     OutputAsmVariant = 0;
138f4a2713aSLionel Sambuc     ShowInst = 0;
139f4a2713aSLionel Sambuc     ShowEncoding = 0;
140f4a2713aSLionel Sambuc     RelaxAll = 0;
141f4a2713aSLionel Sambuc     NoExecStack = 0;
142*0a6a1f1dSLionel Sambuc     FatalWarnings = 0;
143*0a6a1f1dSLionel Sambuc     DwarfVersion = 3;
144f4a2713aSLionel Sambuc   }
145f4a2713aSLionel Sambuc 
146*0a6a1f1dSLionel Sambuc   static bool CreateFromArgs(AssemblerInvocation &Res,
147*0a6a1f1dSLionel Sambuc                              ArrayRef<const char *> Argv,
148*0a6a1f1dSLionel Sambuc                              DiagnosticsEngine &Diags);
149f4a2713aSLionel Sambuc };
150f4a2713aSLionel Sambuc 
151f4a2713aSLionel Sambuc }
152f4a2713aSLionel Sambuc 
CreateFromArgs(AssemblerInvocation & Opts,ArrayRef<const char * > Argv,DiagnosticsEngine & Diags)153f4a2713aSLionel Sambuc bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
154*0a6a1f1dSLionel Sambuc                                          ArrayRef<const char *> Argv,
155f4a2713aSLionel Sambuc                                          DiagnosticsEngine &Diags) {
156f4a2713aSLionel Sambuc   bool Success = true;
157f4a2713aSLionel Sambuc 
158f4a2713aSLionel Sambuc   // Parse the arguments.
159*0a6a1f1dSLionel Sambuc   std::unique_ptr<OptTable> OptTbl(createDriverOptTable());
160*0a6a1f1dSLionel Sambuc 
161*0a6a1f1dSLionel Sambuc   const unsigned IncludedFlagsBitmask = options::CC1AsOption;
162f4a2713aSLionel Sambuc   unsigned MissingArgIndex, MissingArgCount;
163*0a6a1f1dSLionel Sambuc   std::unique_ptr<InputArgList> Args(
164*0a6a1f1dSLionel Sambuc       OptTbl->ParseArgs(Argv.begin(), Argv.end(), MissingArgIndex, MissingArgCount,
165*0a6a1f1dSLionel Sambuc                         IncludedFlagsBitmask));
166f4a2713aSLionel Sambuc 
167f4a2713aSLionel Sambuc   // Check for missing argument error.
168f4a2713aSLionel Sambuc   if (MissingArgCount) {
169f4a2713aSLionel Sambuc     Diags.Report(diag::err_drv_missing_argument)
170f4a2713aSLionel Sambuc         << Args->getArgString(MissingArgIndex) << MissingArgCount;
171f4a2713aSLionel Sambuc     Success = false;
172f4a2713aSLionel Sambuc   }
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc   // Issue errors on unknown arguments.
175*0a6a1f1dSLionel Sambuc   for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
176*0a6a1f1dSLionel Sambuc                     ie = Args->filtered_end();
177*0a6a1f1dSLionel Sambuc        it != ie; ++it) {
178f4a2713aSLionel Sambuc     Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
179f4a2713aSLionel Sambuc     Success = false;
180f4a2713aSLionel Sambuc   }
181f4a2713aSLionel Sambuc 
182f4a2713aSLionel Sambuc   // Construct the invocation.
183f4a2713aSLionel Sambuc 
184f4a2713aSLionel Sambuc   // Target Options
185f4a2713aSLionel Sambuc   Opts.Triple = llvm::Triple::normalize(Args->getLastArgValue(OPT_triple));
186f4a2713aSLionel Sambuc   Opts.CPU = Args->getLastArgValue(OPT_target_cpu);
187f4a2713aSLionel Sambuc   Opts.Features = Args->getAllArgValues(OPT_target_feature);
188f4a2713aSLionel Sambuc 
189f4a2713aSLionel Sambuc   // Use the default target triple if unspecified.
190f4a2713aSLionel Sambuc   if (Opts.Triple.empty())
191f4a2713aSLionel Sambuc     Opts.Triple = llvm::sys::getDefaultTargetTriple();
192f4a2713aSLionel Sambuc 
193f4a2713aSLionel Sambuc   // Language Options
194f4a2713aSLionel Sambuc   Opts.IncludePaths = Args->getAllArgValues(OPT_I);
195f4a2713aSLionel Sambuc   Opts.NoInitialTextSection = Args->hasArg(OPT_n);
196f4a2713aSLionel Sambuc   Opts.SaveTemporaryLabels = Args->hasArg(OPT_msave_temp_labels);
197*0a6a1f1dSLionel Sambuc   Opts.GenDwarfForAssembly = Args->hasArg(OPT_g_Flag);
198*0a6a1f1dSLionel Sambuc   Opts.CompressDebugSections = Args->hasArg(OPT_compress_debug_sections);
199*0a6a1f1dSLionel Sambuc   if (Args->hasArg(OPT_gdwarf_2))
200*0a6a1f1dSLionel Sambuc     Opts.DwarfVersion = 2;
201*0a6a1f1dSLionel Sambuc   if (Args->hasArg(OPT_gdwarf_3))
202*0a6a1f1dSLionel Sambuc     Opts.DwarfVersion = 3;
203*0a6a1f1dSLionel Sambuc   if (Args->hasArg(OPT_gdwarf_4))
204*0a6a1f1dSLionel Sambuc     Opts.DwarfVersion = 4;
205f4a2713aSLionel Sambuc   Opts.DwarfDebugFlags = Args->getLastArgValue(OPT_dwarf_debug_flags);
206f4a2713aSLionel Sambuc   Opts.DwarfDebugProducer = Args->getLastArgValue(OPT_dwarf_debug_producer);
207f4a2713aSLionel Sambuc   Opts.DebugCompilationDir = Args->getLastArgValue(OPT_fdebug_compilation_dir);
208f4a2713aSLionel Sambuc   Opts.MainFileName = Args->getLastArgValue(OPT_main_file_name);
209f4a2713aSLionel Sambuc 
210f4a2713aSLionel Sambuc   // Frontend Options
211f4a2713aSLionel Sambuc   if (Args->hasArg(OPT_INPUT)) {
212f4a2713aSLionel Sambuc     bool First = true;
213f4a2713aSLionel Sambuc     for (arg_iterator it = Args->filtered_begin(OPT_INPUT),
214f4a2713aSLionel Sambuc            ie = Args->filtered_end(); it != ie; ++it, First=false) {
215f4a2713aSLionel Sambuc       const Arg *A = it;
216f4a2713aSLionel Sambuc       if (First)
217f4a2713aSLionel Sambuc         Opts.InputFile = A->getValue();
218f4a2713aSLionel Sambuc       else {
219f4a2713aSLionel Sambuc         Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
220f4a2713aSLionel Sambuc         Success = false;
221f4a2713aSLionel Sambuc       }
222f4a2713aSLionel Sambuc     }
223f4a2713aSLionel Sambuc   }
224f4a2713aSLionel Sambuc   Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
225f4a2713aSLionel Sambuc   Opts.OutputPath = Args->getLastArgValue(OPT_o);
226f4a2713aSLionel Sambuc   if (Arg *A = Args->getLastArg(OPT_filetype)) {
227f4a2713aSLionel Sambuc     StringRef Name = A->getValue();
228f4a2713aSLionel Sambuc     unsigned OutputType = StringSwitch<unsigned>(Name)
229f4a2713aSLionel Sambuc       .Case("asm", FT_Asm)
230f4a2713aSLionel Sambuc       .Case("null", FT_Null)
231f4a2713aSLionel Sambuc       .Case("obj", FT_Obj)
232f4a2713aSLionel Sambuc       .Default(~0U);
233f4a2713aSLionel Sambuc     if (OutputType == ~0U) {
234f4a2713aSLionel Sambuc       Diags.Report(diag::err_drv_invalid_value)
235f4a2713aSLionel Sambuc         << A->getAsString(*Args) << Name;
236f4a2713aSLionel Sambuc       Success = false;
237f4a2713aSLionel Sambuc     } else
238f4a2713aSLionel Sambuc       Opts.OutputType = FileType(OutputType);
239f4a2713aSLionel Sambuc   }
240f4a2713aSLionel Sambuc   Opts.ShowHelp = Args->hasArg(OPT_help);
241f4a2713aSLionel Sambuc   Opts.ShowVersion = Args->hasArg(OPT_version);
242f4a2713aSLionel Sambuc 
243f4a2713aSLionel Sambuc   // Transliterate Options
244f4a2713aSLionel Sambuc   Opts.OutputAsmVariant =
245f4a2713aSLionel Sambuc       getLastArgIntValue(*Args.get(), OPT_output_asm_variant, 0, Diags);
246f4a2713aSLionel Sambuc   Opts.ShowEncoding = Args->hasArg(OPT_show_encoding);
247f4a2713aSLionel Sambuc   Opts.ShowInst = Args->hasArg(OPT_show_inst);
248f4a2713aSLionel Sambuc 
249f4a2713aSLionel Sambuc   // Assemble Options
250f4a2713aSLionel Sambuc   Opts.RelaxAll = Args->hasArg(OPT_mrelax_all);
251f4a2713aSLionel Sambuc   Opts.NoExecStack = Args->hasArg(OPT_mno_exec_stack);
252*0a6a1f1dSLionel Sambuc   Opts.FatalWarnings =  Args->hasArg(OPT_massembler_fatal_warnings);
253f4a2713aSLionel Sambuc 
254f4a2713aSLionel Sambuc   return Success;
255f4a2713aSLionel Sambuc }
256f4a2713aSLionel Sambuc 
GetOutputStream(AssemblerInvocation & Opts,DiagnosticsEngine & Diags,bool Binary)257f4a2713aSLionel Sambuc static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
258f4a2713aSLionel Sambuc                                               DiagnosticsEngine &Diags,
259f4a2713aSLionel Sambuc                                               bool Binary) {
260f4a2713aSLionel Sambuc   if (Opts.OutputPath.empty())
261f4a2713aSLionel Sambuc     Opts.OutputPath = "-";
262f4a2713aSLionel Sambuc 
263f4a2713aSLionel Sambuc   // Make sure that the Out file gets unlinked from the disk if we get a
264f4a2713aSLionel Sambuc   // SIGINT.
265f4a2713aSLionel Sambuc   if (Opts.OutputPath != "-")
266f4a2713aSLionel Sambuc     sys::RemoveFileOnSignal(Opts.OutputPath);
267f4a2713aSLionel Sambuc 
268*0a6a1f1dSLionel Sambuc   std::error_code EC;
269*0a6a1f1dSLionel Sambuc   raw_fd_ostream *Out = new raw_fd_ostream(
270*0a6a1f1dSLionel Sambuc       Opts.OutputPath, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text));
271*0a6a1f1dSLionel Sambuc   if (EC) {
272*0a6a1f1dSLionel Sambuc     Diags.Report(diag::err_fe_unable_to_open_output) << Opts.OutputPath
273*0a6a1f1dSLionel Sambuc                                                      << EC.message();
274*0a6a1f1dSLionel Sambuc     delete Out;
275*0a6a1f1dSLionel Sambuc     return nullptr;
276f4a2713aSLionel Sambuc   }
277f4a2713aSLionel Sambuc 
278f4a2713aSLionel Sambuc   return new formatted_raw_ostream(*Out, formatted_raw_ostream::DELETE_STREAM);
279f4a2713aSLionel Sambuc }
280f4a2713aSLionel Sambuc 
ExecuteAssembler(AssemblerInvocation & Opts,DiagnosticsEngine & Diags)281f4a2713aSLionel Sambuc static bool ExecuteAssembler(AssemblerInvocation &Opts,
282f4a2713aSLionel Sambuc                              DiagnosticsEngine &Diags) {
283f4a2713aSLionel Sambuc   // Get the target specific parser.
284f4a2713aSLionel Sambuc   std::string Error;
285*0a6a1f1dSLionel Sambuc   const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
286*0a6a1f1dSLionel Sambuc   if (!TheTarget)
287*0a6a1f1dSLionel Sambuc     return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
288f4a2713aSLionel Sambuc 
289*0a6a1f1dSLionel Sambuc   ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
290*0a6a1f1dSLionel Sambuc       MemoryBuffer::getFileOrSTDIN(Opts.InputFile);
291*0a6a1f1dSLionel Sambuc 
292*0a6a1f1dSLionel Sambuc   if (std::error_code EC = Buffer.getError()) {
293*0a6a1f1dSLionel Sambuc     Error = EC.message();
294*0a6a1f1dSLionel Sambuc     return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
295f4a2713aSLionel Sambuc   }
296f4a2713aSLionel Sambuc 
297f4a2713aSLionel Sambuc   SourceMgr SrcMgr;
298f4a2713aSLionel Sambuc 
299f4a2713aSLionel Sambuc   // Tell SrcMgr about this buffer, which is what the parser will pick up.
300*0a6a1f1dSLionel Sambuc   SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
301f4a2713aSLionel Sambuc 
302f4a2713aSLionel Sambuc   // Record the location of the include directories so that the lexer can find
303f4a2713aSLionel Sambuc   // it later.
304f4a2713aSLionel Sambuc   SrcMgr.setIncludeDirs(Opts.IncludePaths);
305f4a2713aSLionel Sambuc 
306*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
307f4a2713aSLionel Sambuc   assert(MRI && "Unable to create target register info!");
308f4a2713aSLionel Sambuc 
309*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
310f4a2713aSLionel Sambuc   assert(MAI && "Unable to create target asm info!");
311f4a2713aSLionel Sambuc 
312*0a6a1f1dSLionel Sambuc   // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
313*0a6a1f1dSLionel Sambuc   // may be created with a combination of default and explicit settings.
314*0a6a1f1dSLionel Sambuc   if (Opts.CompressDebugSections)
315*0a6a1f1dSLionel Sambuc     MAI->setCompressDebugSections(true);
316*0a6a1f1dSLionel Sambuc 
317f4a2713aSLionel Sambuc   bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
318*0a6a1f1dSLionel Sambuc   std::unique_ptr<formatted_raw_ostream> Out(
319*0a6a1f1dSLionel Sambuc       GetOutputStream(Opts, Diags, IsBinary));
320f4a2713aSLionel Sambuc   if (!Out)
321*0a6a1f1dSLionel Sambuc     return true;
322f4a2713aSLionel Sambuc 
323f4a2713aSLionel Sambuc   // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
324f4a2713aSLionel Sambuc   // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
325*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
326*0a6a1f1dSLionel Sambuc 
327f4a2713aSLionel Sambuc   MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
328f4a2713aSLionel Sambuc   // FIXME: Assembler behavior can change with -static.
329f4a2713aSLionel Sambuc   MOFI->InitMCObjectFileInfo(Opts.Triple,
330f4a2713aSLionel Sambuc                              Reloc::Default, CodeModel::Default, Ctx);
331f4a2713aSLionel Sambuc   if (Opts.SaveTemporaryLabels)
332f4a2713aSLionel Sambuc     Ctx.setAllowTemporaryLabels(false);
333f4a2713aSLionel Sambuc   if (Opts.GenDwarfForAssembly)
334f4a2713aSLionel Sambuc     Ctx.setGenDwarfForAssembly(true);
335f4a2713aSLionel Sambuc   if (!Opts.DwarfDebugFlags.empty())
336f4a2713aSLionel Sambuc     Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
337f4a2713aSLionel Sambuc   if (!Opts.DwarfDebugProducer.empty())
338f4a2713aSLionel Sambuc     Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
339f4a2713aSLionel Sambuc   if (!Opts.DebugCompilationDir.empty())
340f4a2713aSLionel Sambuc     Ctx.setCompilationDir(Opts.DebugCompilationDir);
341f4a2713aSLionel Sambuc   if (!Opts.MainFileName.empty())
342f4a2713aSLionel Sambuc     Ctx.setMainFileName(StringRef(Opts.MainFileName));
343*0a6a1f1dSLionel Sambuc   Ctx.setDwarfVersion(Opts.DwarfVersion);
344f4a2713aSLionel Sambuc 
345f4a2713aSLionel Sambuc   // Build up the feature string from the target feature list.
346f4a2713aSLionel Sambuc   std::string FS;
347f4a2713aSLionel Sambuc   if (!Opts.Features.empty()) {
348f4a2713aSLionel Sambuc     FS = Opts.Features[0];
349f4a2713aSLionel Sambuc     for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i)
350f4a2713aSLionel Sambuc       FS += "," + Opts.Features[i];
351f4a2713aSLionel Sambuc   }
352f4a2713aSLionel Sambuc 
353*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCStreamer> Str;
354f4a2713aSLionel Sambuc 
355*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
356*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCSubtargetInfo> STI(
357*0a6a1f1dSLionel Sambuc       TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
358f4a2713aSLionel Sambuc 
359f4a2713aSLionel Sambuc   // FIXME: There is a bit of code duplication with addPassesToEmitFile.
360f4a2713aSLionel Sambuc   if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
361f4a2713aSLionel Sambuc     MCInstPrinter *IP =
362f4a2713aSLionel Sambuc       TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI, *MCII, *MRI,
363f4a2713aSLionel Sambuc                                      *STI);
364*0a6a1f1dSLionel Sambuc     MCCodeEmitter *CE = nullptr;
365*0a6a1f1dSLionel Sambuc     MCAsmBackend *MAB = nullptr;
366f4a2713aSLionel Sambuc     if (Opts.ShowEncoding) {
367f4a2713aSLionel Sambuc       CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
368f4a2713aSLionel Sambuc       MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU);
369f4a2713aSLionel Sambuc     }
370f4a2713aSLionel Sambuc     Str.reset(TheTarget->createAsmStreamer(Ctx, *Out, /*asmverbose*/true,
371f4a2713aSLionel Sambuc                                            /*useDwarfDirectory*/ true,
372f4a2713aSLionel Sambuc                                            IP, CE, MAB,
373f4a2713aSLionel Sambuc                                            Opts.ShowInst));
374f4a2713aSLionel Sambuc   } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
375f4a2713aSLionel Sambuc     Str.reset(createNullStreamer(Ctx));
376f4a2713aSLionel Sambuc   } else {
377f4a2713aSLionel Sambuc     assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
378f4a2713aSLionel Sambuc            "Invalid file type!");
379f4a2713aSLionel Sambuc     MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
380f4a2713aSLionel Sambuc     MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
381f4a2713aSLionel Sambuc                                                       Opts.CPU);
382f4a2713aSLionel Sambuc     Str.reset(TheTarget->createMCObjectStreamer(Opts.Triple, Ctx, *MAB, *Out,
383*0a6a1f1dSLionel Sambuc                                                 CE, *STI, Opts.RelaxAll));
384*0a6a1f1dSLionel Sambuc     Str.get()->InitSections(Opts.NoExecStack);
385f4a2713aSLionel Sambuc   }
386f4a2713aSLionel Sambuc 
387*0a6a1f1dSLionel Sambuc   bool Failed = false;
388f4a2713aSLionel Sambuc 
389*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCAsmParser> Parser(
390*0a6a1f1dSLionel Sambuc       createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
391*0a6a1f1dSLionel Sambuc 
392*0a6a1f1dSLionel Sambuc   // FIXME: init MCTargetOptions from sanitizer flags here.
393*0a6a1f1dSLionel Sambuc   MCTargetOptions Options;
394*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCTargetAsmParser> TAP(
395*0a6a1f1dSLionel Sambuc       TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options));
396*0a6a1f1dSLionel Sambuc   if (!TAP)
397*0a6a1f1dSLionel Sambuc     Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
398*0a6a1f1dSLionel Sambuc 
399*0a6a1f1dSLionel Sambuc   if (!Failed) {
400f4a2713aSLionel Sambuc     Parser->setTargetParser(*TAP.get());
401*0a6a1f1dSLionel Sambuc     Failed = Parser->Run(Opts.NoInitialTextSection);
402*0a6a1f1dSLionel Sambuc   }
403f4a2713aSLionel Sambuc 
404*0a6a1f1dSLionel Sambuc   // Close the output stream early.
405*0a6a1f1dSLionel Sambuc   Out.reset();
406f4a2713aSLionel Sambuc 
407*0a6a1f1dSLionel Sambuc   // Delete output file if there were errors.
408*0a6a1f1dSLionel Sambuc   if (Failed && Opts.OutputPath != "-")
409f4a2713aSLionel Sambuc     sys::fs::remove(Opts.OutputPath);
410f4a2713aSLionel Sambuc 
411*0a6a1f1dSLionel Sambuc   return Failed;
412f4a2713aSLionel Sambuc }
413f4a2713aSLionel Sambuc 
LLVMErrorHandler(void * UserData,const std::string & Message,bool GenCrashDiag)414f4a2713aSLionel Sambuc static void LLVMErrorHandler(void *UserData, const std::string &Message,
415f4a2713aSLionel Sambuc                              bool GenCrashDiag) {
416f4a2713aSLionel Sambuc   DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
417f4a2713aSLionel Sambuc 
418f4a2713aSLionel Sambuc   Diags.Report(diag::err_fe_error_backend) << Message;
419f4a2713aSLionel Sambuc 
420f4a2713aSLionel Sambuc   // We cannot recover from llvm errors.
421f4a2713aSLionel Sambuc   exit(1);
422f4a2713aSLionel Sambuc }
423f4a2713aSLionel Sambuc 
cc1as_main(ArrayRef<const char * > Argv,const char * Argv0,void * MainAddr)424*0a6a1f1dSLionel Sambuc int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
425f4a2713aSLionel Sambuc   // Print a stack trace if we signal out.
426f4a2713aSLionel Sambuc   sys::PrintStackTraceOnErrorSignal();
427*0a6a1f1dSLionel Sambuc   PrettyStackTraceProgram X(Argv.size(), Argv.data());
428f4a2713aSLionel Sambuc   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
429f4a2713aSLionel Sambuc 
430f4a2713aSLionel Sambuc   // Initialize targets and assembly printers/parsers.
431f4a2713aSLionel Sambuc   InitializeAllTargetInfos();
432f4a2713aSLionel Sambuc   InitializeAllTargetMCs();
433f4a2713aSLionel Sambuc   InitializeAllAsmParsers();
434f4a2713aSLionel Sambuc 
435f4a2713aSLionel Sambuc   // Construct our diagnostic client.
436f4a2713aSLionel Sambuc   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
437f4a2713aSLionel Sambuc   TextDiagnosticPrinter *DiagClient
438f4a2713aSLionel Sambuc     = new TextDiagnosticPrinter(errs(), &*DiagOpts);
439f4a2713aSLionel Sambuc   DiagClient->setPrefix("clang -cc1as");
440f4a2713aSLionel Sambuc   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
441f4a2713aSLionel Sambuc   DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
442f4a2713aSLionel Sambuc 
443f4a2713aSLionel Sambuc   // Set an error handler, so that any LLVM backend diagnostics go through our
444f4a2713aSLionel Sambuc   // error handler.
445f4a2713aSLionel Sambuc   ScopedFatalErrorHandler FatalErrorHandler
446f4a2713aSLionel Sambuc     (LLVMErrorHandler, static_cast<void*>(&Diags));
447f4a2713aSLionel Sambuc 
448f4a2713aSLionel Sambuc   // Parse the arguments.
449f4a2713aSLionel Sambuc   AssemblerInvocation Asm;
450*0a6a1f1dSLionel Sambuc   if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
451f4a2713aSLionel Sambuc     return 1;
452f4a2713aSLionel Sambuc 
453f4a2713aSLionel Sambuc   if (Asm.ShowHelp) {
454*0a6a1f1dSLionel Sambuc     std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
455*0a6a1f1dSLionel Sambuc     Opts->PrintHelp(llvm::outs(), "clang -cc1as", "Clang Integrated Assembler",
456*0a6a1f1dSLionel Sambuc                     /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0);
457f4a2713aSLionel Sambuc     return 0;
458f4a2713aSLionel Sambuc   }
459f4a2713aSLionel Sambuc 
460f4a2713aSLionel Sambuc   // Honor -version.
461f4a2713aSLionel Sambuc   //
462f4a2713aSLionel Sambuc   // FIXME: Use a better -version message?
463f4a2713aSLionel Sambuc   if (Asm.ShowVersion) {
464f4a2713aSLionel Sambuc     llvm::cl::PrintVersionMessage();
465f4a2713aSLionel Sambuc     return 0;
466f4a2713aSLionel Sambuc   }
467f4a2713aSLionel Sambuc 
468f4a2713aSLionel Sambuc   // Honor -mllvm.
469f4a2713aSLionel Sambuc   //
470f4a2713aSLionel Sambuc   // FIXME: Remove this, one day.
471f4a2713aSLionel Sambuc   if (!Asm.LLVMArgs.empty()) {
472f4a2713aSLionel Sambuc     unsigned NumArgs = Asm.LLVMArgs.size();
473f4a2713aSLionel Sambuc     const char **Args = new const char*[NumArgs + 2];
474f4a2713aSLionel Sambuc     Args[0] = "clang (LLVM option parsing)";
475f4a2713aSLionel Sambuc     for (unsigned i = 0; i != NumArgs; ++i)
476f4a2713aSLionel Sambuc       Args[i + 1] = Asm.LLVMArgs[i].c_str();
477*0a6a1f1dSLionel Sambuc     Args[NumArgs + 1] = nullptr;
478f4a2713aSLionel Sambuc     llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
479f4a2713aSLionel Sambuc   }
480f4a2713aSLionel Sambuc 
481f4a2713aSLionel Sambuc   // Execute the invocation, unless there were parsing errors.
482*0a6a1f1dSLionel Sambuc   bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
483f4a2713aSLionel Sambuc 
484f4a2713aSLionel Sambuc   // If any timers were active but haven't been destroyed yet, print their
485f4a2713aSLionel Sambuc   // results now.
486f4a2713aSLionel Sambuc   TimerGroup::printAll(errs());
487f4a2713aSLionel Sambuc 
488*0a6a1f1dSLionel Sambuc   return !!Failed;
489f4a2713aSLionel Sambuc }
490*0a6a1f1dSLionel Sambuc 
491