diff --git a/src/zig_clang_cc1_main.cpp b/src/zig_clang_cc1_main.cpp index c79306b6f7..9e7f8679b4 100644 --- a/src/zig_clang_cc1_main.cpp +++ b/src/zig_clang_cc1_main.cpp @@ -213,9 +213,7 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, Diags, Argv0); - if (Clang->getFrontendOpts().TimeTrace || - !Clang->getFrontendOpts().TimeTracePath.empty()) { - Clang->getFrontendOpts().TimeTrace = 1; + if (!Clang->getFrontendOpts().TimeTracePath.empty()) { llvm::timeTraceProfilerInitialize( Clang->getFrontendOpts().TimeTraceGranularity, Argv0); } @@ -257,17 +255,21 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { 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); - } + // It is possible that the compiler instance doesn't own a file manager here + // if we're compiling a module unit. Since the file manager are owned by AST + // when we're compiling a module unit. So the file manager may be invalid + // here. + // + // It should be fine to create file manager here since the file system + // options are stored in the compiler invocation and we can recreate the VFS + // from the compiler invocation. + if (!Clang->hasFileManager()) + Clang->createFileManager(createVFSFromCompilerInvocation( + Clang->getInvocation(), Clang->getDiagnostics())); + if (auto profilerOutput = Clang->createOutputFile( - Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false, + Clang->getFrontendOpts().TimeTracePath, /*Binary=*/false, + /*RemoveFileOnSignal=*/false, /*useTemporary=*/false)) { llvm::timeTraceProfilerWrite(*profilerOutput); profilerOutput.reset(); diff --git a/src/zig_clang_cc1as_main.cpp b/src/zig_clang_cc1as_main.cpp index f944113476..3c5926073f 100644 --- a/src/zig_clang_cc1as_main.cpp +++ b/src/zig_clang_cc1as_main.cpp @@ -19,8 +19,8 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.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" @@ -44,7 +44,6 @@ #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" @@ -53,6 +52,8 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/Triple.h" #include #include #include @@ -97,7 +98,7 @@ struct AssemblerInvocation { std::string DwarfDebugFlags; std::string DwarfDebugProducer; std::string DebugCompilationDir; - std::map DebugPrefixMap; + llvm::SmallVector, 0> DebugPrefixMap; llvm::DebugCompressionType CompressDebugSections = llvm::DebugCompressionType::None; std::string MainFileName; @@ -142,6 +143,10 @@ struct AssemblerInvocation { /// Whether to emit DWARF unwind info. EmitDwarfUnwindType EmitDwarfUnwind; + // Whether to emit compact-unwind for non-canonical entries. + // Note: maybe overriden by other constraints. + unsigned EmitCompactUnwindNonCanonical : 1; + /// The name of the relocation model to use. std::string RelocationModel; @@ -181,6 +186,7 @@ public: DwarfVersion = 0; EmbedBitcode = 0; EmitDwarfUnwind = EmitDwarfUnwindType::Default; + EmitCompactUnwindNonCanonical = false; } static bool CreateFromArgs(AssemblerInvocation &Res, @@ -275,8 +281,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, 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)}); + Opts.DebugPrefixMap.emplace_back(Split.first, Split.second); } // Frontend Options @@ -349,6 +354,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, .Case("default", EmitDwarfUnwindType::Default); } + Opts.EmitCompactUnwindNonCanonical = + Args.hasArg(OPT_femit_compact_unwind_non_canonical); + Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file); return Success; @@ -384,8 +392,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, 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; + return Diags.Report(diag::err_fe_error_reading) + << Opts.InputFile << EC.message(); } SourceMgr SrcMgr; @@ -402,6 +410,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, MCTargetOptions MCOptions; MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; + MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical; MCOptions.AsSecureLogFile = Opts.AsSecureLogFile; std::unique_ptr MAI( diff --git a/src/zig_clang_driver.cpp b/src/zig_clang_driver.cpp index 1381eb9b08..471d0181ff 100644 --- a/src/zig_clang_driver.cpp +++ b/src/zig_clang_driver.cpp @@ -36,8 +36,8 @@ #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/LLVMDriver.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Process.h" @@ -48,6 +48,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Host.h" #include #include #include @@ -209,6 +210,9 @@ extern int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr); extern int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr); +extern int cc1gen_reproducer_main(ArrayRef Argv, + const char *Argv0, void *MainAddr, + const llvm::ToolContext &); static void insertTargetAndModeArgs(const ParsedClangName &NameParts, SmallVectorImpl &ArgVector, @@ -303,6 +307,9 @@ static bool SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { TheDriver.CCPrintProcessStats = checkEnvVar("CC_PRINT_PROC_STAT", "CC_PRINT_PROC_STAT_FILE", TheDriver.CCPrintStatReportFilename); + TheDriver.CCPrintInternalStats = + checkEnvVar("CC_PRINT_INTERNAL_STAT", "CC_PRINT_INTERNAL_STAT_FILE", + TheDriver.CCPrintInternalStatReportFilename); return true; } @@ -339,7 +346,8 @@ static void SetInstallDir(SmallVectorImpl &argv, TheDriver.setInstalledDir(InstalledPathParent); } -static int ExecuteCC1Tool(SmallVectorImpl &ArgV) { +static int ExecuteCC1Tool(SmallVectorImpl &ArgV, + const llvm::ToolContext &ToolContext) { // 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 @@ -358,28 +366,22 @@ static int ExecuteCC1Tool(SmallVectorImpl &ArgV) { 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, ToolContext); // Reject unknown tools. llvm::errs() << "error: unknown integrated tool '" << Tool << "'. " << "Valid tools include '-cc1' and '-cc1as'.\n"; return 1; } -extern "C" int ZigClang_main(int Argc, const char **Argv); -int ZigClang_main(int Argc, const char **Argv) { +int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { noteBottomOfStack(); - // ZIG PATCH: On Windows, InitLLVM calls GetCommandLineW(), - // and overwrites the args. We don't want it to do that, - // and we also don't need the signal handlers it installs - // (we have our own already), so we just use llvm_shutdown_obj - // instead. - // llvm::InitLLVM X(Argc, Argv); - llvm::llvm_shutdown_obj X; - + 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"); - size_t argv_offset = (strcmp(Argv[1], "-cc1") == 0 || strcmp(Argv[1], "-cc1as") == 0) ? 0 : 1; - SmallVector Args(Argv + argv_offset, Argv + Argc); + SmallVector Args(Argv, Argv + Argc); if (llvm::sys::Process::FixupStandardFileDescriptors()) return 1; @@ -389,55 +391,20 @@ int ZigClang_main(int Argc, const char **Argv) { 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. + const char *ProgName = + ToolContext.NeedsPrependArg ? ToolContext.PrependArg : ToolContext.Path; + 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; - } + IsClangCL(getDriverMode(ProgName, llvm::ArrayRef(Args).slice(1))); - // 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)) { + if (llvm::Error Err = expandResponseFiles(Args, ClangCLMode, A)) { 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 -cc1 integrated tools. + if (Args.size() >= 2 && StringRef(Args[1]).startswith("-cc1")) + return ExecuteCC1Tool(Args, ToolContext); // Handle options that need handling before the real command line parsing in // Driver::BuildCompilation() @@ -483,9 +450,7 @@ int ZigClang_main(int Argc, const char **Argv) { ApplyQAOverride(Args, OverrideStr, SavedStrings); } - // Pass local param `Argv[0]` as fallback. - // See https://github.com/ziglang/zig/pull/3292 . - std::string Path = GetExecutablePath(Argv[0], CanonicalPrefixes); + std::string Path = GetExecutablePath(ToolContext.Path, CanonicalPrefixes); // Whether the cc1 tool should be called inside the current process, or if we // should spawn a new clang subprocess (old behavior). @@ -503,7 +468,7 @@ int ZigClang_main(int Argc, const char **Argv) { TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); - FixupDiagPrefixExeName(DiagClient, Path); + FixupDiagPrefixExeName(DiagClient, ProgName); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); @@ -521,8 +486,15 @@ int ZigClang_main(int Argc, const char **Argv) { Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); SetInstallDir(Args, TheDriver, CanonicalPrefixes); - auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Args[0]); + auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName); TheDriver.setTargetAndMode(TargetAndMode); + // If -canonical-prefixes is set, GetExecutablePath will have resolved Path + // to the llvm driver binary, not clang. In this case, we need to use + // PrependArg which should be clang-*. Checking just CanonicalPrefixes is + // safe even in the normal case because PrependArg will be null so + // setPrependArg will be a no-op. + if (ToolContext.NeedsPrependArg || CanonicalPrefixes) + TheDriver.setPrependArg(ToolContext.PrependArg); insertTargetAndModeArgs(TargetAndMode, Args, SavedStrings); @@ -530,7 +502,9 @@ int ZigClang_main(int Argc, const char **Argv) { return 1; if (!UseNewCC1Process) { - TheDriver.CC1Main = &ExecuteCC1Tool; + TheDriver.CC1Main = [ToolContext](SmallVectorImpl &ArgV) { + return ExecuteCC1Tool(ArgV, ToolContext); + }; // Ensure the CC1Command actually catches cc1 crashes llvm::CrashRecoveryContext::Enable(); } diff --git a/src/zig_llvm-ar.cpp b/src/zig_llvm-ar.cpp index 093350e15a..d21650d146 100644 --- a/src/zig_llvm-ar.cpp +++ b/src/zig_llvm-ar.cpp @@ -13,20 +13,11 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" -#include "llvm/Object/COFFImportFile.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Object/IRObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolicFile.h" -#include "llvm/Object/TapiFile.h" -#include "llvm/Object/Wasm.h" -#include "llvm/Object/XCOFFObjectFile.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" @@ -34,8 +25,8 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/Host.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/LLVMDriver.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -45,6 +36,8 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h" #include "llvm/ToolDrivers/llvm-lib/LibDriver.h" @@ -646,31 +639,12 @@ static bool shouldCreateArchive(ArchiveOperation Op) { llvm_unreachable("Missing entry in covered switch."); } -static bool is64BitSymbolicFile(SymbolicFile &Obj) { - if (auto *IRObj = dyn_cast(&Obj)) - return Triple(IRObj->getTargetTriple()).isArch64Bit(); - if (isa(Obj) || isa(Obj)) - return false; - if (XCOFFObjectFile *XCOFFObj = dyn_cast(&Obj)) - return XCOFFObj->is64Bit(); - if (isa(Obj)) - return false; - if (TapiFile *Tapi = dyn_cast(&Obj)) - return Tapi->is64Bit(); - if (MachOObjectFile *MachO = dyn_cast(&Obj)) - return MachO->is64Bit(); - if (ELFObjectFileBase *ElfO = dyn_cast(&Obj)) - return ElfO->getBytesInAddress() == 8; - - fail("unsupported file format"); -} - static bool isValidInBitMode(Binary &Bin) { if (BitMode == BitModeTy::Bit32_64 || BitMode == BitModeTy::Any) return true; if (SymbolicFile *SymFile = dyn_cast(&Bin)) { - bool Is64Bit = is64BitSymbolicFile(*SymFile); + bool Is64Bit = SymFile->is64Bit(); if ((Is64Bit && (BitMode == BitModeTy::Bit32)) || (!Is64Bit && (BitMode == BitModeTy::Bit64))) return false; @@ -1452,16 +1426,8 @@ static int ranlib_main(int argc, char **argv) { return 0; } -extern "C" int ZigLlvmAr_main(int argc, char **argv); -int ZigLlvmAr_main(int argc, char **argv) { - // ZIG PATCH: On Windows, InitLLVM calls GetCommandLineW(), - // and overwrites the args. We don't want it to do that, - // and we also don't need the signal handlers it installs - // (we have our own already), so we just use llvm_shutdown_obj - // instead. - // InitLLVM X(argc, argv); - llvm::llvm_shutdown_obj X; - +int llvm_ar_main(int argc, char **argv, const llvm::ToolContext &) { + InitLLVM X(argc, argv); ToolName = argv[0]; llvm::InitializeAllTargetInfos();