Coverage Report

Created: 2019-03-22 08:08

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/tools/driver/cc1as_main.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- cc1as_main.cpp - Clang Assembler  ---------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This is the entry point to the clang -cc1as functionality, which implements
10
// the direct interface to the LLVM MC based assembler.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/Basic/Diagnostic.h"
15
#include "clang/Basic/DiagnosticOptions.h"
16
#include "clang/Driver/DriverDiagnostic.h"
17
#include "clang/Driver/Options.h"
18
#include "clang/Frontend/FrontendDiagnostic.h"
19
#include "clang/Frontend/TextDiagnosticPrinter.h"
20
#include "clang/Frontend/Utils.h"
21
#include "llvm/ADT/STLExtras.h"
22
#include "llvm/ADT/StringSwitch.h"
23
#include "llvm/ADT/Triple.h"
24
#include "llvm/IR/DataLayout.h"
25
#include "llvm/MC/MCAsmBackend.h"
26
#include "llvm/MC/MCAsmInfo.h"
27
#include "llvm/MC/MCCodeEmitter.h"
28
#include "llvm/MC/MCContext.h"
29
#include "llvm/MC/MCInstrInfo.h"
30
#include "llvm/MC/MCObjectFileInfo.h"
31
#include "llvm/MC/MCObjectWriter.h"
32
#include "llvm/MC/MCParser/MCAsmParser.h"
33
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
34
#include "llvm/MC/MCRegisterInfo.h"
35
#include "llvm/MC/MCSectionMachO.h"
36
#include "llvm/MC/MCStreamer.h"
37
#include "llvm/MC/MCSubtargetInfo.h"
38
#include "llvm/MC/MCTargetOptions.h"
39
#include "llvm/Option/Arg.h"
40
#include "llvm/Option/ArgList.h"
41
#include "llvm/Option/OptTable.h"
42
#include "llvm/Support/CommandLine.h"
43
#include "llvm/Support/ErrorHandling.h"
44
#include "llvm/Support/FileSystem.h"
45
#include "llvm/Support/FormattedStream.h"
46
#include "llvm/Support/Host.h"
47
#include "llvm/Support/MemoryBuffer.h"
48
#include "llvm/Support/Path.h"
49
#include "llvm/Support/Signals.h"
50
#include "llvm/Support/SourceMgr.h"
51
#include "llvm/Support/TargetRegistry.h"
52
#include "llvm/Support/TargetSelect.h"
53
#include "llvm/Support/Timer.h"
54
#include "llvm/Support/raw_ostream.h"
55
#include <memory>
56
#include <system_error>
57
using namespace clang;
58
using namespace clang::driver;
59
using namespace clang::driver::options;
60
using namespace llvm;
61
using namespace llvm::opt;
62
63
namespace {
64
65
/// Helper class for representing a single invocation of the assembler.
66
struct AssemblerInvocation {
67
  /// @name Target Options
68
  /// @{
69
70
  /// The name of the target triple to assemble for.
71
  std::string Triple;
72
73
  /// If given, the name of the target CPU to determine which instructions
74
  /// are legal.
75
  std::string CPU;
76
77
  /// The list of target specific features to enable or disable -- this should
78
  /// be a list of strings starting with '+' or '-'.
79
  std::vector<std::string> Features;
80
81
  /// The list of symbol definitions.
82
  std::vector<std::string> SymbolDefs;
83
84
  /// @}
85
  /// @name Language Options
86
  /// @{
87
88
  std::vector<std::string> IncludePaths;
89
  unsigned NoInitialTextSection : 1;
90
  unsigned SaveTemporaryLabels : 1;
91
  unsigned GenDwarfForAssembly : 1;
92
  unsigned RelaxELFRelocations : 1;
93
  unsigned DwarfVersion;
94
  std::string DwarfDebugFlags;
95
  std::string DwarfDebugProducer;
96
  std::string DebugCompilationDir;
97
  std::map<const std::string, const std::string> DebugPrefixMap;
98
  llvm::DebugCompressionType CompressDebugSections =
99
      llvm::DebugCompressionType::None;
100
  std::string MainFileName;
101
  std::string SplitDwarfFile;
102
103
  /// @}
104
  /// @name Frontend Options
105
  /// @{
106
107
  std::string InputFile;
108
  std::vector<std::string> LLVMArgs;
109
  std::string OutputPath;
110
  enum FileType {
111
    FT_Asm,  ///< Assembly (.s) output, transliterate mode.
112
    FT_Null, ///< No output, for timing purposes.
113
    FT_Obj   ///< Object file output.
114
  };
115
  FileType OutputType;
116
  unsigned ShowHelp : 1;
117
  unsigned ShowVersion : 1;
118
119
  /// @}
120
  /// @name Transliterate Options
121
  /// @{
122
123
  unsigned OutputAsmVariant;
124
  unsigned ShowEncoding : 1;
125
  unsigned ShowInst : 1;
126
127
  /// @}
128
  /// @name Assembler Options
129
  /// @{
130
131
  unsigned RelaxAll : 1;
132
  unsigned NoExecStack : 1;
133
  unsigned FatalWarnings : 1;
134
  unsigned IncrementalLinkerCompatible : 1;
135
  unsigned EmbedBitcode : 1;
136
137
  /// The name of the relocation model to use.
138
  std::string RelocationModel;
139
140
  /// @}
141
142
public:
143
744
  AssemblerInvocation() {
144
744
    Triple = "";
145
744
    NoInitialTextSection = 0;
146
744
    InputFile = "-";
147
744
    OutputPath = "-";
148
744
    OutputType = FT_Asm;
149
744
    OutputAsmVariant = 0;
150
744
    ShowInst = 0;
151
744
    ShowEncoding = 0;
152
744
    RelaxAll = 0;
153
744
    NoExecStack = 0;
154
744
    FatalWarnings = 0;
155
744
    IncrementalLinkerCompatible = 0;
156
744
    DwarfVersion = 0;
157
744
    EmbedBitcode = 0;
158
744
  }
159
160
  static bool CreateFromArgs(AssemblerInvocation &Res,
161
                             ArrayRef<const char *> Argv,
162
                             DiagnosticsEngine &Diags);
163
};
164
165
}
166
167
bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
168
                                         ArrayRef<const char *> Argv,
