@@ -1597,6 +1597,105 @@ void AsmPrinter::emitStackUsage(const MachineFunction &MF) {
15971597 *StackUsageStream << " static\n " ;
15981598}
15991599
1600+ // / Extracts a generalized numeric type identifier of a Function's type from
1601+ // / type metadata. Returns null if metadata cannot be found.
1602+ static ConstantInt *extractNumericCGTypeId (const Function &F) {
1603+ SmallVector<MDNode *, 2 > Types;
1604+ F.getMetadata (LLVMContext::MD_type, Types);
1605+ MDString *MDGeneralizedTypeId = nullptr ;
1606+ for (const auto &Type : Types) {
1607+ if (Type->getNumOperands () == 2 && isa<MDString>(Type->getOperand (1 ))) {
1608+ auto *TMDS = cast<MDString>(Type->getOperand (1 ));
1609+ if (TMDS->getString ().ends_with (" generalized" )) {
1610+ MDGeneralizedTypeId = TMDS;
1611+ break ;
1612+ }
1613+ }
1614+ }
1615+
1616+ if (!MDGeneralizedTypeId) {
1617+ errs () << " warning: can't find indirect target type id metadata "
1618+ << " for " << F.getName () << " \n " ;
1619+ return nullptr ;
1620+ }
1621+
1622+ uint64_t TypeIdVal = llvm::MD5Hash (MDGeneralizedTypeId->getString ());
1623+ Type *Int64Ty = Type::getInt64Ty (F.getContext ());
1624+ return cast<ConstantInt>(ConstantInt::get (Int64Ty, TypeIdVal));
1625+ }
1626+
1627+ // / Emits call graph section.
1628+ void AsmPrinter::emitCallGraphSection (const MachineFunction &MF,
1629+ FunctionInfo &FuncInfo) {
1630+ if (!MF.getTarget ().Options .EmitCallGraphSection )
1631+ return ;
1632+
1633+ // Switch to the call graph section for the function
1634+ MCSection *FuncCGSection =
1635+ getObjFileLowering ().getCallGraphSection (*getCurrentSection ());
1636+ assert (FuncCGSection && " null call graph section" );
1637+ OutStreamer->pushSection ();
1638+ OutStreamer->switchSection (FuncCGSection);
1639+
1640+ // Emit format version number.
1641+ OutStreamer->emitInt64 (0 );
1642+
1643+ // Emit function's self information, which is composed of:
1644+ // 1) FunctionEntryPc
1645+ // 2) FunctionKind: Whether the function is indirect target, and if so,
1646+ // whether its type id is known.
1647+ // 3) FunctionTypeId: Emit only when the function is an indirect target
1648+ // and its type id is known.
1649+
1650+ // Emit function entry pc.
1651+ const MCSymbol *FunctionSymbol = getFunctionBegin ();
1652+ OutStreamer->emitSymbolValue (FunctionSymbol, TM.getProgramPointerSize ());
1653+
1654+ // If this function has external linkage or has its address taken and
1655+ // it is not a callback, then anything could call it.
1656+ const Function &F = MF.getFunction ();
1657+ bool IsIndirectTarget =
1658+ !F.hasLocalLinkage () || F.hasAddressTaken (nullptr ,
1659+ /* IgnoreCallbackUses=*/ true ,
1660+ /* IgnoreAssumeLikeCalls=*/ true ,
1661+ /* IgnoreLLVMUsed=*/ false );
1662+
1663+ // FIXME: FunctionKind takes a few values but emitted as a 64-bit value.
1664+ // Can be optimized to occupy 2 bits instead.
1665+ // Emit function kind, and type id if available.
1666+ if (!IsIndirectTarget) {
1667+ OutStreamer->emitInt64 (FunctionInfo::FunctionKind::NOT_INDIRECT_TARGET);
1668+ } else {
1669+ const auto *TypeId = extractNumericCGTypeId (F);
1670+ if (TypeId) {
1671+ OutStreamer->emitInt64 (
1672+ FunctionInfo::FunctionKind::INDIRECT_TARGET_KNOWN_TID);
1673+ OutStreamer->emitInt64 (TypeId->getZExtValue ());
1674+ } else {
1675+ OutStreamer->emitInt64 (
1676+ FunctionInfo::FunctionKind::INDIRECT_TARGET_UNKNOWN_TID);
1677+ }
1678+ }
1679+
1680+ // Emit callsite labels, where each element is a pair of type id and
1681+ // indirect callsite pc.
1682+ const auto &CallSiteLabels = FuncInfo.CallSiteLabels ;
1683+
1684+ // Emit the count of pairs.
1685+ OutStreamer->emitInt64 (CallSiteLabels.size ());
1686+
1687+ // Emit the type id and call site label pairs.
1688+ for (const std::pair<uint64_t , MCSymbol *> &El : CallSiteLabels) {
1689+ auto TypeId = El.first ;
1690+ const auto &Label = El.second ;
1691+ OutStreamer->emitInt64 (TypeId);
1692+ OutStreamer->emitSymbolValue (Label, TM.getProgramPointerSize ());
1693+ }
1694+ FuncInfo.CallSiteLabels .clear ();
1695+
1696+ OutStreamer->popSection ();
1697+ }
1698+
16001699void AsmPrinter::emitPCSectionsLabel (const MachineFunction &MF,
16011700 const MDNode &MD) {
16021701 MCSymbol *S = MF.getContext ().createTempSymbol (" pcsection" );
@@ -1746,6 +1845,8 @@ void AsmPrinter::emitFunctionBody() {
17461845 bool IsEHa = MMI->getModule ()->getModuleFlag (" eh-asynch" );
17471846
17481847 bool CanDoExtraAnalysis = ORE->allowExtraAnalysis (DEBUG_TYPE);
1848+ FunctionInfo FuncInfo;
1849+ const auto &CallSitesInfoMap = MF->getCallSitesInfo ();
17491850 for (auto &MBB : *MF) {
17501851 // Print a label for the basic block.
17511852 emitBasicBlockStart (MBB);
@@ -1859,6 +1960,26 @@ void AsmPrinter::emitFunctionBody() {
18591960 break ;
18601961 }
18611962
1963+ // FIXME: Some indirect calls can get lowered to jump instructions,
1964+ // resulting in emitting labels for them. The extra information can
1965+ // be neglected while disassembling but still takes space in the binary.
1966+ if (TM.Options .EmitCallGraphSection && MI.isCall ()) {
1967+ // Only indirect calls have type identifiers set.
1968+ const auto &CallSiteInfo = CallSitesInfoMap.find (&MI);
1969+ if (CallSiteInfo != CallSitesInfoMap.end ()) {
1970+ if (auto *TypeId = CallSiteInfo->second .TypeId ) {
1971+ // Emit label.
1972+ MCSymbol *S = MF->getContext ().createTempSymbol ();
1973+ OutStreamer->emitLabel (S);
1974+
1975+ // Get type id value.
1976+ uint64_t TypeIdVal = TypeId->getZExtValue ();
1977+
1978+ // Add to function's callsite labels.
1979+ FuncInfo.CallSiteLabels .emplace_back (TypeIdVal, S);
1980+ }
1981+ }
1982+ }
18621983 // If there is a post-instruction symbol, emit a label for it here.
18631984 if (MCSymbol *S = MI.getPostInstrSymbol ())
18641985 OutStreamer->emitLabel (S);
@@ -2040,6 +2161,9 @@ void AsmPrinter::emitFunctionBody() {
20402161 // Emit section containing stack size metadata.
20412162 emitStackSizeSection (*MF);
20422163
2164+ // Emit section containing call graph metadata.
2165+ emitCallGraphSection (*MF, FuncInfo);
2166+
20432167 // Emit .su file containing function stack size information.
20442168 emitStackUsage (*MF);
20452169
@@ -2622,6 +2746,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
26222746 F.hasFnAttribute (" function-instrument" ) ||
26232747 F.hasFnAttribute (" xray-instruction-threshold" ) || needFuncLabels (MF) ||
26242748 NeedsLocalForSize || MF.getTarget ().Options .EmitStackSizeSection ||
2749+ MF.getTarget ().Options .EmitCallGraphSection ||
26252750 MF.getTarget ().Options .BBAddrMap || MF.hasBBLabels ()) {
26262751 CurrentFnBegin = createTempSymbol (" func_begin" );
26272752 if (NeedsLocalForSize)
0 commit comments