Skip to content

Commit a72a703

Browse files
committed
[𝘀𝗽𝗿] changes to main this commit is based on
Created using spr 1.3.6-beta.1 [skip ci]
1 parent 581f755 commit a72a703

Some content is hidden

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

45 files changed

+1094
-29
lines changed

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ CODEGENOPT(EnableNoundefAttrs, 1, 0) ///< Enable emitting `noundef` attributes o
7878
CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
7979
///< pass manager.
8080
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
81+
CODEGENOPT(CallGraphSection, 1, 0) ///< Emit a call graph section into the
82+
///< object file.
8183
CODEGENOPT(EmitCallSiteInfo, 1, 0) ///< Emit call site info only in the case of
8284
///< '-g' + 'O>0' level.
8385
CODEGENOPT(IndirectTlsSegRefs, 1, 0) ///< Set when -mno-tls-direct-seg-refs

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4291,6 +4291,10 @@ defm data_sections : BoolFOption<"data-sections",
42914291
PosFlag<SetTrue, [], [ClangOption, CC1Option],
42924292
"Place each data in its own section">,
42934293
NegFlag<SetFalse>>;
4294+
defm call_graph_section : BoolFOption<"call-graph-section",
4295+
CodeGenOpts<"CallGraphSection">, DefaultFalse,
4296+
PosFlag<SetTrue, [], [CC1Option], "Emit a call graph section">,
4297+
NegFlag<SetFalse>>;
42944298
defm stack_size_section : BoolFOption<"stack-size-section",
42954299
CodeGenOpts<"StackSizeSection">, DefaultFalse,
42964300
PosFlag<SetTrue, [], [ClangOption, CC1Option],

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
455455
Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
456456
Options.EmitAddrsig = CodeGenOpts.Addrsig;
457457
Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
458+
Options.EmitCallGraphSection = CodeGenOpts.CallGraphSection;
458459
Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
459460
Options.EnableAIXExtendedAltivecABI = LangOpts.EnableAIXExtendedAltivecABI;
460461
Options.XRayFunctionIndex = CodeGenOpts.XRayFunctionIndex;

clang/lib/CodeGen/CGCall.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "clang/AST/Decl.h"
2626
#include "clang/AST/DeclCXX.h"
2727
#include "clang/AST/DeclObjC.h"
28+
#include "clang/AST/Type.h"
2829
#include "clang/Basic/CodeGenOptions.h"
2930
#include "clang/Basic/TargetInfo.h"
3031
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -37,6 +38,7 @@
3738
#include "llvm/IR/CallingConv.h"
3839
#include "llvm/IR/DataLayout.h"
3940
#include "llvm/IR/InlineAsm.h"
41+
#include "llvm/IR/Instruction.h"
4042
#include "llvm/IR/IntrinsicInst.h"
4143
#include "llvm/IR/Intrinsics.h"
4244
#include "llvm/IR/Type.h"
@@ -5077,6 +5079,11 @@ static unsigned getMaxVectorWidth(const llvm::Type *Ty) {
50775079
return MaxVectorWidth;
50785080
}
50795081

5082+
static bool isCXXDeclType(const FunctionDecl *FD) {
5083+
return isa<CXXConstructorDecl>(FD) || isa<CXXMethodDecl>(FD) ||
5084+
isa<CXXDestructorDecl>(FD);
5085+
}
5086+
50805087
RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
50815088
const CGCallee &Callee,
50825089
ReturnValueSlot ReturnValue,
@@ -5765,6 +5772,25 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
57655772
AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs);
57665773
Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
57675774

