Path: blob/main/contrib/llvm-project/clang/tools/driver/cc1as_main.cpp
35236 views
//===-- cc1as_main.cpp - Clang Assembler ---------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This is the entry point to the clang -cc1as functionality, which implements9// the direct interface to the LLVM MC based assembler.10//11//===----------------------------------------------------------------------===//1213#include "clang/Basic/Diagnostic.h"14#include "clang/Basic/DiagnosticOptions.h"15#include "clang/Driver/DriverDiagnostic.h"16#include "clang/Driver/Options.h"17#include "clang/Frontend/FrontendDiagnostic.h"18#include "clang/Frontend/TextDiagnosticPrinter.h"19#include "clang/Frontend/Utils.h"20#include "llvm/ADT/STLExtras.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/ADT/StringSwitch.h"23#include "llvm/IR/DataLayout.h"24#include "llvm/MC/MCAsmBackend.h"25#include "llvm/MC/MCAsmInfo.h"26#include "llvm/MC/MCCodeEmitter.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCInstrInfo.h"29#include "llvm/MC/MCObjectFileInfo.h"30#include "llvm/MC/MCObjectWriter.h"31#include "llvm/MC/MCParser/MCAsmParser.h"32#include "llvm/MC/MCParser/MCTargetAsmParser.h"33#include "llvm/MC/MCRegisterInfo.h"34#include "llvm/MC/MCSectionMachO.h"35#include "llvm/MC/MCStreamer.h"36#include "llvm/MC/MCSubtargetInfo.h"37#include "llvm/MC/MCTargetOptions.h"38#include "llvm/MC/TargetRegistry.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/MemoryBuffer.h"47#include "llvm/Support/Path.h"48#include "llvm/Support/Process.h"49#include "llvm/Support/Signals.h"50#include "llvm/Support/SourceMgr.h"51#include "llvm/Support/TargetSelect.h"52#include "llvm/Support/Timer.h"53#include "llvm/Support/raw_ostream.h"54#include "llvm/TargetParser/Host.h"55#include "llvm/TargetParser/Triple.h"56#include <memory>57#include <optional>58#include <system_error>59using namespace clang;60using namespace clang::driver;61using namespace clang::driver::options;62using namespace llvm;63using namespace llvm::opt;6465namespace {6667/// Helper class for representing a single invocation of the assembler.68struct AssemblerInvocation {69/// @name Target Options70/// @{7172/// The name of the target triple to assemble for.73std::string Triple;7475/// If given, the name of the target CPU to determine which instructions76/// are legal.77std::string CPU;7879/// The list of target specific features to enable or disable -- this should80/// be a list of strings starting with '+' or '-'.81std::vector<std::string> Features;8283/// The list of symbol definitions.84std::vector<std::string> SymbolDefs;8586/// @}87/// @name Language Options88/// @{8990std::vector<std::string> IncludePaths;91LLVM_PREFERRED_TYPE(bool)92unsigned NoInitialTextSection : 1;93LLVM_PREFERRED_TYPE(bool)94unsigned SaveTemporaryLabels : 1;95LLVM_PREFERRED_TYPE(bool)96unsigned GenDwarfForAssembly : 1;97LLVM_PREFERRED_TYPE(bool)98unsigned RelaxELFRelocations : 1;99LLVM_PREFERRED_TYPE(bool)100unsigned SSE2AVX : 1;101LLVM_PREFERRED_TYPE(bool)102unsigned Dwarf64 : 1;103unsigned DwarfVersion;104std::string DwarfDebugFlags;105std::string DwarfDebugProducer;106std::string DebugCompilationDir;107llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;108llvm::DebugCompressionType CompressDebugSections =109llvm::DebugCompressionType::None;110std::string MainFileName;111std::string SplitDwarfOutput;112113/// @}114/// @name Frontend Options115/// @{116117std::string InputFile;118std::vector<std::string> LLVMArgs;119std::string OutputPath;120enum FileType {121FT_Asm, ///< Assembly (.s) output, transliterate mode.122FT_Null, ///< No output, for timing purposes.123FT_Obj ///< Object file output.124};125FileType OutputType;126LLVM_PREFERRED_TYPE(bool)127unsigned ShowHelp : 1;128LLVM_PREFERRED_TYPE(bool)129unsigned ShowVersion : 1;130131/// @}132/// @name Transliterate Options133/// @{134135unsigned OutputAsmVariant;136LLVM_PREFERRED_TYPE(bool)137unsigned ShowEncoding : 1;138LLVM_PREFERRED_TYPE(bool)139unsigned ShowInst : 1;140141/// @}142/// @name Assembler Options143/// @{144145LLVM_PREFERRED_TYPE(bool)146unsigned RelaxAll : 1;147LLVM_PREFERRED_TYPE(bool)148unsigned NoExecStack : 1;149LLVM_PREFERRED_TYPE(bool)150unsigned FatalWarnings : 1;151LLVM_PREFERRED_TYPE(bool)152unsigned NoWarn : 1;153LLVM_PREFERRED_TYPE(bool)154unsigned NoTypeCheck : 1;155LLVM_PREFERRED_TYPE(bool)156unsigned IncrementalLinkerCompatible : 1;157LLVM_PREFERRED_TYPE(bool)158unsigned EmbedBitcode : 1;159160/// Whether to emit DWARF unwind info.161EmitDwarfUnwindType EmitDwarfUnwind;162163// Whether to emit compact-unwind for non-canonical entries.164// Note: maybe overriden by other constraints.165LLVM_PREFERRED_TYPE(bool)166unsigned EmitCompactUnwindNonCanonical : 1;167168LLVM_PREFERRED_TYPE(bool)169unsigned Crel : 1;170171/// The name of the relocation model to use.172std::string RelocationModel;173174/// The ABI targeted by the backend. Specified using -target-abi. Empty175/// otherwise.176std::string TargetABI;177178/// Darwin target variant triple, the variant of the deployment target179/// for which the code is being compiled.180std::optional<llvm::Triple> DarwinTargetVariantTriple;181182/// The version of the darwin target variant SDK which was used during the183/// compilation184llvm::VersionTuple DarwinTargetVariantSDKVersion;185186/// The name of a file to use with \c .secure_log_unique directives.187std::string AsSecureLogFile;188/// @}189190public:191AssemblerInvocation() {192Triple = "";193NoInitialTextSection = 0;194InputFile = "-";195OutputPath = "-";196OutputType = FT_Asm;197OutputAsmVariant = 0;198ShowInst = 0;199ShowEncoding = 0;200RelaxAll = 0;201SSE2AVX = 0;202NoExecStack = 0;203FatalWarnings = 0;204NoWarn = 0;205NoTypeCheck = 0;206IncrementalLinkerCompatible = 0;207Dwarf64 = 0;208DwarfVersion = 0;209EmbedBitcode = 0;210EmitDwarfUnwind = EmitDwarfUnwindType::Default;211EmitCompactUnwindNonCanonical = false;212Crel = false;213}214215static bool CreateFromArgs(AssemblerInvocation &Res,216ArrayRef<const char *> Argv,217DiagnosticsEngine &Diags);218};219220}221222bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,223ArrayRef<const char *> Argv,224DiagnosticsEngine &Diags) {225bool Success = true;226227// Parse the arguments.228const OptTable &OptTbl = getDriverOptTable();229230llvm::opt::Visibility VisibilityMask(options::CC1AsOption);231unsigned MissingArgIndex, MissingArgCount;232InputArgList Args =233OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, VisibilityMask);234235// Check for missing argument error.236if (MissingArgCount) {237Diags.Report(diag::err_drv_missing_argument)238<< Args.getArgString(MissingArgIndex) << MissingArgCount;239Success = false;240}241242// Issue errors on unknown arguments.243for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {244auto ArgString = A->getAsString(Args);245std::string Nearest;246if (OptTbl.findNearest(ArgString, Nearest, VisibilityMask) > 1)247Diags.Report(diag::err_drv_unknown_argument) << ArgString;248else249Diags.Report(diag::err_drv_unknown_argument_with_suggestion)250<< ArgString << Nearest;251Success = false;252}253254// Construct the invocation.255256// Target Options257Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));258if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))259Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());260if (Arg *A = Args.getLastArg(OPT_darwin_target_variant_sdk_version_EQ)) {261VersionTuple Version;262if (Version.tryParse(A->getValue()))263Diags.Report(diag::err_drv_invalid_value)264<< A->getAsString(Args) << A->getValue();265else266Opts.DarwinTargetVariantSDKVersion = Version;267}268269Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));270Opts.Features = Args.getAllArgValues(OPT_target_feature);271272// Use the default target triple if unspecified.273if (Opts.Triple.empty())274Opts.Triple = llvm::sys::getDefaultTargetTriple();275276// Language Options277Opts.IncludePaths = Args.getAllArgValues(OPT_I);278Opts.NoInitialTextSection = Args.hasArg(OPT_n);279Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);280// Any DebugInfoKind implies GenDwarfForAssembly.281Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);282283if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections_EQ)) {284Opts.CompressDebugSections =285llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())286.Case("none", llvm::DebugCompressionType::None)287.Case("zlib", llvm::DebugCompressionType::Zlib)288.Case("zstd", llvm::DebugCompressionType::Zstd)289.Default(llvm::DebugCompressionType::None);290}291292Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no);293Opts.SSE2AVX = Args.hasArg(OPT_msse2avx);294if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32))295Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64);296Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);297Opts.DwarfDebugFlags =298std::string(Args.getLastArgValue(OPT_dwarf_debug_flags));299Opts.DwarfDebugProducer =300std::string(Args.getLastArgValue(OPT_dwarf_debug_producer));301if (const Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,302options::OPT_fdebug_compilation_dir_EQ))303Opts.DebugCompilationDir = A->getValue();304Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name));305306for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {307auto Split = StringRef(Arg).split('=');308Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);309}310311// Frontend Options312if (Args.hasArg(OPT_INPUT)) {313bool First = true;314for (const Arg *A : Args.filtered(OPT_INPUT)) {315if (First) {316Opts.InputFile = A->getValue();317First = false;318} else {319Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);320Success = false;321}322}323}324Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);325Opts.OutputPath = std::string(Args.getLastArgValue(OPT_o));326Opts.SplitDwarfOutput =327std::string(Args.getLastArgValue(OPT_split_dwarf_output));328if (Arg *A = Args.getLastArg(OPT_filetype)) {329StringRef Name = A->getValue();330unsigned OutputType = StringSwitch<unsigned>(Name)331.Case("asm", FT_Asm)332.Case("null", FT_Null)333.Case("obj", FT_Obj)334.Default(~0U);335if (OutputType == ~0U) {336Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;337Success = false;338} else339Opts.OutputType = FileType(OutputType);340}341Opts.ShowHelp = Args.hasArg(OPT_help);342Opts.ShowVersion = Args.hasArg(OPT_version);343344// Transliterate Options345Opts.OutputAsmVariant =346getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);347Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);348Opts.ShowInst = Args.hasArg(OPT_show_inst);349350// Assemble Options351Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);352Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);353Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);354Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);355Opts.NoTypeCheck = Args.hasArg(OPT_mno_type_check);356Opts.RelocationModel =357std::string(Args.getLastArgValue(OPT_mrelocation_model, "pic"));358Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi));359Opts.IncrementalLinkerCompatible =360Args.hasArg(OPT_mincremental_linker_compatible);361Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);362363// EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.364// EmbedBitcode behaves the same for all embed options for assembly files.365if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {366Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())367.Case("all", 1)368.Case("bitcode", 1)369.Case("marker", 1)370.Default(0);371}372373if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {374Opts.EmitDwarfUnwind =375llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())376.Case("always", EmitDwarfUnwindType::Always)377.Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)378.Case("default", EmitDwarfUnwindType::Default);379}380381Opts.EmitCompactUnwindNonCanonical =382Args.hasArg(OPT_femit_compact_unwind_non_canonical);383Opts.Crel = Args.hasArg(OPT_crel);384385Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);386387return Success;388}389390static std::unique_ptr<raw_fd_ostream>391getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {392// Make sure that the Out file gets unlinked from the disk if we get a393// SIGINT.394if (Path != "-")395sys::RemoveFileOnSignal(Path);396397std::error_code EC;398auto Out = std::make_unique<raw_fd_ostream>(399Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_TextWithCRLF));400if (EC) {401Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();402return nullptr;403}404405return Out;406}407408static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,409DiagnosticsEngine &Diags) {410// Get the target specific parser.411std::string Error;412const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);413if (!TheTarget)414return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;415416ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =417MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);418419if (std::error_code EC = Buffer.getError()) {420return Diags.Report(diag::err_fe_error_reading)421<< Opts.InputFile << EC.message();422}423424SourceMgr SrcMgr;425426// Tell SrcMgr about this buffer, which is what the parser will pick up.427unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());428429// Record the location of the include directories so that the lexer can find430// it later.431SrcMgr.setIncludeDirs(Opts.IncludePaths);432433std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));434assert(MRI && "Unable to create target register info!");435436MCTargetOptions MCOptions;437MCOptions.MCRelaxAll = Opts.RelaxAll;438MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;439MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;440MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels;441MCOptions.Crel = Opts.Crel;442MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations;443MCOptions.X86Sse2Avx = Opts.SSE2AVX;444MCOptions.CompressDebugSections = Opts.CompressDebugSections;445MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;446447std::unique_ptr<MCAsmInfo> MAI(448TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));449assert(MAI && "Unable to create target asm info!");450451// Ensure MCAsmInfo initialization occurs before any use, otherwise sections452// may be created with a combination of default and explicit settings.453454455bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;456if (Opts.OutputPath.empty())457Opts.OutputPath = "-";458std::unique_ptr<raw_fd_ostream> FDOS =459getOutputStream(Opts.OutputPath, Diags, IsBinary);460if (!FDOS)461return true;462std::unique_ptr<raw_fd_ostream> DwoOS;463if (!Opts.SplitDwarfOutput.empty())464DwoOS = getOutputStream(Opts.SplitDwarfOutput, Diags, IsBinary);465466// Build up the feature string from the target feature list.467std::string FS = llvm::join(Opts.Features, ",");468469std::unique_ptr<MCSubtargetInfo> STI(470TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));471assert(STI && "Unable to create subtarget info!");472473MCContext Ctx(Triple(Opts.Triple), MAI.get(), MRI.get(), STI.get(), &SrcMgr,474&MCOptions);475476bool PIC = false;477if (Opts.RelocationModel == "static") {478PIC = false;479} else if (Opts.RelocationModel == "pic") {480PIC = true;481} else {482assert(Opts.RelocationModel == "dynamic-no-pic" &&483"Invalid PIC model!");484PIC = false;485}486487// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and488// MCObjectFileInfo needs a MCContext reference in order to initialize itself.489std::unique_ptr<MCObjectFileInfo> MOFI(490TheTarget->createMCObjectFileInfo(Ctx, PIC));491if (Opts.DarwinTargetVariantTriple)492MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);493if (!Opts.DarwinTargetVariantSDKVersion.empty())494MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion);495Ctx.setObjectFileInfo(MOFI.get());496497if (Opts.GenDwarfForAssembly)498Ctx.setGenDwarfForAssembly(true);499if (!Opts.DwarfDebugFlags.empty())500Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));501if (!Opts.DwarfDebugProducer.empty())502Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));503if (!Opts.DebugCompilationDir.empty())504Ctx.setCompilationDir(Opts.DebugCompilationDir);505else {506// If no compilation dir is set, try to use the current directory.507SmallString<128> CWD;508if (!sys::fs::current_path(CWD))509Ctx.setCompilationDir(CWD);510}511if (!Opts.DebugPrefixMap.empty())512for (const auto &KV : Opts.DebugPrefixMap)513Ctx.addDebugPrefixMapEntry(KV.first, KV.second);514if (!Opts.MainFileName.empty())515Ctx.setMainFileName(StringRef(Opts.MainFileName));516Ctx.setDwarfFormat(Opts.Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);517Ctx.setDwarfVersion(Opts.DwarfVersion);518if (Opts.GenDwarfForAssembly)519Ctx.setGenDwarfRootFile(Opts.InputFile,520SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());521522std::unique_ptr<MCStreamer> Str;523524std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());525assert(MCII && "Unable to create instruction info!");526527raw_pwrite_stream *Out = FDOS.get();528std::unique_ptr<buffer_ostream> BOS;529530MCOptions.MCNoWarn = Opts.NoWarn;531MCOptions.MCFatalWarnings = Opts.FatalWarnings;532MCOptions.MCNoTypeCheck = Opts.NoTypeCheck;533MCOptions.ShowMCInst = Opts.ShowInst;534MCOptions.AsmVerbose = true;535MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;536MCOptions.ABIName = Opts.TargetABI;537538// FIXME: There is a bit of code duplication with addPassesToEmitFile.539if (Opts.OutputType == AssemblerInvocation::FT_Asm) {540MCInstPrinter *IP = TheTarget->createMCInstPrinter(541llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);542543std::unique_ptr<MCCodeEmitter> CE;544if (Opts.ShowEncoding)545CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));546std::unique_ptr<MCAsmBackend> MAB(547TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));548549auto FOut = std::make_unique<formatted_raw_ostream>(*Out);550Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), IP,551std::move(CE), std::move(MAB)));552} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {553Str.reset(createNullStreamer(Ctx));554} else {555assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&556"Invalid file type!");557if (!FDOS->supportsSeeking()) {558BOS = std::make_unique<buffer_ostream>(*FDOS);559Out = BOS.get();560}561562std::unique_ptr<MCCodeEmitter> CE(563TheTarget->createMCCodeEmitter(*MCII, Ctx));564std::unique_ptr<MCAsmBackend> MAB(565TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));566assert(MAB && "Unable to create asm backend!");567568std::unique_ptr<MCObjectWriter> OW =569DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)570: MAB->createObjectWriter(*Out);571572Triple T(Opts.Triple);573Str.reset(TheTarget->createMCObjectStreamer(574T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));575Str.get()->initSections(Opts.NoExecStack, *STI);576}577578// When -fembed-bitcode is passed to clang_as, a 1-byte marker579// is emitted in __LLVM,__asm section if the object file is MachO format.580if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {581MCSection *AsmLabel = Ctx.getMachOSection(582"__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());583Str.get()->switchSection(AsmLabel);584Str.get()->emitZeros(1);585}586587bool Failed = false;588589std::unique_ptr<MCAsmParser> Parser(590createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));591592// FIXME: init MCTargetOptions from sanitizer flags here.593std::unique_ptr<MCTargetAsmParser> TAP(594TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));595if (!TAP)596Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;597598// Set values for symbols, if any.599for (auto &S : Opts.SymbolDefs) {600auto Pair = StringRef(S).split('=');601auto Sym = Pair.first;602auto Val = Pair.second;603int64_t Value;604// We have already error checked this in the driver.605Val.getAsInteger(0, Value);606Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);607}608609if (!Failed) {610Parser->setTargetParser(*TAP.get());611Failed = Parser->Run(Opts.NoInitialTextSection);612}613614return Failed;615}616617static bool ExecuteAssembler(AssemblerInvocation &Opts,618DiagnosticsEngine &Diags) {619bool Failed = ExecuteAssemblerImpl(Opts, Diags);620621// Delete output file if there were errors.622if (Failed) {623if (Opts.OutputPath != "-")624sys::fs::remove(Opts.OutputPath);625if (!Opts.SplitDwarfOutput.empty() && Opts.SplitDwarfOutput != "-")626sys::fs::remove(Opts.SplitDwarfOutput);627}628629return Failed;630}631632static void LLVMErrorHandler(void *UserData, const char *Message,633bool GenCrashDiag) {634DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);635636Diags.Report(diag::err_fe_error_backend) << Message;637638// We cannot recover from llvm errors.639sys::Process::Exit(1);640}641642int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {643// Initialize targets and assembly printers/parsers.644InitializeAllTargetInfos();645InitializeAllTargetMCs();646InitializeAllAsmParsers();647648// Construct our diagnostic client.649IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();650TextDiagnosticPrinter *DiagClient651= new TextDiagnosticPrinter(errs(), &*DiagOpts);652DiagClient->setPrefix("clang -cc1as");653IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());654DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);655656// Set an error handler, so that any LLVM backend diagnostics go through our657// error handler.658ScopedFatalErrorHandler FatalErrorHandler659(LLVMErrorHandler, static_cast<void*>(&Diags));660661// Parse the arguments.662AssemblerInvocation Asm;663if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))664return 1;665666if (Asm.ShowHelp) {667getDriverOptTable().printHelp(668llvm::outs(), "clang -cc1as [options] file...",669"Clang Integrated Assembler", /*ShowHidden=*/false,670/*ShowAllAliases=*/false,671llvm::opt::Visibility(driver::options::CC1AsOption));672673return 0;674}675676// Honor -version.677//678// FIXME: Use a better -version message?679if (Asm.ShowVersion) {680llvm::cl::PrintVersionMessage();681return 0;682}683684// Honor -mllvm.685//686// FIXME: Remove this, one day.687if (!Asm.LLVMArgs.empty()) {688unsigned NumArgs = Asm.LLVMArgs.size();689auto Args = std::make_unique<const char*[]>(NumArgs + 2);690Args[0] = "clang (LLVM option parsing)";691for (unsigned i = 0; i != NumArgs; ++i)692Args[i + 1] = Asm.LLVMArgs[i].c_str();693Args[NumArgs + 1] = nullptr;694llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());695}696697// Execute the invocation, unless there were parsing errors.698bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);699700// If any timers were active but haven't been destroyed yet, print their701// results now.702TimerGroup::printAll(errs());703TimerGroup::clearAll();704705return !!Failed;706}707708709