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 unsigned NoInitialTextSection
: 1;
93 unsigned SaveTemporaryLabels
: 1;
94 unsigned GenDwarfForAssembly
: 1;
95 unsigned RelaxELFRelocations
: 1;
97 unsigned DwarfVersion
;
98 std::string DwarfDebugFlags
;
99 std::string DwarfDebugProducer
;
100 std::string DebugCompilationDir
;
101 llvm::SmallVector
<std::pair
<std::string
, std::string
>, 0> DebugPrefixMap
;
102 llvm::DebugCompressionType CompressDebugSections
=
103 llvm::DebugCompressionType::None
;
104 std::string MainFileName
;
105 std::string SplitDwarfOutput
;
108 /// @name Frontend Options
111 std::string InputFile
;
112 std::vector
<std::string
> LLVMArgs
;
113 std::string OutputPath
;
115 FT_Asm
, ///< Assembly (.s) output, transliterate mode.
116 FT_Null
, ///< No output, for timing purposes.
117 FT_Obj
///< Object file output.
120 unsigned ShowHelp
: 1;
121 unsigned ShowVersion
: 1;
124 /// @name Transliterate Options
127 unsigned OutputAsmVariant
;
128 unsigned ShowEncoding
: 1;
129 unsigned ShowInst
: 1;
132 /// @name Assembler Options
135 unsigned RelaxAll
: 1;
136 unsigned NoExecStack
: 1;
137 unsigned FatalWarnings
: 1;
139 unsigned NoTypeCheck
: 1;
140 unsigned IncrementalLinkerCompatible
: 1;
141 unsigned EmbedBitcode
: 1;
143 /// Whether to emit DWARF unwind info.
144 EmitDwarfUnwindType EmitDwarfUnwind
;
146 // Whether to emit compact-unwind for non-canonical entries.
147 // Note: maybe overriden by other constraints.
148 unsigned EmitCompactUnwindNonCanonical
: 1;
150 /// The name of the relocation model to use.
151 std::string RelocationModel
;
153 /// The ABI targeted by the backend. Specified using -target-abi. Empty
155 std::string TargetABI
;
157 /// Darwin target variant triple, the variant of the deployment target
158 /// for which the code is being compiled.
159 std::optional
<llvm::Triple
> DarwinTargetVariantTriple
;
161 /// The version of the darwin target variant SDK which was used during the
163 llvm::VersionTuple DarwinTargetVariantSDKVersion
;
165 /// The name of a file to use with \c .secure_log_unique directives.
166 std::string AsSecureLogFile
;
170 AssemblerInvocation() {
172 NoInitialTextSection
= 0;
176 OutputAsmVariant
= 0;
184 IncrementalLinkerCompatible
= 0;
188 EmitDwarfUnwind
= EmitDwarfUnwindType::Default
;
189 EmitCompactUnwindNonCanonical
= false;
192 static bool CreateFromArgs(AssemblerInvocation
&Res
,
193 ArrayRef
<const char *> Argv
,
194 DiagnosticsEngine
&Diags
);
199 bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation
&Opts
,
200 ArrayRef
<const char *> Argv
,
201 DiagnosticsEngine
&Diags
) {
204 // Parse the arguments.
205 const OptTable
&OptTbl
= getDriverOptTable();
207 llvm::opt::Visibility
VisibilityMask(options::CC1AsOption
);
208 unsigned MissingArgIndex
, MissingArgCount
;
210 OptTbl
.ParseArgs(Argv
, MissingArgIndex
, MissingArgCount
, VisibilityMask
);
212 // Check for missing argument error.
213 if (MissingArgCount
) {
214 Diags
.Report(diag::err_drv_missing_argument
)
215 << Args
.getArgString(MissingArgIndex
) << MissingArgCount
;
219 // Issue errors on unknown arguments.
220 for (const Arg
*A
: Args
.filtered(OPT_UNKNOWN
)) {
221 auto ArgString
= A
->getAsString(Args
);
223 if (OptTbl
.findNearest(ArgString
, Nearest
, VisibilityMask
) > 1)
224 Diags
.Report(diag::err_drv_unknown_argument
) << ArgString
;
226 Diags
.Report(diag::err_drv_unknown_argument_with_suggestion
)
227 << ArgString
<< Nearest
;
231 // Construct the invocation.
234 Opts
.Triple
= llvm::Triple::normalize(Args
.getLastArgValue(OPT_triple
));
235 if (Arg
*A
= Args
.getLastArg(options::OPT_darwin_target_variant_triple
))
236 Opts
.DarwinTargetVariantTriple
= llvm::Triple(A
->getValue());
237 if (Arg
*A
= Args
.getLastArg(OPT_darwin_target_variant_sdk_version_EQ
)) {
238 VersionTuple Version
;
239 if (Version
.tryParse(A
->getValue()))
240 Diags
.Report(diag::err_drv_invalid_value
)
241 << A
->getAsString(Args
) << A
->getValue();
243 Opts
.DarwinTargetVariantSDKVersion
= Version
;
246 Opts
.CPU
= std::string(Args
.getLastArgValue(OPT_target_cpu
));
247 Opts
.Features
= Args
.getAllArgValues(OPT_target_feature
);
249 // Use the default target triple if unspecified.
250 if (Opts
.Triple
.empty())
251 Opts
.Triple
= llvm::sys::getDefaultTargetTriple();
254 Opts
.IncludePaths
= Args
.getAllArgValues(OPT_I
);
255 Opts
.NoInitialTextSection
= Args
.hasArg(OPT_n
);
256 Opts
.SaveTemporaryLabels
= Args
.hasArg(OPT_msave_temp_labels
);
257 // Any DebugInfoKind implies GenDwarfForAssembly.
258 Opts
.GenDwarfForAssembly
= Args
.hasArg(OPT_debug_info_kind_EQ
);
260 if (const Arg
*A
= Args
.getLastArg(OPT_compress_debug_sections_EQ
)) {
261 Opts
.CompressDebugSections
=
262 llvm::StringSwitch
<llvm::DebugCompressionType
>(A
->getValue())
263 .Case("none", llvm::DebugCompressionType::None
)
264 .Case("zlib", llvm::DebugCompressionType::Zlib
)
265 .Case("zstd", llvm::DebugCompressionType::Zstd
)
266 .Default(llvm::DebugCompressionType::None
);
269 Opts
.RelaxELFRelocations
= !Args
.hasArg(OPT_mrelax_relocations_no
);
270 if (auto *DwarfFormatArg
= Args
.getLastArg(OPT_gdwarf64
, OPT_gdwarf32
))
271 Opts
.Dwarf64
= DwarfFormatArg
->getOption().matches(OPT_gdwarf64
);
272 Opts
.DwarfVersion
= getLastArgIntValue(Args
, OPT_dwarf_version_EQ
, 2, Diags
);
273 Opts
.DwarfDebugFlags
=
274 std::string(Args
.getLastArgValue(OPT_dwarf_debug_flags
));
275 Opts
.DwarfDebugProducer
=
276 std::string(Args
.getLastArgValue(OPT_dwarf_debug_producer
));
277 if (const Arg
*A
= Args
.getLastArg(options::OPT_ffile_compilation_dir_EQ
,
278 options::OPT_fdebug_compilation_dir_EQ
))
279 Opts
.DebugCompilationDir
= A
->getValue();
280 Opts
.MainFileName
= std::string(Args
.getLastArgValue(OPT_main_file_name
));
282 for (const auto &Arg
: Args
.getAllArgValues(OPT_fdebug_prefix_map_EQ
)) {
283 auto Split
= StringRef(Arg
).split('=');
284 Opts
.DebugPrefixMap
.emplace_back(Split
.first
, Split
.second
);
288 if (Args
.hasArg(OPT_INPUT
)) {
290 for (const Arg
*A
: Args
.filtered(OPT_INPUT
)) {
292 Opts
.InputFile
= A
->getValue();
295 Diags
.Report(diag::err_drv_unknown_argument
) << A
->getAsString(Args
);
300 Opts
.LLVMArgs
= Args
.getAllArgValues(OPT_mllvm
);
301 Opts
.OutputPath
= std::string(Args
.getLastArgValue(OPT_o
));
302 Opts
.SplitDwarfOutput
=
303 std::string(Args
.getLastArgValue(OPT_split_dwarf_output
));
304 if (Arg
*A
= Args
.getLastArg(OPT_filetype
)) {
305 StringRef Name
= A
->getValue();
306 unsigned OutputType
= StringSwitch
<unsigned>(Name
)
308 .Case("null", FT_Null
)
311 if (OutputType
== ~0U) {
312 Diags
.Report(diag::err_drv_invalid_value
) << A
->getAsString(Args
) << Name
;
315 Opts
.OutputType
= FileType(OutputType
);
317 Opts
.ShowHelp
= Args
.hasArg(OPT_help
);
318 Opts
.ShowVersion
= Args
.hasArg(OPT_version
);
320 // Transliterate Options
321 Opts
.OutputAsmVariant
=
322 getLastArgIntValue(Args
, OPT_output_asm_variant
, 0, Diags
);
323 Opts
.ShowEncoding
= Args
.hasArg(OPT_show_encoding
);
324 Opts
.ShowInst
= Args
.hasArg(OPT_show_inst
);
327 Opts
.RelaxAll
= Args
.hasArg(OPT_mrelax_all
);
328 Opts
.NoExecStack
= Args
.hasArg(OPT_mno_exec_stack
);
329 Opts
.FatalWarnings
= Args
.hasArg(OPT_massembler_fatal_warnings
);
330 Opts
.NoWarn
= Args
.hasArg(OPT_massembler_no_warn
);
331 Opts
.NoTypeCheck
= Args
.hasArg(OPT_mno_type_check
);
332 Opts
.RelocationModel
=
333 std::string(Args
.getLastArgValue(OPT_mrelocation_model
, "pic"));
334 Opts
.TargetABI
= std::string(Args
.getLastArgValue(OPT_target_abi
));
335 Opts
.IncrementalLinkerCompatible
=
336 Args
.hasArg(OPT_mincremental_linker_compatible
);
337 Opts
.SymbolDefs
= Args
.getAllArgValues(OPT_defsym
);
339 // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
340 // EmbedBitcode behaves the same for all embed options for assembly files.
341 if (auto *A
= Args
.getLastArg(OPT_fembed_bitcode_EQ
)) {
342 Opts
.EmbedBitcode
= llvm::StringSwitch
<unsigned>(A
->getValue())
349 if (auto *A
= Args
.getLastArg(OPT_femit_dwarf_unwind_EQ
)) {
350 Opts
.EmitDwarfUnwind
=
351 llvm::StringSwitch
<EmitDwarfUnwindType
>(A
->getValue())
352 .Case("always", EmitDwarfUnwindType::Always
)
353 .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind
)
354 .Case("default", EmitDwarfUnwindType::Default
);
357 Opts
.EmitCompactUnwindNonCanonical
=
358 Args
.hasArg(OPT_femit_compact_unwind_non_canonical
);
360 Opts
.AsSecureLogFile
= Args
.getLastArgValue(OPT_as_secure_log_file
);
365 static std::unique_ptr
<raw_fd_ostream
>
366 getOutputStream(StringRef Path
, DiagnosticsEngine
&Diags
, bool Binary
) {
367 // Make sure that the Out file gets unlinked from the disk if we get a
370 sys::RemoveFileOnSignal(Path
);
373 auto Out
= std::make_unique
<raw_fd_ostream
>(
374 Path
, EC
, (Binary
? sys::fs::OF_None
: sys::fs::OF_TextWithCRLF
));
376 Diags
.Report(diag::err_fe_unable_to_open_output
) << Path
<< EC
.message();
383 static bool ExecuteAssemblerImpl(AssemblerInvocation
&Opts
,
384 DiagnosticsEngine
&Diags
) {
385 // Get the target specific parser.
387 const Target
*TheTarget
= TargetRegistry::lookupTarget(Opts
.Triple
, Error
);
389 return Diags
.Report(diag::err_target_unknown_triple
) << Opts
.Triple
;
391 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> Buffer
=
392 MemoryBuffer::getFileOrSTDIN(Opts
.InputFile
, /*IsText=*/true);
394 if (std::error_code EC
= Buffer
.getError()) {
395 return Diags
.Report(diag::err_fe_error_reading
)
396 << Opts
.InputFile
<< EC
.message();
401 // Tell SrcMgr about this buffer, which is what the parser will pick up.
402 unsigned BufferIndex
= SrcMgr
.AddNewSourceBuffer(std::move(*Buffer
), SMLoc());
404 // Record the location of the include directories so that the lexer can find
406 SrcMgr
.setIncludeDirs(Opts
.IncludePaths
);
408 std::unique_ptr
<MCRegisterInfo
> MRI(TheTarget
->createMCRegInfo(Opts
.Triple
));
409 assert(MRI
&& "Unable to create target register info!");
411 MCTargetOptions MCOptions
;
412 MCOptions
.EmitDwarfUnwind
= Opts
.EmitDwarfUnwind
;
413 MCOptions
.EmitCompactUnwindNonCanonical
= Opts
.EmitCompactUnwindNonCanonical
;
414 MCOptions
.AsSecureLogFile
= Opts
.AsSecureLogFile
;
416 std::unique_ptr
<MCAsmInfo
> MAI(
417 TheTarget
->createMCAsmInfo(*MRI
, Opts
.Triple
, MCOptions
));
418 assert(MAI
&& "Unable to create target asm info!");
420 // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
421 // may be created with a combination of default and explicit settings.
422 MAI
->setCompressDebugSections(Opts
.CompressDebugSections
);
424 MAI
->setRelaxELFRelocations(Opts
.RelaxELFRelocations
);
426 bool IsBinary
= Opts
.OutputType
== AssemblerInvocation::FT_Obj
;
427 if (Opts
.OutputPath
.empty())
428 Opts
.OutputPath
= "-";
429 std::unique_ptr
<raw_fd_ostream
> FDOS
=
430 getOutputStream(Opts
.OutputPath
, Diags
, IsBinary
);
433 std::unique_ptr
<raw_fd_ostream
> DwoOS
;
434 if (!Opts
.SplitDwarfOutput
.empty())
435 DwoOS
= getOutputStream(Opts
.SplitDwarfOutput
, Diags
, IsBinary
);
437 // Build up the feature string from the target feature list.
438 std::string FS
= llvm::join(Opts
.Features
, ",");
440 std::unique_ptr
<MCSubtargetInfo
> STI(
441 TheTarget
->createMCSubtargetInfo(Opts
.Triple
, Opts
.CPU
, FS
));
442 assert(STI
&& "Unable to create subtarget info!");
444 MCContext
Ctx(Triple(Opts
.Triple
), MAI
.get(), MRI
.get(), STI
.get(), &SrcMgr
,
448 if (Opts
.RelocationModel
== "static") {
450 } else if (Opts
.RelocationModel
== "pic") {
453 assert(Opts
.RelocationModel
== "dynamic-no-pic" &&
454 "Invalid PIC model!");
458 // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
459 // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
460 std::unique_ptr
<MCObjectFileInfo
> MOFI(
461 TheTarget
->createMCObjectFileInfo(Ctx
, PIC
));
462 if (Opts
.DarwinTargetVariantTriple
)
463 MOFI
->setDarwinTargetVariantTriple(*Opts
.DarwinTargetVariantTriple
);
464 if (!Opts
.DarwinTargetVariantSDKVersion
.empty())
465 MOFI
->setDarwinTargetVariantSDKVersion(Opts
.DarwinTargetVariantSDKVersion
);
466 Ctx
.setObjectFileInfo(MOFI
.get());
468 if (Opts
.SaveTemporaryLabels
)
469 Ctx
.setAllowTemporaryLabels(false);
470 if (Opts
.GenDwarfForAssembly
)
471 Ctx
.setGenDwarfForAssembly(true);
472 if (!Opts
.DwarfDebugFlags
.empty())
473 Ctx
.setDwarfDebugFlags(StringRef(Opts
.DwarfDebugFlags
));
474 if (!Opts
.DwarfDebugProducer
.empty())
475 Ctx
.setDwarfDebugProducer(StringRef(Opts
.DwarfDebugProducer
));
476 if (!Opts
.DebugCompilationDir
.empty())
477 Ctx
.setCompilationDir(Opts
.DebugCompilationDir
);
479 // If no compilation dir is set, try to use the current directory.
480 SmallString
<128> CWD
;
481 if (!sys::fs::current_path(CWD
))
482 Ctx
.setCompilationDir(CWD
);
484 if (!Opts
.DebugPrefixMap
.empty())
485 for (const auto &KV
: Opts
.DebugPrefixMap
)
486 Ctx
.addDebugPrefixMapEntry(KV
.first
, KV
.second
);
487 if (!Opts
.MainFileName
.empty())
488 Ctx
.setMainFileName(StringRef(Opts
.MainFileName
));
489 Ctx
.setDwarfFormat(Opts
.Dwarf64
? dwarf::DWARF64
: dwarf::DWARF32
);
490 Ctx
.setDwarfVersion(Opts
.DwarfVersion
);
491 if (Opts
.GenDwarfForAssembly
)
492 Ctx
.setGenDwarfRootFile(Opts
.InputFile
,
493 SrcMgr
.getMemoryBuffer(BufferIndex
)->getBuffer());
495 std::unique_ptr
<MCStreamer
> Str
;
497 std::unique_ptr
<MCInstrInfo
> MCII(TheTarget
->createMCInstrInfo());
498 assert(MCII
&& "Unable to create instruction info!");
500 raw_pwrite_stream
*Out
= FDOS
.get();
501 std::unique_ptr
<buffer_ostream
> BOS
;
503 MCOptions
.MCNoWarn
= Opts
.NoWarn
;
504 MCOptions
.MCFatalWarnings
= Opts
.FatalWarnings
;
505 MCOptions
.MCNoTypeCheck
= Opts
.NoTypeCheck
;
506 MCOptions
.ABIName
= Opts
.TargetABI
;
508 // FIXME: There is a bit of code duplication with addPassesToEmitFile.
509 if (Opts
.OutputType
== AssemblerInvocation::FT_Asm
) {
510 MCInstPrinter
*IP
= TheTarget
->createMCInstPrinter(
511 llvm::Triple(Opts
.Triple
), Opts
.OutputAsmVariant
, *MAI
, *MCII
, *MRI
);
513 std::unique_ptr
<MCCodeEmitter
> CE
;
514 if (Opts
.ShowEncoding
)
515 CE
.reset(TheTarget
->createMCCodeEmitter(*MCII
, Ctx
));
516 std::unique_ptr
<MCAsmBackend
> MAB(
517 TheTarget
->createMCAsmBackend(*STI
, *MRI
, MCOptions
));
519 auto FOut
= std::make_unique
<formatted_raw_ostream
>(*Out
);
520 Str
.reset(TheTarget
->createAsmStreamer(
521 Ctx
, std::move(FOut
), /*asmverbose*/ true,
522 /*useDwarfDirectory*/ true, IP
, std::move(CE
), std::move(MAB
),
524 } else if (Opts
.OutputType
== AssemblerInvocation::FT_Null
) {
525 Str
.reset(createNullStreamer(Ctx
));
527 assert(Opts
.OutputType
== AssemblerInvocation::FT_Obj
&&
528 "Invalid file type!");
529 if (!FDOS
->supportsSeeking()) {
530 BOS
= std::make_unique
<buffer_ostream
>(*FDOS
);
534 std::unique_ptr
<MCCodeEmitter
> CE(
535 TheTarget
->createMCCodeEmitter(*MCII
, Ctx
));
536 std::unique_ptr
<MCAsmBackend
> MAB(
537 TheTarget
->createMCAsmBackend(*STI
, *MRI
, MCOptions
));
538 assert(MAB
&& "Unable to create asm backend!");
540 std::unique_ptr
<MCObjectWriter
> OW
=
541 DwoOS
? MAB
->createDwoObjectWriter(*Out
, *DwoOS
)
542 : MAB
->createObjectWriter(*Out
);
544 Triple
T(Opts
.Triple
);
545 Str
.reset(TheTarget
->createMCObjectStreamer(
546 T
, Ctx
, std::move(MAB
), std::move(OW
), std::move(CE
), *STI
,
547 Opts
.RelaxAll
, Opts
.IncrementalLinkerCompatible
,
548 /*DWARFMustBeAtTheEnd*/ true));
549 Str
.get()->initSections(Opts
.NoExecStack
, *STI
);
552 // When -fembed-bitcode is passed to clang_as, a 1-byte marker
553 // is emitted in __LLVM,__asm section if the object file is MachO format.
554 if (Opts
.EmbedBitcode
&& Ctx
.getObjectFileType() == MCContext::IsMachO
) {
555 MCSection
*AsmLabel
= Ctx
.getMachOSection(
556 "__LLVM", "__asm", MachO::S_REGULAR
, 4, SectionKind::getReadOnly());
557 Str
.get()->switchSection(AsmLabel
);
558 Str
.get()->emitZeros(1);
561 // Assembly to object compilation should leverage assembly info.
562 Str
->setUseAssemblerInfoForParsing(true);
566 std::unique_ptr
<MCAsmParser
> Parser(
567 createMCAsmParser(SrcMgr
, Ctx
, *Str
.get(), *MAI
));
569 // FIXME: init MCTargetOptions from sanitizer flags here.
570 std::unique_ptr
<MCTargetAsmParser
> TAP(
571 TheTarget
->createMCAsmParser(*STI
, *Parser
, *MCII
, MCOptions
));
573 Failed
= Diags
.Report(diag::err_target_unknown_triple
) << Opts
.Triple
;
575 // Set values for symbols, if any.
576 for (auto &S
: Opts
.SymbolDefs
) {
577 auto Pair
= StringRef(S
).split('=');
578 auto Sym
= Pair
.first
;
579 auto Val
= Pair
.second
;
581 // We have already error checked this in the driver.
582 Val
.getAsInteger(0, Value
);
583 Ctx
.setSymbolValue(Parser
->getStreamer(), Sym
, Value
);
587 Parser
->setTargetParser(*TAP
.get());
588 Failed
= Parser
->Run(Opts
.NoInitialTextSection
);
594 static bool ExecuteAssembler(AssemblerInvocation
&Opts
,
595 DiagnosticsEngine
&Diags
) {
596 bool Failed
= ExecuteAssemblerImpl(Opts
, Diags
);
598 // Delete output file if there were errors.
600 if (Opts
.OutputPath
!= "-")
601 sys::fs::remove(Opts
.OutputPath
);
602 if (!Opts
.SplitDwarfOutput
.empty() && Opts
.SplitDwarfOutput
!= "-")
603 sys::fs::remove(Opts
.SplitDwarfOutput
);
609 static void LLVMErrorHandler(void *UserData
, const char *Message
,
611 DiagnosticsEngine
&Diags
= *static_cast<DiagnosticsEngine
*>(UserData
);
613 Diags
.Report(diag::err_fe_error_backend
) << Message
;
615 // We cannot recover from llvm errors.
616 sys::Process::Exit(1);
619 int cc1as_main(ArrayRef
<const char *> Argv
, const char *Argv0
, void *MainAddr
) {
620 // Initialize targets and assembly printers/parsers.
621 InitializeAllTargetInfos();
622 InitializeAllTargetMCs();
623 InitializeAllAsmParsers();
625 // Construct our diagnostic client.
626 IntrusiveRefCntPtr
<DiagnosticOptions
> DiagOpts
= new DiagnosticOptions();
627 TextDiagnosticPrinter
*DiagClient
628 = new TextDiagnosticPrinter(errs(), &*DiagOpts
);
629 DiagClient
->setPrefix("clang -cc1as");
630 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID(new DiagnosticIDs());
631 DiagnosticsEngine
Diags(DiagID
, &*DiagOpts
, DiagClient
);
633 // Set an error handler, so that any LLVM backend diagnostics go through our
635 ScopedFatalErrorHandler FatalErrorHandler
636 (LLVMErrorHandler
, static_cast<void*>(&Diags
));
638 // Parse the arguments.
639 AssemblerInvocation Asm
;
640 if (!AssemblerInvocation::CreateFromArgs(Asm
, Argv
, Diags
))
644 getDriverOptTable().printHelp(
645 llvm::outs(), "clang -cc1as [options] file...",
646 "Clang Integrated Assembler", /*ShowHidden=*/false,
647 /*ShowAllAliases=*/false,
648 llvm::opt::Visibility(driver::options::CC1AsOption
));
655 // FIXME: Use a better -version message?
656 if (Asm
.ShowVersion
) {
657 llvm::cl::PrintVersionMessage();
663 // FIXME: Remove this, one day.
664 if (!Asm
.LLVMArgs
.empty()) {
665 unsigned NumArgs
= Asm
.LLVMArgs
.size();
666 auto Args
= std::make_unique
<const char*[]>(NumArgs
+ 2);
667 Args
[0] = "clang (LLVM option parsing)";
668 for (unsigned i
= 0; i
!= NumArgs
; ++i
)
669 Args
[i
+ 1] = Asm
.LLVMArgs
[i
].c_str();
670 Args
[NumArgs
+ 1] = nullptr;
671 llvm::cl::ParseCommandLineOptions(NumArgs
+ 1, Args
.get());
674 // Execute the invocation, unless there were parsing errors.
675 bool Failed
= Diags
.hasErrorOccurred() || ExecuteAssembler(Asm
, Diags
);
677 // If any timers were active but haven't been destroyed yet, print their
679 TimerGroup::printAll(errs());
680 TimerGroup::clearAll();