Skip to content
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
00ac51b
[𝘀𝗽𝗿] changes to main this commit is based on
necipfazil Apr 3, 2024
0ca57bd
[𝘀𝗽𝗿] initial version
necipfazil Apr 3, 2024
21a4d2a
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 24, 2024
b9e7dc5
Rebased on top of main
necipfazil Apr 24, 2024
86ba0b1
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 29, 2024
683d7c3
dyn_cast to isa
necipfazil Apr 29, 2024
cd0cabe
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 1, 2024
661af56
Addressed review comments except for the verifier check. Rebased on u…
necipfazil May 1, 2024
639a497
[𝘀𝗽𝗿] changes introduced through rebase
necipfazil Nov 14, 2024
ae8f56a
Rebase patchset
necipfazil Nov 14, 2024
120cb54
[𝘀𝗽𝗿] changes introduced through rebase
necipfazil Nov 14, 2024
d573bf0
Update inline comment as suggested.
necipfazil Nov 14, 2024
2cb9de4
[𝘀𝗽𝗿] changes introduced through rebase
necipfazil Nov 20, 2024
26a149b
Rebase on top of upstream main.
necipfazil Nov 20, 2024
cf96ec2
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Nov 20, 2024
807cb0a
Break clang and llvm parts into separate commits.
necipfazil Nov 20, 2024
5455d3b
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Dec 10, 2024
3ab92c5
Address review comments. Break llvm and clang patches.
necipfazil Dec 10, 2024
1d7ee61
Simplify MIR test.
necipfazil Feb 2, 2025
d235c0f
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Feb 2, 2025
1cf40e1
Rebase on top of main.
necipfazil Feb 2, 2025
9db0468
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Feb 5, 2025
39017d7
Rename OB_type to OB_callee_type.
necipfazil Feb 5, 2025
f6ea853
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Feb 11, 2025
da97117
Squash callgraph option change with MIR changes.
Prabhuk Feb 11, 2025
cacf7fd
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Feb 11, 2025
6883cbd
Rebase on top of main
Prabhuk Feb 11, 2025
86e2c9d
Add requested tests part 1.
Prabhuk Mar 13, 2025
941dde5
Update comments in tests.
Prabhuk Mar 13, 2025
431fafc
Clean up test files.
Prabhuk Mar 15, 2025
b943425
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Mar 19, 2025
dc1b364
Address code refactoring and test cleanup comments.
Prabhuk Mar 19, 2025
7f8e4d9
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 19, 2025
53b24d9
Use list of CalleeTypeIds.
Prabhuk Apr 19, 2025
533454f
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 23, 2025
a7409ab
Handle instcombine usecase for callee_type metadata.
Prabhuk Apr 23, 2025
8c7b1ab
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 23, 2025
8e67a0e
Rebase on parent change.
Prabhuk Apr 23, 2025
c1f37fc
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 23, 2025
e33f18b
Address review comments.
Prabhuk Apr 23, 2025
d4b6ae0
Address review comments.
Prabhuk Apr 24, 2025
9f94841
Fix the test file formatting for calleeTypeIds.
Prabhuk Apr 24, 2025
fb93261
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 24, 2025
64fcf91
Destructuring.
Prabhuk Apr 24, 2025
84e71ce
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Apr 28, 2025
a703c75
Rebase on parent.
Prabhuk Apr 28, 2025
b42dc1b
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 1, 2025
1a104c9
Rebase on parent.
Prabhuk May 1, 2025
79791a2
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 5, 2025
b224d07
Rebase on parent.
Prabhuk May 5, 2025
9bb885a
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 10, 2025
181fabf
Rebase on parent change.
Prabhuk May 10, 2025
39c3c62
Remove dso_local and noundef from tests.
Prabhuk May 13, 2025
0848196
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 14, 2025
5f9c6ce
Rebase change stack on top of parent.
Prabhuk May 14, 2025
fb9fdab
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 14, 2025
028a635
Rebase on main.
Prabhuk May 14, 2025
d95d4f9
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk May 27, 2025
613b498
Rebase on parent.
Prabhuk May 27, 2025
99e871f
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jun 11, 2025
f3a7ef8
Rebase.
Prabhuk Jun 11, 2025
27e073c
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jun 11, 2025
cb887ee
Rebase on main
Prabhuk Jun 11, 2025
436d91b
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jul 10, 2025
222580c
Rebase on top of main.
Prabhuk Jul 10, 2025
cdbf3a2
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jul 18, 2025
6d4910a
Rebase on top of main.
Prabhuk Jul 18, 2025
6a6768e
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jul 18, 2025
154cede
Rebase on parent
Prabhuk Jul 18, 2025
cf8aeae
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jul 18, 2025
b2d6cbc
Rebase on top of main.
Prabhuk Jul 18, 2025
58b5d3d
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jul 18, 2025
9456466
Rebase on parent.
Prabhuk Jul 18, 2025
37d8b40
[𝘀𝗽𝗿] changes introduced through rebase
Prabhuk Jul 18, 2025
2d1d17f
Rebase on parent.
Prabhuk Jul 18, 2025
18b26b5
[𝘀𝗽𝗿] changes introduced through rebase
kkwli Jul 18, 2025
6928996
Address review comments.
Prabhuk Jul 18, 2025
09ba547
[𝘀𝗽𝗿] changes introduced through rebase
topperc Jul 21, 2025
3a41234
Rebase on top of main.
Prabhuk Jul 21, 2025
f5b15c6
[𝘀𝗽𝗿] changes introduced through rebase
RKSimon Jul 22, 2025
72b0dd0
Rebase.
Prabhuk Jul 22, 2025
79920a8
Reduce tests. Rename function names in tests.
Prabhuk Jul 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions llvm/docs/CalleeTypeMetadata.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
====================
Callee Type Metadata
====================

Introduction
============
This ``!callee_type`` metadata is introduced to support the generation of a call graph
section in the object file. The ``!callee_type`` metadata is used
to identify the types of the intended callees of indirect call instructions. The ``!callee_type`` metadata is a
list of one or more generalized ``!type`` metadata objects (See :doc:`TypeMetadata`) with each ``!type``
metadata pointing to a callee's :ref:`type identifier <calleetype-type-identifier>`.
LLVM's `Control Flow Integrity (CFI)`_ also uses the ``!type`` metadata in its implementation.

.. _Control Flow Integrity (CFI): https://clang.llvm.org/docs/ControlFlowIntegrity.html

.. _calleetype-type-identifier:

Type identifier
================

The type for an indirect call target is the callee's function signature.
Mapping from a type to an identifier is an ABI detail.
In the current implementation, an identifier of type T is
computed as follows:

- Obtain the generalized mangled name for “typeinfo name for T”.
- Compute MD5 hash of the name as a string.
- Reinterpret the first 8 bytes of the hash as a little-endian 64-bit integer.

To avoid mismatched pointer types, generalizations are applied.
Pointers in return and argument types are treated as equivalent as long as the qualifiers for the
type they point to match. For example, ``char*``, ``char**``, and ``int*`` are considered equivalent
types. However, ``char*`` and ``const char*`` are considered distinct types.
5 changes: 5 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8091,6 +8091,11 @@ change in the future.

See :doc:`TypeMetadata`.

'``callee_type``' Metadata
^^^^^^^^^^^^^^^^^^^^^^^^^^

See :doc:`CalleeTypeMetadata`.

'``associated``' Metadata
^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
1 change: 1 addition & 0 deletions llvm/docs/Reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ LLVM and API reference documentation.
BlockFrequencyTerminology
BranchWeightMetadata
Bugpoint
CalleeTypeMetadata
CIBestPractices
CommandGuide/index
ConvergenceAndUniformity
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/CodeGen/CommandFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ bool getEnableStackSizeSection();

bool getEnableAddrsig();

bool getEnableCallGraphSection();

bool getEmitCallSiteInfo();

bool getEnableMachineFunctionSplitter();
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/MIRYamlMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ struct CallSiteInfo {

MachineInstrLoc CallLocation;
std::vector<ArgRegPair> ArgForwardingRegs;
/// Numeric callee type identifiers for the callgraph section.
std::vector<uint64_t> CalleeTypeIds;

bool operator==(const CallSiteInfo &Other) const {
return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
Expand Down Expand Up @@ -511,6 +513,7 @@ template <> struct MappingTraits<CallSiteInfo> {
YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
std::vector<CallSiteInfo::ArgRegPair>());
YamlIO.mapOptional("calleeTypeIds", CSInfo.CalleeTypeIds);
}

static const bool flow = true;
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/CodeGen/MachineFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ class LLVM_ABI MachineFunction {
struct CallSiteInfo {
/// Vector of call argument and its forwarding register.
SmallVector<ArgRegPair, 1> ArgRegPairs;
/// Callee type ids.
SmallVector<ConstantInt *, 4> CalleeTypeIds;
};

struct CalledGlobalInfo {
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/FixedMetadataKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ LLVM_FIXED_MD_KIND(MD_DIAssignID, "DIAssignID", 38)
LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)
LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
LLVM_FIXED_MD_KIND(MD_callee_type, "callee_type", 42)
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,12 @@ class MDNode : public Metadata {
bool isReplaceable() const { return isTemporary() || isAlwaysReplaceable(); }
bool isAlwaysReplaceable() const { return getMetadataID() == DIAssignIDKind; }

bool hasGeneralizedMDString() const {
if (getNumOperands() < 2 || !isa<MDString>(getOperand(1)))
return false;
return cast<MDString>(getOperand(1))->getString().ends_with(".generalized");
}

unsigned getNumTemporaryUses() const {
assert(isTemporary() && "Only for temporaries");
return Context.getReplaceableUses()->getNumUses();
Expand Down Expand Up @@ -1463,6 +1469,8 @@ class MDNode : public Metadata {
const Instruction *BInstr);
static MDNode *getMergedMemProfMetadata(MDNode *A, MDNode *B);
static MDNode *getMergedCallsiteMetadata(MDNode *A, MDNode *B);
static MDNode *getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
MDNode *B);
};

/// Tuple of metadata.
Expand Down
12 changes: 8 additions & 4 deletions llvm/include/llvm/Target/TargetOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,11 @@ namespace llvm {
EmitStackSizeSection(false), EnableMachineOutliner(false),
EnableMachineFunctionSplitter(false),
EnableStaticDataPartitioning(false), SupportsDefaultOutlining(false),
EmitAddrsig(false), BBAddrMap(false), EmitCallSiteInfo(false),
SupportsDebugEntryValues(false), EnableDebugEntryValues(false),
ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
XRayFunctionIndex(true), DebugStrictDwarf(false), Hotpatch(false),
EmitAddrsig(false), BBAddrMap(false), EmitCallGraphSection(false),
EmitCallSiteInfo(false), SupportsDebugEntryValues(false),
EnableDebugEntryValues(false), ValueTrackingVariableLocations(false),
ForceDwarfFrameSection(false), XRayFunctionIndex(true),
DebugStrictDwarf(false), Hotpatch(false),
PPCGenScalarMASSEntries(false), JMCInstrument(false),
EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false),
VerifyArgABICompliance(true),
Expand Down Expand Up @@ -333,6 +334,9 @@ namespace llvm {
/// to selectively generate basic block sections.
std::shared_ptr<MemoryBuffer> BBSectionsFuncListBuf;

/// Emit section containing call graph metadata.
unsigned EmitCallGraphSection : 1;

/// The flag enables call site info production. It is used only for debug
/// info, and it is restricted only to optimized code. This can be used for
/// something else, so that should be controlled in the frontend.
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/CodeGen/CommandFlags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ CGOPT(EABI, EABIVersion)
CGOPT(DebuggerKind, DebuggerTuningOpt)
CGOPT(bool, EnableStackSizeSection)
CGOPT(bool, EnableAddrsig)
CGOPT(bool, EnableCallGraphSection)
CGOPT(bool, EmitCallSiteInfo)
CGOPT(bool, EnableMachineFunctionSplitter)
CGOPT(bool, EnableStaticDataPartitioning)
Expand Down Expand Up @@ -461,6 +462,11 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
cl::init(false));
CGBINDOPT(EnableAddrsig);

static cl::opt<bool> EnableCallGraphSection(
"call-graph-section", cl::desc("Emit a call graph section"),
cl::init(false));
CGBINDOPT(EnableCallGraphSection);

static cl::opt<bool> EmitCallSiteInfo(
"emit-call-site-info",
cl::desc(
Expand Down Expand Up @@ -595,6 +601,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
Options.EnableMachineFunctionSplitter = getEnableMachineFunctionSplitter();
Options.EnableStaticDataPartitioning = getEnableStaticDataPartitioning();
Options.EmitAddrsig = getEnableAddrsig();
Options.EmitCallGraphSection = getEnableCallGraphSection();
Options.EmitCallSiteInfo = getEmitCallSiteInfo();
Options.EnableDebugEntryValues = getEnableDebugEntryValues();
Options.ForceDwarfFrameSection = getForceDwarfFrameSection();
Expand Down
14 changes: 11 additions & 3 deletions llvm/lib/CodeGen/MIRParser/MIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,13 +504,21 @@ bool MIRParserImpl::initializeCallSiteInfo(
return error(Error, ArgRegPair.Reg.SourceRange);
CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo);
}
if (!YamlCSInfo.CalleeTypeIds.empty()) {
for (auto CalleeTypeId : YamlCSInfo.CalleeTypeIds) {
IntegerType *Int64Ty = Type::getInt64Ty(Context);
CSInfo.CalleeTypeIds.push_back(ConstantInt::get(Int64Ty, CalleeTypeId,
/*isSigned=*/false));
}
}

if (TM.Options.EmitCallSiteInfo)
if (TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection)
MF.addCallSiteInfo(&*CallI, std::move(CSInfo));
}

if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo)
return error(Twine("Call site info provided but not used"));
if (!YamlMF.CallSitesInfo.empty() &&
!(TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection))
return error("call site info provided but not used");
return false;
}

