|
| 1 | +// Simple integration test for contextual instrumentation |
| 2 | +// |
| 3 | +// Copy the header defining ContextNode. |
| 4 | +// RUN: mkdir -p %t_include |
| 5 | +// RUN: cp %llvm_src/include/llvm/ProfileData/CtxInstrContextNode.h %t_include/ |
| 6 | +// |
| 7 | +// Compile with ctx instrumentation "on". We treat "the_root" as callgraph root. |
| 8 | +// RUN: %clangxx %s -lclang_rt.ctx_profile -I%t_include -O2 -o %t.bin -mllvm -profile-context-root=the_root |
| 9 | +// |
| 10 | +// Run the binary, and observe the profile fetch handler's output. |
| 11 | +// RUN: %t.bin | FileCheck %s |
| 12 | + |
| 13 | +#include "CtxInstrContextNode.h" |
| 14 | +#include <cstdio> |
| 15 | +#include <iostream> |
| 16 | + |
| 17 | +using namespace llvm::ctx_profile; |
| 18 | +extern "C" bool __llvm_ctx_profile_fetch(void *Data, |
| 19 | + bool (*Writer)(void *, |
| 20 | + const ContextNode &)); |
| 21 | + |
| 22 | +extern "C" { |
| 23 | +__attribute__((noinline)) void someFunction() { printf("check 2\n"); } |
| 24 | + |
| 25 | +// block inlining because the pre-inliner otherwise will inline this - it's |
| 26 | +// too small. |
| 27 | +__attribute__((noinline)) void the_root() { |
| 28 | + printf("check 1\n"); |
| 29 | + someFunction(); |
| 30 | + someFunction(); |
| 31 | +} |
| 32 | +} |
| 33 | + |
| 34 | +// Make sure the program actually ran correctly. |
| 35 | +// CHECK: check 1 |
| 36 | +// CHECK: check 2 |
| 37 | +// CHECK: check 2 |
| 38 | + |
| 39 | +void printProfile(const ContextNode &Node, const std::string &Indent, |
| 40 | + const std::string &Increment) { |
| 41 | + std::cout << Indent << "Guid: " << Node.guid() << std::endl; |
| 42 | + std::cout << Indent << "Entries: " << Node.entrycount() << std::endl; |
| 43 | + for (uint32_t I = 0U; I < Node.callsites_size(); ++I) |
| 44 | + for (const auto *N = Node.subContexts()[I]; N; N = N->next()) { |
| 45 | + std::cout << Indent << "At Index " << I << ":" << std::endl; |
| 46 | + printProfile(*N, Indent + Increment, Increment); |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +// CHECK: Guid: 11065787667334760794 |
| 51 | +// CHECK: Entries: 1 |
| 52 | +// CHECK: At Index 1: |
| 53 | +// CHECK: Guid: 6759619411192316602 |
| 54 | +// CHECK: Entries: 1 |
| 55 | +// CHECK: At Index 2: |
| 56 | +// CHECK: Guid: 6759619411192316602 |
| 57 | +// CHECK: Entries: 1 |
| 58 | + |
| 59 | +bool profileWriter() { |
| 60 | + return __llvm_ctx_profile_fetch( |
| 61 | + nullptr, +[](void *, const ContextNode &Node) { |
| 62 | + printProfile(Node, "", " "); |
| 63 | + return true; |
| 64 | + }); |
| 65 | +} |
| 66 | + |
| 67 | +int main(int argc, char **argv) { |
| 68 | + the_root(); |
| 69 | + // This would be implemented in a specific RPC handler, but here we just call |
| 70 | + // it directly. |
| 71 | + return !profileWriter(); |
| 72 | +} |
0 commit comments