aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/tools/driver
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2024-03-13 13:58:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2024-03-13 14:11:53 +0300
commit11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch)
treefabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/tools/driver
parent9685917341315774aad5733b1793b1e533a88bbb (diff)
downloadydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/tools/driver')
-rw-r--r--contrib/libs/clang16/tools/driver/cc1_main.cpp291
-rw-r--r--contrib/libs/clang16/tools/driver/cc1as_main.cpp673
-rw-r--r--contrib/libs/clang16/tools/driver/cc1gen_reproducer_main.cpp197
-rw-r--r--contrib/libs/clang16/tools/driver/clang-driver.cpp11
-rw-r--r--contrib/libs/clang16/tools/driver/driver.cpp625
-rw-r--r--contrib/libs/clang16/tools/driver/ya.make112
6 files changed, 1909 insertions, 0 deletions
diff --git a/contrib/libs/clang16/tools/driver/cc1_main.cpp b/contrib/libs/clang16/tools/driver/cc1_main.cpp
new file mode 100644
index 0000000000..c79306b6f7
--- /dev/null
+++ b/contrib/libs/clang16/tools/driver/cc1_main.cpp
@@ -0,0 +1,291 @@
+//===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1 functionality, which implements the
+// core compiler functionality along with a number of additional tools for
+// demonstration and testing purposes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Stack.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/FrontendTool/Utils.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/LinkAllPasses.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/BuryPointer.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/TimeProfiler.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
+#include <cstdio>
+
+#ifdef CLANG_HAVE_RLIMITS
+#include <sys/resource.h>
+#endif
+
+using namespace clang;
+using namespace llvm::opt;
+
+//===----------------------------------------------------------------------===//
+// Main driver
+//===----------------------------------------------------------------------===//
+
+static void LLVMErrorHandler(void *UserData, const char *Message,
+ bool GenCrashDiag) {
+ DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
+
+ Diags.Report(diag::err_fe_error_backend) << Message;
+
+ // Run the interrupt handlers to make sure any special cleanups get done, in
+ // particular that we remove files registered with RemoveFileOnSignal.
+ llvm::sys::RunInterruptHandlers();
+
+ // We cannot recover from llvm errors. When reporting a fatal error, exit
+ // with status 70 to generate crash diagnostics. For BSD systems this is
+ // defined as an internal software error. Otherwise, exit with status 1.
+ llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);
+}
+
+#ifdef CLANG_HAVE_RLIMITS
+#if defined(__linux__) && defined(__PIE__)
+static size_t getCurrentStackAllocation() {
+ // If we can't compute the current stack usage, allow for 512K of command
+ // line arguments and environment.
+ size_t Usage = 512 * 1024;
+ if (FILE *StatFile = fopen("/proc/self/stat", "r")) {
+ // We assume that the stack extends from its current address to the end of
+ // the environment space. In reality, there is another string literal (the
+ // program name) after the environment, but this is close enough (we only
+ // need to be within 100K or so).
+ unsigned long StackPtr, EnvEnd;
+ // Disable silly GCC -Wformat warning that complains about length
+ // modifiers on ignored format specifiers. We want to retain these
+ // for documentation purposes even though they have no effect.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#endif
+ if (fscanf(StatFile,
+ "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu "
+ "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu "
+ "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d "
+ "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d",
+ &StackPtr, &EnvEnd) == 2) {
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+ Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd;
+ }
+ fclose(StatFile);
+ }
+ return Usage;
+}
+
+#include <alloca.h>
+
+LLVM_ATTRIBUTE_NOINLINE
+static void ensureStackAddressSpace() {
+ // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
+ // relatively close to the stack (they are only guaranteed to be 128MiB
+ // apart). This results in crashes if we happen to heap-allocate more than
+ // 128MiB before we reach our stack high-water mark.
+ //
+ // To avoid these crashes, ensure that we have sufficient virtual memory
+ // pages allocated before we start running.
+ size_t Curr = getCurrentStackAllocation();
+ const int kTargetStack = DesiredStackSize - 256 * 1024;
+ if (Curr < kTargetStack) {
+ volatile char *volatile Alloc =
+ static_cast<volatile char *>(alloca(kTargetStack - Curr));
+ Alloc[0] = 0;
+ Alloc[kTargetStack - Curr - 1] = 0;
+ }
+}
+#else
+static void ensureStackAddressSpace() {}
+#endif
+
+/// Attempt to ensure that we have at least 8MiB of usable stack space.
+static void ensureSufficientStack() {
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_STACK, &rlim) != 0)
+ return;
+
+ // Increase the soft stack limit to our desired level, if necessary and
+ // possible.
+ if (rlim.rlim_cur != RLIM_INFINITY &&
+ rlim.rlim_cur < rlim_t(DesiredStackSize)) {
+ // Try to allocate sufficient stack.
+ if (rlim.rlim_max == RLIM_INFINITY ||
+ rlim.rlim_max >= rlim_t(DesiredStackSize))
+ rlim.rlim_cur = DesiredStackSize;
+ else if (rlim.rlim_cur == rlim.rlim_max)
+ return;
+ else
+ rlim.rlim_cur = rlim.rlim_max;
+
+ if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||
+ rlim.rlim_cur != DesiredStackSize)
+ return;
+ }
+
+ // We should now have a stack of size at least DesiredStackSize. Ensure
+ // that we can actually use that much, if necessary.
+ ensureStackAddressSpace();
+}
+#else
+static void ensureSufficientStack() {}
+#endif
+
+/// Print supported cpus of the given target.
+static int PrintSupportedCPUs(std::string TargetStr) {
+ std::string Error;
+ const llvm::Target *TheTarget =
+ llvm::TargetRegistry::lookupTarget(TargetStr, Error);
+ if (!TheTarget) {
+ llvm::errs() << Error;
+ return 1;
+ }
+
+ // the target machine will handle the mcpu printing
+ llvm::TargetOptions Options;
+ std::unique_ptr<llvm::TargetMachine> TheTargetMachine(
+ TheTarget->createTargetMachine(TargetStr, "", "+cpuhelp", Options,
+ std::nullopt));
+ return 0;
+}
+
+int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
+ ensureSufficientStack();
+
+ std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+
+ // Register the support for object-file-wrapped Clang modules.
+ auto PCHOps = Clang->getPCHContainerOperations();
+ PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
+ PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
+
+ // Initialize targets first, so that --version shows registered targets.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+
+ // Buffer diagnostics from argument parsing so that we can output them using a
+ // well formed diagnostic object.
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
+
+ // Setup round-trip remarks for the DiagnosticsEngine used in CreateFromArgs.
+ if (find(Argv, StringRef("-Rround-trip-cc1-args")) != Argv.end())
+ Diags.setSeverity(diag::remark_cc1_round_trip_generated,
+ diag::Severity::Remark, {});
+
+ bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),
+ Argv, Diags, Argv0);
+
+ if (Clang->getFrontendOpts().TimeTrace ||
+ !Clang->getFrontendOpts().TimeTracePath.empty()) {
+ Clang->getFrontendOpts().TimeTrace = 1;
+ llvm::timeTraceProfilerInitialize(
+ Clang->getFrontendOpts().TimeTraceGranularity, Argv0);
+ }
+ // --print-supported-cpus takes priority over the actual compilation.
+ if (Clang->getFrontendOpts().PrintSupportedCPUs)
+ return PrintSupportedCPUs(Clang->getTargetOpts().Triple);
+
+ // Infer the builtin include path if unspecified.
+ if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
+ Clang->getHeaderSearchOpts().ResourceDir.empty())
+ Clang->getHeaderSearchOpts().ResourceDir =
+ CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
+
+ // Create the actual diagnostics engine.
+ Clang->createDiagnostics();
+ if (!Clang->hasDiagnostics())
+ return 1;
+
+ // Set an error handler, so that any LLVM backend diagnostics go through our
+ // error handler.
+ llvm::install_fatal_error_handler(LLVMErrorHandler,
+ static_cast<void*>(&Clang->getDiagnostics()));
+
+ DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
+ if (!Success) {
+ Clang->getDiagnosticClient().finish();
+ return 1;
+ }
+
+ // Execute the frontend actions.
+ {
+ llvm::TimeTraceScope TimeScope("ExecuteCompiler");
+ Success = ExecuteCompilerInvocation(Clang.get());
+ }
+
+ // If any timers were active but haven't been destroyed yet, print their
+ // results now. This happens in -disable-free mode.
+ llvm::TimerGroup::printAll(llvm::errs());
+ llvm::TimerGroup::clearAll();
+
+ if (llvm::timeTraceProfilerEnabled()) {
+ SmallString<128> Path(Clang->getFrontendOpts().OutputFile);
+ llvm::sys::path::replace_extension(Path, "json");
+ if (!Clang->getFrontendOpts().TimeTracePath.empty()) {
+ // replace the suffix to '.json' directly
+ SmallString<128> TracePath(Clang->getFrontendOpts().TimeTracePath);
+ if (llvm::sys::fs::is_directory(TracePath))
+ llvm::sys::path::append(TracePath, llvm::sys::path::filename(Path));
+ Path.assign(TracePath);
+ }
+ if (auto profilerOutput = Clang->createOutputFile(
+ Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false,
+ /*useTemporary=*/false)) {
+ llvm::timeTraceProfilerWrite(*profilerOutput);
+ profilerOutput.reset();
+ llvm::timeTraceProfilerCleanup();
+ Clang->clearOutputFiles(false);
+ }
+ }
+
+ // Our error handler depends on the Diagnostics object, which we're
+ // potentially about to delete. Uninstall the handler now so that any
+ // later errors use the default handling behavior instead.
+ llvm::remove_fatal_error_handler();
+
+ // When running with -disable-free, don't do any destruction or shutdown.
+ if (Clang->getFrontendOpts().DisableFree) {
+ llvm::BuryPointer(std::move(Clang));
+ return !Success;
+ }
+
+ return !Success;
+}
diff --git a/contrib/libs/clang16/tools/driver/cc1as_main.cpp b/contrib/libs/clang16/tools/driver/cc1as_main.cpp
new file mode 100644
index 0000000000..f944113476
--- /dev/null
+++ b/contrib/libs/clang16/tools/driver/cc1as_main.cpp
@@ -0,0 +1,673 @@
+//===-- cc1as_main.cpp - Clang Assembler ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1as functionality, which implements
+// the direct interface to the LLVM MC based assembler.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <optional>
+#include <system_error>
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace llvm;
+using namespace llvm::opt;
+
+namespace {
+
+/// Helper class for representing a single invocation of the assembler.
+struct AssemblerInvocation {
+ /// @name Target Options
+ /// @{
+
+ /// The name of the target triple to assemble for.
+ std::string Triple;
+
+ /// If given, the name of the target CPU to determine which instructions
+ /// are legal.
+ std::string CPU;
+
+ /// The list of target specific features to enable or disable -- this should
+ /// be a list of strings starting with '+' or '-'.
+ std::vector<std::string> Features;
+
+ /// The list of symbol definitions.
+ std::vector<std::string> SymbolDefs;
+
+ /// @}
+ /// @name Language Options
+ /// @{
+
+ std::vector<std::string> IncludePaths;
+ unsigned NoInitialTextSection : 1;
+ unsigned SaveTemporaryLabels : 1;
+ unsigned GenDwarfForAssembly : 1;
+ unsigned RelaxELFRelocations : 1;
+ unsigned Dwarf64 : 1;
+ unsigned DwarfVersion;
+ std::string DwarfDebugFlags;
+ std::string DwarfDebugProducer;
+ std::string DebugCompilationDir;
+ std::map<const std::string, const std::string> DebugPrefixMap;
+ llvm::DebugCompressionType CompressDebugSections =
+ llvm::DebugCompressionType::None;
+ std::string MainFileName;
+ std::string SplitDwarfOutput;
+
+ /// @}
+ /// @name Frontend Options
+ /// @{
+
+ std::string InputFile;
+ std::vector<std::string> LLVMArgs;
+ std::string OutputPath;
+ enum FileType {
+ FT_Asm, ///< Assembly (.s) output, transliterate mode.
+ FT_Null, ///< No output, for timing purposes.
+ FT_Obj ///< Object file output.
+ };
+ FileType OutputType;
+ unsigned ShowHelp : 1;
+ unsigned ShowVersion : 1;
+
+ /// @}
+ /// @name Transliterate Options
+ /// @{
+
+ unsigned OutputAsmVariant;
+ unsigned ShowEncoding : 1;
+ unsigned ShowInst : 1;
+
+ /// @}
+ /// @name Assembler Options
+ /// @{
+
+ unsigned RelaxAll : 1;
+ unsigned NoExecStack : 1;
+ unsigned FatalWarnings : 1;
+ unsigned NoWarn : 1;
+ unsigned NoTypeCheck : 1;
+ unsigned IncrementalLinkerCompatible : 1;
+ unsigned EmbedBitcode : 1;
+
+ /// Whether to emit DWARF unwind info.
+ EmitDwarfUnwindType EmitDwarfUnwind;
+
+ /// The name of the relocation model to use.
+ std::string RelocationModel;
+
+ /// The ABI targeted by the backend. Specified using -target-abi. Empty
+ /// otherwise.
+ std::string TargetABI;
+
+ /// Darwin target variant triple, the variant of the deployment target
+ /// for which the code is being compiled.
+ std::optional<llvm::Triple> DarwinTargetVariantTriple;
+
+ /// The version of the darwin target variant SDK which was used during the
+ /// compilation
+ llvm::VersionTuple DarwinTargetVariantSDKVersion;
+
+ /// The name of a file to use with \c .secure_log_unique directives.
+ std::string AsSecureLogFile;
+ /// @}
+
+public:
+ AssemblerInvocation() {
+ Triple = "";
+ NoInitialTextSection = 0;
+ InputFile = "-";
+ OutputPath = "-";
+ OutputType = FT_Asm;
+ OutputAsmVariant = 0;
+ ShowInst = 0;
+ ShowEncoding = 0;
+ RelaxAll = 0;
+ NoExecStack = 0;
+ FatalWarnings = 0;
+ NoWarn = 0;
+ NoTypeCheck = 0;
+ IncrementalLinkerCompatible = 0;
+ Dwarf64 = 0;
+ DwarfVersion = 0;
+ EmbedBitcode = 0;
+ EmitDwarfUnwind = EmitDwarfUnwindType::Default;
+ }
+
+ static bool CreateFromArgs(AssemblerInvocation &Res,
+ ArrayRef<const char *> Argv,
+ DiagnosticsEngine &Diags);
+};
+
+}
+
+bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
+ ArrayRef<const char *> Argv,
+ DiagnosticsEngine &Diags) {
+ bool Success = true;
+
+ // Parse the arguments.
+ const OptTable &OptTbl = getDriverOptTable();
+
+ const unsigned IncludedFlagsBitmask = options::CC1AsOption;
+ unsigned MissingArgIndex, MissingArgCount;
+ InputArgList Args = OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount,
+ IncludedFlagsBitmask);
+
+ // Check for missing argument error.
+ if (MissingArgCount) {
+ Diags.Report(diag::err_drv_missing_argument)
+ << Args.getArgString(MissingArgIndex) << MissingArgCount;
+ Success = false;
+ }
+
+ // Issue errors on unknown arguments.
+ for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
+ auto ArgString = A->getAsString(Args);
+ std::string Nearest;
+ if (OptTbl.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
+ Diags.Report(diag::err_drv_unknown_argument) << ArgString;
+ else
+ Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
+ << ArgString << Nearest;
+ Success = false;
+ }
+
+ // Construct the invocation.
+
+ // Target Options
+ Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
+ if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))
+ Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());
+ if (Arg *A = Args.getLastArg(OPT_darwin_target_variant_sdk_version_EQ)) {
+ VersionTuple Version;
+ if (Version.tryParse(A->getValue()))
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ else
+ Opts.DarwinTargetVariantSDKVersion = Version;
+ }
+
+ Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
+ Opts.Features = Args.getAllArgValues(OPT_target_feature);
+
+ // Use the default target triple if unspecified.
+ if (Opts.Triple.empty())
+ Opts.Triple = llvm::sys::getDefaultTargetTriple();
+
+ // Language Options
+ Opts.IncludePaths = Args.getAllArgValues(OPT_I);
+ Opts.NoInitialTextSection = Args.hasArg(OPT_n);
+ Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
+ // Any DebugInfoKind implies GenDwarfForAssembly.
+ Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
+
+ if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections_EQ)) {
+ Opts.CompressDebugSections =
+ llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
+ .Case("none", llvm::DebugCompressionType::None)
+ .Case("zlib", llvm::DebugCompressionType::Zlib)
+ .Case("zstd", llvm::DebugCompressionType::Zstd)
+ .Default(llvm::DebugCompressionType::None);
+ }
+
+ Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no);
+ if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32))
+ Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64);
+ Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
+ Opts.DwarfDebugFlags =
+ std::string(Args.getLastArgValue(OPT_dwarf_debug_flags));
+ Opts.DwarfDebugProducer =
+ std::string(Args.getLastArgValue(OPT_dwarf_debug_producer));
+ if (const Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
+ options::OPT_fdebug_compilation_dir_EQ))
+ Opts.DebugCompilationDir = A->getValue();
+ Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name));
+
+ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
+ auto Split = StringRef(Arg).split('=');
+ Opts.DebugPrefixMap.insert(
+ {std::string(Split.first), std::string(Split.second)});
+ }
+
+ // Frontend Options
+ if (Args.hasArg(OPT_INPUT)) {
+ bool First = true;
+ for (const Arg *A : Args.filtered(OPT_INPUT)) {
+ if (First) {
+ Opts.InputFile = A->getValue();
+ First = false;
+ } else {
+ Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args);
+ Success = false;
+ }
+ }
+ }
+ Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
+ Opts.OutputPath = std::string(Args.getLastArgValue(OPT_o));
+ Opts.SplitDwarfOutput =
+ std::string(Args.getLastArgValue(OPT_split_dwarf_output));
+ if (Arg *A = Args.getLastArg(OPT_filetype)) {
+ StringRef Name = A->getValue();
+ unsigned OutputType = StringSwitch<unsigned>(Name)
+ .Case("asm", FT_Asm)
+ .Case("null", FT_Null)
+ .Case("obj", FT_Obj)
+ .Default(~0U);
+ if (OutputType == ~0U) {
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+ Success = false;
+ } else
+ Opts.OutputType = FileType(OutputType);
+ }
+ Opts.ShowHelp = Args.hasArg(OPT_help);
+ Opts.ShowVersion = Args.hasArg(OPT_version);
+
+ // Transliterate Options
+ Opts.OutputAsmVariant =
+ getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags);
+ Opts.ShowEncoding = Args.hasArg(OPT_show_encoding);
+ Opts.ShowInst = Args.hasArg(OPT_show_inst);
+
+ // Assemble Options
+ Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
+ Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
+ Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
+ Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);
+ Opts.NoTypeCheck = Args.hasArg(OPT_mno_type_check);
+ Opts.RelocationModel =
+ std::string(Args.getLastArgValue(OPT_mrelocation_model, "pic"));
+ Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi));
+ Opts.IncrementalLinkerCompatible =
+ Args.hasArg(OPT_mincremental_linker_compatible);
+ Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
+
+ // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag.
+ // EmbedBitcode behaves the same for all embed options for assembly files.
+ if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
+ Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("all", 1)
+ .Case("bitcode", 1)
+ .Case("marker", 1)
+ .Default(0);
+ }
+
+ if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
+ Opts.EmitDwarfUnwind =
+ llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
+ .Case("always", EmitDwarfUnwindType::Always)
+ .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
+ .Case("default", EmitDwarfUnwindType::Default);
+ }
+
+ Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
+
+ return Success;
+}
+
+static std::unique_ptr<raw_fd_ostream>
+getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
+ // Make sure that the Out file gets unlinked from the disk if we get a
+ // SIGINT.
+ if (Path != "-")
+ sys::RemoveFileOnSignal(Path);
+
+ std::error_code EC;
+ auto Out = std::make_unique<raw_fd_ostream>(
+ Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_TextWithCRLF));
+ if (EC) {
+ Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
+ return nullptr;
+ }
+
+ return Out;
+}
+
+static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
+ DiagnosticsEngine &Diags) {
+ // Get the target specific parser.
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
+ if (!TheTarget)
+ return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
+
+ ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
+ MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
+
+ if (std::error_code EC = Buffer.getError()) {
+ Error = EC.message();
+ return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
+ }
+
+ SourceMgr SrcMgr;
+
+ // Tell SrcMgr about this buffer, which is what the parser will pick up.
+ unsigned BufferIndex = SrcMgr.AddNewSourceBuffer(std::move(*Buffer), SMLoc());
+
+ // Record the location of the include directories so that the lexer can find
+ // it later.
+ SrcMgr.setIncludeDirs(Opts.IncludePaths);
+
+ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple));
+ assert(MRI && "Unable to create target register info!");
+
+ MCTargetOptions MCOptions;
+ MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
+ MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
+
+ std::unique_ptr<MCAsmInfo> MAI(
+ TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
+ assert(MAI && "Unable to create target asm info!");
+
+ // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
+ // may be created with a combination of default and explicit settings.
+ MAI->setCompressDebugSections(Opts.CompressDebugSections);
+
+ MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
+
+ bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
+ if (Opts.OutputPath.empty())
+ Opts.OutputPath = "-";
+ std::unique_ptr<raw_fd_ostream> FDOS =
+ getOutputStream(Opts.OutputPath, Diags, IsBinary);
+ if (!FDOS)
+ return true;
+ std::unique_ptr<raw_fd_ostream> DwoOS;
+ if (!Opts.SplitDwarfOutput.empty())
+ DwoOS = getOutputStream(Opts.SplitDwarfOutput, Diags, IsBinary);
+
+ // Build up the feature string from the target feature list.
+ std::string FS = llvm::join(Opts.Features, ",");
+
+ std::unique_ptr<MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
+ assert(STI && "Unable to create subtarget info!");
+
+ MCContext Ctx(Triple(Opts.Triple), MAI.get(), MRI.get(), STI.get(), &SrcMgr,
+ &MCOptions);
+
+ bool PIC = false;
+ if (Opts.RelocationModel == "static") {
+ PIC = false;
+ } else if (Opts.RelocationModel == "pic") {
+ PIC = true;
+ } else {
+ assert(Opts.RelocationModel == "dynamic-no-pic" &&
+ "Invalid PIC model!");
+ PIC = false;
+ }
+
+ // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
+ // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
+ std::unique_ptr<MCObjectFileInfo> MOFI(
+ TheTarget->createMCObjectFileInfo(Ctx, PIC));
+ if (Opts.DarwinTargetVariantTriple)
+ MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
+ if (!Opts.DarwinTargetVariantSDKVersion.empty())
+ MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion);
+ Ctx.setObjectFileInfo(MOFI.get());
+
+ if (Opts.SaveTemporaryLabels)
+ Ctx.setAllowTemporaryLabels(false);
+ if (Opts.GenDwarfForAssembly)
+ Ctx.setGenDwarfForAssembly(true);
+ if (!Opts.DwarfDebugFlags.empty())
+ Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags));
+ if (!Opts.DwarfDebugProducer.empty())
+ Ctx.setDwarfDebugProducer(StringRef(Opts.DwarfDebugProducer));
+ if (!Opts.DebugCompilationDir.empty())
+ Ctx.setCompilationDir(Opts.DebugCompilationDir);
+ else {
+ // If no compilation dir is set, try to use the current directory.
+ SmallString<128> CWD;
+ if (!sys::fs::current_path(CWD))
+ Ctx.setCompilationDir(CWD);
+ }
+ if (!Opts.DebugPrefixMap.empty())
+ for (const auto &KV : Opts.DebugPrefixMap)
+ Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
+ if (!Opts.MainFileName.empty())
+ Ctx.setMainFileName(StringRef(Opts.MainFileName));
+ Ctx.setDwarfFormat(Opts.Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);
+ Ctx.setDwarfVersion(Opts.DwarfVersion);
+ if (Opts.GenDwarfForAssembly)
+ Ctx.setGenDwarfRootFile(Opts.InputFile,
+ SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());
+
+ std::unique_ptr<MCStreamer> Str;
+
+ std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
+ assert(MCII && "Unable to create instruction info!");
+
+ raw_pwrite_stream *Out = FDOS.get();
+ std::unique_ptr<buffer_ostream> BOS;
+
+ MCOptions.MCNoWarn = Opts.NoWarn;
+ MCOptions.MCFatalWarnings = Opts.FatalWarnings;
+ MCOptions.MCNoTypeCheck = Opts.NoTypeCheck;
+ MCOptions.ABIName = Opts.TargetABI;
+
+ // FIXME: There is a bit of code duplication with addPassesToEmitFile.
+ if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
+ MCInstPrinter *IP = TheTarget->createMCInstPrinter(
+ llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI);
+
+ std::unique_ptr<MCCodeEmitter> CE;
+ if (Opts.ShowEncoding)
+ CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+
+ auto FOut = std::make_unique<formatted_raw_ostream>(*Out);
+ Str.reset(TheTarget->createAsmStreamer(
+ Ctx, std::move(FOut), /*asmverbose*/ true,
+ /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
+ Opts.ShowInst));
+ } else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
+ Str.reset(createNullStreamer(Ctx));
+ } else {
+ assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
+ "Invalid file type!");
+ if (!FDOS->supportsSeeking()) {
+ BOS = std::make_unique<buffer_ostream>(*FDOS);
+ Out = BOS.get();
+ }
+
+ std::unique_ptr<MCCodeEmitter> CE(
+ TheTarget->createMCCodeEmitter(*MCII, Ctx));
+ std::unique_ptr<MCAsmBackend> MAB(
+ TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
+ assert(MAB && "Unable to create asm backend!");
+
+ std::unique_ptr<MCObjectWriter> OW =
+ DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
+ : MAB->createObjectWriter(*Out);
+
+ Triple T(Opts.Triple);
+ Str.reset(TheTarget->createMCObjectStreamer(
+ T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
+ Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ true));
+ Str.get()->initSections(Opts.NoExecStack, *STI);
+ }
+
+ // When -fembed-bitcode is passed to clang_as, a 1-byte marker
+ // is emitted in __LLVM,__asm section if the object file is MachO format.
+ if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
+ MCSection *AsmLabel = Ctx.getMachOSection(
+ "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
+ Str.get()->switchSection(AsmLabel);
+ Str.get()->emitZeros(1);
+ }
+
+ // Assembly to object compilation should leverage assembly info.
+ Str->setUseAssemblerInfoForParsing(true);
+
+ bool Failed = false;
+
+ std::unique_ptr<MCAsmParser> Parser(
+ createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
+
+ // FIXME: init MCTargetOptions from sanitizer flags here.
+ std::unique_ptr<MCTargetAsmParser> TAP(
+ TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
+ if (!TAP)
+ Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
+
+ // Set values for symbols, if any.
+ for (auto &S : Opts.SymbolDefs) {
+ auto Pair = StringRef(S).split('=');
+ auto Sym = Pair.first;
+ auto Val = Pair.second;
+ int64_t Value;
+ // We have already error checked this in the driver.
+ Val.getAsInteger(0, Value);
+ Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);
+ }
+
+ if (!Failed) {
+ Parser->setTargetParser(*TAP.get());
+ Failed = Parser->Run(Opts.NoInitialTextSection);
+ }
+
+ return Failed;
+}
+
+static bool ExecuteAssembler(AssemblerInvocation &Opts,
+ DiagnosticsEngine &Diags) {
+ bool Failed = ExecuteAssemblerImpl(Opts, Diags);
+
+ // Delete output file if there were errors.
+ if (Failed) {
+ if (Opts.OutputPath != "-")
+ sys::fs::remove(Opts.OutputPath);
+ if (!Opts.SplitDwarfOutput.empty() && Opts.SplitDwarfOutput != "-")
+ sys::fs::remove(Opts.SplitDwarfOutput);
+ }
+
+ return Failed;
+}
+
+static void LLVMErrorHandler(void *UserData, const char *Message,
+ bool GenCrashDiag) {
+ DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
+
+ Diags.Report(diag::err_fe_error_backend) << Message;
+
+ // We cannot recover from llvm errors.
+ sys::Process::Exit(1);
+}
+
+int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
+ // Initialize targets and assembly printers/parsers.
+ InitializeAllTargetInfos();
+ InitializeAllTargetMCs();
+ InitializeAllAsmParsers();
+
+ // Construct our diagnostic client.
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(errs(), &*DiagOpts);
+ DiagClient->setPrefix("clang -cc1as");
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
+
+ // Set an error handler, so that any LLVM backend diagnostics go through our
+ // error handler.
+ ScopedFatalErrorHandler FatalErrorHandler
+ (LLVMErrorHandler, static_cast<void*>(&Diags));
+
+ // Parse the arguments.
+ AssemblerInvocation Asm;
+ if (!AssemblerInvocation::CreateFromArgs(Asm, Argv, Diags))
+ return 1;
+
+ if (Asm.ShowHelp) {
+ getDriverOptTable().printHelp(
+ llvm::outs(), "clang -cc1as [options] file...",
+ "Clang Integrated Assembler",
+ /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
+ /*ShowAllAliases=*/false);
+ return 0;
+ }
+
+ // Honor -version.
+ //
+ // FIXME: Use a better -version message?
+ if (Asm.ShowVersion) {
+ llvm::cl::PrintVersionMessage();
+ return 0;
+ }
+
+ // Honor -mllvm.
+ //
+ // FIXME: Remove this, one day.
+ if (!Asm.LLVMArgs.empty()) {
+ unsigned NumArgs = Asm.LLVMArgs.size();
+ auto Args = std::make_unique<const char*[]>(NumArgs + 2);
+ Args[0] = "clang (LLVM option parsing)";
+ for (unsigned i = 0; i != NumArgs; ++i)
+ Args[i + 1] = Asm.LLVMArgs[i].c_str();
+ Args[NumArgs + 1] = nullptr;
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
+ }
+
+ // Execute the invocation, unless there were parsing errors.
+ bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags);
+
+ // If any timers were active but haven't been destroyed yet, print their
+ // results now.
+ TimerGroup::printAll(errs());
+ TimerGroup::clearAll();
+
+ return !!Failed;
+}
diff --git a/contrib/libs/clang16/tools/driver/cc1gen_reproducer_main.cpp b/contrib/libs/clang16/tools/driver/cc1gen_reproducer_main.cpp
new file mode 100644
index 0000000000..9dbfc518ad
--- /dev/null
+++ b/contrib/libs/clang16/tools/driver/cc1gen_reproducer_main.cpp
@@ -0,0 +1,197 @@
+//===-- cc1gen_reproducer_main.cpp - Clang reproducer generator ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1gen-reproducer functionality, which
+// generates reproducers for invocations for clang-based tools.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <optional>
+
+using namespace clang;
+
+namespace {
+
+struct UnsavedFileHash {
+ std::string Name;
+ std::string MD5;
+};
+
+struct ClangInvocationInfo {
+ std::string Toolchain;
+ std::string LibclangOperation;
+ std::string LibclangOptions;
+ std::vector<std::string> Arguments;
+ std::vector<std::string> InvocationArguments;
+ std::vector<UnsavedFileHash> UnsavedFileHashes;
+ bool Dump = false;
+};
+
+} // end anonymous namespace
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(UnsavedFileHash)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<UnsavedFileHash> {
+ static void mapping(IO &IO, UnsavedFileHash &Info) {
+ IO.mapRequired("name", Info.Name);
+ IO.mapRequired("md5", Info.MD5);
+ }
+};
+
+template <> struct MappingTraits<ClangInvocationInfo> {
+ static void mapping(IO &IO, ClangInvocationInfo &Info) {
+ IO.mapRequired("toolchain", Info.Toolchain);
+ IO.mapOptional("libclang.operation", Info.LibclangOperation);
+ IO.mapOptional("libclang.opts", Info.LibclangOptions);
+ IO.mapRequired("args", Info.Arguments);
+ IO.mapOptional("invocation-args", Info.InvocationArguments);
+ IO.mapOptional("unsaved_file_hashes", Info.UnsavedFileHashes);
+ }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+static std::string generateReproducerMetaInfo(const ClangInvocationInfo &Info) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ OS << '{';
+ bool NeedComma = false;
+ auto EmitKey = [&](StringRef Key) {
+ if (NeedComma)
+ OS << ", ";
+ NeedComma = true;
+ OS << '"' << Key << "\": ";
+ };
+ auto EmitStringKey = [&](StringRef Key, StringRef Value) {
+ if (Value.empty())
+ return;
+ EmitKey(Key);
+ OS << '"' << Value << '"';
+ };
+ EmitStringKey("libclang.operation", Info.LibclangOperation);
+ EmitStringKey("libclang.opts", Info.LibclangOptions);
+ if (!Info.InvocationArguments.empty()) {
+ EmitKey("invocation-args");
+ OS << '[';
+ for (const auto &Arg : llvm::enumerate(Info.InvocationArguments)) {
+ if (Arg.index())
+ OS << ',';
+ OS << '"' << Arg.value() << '"';
+ }
+ OS << ']';
+ }
+ OS << '}';
+ // FIXME: Compare unsaved file hashes and report mismatch in the reproducer.
+ if (Info.Dump)
+ llvm::outs() << "REPRODUCER METAINFO: " << OS.str() << "\n";
+ return std::move(OS.str());
+}
+
+/// Generates a reproducer for a set of arguments from a specific invocation.
+static std::optional<driver::Driver::CompilationDiagnosticReport>
+generateReproducerForInvocationArguments(ArrayRef<const char *> Argv,
+ const ClangInvocationInfo &Info) {
+ using namespace driver;
+ auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Argv[0]);
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions;
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new IgnoringDiagConsumer());
+ ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
+ Driver TheDriver(Argv[0], llvm::sys::getDefaultTargetTriple(), Diags);
+ TheDriver.setTargetAndMode(TargetAndMode);
+
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Argv));
+ if (C && !C->containsError()) {
+ for (const auto &J : C->getJobs()) {
+ if (const Command *Cmd = dyn_cast<Command>(&J)) {
+ Driver::CompilationDiagnosticReport Report;
+ TheDriver.generateCompilationDiagnostics(
+ *C, *Cmd, generateReproducerMetaInfo(Info), &Report);
+ return Report;
+ }
+ }
+ }
+
+ return std::nullopt;
+}
+
+std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes);
+
+static void printReproducerInformation(
+ llvm::raw_ostream &OS, const ClangInvocationInfo &Info,
+ const driver::Driver::CompilationDiagnosticReport &Report) {
+ OS << "REPRODUCER:\n";
+ OS << "{\n";
+ OS << R"("files":[)";
+ for (const auto &File : llvm::enumerate(Report.TemporaryFiles)) {
+ if (File.index())
+ OS << ',';
+ OS << '"' << File.value() << '"';
+ }
+ OS << "]\n}\n";
+}
+
+int cc1gen_reproducer_main(ArrayRef<const char *> Argv, const char *Argv0,
+ void *MainAddr) {
+ if (Argv.size() < 1) {
+ llvm::errs() << "error: missing invocation file\n";
+ return 1;
+ }
+ // Parse the invocation descriptor.
+ StringRef Input = Argv[0];
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+ llvm::MemoryBuffer::getFile(Input, /*IsText=*/true);
+ if (!Buffer) {
+ llvm::errs() << "error: failed to read " << Input << ": "
+ << Buffer.getError().message() << "\n";
+ return 1;
+ }
+ llvm::yaml::Input YAML(Buffer.get()->getBuffer());
+ ClangInvocationInfo InvocationInfo;
+ YAML >> InvocationInfo;
+ if (Argv.size() > 1 && Argv[1] == StringRef("-v"))
+ InvocationInfo.Dump = true;
+
+ // Create an invocation that will produce the reproducer.
+ std::vector<const char *> DriverArgs;
+ for (const auto &Arg : InvocationInfo.Arguments)
+ DriverArgs.push_back(Arg.c_str());
+ std::string Path = GetExecutablePath(Argv0, /*CanonicalPrefixes=*/true);
+ DriverArgs[0] = Path.c_str();
+ std::optional<driver::Driver::CompilationDiagnosticReport> Report =
+ generateReproducerForInvocationArguments(DriverArgs, InvocationInfo);
+
+ // Emit the information about the reproduce files to stdout.
+ int Result = 1;
+ if (Report) {
+ printReproducerInformation(llvm::outs(), InvocationInfo, *Report);
+ Result = 0;
+ }
+
+ // Remove the input file.
+ llvm::sys::fs::remove(Input);
+ return Result;
+}
diff --git a/contrib/libs/clang16/tools/driver/clang-driver.cpp b/contrib/libs/clang16/tools/driver/clang-driver.cpp
new file mode 100644
index 0000000000..c1ae548635
--- /dev/null
+++ b/contrib/libs/clang16/tools/driver/clang-driver.cpp
@@ -0,0 +1,11 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+int clang_main(int argc, char **argv);
+
+int main(int argc, char **argv) { return clang_main(argc, argv); }
diff --git a/contrib/libs/clang16/tools/driver/driver.cpp b/contrib/libs/clang16/tools/driver/driver.cpp
new file mode 100644
index 0000000000..d747412336
--- /dev/null
+++ b/contrib/libs/clang16/tools/driver/driver.cpp
@@ -0,0 +1,625 @@
+//===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang driver; it is a thin wrapper
+// for functionality in the Driver clang library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Driver.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/HeaderInclude.h"
+#include "clang/Basic/Stack.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Frontend/ChainedDiagnosticConsumer.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/SerializedDiagnosticPrinter.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/BuryPointer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+#include <optional>
+#include <set>
+#include <system_error>
+using namespace clang;
+using namespace clang::driver;
+using namespace llvm::opt;
+
+std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
+ if (!CanonicalPrefixes) {
+ SmallString<128> ExecutablePath(Argv0);
+ // Do a PATH lookup if Argv0 isn't a valid path.
+ if (!llvm::sys::fs::exists(ExecutablePath))
+ if (llvm::ErrorOr<std::string> P =
+ llvm::sys::findProgramByName(ExecutablePath))
+ ExecutablePath = *P;
+ return std::string(ExecutablePath.str());
+ }
+
+ // This just needs to be some symbol in the binary; C++ doesn't
+ // allow taking the address of ::main however.
+ void *P = (void*) (intptr_t) GetExecutablePath;
+ return llvm::sys::fs::getMainExecutable(Argv0, P);
+}
+
+static const char *GetStableCStr(std::set<std::string> &SavedStrings,
+ StringRef S) {
+ return SavedStrings.insert(std::string(S)).first->c_str();
+}
+
+/// ApplyQAOverride - Apply a list of edits to the input argument lists.
+///
+/// The input string is a space separate list of edits to perform,
+/// they are applied in order to the input argument lists. Edits
+/// should be one of the following forms:
+///
+/// '#': Silence information about the changes to the command line arguments.
+///
+/// '^': Add FOO as a new argument at the beginning of the command line.
+///
+/// '+': Add FOO as a new argument at the end of the command line.
+///
+/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
+/// line.
+///
+/// 'xOPTION': Removes all instances of the literal argument OPTION.
+///
+/// 'XOPTION': Removes all instances of the literal argument OPTION,
+/// and the following argument.
+///
+/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
+/// at the end of the command line.
+///
+/// \param OS - The stream to write edit information to.
+/// \param Args - The vector of command line arguments.
+/// \param Edit - The override command to perform.
+/// \param SavedStrings - Set to use for storing string representations.
+static void ApplyOneQAOverride(raw_ostream &OS,
+ SmallVectorImpl<const char*> &Args,
+ StringRef Edit,
+ std::set<std::string> &SavedStrings) {
+ // This does not need to be efficient.
+
+ if (Edit[0] == '^') {
+ const char *Str =
+ GetStableCStr(SavedStrings, Edit.substr(1));
+ OS << "### Adding argument " << Str << " at beginning\n";
+ Args.insert(Args.begin() + 1, Str);
+ } else if (Edit[0] == '+') {
+ const char *Str =
+ GetStableCStr(SavedStrings, Edit.substr(1));
+ OS << "### Adding argument " << Str << " at end\n";
+ Args.push_back(Str);
+ } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
+ Edit.slice(2, Edit.size() - 1).contains('/')) {
+ StringRef MatchPattern = Edit.substr(2).split('/').first;
+ StringRef ReplPattern = Edit.substr(2).split('/').second;
+ ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
+
+ for (unsigned i = 1, e = Args.size(); i != e; ++i) {
+ // Ignore end-of-line response file markers
+ if (Args[i] == nullptr)
+ continue;
+ std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
+
+ if (Repl != Args[i]) {
+ OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
+ Args[i] = GetStableCStr(SavedStrings, Repl);
+ }
+ }
+ } else if (Edit[0] == 'x' || Edit[0] == 'X') {
+ auto Option = Edit.substr(1);
+ for (unsigned i = 1; i < Args.size();) {
+ if (Option == Args[i]) {
+ OS << "### Deleting argument " << Args[i] << '\n';
+ Args.erase(Args.begin() + i);
+ if (Edit[0] == 'X') {
+ if (i < Args.size()) {
+ OS << "### Deleting argument " << Args[i] << '\n';
+ Args.erase(Args.begin() + i);
+ } else
+ OS << "### Invalid X edit, end of command line!\n";
+ }
+ } else
+ ++i;
+ }
+ } else if (Edit[0] == 'O') {
+ for (unsigned i = 1; i < Args.size();) {
+ const char *A = Args[i];
+ // Ignore end-of-line response file markers
+ if (A == nullptr)
+ continue;
+ if (A[0] == '-' && A[1] == 'O' &&
+ (A[2] == '\0' ||
+ (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
+ ('0' <= A[2] && A[2] <= '9'))))) {
+ OS << "### Deleting argument " << Args[i] << '\n';
+ Args.erase(Args.begin() + i);
+ } else
+ ++i;
+ }
+ OS << "### Adding argument " << Edit << " at end\n";
+ Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));
+ } else {
+ OS << "### Unrecognized edit: " << Edit << "\n";
+ }
+}
+
+/// ApplyQAOverride - Apply a comma separate list of edits to the
+/// input argument lists. See ApplyOneQAOverride.
+static void ApplyQAOverride(SmallVectorImpl<const char*> &Args,
+ const char *OverrideStr,
+ std::set<std::string> &SavedStrings) {
+ raw_ostream *OS = &llvm::errs();
+
+ if (OverrideStr[0] == '#') {
+ ++OverrideStr;
+ OS = &llvm::nulls();
+ }
+
+ *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n";
+
+ // This does not need to be efficient.
+
+ const char *S = OverrideStr;
+ while (*S) {
+ const char *End = ::strchr(S, ' ');
+ if (!End)
+ End = S + strlen(S);
+ if (End != S)
+ ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
+ S = End;
+ if (*S != '\0')
+ ++S;
+ }
+}
+
+extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
+ void *MainAddr);
+extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
+ void *MainAddr);
+extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv,
+ const char *Argv0, void *MainAddr);
+
+static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
+ SmallVectorImpl<const char *> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ // Put target and mode arguments at the start of argument list so that
+ // arguments specified in command line could override them. Avoid putting
+ // them at index 0, as an option like '-cc1' must remain the first.
+ int InsertionPoint = 0;
+ if (ArgVector.size() > 0)
+ ++InsertionPoint;
+
+ if (NameParts.DriverMode) {
+ // Add the mode flag to the arguments.
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
+ GetStableCStr(SavedStrings, NameParts.DriverMode));
+ }
+
+ if (NameParts.TargetIsValid) {
+ const char *arr[] = {"-target", GetStableCStr(SavedStrings,
+ NameParts.TargetPrefix)};
+ ArgVector.insert(ArgVector.begin() + InsertionPoint,
+ std::begin(arr), std::end(arr));
+ }
+}
+
+static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
+ SmallVectorImpl<const char *> &Opts) {
+ llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts);
+ // The first instance of '#' should be replaced with '=' in each option.
+ for (const char *Opt : Opts)
+ if (char *NumberSignPtr = const_cast<char *>(::strchr(Opt, '#')))
+ *NumberSignPtr = '=';
+}
+
+template <class T>
+static T checkEnvVar(const char *EnvOptSet, const char *EnvOptFile,
+ std::string &OptFile) {
+ const char *Str = ::getenv(EnvOptSet);
+ if (!Str)
+ return T{};
+
+ T OptVal = Str;
+ if (const char *Var = ::getenv(EnvOptFile))
+ OptFile = Var;
+ return OptVal;
+}
+
+static bool SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
+ TheDriver.CCPrintOptions =
+ checkEnvVar<bool>("CC_PRINT_OPTIONS", "CC_PRINT_OPTIONS_FILE",
+ TheDriver.CCPrintOptionsFilename);
+ if (checkEnvVar<bool>("CC_PRINT_HEADERS", "CC_PRINT_HEADERS_FILE",
+ TheDriver.CCPrintHeadersFilename)) {
+ TheDriver.CCPrintHeadersFormat = HIFMT_Textual;
+ TheDriver.CCPrintHeadersFiltering = HIFIL_None;
+ } else {
+ std::string EnvVar = checkEnvVar<std::string>(
+ "CC_PRINT_HEADERS_FORMAT", "CC_PRINT_HEADERS_FILE",
+ TheDriver.CCPrintHeadersFilename);
+ if (!EnvVar.empty()) {
+ TheDriver.CCPrintHeadersFormat =
+ stringToHeaderIncludeFormatKind(EnvVar.c_str());
+ if (!TheDriver.CCPrintHeadersFormat) {
+ TheDriver.Diag(clang::diag::err_drv_print_header_env_var)
+ << 0 << EnvVar;
+ return false;
+ }
+
+ const char *FilteringStr = ::getenv("CC_PRINT_HEADERS_FILTERING");
+ HeaderIncludeFilteringKind Filtering;
+ if (!stringToHeaderIncludeFiltering(FilteringStr, Filtering)) {
+ TheDriver.Diag(clang::diag::err_drv_print_header_env_var)
+ << 1 << FilteringStr;
+ return false;
+ }
+
+ if ((TheDriver.CCPrintHeadersFormat == HIFMT_Textual &&
+ Filtering != HIFIL_None) ||
+ (TheDriver.CCPrintHeadersFormat == HIFMT_JSON &&
+ Filtering != HIFIL_Only_Direct_System)) {
+ TheDriver.Diag(clang::diag::err_drv_print_header_env_var_combination)
+ << EnvVar << FilteringStr;
+ return false;
+ }
+ TheDriver.CCPrintHeadersFiltering = Filtering;
+ }
+ }
+
+ TheDriver.CCLogDiagnostics =
+ checkEnvVar<bool>("CC_LOG_DIAGNOSTICS", "CC_LOG_DIAGNOSTICS_FILE",
+ TheDriver.CCLogDiagnosticsFilename);
+ TheDriver.CCPrintProcessStats =
+ checkEnvVar<bool>("CC_PRINT_PROC_STAT", "CC_PRINT_PROC_STAT_FILE",
+ TheDriver.CCPrintStatReportFilename);
+
+ return true;
+}
+
+static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
+ const std::string &Path) {
+ // If the clang binary happens to be named cl.exe for compatibility reasons,
+ // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC.
+ StringRef ExeBasename(llvm::sys::path::stem(Path));
+ if (ExeBasename.equals_insensitive("cl"))
+ ExeBasename = "clang-cl";
+ DiagClient->setPrefix(std::string(ExeBasename));
+}
+
+static void SetInstallDir(SmallVectorImpl<const char *> &argv,
+ Driver &TheDriver, bool CanonicalPrefixes) {
+ // Attempt to find the original path used to invoke the driver, to determine
+ // the installed path. We do this manually, because we want to support that
+ // path being a symlink.
+ SmallString<128> InstalledPath(argv[0]);
+
+ // Do a PATH lookup, if there are no directory components.
+ if (llvm::sys::path::filename(InstalledPath) == InstalledPath)
+ if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName(
+ llvm::sys::path::filename(InstalledPath.str())))
+ InstalledPath = *Tmp;
+
+ // FIXME: We don't actually canonicalize this, we just make it absolute.
+ if (CanonicalPrefixes)
+ llvm::sys::fs::make_absolute(InstalledPath);
+
+ StringRef InstalledPathParent(llvm::sys::path::parent_path(InstalledPath));
+ if (llvm::sys::fs::exists(InstalledPathParent))
+ TheDriver.setInstalledDir(InstalledPathParent);
+}
+
+static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV) {
+ // If we call the cc1 tool from the clangDriver library (through
+ // Driver::CC1Main), we need to clean up the options usage count. The options
+ // are currently global, and they might have been used previously by the
+ // driver.
+ llvm::cl::ResetAllOptionOccurrences();
+
+ llvm::BumpPtrAllocator A;
+ llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine);
+ if (llvm::Error Err = ECtx.expandResponseFiles(ArgV)) {
+ llvm::errs() << toString(std::move(Err)) << '\n';
+ return 1;
+ }
+ StringRef Tool = ArgV[1];
+ void *GetExecutablePathVP = (void *)(intptr_t)GetExecutablePath;
+ if (Tool == "-cc1")
+ return cc1_main(ArrayRef(ArgV).slice(1), ArgV[0], GetExecutablePathVP);
+ if (Tool == "-cc1as")
+ return cc1as_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP);
+ if (Tool == "-cc1gen-reproducer")
+ return cc1gen_reproducer_main(ArrayRef(ArgV).slice(2), ArgV[0],
+ GetExecutablePathVP);
+ // Reject unknown tools.
+ llvm::errs() << "error: unknown integrated tool '" << Tool << "'. "
+ << "Valid tools include '-cc1' and '-cc1as'.\n";
+ return 1;
+}
+
+int clang_main(int Argc, char **Argv) {
+ noteBottomOfStack();
+ llvm::InitLLVM X(Argc, Argv);
+ llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL
+ " and include the crash backtrace, preprocessed "
+ "source, and associated run script.\n");
+ SmallVector<const char *, 256> Args(Argv, Argv + Argc);
+
+ if (llvm::sys::Process::FixupStandardFileDescriptors())
+ return 1;
+
+ llvm::InitializeAllTargets();
+
+ llvm::BumpPtrAllocator A;
+ llvm::StringSaver Saver(A);
+
+ // Parse response files using the GNU syntax, unless we're in CL mode. There
+ // are two ways to put clang in CL compatibility mode: Args[0] is either
+ // clang-cl or cl, or --driver-mode=cl is on the command line. The normal
+ // command line parsing can't happen until after response file parsing, so we
+ // have to manually search for a --driver-mode=cl argument the hard way.
+ // Finally, our -cc1 tools don't care which tokenization mode we use because
+ // response files written by clang will tokenize the same way in either mode.
+ bool ClangCLMode =
+ IsClangCL(getDriverMode(Args[0], llvm::ArrayRef(Args).slice(1)));
+ enum { Default, POSIX, Windows } RSPQuoting = Default;
+ for (const char *F : Args) {
+ if (strcmp(F, "--rsp-quoting=posix") == 0)
+ RSPQuoting = POSIX;
+ else if (strcmp(F, "--rsp-quoting=windows") == 0)
+ RSPQuoting = Windows;
+ }
+
+ // Determines whether we want nullptr markers in Args to indicate response
+ // files end-of-lines. We only use this for the /LINK driver argument with
+ // clang-cl.exe on Windows.
+ bool MarkEOLs = ClangCLMode;
+
+ llvm::cl::TokenizerCallback Tokenizer;
+ if (RSPQuoting == Windows || (RSPQuoting == Default && ClangCLMode))
+ Tokenizer = &llvm::cl::TokenizeWindowsCommandLine;
+ else
+ Tokenizer = &llvm::cl::TokenizeGNUCommandLine;
+
+ if (MarkEOLs && Args.size() > 1 && StringRef(Args[1]).startswith("-cc1"))
+ MarkEOLs = false;
+ llvm::cl::ExpansionContext ECtx(A, Tokenizer);
+ ECtx.setMarkEOLs(MarkEOLs);
+ if (llvm::Error Err = ECtx.expandResponseFiles(Args)) {
+ llvm::errs() << toString(std::move(Err)) << '\n';
+ return 1;
+ }
+
+ // Handle -cc1 integrated tools, even if -cc1 was expanded from a response
+ // file.
+ auto FirstArg = llvm::find_if(llvm::drop_begin(Args),
+ [](const char *A) { return A != nullptr; });
+ if (FirstArg != Args.end() && StringRef(*FirstArg).startswith("-cc1")) {
+ // If -cc1 came from a response file, remove the EOL sentinels.
+ if (MarkEOLs) {
+ auto newEnd = std::remove(Args.begin(), Args.end(), nullptr);
+ Args.resize(newEnd - Args.begin());
+ }
+ return ExecuteCC1Tool(Args);
+ }
+
+ // Handle options that need handling before the real command line parsing in
+ // Driver::BuildCompilation()
+ bool CanonicalPrefixes = true;
+ for (int i = 1, size = Args.size(); i < size; ++i) {
+ // Skip end-of-line response file markers
+ if (Args[i] == nullptr)
+ continue;
+ if (StringRef(Args[i]) == "-canonical-prefixes")
+ CanonicalPrefixes = true;
+ else if (StringRef(Args[i]) == "-no-canonical-prefixes")
+ CanonicalPrefixes = false;
+ }
+
+ // Handle CL and _CL_ which permits additional command line options to be
+ // prepended or appended.
+ if (ClangCLMode) {
+ // Arguments in "CL" are prepended.
+ std::optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
+ if (OptCL) {
+ SmallVector<const char *, 8> PrependedOpts;
+ getCLEnvVarOptions(*OptCL, Saver, PrependedOpts);
+
+ // Insert right after the program name to prepend to the argument list.
+ Args.insert(Args.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());
+ }
+ // Arguments in "_CL_" are appended.
+ std::optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");
+ if (Opt_CL_) {
+ SmallVector<const char *, 8> AppendedOpts;
+ getCLEnvVarOptions(*Opt_CL_, Saver, AppendedOpts);
+
+ // Insert at the end of the argument list to append.
+ Args.append(AppendedOpts.begin(), AppendedOpts.end());
+ }
+ }
+
+ std::set<std::string> SavedStrings;
+ // Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the
+ // scenes.
+ if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) {
+ // FIXME: Driver shouldn't take extra initial argument.
+ ApplyQAOverride(Args, OverrideStr, SavedStrings);
+ }
+
+ std::string Path = GetExecutablePath(Args[0], CanonicalPrefixes);
+
+ // Whether the cc1 tool should be called inside the current process, or if we
+ // should spawn a new clang subprocess (old behavior).
+ // Not having an additional process saves some execution time of Windows,
+ // and makes debugging and profiling easier.
+ bool UseNewCC1Process = CLANG_SPAWN_CC1;
+ for (const char *Arg : Args)
+ UseNewCC1Process = llvm::StringSwitch<bool>(Arg)
+ .Case("-fno-integrated-cc1", true)
+ .Case("-fintegrated-cc1", false)
+ .Default(UseNewCC1Process);
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
+ CreateAndPopulateDiagOpts(Args);
+
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
+ FixupDiagPrefixExeName(DiagClient, Path);
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
+
+ if (!DiagOpts->DiagnosticSerializationFile.empty()) {
+ auto SerializedConsumer =
+ clang::serialized_diags::create(DiagOpts->DiagnosticSerializationFile,
+ &*DiagOpts, /*MergeChildRecords=*/true);
+ Diags.setClient(new ChainedDiagnosticConsumer(
+ Diags.takeClient(), std::move(SerializedConsumer)));
+ }
+
+ ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
+
+ Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
+ SetInstallDir(Args, TheDriver, CanonicalPrefixes);
+ auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Args[0]);
+ TheDriver.setTargetAndMode(TargetAndMode);
+
+ insertTargetAndModeArgs(TargetAndMode, Args, SavedStrings);
+
+ if (!SetBackdoorDriverOutputsFromEnvVars(TheDriver))
+ return 1;
+
+ if (!UseNewCC1Process) {
+ TheDriver.CC1Main = &ExecuteCC1Tool;
+ // Ensure the CC1Command actually catches cc1 crashes
+ llvm::CrashRecoveryContext::Enable();
+ }
+
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args));
+
+ Driver::ReproLevel ReproLevel = Driver::ReproLevel::OnCrash;
+ if (Arg *A = C->getArgs().getLastArg(options::OPT_gen_reproducer_eq)) {
+ auto Level =
+ llvm::StringSwitch<std::optional<Driver::ReproLevel>>(A->getValue())
+ .Case("off", Driver::ReproLevel::Off)
+ .Case("crash", Driver::ReproLevel::OnCrash)
+ .Case("error", Driver::ReproLevel::OnError)
+ .Case("always", Driver::ReproLevel::Always)
+ .Default(std::nullopt);
+ if (!Level) {
+ llvm::errs() << "Unknown value for " << A->getSpelling() << ": '"
+ << A->getValue() << "'\n";
+ return 1;
+ }
+ ReproLevel = *Level;
+ }
+ if (!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
+ ReproLevel = Driver::ReproLevel::Always;
+
+ int Res = 1;
+ bool IsCrash = false;
+ Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok;
+ // Pretend the first command failed if ReproStatus is Always.
+ const Command *FailingCommand = nullptr;
+ if (!C->getJobs().empty())
+ FailingCommand = &*C->getJobs().begin();
+ if (C && !C->containsError()) {
+ SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
+ Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
+
+ for (const auto &P : FailingCommands) {
+ int CommandRes = P.first;
+ FailingCommand = P.second;
+ if (!Res)
+ Res = CommandRes;
+
+ // If result status is < 0, then the driver command signalled an error.
+ // If result status is 70, then the driver command reported a fatal error.
+ // On Windows, abort will return an exit code of 3. In these cases,
+ // generate additional diagnostic information if possible.
+ IsCrash = CommandRes < 0 || CommandRes == 70;
+#ifdef _WIN32
+ IsCrash |= CommandRes == 3;
+#endif
+#if LLVM_ON_UNIX
+ // When running in integrated-cc1 mode, the CrashRecoveryContext returns
+ // the same codes as if the program crashed. See section "Exit Status for
+ // Commands":
+ // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
+ IsCrash |= CommandRes > 128;
+#endif
+ CommandStatus =
+ IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error;
+ if (IsCrash)
+ break;
+ }
+ }
+
+ // Print the bug report message that would be printed if we did actually
+ // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH.
+ if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
+ llvm::dbgs() << llvm::getBugReportMsg();
+ if (FailingCommand != nullptr &&
+ TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel,
+ *C, *FailingCommand))
+ Res = 1;
+
+ Diags.getClient()->finish();
+
+ if (!UseNewCC1Process && IsCrash) {
+ // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because
+ // the internal linked list might point to already released stack frames.
+ llvm::BuryPointer(llvm::TimerGroup::aquireDefaultGroup());
+ } else {
+ // If any timers were active but haven't been destroyed yet, print their
+ // results now. This happens in -disable-free mode.
+ llvm::TimerGroup::printAll(llvm::errs());
+ llvm::TimerGroup::clearAll();
+ }
+
+#ifdef _WIN32
+ // Exit status should not be negative on Win32, unless abnormal termination.
+ // Once abnormal termination was caught, negative status should not be
+ // propagated.
+ if (Res < 0)
+ Res = 1;
+#endif
+
+ // If we have multiple failing commands, we return the result of the first
+ // failing command.
+ return Res;
+}
diff --git a/contrib/libs/clang16/tools/driver/ya.make b/contrib/libs/clang16/tools/driver/ya.make
new file mode 100644
index 0000000000..b0fb76cc26
--- /dev/null
+++ b/contrib/libs/clang16/tools/driver/ya.make
@@ -0,0 +1,112 @@
+# Generated by devtools/yamaker.
+
+PROGRAM(clang)
+
+LICENSE(Apache-2.0 WITH LLVM-exception)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+PEERDIR(
+ contrib/libs/clang16
+ contrib/libs/clang16/include
+ contrib/libs/clang16/lib/ARCMigrate
+ contrib/libs/clang16/lib/AST
+ contrib/libs/clang16/lib/ASTMatchers
+ contrib/libs/clang16/lib/Analysis
+ contrib/libs/clang16/lib/Basic
+ contrib/libs/clang16/lib/CodeGen
+ contrib/libs/clang16/lib/CrossTU
+ contrib/libs/clang16/lib/Driver
+ contrib/libs/clang16/lib/Edit
+ contrib/libs/clang16/lib/ExtractAPI
+ contrib/libs/clang16/lib/Format
+ contrib/libs/clang16/lib/Frontend
+ contrib/libs/clang16/lib/Frontend/Rewrite
+ contrib/libs/clang16/lib/FrontendTool
+ contrib/libs/clang16/lib/Index
+ contrib/libs/clang16/lib/Lex
+ contrib/libs/clang16/lib/Parse
+ contrib/libs/clang16/lib/Rewrite
+ contrib/libs/clang16/lib/Sema
+ contrib/libs/clang16/lib/Serialization
+ contrib/libs/clang16/lib/StaticAnalyzer/Checkers
+ contrib/libs/clang16/lib/StaticAnalyzer/Core
+ contrib/libs/clang16/lib/StaticAnalyzer/Frontend
+ contrib/libs/clang16/lib/Support
+ contrib/libs/clang16/lib/Tooling/Core
+ contrib/libs/clang16/lib/Tooling/Inclusions
+ contrib/libs/llvm16
+ contrib/libs/llvm16/lib/Analysis
+ contrib/libs/llvm16/lib/CodeGen
+ contrib/libs/llvm16/lib/IR
+ contrib/libs/llvm16/lib/MC
+ contrib/libs/llvm16/lib/MC/MCParser
+ contrib/libs/llvm16/lib/Option
+ contrib/libs/llvm16/lib/Support
+ contrib/libs/llvm16/lib/Target/AArch64
+ contrib/libs/llvm16/lib/Target/AArch64/AsmParser
+ contrib/libs/llvm16/lib/Target/AArch64/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/AArch64/TargetInfo
+ contrib/libs/llvm16/lib/Target/ARM
+ contrib/libs/llvm16/lib/Target/ARM/AsmParser
+ contrib/libs/llvm16/lib/Target/ARM/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/ARM/TargetInfo
+ contrib/libs/llvm16/lib/Target/BPF
+ contrib/libs/llvm16/lib/Target/BPF/AsmParser
+ contrib/libs/llvm16/lib/Target/BPF/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/BPF/TargetInfo
+ contrib/libs/llvm16/lib/Target/LoongArch
+ contrib/libs/llvm16/lib/Target/LoongArch/AsmParser
+ contrib/libs/llvm16/lib/Target/LoongArch/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/LoongArch/TargetInfo
+ contrib/libs/llvm16/lib/Target/NVPTX
+ contrib/libs/llvm16/lib/Target/NVPTX/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/NVPTX/TargetInfo
+ contrib/libs/llvm16/lib/Target/PowerPC
+ contrib/libs/llvm16/lib/Target/PowerPC/AsmParser
+ contrib/libs/llvm16/lib/Target/PowerPC/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/PowerPC/TargetInfo
+ contrib/libs/llvm16/lib/Target/WebAssembly
+ contrib/libs/llvm16/lib/Target/WebAssembly/AsmParser
+ contrib/libs/llvm16/lib/Target/WebAssembly/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/WebAssembly/TargetInfo
+ contrib/libs/llvm16/lib/Target/X86
+ contrib/libs/llvm16/lib/Target/X86/AsmParser
+ contrib/libs/llvm16/lib/Target/X86/MCTargetDesc
+ contrib/libs/llvm16/lib/Target/X86/TargetInfo
+ contrib/libs/llvm16/lib/TargetParser
+ contrib/libs/llvm16/lib/Transforms/IPO
+ contrib/libs/llvm16/lib/Transforms/InstCombine
+ contrib/libs/llvm16/lib/Transforms/ObjCARC
+ contrib/libs/llvm16/lib/Transforms/Scalar
+ contrib/libs/llvm16/lib/Transforms/Utils
+ contrib/libs/llvm16/lib/Transforms/Vectorize
+)
+
+IF (ALLOCATOR == TCMALLOC_TC)
+ PEERDIR(
+ library/cpp/tcmalloc
+ )
+ENDIF()
+
+ADDINCL(
+ contrib/libs/clang16/tools/driver
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+SRCS(
+ cc1_main.cpp
+ cc1as_main.cpp
+ cc1gen_reproducer_main.cpp
+ clang-driver.cpp
+ driver.cpp
+)
+
+IF (OS_WINDOWS)
+ LDFLAGS(/STACK:8388608)
+ENDIF()
+
+END()