31#define DEBUG_TYPE "mcpseudoprobe"
34using namespace support;
54 assert((LastProbe || IsSentinel) &&
55 "Last probe should not be null for non-sentinel probes");
64 assert(
Type <= 0xF &&
"Probe type too big to encode, exceeding 15");
68 assert(NewAttributes <= 0x7 &&
69 "Probe attributes too big to encode, exceeding 7");
70 uint8_t PackedType =
Type | (NewAttributes << 4);
117 if (InlineStack.
empty()) {
127 if (!InlineStack.
empty()) {
128 auto Iter = InlineStack.
begin();
129 auto Index = std::get<1>(*Iter);
131 for (; Iter != InlineStack.
end(); Iter++) {
134 Index = std::get<1>(*Iter);
139 Cur->Probes.push_back(Probe);
146 dbgs() <<
"Group [\n";
149 assert(!
isRoot() &&
"Root should be handled seperately");
160 bool NeedSentinel =
false;
163 "Starting probe of a top-level function should be a sentinel probe");
174 LastProbe->
emit(MCOS,
nullptr);
177 for (
const auto &Probe :
Probes) {
178 Probe.emit(MCOS, LastProbe);
184 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
185 auto Comparer = [](
const InlineeType &
A,
const InlineeType &
B) {
186 return A.first <
B.first;
188 std::vector<InlineeType> Inlinees;
190 Inlinees.emplace_back(Child.first, Child.second.get());
191 std::sort(Inlinees.begin(), Inlinees.end(), Comparer);
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;
226 FuncSym->getSection())) {
232 using InlineeType = std::pair<InlineSite, MCPseudoProbeInlineTree *>;
233 auto Comparer = [](
const InlineeType &
A,
const InlineeType &
B) {
234 return A.first <
B.first;
236 std::vector<InlineeType> Inlinees;
237 for (
const auto &Child : Root.getChildren())
238 Inlinees.emplace_back(Child.first, Child.second.get());
239 std::sort(Inlinees.begin(), Inlinees.end(), Comparer);
241 for (
const auto &Inlinee : Inlinees) {
249 Inlinee.second->emit(MCOS, Probe);
265 if (ProbeSections.empty())
271 ProbeSections.emit(MCOS);
276 auto It = GUID2FuncMAP.
find(GUID);
277 assert(It != GUID2FuncMAP.end() &&
278 "Probe function must exist for a valid GUID");
279 return It->second.FuncName;
301 std::reverse(ContextStack.
begin() + Begin, ContextStack.
end());
306 std::ostringstream OContextStr;
309 for (
auto &Cxt : ContextStack) {
310 if (OContextStr.str().size())
311 OContextStr <<
" @ ";
312 OContextStr << Cxt.first.str() <<
":" << Cxt.second;
314 return OContextStr.str();
322 bool ShowName)
const {
326 OS << FuncName.
str() <<
" ";
330 OS <<
"Index: " <<
Index <<
" ";
335 if (InlineContextStr.size()) {
337 OS << InlineContextStr;
342template <
typename T>
ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
343 if (Data +
sizeof(
T) > End) {
344 return std::error_code();
346 T Val = endian::readNext<T, llvm::endianness::little, unaligned>(Data);
350template <
typename T>
ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
351 unsigned NumBytesRead = 0;
353 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
354 return std::error_code();
356 Data += NumBytesRead;
360template <
typename T>
ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
361 unsigned NumBytesRead = 0;
363 if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
364 return std::error_code();
366 Data += NumBytesRead;
372 if (Data +
Size > End) {
373 return std::error_code();
396 auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
400 auto ErrorOrHash = readUnencodedNumber<uint64_t>();
404 auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
405 if (!ErrorOrNameSize)
409 auto ErrorOrName = readString(
NameSize);
413 uint64_t GUID = std::move(*ErrorOrGUID);
414 uint64_t Hash = std::move(*ErrorOrHash);
420 assert(Data == End &&
"Have unprocessed data in pseudo_probe_desc section");
431 bool IsTopLevelFunc = Cur == &DummyInlineRoot;
432 if (IsTopLevelFunc) {
437 auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
440 Index = std::move(*ErrorOrIndex);
444 auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
447 uint64_t Guid = std::move(*ErrorOrCurGuid);
450 if (IsTopLevelFunc && !GuidFilter.
empty() && !GuidFilter.
count(Guid))
458 if (IsTopLevelFunc && !EncodingIsAddrBased) {
459 if (
auto V = FuncStartAddrs.
lookup(Guid))
465 auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
466 if (!ErrorOrNodeCount)
468 uint32_t NodeCount = std::move(*ErrorOrNodeCount);
470 auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
471 if (!ErrorOrCurChildrenToProcess)
474 for (std::size_t
I = 0;
I < NodeCount;
I++) {
476 auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
481 auto ErrorOrValue = readUnencodedNumber<uint8_t>();
484 uint8_t
Value = std::move(*ErrorOrValue);
485 uint8_t Kind =
Value & 0xf;
486 uint8_t Attr = (
Value & 0x70) >> 4;
490 auto ErrorOrOffset = readSignedNumber<int64_t>();
493 int64_t
Offset = std::move(*ErrorOrOffset);
496 auto ErrorOrAddr = readUnencodedNumber<int64_t>();
499 Addr = std::move(*ErrorOrAddr);
510 EncodingIsAddrBased =
true;
516 auto ErrorOrDiscriminator = readUnsignedNumber<uint32_t>();
517 if (!ErrorOrDiscriminator)
519 Discriminator = std::move(*ErrorOrDiscriminator);
524 auto &Probes = Address2ProbesMap[
Addr];
532 uint32_t ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
541 const uint8_t *Start, std::size_t
Size,
const Uint64Set &GuidFilter,
549 assert(Data == End &&
"Have unprocessed data in pseudo_probe section");
554 OS <<
"Pseudo Probe Desc:\n";
556 std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
557 GUID2FuncDescMap.end());
558 for (
auto &
I : OrderedMap) {
565 auto It = Address2ProbesMap.find(
Address);
566 if (It != Address2ProbesMap.end()) {
567 for (
auto &Probe : It->second) {
569 Probe.print(
OS, GUID2FuncDescMap,
true);
578 for (
auto K : Addresses) {
588 auto It = Address2ProbesMap.find(
Address);
589 if (It == Address2ProbesMap.end())
591 const auto &Probes = It->second;
594 for (
const auto &Probe : Probes) {
595 if (Probe.isCall()) {
617 auto It = GUID2FuncDescMap.find(GUID);
618 assert(It != GUID2FuncDescMap.end() &&
"Function descriptor doesn't exist");
625 bool IncludeLeaf)
const {
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Represents either an error or a value T.
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Context object for machine code objects.
MCPseudoProbeTable & getMCPseudoProbeTable()
const MCObjectFileInfo * getObjectFileInfo() const
bool hasInlineSite() const
void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP, bool ShowName) const
std::string getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const
void getInlineContext(SmallVectorImpl< MCPseduoProbeFrameLocation > &ContextStack, const GUIDProbeFunctionMap &GUID2FuncMAP) const
MCDecodedPseudoProbeInlineTree * getInlineTreeNode() const
Base class for the full range of assembler expressions which are needed for parsing.
MCSection * getPseudoProbeSection(const MCSection &TextSec) const
Streaming object file generation interface.
MCAssembler & getAssembler()
MCAssembler * getAssemblerPtr() override
void insert(MCFragment *F)
uint8_t getAttributes() const
uint64_t getIndex() const
bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size, const Uint64Set &GuildFilter, const Uint64Map &FuncStartAddrs)
void getInlineContextForProbe(const MCDecodedPseudoProbe *Probe, SmallVectorImpl< MCPseduoProbeFrameLocation > &InlineContextStack, bool IncludeLeaf) const
void printProbesForAllAddresses(raw_ostream &OS)
bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size)
void printGUID2FuncDescMap(raw_ostream &OS)
void printProbeForAddress(raw_ostream &OS, uint64_t Address)
const MCPseudoProbeFuncDesc * getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const
const MCDecodedPseudoProbe * getCallProbeForAddr(uint64_t Address) const
const MCPseudoProbeFuncDesc * getFuncDescForGUID(uint64_t GUID) const
InlinedProbeTreeMap & getChildren()
MCPseudoProbeInlineTreeBase< MCPseudoProbe, MCPseudoProbeInlineTree > * Parent
void addProbes(ProbeType Probe)
MCPseudoProbeInlineTree * getOrAddNode(const InlineSite &Site)
std::vector< MCPseudoProbe > Probes
InlinedProbeTreeMap Children
void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe)
void addPseudoProbe(const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack)
void emit(MCObjectStreamer *MCOS)
MCPseudoProbeSections & getProbeSections()
static int DdgPrintIndent
static void emit(MCObjectStreamer *MCOS)
Instances of this class represent a pseudo probe instance for a pseudo probe table entry,...
MCSymbol * getLabel() const
void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) 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, const MCExpr *Subsection=nullptr)
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)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
The instances of the Type class are immutable: once they are created, they are never changed.
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)
This is an optimization pass for GlobalISel generic memory operations.
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 are tuples (A,...
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.
std::pair< StringRef, uint32_t > MCPseduoProbeFrameLocation
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.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
static bool hasDiscriminator(uint32_t Flags)
std::unordered_map< uint64_t, MCPseudoProbeFuncDesc > GUIDProbeFunctionMap
void print(raw_ostream &OS)