Fix callee type generation (#186272)
The callee_type metadata is expected to be a list of generalized type metadata by the IR verifier. But for indirect calls with internal linkage the type metadata is just an integer. Avoid including them in callee_type metadata. This will reduce the precision of the generated call graph as the edges to internal linkage functions whose address were taken will not be present anymore. We need to handle this in the future.
This commit is contained in:
parent
7449009719
commit
60669c1cfe
@ -3267,8 +3267,12 @@ void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD,
|
||||
|
||||
void CodeGenModule::createCalleeTypeMetadataForIcall(const QualType &QT,
|
||||
llvm::CallBase *CB) {
|
||||
// Only if needed for call graph section and only for indirect calls.
|
||||
if (!CodeGenOpts.CallGraphSection || !CB->isIndirectCall())
|
||||
// Only if needed for call graph section and only for indirect calls that are
|
||||
// visible externally.
|
||||
// TODO: Handle local linkage symbols so they are not left out of call graph
|
||||
// reducing precision.
|
||||
if (!CodeGenOpts.CallGraphSection || !CB->isIndirectCall() ||
|
||||
!isExternallyVisible(QT->getLinkage()))
|
||||
return;
|
||||
|
||||
llvm::Metadata *TypeIdMD = CreateMetadataIdentifierGeneralized(QT);
|
||||
|
||||
37
clang/test/CodeGen/call-graph-section-internal.cpp
Normal file
37
clang/test/CodeGen/call-graph-section-internal.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux -fexperimental-call-graph-section -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
// Check that we do not generate callee_type metadata for indirect calls
|
||||
// to functions with internal linkage (e.g., types in anonymous namespaces),
|
||||
// as their type metadata identifiers are distinct MDNodes instead of
|
||||
// generalized strings, which would fail the LLVM Verifier.
|
||||
|
||||
namespace {
|
||||
class a;
|
||||
class b {
|
||||
public:
|
||||
virtual void c(a);
|
||||
};
|
||||
class a {
|
||||
public:
|
||||
b &e;
|
||||
void d() { e.c(*this); }
|
||||
};
|
||||
|
||||
void b::c(a) {}
|
||||
|
||||
void f() {
|
||||
a *g = nullptr;
|
||||
g->d();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void test() {
|
||||
f();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} void @{{.*}}1a1dEv
|
||||
// CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %{{.*}}, i{{[0-9]+}} 0
|
||||
// CHECK: %[[FP:.*]] = load ptr, ptr %[[VFN]], align {{[0-9]+}}
|
||||
// CHECK: call void %[[FP]]({{.*}})
|
||||
// CHECK-NOT: !callee_type
|
||||
// CHECK: ret void
|
||||
Loading…
x
Reference in New Issue
Block a user