[CIR] Handle explicit instantiation declaration in getVTableLinkage#193809
[CIR] Handle explicit instantiation declaration in getVTableLinkage#193809AbdallahRashed wants to merge 1 commit intollvm:mainfrom
Conversation
Replace errorNYI for TSK_ExplicitInstantiationDeclaration with the correct linkage logic: use discardable ODR linkage for MSVC, and for Itanium choose between AvailableExternallyLinkage (when the vtable can be speculatively emitted) or ExternalLinkage. Fixes point 3 of llvm#192330.
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: AbdallahRashed (AbdallahRashed) ChangesReplace errorNYI for TSK_ExplicitInstantiationDeclaration with the correct linkage logic: use discardable ODR linkage for MSVC, and for Itanium choose between AvailableExternallyLinkage (when the vtable can be speculatively emitted) or ExternalLinkage. Fixes point 3 of #192330. Full diff: https://github.com/llvm/llvm-project/pull/193809.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index 6e1a80926f679..ca83d7a355408 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -326,6 +326,9 @@ cir::GlobalOp CIRGenVTables::generateConstructionVTable(
return vtable;
}
+static bool shouldEmitAvailableExternallyVTable(const CIRGenModule &cgm,
+ const CXXRecordDecl *rd);
+
/// Compute the required linkage of the vtable for the given class.
///
/// Note that we only call this at the end of the translation unit.
@@ -395,11 +398,14 @@ cir::GlobalLinkageKind CIRGenModule::getVTableLinkage(const CXXRecordDecl *rd) {
case TSK_ImplicitInstantiation:
return discardableODRLinkage;
- case TSK_ExplicitInstantiationDeclaration: {
- errorNYI(rd->getSourceRange(),
- "getVTableLinkage: explicit instantiation declaration");
- return cir::GlobalLinkageKind::ExternalLinkage;
- }
+ case TSK_ExplicitInstantiationDeclaration:
+ // Explicit instantiations in MSVC do not provide vtables, so we must emit
+ // our own.
+ if (getTarget().getCXXABI().isMicrosoft())
+ return discardableODRLinkage;
+ return shouldEmitAvailableExternallyVTable(*this, rd)
+ ? cir::GlobalLinkageKind::AvailableExternallyLinkage
+ : cir::GlobalLinkageKind::ExternalLinkage;
case TSK_ExplicitInstantiationDefinition:
return nonDiscardableODRLinkage;
diff --git a/clang/test/CIR/CodeGen/vtable-linkage-explicit-instantiation.cpp b/clang/test/CIR/CodeGen/vtable-linkage-explicit-instantiation.cpp
new file mode 100644
index 0000000000000..6fc4cc4d51fbf
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vtable-linkage-explicit-instantiation.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+
+// Test that explicit instantiation declarations don't trigger
+// "getVTableLinkage: explicit instantiation declaration" errorNYI.
+
+template <typename T>
+struct Base {
+ virtual ~Base() {}
+ virtual void foo() {}
+ T val;
+};
+
+extern template class Base<int>;
+
+void use(Base<int> *p) {
+ p->foo();
+}
+
+// Verify the virtual call goes through the vtable.
+// CHECK: cir.func {{.*}} @_Z3useP4BaseIiE
+// CHECK: cir.vtable.get_vptr
+// CHECK: cir.vtable.get_virtual_fn_addr
+
+// LLVM: define {{.*}} @_Z3useP4BaseIiE
|
| "getVTableLinkage: explicit instantiation declaration"); | ||
| return cir::GlobalLinkageKind::ExternalLinkage; | ||
| } | ||
| case TSK_ExplicitInstantiationDeclaration: |
There was a problem hiding this comment.
The llvm_unreachable on line 375 relates to this same kind. It shouldn't be unreachable. That isn't implemented in the incubator, but it is in classic codegen (doing basically what you have here). Can you add that in this PR also. It will require an additional test case to reach that code.
| // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll | ||
| // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s | ||
|
|
||
| // Test that explicit instantiation declarations don't trigger |
There was a problem hiding this comment.
This comment isn't useful. I'd delete it.
| @@ -0,0 +1,27 @@ | |||
| // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir | |||
| // RUN: FileCheck --input-file=%t.cir %s | |||
| // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll | |||
There was a problem hiding this comment.
Can you also add RUN lines to compile without -fclangir? This is useful for verifying that we do the same thing as classic codegen.
Replace errorNYI for TSK_ExplicitInstantiationDeclaration with the correct linkage logic: use discardable ODR linkage for MSVC, and for Itanium choose between AvailableExternallyLinkage (when the vtable can be speculatively emitted) or ExternalLinkage.
Fixes point 3 of #192330.