necipfazil created this revision. Herald added subscribers: dexonsmith, hiraditya. necipfazil requested review of this revision. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
Create and add generalized type identifier metadata to indirect calls, and to functions that may be target to indirect calls. To avoid metadata loss, indirect callsite type identifier metadata are carried with operand bundles. Type identifiers will be used by the back-end to construct the call graph section to precisely represent the possible targets for indirect calls. The type information is deliberately pulled from the front-end to have extra precision since some type information is lost at IR, and to ensure consistent type identifiers between object files compiled at different times (as C/C++ standards require language-level types to match). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D106172 Files: clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/call-graph-section-1.cpp clang/test/CodeGen/call-graph-section-2.cpp clang/test/CodeGen/call-graph-section-3.cpp clang/test/CodeGen/call-graph-section.c llvm/include/llvm/IR/LLVMContext.h llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2877,7 +2877,7 @@ {LLVMContext::OB_deopt, LLVMContext::OB_gc_transition, LLVMContext::OB_gc_live, LLVMContext::OB_funclet, LLVMContext::OB_cfguardtarget, - LLVMContext::OB_clang_arc_attachedcall}) && + LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_type}) && "Cannot lower invokes with arbitrary operand bundles yet!"); const Value *Callee(I.getCalledOperand()); @@ -2960,8 +2960,9 @@ // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't // have to do anything here to lower funclet bundles. - assert(!I.hasOperandBundlesOtherThan( - {LLVMContext::OB_deopt, LLVMContext::OB_funclet}) && + assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt, + LLVMContext::OB_funclet, + LLVMContext::OB_type}) && "Cannot lower callbrs with arbitrary operand bundles yet!"); assert(I.isInlineAsm() && "Only know how to handle inlineasm callbr"); @@ -8086,7 +8087,7 @@ assert(!I.hasOperandBundlesOtherThan( {LLVMContext::OB_deopt, LLVMContext::OB_funclet, LLVMContext::OB_cfguardtarget, LLVMContext::OB_preallocated, - LLVMContext::OB_clang_arc_attachedcall}) && + LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_type}) && "Cannot lower calls with arbitrary operand bundles!"); SDValue Callee = getValue(I.getCalledOperand()); Index: llvm/include/llvm/IR/LLVMContext.h =================================================================== --- llvm/include/llvm/IR/LLVMContext.h +++ llvm/include/llvm/IR/LLVMContext.h @@ -94,6 +94,7 @@ OB_preallocated = 4, // "preallocated" OB_gc_live = 5, // "gc-live" OB_clang_arc_attachedcall = 6, // "clang.arc.attachedcall" + OB_type = 7, // "type" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. Index: clang/test/CodeGen/call-graph-section.c =================================================================== --- /dev/null +++ clang/test/CodeGen/call-graph-section.c @@ -0,0 +1,85 @@ +// Tests that we assign appropriate identifiers to indirect calls and targets. + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \ +// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,ITANIUM %s + +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fcall-graph-section -S \ +// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s + +// CHECK-DAG: define {{(dso_local)?}} void @foo({{.*}} !type [[F_TVOID:![0-9]+]] +void foo() { +} + +// CHECK-DAG: define {{(dso_local)?}} void @bar({{.*}} !type [[F_TVOID]] +void bar() { + void (*fp)() = foo; + // ITANIUM: call {{.*}} [ "type"(metadata !"_ZTSFvE.generalized") ] + // MS: call {{.*}} [ "type"(metadata !"?6AX@Z.generalized") ] + fp(); +} + +// CHECK-DAG: define {{(dso_local)?}} i32 @baz({{.*}} !type [[F_TPRIMITIVE:![0-9]+]] +int baz(char a, float b, double c) { + return 1; +} + +// CHECK-DAG: define {{(dso_local)?}} i32* @qux({{.*}} !type [[F_TPTR:![0-9]+]] +int *qux(char *a, float *b, double *c) { + return 0; +} + +// CHECK-DAG: define {{(dso_local)?}} void @corge({{.*}} !type [[F_TVOID]] +void corge() { + int (*fp_baz)(char, float, double) = baz; + // ITANIUM: call i32 {{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ] + // MS: call i32 {{.*}} [ "type"(metadata !"?6AHDMN@Z.generalized") ] + fp_baz('a', .0f, .0); + + int *(*fp_qux)(char *, float *, double *) = qux; + // ITANIUM: call i32* {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ] + // MS: call i32* {{.*}} [ "type"(metadata !"?6APEAXPEAX00@Z.generalized") ] + fp_qux(0, 0, 0); +} + +struct st1 { + int *(*fp)(char *, float *, double *); +}; + +struct st2 { + struct st1 m; +}; + +// CHECK-DAG: define {{(dso_local)?}} void @stparam({{.*}} !type [[F_TSTRUCT:![0-9]+]] +void stparam(struct st2 a, struct st2 *b) {} + +// CHECK-DAG: define {{(dso_local)?}} void @stf({{.*}} !type [[F_TVOID]] +void stf() { + struct st1 St1; + St1.fp = qux; + // ITANIUM: call i32* {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ] + // MS: call i32* {{.*}} [ "type"(metadata !"?6APEAXPEAX00@Z.generalized") ] + St1.fp(0, 0, 0); + + struct st2 St2; + St2.m.fp = qux; + // ITANIUM: call i32* {{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ] + // MS: call i32* {{.*}} [ "type"(metadata !"?6APEAXPEAX00@Z.generalized") ] + St2.m.fp(0, 0, 0); + + // ITANIUM: call void {{.*}} [ "type"(metadata !"_ZTSFv3st2PvE.generalized") ] + // MS: call void {{.*}} [ "type"(metadata !"?6AXUst2@@PEAX@Z.generalized") ] + void (*fp_stparam)(struct st2, struct st2 *) = stparam; + fp_stparam(St2, &St2); +} + +// ITANIUM-DAG: [[F_TVOID]] = !{i64 0, !"_ZTSFvE.generalized"} +// MS-DAG: [[F_TVOID]] = !{i64 0, !"?6AX@Z.generalized"} + +// ITANIUM-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"} +// MS-DAG: [[F_TPRIMITIVE]] = !{i64 0, !"?6AHDMN@Z.generalized"} + +// ITANIUM-DAG: [[F_TPTR]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"} +// MS-DAG: [[F_TPTR]] = !{i64 0, !"?6APEAXPEAX00@Z.generalized"} + +// ITANIUM-DAG: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PvE.generalized"} +// MS-DAG: [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAX@Z.generalized"} Index: clang/test/CodeGen/call-graph-section-3.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/call-graph-section-3.cpp @@ -0,0 +1,52 @@ +// Tests that we assign appropriate identifiers to indirect calls and targets +// specifically for virtual methods. + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \ +// RUN: -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix=FT %s < %t +// RUN: FileCheck --check-prefix=CST %s < %t + +//////////////////////////////////////////////////////////////////////////////// +// Class definitions (check for indirect target metadata) + +class Base { +public: + // FT-DAG: define {{.*}} @_ZN4Base2vfEPc({{.*}} !type [[F_TVF:![0-9]+]] + virtual int vf(char *a) { return 0; }; +}; + +class Derived : public Base { +public: + // FT-DAG: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !type [[F_TVF]] + int vf(char *a) override { return 1; }; +}; + +// FT-DAG: [[F_TVF]] = !{i64 0, !"_ZTSFiPvE.generalized"} + +//////////////////////////////////////////////////////////////////////////////// +// Callsites (check for indirect callsite operand bundles) + +// CST-LABEL: define {{.*}} @_Z3foov +void foo() { + auto B = Base(); + auto D = Derived(); + + Base *Bptr = &B; + Base *BptrToD = &D; + Derived *Dptr = &D; + + auto FpBaseVf = &Base::vf; + auto FpDerivedVf = &Derived::vf; + + // CST: call i32 %{{.*}}(%class.Base* {{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ] + (Bptr->*FpBaseVf)(0); + + // CST: call i32 %{{.*}}(%class.Base* {{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ] + (BptrToD->*FpBaseVf)(0); + + // CST: call i32 %{{.*}}(%class.Base* {{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ] + (Dptr->*FpBaseVf)(0); + + // CST: call i32 %{{.*}}(%class.Derived* {{.*}} [ "type"(metadata !"_ZTSFiPvE.generalized") ] + (Dptr->*FpDerivedVf)(0); +} Index: clang/test/CodeGen/call-graph-section-2.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/call-graph-section-2.cpp @@ -0,0 +1,95 @@ +// Tests that we assign appropriate identifiers to indirect calls and targets +// specifically for C++ templates. + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \ +// RUN: -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix=FT %s < %t +// RUN: FileCheck --check-prefix=CST %s < %t +// RUN: FileCheck --check-prefix=CHECK %s < %t + +//////////////////////////////////////////////////////////////////////////////// +// Class definitions and template classes (check for indirect target metadata) + +class Cls1 {}; + +// Cls2 is instantiated with T=Cls1 in foo(). Following checks are for this +// instantiation. +template <class T> +class Cls2 { +public: + // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f1Ev({{.*}} !type [[F_TCLS2F1:![0-9]+]] + void f1() {} + + // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f2ES0_({{.*}} !type [[F_TCLS2F2:![0-9]+]] + void f2(T a) {} + + // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f3EPS0_({{.*}} !type [[F_TCLS2F3:![0-9]+]] + void f3(T *a) {} + + // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f4EPKS0_({{.*}} !type [[F_TCLS2F4:![0-9]+]] + void f4(const T *a) {} + + // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f5ERS0_({{.*}} !type [[F_TCLS2F5:![0-9]+]] + void f5(T &a) {} + + // FT: define {{.*}} void @_ZN4Cls2I4Cls1E2f6ERKS0_({{.*}} !type [[F_TCLS2F6:![0-9]+]] + void f6(const T &a) {} + + // Mixed type function pointer member + T *(*fp)(T a, T *b, const T *c, T &d, const T &e); +}; + +// FT-DAG: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"} +// FT-DAG: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"} +// FT-DAG: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvPvE.generalized"} +// FT-DAG: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPKvE.generalized"} +// FT-DAG: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"} +// FT-DAG: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"} + +//////////////////////////////////////////////////////////////////////////////// +// Callsites (check for indirect callsite operand bundles) + +template <class T> +T *T_func(T a, T *b, const T *c, T &d, const T &e) { return b; } + +// CST-LABEL: define {{.*}} @_Z3foov +void foo() { + // Methods for Cls2<Cls1> is checked above within the template description. + Cls2<Cls1> Obj; + + // CHECK-DAG: define {{.*}} @_Z6T_funcI4Cls1EPT_S1_S2_PKS1_RS1_RS3_({{.*}} !type [[F_TFUNC_CLS1:![0-9]+]] + // CHECK-DAG: [[F_TFUNC_CLS1]] = !{i64 0, !"_ZTSFPv4Cls1S_PKvRS0_RKS0_E.generalized"} + Obj.fp = T_func<Cls1>; + Cls1 Cls1Obj; + + // CST: call %class.Cls1* {{.*}} [ "type"(metadata !"_ZTSFPv4Cls1S_PKvRS0_RKS0_E.generalized") ] + Obj.fp(Cls1Obj, &Cls1Obj, &Cls1Obj, Cls1Obj, Cls1Obj); + + // Make indirect calls to Cls2's member methods + auto fp_f1 = &Cls2<Cls1>::f1; + auto fp_f2 = &Cls2<Cls1>::f2; + auto fp_f3 = &Cls2<Cls1>::f3; + auto fp_f4 = &Cls2<Cls1>::f4; + auto fp_f5 = &Cls2<Cls1>::f5; + auto fp_f6 = &Cls2<Cls1>::f6; + + auto *Obj2Ptr = &Obj; + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvvE.generalized") ] + (Obj2Ptr->*fp_f1)(); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ] + (Obj2Ptr->*fp_f2)(Cls1Obj); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ] + (Obj2Ptr->*fp_f3)(&Cls1Obj); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ] + (Obj2Ptr->*fp_f4)(&Cls1Obj); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ] + (Obj2Ptr->*fp_f5)(Cls1Obj); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ] + (Obj2Ptr->*fp_f6)(Cls1Obj); +} Index: clang/test/CodeGen/call-graph-section-1.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/call-graph-section-1.cpp @@ -0,0 +1,110 @@ +// Tests that we assign appropriate identifiers to indirect calls and targets +// specifically for C++ class and instance methods. + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fcall-graph-section -S \ +// RUN: -emit-llvm -o %t %s +// RUN: FileCheck --check-prefix=FT %s < %t +// RUN: FileCheck --check-prefix=CST %s < %t + +//////////////////////////////////////////////////////////////////////////////// +// Class definitions (check for indirect target metadata) + +class Cls1 { +public: + // FT-DAG: define {{.*}} i32* @_ZN4Cls18receiverEPcPf({{.*}} !type [[F_TCLS1RECEIVER:![0-9]+]] + static int *receiver(char *a, float *b) { return 0; } +}; + +class Cls2 { +public: + int *(*fp)(char *, float *); + + // FT-DAG: define {{.*}} i32 @_ZN4Cls22f1Ecfd({{.*}} !type [[F_TCLS2F1:![0-9]+]] + int f1(char a, float b, double c) { return 0; } + + // FT-DAG: define {{.*}} i32* @_ZN4Cls22f2EPcPfPd({{.*}} !type [[F_TCLS2F2:![0-9]+]] + int *f2(char *a, float *b, double *c) { return 0; } + + // FT-DAG: define {{.*}} void @_ZN4Cls22f3E4Cls1({{.*}} !type [[F_TCLS2F3F4:![0-9]+]] + void f3(Cls1 a) {} + + // FT-DAG: define {{.*}} void @_ZN4Cls22f4E4Cls1({{.*}} !type [[F_TCLS2F3F4]] + void f4(const Cls1 a) {} + + // FT-DAG: define {{.*}} void @_ZN4Cls22f5EP4Cls1({{.*}} !type [[F_TCLS2F5:![0-9]+]] + void f5(Cls1 *a) {} + + // FT-DAG: define {{.*}} void @_ZN4Cls22f6EPK4Cls1({{.*}} !type [[F_TCLS2F6:![0-9]+]] + void f6(const Cls1 *a) {} + + // FT-DAG: define {{.*}} void @_ZN4Cls22f7ER4Cls1({{.*}} !type [[F_TCLS2F7:![0-9]+]] + void f7(Cls1 &a) {} + + // FT-DAG: define {{.*}} void @_ZN4Cls22f8ERK4Cls1({{.*}} !type [[F_TCLS2F8:![0-9]+]] + void f8(const Cls1 &a) {} + + // FT-DAG: define {{.*}} void @_ZNK4Cls22f9Ev({{.*}} !type [[F_TCLS2F9:![0-9]+]] + void f9() const {} +}; + +// FT-DAG: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPvS_S_E.generalized"} +// FT-DAG: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFPvS_S_S_E.generalized"} +// FT-DAG: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFicfdE.generalized"} +// FT-DAG: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"} +// FT-DAG: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvPvE.generalized"} +// FT-DAG: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvPKvE.generalized"} +// FT-DAG: [[F_TCLS2F7]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"} +// FT-DAG: [[F_TCLS2F8]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"} +// FT-DAG: [[F_TCLS2F9]] = !{i64 0, !"_ZTSKFvvE.generalized"} + +//////////////////////////////////////////////////////////////////////////////// +// Callsites (check for indirect callsite operand bundles) + +// CST-LABEL: define {{.*}} @_Z3foov +void foo() { + Cls2 ObjCls2; + ObjCls2.fp = &Cls1::receiver; + + // CST: call i32* {{.*}} [ "type"(metadata !"_ZTSFPvS_S_E.generalized") ] + ObjCls2.fp(0, 0); + + auto fp_f1 = &Cls2::f1; + auto fp_f2 = &Cls2::f2; + auto fp_f3 = &Cls2::f3; + auto fp_f4 = &Cls2::f4; + auto fp_f5 = &Cls2::f5; + auto fp_f6 = &Cls2::f6; + auto fp_f7 = &Cls2::f7; + auto fp_f8 = &Cls2::f8; + auto fp_f9 = &Cls2::f9; + + Cls2 *ObjCls2Ptr = &ObjCls2; + Cls1 Cls1Param; + + // CST: call i32 %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFicfdE.generalized") ] + (ObjCls2Ptr->*fp_f1)(0, 0, 0); + + // CST: call i32* %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFPvS_S_S_E.generalized") ] + (ObjCls2Ptr->*fp_f2)(0, 0, 0); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ] + (ObjCls2Ptr->*fp_f3)(Cls1Param); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFv4Cls1E.generalized") ] + (ObjCls2Ptr->*fp_f4)(Cls1Param); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvPvE.generalized") ] + (ObjCls2Ptr->*fp_f5)(&Cls1Param); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvPKvE.generalized") ] + (ObjCls2Ptr->*fp_f6)(&Cls1Param); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvR4Cls1E.generalized") ] + (ObjCls2Ptr->*fp_f7)(Cls1Param); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSFvRK4Cls1E.generalized") ] + (ObjCls2Ptr->*fp_f8)(Cls1Param); + + // CST: call void %{{.*}}(%class.Cls2*{{.*}} [ "type"(metadata !"_ZTSKFvvE.generalized") ] + (ObjCls2Ptr->*fp_f9)(); +} Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -2057,7 +2057,17 @@ void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, llvm::Function *F) { - // Only if we are checking indirect calls. + bool EmittedMDIdGeneralized = false; + if (CodeGenOpts.CallGraphSection && + (!F->hasLocalLinkage() || + F->getFunction().hasAddressTaken(nullptr, /* IgnoreCallbackUses */ true, + /* IgnoreAssumeLikeCalls */ true, + /* IgnoreLLVMUsed */ false))) { + F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType())); + EmittedMDIdGeneralized = true; + } + + // Add additional metadata only if we are checking indirect calls with CFI. if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall)) return; @@ -2068,7 +2078,9 @@ llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType()); F->addTypeMetadata(0, MD); - F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType())); + // Add the generalized identifier if not added already. + if (!EmittedMDIdGeneralized) + F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType())); // Emit a hash-based bit set entry for cross-DSO calls. if (CodeGenOpts.SanitizeCfiCrossDso) @@ -2150,7 +2162,8 @@ // are non-canonical then we need type metadata in order to produce the local // jump table. if (!CodeGenOpts.SanitizeCfiCrossDso || - !CodeGenOpts.SanitizeCfiCanonicalJumpTables) + !CodeGenOpts.SanitizeCfiCanonicalJumpTables || + CodeGenOpts.CallGraphSection) CreateFunctionTypeMetadataForIcall(FD, F); if (getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>()) Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -5242,6 +5242,27 @@ AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs); Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs); + if (CGM.getCodeGenOpts().CallGraphSection) { + // FIXME: create operand bundle only for indirect calls, not for all + + assert((TargetDecl && TargetDecl->getFunctionType() || + Callee.getAbstractInfo().getCalleeFunctionProtoType()) && + "cannot find callsite type"); + + QualType CST; + if (TargetDecl && TargetDecl->getFunctionType()) + CST = QualType(TargetDecl->getFunctionType(), 0); + else if (auto FPT = Callee.getAbstractInfo().getCalleeFunctionProtoType()) + CST = QualType(FPT, 0); + + if (!CST.isNull()) { + auto *TypeIdMD = CGM.CreateMetadataIdentifierGeneralized(CST); + auto *TypeIdMDVal = + llvm::MetadataAsValue::get(getLLVMContext(), TypeIdMD); + BundleList.emplace_back("type", TypeIdMDVal); + } + } + // Emit the actual call/invoke instruction. llvm::CallBase *CI; if (!InvokeDest) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits