@@ -1654,6 +1654,88 @@ void AsmPrinter::emitStackUsage(const MachineFunction &MF) {
1654
1654
*StackUsageStream << " static\n " ;
1655
1655
}
1656
1656
1657
+ // / Extracts a generalized numeric type identifier of a Function's type from
1658
+ // / type metadata. Returns null if metadata cannot be found.
1659
+ static ConstantInt *extractNumericCGTypeId (const Function &F) {
1660
+ SmallVector<MDNode *, 2 > Types;
1661
+ F.getMetadata (LLVMContext::MD_type, Types);
1662
+ for (const auto &Type : Types) {
1663
+ if (Type->hasGeneralizedMDString ()) {
1664
+ MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand (1 ));
1665
+ uint64_t TypeIdVal = llvm::MD5Hash (MDGeneralizedTypeId->getString ());
1666
+ IntegerType *Int64Ty = Type::getInt64Ty (F.getContext ());
1667
+ return ConstantInt::get (Int64Ty, TypeIdVal);
1668
+ }
1669
+ }
1670
+ return nullptr ;
1671
+ }
1672
+
1673
+ // / Emits .callgraph section.
1674
+ void AsmPrinter::emitCallGraphSection (const MachineFunction &MF,
1675
+ FunctionInfo &FuncInfo) {
1676
+ if (!MF.getTarget ().Options .EmitCallGraphSection )
1677
+ return ;
1678
+
1679
+ // Switch to the call graph section for the function
1680
+ MCSection *FuncCGSection =
1681
+ getObjFileLowering ().getCallGraphSection (*getCurrentSection ());
1682
+ assert (FuncCGSection && " null callgraph section" );
1683
+ OutStreamer->pushSection ();
1684
+ OutStreamer->switchSection (FuncCGSection);
1685
+
1686
+ // Emit format version number.
1687
+ OutStreamer->emitInt64 (CallGraphSectionFormatVersion::V_0);
1688
+
1689
+ // Emit function's self information, which is composed of:
1690
+ // 1) FunctionEntryPc
1691
+ // 2) FunctionKind: Whether the function is indirect target, and if so,
1692
+ // whether its type id is known.
1693
+ // 3) FunctionTypeId: Emit only when the function is an indirect target
1694
+ // and its type id is known.
1695
+
1696
+ // Emit function entry pc.
1697
+ const MCSymbol *FunctionSymbol = getFunctionBegin ();
1698
+ OutStreamer->emitSymbolValue (FunctionSymbol, TM.getProgramPointerSize ());
1699
+
1700
+ // If this function has external linkage or has its address taken and
1701
+ // it is not a callback, then anything could call it.
1702
+ const Function &F = MF.getFunction ();
1703
+ bool IsIndirectTarget =
1704
+ !F.hasLocalLinkage () || F.hasAddressTaken (nullptr ,
1705
+ /* IgnoreCallbackUses=*/ true ,
1706
+ /* IgnoreAssumeLikeCalls=*/ true ,
1707
+ /* IgnoreLLVMUsed=*/ false );
1708
+
1709
+ // FIXME: FunctionKind takes a few values but emitted as a 64-bit value.
1710
+ // Can be optimized to occupy 2 bits instead.
1711
+ // Emit function kind, and type id if available.
1712
+ if (!IsIndirectTarget) {
1713
+ OutStreamer->emitInt64 (
1714
+ static_cast <uint64_t >(FunctionInfo::FunctionKind::NOT_INDIRECT_TARGET));
1715
+ } else {
1716
+ if (const auto *TypeId = extractNumericCGTypeId (F)) {
1717
+ OutStreamer->emitInt64 (static_cast <uint64_t >(
1718
+ FunctionInfo::FunctionKind::INDIRECT_TARGET_KNOWN_TID));
1719
+ OutStreamer->emitInt64 (TypeId->getZExtValue ());
1720
+ } else {
1721
+ OutStreamer->emitInt64 (static_cast <uint64_t >(
1722
+ FunctionInfo::FunctionKind::INDIRECT_TARGET_UNKNOWN_TID));
1723
+ }
1724
+ }
1725
+
1726
+ // Emit callsite labels, where each element is a pair of type id and
1727
+ // indirect callsite pc.
1728
+ const auto &CallSiteLabels = FuncInfo.CallSiteLabels ;
1729
+ OutStreamer->emitInt64 (CallSiteLabels.size ());
1730
+ for (const auto &[TypeId, Label] : CallSiteLabels) {
1731
+ OutStreamer->emitInt64 (TypeId);
1732
+ OutStreamer->emitSymbolValue (Label, TM.getProgramPointerSize ());
1733
+ }
1734
+ FuncInfo.CallSiteLabels .clear ();
1735
+
1736
+ OutStreamer->popSection ();
1737
+ }
1738
+
1657
1739
void AsmPrinter::emitPCSectionsLabel (const MachineFunction &MF,
1658
1740
const MDNode &MD) {
1659
1741
MCSymbol *S = MF.getContext ().createTempSymbol (" pcsection" );
@@ -1784,6 +1866,23 @@ static StringRef getMIMnemonic(const MachineInstr &MI, MCStreamer &Streamer) {
1784
1866
return Name;
1785
1867
}
1786
1868
1869
+ void AsmPrinter::emitIndirectCalleeLabels (
1870
+ FunctionInfo &FuncInfo,
1871
+ const MachineFunction::CallSiteInfoMap &CallSitesInfoMap,
1872
+ const MachineInstr &MI) {
1873
+ // Only indirect calls have type identifiers set.
1874
+ const auto &CallSiteInfo = CallSitesInfoMap.find (&MI);
1875
+ if (CallSiteInfo == CallSitesInfoMap.end ())
1876
+ return ;
1877
+
1878
+ for (ConstantInt *CalleeTypeId : CallSiteInfo->second .CalleeTypeIds ) {
1879
+ MCSymbol *S = MF->getContext ().createTempSymbol ();
1880
+ OutStreamer->emitLabel (S);
1881
+ uint64_t CalleeTypeIdVal = CalleeTypeId->getZExtValue ();
1882
+ FuncInfo.CallSiteLabels .emplace_back (CalleeTypeIdVal, S);
1883
+ }
1884
+ }
1885
+
1787
1886
// / EmitFunctionBody - This method emits the body and trailer for a
1788
1887
// / function.
1789
1888
void AsmPrinter::emitFunctionBody () {
@@ -1830,6 +1929,8 @@ void AsmPrinter::emitFunctionBody() {
1830
1929
MBBSectionRanges[MF->front ().getSectionID ()] =
1831
1930
MBBSectionRange{CurrentFnBegin, nullptr };
1832
1931
1932
+ FunctionInfo FuncInfo;
1933
+ const auto &CallSitesInfoMap = MF->getCallSitesInfo ();
1833
1934
for (auto &MBB : *MF) {
1834
1935
// Print a label for the basic block.
1835
1936
emitBasicBlockStart (MBB);
@@ -1963,6 +2064,9 @@ void AsmPrinter::emitFunctionBody() {
1963
2064
break ;
1964
2065
}
1965
2066
2067
+ if (TM.Options .EmitCallGraphSection && MI.isCall ())
2068
+ emitIndirectCalleeLabels (FuncInfo, CallSitesInfoMap, MI);
2069
+
1966
2070
// If there is a post-instruction symbol, emit a label for it here.
1967
2071
if (MCSymbol *S = MI.getPostInstrSymbol ())
1968
2072
OutStreamer->emitLabel (S);
@@ -2142,6 +2246,9 @@ void AsmPrinter::emitFunctionBody() {
2142
2246
// Emit section containing stack size metadata.
2143
2247
emitStackSizeSection (*MF);
2144
2248
2249
+ // Emit section containing call graph metadata.
2250
+ emitCallGraphSection (*MF, FuncInfo);
2251
+
2145
2252
// Emit .su file containing function stack size information.
2146
2253
emitStackUsage (*MF);
2147
2254
@@ -2841,6 +2948,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
2841
2948
F.hasFnAttribute (" xray-instruction-threshold" ) ||
2842
2949
needFuncLabels (MF, *this ) || NeedsLocalForSize ||
2843
2950
MF.getTarget ().Options .EmitStackSizeSection ||
2951
+ MF.getTarget ().Options .EmitCallGraphSection ||
2844
2952
MF.getTarget ().Options .BBAddrMap ) {
2845
2953
CurrentFnBegin = createTempSymbol (" func_begin" );
2846
2954
if (NeedsLocalForSize)
0 commit comments