5775+
if (CGM.getCodeGenOpts().CallGraphSection) {
5776+
assert((TargetDecl && TargetDecl->getFunctionType() ||
5777+
Callee.getAbstractInfo().getCalleeFunctionProtoType()) &&
5778+
"cannot find callsite type");
5779+
QualType CST;
5780+
if (TargetDecl && TargetDecl->getFunctionType())
5781+
CST = QualType(TargetDecl->getFunctionType(), 0);
5782+
else if (const auto *FPT =
5783+
Callee.getAbstractInfo().getCalleeFunctionProtoType())
5784+
CST = QualType(FPT, 0);
5785+
5786+
if (!CST.isNull()) {
5787+
auto *TypeIdMD = CGM.CreateMetadataIdentifierGeneralized(CST);
5788+
auto *TypeIdMDVal =
5789+
llvm::MetadataAsValue::get(getLLVMContext(), TypeIdMD);
5790+
BundleList.emplace_back("type", TypeIdMDVal);
5791+
}
5792+
}
5793+
57685794
// Emit the actual call/invoke instruction.
57695795
llvm::CallBase *CI;
57705796
if (!InvokeDest) {
@@ -5779,8 +5805,18 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
57795805
CI->getCalledFunction()->getName().starts_with("_Z4sqrt")) {
57805806
SetSqrtFPAccuracy(CI);
57815807
}
5782-
if (callOrInvoke)
5808+
if (callOrInvoke) {
57835809
*callOrInvoke = CI;
5810+
if (CGM.getCodeGenOpts().CallGraphSection) {
5811+
// Set type identifier metadata of indirect calls for call graph section.
5812+
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
5813+
// Type id metadata is set only for C/C++ contexts.
5814+
if (isCXXDeclType(FD)) {
5815+
CGM.CreateFunctionTypeMetadataForIcall(FD->getType(), *callOrInvoke);
5816+
}
5817+
}
5818+
}
5819+
}
57845820

57855821
// If this is within a function that has the guard(nocf) attribute and is an
57865822
// indirect call, add the "guard_nocf" attribute to this call to indicate that

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6172,7 +6172,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
61726172
}
61736173
if (CallOrInvoke)
61746174
*CallOrInvoke = LocalCallOrInvoke;
6175-
61766175
return Call;
61776176
}
61786177

clang/lib/CodeGen/CGObjCMac.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,9 +2214,8 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
22142214

22152215
llvm::CallBase *CallSite;
22162216
CGCallee Callee = CGCallee::forDirect(BitcastFn);
2217-
RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2218-
&CallSite);
2219-
2217+
RValue rvalue =
2218+
CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite);
22202219
// Mark the call as noreturn if the method is marked noreturn and the
22212220
// receiver cannot be null.
22222221
if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2622,8 +2622,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
26222622

26232623
// In the cross-dso CFI mode with canonical jump tables, we want !type
26242624
// attributes on definitions only.
2625-
if (CodeGenOpts.SanitizeCfiCrossDso &&
2626-
CodeGenOpts.SanitizeCfiCanonicalJumpTables) {
2625+
if ((CodeGenOpts.SanitizeCfiCrossDso &&
2626+
CodeGenOpts.SanitizeCfiCanonicalJumpTables) ||
2627+
CodeGenOpts.CallGraphSection) {
26272628
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
26282629
// Skip available_externally functions. They won't be codegen'ed in the
26292630
// current module anyway.
@@ -2813,7 +2814,17 @@ static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) {
28132814

28142815
void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
28152816
llvm::Function *F) {
2816-
// Only if we are checking indirect calls.
2817+
bool EmittedMDIdGeneralized = false;
2818+
if (CodeGenOpts.CallGraphSection &&
2819+
(!F->hasLocalLinkage() ||
2820+
F->getFunction().hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
2821+
/*IgnoreAssumeLikeCalls=*/true,
2822+
/*IgnoreLLVMUsed=*/false))) {
2823+
F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
2824+
EmittedMDIdGeneralized = true;
2825+
}
2826+
2827+
// Add additional metadata only if we are checking indirect calls with CFI.
28172828
if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
28182829
return;
28192830

@@ -2824,14 +2835,27 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
28242835

28252836
llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
28262837
F->addTypeMetadata(0, MD);
2827-
F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
2838+
// Add the generalized identifier if not added already.
2839+
if (!EmittedMDIdGeneralized)
2840+
F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));
28282841

28292842
// Emit a hash-based bit set entry for cross-DSO calls.
28302843
if (CodeGenOpts.SanitizeCfiCrossDso)
28312844
if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD))
28322845
F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId));
28332846
}
28342847

2848+
void CodeGenModule::CreateFunctionTypeMetadataForIcall(const QualType &QT,
2849+
llvm::CallBase *CB) {
2850+
// Only if needed for call graph section and only for indirect calls.
2851+
if (!CodeGenOpts.CallGraphSection || !CB || !CB->isIndirectCall())
2852+
return;
2853+
2854+
auto *MD = CreateMetadataIdentifierGeneralized(QT);
2855+
auto *MDN = llvm::MDNode::get(getLLVMContext(), MD);
2856+
CB->setMetadata(llvm::LLVMContext::MD_type, MDN);
2857+
}
2858+
28352859
void CodeGenModule::setKCFIType(const FunctionDecl *FD, llvm::Function *F) {
28362860
llvm::LLVMContext &Ctx = F->getContext();
28372861
llvm::MDBuilder MDB(Ctx);
@@ -2959,7 +2983,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
29592983
// are non-canonical then we need type metadata in order to produce the local
29602984
// jump table.
29612985
if (!CodeGenOpts.SanitizeCfiCrossDso ||
2962-
!CodeGenOpts.SanitizeCfiCanonicalJumpTables)
2986+
!CodeGenOpts.SanitizeCfiCanonicalJumpTables ||
2987+
CodeGenOpts.CallGraphSection)
29632988
CreateFunctionTypeMetadataForIcall(FD, F);
29642989

29652990
if (LangOpts.Sanitize.has(SanitizerKind::KCFI))

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,10 @@ class CodeGenModule : public CodeGenTypeCache {
15721572
void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
15731573
llvm::Function *F);
15741574

1575+
/// Create and attach type metadata to the given call.
1576+
void CreateFunctionTypeMetadataForIcall(const QualType &QT,
1577+
llvm::CallBase *CB);
1578+
15751579
/// Set type metadata to the given function.
15761580
void setKCFIType(const FunctionDecl *FD, llvm::Function *F);
15771581

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6609,6 +6609,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
66096609
CmdArgs.push_back(A->getValue());
66106610
}
66116611

