https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/146422
>From 69049bfcd81134f3787d1ee14ab3e5c6d91eb87d Mon Sep 17 00:00:00 2001 From: Jan Svoboda <jan_svob...@apple.com> Date: Thu, 3 Jul 2025 12:46:58 -0700 Subject: [PATCH] [clang][modules] Serialize `CodeGenOptions` --- clang-tools-extra/clangd/ModulesBuilder.cpp | 3 +- clang/include/clang/Basic/CodeGenOptions.def | 30 ++-- clang/include/clang/Basic/CodeGenOptions.h | 20 ++- clang/include/clang/Basic/DebugOptions.def | 58 ++++---- .../Basic/DiagnosticSerializationKinds.td | 4 + clang/include/clang/Basic/LangOptions.def | 3 - clang/include/clang/Frontend/ASTUnit.h | 2 + .../include/clang/Frontend/CompilerInstance.h | 1 + .../include/clang/Serialization/ASTBitCodes.h | 5 +- clang/include/clang/Serialization/ASTReader.h | 39 ++++-- clang/include/clang/Serialization/ASTWriter.h | 21 ++- clang/lib/Basic/CodeGenOptions.cpp | 6 +- clang/lib/CodeGen/CGDebugInfo.cpp | 34 +++-- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 4 +- clang/lib/CodeGen/CodeGenAction.cpp | 2 +- clang/lib/Frontend/ASTUnit.cpp | 36 +++-- clang/lib/Frontend/ChainedIncludesSource.cpp | 5 +- clang/lib/Frontend/CompilerInstance.cpp | 8 +- clang/lib/Frontend/CompilerInvocation.cpp | 37 +++-- clang/lib/Frontend/FrontendAction.cpp | 5 +- clang/lib/Frontend/FrontendActions.cpp | 17 +-- clang/lib/Frontend/InitPreprocessor.cpp | 12 +- clang/lib/Frontend/PrecompiledPreamble.cpp | 8 +- clang/lib/Serialization/ASTReader.cpp | 130 +++++++++++++++++- clang/lib/Serialization/ASTWriter.cpp | 21 ++- clang/lib/Serialization/GeneratePCH.cpp | 6 +- clang/test/PCH/no-validate-pch.cl | 2 +- llvm/clang/test/Modules/implicit-opt-level.c | 15 ++ 28 files changed, 386 insertions(+), 148 deletions(-) create mode 100644 llvm/clang/test/Modules/implicit-opt-level.c diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp index d88aa01aad05d..b9aeb3889f5f2 100644 --- a/clang-tools-extra/clangd/ModulesBuilder.cpp +++ b/clang-tools-extra/clangd/ModulesBuilder.cpp @@ -209,8 +209,9 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath, IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache(); PCHContainerOperations PCHOperations; + CodeGenOptions CodeGenOpts; ASTReader Reader(PP, *ModCache, /*ASTContext=*/nullptr, - PCHOperations.getRawReader(), {}); + PCHOperations.getRawReader(), CodeGenOpts, {}); // We don't need any listener here. By default it will use a validator // listener. diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 41031026c99f6..a11e12d495cd2 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -209,17 +209,17 @@ CODEGENOPT(ObjCAvoidHeapifyLocalBlocks, 1, 0, Benign) // The optimization options affect frontend options, which in turn do affect the AST. -VALUE_CODEGENOPT(OptimizationLevel, 2, 0, Affecting) ///< The -O[0-3] option specified. -VALUE_CODEGENOPT(OptimizeSize, 2, 0, Affecting) ///< If -Os (==1, Benign) or -Oz (==2, Benign) is specified. +VALUE_CODEGENOPT(OptimizationLevel, 2, 0, Compatible) ///< The -O[0-3] option specified. +VALUE_CODEGENOPT(OptimizeSize, 2, 0, Compatible) ///< If -Os (==1, Benign) or -Oz (==2, Benign) is specified. CODEGENOPT(AtomicProfileUpdate , 1, 0, Benign) ///< Set -fprofile-update=atomic CODEGENOPT(ContinuousProfileSync, 1, 0, Benign) ///< Enable continuous instrumentation profiling /// Choose profile instrumenation kind or no instrumentation. -ENUM_CODEGENOPT(ProfileInstr, llvm::driver::ProfileInstrKind, 4, llvm::driver::ProfileInstrKind::ProfileNone, Benign) +ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 4, ProfileInstrKind::ProfileNone, Benign) /// Choose profile kind for PGO use compilation. -ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::ProfileInstrKind::ProfileNone, Benign) +ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileInstrKind::ProfileNone, Benign) /// Partition functions into N groups and select only functions in group i to be /// instrumented. Selected group numbers can be 0 to N-1 inclusive. VALUE_CODEGENOPT(ProfileTotalFunctionGroups, 32, 1, Benign) @@ -244,8 +244,8 @@ CODEGENOPT(SaveTempLabels , 1, 0, Benign) ///< Save temporary labels. CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0, Benign) ///< Enable use-after-scope detection ///< in AddressSanitizer ENUM_CODEGENOPT(SanitizeAddressUseAfterReturn, - llvm::AsanDetectStackUseAfterReturnMode, 2, - llvm::AsanDetectStackUseAfterReturnMode::Runtime, + AsanDetectStackUseAfterReturnMode, 2, + AsanDetectStackUseAfterReturnMode::Runtime, Benign ) ///< Set detection mode for stack-use-after-return. CODEGENOPT(SanitizeAddressPoisonCustomArrayCookie, 1, 0, Benign) ///< Enable poisoning operator new[] which is not a replaceable @@ -255,9 +255,9 @@ CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0, Benign) ///< Enable linker CODEGENOPT(SanitizeAddressUseOdrIndicator, 1, 0, Benign) ///< Enable ODR indicator globals CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0, Benign) ///< Enable tracking origins in ///< MemorySanitizer -ENUM_CODEGENOPT(SanitizeAddressDtor, llvm::AsanDtorKind, 2, - llvm::AsanDtorKind::Global, Benign) ///< Set how ASan global - ///< destructors are emitted. +ENUM_CODEGENOPT(SanitizeAddressDtor, AsanDtorKind, 2, + AsanDtorKind::Global, Benign) ///< Set how ASan global + ///< destructors are emitted. CODEGENOPT(SanitizeMemoryParamRetval, 1, 0, Benign) ///< Enable detection of uninitialized ///< parameters and return values ///< in MemorySanitizer @@ -375,13 +375,13 @@ VALUE_CODEGENOPT(SmallDataLimit, 32, 0, Benign) VALUE_CODEGENOPT(SSPBufferSize, 32, 0, Benign) /// The kind of inlining to perform. -ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining, Benign) +ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining, Compatible) /// The maximum stack size a function can have to be considered for inlining. VALUE_CODEGENOPT(InlineMaxStackSize, 32, UINT_MAX, Benign) // Vector functions library to use. -ENUM_CODEGENOPT(VecLib, llvm::driver::VectorLibrary, 4, llvm::driver::VectorLibrary::NoLibrary, Benign) +ENUM_CODEGENOPT(VecLib, VectorLibrary, 4, VectorLibrary::NoLibrary, Benign) /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel, Benign) @@ -457,8 +457,8 @@ ENUM_CODEGENOPT(SwiftAsyncFramePointer, SwiftAsyncFramePointerKind, 2, CODEGENOPT(SkipRaxSetup, 1, 0, Benign) /// Whether to zero out caller-used registers before returning. -ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind, - 5, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip, Benign) +ENUM_CODEGENOPT(ZeroCallUsedRegs, ZeroCallUsedRegsKind, + 5, ZeroCallUsedRegsKind::Skip, Benign) /// Modify C++ ABI to returning `this` pointer from constructors and /// non-deleting destructors. (No effect on Microsoft ABI.) @@ -477,8 +477,8 @@ CODEGENOPT(ResMayAlias, 1, 0, Benign) /// Controls how unwind v2 (epilog) information should be generated for x64 /// Windows. -ENUM_CODEGENOPT(WinX64EHUnwindV2, llvm::WinX64EHUnwindV2Mode, - 2, llvm::WinX64EHUnwindV2Mode::Disabled, Benign) +ENUM_CODEGENOPT(WinX64EHUnwindV2, WinX64EHUnwindV2Mode, + 2, WinX64EHUnwindV2Mode::Disabled, Benign) /// FIXME: Make DebugOptions its own top-level .def file. #include "DebugOptions.def" diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index fe634d221b424..7cd5ea3256cdb 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -46,13 +46,31 @@ class CodeGenOptionsBase { enum class CompatibilityKind { /// Does affect the construction of the AST in a way that does prevent /// module interoperability. - Affecting, + NotCompatible, + /// Does affect the construction of the AST in a way that doesn't prevent + /// interoperability (that is, the value can be different between an + /// explicit module and the user of that module). + Compatible, /// Does not affect the construction of the AST in any way (that is, the /// value can be different between an implicit module and the user of that /// module). Benign, }; + using CFBranchLabelSchemeKind = CFBranchLabelSchemeKind; + using ProfileInstrKind = llvm::driver::ProfileInstrKind; + using AsanDetectStackUseAfterReturnMode = llvm::AsanDetectStackUseAfterReturnMode; + using AsanDtorKind = llvm::AsanDtorKind; + using VectorLibrary = llvm::driver::VectorLibrary; + using ZeroCallUsedRegsKind = llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind; + using WinX64EHUnwindV2Mode = llvm::WinX64EHUnwindV2Mode; + + using DebugCompressionType = llvm::DebugCompressionType; + using EmitDwarfUnwindType = llvm::EmitDwarfUnwindType; + using DebugTemplateNamesKind = llvm::codegenoptions::DebugTemplateNamesKind; + using DebugInfoKind = llvm::codegenoptions::DebugInfoKind; + using DebuggerKind = llvm::DebuggerKind; + #define CODEGENOPT(Name, Bits, Default, Compatibility) unsigned Name : Bits; #define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) #include "clang/Basic/CodeGenOptions.def" diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index e2ab06184b96a..c6e736e92744c 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -28,9 +28,9 @@ VALUE_CODEGENOPT(Name, Bits, Default, Compatibility) ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) #endif -ENUM_DEBUGOPT(CompressDebugSections, llvm::DebugCompressionType, 2, - llvm::DebugCompressionType::None, Benign) -DEBUGOPT(Dwarf64, 1, 0, Affecting) ///< -gdwarf64. +ENUM_DEBUGOPT(CompressDebugSections, DebugCompressionType, 2, + DebugCompressionType::None, Benign) +DEBUGOPT(Dwarf64, 1, 0, Compatible) ///< -gdwarf64. DEBUGOPT(EnableDIPreservationVerify, 1, 0, Benign) ///< Enable di preservation ///< verify each (it means ///< check the original debug @@ -40,8 +40,8 @@ DEBUGOPT(ForceDwarfFrameSection , 1, 0, Benign) ///< Set when -fforce-dwarf-fram ///< is enabled. ///< Set when -femit-dwarf-unwind is passed. -ENUM_DEBUGOPT(EmitDwarfUnwind, llvm::EmitDwarfUnwindType, 2, - llvm::EmitDwarfUnwindType::Default, Benign) +ENUM_DEBUGOPT(EmitDwarfUnwind, EmitDwarfUnwindType, 2, + EmitDwarfUnwindType::Default, Benign) DEBUGOPT(NoDwarfDirectoryAsm , 1, 0, Benign) ///< Set when -fno-dwarf-directory-asm ///< is enabled. @@ -49,8 +49,8 @@ DEBUGOPT(NoDwarfDirectoryAsm , 1, 0, Benign) ///< Set when -fno-dwarf-directory- DEBUGOPT(NoInlineLineTables, 1, 0, Benign) ///< Whether debug info should contain ///< inline line tables. -DEBUGOPT(DebugStrictDwarf, 1, 1, Affecting) ///< Whether or not to use strict DWARF info. -DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0, Affecting) ///< Omit unreferenced member +DEBUGOPT(DebugStrictDwarf, 1, 1, Compatible) ///< Whether or not to use strict DWARF info. +DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0, Compatible) ///< Omit unreferenced member ///< functions in type debug info. /// Control the Assignment Tracking debug info feature. @@ -60,73 +60,73 @@ ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, /// Whether or not to use Key Instructions to determine breakpoint locations. DEBUGOPT(DebugKeyInstructions, 1, 0, Benign) -DEBUGOPT(DebugColumnInfo, 1, 0, Affecting) ///< Whether or not to use column information +DEBUGOPT(DebugColumnInfo, 1, 0, Compatible) ///< Whether or not to use column information ///< in debug info. -DEBUGOPT(DebugTypeExtRefs, 1, 0, Affecting) ///< Whether or not debug info should contain +DEBUGOPT(DebugTypeExtRefs, 1, 0, Compatible) ///< Whether or not debug info should contain ///< external references to a PCH or module. -DEBUGOPT(DebugExplicitImport, 1, 0, Affecting) ///< Whether or not debug info should +DEBUGOPT(DebugExplicitImport, 1, 0, Compatible) ///< Whether or not debug info should ///< contain explicit imports for ///< anonymous namespaces /// Set debug info source file hashing algorithm. -ENUM_DEBUGOPT(DebugSrcHash, DebugSrcHashKind, 2, DSH_MD5, Affecting) +ENUM_DEBUGOPT(DebugSrcHash, DebugSrcHashKind, 2, DSH_MD5, Compatible) -DEBUGOPT(SplitDwarfInlining, 1, 1, Affecting) ///< Whether to include inlining info in the +DEBUGOPT(SplitDwarfInlining, 1, 1, Compatible) ///< Whether to include inlining info in the ///< skeleton CU to allow for symbolication ///< of inline stack frames without .dwo files. -DEBUGOPT(DebugFwdTemplateParams, 1, 0, Affecting) ///< Whether to emit complete +DEBUGOPT(DebugFwdTemplateParams, 1, 0, Compatible) ///< Whether to emit complete ///< template parameter descriptions in ///< forward declarations (versus just ///< including them in the name). ENUM_DEBUGOPT(DebugSimpleTemplateNames, - llvm::codegenoptions::DebugTemplateNamesKind, 2, - llvm::codegenoptions::DebugTemplateNamesKind::Full, Affecting) + DebugTemplateNamesKind, 2, + DebugTemplateNamesKind::Full, Compatible) ///< Whether to emit template parameters in the textual names of ///< template specializations. ///< Implies DebugFwdTemplateNames to allow decorated names to be ///< reconstructed when needed. /// The kind of generated debug info. -ENUM_DEBUGOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, - llvm::codegenoptions::NoDebugInfo, Affecting) +ENUM_DEBUGOPT(DebugInfo, DebugInfoKind, 4, + DebugInfoKind::NoDebugInfo, Compatible) /// Whether to generate macro debug info. -DEBUGOPT(MacroDebugInfo, 1, 0, Affecting) +DEBUGOPT(MacroDebugInfo, 1, 0, Compatible) /// Tune the debug info for this debugger. -ENUM_DEBUGOPT(DebuggerTuning, llvm::DebuggerKind, 3, - llvm::DebuggerKind::Default, Affecting) +ENUM_DEBUGOPT(DebuggerTuning, DebuggerKind, 3, + DebuggerKind::Default, Compatible) /// Dwarf version. Version zero indicates to LLVM that no DWARF should be /// emitted. -VALUE_DEBUGOPT(DwarfVersion, 3, 0, Affecting) +VALUE_DEBUGOPT(DwarfVersion, 3, 0, Compatible) /// Whether we should emit CodeView debug information. It's possible to emit /// CodeView and DWARF into the same object. -DEBUGOPT(EmitCodeView, 1, 0, Affecting) +DEBUGOPT(EmitCodeView, 1, 0, Compatible) /// Whether to emit the .debug$H section containing hashes of CodeView types. -DEBUGOPT(CodeViewGHash, 1, 0, Affecting) +DEBUGOPT(CodeViewGHash, 1, 0, Compatible) /// Whether to emit the compiler path and command line into the CodeView debug information. -DEBUGOPT(CodeViewCommandLine, 1, 0, Affecting) +DEBUGOPT(CodeViewCommandLine, 1, 0, Compatible) /// Whether emit extra debug info for sample pgo profile collection. -DEBUGOPT(DebugInfoForProfiling, 1, 0, Affecting) +DEBUGOPT(DebugInfoForProfiling, 1, 0, Compatible) /// Whether to emit DW_TAG_template_alias for template aliases. -DEBUGOPT(DebugTemplateAlias, 1, 0, Affecting) +DEBUGOPT(DebugTemplateAlias, 1, 0, Compatible) /// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames. -DEBUGOPT(DebugNameTable, 2, 0, Affecting) +DEBUGOPT(DebugNameTable, 2, 0, Compatible) /// Whether to use DWARF base address specifiers in .debug_ranges. -DEBUGOPT(DebugRangesBaseAddress, 1, 0, Affecting) +DEBUGOPT(DebugRangesBaseAddress, 1, 0, Compatible) /// Whether to embed source in DWARF debug line section. -DEBUGOPT(EmbedSource, 1, 0, Affecting) +DEBUGOPT(EmbedSource, 1, 0, Compatible) #undef DEBUGOPT #undef ENUM_DEBUGOPT diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 584c8d62280bf..fc3585ffe8549 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -41,6 +41,10 @@ def err_ast_file_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "precompiled file '%3' but is currently %select{disabled|enabled}2">; def err_ast_file_langopt_value_mismatch : Error< "%0 differs in precompiled file '%1' vs. current file">; +def err_ast_file_codegenopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " + "precompiled file '%3' but is currently %select{disabled|enabled}2">; +def err_ast_file_codegenopt_value_mismatch + : Error<"%0 differs in precompiled file '%1' vs. current file">; def err_ast_file_diagopt_mismatch : Error<"%0 is currently enabled, but was not in " "the precompiled file '%1'">; def err_ast_file_modulecache_mismatch : Error<"precompiled file '%2' was compiled with module cache " diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 72321c204ce96..851074c500d6e 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -161,8 +161,6 @@ LANGOPT(ModulesValidateTextualHeaderIncludes, 1, 1, Compatible, "validation of t LANGOPT(ModulesErrorRecovery, 1, 1, Benign, "automatically importing modules as needed when performing error recovery") LANGOPT(ImplicitModules, 1, 1, Benign, "building modules that are not specified via -fmodule-file") LANGOPT(ModulesLocalVisibility, 1, 0, Compatible, "local submodule visibility") -LANGOPT(Optimize , 1, 0, Compatible, "__OPTIMIZE__ predefined macro") -LANGOPT(OptimizeSize , 1, 0, Compatible, "__OPTIMIZE_SIZE__ predefined macro") LANGOPT(Static , 1, 0, Compatible, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") VALUE_LANGOPT(PackStruct , 32, 0, NotCompatible, "default struct packing maximum alignment") @@ -179,7 +177,6 @@ VALUE_LANGOPT(PIE , 1, 0, Compatible, "is pie") LANGOPT(ROPI , 1, 0, NotCompatible, "Read-only position independence") LANGOPT(RWPI , 1, 0, NotCompatible, "Read-write position independence") LANGOPT(GNUInline , 1, 0, Compatible, "GNU inline semantics") -LANGOPT(NoInlineDefine , 1, 0, Compatible, "__NO_INLINE__ predefined macro") LANGOPT(Deprecated , 1, 0, Compatible, "__DEPRECATED predefined macro") LANGOPT(FastMath , 1, 0, Compatible, "fast FP math optimizations, and __FAST_MATH__ predefined macro") LANGOPT(UnsafeFPMath , 1, 0, Compatible, "Unsafe Floating Point Math") diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 1485192e8f1e3..1286fe4cca0f4 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -62,6 +62,7 @@ class ASTContext; class ASTDeserializationListener; class ASTMutationListener; class ASTReader; +class CodeGenOptions; class CompilerInstance; class CompilerInvocation; class Decl; @@ -107,6 +108,7 @@ class ASTUnit { private: std::unique_ptr<LangOptions> LangOpts; + std::unique_ptr<CodeGenOptions> CodeGenOpts; // FIXME: The documentation on \c LoadFrom* member functions states that the // DiagnosticsEngine (and therefore DiagnosticOptions) must outlive the // returned ASTUnit. This is not the case. Enfore it by storing non-owning diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 0ae490f0e8073..2408367e19833 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -720,6 +720,7 @@ class CompilerInstance : public ModuleLoader { DisableValidationForModuleKind DisableValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 9d265f27b8e31..441047d64f48c 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -44,7 +44,7 @@ namespace serialization { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. -const unsigned VERSION_MAJOR = 34; +const unsigned VERSION_MAJOR = 35; /// AST file minor version number supported by this version of /// Clang. @@ -399,6 +399,9 @@ enum OptionsRecordTypes { /// Record code for the preprocessor options table. PREPROCESSOR_OPTIONS, + + /// Record code for the codegen options table. + CODEGEN_OPTIONS, }; /// Record codes for the unhashed control block. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 3d96f8e65180d..7ce626cedae74 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -72,6 +72,7 @@ class ASTContext; class ASTDeserializationListener; class ASTReader; class ASTRecordReader; +class CodeGenOptions; class CXXTemporary; class Decl; class DeclarationName; @@ -137,6 +138,15 @@ class ASTReaderListener { return false; } + /// Receives the codegen options. + /// + /// \returns true to indicate the options are invalid or false otherwise. + virtual bool ReadCodeGenOptions(const CodeGenOptions &CGOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) { + return false; + } + /// Receives the target options. /// /// \returns true to indicate the target options are invalid, or false @@ -281,6 +291,9 @@ class ChainedASTReaderListener : public ASTReaderListener { bool ReadLanguageOptions(const LangOptions &LangOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) override; + bool ReadCodeGenOptions(const CodeGenOptions &CGOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) override; bool ReadTargetOptions(const TargetOptions &TargetOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) override; @@ -322,6 +335,9 @@ class PCHValidator : public ASTReaderListener { bool ReadLanguageOptions(const LangOptions &LangOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) override; + bool ReadCodeGenOptions(const CodeGenOptions &CGOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) override; bool ReadTargetOptions(const TargetOptions &TargetOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) override; @@ -493,6 +509,9 @@ class ASTReader /// The AST consumer. ASTConsumer *Consumer = nullptr; + /// The codegen options. + const CodeGenOptions &CodeGenOpts; + /// The module manager which manages modules and their dependencies ModuleManager ModuleMgr; @@ -1580,6 +1599,10 @@ class ASTReader StringRef ModuleFilename, bool Complain, ASTReaderListener &Listener, bool AllowCompatibleDifferences); + static bool ParseCodeGenOptions(const RecordData &Record, + StringRef ModuleFilename, bool Complain, + ASTReaderListener &Listener, + bool AllowCompatibleDifferences); static bool ParseTargetOptions(const RecordData &Record, StringRef ModuleFilename, bool Complain, ASTReaderListener &Listener, @@ -1771,6 +1794,7 @@ class ASTReader /// deserializing. ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, StringRef isysroot = "", DisableValidationForModuleKind DisableValidationKind = @@ -1789,6 +1813,7 @@ class ASTReader SourceManager &getSourceManager() const { return SourceMgr; } FileManager &getFileManager() const { return FileMgr; } DiagnosticsEngine &getDiags() const { return Diags; } + const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } /// Flags that indicate what kind of AST loading failures the client /// of the AST reader can directly handle. @@ -1990,14 +2015,12 @@ class ASTReader /// Determine whether the given AST file is acceptable to load into a /// translation unit with the given language and target options. - static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, - const ModuleCache &ModCache, - const PCHContainerReader &PCHContainerRdr, - const LangOptions &LangOpts, - const TargetOptions &TargetOpts, - const PreprocessorOptions &PPOpts, - StringRef ExistingModuleCachePath, - bool RequireStrictOptionMatches = false); + static bool isAcceptableASTFile( + StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache, + const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, + const CodeGenOptions &CGOpts, const TargetOptions &TargetOpts, + const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath, + bool RequireStrictOptionMatches = false); /// Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index c86019f01d9f3..edf5bbaddf1aa 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -49,6 +49,7 @@ namespace clang { class ASTContext; class ASTReader; class Attr; +class CodeGenOptions; class CXXRecordDecl; class FileEntry; class FPOptionsOverride; @@ -124,6 +125,8 @@ class ASTWriter : public ASTDeserializationListener, /// The PCM manager which manages memory buffers for pcm files. ModuleCache &ModCache; + const CodeGenOptions &CodeGenOpts; + /// The preprocessor we're writing. Preprocessor *PP = nullptr; @@ -686,13 +689,14 @@ class ASTWriter : public ASTDeserializationListener, /// Create a new precompiled header writer that outputs to /// the given bitstream. ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, - ModuleCache &ModCache, + ModuleCache &ModCache, const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool IncludeTimestamps = true, bool BuildingImplicitModule = false, bool GeneratingReducedBMI = false); ~ASTWriter() override; const LangOptions &getLangOpts() const; + const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } /// Get a timestamp for output into the AST file. The actual timestamp /// of the specified file may be ignored if we have been instructed to not @@ -999,6 +1003,7 @@ class PCHGenerator : public SemaConsumer { public: PCHGenerator(Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool AllowASTWithErrors = false, bool IncludeTimestamps = true, bool BuildingImplicitModule = false, @@ -1021,13 +1026,14 @@ class CXX20ModulesGenerator : public PCHGenerator { virtual Module *getEmittingModule(ASTContext &Ctx) override; CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache, - StringRef OutputFile, bool GeneratingReducedBMI, - bool AllowASTWithErrors); + StringRef OutputFile, const CodeGenOptions &CodeGenOpts, + bool GeneratingReducedBMI, bool AllowASTWithErrors); public: CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache, - StringRef OutputFile, bool AllowASTWithErrors = false) - : CXX20ModulesGenerator(PP, ModCache, OutputFile, + StringRef OutputFile, const CodeGenOptions &CodeGenOpts, + bool AllowASTWithErrors = false) + : CXX20ModulesGenerator(PP, ModCache, OutputFile, CodeGenOpts, /*GeneratingReducedBMI=*/false, AllowASTWithErrors) {} @@ -1039,8 +1045,9 @@ class ReducedBMIGenerator : public CXX20ModulesGenerator { public: ReducedBMIGenerator(Preprocessor &PP, ModuleCache &ModCache, - StringRef OutputFile, bool AllowASTWithErrors = false) - : CXX20ModulesGenerator(PP, ModCache, OutputFile, + StringRef OutputFile, const CodeGenOptions &CodeGenOpts, + bool AllowASTWithErrors = false) + : CXX20ModulesGenerator(PP, ModCache, OutputFile, CodeGenOpts, /*GeneratingReducedBMI=*/true, AllowASTWithErrors) {} }; diff --git a/clang/lib/Basic/CodeGenOptions.cpp b/clang/lib/Basic/CodeGenOptions.cpp index 9a2aa9beb9e0d..ed877c40573ac 100644 --- a/clang/lib/Basic/CodeGenOptions.cpp +++ b/clang/lib/Basic/CodeGenOptions.cpp @@ -36,13 +36,13 @@ void CodeGenOptions::resetNonModularOptions(StringRef ModuleFormat) { // emitted into the PCM (-gmodules). if (ModuleFormat == "raw" && !DebugTypeExtRefs) { #define DEBUGOPT(Name, Bits, Default, Compatibility) \ - if constexpr (CK::Compatibility == CK::Affecting) \ + if constexpr (CK::Compatibility != CK::Benign) \ Name = Default; #define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \ - if constexpr (CK::Compatibility == CK::Affecting) \ + if constexpr (CK::Compatibility == CK::Benign) \ Name = Default; #define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \ - if constexpr (CK::Compatibility == CK::Affecting) \ + if constexpr (CK::Compatibility == CK::Benign) \ set##Name(Default); #include "clang/Basic/DebugOptions.def" } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 8bf7d24d8551d..875356455bca9 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -797,7 +797,8 @@ void CGDebugInfo::CreateCompileUnit() { // Create new compile unit. TheCU = DBuilder.createCompileUnit( LangTag, CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "", - LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, + CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO || + CGOpts.PrepareForThinLTO, CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.SplitDwarfFile, EmissionKind, DwoId, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling, NameTableKind, CGOpts.DebugRangesBaseAddress, remapDIPath(Sysroot), SDK); @@ -2282,7 +2283,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( Flags |= llvm::DINode::FlagRValueReference; if (!Method->isExternallyVisible()) SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit; - if (CGM.getLangOpts().Optimize) + if (CGM.getCodeGenOpts().OptimizationLevel != 0) SPFlags |= llvm::DISubprogram::SPFlagOptimized; // In this debug mode, emit type info for a class when its constructor type @@ -4353,7 +4354,7 @@ llvm::DISubprogram *CGDebugInfo::getFunctionFwdDeclOrStub(GlobalDecl GD, FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); if (!FD->isExternallyVisible()) SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit; - if (CGM.getLangOpts().Optimize) + if (CGM.getCodeGenOpts().OptimizationLevel != 0) SPFlags |= llvm::DISubprogram::SPFlagOptimized; if (Stub) { @@ -4679,7 +4680,7 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc, if (Fn->hasLocalLinkage()) SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit; - if (CGM.getLangOpts().Optimize) + if (CGM.getCodeGenOpts().OptimizationLevel != 0) SPFlags |= llvm::DISubprogram::SPFlagOptimized; llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs(); @@ -4762,7 +4763,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, unsigned LineNo = getLineNumber(Loc); unsigned ScopeLine = 0; llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero; - if (CGM.getLangOpts().Optimize) + if (CGM.getCodeGenOpts().OptimizationLevel != 0) SPFlags |= llvm::DISubprogram::SPFlagOptimized; llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D); @@ -5094,7 +5095,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, // Use VarDecl's Tag, Scope and Line number. auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext()); auto *D = DBuilder.createAutoVariable( - Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize, + Scope, FieldName, Unit, Line, FieldTy, + CGM.getCodeGenOpts().OptimizationLevel != 0, Flags | llvm::DINode::FlagArtificial, FieldAlign); // Insert an llvm.dbg.declare into the current block. @@ -5120,9 +5122,9 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::DILocalVariable *D = nullptr; if (ArgNo) { llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD); - D = DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags, - Annotations); + D = DBuilder.createParameterVariable( + Scope, Name, *ArgNo, Unit, Line, Ty, + CGM.getCodeGenOpts().OptimizationLevel != 0, Flags, Annotations); } else { // For normal local variable, we will try to find out whether 'VD' is the // copy parameter of coroutine. @@ -5163,8 +5165,9 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, D = RemapCoroArgToLocalVar(); // Or we will create a new DIVariable for this Decl if D dose not exists. if (!D) - D = DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags, Align); + D = DBuilder.createAutoVariable( + Scope, Name, Unit, Line, Ty, + CGM.getCodeGenOpts().OptimizationLevel != 0, Flags, Align); } // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), @@ -5218,7 +5221,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD, auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back()); // Create the descriptor for the variable. llvm::DILocalVariable *D = DBuilder.createAutoVariable( - Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize, + Scope, Name, Unit, Line, Ty, CGM.getCodeGenOpts().OptimizationLevel != 0, llvm::DINode::FlagZero, Align); if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) { @@ -5318,7 +5321,7 @@ void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { // Create the descriptor for the label. auto *L = DBuilder.createLabel( Scope, Name, Unit, Line, Column, /*IsArtificial=*/false, - /*CoroSuspendIdx=*/std::nullopt, CGM.getLangOpts().Optimize); + /*CoroSuspendIdx=*/std::nullopt, CGM.getCodeGenOpts().OptimizationLevel != 0); // Insert an llvm.dbg.label into the current block. DBuilder.insertLabel(L, @@ -5581,7 +5584,8 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, // Create the descriptor for the parameter. auto *debugVar = DBuilder.createParameterVariable( - scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags); + scope, Name, ArgNo, tunit, line, type, + CGM.getCodeGenOpts().OptimizationLevel != 0, flags); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(), @@ -6356,7 +6360,7 @@ llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) { llvm::DINode::DIFlags CGDebugInfo::getCallSiteRelatedAttrs() const { // Call site-related attributes are only useful in optimized programs, and // when there's a possibility of debugging backtraces. - if (!CGM.getLangOpts().Optimize || + if (CGM.getCodeGenOpts().OptimizationLevel == 0 || DebugKind == llvm::codegenoptions::NoDebugInfo || DebugKind == llvm::codegenoptions::LocTrackingOnly) return llvm::DINode::FlagZero; diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 8ccc37ef98a74..d26461d8e427a 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1092,7 +1092,7 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); - if (CGM.getLangOpts().Optimize) { + if (CGM.getCodeGenOpts().OptimizationLevel != 0) { Fn->removeFnAttr(llvm::Attribute::NoInline); Fn->removeFnAttr(llvm::Attribute::OptimizeNone); Fn->addFnAttr(llvm::Attribute::AlwaysInline); @@ -3199,7 +3199,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, &CGM.getModule()); CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, TaskPrivatesMapFnInfo); - if (CGM.getLangOpts().Optimize) { + if (CGM.getCodeGenOpts().OptimizationLevel != 0) { TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 5493cc92bd8b0..eb5b6045510df 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -995,7 +995,7 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::vector<std::unique_ptr<ASTConsumer>> Consumers(2); Consumers[0] = std::make_unique<ReducedBMIGenerator>( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().ModuleOutputPath); + CI.getFrontendOpts().ModuleOutputPath, CI.getCodeGenOpts()); Consumers[1] = std::move(Result); return std::make_unique<MultiplexConsumer>(std::move(Consumers)); } diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 4ebec8e074330..dcf2865c94723 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -215,8 +215,8 @@ struct ASTUnit::ASTWriterData { llvm::BitstreamWriter Stream; ASTWriter Writer; - ASTWriterData(ModuleCache &ModCache) - : Stream(Buffer), Writer(Stream, Buffer, ModCache, {}) {} + ASTWriterData(ModuleCache &ModCache, const CodeGenOptions &CGOpts) + : Stream(Buffer), Writer(Stream, Buffer, ModCache, CGOpts, {}) {} }; void ASTUnit::clearFileLevelDecls() { @@ -235,7 +235,8 @@ const unsigned DefaultPreambleRebuildInterval = 5; static std::atomic<unsigned> ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) - : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")), + : CodeGenOpts(std::make_unique<CodeGenOptions>()), + MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")), ShouldCacheCodeCompletionResults(false), IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false), UnsafeToFree(false) { @@ -516,6 +517,7 @@ class ASTInfoCollector : public ASTReaderListener { HeaderSearchOptions &HSOpts; PreprocessorOptions &PPOpts; LangOptions &LangOpt; + CodeGenOptions &CodeGenOpts; std::shared_ptr<TargetOptions> &TargetOpts; IntrusiveRefCntPtr<TargetInfo> &Target; unsigned &Counter; @@ -525,12 +527,12 @@ class ASTInfoCollector : public ASTReaderListener { public: ASTInfoCollector(Preprocessor &PP, ASTContext *Context, HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, - LangOptions &LangOpt, + LangOptions &LangOpt, CodeGenOptions &CodeGenOpts, std::shared_ptr<TargetOptions> &TargetOpts, IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter) : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), - LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target), - Counter(Counter) {} + LangOpt(LangOpt), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), + Target(Target), Counter(Counter) {} bool ReadLanguageOptions(const LangOptions &LangOpts, StringRef ModuleFilename, bool Complain, @@ -555,6 +557,13 @@ class ASTInfoCollector : public ASTReaderListener { return false; } + bool ReadCodeGenOptions(const CodeGenOptions &CGOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) override { + this->CodeGenOpts = CGOpts; + return false; + } + bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, StringRef ModuleFilename, StringRef SpecificModuleCachePath, @@ -858,14 +867,16 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( DisableValidationForModuleKind::None; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = DisableValidationForModuleKind::All; - AST->Reader = new ASTReader( - PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, {}, /*isysroot=*/"", - /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors); + AST->Reader = new ASTReader(PP, *AST->ModCache, AST->Ctx.get(), + PCHContainerRdr, *AST->CodeGenOpts, {}, + /*isysroot=*/"", + /*DisableValidationKind=*/disableValid, + AllowASTWithCompilerErrors); unsigned Counter = 0; AST->Reader->setListener(std::make_unique<ASTInfoCollector>( *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, - AST->TargetOpts, AST->Target, Counter)); + *AST->CodeGenOpts, AST->TargetOpts, AST->Target, Counter)); // Attach the AST reader to the AST context as an external AST // source, so that declarations will be deserialized from the @@ -1836,6 +1847,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine( AST->DiagOpts = DiagOpts; AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); + AST->CodeGenOpts = std::make_unique<CodeGenOptions>(CI->getCodeGenOpts()); VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS); AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); AST->StorePreamblesInMemory = StorePreamblesInMemory; @@ -1851,7 +1863,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine( AST->Invocation = CI; AST->SkipFunctionBodies = SkipFunctionBodies; if (ForSerialization) - AST->WriterData.reset(new ASTWriterData(*AST->ModCache)); + AST->WriterData.reset(new ASTWriterData(*AST->ModCache, *AST->CodeGenOpts)); // Zero out now to ease cleanup during crash recovery. CI = nullptr; Diags = nullptr; @@ -2385,7 +2397,7 @@ bool ASTUnit::serialize(raw_ostream &OS) { SmallString<128> Buffer; llvm::BitstreamWriter Stream(Buffer); IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache(); - ASTWriter Writer(Stream, Buffer, *ModCache, {}); + ASTWriter Writer(Stream, Buffer, *ModCache, *CodeGenOpts, {}); return serializeUnit(Writer, Buffer, getSema(), OS); } diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index f9a398dbfb90f..ba7c767f8e987 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -62,7 +62,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, std::unique_ptr<ASTReader> Reader; Reader.reset(new ASTReader( PP, CI.getModuleCache(), &CI.getASTContext(), CI.getPCHContainerReader(), - /*Extensions=*/{}, + CI.getCodeGenOpts(), /*Extensions=*/{}, /*isysroot=*/"", DisableValidationForModuleKind::PCH)); for (unsigned ti = 0; ti < bufNames.size(); ++ti) { StringRef sr(bufNames[ti]); @@ -138,7 +138,8 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource( ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions; auto consumer = std::make_unique<PCHGenerator>( Clang->getPreprocessor(), Clang->getModuleCache(), "-", /*isysroot=*/"", - Buffer, Extensions, /*AllowASTWithErrors=*/true); + Buffer, Clang->getCodeGenOpts(), Extensions, + /*AllowASTWithErrors=*/true); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(std::move(consumer)); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 09a66b652518f..6c8b08b6acb1b 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -614,7 +614,7 @@ void CompilerInstance::createPCHExternalASTSource( TheASTReader = createPCHExternalASTSource( Path, getHeaderSearchOpts().Sysroot, DisableValidation, AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(), - getASTContext(), getPCHContainerReader(), + getASTContext(), getPCHContainerReader(), getCodeGenOpts(), getFrontendOpts().ModuleFileExtensions, DependencyCollectors, DeserializationListener, OwnDeserializationListener, Preamble, getFrontendOpts().UseGlobalModuleIndex); @@ -625,6 +625,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( DisableValidationForModuleKind DisableValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, @@ -633,7 +634,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( PP.getHeaderSearchInfo().getHeaderSearchOpts(); IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader( - PP, ModCache, &Context, PCHContainerRdr, Extensions, + PP, ModCache, &Context, PCHContainerRdr, CodeGenOpts, Extensions, Sysroot.empty() ? "" : Sysroot.data(), DisableValidation, AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, @@ -1746,7 +1747,8 @@ void CompilerInstance::createASTReader() { "Reading modules", *timerGroup); TheASTReader = new ASTReader( getPreprocessor(), getModuleCache(), &getASTContext(), - getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions, + getPCHContainerReader(), getCodeGenOpts(), + getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHOrModuleValidation, /*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index b9f75796ecc16..0bdd9f0a6dec2 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4436,22 +4436,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.OpenACCMacroOverride = A->getValue(); } - // FIXME: Eliminate this dependency. - unsigned Opt = getOptimizationLevel(Args, IK, Diags), - OptSize = getOptimizationLevelSize(Args); - Opts.Optimize = Opt != 0; - Opts.OptimizeSize = OptSize != 0; - - // This is the __NO_INLINE__ define, which just depends on things like the - // optimization level and -fno-inline, not actually whether the backend has - // inlining enabled. - Opts.NoInlineDefine = !Opts.Optimize; - if (Arg *InlineArg = Args.getLastArg( - options::OPT_finline_functions, options::OPT_finline_hint_functions, - options::OPT_fno_inline_functions, options::OPT_fno_inline)) - if (InlineArg->getOption().matches(options::OPT_fno_inline)) - Opts.NoInlineDefine = true; - if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { StringRef Val = A->getValue(); if (Val == "fast") @@ -5301,6 +5285,21 @@ std::string CompilerInvocation::getModuleHash() const { HBuilder.add(*Build); } + // Extend the signature with affecting codegen options. + { + using CK = CodeGenOptions::CompatibilityKind; +#define CODEGENOPT(Name, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) \ + HBuilder.add(CodeGenOpts->Name); +#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) \ + HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name())); +#define DEBUGOPT(Name, Bits, Default, Compatibility) +#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) +#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) +#include "clang/Basic/CodeGenOptions.def" + } + // When compiling with -gmodules, also hash -fdebug-prefix-map as it // affects the debug info in the PCM. if (getCodeGenOpts().DebugTypeExtRefs) @@ -5311,13 +5310,13 @@ std::string CompilerInvocation::getModuleHash() const { // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`. using CK = CodeGenOptions::CompatibilityKind; #define DEBUGOPT(Name, Bits, Default, Compatibility) \ - if constexpr (CK::Compatibility == CK::Affecting) \ + if constexpr (CK::Compatibility != CK::Benign) \ HBuilder.add(CodeGenOpts->Name); #define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) \ - if constexpr (CK::Compatibility == CK::Affecting) \ + if constexpr (CK::Compatibility != CK::Benign) \ HBuilder.add(CodeGenOpts->Name); #define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) \ - if constexpr (CK::Compatibility == CK::Affecting) \ + if constexpr (CK::Compatibility != CK::Benign) \ HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name())); #include "clang/Basic/DebugOptions.def" } diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index f5996a8e1e88b..1d82fc775b28a 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -947,8 +947,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (ASTReader::isAcceptableASTFile( Dir->path(), FileMgr, CI.getModuleCache(), CI.getPCHContainerReader(), CI.getLangOpts(), - CI.getTargetOpts(), CI.getPreprocessorOpts(), - SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) { + CI.getCodeGenOpts(), CI.getTargetOpts(), + CI.getPreprocessorOpts(), SpecificModuleCachePath, + /*RequireStrictOptionMatches=*/true)) { PPOpts.ImplicitPCHInclude = std::string(Dir->path()); Found = true; break; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 89eb0b689f85c..dcfbd5386f3dc 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -139,7 +139,7 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::vector<std::unique_ptr<ASTConsumer>> Consumers; Consumers.push_back(std::make_unique<PCHGenerator>( CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, - FrontendOpts.ModuleFileExtensions, + CI.getCodeGenOpts(), FrontendOpts.ModuleFileExtensions, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, FrontendOpts.IncludeTimestamps, FrontendOpts.BuildingImplicitModule, +CI.getLangOpts().CacheGeneratedPCH)); @@ -199,7 +199,7 @@ GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI, Consumers.push_back(std::make_unique<PCHGenerator>( CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, - CI.getFrontendOpts().ModuleFileExtensions, + CI.getCodeGenOpts(), CI.getFrontendOpts().ModuleFileExtensions, /*AllowASTWithErrors=*/ +CI.getFrontendOpts().AllowPCMWithCompilerErrors, /*IncludeTimestamps=*/ @@ -292,13 +292,13 @@ GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, !CI.getFrontendOpts().ModuleOutputPath.empty()) { Consumers.push_back(std::make_unique<ReducedBMIGenerator>( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().ModuleOutputPath, + CI.getFrontendOpts().ModuleOutputPath, CI.getCodeGenOpts(), +CI.getFrontendOpts().AllowPCMWithCompilerErrors)); } Consumers.push_back(std::make_unique<CXX20ModulesGenerator>( CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().OutputFile, + CI.getFrontendOpts().OutputFile, CI.getCodeGenOpts(), +CI.getFrontendOpts().AllowPCMWithCompilerErrors)); return std::make_unique<MultiplexConsumer>(std::move(Consumers)); @@ -313,9 +313,9 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, std::unique_ptr<ASTConsumer> GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return std::make_unique<ReducedBMIGenerator>(CI.getPreprocessor(), - CI.getModuleCache(), - CI.getFrontendOpts().OutputFile); + return std::make_unique<ReducedBMIGenerator>( + CI.getPreprocessor(), CI.getModuleCache(), + CI.getFrontendOpts().OutputFile, CI.getCodeGenOpts()); } bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) { @@ -358,7 +358,8 @@ void VerifyPCHAction::ExecuteAction() { const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; std::unique_ptr<ASTReader> Reader(new ASTReader( CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(), - CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions, + CI.getPCHContainerReader(), CI.getCodeGenOpts(), + CI.getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), DisableValidationForModuleKind::None, /*AllowASTWithCompilerErrors*/ false, diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index f64613fb4a6cb..3eb5e6ff1c0bd 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -865,6 +865,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, const PreprocessorOptions &PPOpts, + const CodeGenOptions &CGOpts, MacroBuilder &Builder) { // Compiler version introspection macros. Builder.defineMacro("__llvm__"); // LLVM Backend @@ -1073,9 +1074,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__clang_wide_literal_encoding__", "\"UTF-16\""); } - if (LangOpts.Optimize) + if (CGOpts.OptimizationLevel != 0) Builder.defineMacro("__OPTIMIZE__"); - if (LangOpts.OptimizeSize) + if (CGOpts.OptimizeSize != 0) Builder.defineMacro("__OPTIMIZE_SIZE__"); if (LangOpts.FastMath) @@ -1396,7 +1397,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.GNUCVersion) addLockFreeMacros("__GCC_ATOMIC_"); - if (LangOpts.NoInlineDefine) + if (CGOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) Builder.defineMacro("__NO_INLINE__"); if (unsigned PICLevel = LangOpts.PICLevel) { @@ -1575,10 +1576,11 @@ void clang::InitializePreprocessor(Preprocessor &PP, // macros. This is not the right way to handle this. if ((LangOpts.CUDA || LangOpts.isTargetDevice()) && PP.getAuxTargetInfo()) InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts, - PP.getPreprocessorOpts(), Builder); + PP.getPreprocessorOpts(), CodeGenOpts, + Builder); InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, - PP.getPreprocessorOpts(), Builder); + PP.getPreprocessorOpts(), CodeGenOpts, Builder); // Install definitions to make Objective-C++ ARC work well with various // C++ Standard Library implementations. diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 3f3fe3c9937e4..146cf903a5727 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -293,8 +293,9 @@ class PrecompilePreambleConsumer : public PCHGenerator { public: PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP, ModuleCache &ModCache, StringRef isysroot, - std::shared_ptr<PCHBuffer> Buffer) - : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer), + std::shared_ptr<PCHBuffer> Buffer, + const CodeGenOptions &CodeGenOpts) + : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer), CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>>(), /*AllowASTWithErrors=*/true), Action(Action) {} @@ -337,7 +338,8 @@ PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI, Sysroot.clear(); return std::make_unique<PrecompilePreambleConsumer>( - *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer); + *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, Buffer, + CI.getCodeGenOpts()); } template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 30e0973149594..4a96e65bb536c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -175,6 +175,15 @@ bool ChainedASTReaderListener::ReadLanguageOptions( AllowCompatibleDifferences); } +bool ChainedASTReaderListener::ReadCodeGenOptions( + const CodeGenOptions &CGOpts, StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) { + return First->ReadCodeGenOptions(CGOpts, ModuleFilename, Complain, + AllowCompatibleDifferences) || + Second->ReadCodeGenOptions(CGOpts, ModuleFilename, Complain, + AllowCompatibleDifferences); +} + bool ChainedASTReaderListener::ReadTargetOptions( const TargetOptions &TargetOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) { @@ -383,6 +392,68 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, return false; } +static bool checkCodegenOptions(const CodeGenOptions &CGOpts, + const CodeGenOptions &ExistingCGOpts, + StringRef ModuleFilename, + DiagnosticsEngine *Diags, + bool AllowCompatibleDifferences = true) { + // FIXME: Specify and print a description for each option instead of the name. + // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`. + using CK = CodeGenOptions::CompatibilityKind; +#define CODEGENOPT(Name, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) { \ + if ((CK::Compatibility == CK::NotCompatible) || \ + (CK::Compatibility == CK::Compatible && \ + !AllowCompatibleDifferences)) { \ + if (ExistingCGOpts.Name != CGOpts.Name) { \ + if (Diags) { \ + if (Bits == 1) \ + Diags->Report(diag::err_ast_file_codegenopt_mismatch) \ + << #Name << CGOpts.Name << ExistingCGOpts.Name \ + << ModuleFilename; \ + else \ + Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \ + << #Name << ModuleFilename; \ + } \ + return true; \ + } \ + } \ + } + +#define VALUE_CODEGENOPT(Name, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) { \ + if ((CK::Compatibility == CK::NotCompatible) || \ + (CK::Compatibility == CK::Compatible && \ + !AllowCompatibleDifferences)) { \ + if (ExistingCGOpts.Name != CGOpts.Name) { \ + if (Diags) \ + Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \ + << #Name << ModuleFilename; \ + return true; \ + } \ + } \ + } +#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) { \ + if ((CK::Compatibility == CK::NotCompatible) || \ + (CK::Compatibility == CK::Compatible && \ + !AllowCompatibleDifferences)) { \ + if (ExistingCGOpts.get##Name() != CGOpts.get##Name()) { \ + if (Diags) \ + Diags->Report(diag::err_ast_file_codegenopt_value_mismatch) \ + << #Name << ModuleFilename; \ + return true; \ + } \ + } \ + } +#define DEBUGOPT(Name, Bits, Default, Compatibility) +#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) +#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) +#include "clang/Basic/CodeGenOptions.def" + + return false; +} + /// Compare the given set of target options against an existing set of /// target options. /// @@ -462,6 +533,15 @@ bool PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts, AllowCompatibleDifferences); } +bool PCHValidator::ReadCodeGenOptions(const CodeGenOptions &CGOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) { + const CodeGenOptions &ExistingCGOpts = Reader.getCodeGenOpts(); + return checkCodegenOptions(ExistingCGOpts, CGOpts, ModuleFilename, + Complain ? &Reader.Diags : nullptr, + AllowCompatibleDifferences); +} + bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) { @@ -2993,6 +3073,14 @@ ASTReader::ASTReadResult ASTReader::ReadOptionsBlock( break; } + case CODEGEN_OPTIONS: { + bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; + if (ParseCodeGenOptions(Record, Filename, Complain, Listener, + AllowCompatibleConfigurationMismatch)) + Result = ConfigurationMismatch; + break; + } + case TARGET_OPTIONS: { bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0; if (ParseTargetOptions(Record, Filename, Complain, Listener, @@ -5639,6 +5727,7 @@ namespace { class SimplePCHValidator : public ASTReaderListener { const LangOptions &ExistingLangOpts; + const CodeGenOptions &ExistingCGOpts; const TargetOptions &ExistingTargetOpts; const PreprocessorOptions &ExistingPPOpts; std::string ExistingModuleCachePath; @@ -5647,11 +5736,12 @@ namespace { public: SimplePCHValidator(const LangOptions &ExistingLangOpts, + const CodeGenOptions &ExistingCGOpts, const TargetOptions &ExistingTargetOpts, const PreprocessorOptions &ExistingPPOpts, StringRef ExistingModuleCachePath, FileManager &FileMgr, bool StrictOptionMatches) - : ExistingLangOpts(ExistingLangOpts), + : ExistingLangOpts(ExistingLangOpts), ExistingCGOpts(ExistingCGOpts), ExistingTargetOpts(ExistingTargetOpts), ExistingPPOpts(ExistingPPOpts), ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr), @@ -5664,6 +5754,13 @@ namespace { nullptr, AllowCompatibleDifferences); } + bool ReadCodeGenOptions(const CodeGenOptions &CGOpts, + StringRef ModuleFilename, bool Complain, + bool AllowCompatibleDifferences) override { + return checkCodegenOptions(ExistingCGOpts, CGOpts, ModuleFilename, + nullptr, AllowCompatibleDifferences); + } + bool ReadTargetOptions(const TargetOptions &TargetOpts, StringRef ModuleFilename, bool Complain, bool AllowCompatibleDifferences) override { @@ -6012,9 +6109,10 @@ bool ASTReader::readASTFileControlBlock( bool ASTReader::isAcceptableASTFile( StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, - const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, - StringRef ExistingModuleCachePath, bool RequireStrictOptionMatches) { - SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, + const CodeGenOptions &CGOpts, const TargetOptions &TargetOpts, + const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath, + bool RequireStrictOptionMatches) { + SimplePCHValidator validator(LangOpts, CGOpts, TargetOpts, PPOpts, ExistingModuleCachePath, FileMgr, RequireStrictOptionMatches); return !readASTFileControlBlock(Filename, FileMgr, ModCache, PCHContainerRdr, @@ -6395,6 +6493,28 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, AllowCompatibleDifferences); } +bool ASTReader::ParseCodeGenOptions(const RecordData &Record, + StringRef ModuleFilename, bool Complain, + ASTReaderListener &Listener, + bool AllowCompatibleDifferences) { + unsigned Idx = 0; + CodeGenOptions CGOpts; + using CK = CodeGenOptions::CompatibilityKind; +#define CODEGENOPT(Name, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) \ + CGOpts.Name = static_cast<unsigned>(Record[Idx++]); +#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) \ + CGOpts.set##Name(static_cast<clang::CodeGenOptions::Type>(Record[Idx++])); +#define DEBUGOPT(Name, Bits, Default, Compatibility) +#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) +#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) +#include "clang/Basic/CodeGenOptions.def" + + return Listener.ReadCodeGenOptions(CGOpts, ModuleFilename, Complain, + AllowCompatibleDifferences); +} + bool ASTReader::ParseTargetOptions(const RecordData &Record, StringRef ModuleFilename, bool Complain, ASTReaderListener &Listener, @@ -10985,6 +11105,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context, const PCHContainerReader &PCHContainerRdr, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, StringRef isysroot, DisableValidationForModuleKind DisableValidationKind, @@ -10999,6 +11120,7 @@ ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache, SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), StackHandler(Diags), PP(PP), ContextObj(Context), + CodeGenOpts(CodeGenOpts), ModuleMgr(PP.getFileManager(), ModCache, PCHContainerRdr, PP.getHeaderSearchInfo()), DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot), diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1a20fc9595dce..847283e9842e5 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -898,6 +898,7 @@ void ASTWriter::WriteBlockInfoBlock() { BLOCK(OPTIONS_BLOCK); RECORD(LANGUAGE_OPTIONS); + RECORD(CODEGEN_OPTIONS); RECORD(TARGET_OPTIONS); RECORD(FILE_SYSTEM_OPTIONS); RECORD(HEADER_SEARCH_OPTIONS); @@ -1646,6 +1647,23 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) { Stream.EmitRecord(LANGUAGE_OPTIONS, Record); + // Codegen options. + // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`. + using CK = CodeGenOptions::CompatibilityKind; + Record.clear(); + const CodeGenOptions &CGOpts = getCodeGenOpts(); +#define CODEGENOPT(Name, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) \ + Record.push_back(static_cast<unsigned>(CGOpts.Name)); +#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \ + if constexpr (CK::Compatibility != CK::Benign) \ + Record.push_back(static_cast<unsigned>(CGOpts.get##Name())); +#define DEBUGOPT(Name, Bits, Default, Compatibility) +#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility) +#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility) +#include "clang/Basic/CodeGenOptions.def" + Stream.EmitRecord(CODEGEN_OPTIONS, Record); + // Target options. Record.clear(); const TargetInfo &Target = PP.getTargetInfo(); @@ -5384,11 +5402,12 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, ModuleCache &ModCache, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool IncludeTimestamps, bool BuildingImplicitModule, bool GeneratingReducedBMI) : Stream(Stream), Buffer(Buffer), ModCache(ModCache), - IncludeTimestamps(IncludeTimestamps), + CodeGenOpts(CodeGenOpts), IncludeTimestamps(IncludeTimestamps), BuildingImplicitModule(BuildingImplicitModule), GeneratingReducedBMI(GeneratingReducedBMI) { for (const auto &Ext : Extensions) { diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index 77317f0a1db32..f8be0e45078db 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -25,13 +25,14 @@ using namespace clang; PCHGenerator::PCHGenerator( Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, + const CodeGenOptions &CodeGenOpts, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, bool AllowASTWithErrors, bool IncludeTimestamps, bool BuildingImplicitModule, bool ShouldCacheASTInMemory, bool GeneratingReducedBMI) : PP(PP), Subject(&PP), OutputFile(OutputFile), isysroot(isysroot.str()), Buffer(std::move(Buffer)), Stream(this->Buffer->Data), - Writer(Stream, this->Buffer->Data, ModCache, Extensions, + Writer(Stream, this->Buffer->Data, ModCache, CodeGenOpts, Extensions, IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI), AllowASTWithErrors(AllowASTWithErrors), ShouldCacheASTInMemory(ShouldCacheASTInMemory) { @@ -102,11 +103,12 @@ void PCHGenerator::anchor() {} CXX20ModulesGenerator::CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile, + const CodeGenOptions &CodeGenOpts, bool GeneratingReducedBMI, bool AllowASTWithErrors) : PCHGenerator( PP, ModCache, OutputFile, llvm::StringRef(), - std::make_shared<PCHBuffer>(), + std::make_shared<PCHBuffer>(), CodeGenOpts, /*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(), AllowASTWithErrors, /*IncludeTimestamps=*/false, /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false, diff --git a/clang/test/PCH/no-validate-pch.cl b/clang/test/PCH/no-validate-pch.cl index f6a7c65461fe1..ce3a9095fe2e6 100644 --- a/clang/test/PCH/no-validate-pch.cl +++ b/clang/test/PCH/no-validate-pch.cl @@ -16,7 +16,7 @@ // CHECK: note: previous definition is here // CHECK: #define X 4 -// CHECK-VAL: error: __OPTIMIZE__ predefined macro was enabled in precompiled file '{{.*}}' but is currently disabled +// CHECK-VAL: error: OptimizationLevel differs in precompiled file '{{.*}}' vs. current file // CHECK-VAL: error: definition of macro 'X' differs between the precompiled file '{{.*}}' ('4') and the command line ('5') void test(void) { diff --git a/llvm/clang/test/Modules/implicit-opt-level.c b/llvm/clang/test/Modules/implicit-opt-level.c new file mode 100644 index 0000000000000..f6f1f58d31d79 --- /dev/null +++ b/llvm/clang/test/Modules/implicit-opt-level.c @@ -0,0 +1,15 @@ +// This test checks that under implicit modules, different optimization levels +// get different context hashes. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +//--- module.modulemap +module M { header "M.h" } +//--- M.h +//--- tu.c +#include "M.h" + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -O0 -fsyntax-only %t/tu.c +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -O1 -fsyntax-only %t/tu.c +// RUN: find %t/cache -name "M-*.pcm" | count 2 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits