@@ -1654,6 +1654,88 @@ void AsmPrinter::emitStackUsage(const MachineFunction &MF) {
16541654 *StackUsageStream << " static\n " ;
16551655}
16561656
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+
16571739void AsmPrinter::emitPCSectionsLabel (const MachineFunction &MF,
16581740 const MDNode &MD) {
16591741 MCSymbol *S = MF.getContext ().createTempSymbol (" pcsection" );
@@ -1784,6 +1866,23 @@ static StringRef getMIMnemonic(const MachineInstr &MI, MCStreamer &Streamer) {
17841866 return Name;
17851867}
17861868
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+
17871886// / EmitFunctionBody - This method emits the body and trailer for a
17881887// / function.
17891888void AsmPrinter::emitFunctionBody () {
@@ -1830,6 +1929,8 @@ void AsmPrinter::emitFunctionBody() {
18301929 MBBSectionRanges[MF->front ().getSectionID ()] =
18311930 MBBSectionRange{CurrentFnBegin, nullptr };
18321931
1932+ FunctionInfo FuncInfo;
1933+ const auto &CallSitesInfoMap = MF->getCallSitesInfo ();
18331934 for (auto &MBB : *MF) {
18341935 // Print a label for the basic block.
18351936 emitBasicBlockStart (MBB);
@@ -1963,6 +2064,9 @@ void AsmPrinter::emitFunctionBody() {
19632064 break ;
19642065 }
19652066
2067+ if (TM.Options .EmitCallGraphSection && MI.isCall ())
2068+ emitIndirectCalleeLabels (FuncInfo, CallSitesInfoMap, MI);
2069+
19662070 // If there is a post-instruction symbol, emit a label for it here.
19672071 if (MCSymbol *S = MI.getPostInstrSymbol ())
19682072 OutStreamer->emitLabel (S);
@@ -2142,6 +2246,9 @@ void AsmPrinter::emitFunctionBody() {
21422246 // Emit section containing stack size metadata.
21432247 emitStackSizeSection (*MF);
21442248
2249+ // Emit section containing call graph metadata.
2250+ emitCallGraphSection (*MF, FuncInfo);
2251+
21452252 // Emit .su file containing function stack size information.
21462253 emitStackUsage (*MF);
21472254
@@ -2841,6 +2948,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
28412948 F.hasFnAttribute (" xray-instruction-threshold" ) ||
28422949 needFuncLabels (MF, *this ) || NeedsLocalForSize ||
28432950 MF.getTarget ().Options .EmitStackSizeSection ||
2951+ MF.getTarget ().Options .EmitCallGraphSection ||
28442952 MF.getTarget ().Options .BBAddrMap ) {
28452953 CurrentFnBegin = createTempSymbol (" func_begin" );
28462954 if (NeedsLocalForSize)
0 commit comments