Skip to content

Commit 3e6f407

Browse files
committed
merge main into amd-staging
xfails: * clang/test/CodeGenCXX/modules-vtable.cppm * clang/test/CodeGenCXX/pr70585.cppm cause: llvm#75912 [C++20] [Modules] [Itanium ABI] Generate the vtable in the module unit of dynamic classes Change-Id: I7c502ffc1fe6bc7f98f3a60bc6c7bfe0af52b497
2 parents 103219d + 87aed82 commit 3e6f407

65 files changed

Lines changed: 6895 additions & 339 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

clang/include/clang/AST/DeclBase.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,16 @@ class alignas(8) Decl {
670670
/// Whether this declaration comes from another module unit.
671671
bool isInAnotherModuleUnit() const;
672672

673+
/// Whether this declaration comes from the same module unit being compiled.
674+
bool isInCurrentModuleUnit() const;
675+
676+
/// Whether the definition of the declaration should be emitted in external
677+
/// sources.
678+
bool shouldEmitInExternalSource() const;
679+
680+
/// Whether this declaration comes from a named module;
681+
bool isInNamedModule() const;
682+
673683
/// Whether this declaration comes from explicit global module.
674684
bool isFromExplicitGlobalModule() const;
675685

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,9 @@ enum ASTRecordTypes {
697697

698698
/// Record code for \#pragma clang unsafe_buffer_usage begin/end
699699
PP_UNSAFE_BUFFER_USAGE = 69,
700+
701+
/// Record code for vtables to emit.
702+
VTABLES_TO_EMIT = 70,
700703
};
701704

702705
/// Record types used within a source manager block.

clang/include/clang/Serialization/ASTReader.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,11 @@ class ASTReader
805805
/// the consumer eagerly.
806806
SmallVector<GlobalDeclID, 16> EagerlyDeserializedDecls;
807807

808+
/// The IDs of all vtables to emit. The referenced declarations are passed
809+
/// to the consumers's HandleVTable eagerly after passing
810+
/// EagerlyDeserializedDecls.
811+
SmallVector<GlobalDeclID, 16> VTablesToEmit;
812+
808813
/// The IDs of all tentative definitions stored in the chain.
809814
///
810815
/// Sema keeps track of all tentative definitions in a TU because it has to
@@ -1514,6 +1519,7 @@ class ASTReader
15141519
bool isConsumerInterestedIn(Decl *D);
15151520
void PassInterestingDeclsToConsumer();
15161521
void PassInterestingDeclToConsumer(Decl *D);
1522+
void PassVTableToConsumer(CXXRecordDecl *RD);
15171523

15181524
void finishPendingActions();
15191525
void diagnoseOdrViolations();

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,10 @@ class ASTWriter : public ASTDeserializationListener,
495495
std::vector<SourceRange> NonAffectingRanges;
496496
std::vector<SourceLocation::UIntTy> NonAffectingOffsetAdjustments;
497497

498+
/// A list of classes which need to emit the VTable in the corresponding
499+
/// object file.
500+
llvm::SmallVector<CXXRecordDecl *> PendingEmittingVTables;
501+
498502
/// Computes input files that didn't affect compilation of the current module,
499503
/// and initializes data structures necessary for leaving those files out
500504
/// during \c SourceManager serialization.
@@ -849,6 +853,8 @@ class ASTWriter : public ASTDeserializationListener,
849853

850854
bool getDoneWritingDeclsAndTypes() const { return DoneWritingDeclsAndTypes; }
851855

856+
void handleVTable(CXXRecordDecl *RD);
857+
852858
private:
853859
// ASTDeserializationListener implementation
854860
void ReaderInitialized(ASTReader *Reader) override;
@@ -943,6 +949,7 @@ class PCHGenerator : public SemaConsumer {
943949

944950
void InitializeSema(Sema &S) override { SemaPtr = &S; }
945951
void HandleTranslationUnit(ASTContext &Ctx) override;
952+
void HandleVTable(CXXRecordDecl *RD) override { Writer.handleVTable(RD); }
946953
ASTMutationListener *GetASTMutationListener() override;
947954
ASTDeserializationListener *GetASTDeserializationListener() override;
948955
bool hasEmittedPCH() const { return Buffer->IsComplete; }

clang/lib/AST/Decl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
11901190
return false;
11911191
case Decl::ModuleOwnershipKind::Visible:
11921192
case Decl::ModuleOwnershipKind::VisibleWhenImported:
1193-
return isInNamedModule(D);
1193+
return D->isInNamedModule();
11941194
}
11951195
llvm_unreachable("unexpected module ownership kind");
11961196
}
@@ -1208,7 +1208,7 @@ Linkage NamedDecl::getFormalLinkage() const {
12081208
// [basic.namespace.general]/p2
12091209
// A namespace is never attached to a named module and never has a name with
12101210
// module linkage.
1211-
if (isInNamedModule(this) && InternalLinkage == Linkage::External &&
1211+
if (isInNamedModule() && InternalLinkage == Linkage::External &&
12121212
!isExportedFromModuleInterfaceUnit(
12131213
cast<NamedDecl>(this->getCanonicalDecl())) &&
12141214
!isa<NamespaceDecl>(this))

clang/lib/AST/DeclBase.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,28 @@ bool Decl::isInAnotherModuleUnit() const {
11411141
return M != getASTContext().getCurrentNamedModule();
11421142
}
11431143

1144+
1145+
bool Decl::isInCurrentModuleUnit() const {
1146+
auto *M = getOwningModule();
1147+
1148+
if (!M || !M->isNamedModule())
1149+
return false;
1150+
1151+
return M == getASTContext().getCurrentNamedModule();
1152+
}
1153+
1154+
bool Decl::shouldEmitInExternalSource() const {
1155+
ExternalASTSource *Source = getASTContext().getExternalSource();
1156+
if (!Source)
1157+
return false;
1158+
1159+
return Source->hasExternalDefinitions(this) == ExternalASTSource::EK_Always;
1160+
}
1161+
1162+
bool Decl::isInNamedModule() const {
1163+
return getOwningModule() && getOwningModule()->isNamedModule();
1164+
}
1165+
11441166
bool Decl::isFromExplicitGlobalModule() const {
11451167
return getOwningModule() && getOwningModule()->isExplicitGlobalModule();
11461168
}

clang/lib/Basic/Targets/AArch64.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,18 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
220220
return true;
221221
}
222222

223+
bool AArch64TargetInfo::validateGlobalRegisterVariable(
224+
StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
225+
if ((RegName == "sp") || RegName.starts_with("x")) {
226+
HasSizeMismatch = RegSize != 64;
227+
return true;
228+
} else if (RegName.starts_with("w")) {
229+
HasSizeMismatch = RegSize != 32;
230+
return true;
231+
}
232+
return false;
233+
}
234+
223235
bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
224236
BranchProtectionInfo &BPI,
225237
StringRef &Err) const {

clang/lib/Basic/Targets/AArch64.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
202202
bool hasBitIntType() const override { return true; }
203203

204204
bool validateTarget(DiagnosticsEngine &Diags) const override;
205+
206+
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize,
207+
bool &HasSizeMismatch) const override;
205208
};
206209

