From b19d3ee7120bff4a84db7c9fa8f86c9b6ec3b1cf Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Mon, 11 Jul 2022 19:50:31 +0100 Subject: [PATCH] Revert "[C++20][Modules] Build module static initializers per P1874R1." This reverts commit ac507102d258b6fc0cb57eb60c9dfabd57ff562f. reverting while we figuere out why one of the green dragon lldb test fails. --- clang/include/clang/AST/ASTContext.h | 9 -- clang/include/clang/Basic/Module.h | 12 -- clang/include/clang/Sema/Sema.h | 5 - clang/lib/CodeGen/CGDeclCXX.cpp | 179 ++------------------------ clang/lib/CodeGen/CodeGenModule.cpp | 55 +------- clang/lib/CodeGen/CodeGenModule.h | 8 +- clang/lib/Parse/ParseAST.cpp | 23 ---- clang/lib/Sema/SemaModule.cpp | 10 -- clang/test/CodeGen/module-intializer-pmf.cpp | 41 ------ clang/test/CodeGen/module-intializer.cpp | 186 --------------------------- 10 files changed, 11 insertions(+), 517 deletions(-) delete mode 100644 clang/test/CodeGen/module-intializer-pmf.cpp delete mode 100644 clang/test/CodeGen/module-intializer.cpp diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index db7ae9a..87b5a60 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -472,9 +472,6 @@ class ASTContext : public RefCountedBase { }; llvm::DenseMap ModuleInitializers; - /// For module code-gen cases, this is the top-level module we are building. - Module *TopLevelModule = nullptr; - static constexpr unsigned ConstantArrayTypesLog2InitSize = 8; static constexpr unsigned GeneralTypesLog2InitSize = 9; static constexpr unsigned FunctionProtoTypesLog2InitSize = 12; @@ -1078,12 +1075,6 @@ public: /// Get the initializations to perform when importing a module, if any. ArrayRef getModuleInitializers(Module *M); - /// Set the (C++20) module we are building. - void setModuleForCodeGen(Module *M) { TopLevelModule = M; } - - /// Get module under construction, nullptr if this is not a C++20 module. - Module *getModuleForCodeGen() const { return TopLevelModule; } - TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl->getMostRecentDecl(); } diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 47d736a..a1778ba 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -665,18 +665,6 @@ public: Module *findSubmodule(StringRef Name) const; Module *findOrInferSubmodule(StringRef Name); - /// Get the Global Module Fragment (sub-module) for this module, it there is - /// one. - /// - /// \returns The GMF sub-module if found, or NULL otherwise. - Module *getGlobalModuleFragment() { return findSubmodule(""); } - - /// Get the Private Module Fragment (sub-module) for this module, it there is - /// one. - /// - /// \returns The PMF sub-module if found, or NULL otherwise. - Module *getPrivateModuleFragment() { return findSubmodule(""); } - /// Determine whether the specified module would be visible to /// a lookup at the end of this module. /// diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7dafb1b..75a2e7e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2281,11 +2281,6 @@ public: return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module; } - /// Is the module scope we are an interface? - bool currentModuleIsInterface() const { - return ModuleScopes.empty() ? false : ModuleScopes.back().ModuleInterface; - } - /// Get the module owning an entity. Module *getOwningModule(const Decl *Entity) { return Entity->getOwningModule(); diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 98b6306..de5cb91 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -618,127 +618,6 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() { CXXThreadLocals.clear(); } -/* Build the initializer for a C++20 module: - This is arranged to be run only once regardless of how many times the module - might be included transitively. This arranged by using a control variable. - - First we call any initializers for imported modules. - We then call initializers for the Global Module Fragment (if present) - We then call initializers for the current module. - We then call initializers for the Private Module Fragment (if present) -*/ - -void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) { - while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) - CXXGlobalInits.pop_back(); - - // We create the function, even if it is empty, since an importer of this - // module will refer to it unconditionally (for the current implementation - // there is no way for the importer to know that an importee does not need - // an initializer to be run). - - // Module initializers for imported modules are emitted first. - // Collect the modules that we import - SmallVector AllImports; - // Ones that we export - for (auto I : Primary->Exports) - AllImports.push_back(I.getPointer()); - // Ones that we only import. - for (Module *M : Primary->Imports) - AllImports.push_back(M); - - SmallVector ModuleInits; - for (Module *M : AllImports) { - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - SmallString<256> FnName; - { - llvm::raw_svector_ostream Out(FnName); - cast(getCXXABI().getMangleContext()) - .mangleModuleInitializer(M, Out); - } - assert(!GetGlobalValue(FnName.str()) && - "We should only have one use of the initializer call"); - llvm::Function *Fn = llvm::Function::Create( - FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule()); - ModuleInits.push_back(Fn); - } - AllImports.clear(); - - // Add any initializers with specified priority; this uses the same approach - // as EmitCXXGlobalInitFunc(). - if (!PrioritizedCXXGlobalInits.empty()) { - SmallVector LocalCXXGlobalInits; - llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), - PrioritizedCXXGlobalInits.end()); - for (SmallVectorImpl::iterator - I = PrioritizedCXXGlobalInits.begin(), - E = PrioritizedCXXGlobalInits.end(); - I != E;) { - SmallVectorImpl::iterator PrioE = - std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp()); - - for (; I < PrioE; ++I) - ModuleInits.push_back(I->second); - } - PrioritizedCXXGlobalInits.clear(); - } - - // Now append the ones without specified priority. - for (auto F : CXXGlobalInits) - ModuleInits.push_back(F); - CXXGlobalInits.clear(); - - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction(); - - // We now build the initializer for this module, which has a mangled name - // as per the Itanium ABI . The action of the initializer is guarded so that - // each init is run just once (even though a module might be imported - // multiple times via nested use). - llvm::Function *Fn; - llvm::GlobalVariable *Guard = nullptr; - { - SmallString<256> InitFnName; - llvm::raw_svector_ostream Out(InitFnName); - cast(getCXXABI().getMangleContext()) - .mangleModuleInitializer(Primary, Out); - Fn = CreateGlobalInitOrCleanUpFunction( - FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false, - llvm::GlobalVariable::ExternalLinkage); - - Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false, - llvm::GlobalVariable::InternalLinkage, - llvm::ConstantInt::get(Int8Ty, 0), - InitFnName.str() + "__in_chrg"); - } - CharUnits GuardAlign = CharUnits::One(); - Guard->setAlignment(GuardAlign.getAsAlign()); - - CodeGenFunction(*this).GenerateCXXGlobalInitFunc( - Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign)); - // We allow for the case that a module object is added to a linked binary - // without a specific call to the the initializer. This also ensure that - // implementation partition initializers are called when the partition - // is not imported as an interface. - AddGlobalCtor(Fn); - - // See the comment in EmitCXXGlobalInitFunc about OpenCL global init - // functions. - if (getLangOpts().OpenCL) { - GenKernelArgMetadata(Fn); - Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL); - } - - assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice || - getLangOpts().GPUAllowDeviceInit); - if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) { - Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); - Fn->addFnAttr("device-init"); - } - - ModuleInits.clear(); -} - static SmallString<128> getTransformedFileName(llvm::Module &M) { SmallString<128> FileName = llvm::sys::path::filename(M.getName()); @@ -771,26 +650,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() { while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) CXXGlobalInits.pop_back(); - // When we import C++20 modules, we must run their initializers first. - SmallVector ModuleInits; - if (CXX20ModuleInits) - for (Module *M : ImportedModules) { - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - SmallString<256> FnName; - { - llvm::raw_svector_ostream Out(FnName); - cast(getCXXABI().getMangleContext()) - .mangleModuleInitializer(M, Out); - } - assert(!GetGlobalValue(FnName.str()) && - "We should only have one use of the initializer call"); - llvm::Function *Fn = llvm::Function::Create( - FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule()); - ModuleInits.push_back(Fn); - } - - if (ModuleInits.empty() && CXXGlobalInits.empty() && - PrioritizedCXXGlobalInits.empty()) + if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) return; llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); @@ -816,13 +676,6 @@ CodeGenModule::EmitCXXGlobalInitFunc() { llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI); - // Prepend the module inits to the highest priority set. - if (!ModuleInits.empty()) { - for (auto F : ModuleInits) - LocalCXXGlobalInits.push_back(F); - ModuleInits.clear(); - } - for (; I < PrioE; ++I) LocalCXXGlobalInits.push_back(I->second); @@ -832,33 +685,17 @@ CodeGenModule::EmitCXXGlobalInitFunc() { PrioritizedCXXGlobalInits.clear(); } - if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() && - CXXGlobalInits.empty()) + if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty()) return; - for (auto F : CXXGlobalInits) - ModuleInits.push_back(F); - CXXGlobalInits.clear(); - // Include the filename in the symbol name. Including "sub_" matches gcc // and makes sure these symbols appear lexicographically behind the symbols // with priority emitted above. - llvm::Function *Fn; - if (CXX20ModuleInits && getContext().getModuleForCodeGen()) { - SmallString<256> InitFnName; - llvm::raw_svector_ostream Out(InitFnName); - cast(getCXXABI().getMangleContext()) - .mangleModuleInitializer(getContext().getModuleForCodeGen(), Out); - Fn = CreateGlobalInitOrCleanUpFunction( - FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false, - llvm::GlobalVariable::ExternalLinkage); - } else - Fn = CreateGlobalInitOrCleanUpFunction( - FTy, - llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())), - FI); - - CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits); + llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( + FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())), + FI); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits); AddGlobalCtor(Fn); // In OpenCL global init functions must be converted to kernels in order to @@ -881,7 +718,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() { Fn->addFnAttr("device-init"); } - ModuleInits.clear(); + CXXGlobalInits.clear(); } void CodeGenModule::EmitCXXGlobalCleanUpFunc() { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e282bc8..56ed59d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -136,13 +136,6 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, GlobalsInt8PtrTy = Int8Ty->getPointerTo(DL.getDefaultGlobalsAddressSpace()); ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace(); - // Build C++20 Module initializers. - // TODO: Add Microsoft here once we know the mangling required for the - // initializers. - CXX20ModuleInits = - LangOpts.CPlusPlusModules && getCXXABI().getMangleContext().getKind() == - ItaniumMangleContext::MK_Itanium; - RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC(); if (LangOpts.ObjC) @@ -516,18 +509,12 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO, } void CodeGenModule::Release() { - Module *Primary = getContext().getModuleForCodeGen(); - if (CXX20ModuleInits && Primary) - EmitModuleInitializers(Primary); EmitDeferred(); EmitVTablesOpportunistically(); applyGlobalValReplacements(); applyReplacements(); emitMultiVersionFunctions(); - if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition()) - EmitCXXModuleInitFunc(Primary); - else - EmitCXXGlobalInitFunc(); + EmitCXXGlobalInitFunc(); EmitCXXGlobalCleanUpFunc(); registerGlobalDtorsWithAtExit(); EmitCXXThreadLocalInitFunc(); @@ -2504,31 +2491,6 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, } } -void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) { - // Emit the initializers in the order that sub-modules appear in the - // source, first Global Module Fragments, if present. - if (auto GMF = Primary->getGlobalModuleFragment()) { - for (Decl *D : getContext().getModuleInitializers(GMF)) { - assert(D->getKind() == Decl::Var && "GMF initializer decl is not a var?"); - EmitTopLevelDecl(D); - } - } - // Second any associated with the module, itself. - for (Decl *D : getContext().getModuleInitializers(Primary)) { - // Skip import decls, the inits for those are called explicitly. - if (D->getKind() == Decl::Import) - continue; - EmitTopLevelDecl(D); - } - // Third any associated with the Privat eMOdule Fragment, if present. - if (auto PMF = Primary->getPrivateModuleFragment()) { - for (Decl *D : getContext().getModuleInitializers(PMF)) { - assert(D->getKind() == Decl::Var && "PMF initializer decl is not a var?"); - EmitTopLevelDecl(D); - } - } -} - void CodeGenModule::EmitModuleLinkOptions() { // Collect the set of all of the modules we want to visit to emit link // options, which is essentially the imported modules and all of their @@ -2934,19 +2896,12 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // explicitly instantiated, so they should not be emitted eagerly. return false; } - if (const auto *VD = dyn_cast(Global)) { + if (const auto *VD = dyn_cast(Global)) if (Context.getInlineVariableDefinitionKind(VD) == ASTContext::InlineVariableDefinitionKind::WeakUnknown) // A definition of an inline constexpr static data member may change // linkage later if it's redeclared outside the class. return false; - if (CXX20ModuleInits && VD->getOwningModule()) { - // For CXX20, module-owned initializers need to be deferred, since it is - // not known at this point if they will be run for the current module or - // as part of the initializer for an imported one. - return false; - } - } // If OpenMP is enabled and threadprivates must be generated like TLS, delay // codegen for global variables, because they may be marked as threadprivate. if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && @@ -6243,12 +6198,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { DI->EmitImportDecl(*Import); } - // For CXX20 we are done - we will call the module initializer for the - // imported module, and that will likewise call those for any imports it - // has. - if (CXX20ModuleInits) - break; - // Find all of the submodules and emit the module initializers. llvm::SmallPtrSet Visited; SmallVector Stack; diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 94ee5f8..da43b96 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -303,7 +303,7 @@ private: std::unique_ptr ABI; llvm::LLVMContext &VMContext; std::string ModuleNameHash; - bool CXX20ModuleInits = false; + std::unique_ptr TBAA; mutable std::unique_ptr TheTargetCodeGenInfo; @@ -1574,9 +1574,6 @@ private: /// Emit the function that initializes C++ thread_local variables. void EmitCXXThreadLocalInitFunc(); - /// Emit the function that initializes global variables for a C++ Module. - void EmitCXXModuleInitFunc(clang::Module *Primary); - /// Emit the function that initializes C++ globals. void EmitCXXGlobalInitFunc(); @@ -1644,9 +1641,6 @@ private: /// Emit the llvm.used and llvm.compiler.used metadata. void emitLLVMUsed(); - /// For C++20 Itanium ABI, emit the initializers for the module. - void EmitModuleInitializers(clang::Module *Primary); - /// Emit the link options introduced by imported modules. void EmitModuleLinkOptions(); diff --git a/clang/lib/Parse/ParseAST.cpp b/clang/lib/Parse/ParseAST.cpp index 5fca029..04b3f04 100644 --- a/clang/lib/Parse/ParseAST.cpp +++ b/clang/lib/Parse/ParseAST.cpp @@ -172,29 +172,6 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { for (Decl *D : S.WeakTopLevelDecls()) Consumer->HandleTopLevelDecl(DeclGroupRef(D)); - // For C++20 modules, the codegen for module initializers needs to be altered - // and to be able to use a name based on the module name. - - // At this point, we should know if we are building a non-header C++20 module. - if (S.getLangOpts().CPlusPlusModules && !S.getLangOpts().IsHeaderFile && - !S.getLangOpts().CurrentModule.empty()) { - // If we are building the module from source, then the top level module - // will be here. - Module *CodegenModule = S.getCurrentModule(); - bool Interface = true; - if (CodegenModule) - // We only use module initializers for interfaces (including partition - // implementation units). - Interface = S.currentModuleIsInterface(); - else - // If we are building the module from a PCM file, then the module can be - // found here. - CodegenModule = S.getPreprocessor().getCurrentModule(); - // If neither. then .... - assert(CodegenModule && "codegen for a module, but don't know which?"); - if (Interface) - S.getASTContext().setModuleForCodeGen(CodegenModule); - } Consumer->HandleTranslationUnit(S.getASTContext()); // Finalize the template instantiation observer chain. diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index f5c24bd..e9a1ac17 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -344,16 +344,6 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // statements, so imports are allowed. ImportState = ModuleImportState::ImportAllowed; - // For an implementation, We already made an implicit import (its interface). - // Make and return the import decl to be added to the current TU. - if (MDK == ModuleDeclKind::Implementation) { - // Make the import decl for the interface. - ImportDecl *Import = - ImportDecl::Create(Context, CurContext, ModuleLoc, Mod, Path[0].second); - // and return it to be added. - return ConvertDeclToDeclGroup(Import); - } - // FIXME: Create a ModuleDecl. return nullptr; } diff --git a/clang/test/CodeGen/module-intializer-pmf.cpp b/clang/test/CodeGen/module-intializer-pmf.cpp deleted file mode 100644 index 082dda1..0000000 --- a/clang/test/CodeGen/module-intializer-pmf.cpp +++ /dev/null @@ -1,41 +0,0 @@ - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s \ -// RUN: -emit-module-interface -o HasPMF.pcm -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 HasPMF.pcm \ -// RUN: -S -emit-llvm -o - | FileCheck %s - -module; - -struct Glob { - Glob(){}; -}; - -Glob G; - -export module HasPMF; - -export struct InMod { - InMod(){}; -}; - -export InMod IM; - -module :private; - -struct InPMF { - InPMF(){}; -}; - -InPMF P; - -// CHECK: define internal void @__cxx_global_var_init -// CHECK: call void @_ZN4GlobC1Ev -// CHECK: define internal void @__cxx_global_var_init -// CHECK: call void @_ZNW6HasPMF5InPMFC1Ev -// CHECK: define internal void @__cxx_global_var_init -// CHECK: call void @_ZNW6HasPMF5InModC1Ev -// CHECK: define void @_ZGIW6HasPMF -// CHECK: store i8 1, ptr @_ZGIW6HasPMF__in_chrg -// CHECK: call void @__cxx_global_var_init -// CHECK: call void @__cxx_global_var_init -// CHECK: call void @__cxx_global_var_init diff --git a/clang/test/CodeGen/module-intializer.cpp b/clang/test/CodeGen/module-intializer.cpp deleted file mode 100644 index df2f0a5..0000000 --- a/clang/test/CodeGen/module-intializer.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: cd %t - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.cpp \ -// RUN: -emit-module-interface -o N.pcm -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-N - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp \ -// RUN: -emit-module-interface -o O.pcm -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-O - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.cpp \ -// RUN: -emit-module-interface -o M-part.pcm -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.pcm -S \ -// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-P - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.cpp \ -// RUN: -fmodule-file=N.pcm -fmodule-file=O.pcm -fmodule-file=M-part.pcm \ -// RUN: -emit-module-interface -o M.pcm -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.pcm -S -emit-llvm \ -// RUN: -o - | FileCheck %s --check-prefix=CHECK-M - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 useM.cpp \ -// RUN: -fmodule-file=M.pcm -S -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CHECK-USE - -// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-impl.cpp \ -// RUN: -fmodule-file=M.pcm -S -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CHECK-IMPL - -//--- N-h.h - -struct Oink { - Oink(){}; -}; - -Oink Hog; - -//--- N.cpp - -module; -#include "N-h.h" - -export module N; - -export struct Quack { - Quack(){}; -}; - -export Quack Duck; - -// CHECK-N: define internal void @__cxx_global_var_init -// CHECK-N: call void @_ZN4OinkC1Ev -// CHECK-N: define internal void @__cxx_global_var_init -// CHECK-N: call void @_ZNW1N5QuackC1Ev -// CHECK-N: define void @_ZGIW1N -// CHECK-N: store i8 1, ptr @_ZGIW1N__in_chrg -// CHECK-N: call void @__cxx_global_var_init -// CHECK-N: call void @__cxx_global_var_init - -//--- O-h.h - -struct Meow { - Meow(){}; -}; - -Meow Cat; - -//--- O.cpp - -module; -#include "O-h.h" - -export module O; - -export struct Bark { - Bark(){}; -}; - -export Bark Dog; - -// CHECK-O: define internal void @__cxx_global_var_init -// CHECK-O: call void @_ZN4MeowC2Ev -// CHECK-O: define internal void @__cxx_global_var_init -// CHECK-O: call void @_ZNW1O4BarkC1Ev -// CHECK-O: define void @_ZGIW1O -// CHECK-O: store i8 1, ptr @_ZGIW1O__in_chrg -// CHECK-O: call void @__cxx_global_var_init -// CHECK-O: call void @__cxx_global_var_init - -//--- P-h.h - -struct Croak { - Croak(){}; -}; - -Croak Frog; - -//--- M-part.cpp - -module; -#include "P-h.h" - -module M:Part; - -struct Squawk { - Squawk(){}; -}; - -Squawk parrot; - -// CHECK-P: define internal void @__cxx_global_var_init -// CHECK-P: call void @_ZN5CroakC1Ev -// CHECK-P: define internal void @__cxx_global_var_init -// CHECK-P: call void @_ZNW1M6SquawkC1Ev -// CHECK-P: define void @_ZGIW1MWP4Part -// CHECK-P: store i8 1, ptr @_ZGIW1MWP4Part__in_chrg -// CHECK-P: call void @__cxx_global_var_init -// CHECK-P: call void @__cxx_global_var_init - -//--- M-h.h - -struct Moo { - Moo(){}; -}; - -Moo Cow; - -//--- M.cpp - -module; -#include "M-h.h" - -export module M; -import N; -export import O; -import :Part; - -export struct Baa { - int x; - Baa(){}; - Baa(int x) : x(x) {} - int getX() { return x; } -}; - -export Baa Sheep(10); - -// CHECK-M: define internal void @__cxx_global_var_init -// CHECK-M: call void @_ZN3MooC1Ev -// CHECK-M: define internal void @__cxx_global_var_init -// CHECK-M: call void @_ZNW1M3BaaC1Ei -// CHECK-M: declare void @_ZGIW1O() -// CHECK-M: declare void @_ZGIW1N() -// CHECK-M: declare void @_ZGIW1MWP4Part() -// CHECK-M: define void @_ZGIW1M -// CHECK-M: store i8 1, ptr @_ZGIW1M__in_chrg -// CHECK-M: call void @_ZGIW1O() -// CHECK-M: call void @_ZGIW1N() -// CHECK-M: call void @_ZGIW1MWP4Part() -// CHECK-M: call void @__cxx_global_var_init -// CHECK-M: call void @__cxx_global_var_init - -//--- useM.cpp - -import M; - -int main() { - return Sheep.getX(); -} - -// CHECK-USE: declare void @_ZGIW1M -// CHECK-USE: define internal void @_GLOBAL__sub_I_useM.cpp -// CHECK-USE: call void @_ZGIW1M() - -//--- M-impl.cpp - -module M; - -int foo(int i) { return i + 1; } - -// CHECK-IMPL: declare void @_ZGIW1M -// CHECK-IMPL: define internal void @_GLOBAL__sub_I_M_impl.cpp -// CHECK-IMPL: call void @_ZGIW1M() -- 2.7.4