Expand Down
12 changes: 9 additions & 3 deletions llvm/lib/CodeGen/MIRPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,24 +551,30 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
const MachineFunction &MF,
ModuleSlotTracker &MST) {
const auto *TRI = MF.getSubtarget().getRegisterInfo();
for (auto CSInfo : MF.getCallSitesInfo()) {
for (auto [MI, CallSiteInfo] : MF.getCallSitesInfo()) {
yaml::CallSiteInfo YmlCS;
yaml::MachineInstrLoc CallLocation;

// Prepare instruction position.
MachineBasicBlock::const_instr_iterator CallI = CSInfo.first->getIterator();
MachineBasicBlock::const_instr_iterator CallI = MI->getIterator();
CallLocation.BlockNum = CallI->getParent()->getNumber();
// Get call instruction offset from the beginning of block.
CallLocation.Offset =
std::distance(CallI->getParent()->instr_begin(), CallI);
YmlCS.CallLocation = CallLocation;

auto [ArgRegPairs, CalleeTypeIds] = CallSiteInfo;
// Construct call arguments and theirs forwarding register info.
for (auto ArgReg : CSInfo.second.ArgRegPairs) {
for (auto ArgReg : ArgRegPairs) {
yaml::CallSiteInfo::ArgRegPair YmlArgReg;
YmlArgReg.ArgNo = ArgReg.ArgNo;
printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI);
YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
}
// Get type ids.
for (auto *CalleeTypeId : CalleeTypeIds) {
YmlCS.CalleeTypeIds.push_back(CalleeTypeId->getZExtValue());
}
YMF.CallSitesInfo.push_back(std::move(YmlCS));
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/MachineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ MachineFunction::getCallSiteInfo(const MachineInstr *MI) {
assert(MI->isCandidateForAdditionalCallInfo() &&
"Call site info refers only to call (MI) candidates");

if (!Target.Options.EmitCallSiteInfo)
if (!Target.Options.EmitCallSiteInfo && !Target.Options.EmitCallGraphSection)
return CallSitesInfo.end();
return CallSitesInfo.find(MI);
}
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/IR/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,24 @@ static void addRange(SmallVectorImpl<ConstantInt *> &EndPoints,
EndPoints.push_back(High);
}

MDNode *MDNode::getMergedCalleeTypeMetadata(LLVMContext &Ctx, MDNode *A,
MDNode *B) {
SmallVector<Metadata *, 8> AB;
SmallPtrSet<Metadata *, 8> MergedCallees;
auto AddUniqueCallees = [&AB, &MergedCallees](MDNode *N) {
if (!N)
return;
for (const MDOperand &Op : N->operands()) {
Metadata *MD = Op.get();
if (MergedCallees.insert(MD).second)
AB.push_back(MD);
}
};
AddUniqueCallees(A);
AddUniqueCallees(B);
return MDNode::get(Ctx, AB);
}

MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
// Given two ranges, we want to compute the union of the ranges. This
// is slightly complicated by having to combine the intervals and merge
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
void visitCallStackMetadata(MDNode *MD);
void visitMemProfMetadata(Instruction &I, MDNode *MD);
void visitCallsiteMetadata(Instruction &I, MDNode *MD);
void visitCalleeTypeMetadata(Instruction &I, MDNode *MD);
void visitDIAssignIDMetadata(Instruction &I, MDNode *MD);
void visitMMRAMetadata(Instruction &I, MDNode *MD);
void visitAnnotationMetadata(MDNode *Annotation);
Expand Down Expand Up @@ -5096,6 +5097,19 @@ void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) {
visitCallStackMetadata(MD);
}

void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) {
Check(isa<CallBase>(I), "!callee_type metadata should only exist on calls",
&I);
for (const MDOperand &Op : MD->operands()) {
Check(isa<MDNode>(Op.get()),
"The callee_type metadata must be a list of type metadata nodes");
auto *TypeMD = cast<MDNode>(Op.get());
Check(TypeMD->hasGeneralizedMDString(),
"Only generalized type metadata can be part of the callee_type "
"metadata list");
}
}

void Verifier::visitAnnotationMetadata(MDNode *Annotation) {
Check(isa<MDTuple>(Annotation), "annotation must be a tuple");
Check(Annotation->getNumOperands() >= 1,
Expand Down Expand Up @@ -5373,6 +5387,9 @@ void Verifier::visitInstruction(Instruction &I) {
if (MDNode *MD = I.getMetadata(LLVMContext::MD_callsite))
visitCallsiteMetadata(I, MD);

if (MDNode *MD = I.getMetadata(LLVMContext::MD_callee_type))
visitCalleeTypeMetadata(I, MD);

if (MDNode *MD = I.getMetadata(LLVMContext::MD_DIAssignID))
visitDIAssignIDMetadata(I, MD);

Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4161,6 +4161,13 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
Call, Builder.CreateBitOrPointerCast(ReturnedArg, CallTy));
}

// Drop unnecessary callee_type metadata from calls that were converted
// into direct calls.
if (Call.getMetadata(LLVMContext::MD_callee_type) && !Call.isIndirectCall()) {
Call.setMetadata(LLVMContext::MD_callee_type, nullptr);
Changed = true;
}

// Drop unnecessary kcfi operand bundles from calls that were converted
// into direct calls.
auto Bundle = Call.getOperandBundle(LLVMContext::OB_kcfi);
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Transforms/Utils/Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3365,6 +3365,7 @@ static void combineMetadata(Instruction *K, const Instruction *J,
case LLVMContext::MD_mmra:
case LLVMContext::MD_memprof:
case LLVMContext::MD_callsite:
case LLVMContext::MD_callee_type:
break;
case LLVMContext::MD_align:
if (!AAOnly && (DoesKMove || !K->hasMetadata(LLVMContext::MD_noundef)))
Expand Down Expand Up @@ -3437,6 +3438,17 @@ static void combineMetadata(Instruction *K, const Instruction *J,
MDNode::getMergedCallsiteMetadata(KCallSite, JCallSite));
}

// Merge callee_type metadata.
// Handle separately to support cases where only one instruction has the
// metadata.
auto *JCalleeType = J->getMetadata(LLVMContext::MD_callee_type);
auto *KCalleeType = K->getMetadata(LLVMContext::MD_callee_type);
if (!AAOnly && (JCalleeType || KCalleeType)) {
K->setMetadata(LLVMContext::MD_callee_type,
MDNode::getMergedCalleeTypeMetadata(
K->getContext(), KCalleeType, JCalleeType));
}

// Merge prof metadata.
// Handle separately to support cases where only one instruction has the
// metadata.
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/Utils/ValueMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,13 @@ void Mapper::remapInstruction(Instruction *I) {
"Referenced value not in value map!");
}

// Drop callee_type metadata from calls that were remapped
// into a direct call from an indirect one.
if (auto *CB = dyn_cast<CallBase>(I)) {
if (CB->getMetadata(LLVMContext::MD_callee_type) && !CB->isIndirectCall())
CB->setMetadata(LLVMContext::MD_callee_type, nullptr);
}

// Remap phi nodes' incoming blocks.
if (PHINode *PN = dyn_cast<PHINode>(I)) {
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/Assembler/callee-type-metadata.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
;; Test if the callee_type metadata attached to indirect call sites adhere to the expected format.

; RUN: llvm-as < %s | llvm-dis | FileCheck %s
define i32 @_Z13call_indirectPFicEc(ptr %func, i8 signext %x) !type !0 {
entry:
%func.addr = alloca ptr, align 8
%x.addr = alloca i8, align 1
store ptr %func, ptr %func.addr, align 8
store i8 %x, ptr %x.addr, align 1
%fptr = load ptr, ptr %func.addr, align 8
%x_val = load i8, ptr %x.addr, align 1
; CHECK: %call = call i32 %fptr(i8 signext %x_val), !callee_type !1
%call = call i32 %fptr(i8 signext %x_val), !callee_type !1
ret i32 %call
}

declare !type !2 i32 @_Z3barc(i8 signext)

!0 = !{i64 0, !"_ZTSFiPvcE.generalized"}
!1 = !{!2}
!2 = !{i64 0, !"_ZTSFicE.generalized"}
Loading
Loading