1 //===-- cc1as_main.cpp - Clang Assembler ---------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This is the entry point to the clang -cc1as functionality, which implements
10 // the direct interface to the LLVM MC based assembler.
12 //===----------------------------------------------------------------------===//
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"
59 #include <system_error>
60 using namespace clang
;
61 using namespace clang::driver
;
62 using namespace clang::driver::options
;
64 using namespace llvm::opt
;
68 /// Helper class for representing a single invocation of the assembler.
69 struct AssemblerInvocation
{
70 /// @name Target Options
73 /// The name of the target triple to assemble for.
76 /// If given, the name of the target CPU to determine which instructions
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
;
84 /// The list of symbol definitions.
85 std::vector
<std::string
> SymbolDefs
;
88 /// @name Language Options
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)
100 unsigned DwarfVersion
;
101 std::string DwarfDebugFlags
;
102 std::string DwarfDebugProducer
;
103 std::string DebugCompilationDir
;
104 llvm::SmallVector
<std::pair
<std::string
, std::string
>, 0> DebugPrefixMap
;
105 llvm::DebugCompressionType CompressDebugSections
=
106 llvm::DebugCompressionType::None
;
107 std::string MainFileName
;
108 std::string SplitDwarfOutput
;
111 /// @name Frontend Options
114 std::string InputFile
;
115 std::vector
<std::string
> LLVMArgs
;
116 std::string OutputPath
;
118 FT_Asm
, ///< Assembly (.s) output, transliterate mode.
119 FT_Null
, ///< No output, for timing purposes.
120 FT_Obj
///< Object file output.
123 LLVM_PREFERRED_TYPE(bool)
124 unsigned ShowHelp
: 1;
125 LLVM_PREFERRED_TYPE(bool)
126 unsigned ShowVersion
: 1;
129 /// @name Transliterate Options
132 unsigned OutputAsmVariant
;
133 LLVM_PREFERRED_TYPE(bool)
134 unsigned ShowEncoding
: 1;
135 LLVM_PREFERRED_TYPE(bool)
136 unsigned ShowInst
: 1;
139 /// @name Assembler Options
142 LLVM_PREFERRED_TYPE(bool)
143 unsigned RelaxAll
: 1;
144 LLVM_PREFERRED_TYPE(bool)
145 unsigned NoExecStack
: 1;
146 LLVM_PREFERRED_TYPE(bool)
147 unsigned FatalWarnings
: 1;
148 LLVM_PREFERRED_TYPE(bool)
150 LLVM_PREFERRED_TYPE(bool)
151 unsigned NoTypeCheck
: 1;
152 LLVM_PREFERRED_TYPE(bool)
153 unsigned IncrementalLinkerCompatible
: 1;
154 LLVM_PREFERRED_TYPE(bool)
155 unsigned EmbedBitcode
: 1;
157 /// Whether to emit DWARF unwind info.
158 EmitDwarfUnwindType EmitDwarfUnwind
;
160 // Whether to emit compact-unwind for non-canonical entries.
161 // Note: maybe overriden by other constraints.
162 LLVM_PREFERRED_TYPE(bool)
163 unsigned EmitCompactUnwindNonCanonical
: 1;
165 LLVM_PREFERRED_TYPE(bool)
167 LLVM_PREFERRED_TYPE(bool)
168 unsigned ImplicitMapsyms
: 1;
170 LLVM_PREFERRED_TYPE(bool)
171 unsigned X86RelaxRelocations
: 1;
172 LLVM_PREFERRED_TYPE(bool)
173 unsigned X86Sse2Avx
: 1;
175 /// The name of the relocation model to use.
176 std::string RelocationModel
;
178 /// The ABI targeted by the backend. Specified using -target-abi. Empty
180 std::string TargetABI
;
182 /// Darwin target variant triple, the variant of the deployment target
183 /// for which the code is being compiled.
184 std::optional
<llvm::Triple
> DarwinTargetVariantTriple
;
186 /// The version of the darwin target variant SDK which was used during the
188 llvm::VersionTuple DarwinTargetVariantSDKVersion
;
190 /// The name of a file to use with \c .secure_log_unique directives.
191 std::string AsSecureLogFile
;
195 AssemblerInvocation() {
197 NoInitialTextSection
= 0;
201 OutputAsmVariant
= 0;
209 IncrementalLinkerCompatible
= 0;
213 EmitDwarfUnwind
= EmitDwarfUnwindType::Default
;
214 EmitCompactUnwindNonCanonical
= false;
217 X86RelaxRelocations
= 0;
221 static bool CreateFromArgs(AssemblerInvocation
&Res
,
222 ArrayRef
<const char *> Argv
,
223 DiagnosticsEngine
&Diags
);
228 bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation
&Opts
,
229 ArrayRef
<const char *> Argv
,
230 DiagnosticsEngine
&Diags
) {
233 // Parse the arguments.
234 const OptTable
&OptTbl
= getDriverOptTable();
236 llvm::opt::Visibility
VisibilityMask(options::CC1AsOption
);
237 unsigned MissingArgIndex
, MissingArgCount
;
239 OptTbl
.ParseArgs(Argv
, MissingArgIndex
, MissingArgCount
, VisibilityMask
);
241 // Check for missing argument error.
242 if (MissingArgCount
) {
243 Diags
.Report(diag::err_drv_missing_argument
)
244 << Args
.getArgString(MissingArgIndex
) << MissingArgCount
;
248 // Issue errors on unknown arguments.
249 for (const Arg
*A
: Args
.filtered(OPT_UNKNOWN
)) {
250 auto ArgString
= A
->getAsString(Args
);
252 if (OptTbl
.findNearest(ArgString
, Nearest
, VisibilityMask
) > 1)
253 Diags
.Report(diag::err_drv_unknown_argument
) << ArgString
;
255 Diags
.Report(diag::err_drv_unknown_argument_with_suggestion
)
256 << ArgString
<< Nearest
;
260 // Construct the invocation.
263 Opts
.Triple
= llvm::Triple::normalize(Args
.getLastArgValue(OPT_triple
));
264 if (Arg
*A
= Args
.getLastArg(options::OPT_darwin_target_variant_triple
))
265 Opts
.DarwinTargetVariantTriple
= llvm::Triple(A
->getValue());
266 if (Arg
*A
= Args
.getLastArg(OPT_darwin_target_variant_sdk_version_EQ
)) {
267 VersionTuple Version
;
268 if (Version
.tryParse(A
->getValue()))
269 Diags
.Report(diag::err_drv_invalid_value
)
270 << A
->getAsString(Args
) << A
->getValue();
272 Opts
.DarwinTargetVariantSDKVersion
= Version
;
275 Opts
.CPU
= std::string(Args
.getLastArgValue(OPT_target_cpu
));
276 Opts
.Features
= Args
.getAllArgValues(OPT_target_feature
);
278 // Use the default target triple if unspecified.
279 if (Opts
.Triple
.empty())
280 Opts
.Triple
= llvm::sys::getDefaultTargetTriple();
283 Opts
.IncludePaths
= Args
.getAllArgValues(OPT_I
);
284 Opts
.NoInitialTextSection
= Args
.hasArg(OPT_n
);
285 Opts
.SaveTemporaryLabels
= Args
.hasArg(OPT_msave_temp_labels
);
286 // Any DebugInfoKind implies GenDwarfForAssembly.
287 Opts
.GenDwarfForAssembly
= Args
.hasArg(OPT_debug_info_kind_EQ
);
289 if (const Arg
*A
= Args
.getLastArg(OPT_compress_debug_sections_EQ
)) {
290 Opts
.CompressDebugSections
=
291 llvm::StringSwitch
<llvm::DebugCompressionType
>(A
->getValue())
292 .Case("none", llvm::DebugCompressionType::None
)
293 .Case("zlib", llvm::DebugCompressionType::Zlib
)
294 .Case("zstd", llvm::DebugCompressionType::Zstd
)
295 .Default(llvm::DebugCompressionType::None
);
298 if (auto *DwarfFormatArg
= Args
.getLastArg(OPT_gdwarf64
, OPT_gdwarf32
))
299 Opts
.Dwarf64
= DwarfFormatArg
->getOption().matches(OPT_gdwarf64
);
300 Opts
.DwarfVersion
= getLastArgIntValue(Args
, OPT_dwarf_version_EQ
, 2, Diags
);
301 Opts
.DwarfDebugFlags
=
302 std::string(Args
.getLastArgValue(OPT_dwarf_debug_flags
));
303 Opts
.DwarfDebugProducer
=
304 std::string(Args
.getLastArgValue(OPT_dwarf_debug_producer
));
305 if (const Arg
*A
= Args
.getLastArg(options::OPT_ffile_compilation_dir_EQ
,
306 options::OPT_fdebug_compilation_dir_EQ
))
307 Opts
.DebugCompilationDir
= A
->getValue();
308 Opts
.MainFileName
= std::string(Args
.getLastArgValue(OPT_main_file_name
));
310 for (const auto &Arg
: Args
.getAllArgValues(OPT_fdebug_prefix_map_EQ
)) {
311 auto Split
= StringRef(Arg
).split('=');
312 Opts
.DebugPrefixMap
.emplace_back(Split
.first
, Split
.second
);
316 if (Args
.hasArg(OPT_INPUT
)) {
318 for (const Arg
*A
: Args
.filtered(OPT_INPUT
)) {
320 Opts
.InputFile
= A
->getValue();
323 Diags
.Report(diag::err_drv_unknown_argument
) << A
->getAsString(Args
);
328 Opts
.LLVMArgs
= Args
.getAllArgValues(OPT_mllvm
);
329 Opts
.OutputPath
= std::string(Args
.getLastArgValue(OPT_o
));
330 Opts
.SplitDwarfOutput
=
331 std::string(Args
.getLastArgValue(OPT_split_dwarf_output
));
332 if (Arg
*A
= Args
.getLastArg(OPT_filetype
)) {
333 StringRef Name
= A
->getValue();
334 unsigned OutputType
= StringSwitch
<unsigned>(Name
)
336 .Case("null", FT_Null
)
339 if (OutputType
== ~0U) {
340 Diags
.Report(diag::err_drv_invalid_value
) << A
->getAsString(Args
) << Name
;
343 Opts
.OutputType
= FileType(OutputType
);
345 Opts
.ShowHelp
= Args
.hasArg(OPT_help
);
346 Opts
.ShowVersion
= Args
.hasArg(OPT_version
);
348 // Transliterate Options
349 Opts
.OutputAsmVariant
=
350 getLastArgIntValue(Args
, OPT_output_asm_variant
, 0, Diags
);
351 Opts
.ShowEncoding
= Args
.hasArg(OPT_show_encoding
);
352 Opts
.ShowInst
= Args
.hasArg(OPT_show_inst
);
355 Opts
.RelaxAll
= Args
.hasArg(OPT_mrelax_all
);
356 Opts
.NoExecStack
= Args
.hasArg(OPT_mno_exec_stack
);
357 Opts
.FatalWarnings
= Args
.hasArg(OPT_massembler_fatal_warnings
);
358 Opts
.NoWarn
= Args
.hasArg(OPT_massembler_no_warn
);
359 Opts
.NoTypeCheck
= Args
.hasArg(OPT_mno_type_check
);
360 Opts
.RelocationModel
=
361 std::string(Args
.getLastArgValue(OPT_mrelocation_model
, "pic"));
362 Opts
.TargetABI
= std::string(Args
.getLastArgValue(OPT_target_abi
));
363 Opts
.IncrementalLinkerCompatible
=
364 Args
.hasArg(OPT_mincremental_linker_compatible
);
365 Opts
.SymbolDefs
= Args
.getAllArgValues(OPT_defsym
);
367 // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
368 // EmbedBitcode behaves the same for all embed options for assembly files.
369 if (auto *A
= Args
.getLastArg(OPT_fembed_bitcode_EQ
)) {
370 Opts
.EmbedBitcode
= llvm::StringSwitch
<unsigned>(A
->getValue())
377 if (auto *A
= Args
.getLastArg(OPT_femit_dwarf_unwind_EQ
)) {
378 Opts
.EmitDwarfUnwind
=
379 llvm::StringSwitch
<EmitDwarfUnwindType
>(A
->getValue())
380 .Case("always", EmitDwarfUnwindType::Always
)
381 .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind
)
382 .Case("default", EmitDwarfUnwindType::Default
);
385 Opts
.EmitCompactUnwindNonCanonical
=
386 Args
.hasArg(OPT_femit_compact_unwind_non_canonical
);
387 Opts
.Crel
= Args
.hasArg(OPT_crel
);
388 Opts
.ImplicitMapsyms
= Args
.hasArg(OPT_mmapsyms_implicit
);
389 Opts
.X86RelaxRelocations
= !Args
.hasArg(OPT_mrelax_relocations_no
);
390 Opts
.X86Sse2Avx
= Args
.hasArg(OPT_msse2avx
);
392 Opts
.AsSecureLogFile
= Args
.getLastArgValue(OPT_as_secure_log_file
);
397 static std::unique_ptr
<raw_fd_ostream
>
398 getOutputStream(StringRef Path
, DiagnosticsEngine
&Diags
, bool Binary
) {
399 // Make sure that the Out file gets unlinked from the disk if we get a
402 sys::RemoveFileOnSignal(Path
);
405 auto Out
= std::make_unique
<raw_fd_ostream
>(
406 Path
, EC
, (Binary
? sys::fs::OF_None
: sys::fs::OF_TextWithCRLF
));
408 Diags
.Report(diag::err_fe_unable_to_open_output
) << Path
<< EC
.message();
415 static bool ExecuteAssemblerImpl(AssemblerInvocation
&Opts
,
416 DiagnosticsEngine
&Diags
) {
417 // Get the target specific parser.
419 const Target
*TheTarget
= TargetRegistry::lookupTarget(Opts
.Triple
, Error
);
421 return Diags
.Report(diag::err_target_unknown_triple
) << Opts
.Triple
;
423 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> Buffer
=
424 MemoryBuffer::getFileOrSTDIN(Opts
.InputFile
, /*IsText=*/true);
426 if (std::error_code EC
= Buffer
.getError()) {
427 return Diags
.Report(diag::err_fe_error_reading
)
428 << Opts
.InputFile
<< EC
.message();
433 // Tell SrcMgr about this buffer, which is what the parser will pick up.
434 unsigned BufferIndex
= SrcMgr
.AddNewSourceBuffer(std::move(*Buffer
), SMLoc());
436 // Record the location of the include directories so that the lexer can find
438 SrcMgr
.setIncludeDirs(Opts
.IncludePaths
);
440 std::unique_ptr
<MCRegisterInfo
> MRI(TheTarget
->createMCRegInfo(Opts
.Triple
));
441 assert(MRI
&& "Unable to create target register info!");
443 MCTargetOptions MCOptions
;
444 MCOptions
.MCRelaxAll
= Opts
.RelaxAll
;
445 MCOptions
.EmitDwarfUnwind
= Opts
.EmitDwarfUnwind
;
446 MCOptions
.EmitCompactUnwindNonCanonical
= Opts
.EmitCompactUnwindNonCanonical
;
447 MCOptions
.MCSaveTempLabels
= Opts
.SaveTemporaryLabels
;
448 MCOptions
.Crel
= Opts
.Crel
;
449 MCOptions
.ImplicitMapSyms
= Opts
.ImplicitMapsyms
;
450 MCOptions
.X86RelaxRelocations
= Opts
.X86RelaxRelocations
;
451 MCOptions
.X86Sse2Avx
= Opts
.X86Sse2Avx
;
452 MCOptions
.CompressDebugSections
= Opts
.CompressDebugSections
;
453 MCOptions
.AsSecureLogFile
= Opts
.AsSecureLogFile
;
455 std::unique_ptr
<MCAsmInfo
> MAI(
456 TheTarget
->createMCAsmInfo(*MRI
, Opts
.Triple
, MCOptions
));
457 assert(MAI
&& "Unable to create target asm info!");
459 // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
460 // may be created with a combination of default and explicit settings.
463 bool IsBinary
= Opts
.OutputType
== AssemblerInvocation::FT_Obj
;
464 if (Opts
.OutputPath
.empty())
465 Opts
.OutputPath
= "-";
466 std::unique_ptr
<raw_fd_ostream
> FDOS
=
467 getOutputStream(Opts
.OutputPath
, Diags
, IsBinary
);
470 std::unique_ptr
<raw_fd_ostream
> DwoOS
;
471 if (!Opts
.SplitDwarfOutput
.empty())
472 DwoOS
= getOutputStream(Opts
.SplitDwarfOutput
, Diags
, IsBinary
);
474 // Build up the feature string from the target feature list.
475 std::string FS
= llvm::join(Opts
.Features
, ",");
477 std::unique_ptr
<MCSubtargetInfo
> STI(
478 TheTarget
->createMCSubtargetInfo(Opts
.Triple
, Opts
.CPU
, FS
));
479 assert(STI
&& "Unable to create subtarget info!");
481 MCContext
Ctx(Triple(Opts
.Triple
), MAI
.get(), MRI
.get(), STI
.get(), &SrcMgr
,
485 if (Opts
.RelocationModel
== "static") {
487 } else if (Opts
.RelocationModel
== "pic") {
490 assert(Opts
.RelocationModel
== "dynamic-no-pic" &&
491 "Invalid PIC model!");
495 // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
496 // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
497 std::unique_ptr
<MCObjectFileInfo
> MOFI(
498 TheTarget
->createMCObjectFileInfo(Ctx
, PIC
));
499 Ctx
.setObjectFileInfo(MOFI
.get());
501 if (Opts
.GenDwarfForAssembly
)
502 Ctx
.setGenDwarfForAssembly(true);
503 if (!Opts
.DwarfDebugFlags
.empty())
504 Ctx
.setDwarfDebugFlags(StringRef(Opts
.DwarfDebugFlags
));
505 if (!Opts
.DwarfDebugProducer
.empty())
506 Ctx
.setDwarfDebugProducer(StringRef(Opts
.DwarfDebugProducer
));
507 if (!Opts
.DebugCompilationDir
.empty())
508 Ctx
.setCompilationDir(Opts
.DebugCompilationDir
);
510 // If no compilation dir is set, try to use the current directory.
511 SmallString
<128> CWD
;
512 if (!sys::fs::current_path(CWD
))
513 Ctx
.setCompilationDir(CWD
);
515 if (!Opts
.DebugPrefixMap
.empty())
516 for (const auto &KV
: Opts
.DebugPrefixMap
)
517 Ctx
.addDebugPrefixMapEntry(KV
.first
, KV
.second
);
518 if (!Opts
.MainFileName
.empty())
519 Ctx
.setMainFileName(StringRef(Opts
.MainFileName
));
520 Ctx
.setDwarfFormat(Opts
.Dwarf64
? dwarf::DWARF64
: dwarf::DWARF32
);
521 Ctx
.setDwarfVersion(Opts
.DwarfVersion
);
522 if (Opts
.GenDwarfForAssembly
)
523 Ctx
.setGenDwarfRootFile(Opts
.InputFile
,
524 SrcMgr
.getMemoryBuffer(BufferIndex
)->getBuffer());
526 std::unique_ptr
<MCStreamer
> Str
;
528 std::unique_ptr
<MCInstrInfo
> MCII(TheTarget
->createMCInstrInfo());
529 assert(MCII
&& "Unable to create instruction info!");
531 raw_pwrite_stream
*Out
= FDOS
.get();
532 std::unique_ptr
<buffer_ostream
> BOS
;
534 MCOptions
.MCNoWarn
= Opts
.NoWarn
;
535 MCOptions
.MCFatalWarnings
= Opts
.FatalWarnings
;
536 MCOptions
.MCNoTypeCheck
= Opts
.NoTypeCheck
;
537 MCOptions
.ShowMCInst
= Opts
.ShowInst
;
538 MCOptions
.AsmVerbose
= true;
539 MCOptions
.MCUseDwarfDirectory
= MCTargetOptions::EnableDwarfDirectory
;
540 MCOptions
.ABIName
= Opts
.TargetABI
;
542 // FIXME: There is a bit of code duplication with addPassesToEmitFile.
543 if (Opts
.OutputType
== AssemblerInvocation::FT_Asm
) {
544 MCInstPrinter
*IP
= TheTarget
->createMCInstPrinter(
545 llvm::Triple(Opts
.Triple
), Opts
.OutputAsmVariant
, *MAI
, *MCII
, *MRI
);
547 std::unique_ptr
<MCCodeEmitter
> CE
;
548 if (Opts
.ShowEncoding
)
549 CE
.reset(TheTarget
->createMCCodeEmitter(*MCII
, Ctx
));
550 std::unique_ptr
<MCAsmBackend
> MAB(
551 TheTarget
->createMCAsmBackend(*STI
, *MRI
, MCOptions
));
553 auto FOut
= std::make_unique
<formatted_raw_ostream
>(*Out
);
554 Str
.reset(TheTarget
->createAsmStreamer(Ctx
, std::move(FOut
), IP
,
555 std::move(CE
), std::move(MAB
)));
556 } else if (Opts
.OutputType
== AssemblerInvocation::FT_Null
) {
557 Str
.reset(createNullStreamer(Ctx
));
559 assert(Opts
.OutputType
== AssemblerInvocation::FT_Obj
&&
560 "Invalid file type!");
561 if (!FDOS
->supportsSeeking()) {
562 BOS
= std::make_unique
<buffer_ostream
>(*FDOS
);
566 std::unique_ptr
<MCCodeEmitter
> CE(
567 TheTarget
->createMCCodeEmitter(*MCII
, Ctx
));
568 std::unique_ptr
<MCAsmBackend
> MAB(
569 TheTarget
->createMCAsmBackend(*STI
, *MRI
, MCOptions
));
570 assert(MAB
&& "Unable to create asm backend!");
572 std::unique_ptr
<MCObjectWriter
> OW
=
573 DwoOS
? MAB
->createDwoObjectWriter(*Out
, *DwoOS
)
574 : MAB
->createObjectWriter(*Out
);
576 Triple
T(Opts
.Triple
);
577 Str
.reset(TheTarget
->createMCObjectStreamer(
578 T
, Ctx
, std::move(MAB
), std::move(OW
), std::move(CE
), *STI
));
579 Str
.get()->initSections(Opts
.NoExecStack
, *STI
);
580 if (T
.isOSBinFormatMachO() && T
.isOSDarwin()) {
581 Triple
*TVT
= Opts
.DarwinTargetVariantTriple
582 ? &*Opts
.DarwinTargetVariantTriple
584 Str
->emitVersionForTarget(T
, VersionTuple(), TVT
,
585 Opts
.DarwinTargetVariantSDKVersion
);
589 // When -fembed-bitcode is passed to clang_as, a 1-byte marker
590 // is emitted in __LLVM,__asm section if the object file is MachO format.
591 if (Opts
.EmbedBitcode
&& Ctx
.getObjectFileType() == MCContext::IsMachO
) {
592 MCSection
*AsmLabel
= Ctx
.getMachOSection(
593 "__LLVM", "__asm", MachO::S_REGULAR
, 4, SectionKind::getReadOnly());
594 Str
.get()->switchSection(AsmLabel
);
595 Str
.get()->emitZeros(1);
600 std::unique_ptr
<MCAsmParser
> Parser(
601 createMCAsmParser(SrcMgr
, Ctx
, *Str
.get(), *MAI
));
603 // FIXME: init MCTargetOptions from sanitizer flags here.
604 std::unique_ptr
<MCTargetAsmParser
> TAP(
605 TheTarget
->createMCAsmParser(*STI
, *Parser
, *MCII
, MCOptions
));
607 Failed
= Diags
.Report(diag::err_target_unknown_triple
) << Opts
.Triple
;
609 // Set values for symbols, if any.
610 for (auto &S
: Opts
.SymbolDefs
) {
611 auto Pair
= StringRef(S
).split('=');
612 auto Sym
= Pair
.first
;
613 auto Val
= Pair
.second
;
615 // We have already error checked this in the driver.
616 Val
.getAsInteger(0, Value
);
617 Ctx
.setSymbolValue(Parser
->getStreamer(), Sym
, Value
);
621 Parser
->setTargetParser(*TAP
.get());
622 Failed
= Parser
->Run(Opts
.NoInitialTextSection
);
628 static bool ExecuteAssembler(AssemblerInvocation
&Opts
,
629 DiagnosticsEngine
&Diags
) {
630 bool Failed
= ExecuteAssemblerImpl(Opts
, Diags
);
632 // Delete output file if there were errors.
634 if (Opts
.OutputPath
!= "-")
635 sys::fs::remove(Opts
.OutputPath
);
636 if (!Opts
.SplitDwarfOutput
.empty() && Opts
.SplitDwarfOutput
!= "-")
637 sys::fs::remove(Opts
.SplitDwarfOutput
);
643 static void LLVMErrorHandler(void *UserData
, const char *Message
,
645 DiagnosticsEngine
&Diags
= *static_cast<DiagnosticsEngine
*>(UserData
);
647 Diags
.Report(diag::err_fe_error_backend
) << Message
;
649 // We cannot recover from llvm errors.
650 sys::Process::Exit(1);
653 int cc1as_main(ArrayRef
<const char *> Argv
, const char *Argv0
, void *MainAddr
) {
654 // Initialize targets and assembly printers/parsers.
655 InitializeAllTargetInfos();
656 InitializeAllTargetMCs();
657 InitializeAllAsmParsers();
659 // Construct our diagnostic client.
660 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
661 TextDiagnosticPrinter
*DiagClient
662 = new TextDiagnosticPrinter(errs(), &*DiagOpts
);
663 DiagClient
->setPrefix("clang -cc1as");
664 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
665 DiagnosticsEngine
Diags(DiagID
, &*DiagOpts
, DiagClient
);
667 // Set an error handler, so that any LLVM backend diagnostics go through our
669 ScopedFatalErrorHandler FatalErrorHandler
670 (LLVMErrorHandler
, static_cast<void*>(&Diags
));
672 // Parse the arguments.
673 AssemblerInvocation Asm
;
674 if (!AssemblerInvocation::CreateFromArgs(Asm
, Argv
, Diags
))
678 getDriverOptTable().printHelp(
679 llvm::outs(), "clang -cc1as [options] file...",
680 "Clang Integrated Assembler", /*ShowHidden=*/false,
681 /*ShowAllAliases=*/false,
682 llvm::opt::Visibility(driver::options::CC1AsOption
));
689 // FIXME: Use a better -version message?
690 if (Asm
.ShowVersion
) {
691 llvm::cl::PrintVersionMessage();
697 // FIXME: Remove this, one day.
698 if (!Asm
.LLVMArgs
.empty()) {
699 unsigned NumArgs
= Asm
.LLVMArgs
.size();
700 auto Args
= std::make_unique
<const char*[]>(NumArgs
+ 2);
701 Args
[0] = "clang (LLVM option parsing)";
702 for (unsigned i
= 0; i
!= NumArgs
; ++i
)
703 Args
[i
+ 1] = Asm
.LLVMArgs
[i
].c_str();
704 Args
[NumArgs
+ 1] = nullptr;
705 llvm::cl::ParseCommandLineOptions(NumArgs
+ 1, Args
.get());
708 // Execute the invocation, unless there were parsing errors.
709 bool Failed
= Diags
.hasErrorOccurred() || ExecuteAssembler(Asm
, Diags
);
711 // If any timers were active but haven't been destroyed yet, print their
713 TimerGroup::printAll(errs());
714 TimerGroup::clearAll();