31#define DEBUG_TYPE "mcpseudoprobe"
55 assert((LastProbe || IsSentinel) &&
56 "Last probe should not be null for non-sentinel probes");
65 assert(
Type <= 0xF &&
"Probe type too big to encode, exceeding 15");
69 assert(NewAttributes <= 0x7 &&
70 "Probe attributes too big to encode, exceeding 7");
85 F->makeLEB(
true, AddrDelta);
120 if (InlineStack.
empty()) {
130 if (!InlineStack.
empty()) {
131 auto Iter = InlineStack.
begin();
132 auto Index = std::get<1>(*Iter);
134 for (; Iter != InlineStack.
end(); Iter++) {
136 Cur = Cur->getOrAddNode(
InlineSite(std::get<0>(*Iter), Index));
137 Index = std::get<1>(*Iter);
142 Cur->Probes.push_back(Probe);
149 dbgs() <<
"Group [\n";
152 assert(!
isRoot() &&
"Root should be handled separately");
163 bool NeedSentinel =
false;
166 "Starting probe of a top-level function should be a sentinel probe");
177 LastProbe->
emit(MCOS,
nullptr);
180 for (
const auto &Probe :
Probes) {
181 Probe.emit(MCOS, LastProbe);
187 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
188 std::vector<InlineeType> Inlinees;
190 Inlinees.emplace_back(Child.first, Child.second.get());
193 for (
const auto &Inlinee : Inlinees) {
198 dbgs() <<
"InlineSite: " << std::get<1>(Inlinee.first) <<
"\n";
201 Inlinee.second->emit(MCOS, LastProbe);
214 Vec.
reserve(MCProbeDivisions.size());
215 for (
auto &ProbeSec : MCProbeDivisions)
218 I.value().setOrdinal(
I.index());
220 return A.first->getSection().getOrdinal() <
221 B.first->getSection().getOrdinal();
223 for (
auto [FuncSym, RootPtr] : Vec) {
224 const auto &Root = *RootPtr;
225 if (
auto *S = Ctx.getObjectFileInfo()->getPseudoProbeSection(
226 FuncSym->getSection())) {
232 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
233 std::vector<InlineeType> Inlinees;
234 for (
const auto &Child : Root.getChildren())
235 Inlinees.emplace_back(Child.first, Child.second.get());
238 for (
const auto &Inlinee : Inlinees) {
246 Inlinee.second->emit(MCOS, Probe);
262 if (ProbeSections.empty())
268 ProbeSections.emit(MCOS);
273 auto It = GUID2FuncMAP.
find(GUID);
274 assert(It != GUID2FuncMAP.end() &&
275 "Probe function must exist for a valid GUID");
298 std::reverse(ContextStack.
begin() + Begin, ContextStack.
end());
303 std::ostringstream OContextStr;
306 for (
auto &Cxt : ContextStack) {
307 if (OContextStr.str().size())
308 OContextStr <<
" @ ";
309 OContextStr << Cxt.first.str() <<
":" << Cxt.second;
311 return OContextStr.str();
319 bool ShowName)
const {
323 OS << FuncName.
str() <<
" ";
327 OS <<
"Index: " <<
Index <<
" ";
332 if (InlineContextStr.size()) {
334 OS << InlineContextStr;
339template <
typename T>
ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
340 if (
Data +
sizeof(
T) > End) {
341 return std::error_code();
347template <
typename T>
ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
348 unsigned NumBytesRead = 0;
350 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
351 return std::error_code();
353 Data += NumBytesRead;
354 return ErrorOr<T>(
static_cast<T>(Val));
357template <
typename T>
ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
358 unsigned NumBytesRead = 0;
360 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
361 return std::error_code();
363 Data += NumBytesRead;
364 return ErrorOr<T>(
static_cast<T>(Val));
368 StringRef Str(
reinterpret_cast<const char *
>(Data),
Size);
369 if (Data +
Size > End) {
370 return std::error_code();
373 return ErrorOr<StringRef>(Str);
396 if (!readUnencodedNumber<uint64_t>())
399 if (!readUnencodedNumber<uint64_t>())
402 auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
403 if (!ErrorOrNameSize)
406 if (!readString(*ErrorOrNameSize))
410 assert(Data == End &&
"Have unprocessed data in pseudo_probe_desc section");
411 GUID2FuncDescMap.reserve(FuncDescCount);
425 GUID2FuncDescMap.emplace_back(
426 GUID, Hash, IsMMapped ? Name : Name.copy(FuncNameAllocator));
428 assert(Data == End &&
"Have unprocessed data in pseudo_probe_desc section");
429 assert(GUID2FuncDescMap.size() == FuncDescCount &&
430 "Mismatching function description count pre- and post-parsing");
431 llvm::sort(GUID2FuncDescMap, [](
const auto &LHS,
const auto &RHS) {
432 return LHS.FuncGUID < RHS.FuncGUID;
437template <
bool IsTopLevelFunc>
440 const Uint64Set &GuidFilter,
const Uint64Map &FuncStartAddrs,
446 if (IsTopLevelFunc) {
448 Index = CurChildIndex;
458 if (IsTopLevelFunc && !GuidFilter.empty() && !GuidFilter.count(
Guid))
467 if (IsTopLevelFunc && !EncodingIsAddrBased) {
468 if (
auto V = FuncStartAddrs.lookup(
Guid))
476 uint32_t CurrentProbeCount = 0;
478 uint32_t ChildrenToProcess =
481 for (std::size_t
I = 0;
I < NodeCount;
I++) {
488 uint8_t Attr = (
Value & 0x70) >> 4;
499 if (
auto V = FuncStartAddrs.lookup(Addr))
506 EncodingIsAddrBased =
true;
527 InlineTreeVec.resize(InlineTreeVec.size() + ChildrenToProcess);
531 for (uint32_t
I = 0;
I < ChildrenToProcess;
I++) {
537template <
bool IsTopLevelFunc>
543 if (!readUnsignedNumber<uint32_t>())
547 auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
553 if (IsTopLevelFunc) {
561 auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
562 if (!ErrorOrNodeCount)
564 uint32_t NodeCount = std::move(*ErrorOrNodeCount);
568 auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
569 if (!ErrorOrCurChildrenToProcess)
571 uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
574 for (std::size_t
I = 0;
I < NodeCount;
I++) {
576 if (!readUnsignedNumber<uint32_t>())
580 auto ErrorOrValue = readUnencodedNumber<uint8_t>();
588 if (!readSignedNumber<int64_t>())
592 if (!readUnencodedNumber<int64_t>())
598 if (!readUnsignedNumber<uint32_t>())
606 ProbeCount += CurrentProbeCount;
607 InlinedCount += ChildrenToProcess;
626 bool Discard =
false;
630 TopLevelFuncs += !Discard;
632 assert(Data == End &&
"Have unprocessed data in pseudo_probe section");
633 PseudoProbeVec.reserve(ProbeCount);
634 InlineTreeVec.reserve(InlinedCount);
637 InlineTreeVec.resize(TopLevelFuncs);
646 &DummyInlineRoot, LastAddr, GuidFilter, FuncStartAddrs, CurChildIndex);
647 assert(Data == End &&
"Have unprocessed data in pseudo_probe section");
648 assert(PseudoProbeVec.size() == ProbeCount &&
649 "Mismatching probe count pre- and post-parsing");
650 assert(InlineTreeVec.size() == InlinedCount &&
651 "Mismatching function records count pre- and post-parsing");
653 std::vector<std::pair<uint64_t, uint32_t>> SortedA2P(ProbeCount);
655 SortedA2P[
I] = {Probe.getAddress(),
I};
657 Address2ProbesMap.reserve(ProbeCount);
659 Address2ProbesMap.emplace_back(PseudoProbeVec[
I]);
665 OS <<
"Pseudo Probe Desc:\n";
666 for (
auto &
I : GUID2FuncDescMap)
674 Probe.print(OS, GUID2FuncDescMap,
true);
684 OS <<
"Address:\t" <<
Address <<
'\n';
687 Probe.print(OS, GUID2FuncDescMap,
true);
695 if (Probe.isCall()) {
717 auto It = GUID2FuncDescMap.find(GUID);
718 assert(It != GUID2FuncDescMap.end() &&
"Function descriptor doesn't exist");
725 bool IncludeLeaf)
const {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static const MCExpr * buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A, const MCSymbol *B, SMLoc Loc)
static const char * PseudoProbeTypeStr[3]
static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP, uint64_t GUID)
static const MCExpr * buildSymbolDiff(MCObjectStreamer *MCOS, const MCSymbol *A, const MCSymbol *B)
Represents either an error or a value T.
auto find(uint64_t GUID) const
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Context object for machine code objects.
MCPseudoProbeTable & getMCPseudoProbeTable()
InlineSite getInlineSite() const
bool hasInlineSite() const
void setProbes(MutableArrayRef< MCDecodedPseudoProbe > ProbesRef)
LLVM_ABI void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP, bool ShowName) const
LLVM_ABI uint64_t getGuid() const
LLVM_ABI std::string getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const
MCDecodedPseudoProbeInlineTree * getInlineTreeNode() const
LLVM_ABI void getInlineContext(SmallVectorImpl< MCPseudoProbeFrameLocation > &ContextStack, const GUIDProbeFunctionMap &GUID2FuncMAP) const
Base class for the full range of assembler expressions which are needed for parsing.
Streaming object file generation interface.
MCAssembler & getAssembler()
MCAssembler * getAssemblerPtr() override
uint32_t getIndex() const
uint8_t getAttributes() const
DenseSet< uint64_t > Uint64Set
LLVM_ABI bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size, const Uint64Set &GuildFilter, const Uint64Map &FuncStartAddrs)
LLVM_ABI void printProbesForAllAddresses(raw_ostream &OS)
LLVM_ABI void printGUID2FuncDescMap(raw_ostream &OS)
DenseMap< uint64_t, uint64_t > Uint64Map
LLVM_ABI bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size, bool IsMMapped=false)
LLVM_ABI void printProbeForAddress(raw_ostream &OS, uint64_t Address)
LLVM_ABI void getInlineContextForProbe(const MCDecodedPseudoProbe *Probe, SmallVectorImpl< MCPseudoProbeFrameLocation > &InlineContextStack, bool IncludeLeaf) const
LLVM_ABI const MCPseudoProbeFuncDesc * getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const
bool countRecords(bool &Discard, uint32_t &ProbeCount, uint32_t &InlinedCount, const Uint64Set &GuidFilter)
LLVM_ABI const MCDecodedPseudoProbe * getCallProbeForAddr(uint64_t Address) const
LLVM_ABI const MCPseudoProbeFuncDesc * getFuncDescForGUID(uint64_t GUID) const
std::unordered_map< InlineSite, std::unique_ptr< MCPseudoProbeInlineTree >, InlineSiteHash > Children
MCPseudoProbeInlineTree * getOrAddNode(const InlineSite &Site)
std::vector< MCPseudoProbe > Probes
MCPseudoProbeInlineTreeBase< std::vector< MCPseudoProbe >, MCPseudoProbeInlineTree, std::unordered_map< InlineSite, std::unique_ptr< MCPseudoProbeInlineTree >, InlineSiteHash > > * Parent
InlinedProbeTreeMap & getChildren()
LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe)
LLVM_ABI void addPseudoProbe(const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack)
LLVM_ABI void emit(MCObjectStreamer *MCOS)
MCPseudoProbeSections & getProbeSections()
static int DdgPrintIndent
static LLVM_ABI void emit(MCObjectStreamer *MCOS)
Instances of this class represent a pseudo probe instance for a pseudo probe table entry,...
MCSymbol * getLabel() const
LLVM_ABI void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const
MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attributes, uint32_t Discriminator)
MCFragment * getCurrentFragment() const
MCContext & getContext() const
unsigned emitULEB128IntValue(uint64_t Value, unsigned PadTo=0)
Special case of EmitULEB128Value that avoids the client having to pass in a MCExpr for constant integ...
void emitInt64(uint64_t Value)
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
unsigned emitSLEB128IntValue(int64_t Value)
Special case of EmitSLEB128Value that avoids the client having to pass in a MCExpr for constant integ...
void emitInt8(uint64_t Value)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MutableArrayRef< T > take_back(size_t N=1) const
Return a copy of *this with only the last N elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
LLVM Value Representation.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
constexpr size_t NameSize
uint64_t MD5Hash(const FunctionId &Obj)
value_type readNext(const CharT *&memory, endianness endian)
Read a value of a particular endianness from a buffer, and increment the buffer past that value.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
static bool isSentinelProbe(uint32_t Flags)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
std::tuple< uint64_t, uint32_t > InlineSite
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
std::pair< StringRef, uint32_t > MCPseudoProbeFrameLocation
void sort(IteratorTy Start, IteratorTy End)
SmallVector< InlineSite, 8 > MCPseudoProbeInlineStack
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static bool hasDiscriminator(uint32_t Flags)
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
LLVM_ABI void print(raw_ostream &OS)
Function object to check whether the first component of a container supported by std::get (like std::...