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