6612+
if (Args.hasFlag(options::OPT_fcall_graph_section,
6613+
options::OPT_fno_call_graph_section, false))
6614+
CmdArgs.push_back("-fcall-graph-section");
6615+
66126616
Args.addOptInFlag(CmdArgs, options::OPT_fstack_size_section,
66136617
options::OPT_fno_stack_size_section);
66146618

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Tests that we assign appropriate identifiers to indirect calls and targets
2+
// specifically for C++ class and instance methods.
3+
4+
// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section \
5+
// RUN: -emit-llvm -o %t %s
6+
// RUN: FileCheck --check-prefix=FT %s < %t
7+
// RUN: FileCheck --check-prefix=CST %s < %t
8+
9+
////////////////////////////////////////////////////////////////////////////////
10+
// Class definitions (check for indirect target metadata)
11+
12+
class Cls1 {
13+
public:
14+
// FT-DAG: define {{.*}} ptr @_ZN4Cls18receiverEPcPf({{.*}} !type [[F_TCLS1RECEIVER:![0-9]+]]
15+
static int *receiver(char *a, float *b) { return 0; }
16+
};
17+
18+
class Cls2 {
19+
public:
20+
int *(*fp)(char *, float *);
21+
22+
// FT-DAG: define {{.*}} i32 @_ZN4Cls22f1Ecfd({{.*}} !type [[F_TCLS2F1:![0-9]+]]
23+
int f1(char a, float b, double c) { return 0; }
24+
25+
// FT-DAG: define {{.*}} ptr @_ZN4Cls22f2EPcPfPd({{.*}} !type [[F_TCLS2F2:![0-9]+]]
26+
int *f2(char *a, float *b, double *c) { return 0; }
27+
28+
// FT-DAG: define {{.*}} void @_ZN4Cls22f3E4Cls1({{.*}} !type [[F_TCLS2F3F4:![0-9]+]]
29+
void f3(Cls1 a) {}
30+
31+
// FT-DAG: define {{.*}} void @_ZN4Cls22f4E4Cls1({{.*}} !type [[F_TCLS2F3F4]]
32+
void f4(const Cls1 a) {}
33+
34+
// FT-DAG: define {{.*}} void @_ZN4Cls22f5EP4Cls1({{.*}} !type [[F_TCLS2F5:![0-9]+]]
35+
void f5(Cls1 *a) {}
36+
37+
// FT-DAG: define {{.*}} void @_ZN4Cls22f6EPK4Cls1({{.*}} !type [[F_TCLS2F6:![0-9]+]]
38+
void f6(const Cls1 *a) {}
39+
40+
// FT-DAG: define {{.*}} void @_ZN4Cls22f7ER4Cls1({{.*}} !type [[F_TCLS2F7:![0-9]+]]
41+
void f7(Cls1 &a) {}
42+
43+
// FT-DAG: define {{.*}} void @_ZN4Cls22f8ERK4Cls1({{.*}} !type [[F_TCLS2F8:![0-9]+]]
44+
void f8(const Cls1 &a) {}
45+
46+
// FT-DAG: define {{.*}} void @_ZNK4Cls22f9Ev({{.*}} !type [[F_TCLS2F9:![0-9]+]]
47+
void f9() const {}
48+
};
49+
50+
// FT-DAG: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPvS_S_E.generalized"}
51+
// FT-DAG: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"}
52+
// FT-DAG: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFicfdE.generalized"}
53+
// FT-DAG: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"}
54+
// FT-DAG: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvPvE.generalized"}
55+
// FT-DAG: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvPKvE.generalized"}
56+
// FT-DAG: [[F_TCLS2F7]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"}
57+
// FT-DAG: [[F_TCLS2F8]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"}
58+
// FT-DAG: [[F_TCLS2F9]] = !{i64 0, !"_ZTSKFvvE.generalized"}
59+
60+
////////////////////////////////////////////////////////////////////////////////
61+
// Callsites (check for indirect callsite operand bundles)
62+
63+
// CST-LABEL: define {{.*}} @_Z3foov
64+
void foo() {
65+
Cls2 ObjCls2;
66+
ObjCls2.fp = &Cls1::receiver;
67+
68+
// CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPvS_S_E.generalized") ]
69+
ObjCls2.fp(0, 0);
70+
71+
auto fp_f1 = &Cls2::f1;
72+
auto fp_f2 = &Cls2::f2;
73+
auto fp_f3 = &Cls2::f3;
74+
auto fp_f4 = &Cls2::f4;
75+
auto fp_f5 = &Cls2::f5;
76+
auto fp_f6 = &Cls2::f6;
77+
auto fp_f7 = &Cls2::f7;
78+
auto fp_f8 = &Cls2::f8;
79+
auto fp_f9 = &Cls2::f9;
80+
81+
Cls2 *ObjCls2Ptr = &ObjCls2;
82+
Cls1 Cls1Param;
83+
84+
// CST: call noundef i32 %{{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ]
85+
(ObjCls2Ptr->*fp_f1)(0, 0, 0);
86+
87+
// CST: call noundef ptr %{{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ]
88+
(ObjCls2Ptr->*fp_f2)(0, 0, 0);
89+
90+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
91+
(ObjCls2Ptr->*fp_f3)(Cls1Param);
92+
93+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ]
94+
(ObjCls2Ptr->*fp_f4)(Cls1Param);
95+
96+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ]
97+
(ObjCls2Ptr->*fp_f5)(&Cls1Param);
98+
99+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ]
100+
(ObjCls2Ptr->*fp_f6)(&Cls1Param);
101+
102+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ]
103+
(ObjCls2Ptr->*fp_f7)(Cls1Param);
104+
105+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ]
106+
(ObjCls2Ptr->*fp_f8)(Cls1Param);
107+
108+
// CST: call void %{{.*}} [ "type"(metadata !"_ZTSKFvvE.generalized") ]
109+
(ObjCls2Ptr->*fp_f9)();
110+
}

0 commit comments

Comments
 (0)