CCTLib
Calling-context and data-object attribution library for Intel Pin
rec_mixed_direct_indirect.cpp
Go to the documentation of this file.
1 // Same routine has BOTH a direct self-call and an indirect self-call.
2 // Verifies the two mechanisms are mutually orthogonal per the design:
3 // * direct site: hasSelfRec=true -> SetCallInitFlag suppressed ->
4 // splay/sibling-branch collapses activation in place.
5 // * indirect site: SetCallInitFlag fires as before -> new frame is
6 // allocated. From inside the new frame, further direct calls
7 // still collapse under that (new) frame.
8 // A regression where the two paths cross-contaminate would either
9 // blow up the CCT (direct sites not folding) or wrongly return past
10 // the indirect-frame boundary.
11 #include <cstdint>
12 #include <cstdio>
13 
14 static volatile uint64_t sink;
15 
16 typedef uint64_t (*RecFn)(int);
17 static RecFn g_next;
18 
19 static uint64_t mixed(int n) {
20  if (n <= 0) return 0;
21  // n % 4 == 0: indirect recursion (introduces a physical frame).
22  // otherwise: direct recursion (collapses in place).
23  if ((n % 5) == 0) {
24  return 1 + g_next(n - 1); // indirect self-call (~1 in 5)
25  }
26  return 1 + mixed(n - 1); // direct self-call
27 }
28 
29 int main(int argc, char** argv) {
30  (void)argc; (void)argv;
31  g_next = &mixed;
32  // depth 30 with every-5th indirect -> ~6 indirect physical frames
33  // (uncollapsed) plus ~24 direct-collapse steps folded into them.
34  // Under cctlib's MAX_CCT_PRINT_DEPTH=20 the deepest chain is
35  // main + 6 indirect frames + one collapsed direct-frame = 8.
36  uint64_t r = mixed(30);
37  sink ^= r;
38  fprintf(stderr, "rec_mixed_direct_indirect: r=%llu sink=%llx\n",
39  (unsigned long long)r, (unsigned long long)sink);
40  return r == 30 ? 0 : 1;
41 }
int main(int argc, char **argv)
static uint64_t mixed(int n)
static RecFn g_next
uint64_t(* RecFn)(int)
static volatile uint64_t sink