169
744
                                         DiagnosticsEngine &Diags) {
170
744
  bool Success = true;
171
744
172
744
  // Parse the arguments.
173
744
  std::unique_ptr<OptTable> OptTbl(createDriverOptTable());
174
744
175
744
  const unsigned IncludedFlagsBitmask = options::CC1AsOption;
176
744
  unsigned MissingArgIndex, MissingArgCount;
177
744
  InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount,
178
744
                                        IncludedFlagsBitmask);
179
744
180
744
  // Check for missing argument error.
181
744
  if (MissingArgCount) {
182
0
    Diags.Report(diag::err_drv_missing_argument)
183
0
        << Args.getArgString(MissingArgIndex) << MissingArgCount;
184
0
    Success = false;
185
0
  }
186
744
187
744
  // Issue errors on unknown arguments.
188
744
  for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
189
2
    auto ArgString = A->getAsString(Args);
190
2
    std::string Nearest;
191
2
    if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
192
0
      Diags.Report(diag::err_drv_unknown_argument) << ArgString;
193
2
    else
194
2
      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
195
2
          << ArgString << Nearest;
196
2
    Success = false;
197
2
  }
198
744
199
744
  // Construct the invocation.
200
744
201
744
  // Target Options
202
744
  Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
203
744
  Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
204
744
  Opts.Features = Args.getAllArgValues(OPT_target_feature);
205
744
206
744
  // Use the default target triple if unspecified.
207
744
  if (Opts.Triple.empty())
208
0
    Opts.Triple = llvm::sys::getDefaultTargetTriple();
209
744
210
744
  // Language Options
211
744
  Opts.IncludePaths = Args.getAllArgValues(OPT_I);