207210
class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,11 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
10521052
if (!RD->isExternallyVisible())
10531053
return llvm::GlobalVariable::InternalLinkage;
10541054

1055+
// V-tables for non-template classes with an owning module are always
1056+
// uniquely emitted in that module.
1057+
if (RD->isInNamedModule())
1058+
return llvm::GlobalVariable::ExternalLinkage;
1059+
10551060
// We're at the end of the translation unit, so the current key
10561061
// function is fully correct.
10571062
const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD);
@@ -1186,6 +1191,21 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
11861191
TSK == TSK_ExplicitInstantiationDefinition)
11871192
return false;
11881193

1194+
// Itanium C++ ABI [5.2.3]:
1195+
// Virtual tables for dynamic classes are emitted as follows:
1196+
//
1197+
// - If the class is templated, the tables are emitted in every object that
1198+
// references any of them.
1199+
// - Otherwise, if the class is attached to a module, the tables are uniquely
1200+
// emitted in the object for the module unit in which it is defined.
1201+
// - Otherwise, if the class has a key function (see below), the tables are
1202+
// emitted in the object for the translation unit containing the definition of
1203+
// the key function. This is unique if the key function is not inline.
1204+
// - Otherwise, the tables are emitted in every object that references any of
1205+
// them.
1206+
if (RD->isInNamedModule())
1207+
return RD->shouldEmitInExternalSource();
1208+
11891209
// Otherwise, if the class doesn't have a key function (possibly
11901210
// anymore), the vtable must be defined here.
11911211
const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
@@ -1195,13 +1215,7 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
11951215
const FunctionDecl *Def;
11961216
// Otherwise, if we don't have a definition of the key function, the
11971217
// vtable must be defined somewhere else.
1198-
if (!keyFunction->hasBody(Def))
1199-
return true;
1200-
1201-
assert(Def && "The body of the key function is not assigned to Def?");
1202-
// If the non-inline key function comes from another module unit, the vtable
1203-
// must be defined there.
1204-
return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
1218+
return !keyFunction->hasBody(Def);
12051219
}
12061220

12071221
/// Given that we're currently at the end of the translation unit, and

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,9 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
21302130
if (!canSpeculativelyEmitVTableAsBaseClass(RD))
21312131
return false;
21322132

2133+
if (RD->shouldEmitInExternalSource())
2134+
return false;
2135+
21332136
// For a complete-object vtable (or more specifically, for the VTT), we need
21342137
// to be able to speculatively emit the vtables of all dynamic virtual bases.
21352138
for (const auto &B : RD->vbases()) {

0 commit comments

Comments
 (0)