Index: llvm/include/llvm/CodeGen/MachineFunction.h =================================================================== --- llvm/include/llvm/CodeGen/MachineFunction.h +++ llvm/include/llvm/CodeGen/MachineFunction.h @@ -28,6 +28,7 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/AtomicOrdering.h" @@ -414,16 +415,36 @@ assert(Arg < (1 << 16) && "Arg out of range"); } }; - /// Vector of call argument and its forwarding register. - using CallSiteInfo = SmallVector; - using CallSiteInfoImpl = SmallVectorImpl; + + struct CallSiteInfo { + /// Vector of call argument and its forwarding register. + SmallVector ArgRegPairs; + /// Callee type id. + ConstantInt *TypeId = nullptr; + + /// Extracts a generalized numeric type identifier of a CallBase's type from + /// type metadata. Returned object can be used to set TypeId. Returns null + /// if metadata cannot be found. + static ConstantInt *extractNumericCGTypeId(const CallBase &CB) { + const auto *MDN = CB.getMetadata(LLVMContext::MD_type); + if (MDN && MDN->getNumOperands() == 1) { + auto *TMDS = dyn_cast(MDN->getOperand(0)); + if (TMDS && TMDS->getString().endswith("generalized")) { + uint64_t TypeIdVal = llvm::MD5Hash(TMDS->getString()); + Type *Int64Ty = Type::getInt64Ty(CB.getContext()); + return cast(ConstantInt::get(Int64Ty, TypeIdVal)); + } + } + return nullptr; + } + }; private: Delegate *TheDelegate = nullptr; GISelChangeObserver *Observer = nullptr; using CallSiteInfoMap = DenseMap; - /// Map a call instruction to call site arguments forwarding info. + /// Map a call instruction to call site arguments forwarding and type id. CallSiteInfoMap CallSitesInfo; /// A helper function that returns call site info for a give call @@ -1172,9 +1193,8 @@ return VariableDbgInfos; } - /// Start tracking the arguments passed to the call \p CallI. - void addCallArgsForwardingRegs(const MachineInstr *CallI, - CallSiteInfoImpl &&CallInfo) { + /// Start tracking the arguments passed to the call \p CallI and call type. + void addCallSiteInfo(const MachineInstr *CallI, CallSiteInfo &&CallInfo) { assert(CallI->isCandidateForCallSiteEntry()); bool Inserted = CallSitesInfo.try_emplace(CallI, std::move(CallInfo)).second; Index: llvm/include/llvm/CodeGen/SelectionDAG.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAG.h +++ llvm/include/llvm/CodeGen/SelectionDAG.h @@ -266,7 +266,6 @@ SDDbgInfo *DbgInfo; using CallSiteInfo = MachineFunction::CallSiteInfo; - using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; struct CallSiteDbgInfo { CallSiteInfo CSInfo; @@ -1939,7 +1938,7 @@ isConstantFPBuildVectorOrConstantFP(N); } - void addCallSiteInfo(const SDNode *CallNode, CallSiteInfoImpl &&CallInfo) { + void addCallSiteInfo(const SDNode *CallNode, CallSiteInfo &&CallInfo) { SDCallSiteDbgInfo[CallNode].CSInfo = std::move(CallInfo); } Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -804,12 +804,14 @@ ParamSet &Params) { const MachineFunction *MF = CallMI->getMF(); const auto &CalleesMap = MF->getCallSitesInfo(); - auto CallFwdRegsInfo = CalleesMap.find(CallMI); + auto CallSiteInfo = CalleesMap.find(CallMI); // There is no information for the call instruction. - if (CallFwdRegsInfo == CalleesMap.end()) + if (CallSiteInfo == CalleesMap.end()) return; + auto CallFwdRegsInfo = CallSiteInfo->second.ArgRegPairs; + const MachineBasicBlock *MBB = CallMI->getParent(); // Skip the call instruction. @@ -821,7 +823,7 @@ DIExpression::get(MF->getFunction().getContext(), {}); // Add all the forwarding registers into the ForwardedRegWorklist. - for (const auto &ArgReg : CallFwdRegsInfo->second) { + for (const auto &ArgReg : CallFwdRegsInfo) { bool InsertedReg = ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}}) .second; Index: llvm/lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -401,14 +401,15 @@ Register Reg; if (parseNamedRegisterReference(PFS, Reg, ArgRegPair.Reg.Value, Error)) return error(Error, ArgRegPair.Reg.SourceRange); - CSInfo.emplace_back(Reg, ArgRegPair.ArgNo); + CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo); } - if (TM.Options.EmitCallSiteInfo) - MF.addCallArgsForwardingRegs(&*CallI, std::move(CSInfo)); + if (TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection) + MF.addCallSiteInfo(&*CallI, std::move(CSInfo)); } - if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo) + if (YamlMF.CallSitesInfo.size() && + !(TM.Options.EmitCallSiteInfo || TM.Options.EmitCallGraphSection)) return error(Twine("Call site info provided but not used")); return false; } Index: llvm/lib/CodeGen/MIRPrinter.cpp =================================================================== --- llvm/lib/CodeGen/MIRPrinter.cpp +++ llvm/lib/CodeGen/MIRPrinter.cpp @@ -519,7 +519,7 @@ std::distance(CallI->getParent()->instr_begin(), CallI); YmlCS.CallLocation = CallLocation; // Construct call arguments and theirs forwarding register info. - for (auto ArgReg : CSInfo.second) { + for (auto ArgReg : CSInfo.second.ArgRegPairs) { yaml::CallSiteInfo::ArgRegPair YmlArgReg; YmlArgReg.ArgNo = ArgReg.ArgNo; printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI); Index: llvm/lib/CodeGen/MachineFunction.cpp =================================================================== --- llvm/lib/CodeGen/MachineFunction.cpp +++ llvm/lib/CodeGen/MachineFunction.cpp @@ -897,7 +897,7 @@ assert(MI->isCandidateForCallSiteEntry() && "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); } Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -887,8 +887,9 @@ } if (MI->isCandidateForCallSiteEntry() && - DAG->getTarget().Options.EmitCallSiteInfo) - MF.addCallArgsForwardingRegs(MI, DAG->getSDCallSiteInfo(Node)); + (DAG->getTarget().Options.EmitCallSiteInfo || + DAG->getTarget().Options.EmitCallGraphSection)) + MF.addCallSiteInfo(MI, DAG->getSDCallSiteInfo(Node)); if (DAG->getNoMergeSiteInfo(Node)) { MI->setFlag(MachineInstr::MIFlag::NoMerge); Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5701,6 +5701,7 @@ bool &IsTailCall = CLI.IsTailCall; CallingConv::ID CallConv = CLI.CallConv; bool IsVarArg = CLI.IsVarArg; + const auto *CB = CLI.CB; MachineFunction &MF = DAG.getMachineFunction(); MachineFunction::CallSiteInfo CSInfo; @@ -5711,6 +5712,16 @@ bool IsSibCall = false; bool IsCalleeWin64 = Subtarget->isCallingConvWin64(CallConv); + // Set type id for call site info. + if (MF.getTarget().Options.EmitCallGraphSection && CB && + CB->isIndirectCall()) { + CSInfo.TypeId = MachineFunction::CallSiteInfo::extractNumericCGTypeId(*CB); + if (!CSInfo.TypeId) { + errs() << "warning: cannot find indirect call type id metadata for " + "call graph section\n"; + } + } + // Check callee args/returns for SVE registers and set calling convention // accordingly. if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) { @@ -5978,15 +5989,16 @@ // Call site info is used for function's parameter entry value // tracking. For now we track only simple cases when parameter // is transferred through whole register. - llvm::erase_if(CSInfo, [&VA](MachineFunction::ArgRegPair ArgReg) { - return ArgReg.Reg == VA.getLocReg(); - }); + llvm::erase_if(CSInfo.ArgRegPairs, + [&VA](MachineFunction::ArgRegPair ArgReg) { + return ArgReg.Reg == VA.getLocReg(); + }); } else { RegsToPass.emplace_back(VA.getLocReg(), Arg); RegsUsed.insert(VA.getLocReg()); const TargetOptions &Options = DAG.getTarget().Options; if (Options.EmitCallSiteInfo) - CSInfo.emplace_back(VA.getLocReg(), i); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i); } } else { assert(VA.isMemLoc()); Index: llvm/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2279,6 +2279,7 @@ CallingConv::ID CallConv = CLI.CallConv; bool doesNotRet = CLI.DoesNotReturn; bool isVarArg = CLI.IsVarArg; + const auto *CB = CLI.CB; MachineFunction &MF = DAG.getMachineFunction(); ARMFunctionInfo *AFI = MF.getInfo(); @@ -2289,6 +2290,16 @@ bool isSibCall = false; bool PreferIndirect = false; + // Set type id for call site info. + if (MF.getTarget().Options.EmitCallGraphSection && CB && + CB->isIndirectCall()) { + CSInfo.TypeId = MachineFunction::CallSiteInfo::extractNumericCGTypeId(*CB); + if (!CSInfo.TypeId) { + errs() << "warning: cannot find indirect call type id metadata for call " + "graph section\n"; + } + } + // Determine whether this is a non-secure function call. if (CLI.CB && CLI.CB->getAttributes().hasFnAttribute("cmse_nonsecure_call")) isCmseNSCall = true; @@ -2485,7 +2496,7 @@ } const TargetOptions &Options = DAG.getTarget().Options; if (Options.EmitCallSiteInfo) - CSInfo.emplace_back(VA.getLocReg(), i); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i); RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); } else if (isByVal) { assert(VA.isMemLoc()); Index: llvm/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -3148,6 +3148,7 @@ bool &IsTailCall = CLI.IsTailCall; CallingConv::ID CallConv = CLI.CallConv; bool IsVarArg = CLI.IsVarArg; + const auto *CB = CLI.CB; MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = MF.getFrameInfo(); @@ -3205,8 +3206,17 @@ // Get a count of how many bytes are to be pushed on the stack. unsigned NextStackOffset = CCInfo.getNextStackOffset(); - // Call site info for function parameters tracking. + // Call site info for function parameters tracking and call base type info. MachineFunction::CallSiteInfo CSInfo; + // Set type id for call site info. + if (MF.getTarget().Options.EmitCallGraphSection && CB && + CB->isIndirectCall()) { + CSInfo.TypeId = MachineFunction::CallSiteInfo::extractNumericCGTypeId(*CB); + if (!CSInfo.TypeId) { + errs() << "warning: cannot find indirect call type id metadata for call " + "graph section\n"; + } + } // Check if it's really possible to do a tail call. Restrict it to functions // that are part of this compilation unit. @@ -3343,7 +3353,7 @@ // Collect CSInfo about which register passes which parameter. const TargetOptions &Options = DAG.getTarget().Options; if (Options.SupportsDebugEntryValues) - CSInfo.emplace_back(VA.getLocReg(), i); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i); continue; } Index: llvm/lib/Target/X86/X86FastISel.cpp =================================================================== --- llvm/lib/Target/X86/X86FastISel.cpp +++ llvm/lib/Target/X86/X86FastISel.cpp @@ -3579,6 +3579,19 @@ CLI.NumResultRegs = RVLocs.size(); CLI.Call = MIB; + // Add call site information (only call type id for call graph section). + if (TM.Options.EmitCallGraphSection && CB && CB->isIndirectCall()) { + auto *TypeId = MachineFunction::CallSiteInfo::extractNumericCGTypeId(*CB); + if (TypeId) { + MachineFunction::CallSiteInfo CSInfo; + CSInfo.TypeId = TypeId; + MF->addCallSiteInfo(CLI.Call, std::move(CSInfo)); + } else { + errs() << "warning: cannot find indirect call type id metadata for call " + "graph section\n"; + } + } + return true; } @@ -3969,6 +3982,8 @@ MO.setReg(IndexReg); } + if (MI->isCall()) + FuncInfo.MF->moveCallSiteInfo(MI, Result); Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI)); Result->cloneInstrSymbols(*FuncInfo.MF, *MI); MachineBasicBlock::iterator I(MI); Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -3935,6 +3935,16 @@ if (CallConv == CallingConv::X86_INTR) report_fatal_error("X86 interrupts may not be called directly"); + // Set type id for call site info. + if (MF.getTarget().Options.EmitCallGraphSection && CB && + CB->isIndirectCall()) { + CSInfo.TypeId = MachineFunction::CallSiteInfo::extractNumericCGTypeId(*CB); + if (!CSInfo.TypeId) { + errs() << "warning: cannot find indirect call type id metadata for call " + "graph section\n"; + } + } + bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall(); if (Subtarget.isPICStyleGOT() && !IsGuaranteeTCO && !IsMustTail) { // If we are using a GOT, disable tail calls to external symbols with @@ -4140,7 +4150,7 @@ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); const TargetOptions &Options = DAG.getTarget().Options; if (Options.EmitCallSiteInfo) - CSInfo.emplace_back(VA.getLocReg(), I); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), I); if (isVarArg && IsWin64) { // Win64 ABI requires argument XMM reg to be copied to the corresponding // shadow reg if callee is a varargs function.