cc1as.cpp raw

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