212
744
  Opts.NoInitialTextSection = Args.hasArg(OPT_n);
213
744
  Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
214
744
  // Any DebugInfoKind implies GenDwarfForAssembly.
215
744
  Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
216
744
217
744
  if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
218
2
                                     OPT_compress_debug_sections_EQ)) {
219
2
    if (A->getOption().getID() == OPT_compress_debug_sections) {
220
2
      // TODO: be more clever about the compression type auto-detection
221
2
      Opts.CompressDebugSections = llvm::DebugCompressionType::GNU;
222
2
    } else {
223
0
      Opts.CompressDebugSections =
224
0
          llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
225
0
              .Case("none", llvm::DebugCompressionType::None)
226
0
              .Case("zlib", llvm::DebugCompressionType::Z)
227
0
              .Case("zlib-gnu", llvm::DebugCompressionType::GNU)
228
0
              .Default(llvm::DebugCompressionType::None);
229
0
    }
230
2
  }
231
744
232
744
  Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
233
744
  Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
234
744
  Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
235
744
  Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer);
236
744
  Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
237
744
  Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
238
744
239
744
  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
240
0
    Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
241
744
242
744
  // Frontend Options
243
744
  if (Args.hasArg(OPT_INPUT)) {
244
743
    bool First = true;
245
743
    for (const Arg *A : Args.filtered(OPT_INPUT)) {
246
743
      if (First) {
247
743
        Opts.InputFile = A->getValue();
248
743
        First = false;
249
743
      } else {
250
0
        Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
251
0
        Success = false;
252
0
      }
253
743
    }
254
743
  }
255
744
  Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
256
744
  Opts.OutputPath = Args.getLastArgValue(OPT_o);
257
744
  Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
258
744
  if (Arg *A = Args.getLastArg(OPT_filetype)) {
259
743
    StringRef Name = A->getValue();
260
743
    unsigned OutputType = StringSwitch<unsigned>(Name)
261
743
      .Case("asm", FT_Asm)
262
743
      .Case("null", FT_Null)
263
743
      .Case("obj", FT_Obj)
264
743
      .Default(~0U);
265
743
    if (OutputType == ~0U) {
266
0
      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
267
0
      Success = false;
268
0
    } else
269
743
      Opts.OutputType = FileType(OutputType);
270
743
  }
271
744
  Opts.ShowHelp = Args.hasArg(OPT_help);
272
744
  Opts.ShowVersion = Args.hasArg(OPT_version);
273
744
274
744
  // Transliterate Options
275
744
  Opts.OutputAsmVariant =
276
744
      getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);
277
744
  Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);
278
744
  Opts.ShowInst = Args.hasArg(OPT_show_inst);
279
744
280
744
  // Assemble Options
281
744
  Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
282
744
  Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
283
744
  Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
284
744
  Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
285
744
  Opts.IncrementalLinkerCompatible =
286
744
      Args.hasArg(OPT_mincremental_linker_compatible);
287
744
  Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
288
744
289
744
  // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
290
744
  // EmbedBitcode behaves the same for all embed options for assembly files.
291
744
  if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
292
1
    Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())
293
1
                            .Case("all", 1)
294
1
                            .Case("bitcode", 1)
295
1
                            .Case("marker", 1)
296
1
                            .Default(0);
297
1
  }
298
744
299
744
  return Success;
300
744
}
301
302
static std::unique_ptr<raw_fd_ostream>
303
744
getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
304
744
  // Make sure that the Out file gets unlinked from the disk if we get a
305
744
  // SIGINT.
306
744
  if (Path != "-")
307
741
    sys::RemoveFileOnSignal(Path);
308
744
309
744
  std::error_code EC;
310
744
  auto Out = llvm::make_unique<raw_fd_ostream>(
311
744
      Path, EC, (Binary ? 
sys::fs::F_None739
:
sys::fs::F_Text5
));
312
744
  if (EC) {
313
0
    Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
314
0
    return nullptr;
315
0
  }
316
744
317
744
  return Out;
