xref: /llvm-project/lldb/test/API/functionalities/inline-stepping/calling.cpp (revision 3243e3d8872585091d65ea7ff0639155b4c1dd7a)
1 #include <algorithm>
2 #include <cstdio>
3 #include <string>
4 
5 inline int inline_ref_1 (int &value) __attribute__((always_inline));
6 inline int inline_ref_2 (int &value) __attribute__((always_inline));
7 
8 int caller_ref_1 (int &value);
9 int caller_ref_2 (int &value);
10 
11 int called_by_inline_ref (int &value);
12 
13 inline void inline_trivial_1 () __attribute__((always_inline));
14 inline void inline_trivial_2 () __attribute__((always_inline));
15 
16 // These three should share the same initial pc so we can test
17 // virtual inline stepping.
18 inline void caller_trivial_inline_1() __attribute__((always_inline));
19 inline void caller_trivial_inline_2() __attribute__((always_inline));
20 inline void caller_trivial_inline_3() __attribute__((always_inline));
21 
22 void caller_trivial_1 ();
23 void caller_trivial_2 ();
24 
25 void called_by_inline_trivial ();
26 
27 static int inline_value;
28 
29 int
30 function_to_call ()
31 {
32     return inline_value;
33 }
34 
35 int
36 caller_ref_1 (int &value)
37 {
38     int increment = caller_ref_2(value); // In caller_ref_1.
39     value += increment; // At increment in caller_ref_1.
40     return value;
41 }
42 
43 int
44 caller_ref_2 (int &value)
45 {
46     int increment = inline_ref_1 (value); // In caller_ref_2.
47     value += increment;  // At increment in caller_ref_2.
48     return value;
49 }
50 
51 int
52 called_by_inline_ref (int &value)
53 {
54     value += 1; // In called_by_inline_ref.
55     return value;
56 }
57 
58 int
59 inline_ref_1 (int &value)
60 {
61     int increment = inline_ref_2(value); // In inline_ref_1.
62     value += increment; // At increment in inline_ref_1.
63     return value;
64 }
65 
66 int
67 inline_ref_2 (int &value)
68 {
69     int increment = called_by_inline_ref (value);  // In inline_ref_2.
70     value += 1; // At increment in inline_ref_2.
71     return value;
72 }
73 
74 void
75 caller_trivial_1 ()
76 {
77     caller_trivial_2(); // In caller_trivial_1.
78     inline_value += 1;
79 }
80 
81 void
82 caller_trivial_2 ()
83 {
84     asm volatile ("nop"); inline_trivial_1 (); // In caller_trivial_2.
85     inline_value += 1;  // At increment in caller_trivial_2.
86 }
87 
88 // When you call caller_trivial_inline_1, the inlined call-site
89 // should share a PC with all three of the following inlined
90 // functions, so we can exercise "virtual inline stepping".
91 void caller_trivial_inline_1() {
92   caller_trivial_inline_2(); // In caller_trivial_inline_1.
93   inline_value += 1;
94 }
95 
96 void caller_trivial_inline_2() {
97   caller_trivial_inline_3(); // In caller_trivial_inline_2.
98   inline_value += 1;         // After caller_trivial_inline_3
99 }
100 
101 void caller_trivial_inline_3() {
102   inline_value += 1; // In caller_trivial_inline_3.
103 }
104 
105 void
106 called_by_inline_trivial ()
107 {
108     inline_value += 1; // In called_by_inline_trivial.
109 }
110 
111 void
112 inline_trivial_1 ()
113 {
114     asm volatile ("nop"); inline_trivial_2(); // In inline_trivial_1.
115     inline_value += 1;  // At increment in inline_trivial_1.
116 }
117 
118 void
119 inline_trivial_2 ()
120 {
121     inline_value += 1; // In inline_trivial_2.
122     called_by_inline_trivial (); // At caller_by_inline_trivial in inline_trivial_2.
123 }
124 
125 template<typename T> T
126 max_value(const T& lhs, const T& rhs)
127 {
128     return std::max(lhs, rhs); // In max_value template
129 }
130 
131 template<> std::string
132 max_value(const std::string& lhs, const std::string& rhs)
133 {
134     return (lhs.size() > rhs.size()) ? lhs : rhs; // In max_value specialized
135 }
136 
137 int
138 main (int argc, char **argv)
139 {
140 
141     inline_value = 0;    // Stop here and step over to set up stepping over.
142 
143     inline_trivial_1 ();    // At inline_trivial_1 called from main.
144 
145     caller_trivial_1();     // At first call of caller_trivial_1 in main.
146 
147     caller_trivial_1();     // At second call of caller_trivial_1 in main.
148 
149     caller_ref_1 (argc); // At first call of caller_ref_1 in main.
150 
151     caller_ref_1 (argc); // At second call of caller_ref_1 in main.
152 
153     function_to_call (); // Make sure debug info for this function gets generated.
154 
155     max_value(123, 456);                                // Call max_value template
156     max_value(std::string("abc"), std::string("0022")); // Call max_value specialized
157 
158     caller_trivial_inline_1(); // At caller_trivial_inline_1.
159 
160     return 0;            // About to return from main.
161 }
162