diff --git a/src/zig_clang_cc1_main.cpp b/src/zig_clang_cc1_main.cpp index 2c17f28621..1adb217014 100644 --- a/src/zig_clang_cc1_main.cpp +++ b/src/zig_clang_cc1_main.cpp @@ -12,19 +12,20 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/Stack.h" #include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/ObjectFilePCHContainerWriter.h" #include "clang/Config/config.h" +#include "clang/Driver/Driver.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 "clang/Options/Options.h" #include "clang/Serialization/ObjectFilePCHContainerReader.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -38,6 +39,7 @@ #include "llvm/Support/BuryPointer.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/IOSandbox.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" @@ -217,7 +219,7 @@ static int PrintEnabledExtensions(const TargetOptions& TargetOpts) { int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { ensureSufficientStack(); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagID = DiagnosticIDs::create(); // Register the support for object-file-wrapped Clang modules. auto PCHOps = std::make_shared(); @@ -269,12 +271,17 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && Clang->getHeaderSearchOpts().ResourceDir.empty()) Clang->getHeaderSearchOpts().ResourceDir = - CompilerInvocation::GetResourcesPath(Argv0, MainAddr); + GetResourcesPath(Argv0, MainAddr); + + /// Create the actual file system. + auto VFS = [] { + auto BypassSandbox = llvm::sys::sandbox::scopedDisable(); + return llvm::vfs::getRealFileSystem(); + }(); + Clang->createVirtualFileSystem(std::move(VFS), DiagsBuffer); // Create the actual diagnostics engine. - Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); - if (!Clang->hasDiagnostics()) - return 1; + Clang->createDiagnostics(); // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. @@ -299,29 +306,21 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { // If any timers were active but haven't been destroyed yet, print their // results now. This happens in -disable-free mode. - std::unique_ptr IOFile = llvm::CreateInfoOutputFile(); - if (Clang->getCodeGenOpts().TimePassesJson) { - *IOFile << "{\n"; - llvm::TimerGroup::printAllJSONValues(*IOFile, ""); - *IOFile << "\n}\n"; - } else { - llvm::TimerGroup::printAll(*IOFile); + { + // This isn't a formal input or output of the compiler. + auto BypassSandbox = llvm::sys::sandbox::scopedDisable(); + std::unique_ptr IOFile = llvm::CreateInfoOutputFile(); + if (Clang->getCodeGenOpts().TimePassesJson) { + *IOFile << "{\n"; + llvm::TimerGroup::printAllJSONValues(*IOFile, ""); + *IOFile << "\n}\n"; + } else if (!Clang->getCodeGenOpts().TimePassesStatsFile) { + llvm::TimerGroup::printAll(*IOFile); + } + llvm::TimerGroup::clearAll(); } - llvm::TimerGroup::clearAll(); if (llvm::timeTraceProfilerEnabled()) { - // 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( Clang->getFrontendOpts().TimeTracePath, /*Binary=*/false, /*RemoveFileOnSignal=*/false, diff --git a/src/zig_clang_cc1as_main.cpp b/src/zig_clang_cc1as_main.cpp index f938e7e404..339693e709 100644 --- a/src/zig_clang_cc1as_main.cpp +++ b/src/zig_clang_cc1as_main.cpp @@ -12,12 +12,12 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticFrontend.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 "clang/Options/Options.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -45,6 +45,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/IOSandbox.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" @@ -59,8 +60,7 @@ #include #include using namespace clang; -using namespace clang::driver; -using namespace clang::driver::options; +using namespace clang::options; using namespace llvm; using namespace llvm::opt; @@ -71,8 +71,8 @@ struct AssemblerInvocation { /// @name Target Options /// @{ - /// The name of the target triple to assemble for. - std::string Triple; + /// The target triple to assemble for. + llvm::Triple Triple; /// If given, the name of the target CPU to determine which instructions /// are legal. @@ -163,6 +163,10 @@ struct AssemblerInvocation { LLVM_PREFERRED_TYPE(bool) unsigned EmitCompactUnwindNonCanonical : 1; + // Whether to emit sframe unwind sections. + LLVM_PREFERRED_TYPE(bool) + unsigned EmitSFrameUnwind : 1; + LLVM_PREFERRED_TYPE(bool) unsigned Crel : 1; LLVM_PREFERRED_TYPE(bool) @@ -192,9 +196,12 @@ struct AssemblerInvocation { std::string AsSecureLogFile; /// @} + void setTriple(llvm::StringRef Str) { + Triple = llvm::Triple(llvm::Triple::normalize(Str)); + } + public: AssemblerInvocation() { - Triple = ""; NoInitialTextSection = 0; InputFile = "-"; OutputPath = "-"; @@ -261,7 +268,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Construct the invocation. // Target Options - Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); + Opts.setTriple(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)) { @@ -278,7 +285,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Use the default target triple if unspecified. if (Opts.Triple.empty()) - Opts.Triple = llvm::sys::getDefaultTargetTriple(); + Opts.setTriple(llvm::sys::getDefaultTargetTriple()); // Language Options Opts.IncludePaths = Args.getAllArgValues(OPT_I); @@ -385,6 +392,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.EmitCompactUnwindNonCanonical = Args.hasArg(OPT_femit_compact_unwind_non_canonical); + Opts.EmitSFrameUnwind = Args.hasArg(OPT_gsframe); Opts.Crel = Args.hasArg(OPT_crel); Opts.ImplicitMapsyms = Args.hasArg(OPT_mmapsyms_implicit); Opts.X86RelaxRelocations = !Args.hasArg(OPT_mrelax_relocations_no); @@ -414,15 +422,19 @@ getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) { } static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + IntrusiveRefCntPtr VFS) { // 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; + return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple.str(); - ErrorOr> Buffer = - MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true); + ErrorOr> Buffer = [&] { + // FIXME(sandboxing): Make this a proper input file. + auto BypassSandbox = sys::sandbox::scopedDisable(); + return MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true); + }(); if (std::error_code EC = Buffer.getError()) { return Diags.Report(diag::err_fe_error_reading) @@ -437,6 +449,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(Opts.IncludePaths); + SrcMgr.setVirtualFileSystem(VFS); std::unique_ptr MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); @@ -445,11 +458,13 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, MCOptions.MCRelaxAll = Opts.RelaxAll; MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical; + MCOptions.EmitSFrameUnwind = Opts.EmitSFrameUnwind; MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels; MCOptions.Crel = Opts.Crel; MCOptions.ImplicitMapSyms = Opts.ImplicitMapsyms; MCOptions.X86RelaxRelocations = Opts.X86RelaxRelocations; MCOptions.X86Sse2Avx = Opts.X86Sse2Avx; + MCOptions.MCNoExecStack = Opts.NoExecStack; MCOptions.CompressDebugSections = Opts.CompressDebugSections; MCOptions.AsSecureLogFile = Opts.AsSecureLogFile; @@ -477,7 +492,10 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, std::unique_ptr STI( TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS)); - assert(STI && "Unable to create subtarget info!"); + if (!STI) { + return Diags.Report(diag::err_fe_unable_to_create_subtarget) + << Opts.CPU << FS.empty() << FS; + } MCContext Ctx(Triple(Opts.Triple), MAI.get(), MRI.get(), STI.get(), &SrcMgr, &MCOptions); @@ -509,9 +527,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, 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 (auto CWD = VFS->getCurrentWorkingDirectory()) + Ctx.setCompilationDir(*CWD); } if (!Opts.DebugPrefixMap.empty()) for (const auto &KV : Opts.DebugPrefixMap) @@ -577,7 +594,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, Triple T(Opts.Triple); Str.reset(TheTarget->createMCObjectStreamer( T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI)); - Str->initSections(Opts.NoExecStack, *STI); if (T.isOSBinFormatMachO() && T.isOSDarwin()) { Triple *TVT = Opts.DarwinTargetVariantTriple ? &*Opts.DarwinTargetVariantTriple @@ -605,7 +621,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, std::unique_ptr TAP( TheTarget->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); if (!TAP) - Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple; + Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple.str(); // Set values for symbols, if any. for (auto &S : Opts.SymbolDefs) { @@ -627,8 +643,9 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, } static bool ExecuteAssembler(AssemblerInvocation &Opts, - DiagnosticsEngine &Diags) { - bool Failed = ExecuteAssemblerImpl(Opts, Diags); + DiagnosticsEngine &Diags, + IntrusiveRefCntPtr VFS) { + bool Failed = ExecuteAssemblerImpl(Opts, Diags, VFS); // Delete output file if there were errors. if (Failed) { @@ -662,8 +679,12 @@ int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(errs(), DiagOpts); DiagClient->setPrefix("clang -cc1as"); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - DiagnosticsEngine Diags(DiagID, DiagOpts, DiagClient); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagClient); + + auto VFS = [] { + auto BypassSandbox = sys::sandbox::scopedDisable(); + return vfs::getRealFileSystem(); + }(); // Set an error handler, so that any LLVM backend diagnostics go through our // error handler. @@ -679,8 +700,7 @@ int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { getDriverOptTable().printHelp( llvm::outs(), "clang -cc1as [options] file...", "Clang Integrated Assembler", /*ShowHidden=*/false, - /*ShowAllAliases=*/false, - llvm::opt::Visibility(driver::options::CC1AsOption)); + /*ShowAllAliases=*/false, llvm::opt::Visibility(options::CC1AsOption)); return 0; } @@ -703,11 +723,12 @@ int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { 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()); + llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(), /*Overview=*/"", + /*Errs=*/nullptr, /*VFS=*/VFS.get()); } // Execute the invocation, unless there were parsing errors. - bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags); + bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags, VFS); // If any timers were active but haven't been destroyed yet, print their // results now. diff --git a/src/zig_clang_driver.cpp b/src/zig_clang_driver.cpp index 7f4c6034be..75d945d6de 100644 --- a/src/zig_clang_driver.cpp +++ b/src/zig_clang_driver.cpp @@ -18,13 +18,13 @@ #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 "clang/Options/Options.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -38,6 +38,7 @@ #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/IOSandbox.h" #include "llvm/Support/LLVMDriver.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" @@ -201,7 +202,8 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, } static int ExecuteCC1Tool(SmallVectorImpl &ArgV, - const llvm::ToolContext &ToolContext) { + const llvm::ToolContext &ToolContext, + IntrusiveRefCntPtr VFS) { // 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 @@ -209,7 +211,8 @@ static int ExecuteCC1Tool(SmallVectorImpl &ArgV, llvm::cl::ResetAllOptionOccurrences(); llvm::BumpPtrAllocator A; - llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine); + llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine, + VFS.get()); if (llvm::Error Err = ECtx.expandResponseFiles(ArgV)) { llvm::errs() << toString(std::move(Err)) << '\n'; return 1; @@ -249,14 +252,22 @@ static int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContex bool ClangCLMode = IsClangCL(getDriverMode(ProgName, llvm::ArrayRef(Args).slice(1))); - if (llvm::Error Err = expandResponseFiles(Args, ClangCLMode, A)) { + auto VFS = llvm::vfs::getRealFileSystem(); + + if (llvm::Error Err = expandResponseFiles(Args, ClangCLMode, A, VFS.get())) { llvm::errs() << toString(std::move(Err)) << '\n'; return 1; } // Handle -cc1 integrated tools. - if (Args.size() >= 2 && StringRef(Args[1]).starts_with("-cc1")) - return ExecuteCC1Tool(Args, ToolContext); + if (Args.size() >= 2 && StringRef(Args[1]).starts_with("-cc1")) { + // Note that this only enables the sandbox for direct -cc1 invocations and + // out-of-process -cc1 invocations launched by the driver. For in-process + // -cc1 invocations launched by the driver, the sandbox is enabled in + // CC1Command::Execute() for better crash recovery. + auto EnableSandbox = llvm::sys::sandbox::scopedEnable(); + return ExecuteCC1Tool(Args, ToolContext, VFS); + } // Handle options that need handling before the real command line parsing in // Driver::BuildCompilation() @@ -326,9 +337,7 @@ static int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContex new TextDiagnosticPrinter(llvm::errs(), *DiagOpts); FixupDiagPrefixExeName(DiagClient, ProgName); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - - DiagnosticsEngine Diags(DiagID, *DiagOpts, DiagClient); + DiagnosticsEngine Diags(DiagnosticIDs::create(), *DiagOpts, DiagClient); if (!DiagOpts->DiagnosticSerializationFile.empty()) { auto SerializedConsumer = @@ -338,7 +347,6 @@ static int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContex Diags.takeClient(), std::move(SerializedConsumer))); } - auto VFS = llvm::vfs::getRealFileSystem(); ProcessWarningOptions(Diags, *DiagOpts, *VFS, /*ReportDiags=*/false); Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags, @@ -358,10 +366,10 @@ static int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContex if (!SetBackdoorDriverOutputsFromEnvVars(TheDriver)) return 1; - auto ExecuteCC1WithContext = - [&ToolContext](SmallVectorImpl &ArgV) { - return ExecuteCC1Tool(ArgV, ToolContext); - }; + auto ExecuteCC1WithContext = [&ToolContext, + &VFS](SmallVectorImpl &ArgV) { + return ExecuteCC1Tool(ArgV, ToolContext, VFS); + }; if (!UseNewCC1Process) { TheDriver.CC1Main = ExecuteCC1WithContext; // Ensure the CC1Command actually catches cc1 crashes diff --git a/src/zig_llvm-ar.cpp b/src/zig_llvm-ar.cpp index 50478e8dda..fd00a7be49 100644 --- a/src/zig_llvm-ar.cpp +++ b/src/zig_llvm-ar.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/IR/LLVMContext.h" diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 90e462860f..9bba8e96d5 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -439,7 +439,7 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) { static OptBisect opt_bisect; - opt_bisect.setLimit(limit); + opt_bisect.setIntervals({0, limit}); unwrap(context_ref)->setOptPassGate(opt_bisect); }