318
744
}
319
320
static bool ExecuteAssembler(AssemblerInvocation &Opts,
321
743
                             DiagnosticsEngine &Diags) {
322
743
  // Get the target specific parser.
323
743
  std::string Error;
324
743
  const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
325
743
  if (!TheTarget)
326
0
    return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
327
743
328
743
  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
329
743
      MemoryBuffer::getFileOrSTDIN(Opts.InputFile);
330
743
331
743
  if (std::error_code EC = Buffer.getError()) {
332
0
    Error = EC.message();
333
0
    return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
334
0
  }
335
743
336
743
  SourceMgr SrcMgr;
337
743
338
743
  // Tell SrcMgr about this buffer, which is what the parser will pick up.
339
743
  unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
340
743
341
743
  // Record the location of the include directories so that the lexer can find
342
743
  // it later.
343
743
  SrcMgr.setIncludeDirs(Opts.IncludePaths);
344
743
345
743
  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
346
743
  assert(MRI && "Unable to create target register info!");
347
743
348
743
  std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple));
349
743
  assert(MAI && "Unable to create target asm info!");
350
743
351
743
  // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
352
743
  // may be created with a combination of default and explicit settings.
353
743
  MAI->setCompressDebugSections(Opts.CompressDebugSections);
354
743
355
743
  MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
356
743
357
743
  bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
358
743
  if (Opts.OutputPath.empty())
359
3
    Opts.OutputPath = "-";
360
743
  std::unique_ptr<raw_fd_ostream> FDOS =
361
743
      getOutputStream(Opts.OutputPath, Diags, IsBinary);
362
743
  if (!FDOS)
363
0
    return true;
364
743
  std::unique_ptr<raw_fd_ostream> DwoOS;
365
743
  if (!Opts.SplitDwarfFile.empty())
366
1
    DwoOS = getOutputStream(Opts.SplitDwarfFile, Diags, IsBinary);
367
743
368
743
  // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
369
743
  // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
370
743
  std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
371
743
372
743
  MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
373
743
374
743
  bool PIC = false;
375
743
  if (Opts.RelocationModel == "static") {
376
165
    PIC = false;
377
578
  } else if (Opts.RelocationModel == "pic") {
378
578
    PIC = true;
379
578
  } else {
380
0
    assert(Opts.RelocationModel == "dynamic-no-pic" &&
381
0
           "Invalid PIC model!");
382
0
    PIC = false;
383
0
  }
384
743
385
743
  MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
386
743
  if (Opts.SaveTemporaryLabels)
387
0
    Ctx.setAllowTemporaryLabels(false);
388
743
  if (Opts.GenDwarfForAssembly)
389
20
    Ctx.setGenDwarfForAssembly(true);
390
743
  if (!Opts.DwarfDebugFlags.empty())
391
0
    Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
392
743
  if (!Opts.DwarfDebugProducer.empty())
393
730
    Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
394
743
  if (!Opts.DebugCompilationDir.empty())
395
730
    Ctx.setCompilationDir(Opts.DebugCompilationDir);
396
13
  else {
397
13
    // If no compilation dir is set, try to use the current directory.
398
13
    SmallString<128> CWD;
399
13
    if (!sys::fs::current_path(CWD))
400
13
      Ctx.setCompilationDir(CWD);
401
13
  }
402
743
  if (!Opts.DebugPrefixMap.empty())
403
0
    for (const auto &KV : Opts.DebugPrefixMap)
404
0
      Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
405
743
  if (!Opts.MainFileName.empty())
406
734
    Ctx.setMainFileName(StringRef(Opts.MainFileName));
407
743
  Ctx.setDwarfVersion(Opts.DwarfVersion);
408
743
  if (Opts.GenDwarfForAssembly)
409
20
    Ctx.setGenDwarfRootFile(Opts.InputFile,
410
20
                            SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());
411
743
412
743
  // Build up the feature string from the target feature list.
413
743
  std::string FS;
