forked from OSchip/llvm-project
Revert "[C++20][Modules] Build module static initializers per P1874R1."
This reverts commit ac507102d2
.
reverting while we figuere out why one of the green dragon lldb test fails.
This commit is contained in:
parent
e7c8ded6df
commit
b19d3ee712
|
@ -472,9 +472,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
};
|
||||
llvm::DenseMap<Module*, PerModuleInitializers*> 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<Decl*> 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();
|
||||
}
|
||||
|
|
|
@ -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("<global>"); }
|
||||
|
||||
/// 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("<private>"); }
|
||||
|
||||
/// Determine whether the specified module would be visible to
|
||||
/// a lookup at the end of this module.
|
||||
///
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<Module *> 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<llvm::Function *, 8> ModuleInits;
|
||||
for (Module *M : AllImports) {
|
||||
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
|
||||
SmallString<256> FnName;
|
||||
{
|
||||
llvm::raw_svector_ostream Out(FnName);
|
||||
cast<ItaniumMangleContext>(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<llvm::Function *, 8> LocalCXXGlobalInits;
|
||||
llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
|
||||
PrioritizedCXXGlobalInits.end());
|
||||
for (SmallVectorImpl<GlobalInitData>::iterator
|
||||
I = PrioritizedCXXGlobalInits.begin(),
|
||||
E = PrioritizedCXXGlobalInits.end();
|
||||
I != E;) {
|
||||
SmallVectorImpl<GlobalInitData>::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<ItaniumMangleContext>(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<llvm::Function *, 8> 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<ItaniumMangleContext>(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<ItaniumMangleContext>(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);
|
||||
llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
|
||||
FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
|
||||
FI);
|
||||
|
||||
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
|
||||
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() {
|
||||
|
|
|
@ -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<VarDecl>(Global)) {
|
||||
if (const auto *VD = dyn_cast<VarDecl>(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<clang::Module *, 16> Visited;
|
||||
SmallVector<clang::Module *, 16> Stack;
|
||||
|
|
|
@ -303,7 +303,7 @@ private:
|
|||
std::unique_ptr<CGCXXABI> ABI;
|
||||
llvm::LLVMContext &VMContext;
|
||||
std::string ModuleNameHash;
|
||||
bool CXX20ModuleInits = false;
|
||||
|
||||
std::unique_ptr<CodeGenTBAA> TBAA;
|
||||
|
||||
mutable std::unique_ptr<TargetCodeGenInfo> 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();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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()
|
Loading…
Reference in New Issue