Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/tools/driver/cc1as_main.cpp
35236 views
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/StringExtras.h"
23
#include "llvm/ADT/StringSwitch.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/MC/TargetRegistry.h"
40
#include "llvm/Option/Arg.h"
41
#include "llvm/Option/ArgList.h"
42
#include "llvm/Option/OptTable.h"
43
#include "llvm/Support/CommandLine.h"
44
#include "llvm/Support/ErrorHandling.h"
45
#include "llvm/Support/FileSystem.h"
46
#include "llvm/Support/FormattedStream.h"
47
#include "llvm/Support/MemoryBuffer.h"
48
#include "llvm/Support/Path.h"
49
#include "llvm/Support/Process.h"
50
#include "llvm/Support/Signals.h"
51
#include "llvm/Support/SourceMgr.h"
52
#include "llvm/Support/TargetSelect.h"
53
#include "llvm/Support/Timer.h"
54
#include "llvm/Support/raw_ostream.h"
55
#include "llvm/TargetParser/Host.h"
56
#include "llvm/TargetParser/Triple.h"
57
#include <memory>
58
#include <optional>
59
#include <system_error>
60
using namespace clang;
61
using namespace clang::driver;
62
using namespace clang::driver::options;
63
using namespace llvm;
64
using namespace llvm::opt;
65
66
namespace {
67
68
/// Helper class for representing a single invocation of the assembler.
69
struct AssemblerInvocation {
70
/// @name Target Options
71
/// @{
72
73
/// The name of the target triple to assemble for.
74
std::string Triple;
75
76
/// If given, the name of the target CPU to determine which instructions
77
/// are legal.
78
std::string CPU;
79
80
/// The list of target specific features to enable or disable -- this should
81
/// be a list of strings starting with '+' or '-'.
82
std::vector<std::string> Features;
83
84
/// The list of symbol definitions.
85
std::vector<std::string> SymbolDefs;
86
87
/// @}
88
/// @name Language Options
89
/// @{
90
91
std::vector<std::string> IncludePaths;
92
LLVM_PREFERRED_TYPE(bool)
93
unsigned NoInitialTextSection : 1;
94
LLVM_PREFERRED_TYPE(bool)
95
unsigned SaveTemporaryLabels : 1;
96
LLVM_PREFERRED_TYPE(bool)
97
unsigned GenDwarfForAssembly : 1;
98
LLVM_PREFERRED_TYPE(bool)
99
unsigned RelaxELFRelocations : 1;
100
LLVM_PREFERRED_TYPE(bool)
101
unsigned SSE2AVX : 1;
102
LLVM_PREFERRED_TYPE(bool)
103
unsigned Dwarf64 : 1;
104
unsigned DwarfVersion;
105
std::string DwarfDebugFlags;
106
std::string DwarfDebugProducer;
107
std::string DebugCompilationDir;
108
llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;
109
llvm::DebugCompressionType CompressDebugSections =
110
llvm::DebugCompressionType::None;
111
std::string MainFileName;
112
std::string SplitDwarfOutput;
113
114
/// @}
115
/// @name Frontend Options
116
/// @{
117
118
std::string InputFile;
119
std::vector<std::string> LLVMArgs;
120
std::string OutputPath;
121
enum FileType {
122
FT_Asm, ///< Assembly (.s) output, transliterate mode.
123
FT_Null, ///< No output, for timing purposes.
124
FT_Obj ///< Object file output.
125
};
126
FileType OutputType;
127
LLVM_PREFERRED_TYPE(bool)
128
unsigned ShowHelp : 1;
129
LLVM_PREFERRED_TYPE(bool)
130
unsigned ShowVersion : 1;
131
132
/// @}
133
/// @name Transliterate Options
134
/// @{
135
136
unsigned OutputAsmVariant;
137
LLVM_PREFERRED_TYPE(bool)
138
unsigned ShowEncoding : 1;
139
LLVM_PREFERRED_TYPE(bool)
140
unsigned ShowInst : 1;
141
142
/// @}
143
/// @name Assembler Options
144
/// @{
145
146
LLVM_PREFERRED_TYPE(bool)
147
unsigned RelaxAll : 1;
148
LLVM_PREFERRED_TYPE(bool)
149
unsigned NoExecStack : 1;
150
LLVM_PREFERRED_TYPE(bool)
151
unsigned FatalWarnings : 1;
152
LLVM_PREFERRED_TYPE(bool)
153
unsigned NoWarn : 1;
154
LLVM_PREFERRED_TYPE(bool)
155
unsigned NoTypeCheck : 1;
156
LLVM_PREFERRED_TYPE(bool)
157
unsigned IncrementalLinkerCompatible : 1;
158
LLVM_PREFERRED_TYPE(bool)
159
unsigned EmbedBitcode : 1;
160
161
/// Whether to emit DWARF unwind info.
162
EmitDwarfUnwindType EmitDwarfUnwind;
163
164
// Whether to emit compact-unwind for non-canonical entries.
165
// Note: maybe overriden by other constraints.
166
LLVM_PREFERRED_TYPE(bool)
167
unsigned EmitCompactUnwindNonCanonical : 1;
168
169
LLVM_PREFERRED_TYPE(bool)
170
unsigned Crel : 1;
171
172
/// The name of the relocation model to use.
173
std::string RelocationModel;
174
175
/// The ABI targeted by the backend. Specified using -target-abi. Empty
176
/// otherwise.
177
std::string TargetABI;
178
179
/// Darwin target variant triple, the variant of the deployment target
180
/// for which the code is being compiled.
181
std::optional<llvm::Triple> DarwinTargetVariantTriple;
182
183
/// The version of the darwin target variant SDK which was used during the
184
/// compilation
185
llvm::VersionTuple DarwinTargetVariantSDKVersion;
186
187
/// The name of a file to use with \c .secure_log_unique directives.
188
std::string AsSecureLogFile;
189
/// @}
190
191
public:
192
AssemblerInvocation() {
193
Triple = "";
194
NoInitialTextSection = 0;
195
InputFile = "-";
196
OutputPath = "-";
197
OutputType = FT_Asm;
198
OutputAsmVariant = 0;
199
ShowInst = 0;
200
ShowEncoding = 0;
201
RelaxAll = 0;
202
SSE2AVX = 0;
203
NoExecStack = 0;
204
FatalWarnings = 0;
205
NoWarn = 0;
206
NoTypeCheck = 0;
207
IncrementalLinkerCompatible = 0;
208
Dwarf64 = 0;
209
DwarfVersion = 0;
210
EmbedBitcode = 0;
211
EmitDwarfUnwind = EmitDwarfUnwindType::Default;
212
EmitCompactUnwindNonCanonical = false;
213
Crel = false;
214
}
215
216
static bool CreateFromArgs(AssemblerInvocation &Res,
217
ArrayRef<const char *> Argv,
218
DiagnosticsEngine &Diags);
219
};
220
221
}
222
223
bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
224
ArrayRef<const char *> Argv,
225
DiagnosticsEngine &Diags) {
226
bool Success = true;
227
228
// Parse the arguments.
229
const OptTable &OptTbl = getDriverOptTable();
230
231
llvm::opt::Visibility VisibilityMask(options::CC1AsOption);
232
unsigned MissingArgIndex, MissingArgCount;
233
InputArgList Args =
234
OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, VisibilityMask);
235
236
// Check for missing argument error.
237
if (MissingArgCount) {
238
Diags.Report(diag::err_drv_missing_argument)
239
<< Args.getArgString(MissingArgIndex) << MissingArgCount;
240
Success = false;
241
}
242
243
// Issue errors on unknown arguments.
244
for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
245
auto ArgString = A->getAsString(Args);
246
std::string Nearest;
247
if (OptTbl.findNearest(ArgString, Nearest, VisibilityMask) > 1)
248
Diags.Report(diag::err_drv_unknown_argument) << ArgString;
249
else
250
Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
251
<< ArgString << Nearest;
252
Success = false;
253
}
254
255
// Construct the invocation.
256
257
// Target Options
258
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
259
if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))
260
Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());
261
if (Arg *A = Args.getLastArg(OPT_darwin_target_variant_sdk_version_EQ)) {
262
VersionTuple Version;
263
if (Version.tryParse(A->getValue()))
264
Diags.Report(diag::err_drv_invalid_value)
265
<< A->getAsString(Args) << A->getValue();
266
else
267
Opts.DarwinTargetVariantSDKVersion = Version;
268
}
269
270
Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
271
Opts.Features = Args.getAllArgValues(OPT_target_feature);
272
273
// Use the default target triple if unspecified.
274
if (Opts.Triple.empty())
275
Opts.Triple = llvm::sys::getDefaultTargetTriple();
276
277
// Language Options
278
Opts.IncludePaths = Args.getAllArgValues(OPT_I);
279
Opts.NoInitialTextSection = Args.hasArg(OPT_n);
280
Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
281
// Any DebugInfoKind implies GenDwarfForAssembly.
282
Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
283
284
if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections_EQ)) {
285
Opts.CompressDebugSections =
286
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
287
.Case("none", llvm::DebugCompressionType::None)
288
.Case("zlib", llvm::DebugCompressionType::Zlib)
289
.Case("zstd", llvm::DebugCompressionType::Zstd)
290
.Default(llvm::DebugCompressionType::None);
291
}
292
293
Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no);
294
Opts.SSE2AVX = Args.hasArg(OPT_msse2avx);
295
if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32))
296
Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64);
297
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
298
Opts.DwarfDebugFlags =
299
std::string(Args.getLastArgValue(OPT_dwarf_debug_flags));
300
Opts.DwarfDebugProducer =
301
std::string(Args.getLastArgValue(OPT_dwarf_debug_producer));
302
if (const Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
303
options::OPT_fdebug_compilation_dir_EQ))
304
Opts.DebugCompilationDir = A->getValue();
305
Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name));
306
307
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
308
auto Split = StringRef(Arg).split('=');
309
Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
310
}
311
312
// Frontend Options
313
if (Args.hasArg(OPT_INPUT)) {
314
bool First = true;
315
for (const Arg *A : Args.filtered(OPT_INPUT)) {
316
if (First) {
317
Opts.InputFile = A->getValue();
318
First = false;
319
} else {
320
Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
321
Success = false;
322
}
323
}
324
}
325
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
326
Opts.OutputPath = std::string(Args.getLastArgValue(OPT_o));
327
Opts.SplitDwarfOutput =
328
std::string(Args.getLastArgValue(OPT_split_dwarf_output));
329
if (Arg *A = Args.getLastArg(OPT_filetype)) {
330
StringRef Name = A->getValue();
331
unsigned OutputType = StringSwitch<unsigned>(Name)
332
.Case("asm", FT_Asm)
333
.Case("null", FT_Null)
334
.Case("obj", FT_Obj)
335
.Default(~0U);
336
if (OutputType == ~0U) {
337
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
338
Success = false;
339
} else
340
Opts.OutputType = FileType(OutputType);
341
}
342
Opts.ShowHelp = Args.hasArg(OPT_help);
343
Opts.ShowVersion = Args.hasArg(OPT_version);
344
345
// Transliterate Options
346
Opts.OutputAsmVariant =
347
getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);
348
Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);
349
Opts.ShowInst = Args.hasArg(OPT_show_inst);
350
351
// Assemble Options
352
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
353
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
354
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
355
Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);
356
Opts.NoTypeCheck = Args.hasArg(OPT_mno_type_check);
357
Opts.RelocationModel =
358
std::string(Args.getLastArgValue(OPT_mrelocation_model, "pic"));
359
Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi));
360
Opts.IncrementalLinkerCompatible =
361
Args.hasArg(OPT_mincremental_linker_compatible);
362
Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
363
364
// EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
365
// EmbedBitcode behaves the same for all embed options for assembly files.
366
if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
367
Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())
368
.Case("all", 1)
369
.Case("bitcode", 1)
370
.Case("marker", 1)
371
.Default(0);
372
}
373
374
if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
375
Opts.EmitDwarfUnwind =
376
llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
377
.Case("always", EmitDwarfUnwindType::Always)
378
.Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
379
.Case("default", EmitDwarfUnwindType::Default);
380
}
381
382
Opts.EmitCompactUnwindNonCanonical =
383
Args.hasArg(OPT_femit_compact_unwind_non_canonical);
384
Opts.Crel = Args.hasArg(OPT_crel);
385
386
Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
387
388
return Success;
389
}
390
391
static std::unique_ptr<raw_fd_ostream>
392
getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
393
// Make sure that the Out file gets unlinked from the disk if we get a
394
// SIGINT.
395
if (Path != "-")
396
sys::RemoveFileOnSignal(Path);
397
398
std::error_code EC;
399
auto Out = std::make_unique<raw_fd_ostream>(
400
Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_TextWithCRLF));
401
if (EC) {
402
Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
403
return nullptr;
404
}
405
406
return Out;
407
}
408
409
static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
410
DiagnosticsEngine &Diags) {
411
// Get the target specific parser.
412
std::string Error;
413
const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
414
if (!TheTarget)
415
return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
416
417
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
418
MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
419
420
if (std::error_code EC = Buffer.getError()) {
421
return Diags.Report(diag::err_fe_error_reading)
422
<< Opts.InputFile << EC.message();
423
}
424
425
SourceMgr SrcMgr;
426
427
// Tell SrcMgr about this buffer, which is what the parser will pick up.
428
unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
429
430
// Record the location of the include directories so that the lexer can find
431
// it later.
432
SrcMgr.setIncludeDirs(Opts.IncludePaths);
433
434
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
435
assert(MRI && "Unable to create target register info!");
436
437
MCTargetOptions MCOptions;
438
MCOptions.MCRelaxAll = Opts.RelaxAll;
439
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
440
MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;
441
MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels;
442
MCOptions.Crel = Opts.Crel;
443
MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations;
444
MCOptions.X86Sse2Avx = Opts.SSE2AVX;
445
MCOptions.CompressDebugSections = Opts.CompressDebugSections;
446
MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
447
448
std::unique_ptr<MCAsmInfo> MAI(
449
TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
450
assert(MAI && "Unable to create target asm info!");
451
452
// Ensure MCAsmInfo initialization occurs before any use, otherwise sections
453
// may be created with a combination of default and explicit settings.
454
455
456
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
457
if (Opts.OutputPath.empty())
458
Opts.OutputPath = "-";
459
std::unique_ptr<raw_fd_ostream> FDOS =
460
getOutputStream(Opts.OutputPath, Diags, IsBinary);
461
if (!FDOS)
462
return true;
463
std::unique_ptr<raw_fd_ostream> DwoOS;
464
if (!Opts.SplitDwarfOutput.empty())
465
DwoOS = getOutputStream(Opts.SplitDwarfOutput, Diags, IsBinary);
466
467
// Build up the feature string from the target feature list.
468
std::string FS = llvm::join(Opts.Features, ",");
469
470
std::unique_ptr<MCSubtargetInfo> STI(
471
TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
472
assert(STI && "Unable to create subtarget info!");
473
474
MCContext Ctx(Triple(Opts.Triple), MAI.get(), MRI.get(), STI.get(), &SrcMgr,
475
&MCOptions);
476
477
bool PIC = false;
478
if (Opts.RelocationModel == "static") {
479
PIC = false;
480
} else if (Opts.RelocationModel == "pic") {
481
PIC = true;
482
} else {
483
assert(Opts.RelocationModel == "dynamic-no-pic" &&
484
"Invalid PIC model!");
485
PIC = false;
486
}
487
488
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
489
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
490
std::unique_ptr<MCObjectFileInfo> MOFI(
491
TheTarget->createMCObjectFileInfo(Ctx, PIC));
492
if (Opts.DarwinTargetVariantTriple)
493
MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
494
if (!Opts.DarwinTargetVariantSDKVersion.empty())
495
MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion);
496
Ctx.setObjectFileInfo(MOFI.get());
497
498
if (Opts.GenDwarfForAssembly)
499
Ctx.setGenDwarfForAssembly(true);
500
if (!Opts.DwarfDebugFlags.empty())
501
Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
502
if (!Opts.DwarfDebugProducer.empty())
503
Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
504
if (!Opts.DebugCompilationDir.empty())
505
Ctx.setCompilationDir(Opts.DebugCompilationDir);
506
else {
507
// If no compilation dir is set, try to use the current directory.
508
SmallString<128> CWD;
509
if (!sys::fs::current_path(CWD))
510
Ctx.setCompilationDir(CWD);
511
}
512
if (!Opts.DebugPrefixMap.empty())
513
for (const auto &KV : Opts.DebugPrefixMap)
514
Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
515
if (!Opts.MainFileName.empty())
516
Ctx.setMainFileName(StringRef(Opts.MainFileName));
517
Ctx.setDwarfFormat(Opts.Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);
518
Ctx.setDwarfVersion(Opts.DwarfVersion);
519
if (Opts.GenDwarfForAssembly)
520
Ctx.setGenDwarfRootFile(Opts.InputFile,
521
SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());
522
523
std::unique_ptr<MCStreamer> Str;
524
525
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
526
assert(MCII && "Unable to create instruction info!");
527
528
raw_pwrite_stream *Out = FDOS.get();
529
std::unique_ptr<buffer_ostream> BOS;
530
531
MCOptions.MCNoWarn = Opts.NoWarn;
532
MCOptions.MCFatalWarnings = Opts.FatalWarnings;
533
MCOptions.MCNoTypeCheck = Opts.NoTypeCheck;
534
MCOptions.ShowMCInst = Opts.ShowInst;
535
MCOptions.AsmVerbose = true;
536
MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;
537
MCOptions.ABIName = Opts.TargetABI;
538
539
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
540
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
541
MCInstPrinter *IP = TheTarget->createMCInstPrinter(
542
llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
543
544
std::unique_ptr<MCCodeEmitter> CE;
545
if (Opts.ShowEncoding)
546
CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
547
std::unique_ptr<MCAsmBackend> MAB(
548
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
549
550
auto FOut = std::make_unique<formatted_raw_ostream>(*Out);
551
Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), IP,
552
std::move(CE), std::move(MAB)));
553
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
554
Str.reset(createNullStreamer(Ctx));
555
} else {
556
assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
557
"Invalid file type!");
558
if (!FDOS->supportsSeeking()) {
559
BOS = std::make_unique<buffer_ostream>(*FDOS);
560
Out = BOS.get();
561
}
562
563
std::unique_ptr<MCCodeEmitter> CE(
564
TheTarget->createMCCodeEmitter(*MCII, Ctx));
565
std::unique_ptr<MCAsmBackend> MAB(
566
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
567
assert(MAB && "Unable to create asm backend!");
568
569
std::unique_ptr<MCObjectWriter> OW =
570
DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
571
: MAB->createObjectWriter(*Out);
572
573
Triple T(Opts.Triple);
574
Str.reset(TheTarget->createMCObjectStreamer(
575
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));
576
Str.get()->initSections(Opts.NoExecStack, *STI);
577
}
578
579
// When -fembed-bitcode is passed to clang_as, a 1-byte marker
580
// is emitted in __LLVM,__asm section if the object file is MachO format.
581
if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
582
MCSection *AsmLabel = Ctx.getMachOSection(
583
"__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
584
Str.get()->switchSection(AsmLabel);
585
Str.get()->emitZeros(1);
586
}
587
588
bool Failed = false;
589
590
std::unique_ptr<MCAsmParser> Parser(
591
createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
592
593
// FIXME: init MCTargetOptions from sanitizer flags here.
594
std::unique_ptr<MCTargetAsmParser> TAP(
595
TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
596
if (!TAP)
597
Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
598
599
// Set values for symbols, if any.
600
for (auto &S : Opts.SymbolDefs) {
601
auto Pair = StringRef(S).split('=');
602
auto Sym = Pair.first;
603
auto Val = Pair.second;
604
int64_t Value;
605
// We have already error checked this in the driver.
606
Val.getAsInteger(0, Value);
607
Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);
608
}
609
610
if (!Failed) {
611
Parser->setTargetParser(*TAP.get());
612
Failed = Parser->Run(Opts.NoInitialTextSection);
613
}
614
615
return Failed;
616
}
617
618
static bool ExecuteAssembler(AssemblerInvocation &Opts,
619
DiagnosticsEngine &Diags) {
620
bool Failed = ExecuteAssemblerImpl(Opts, Diags);
621
622
// Delete output file if there were errors.
623
if (Failed) {
624
if (Opts.OutputPath != "-")
625
sys::fs::remove(Opts.OutputPath);
626
if (!Opts.SplitDwarfOutput.empty() && Opts.SplitDwarfOutput != "-")
627
sys::fs::remove(Opts.SplitDwarfOutput);
628
}
629
630
return Failed;
631
}
632
633
static void LLVMErrorHandler(void *UserData, const char *Message,
634
bool GenCrashDiag) {
635
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
636
637
Diags.Report(diag::err_fe_error_backend) << Message;
638
639
// We cannot recover from llvm errors.
640
sys::Process::Exit(1);
641
}
642
643
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
644
// Initialize targets and assembly printers/parsers.
645
InitializeAllTargetInfos();
646
InitializeAllTargetMCs();
647
InitializeAllAsmParsers();
648
649
// Construct our diagnostic client.
650
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
651
TextDiagnosticPrinter *DiagClient
652
= new TextDiagnosticPrinter(errs(), &*DiagOpts);
653
DiagClient->setPrefix("clang -cc1as");
654
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
655
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
656
657
// Set an error handler, so that any LLVM backend diagnostics go through our
658
// error handler.
659
ScopedFatalErrorHandler FatalErrorHandler
660
(LLVMErrorHandler, static_cast<void*>(&Diags));
661
662
// Parse the arguments.
663
AssemblerInvocation Asm;
664
if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
665
return 1;
666
667
if (Asm.ShowHelp) {
668
getDriverOptTable().printHelp(
669
llvm::outs(), "clang -cc1as [options] file...",
670
"Clang Integrated Assembler", /*ShowHidden=*/false,
671
/*ShowAllAliases=*/false,
672
llvm::opt::Visibility(driver::options::CC1AsOption));
673
674
return 0;
675
}
676
677
// Honor -version.
678
//
679
// FIXME: Use a better -version message?
680
if (Asm.ShowVersion) {
681
llvm::cl::PrintVersionMessage();
682
return 0;
683
}
684
685
// Honor -mllvm.
686
//
687
// FIXME: Remove this, one day.
688
if (!Asm.LLVMArgs.empty()) {
689
unsigned NumArgs = Asm.LLVMArgs.size();
690
auto Args = std::make_unique<const char*[]>(NumArgs + 2);
691
Args[0] = "clang (LLVM option parsing)";
692
for (unsigned i = 0; i != NumArgs; ++i)
693
Args[i + 1] = Asm.LLVMArgs[i].c_str();
694
Args[NumArgs + 1] = nullptr;
695
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
696
}
697
698
// Execute the invocation, unless there were parsing errors.
699
bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
700
701
// If any timers were active but haven't been destroyed yet, print their
702
// results now.
703
TimerGroup::printAll(errs());
704
TimerGroup::clearAll();
705
706
return !!Failed;
707
}
708
709