414
743
  if (!Opts.Features.empty()) {
415
459
    FS = Opts.Features[0];
416
2.18k
    for (unsigned i = 1, e = Opts.Features.size(); i != e; 
++i1.72k
)
417
1.72k
      FS += "," + Opts.Features[i];
418
459
  }
419
743
420
743
  std::unique_ptr<MCStreamer> Str;
421
743
422
743
  std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
423
743
  std::unique_ptr<MCSubtargetInfo> STI(
424
743
      TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
425
743
426
743
  raw_pwrite_stream *Out = FDOS.get();
427
743
  std::unique_ptr<buffer_ostream> BOS;
428
743
429
743
  // FIXME: There is a bit of code duplication with addPassesToEmitFile.
430
743
  if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
431
5
    MCInstPrinter *IP = TheTarget->createMCInstPrinter(
432
5
        llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
433
5
434
5
    std::unique_ptr<MCCodeEmitter> CE;
435
5
    if (Opts.ShowEncoding)
436
0
      CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
437
5
    MCTargetOptions MCOptions;
438
5
    std::unique_ptr<MCAsmBackend> MAB(
439
5
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
440
5
441
5
    auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out);
442
5
    Str.reset(TheTarget->createAsmStreamer(
443
5
        Ctx, std::move(FOut), /*asmverbose*/ true,
444
5
        /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
445
5
        Opts.ShowInst));
446
738
  } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
447
0
    Str.reset(createNullStreamer(Ctx));
448
738
  } else {
449
738
    assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
450
738
           "Invalid file type!");
451
738
    if (!FDOS->supportsSeeking()) {
452
1
      BOS = make_unique<buffer_ostream>(*FDOS);
453
1
      Out = BOS.get();
454
1
    }
455
738
456
738
    std::unique_ptr<MCCodeEmitter> CE(
457
738
        TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
458
738
    MCTargetOptions MCOptions;
459
738
    std::unique_ptr<MCAsmBackend> MAB(
460
738
        TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
461
738
    std::unique_ptr<MCObjectWriter> OW =
462
738
        DwoOS ? 
MAB->createDwoObjectWriter(*Out, *DwoOS)1
463
738
              : 
MAB->createObjectWriter(*Out)737
;
464
738
465
738
    Triple T(Opts.Triple);
466
738
    Str.reset(TheTarget->createMCObjectStreamer(
467
738
        T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
468
738
        Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
469
738
        /*DWARFMustBeAtTheEnd*/ true));
470
738
    Str.get()->InitSections(Opts.NoExecStack);
471
738
  }
472
743
473
743
  // When -fembed-bitcode is passed to clang_as, a 1-byte marker
474
743
  // is emitted in __LLVM,__asm section if the object file is MachO format.
475
743
  if (Opts.EmbedBitcode && Ctx.getObjectFileInfo()->getObjectFileType() ==
476
1
                               MCObjectFileInfo::IsMachO) {
477
1
    MCSection *AsmLabel = Ctx.getMachOSection(
478
1
        "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
479
1
    Str.get()->SwitchSection(AsmLabel);
480
1
    Str.get()->EmitZeros(1);
481
1
  }
482
743
483
743
  // Assembly to object compilation should leverage assembly info.
484
743
  Str->setUseAssemblerInfoForParsing(true);
485
743
486
743
  bool Failed = false;
487
743
488
743
  std::unique_ptr<MCAsmParser> Parser(
489
743
      createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
490
743
491
743
  // FIXME: init MCTargetOptions from sanitizer flags here.
492
743
  MCTargetOptions Options;
493
743
  std::unique_ptr<MCTargetAsmParser> TAP(
494
743
      TheTarget->createMCAsmParser(*STI, *Parser, *MCII, Options));
495
743
  if (!TAP)
496
0
    Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
497
743
498
743
  // Set values for symbols, if any.
499
743
  for (auto &S : Opts.SymbolDefs) {
500
0
    auto Pair = StringRef(S).split('=');
501
0
    auto Sym = Pair.first;
502
0
    auto Val = Pair.second;
503
0
    int64_t Value;
504
0
    // We have already error checked this in the driver.
505
0
    Val.getAsInteger(0, Value);
506
0
    Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);
507
0
  }
508
743
509
743
  if (!Failed) {
510
743
    Parser->setTargetParser(*TAP.get());
511
743
    Failed = Parser->Run(Opts.NoInitialTextSection);
512
743
  }
513
743
514
743
  // Close Streamer first.
515
743
  // It might have a reference to the output stream.
516
743
  Str.reset();
517
743
  // Close the output stream early.
518
743
  BOS.reset();
519
743
  FDOS.reset();
520
743
521
743
  // Delete output file if there were errors.
522
743
  if (Failed) {
523
0
    if (Opts.OutputPath != "-")
524
0
      sys::fs::remove(Opts.OutputPath);
525
0
    if (!Opts.SplitDwarfFile.empty() && Opts.SplitDwarfFile != "-")
526
0
      sys::fs::remove(Opts.SplitDwarfFile);
527
0
  }
528
743
529
743
  return Failed;
530
743
}
531
532
static void LLVMErrorHandler(void *UserData, const std::string &Message,
533
0
                             bool GenCrashDiag) {
534
0
  DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
535
0
536
0
  Diags.Report(diag::err_fe_error_backend) << Message;
537
0
538
0
  // We cannot recover from llvm errors.
539
0
  exit(1);
540
0
}
541
542
744
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
543
744
  // Initialize targets and assembly printers/parsers.
544
744
  InitializeAllTargetInfos();
545
744
  InitializeAllTargetMCs();
546
744
  InitializeAllAsmParsers();
547
744
548
744
  // Construct our diagnostic client.
549
744
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
550
744
  TextDiagnosticPrinter *DiagClient
551
744
    = new TextDiagnosticPrinter(errs(), &*DiagOpts);
552
744
  DiagClient->setPrefix("clang -cc1as");
553
744
  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
554
744
  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
555
744
556
744
  // Set an error handler, so that any LLVM backend diagnostics go through our
557
744
  // error handler.
558
744
  ScopedFatalErrorHandler FatalErrorHandler
559
744
    (LLVMErrorHandler, static_cast<void*>(&Diags));
560
744
561
744
  // Parse the arguments.
562
744
  AssemblerInvocation Asm;
563
744
  if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
564
1
    return 1;
565
743
566
743
  if (Asm.ShowHelp) {
567
0
    std::unique_ptr<OptTable> Opts(driver::createDriverOptTable());
568
0
    Opts->PrintHelp(llvm::outs(), "clang -cc1as [options] file...",
569
0
                    "Clang Integrated Assembler",
570
0
                    /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
571
0
                    /*ShowAllAliases=*/false);
572
0
    return 0;
573
0
  }
574
743
575
743
  // Honor -version.
576
743
  //
577
743
  // FIXME: Use a better -version message?
578
743
  if (Asm.ShowVersion) {
579
0
    llvm::cl::PrintVersionMessage();
580
0
    return 0;
581
0
  }
582
743
583
743
  // Honor -mllvm.
584
743
  //
585
743
  // FIXME: Remove this, one day.
586
743
  if (!Asm.LLVMArgs.empty()) {
587
652
    unsigned NumArgs = Asm.LLVMArgs.size();
588
652
    auto Args = llvm::make_unique<const char*[]>(NumArgs + 2);
589
652
    Args[0] = "clang (LLVM option parsing)";
590
1.30k
    for (unsigned i = 0; i != NumArgs; 
++i652
)
591
652
      Args[i + 1] = Asm.LLVMArgs[i].c_str();
592
652
    Args[NumArgs + 1] = nullptr;
593
652
    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
594
652
  }
595
743
596
743
  // Execute the invocation, unless there were parsing errors.
597
743
  bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
598
743
599
743
  // If any timers were active but haven't been destroyed yet, print their
600
743
  // results now.
601
743
  TimerGroup::printAll(errs());
602
743
603
743
  return !!Failed;
604
743
}