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 (value&: argc); // At first call of caller_ref_1 in main. |
150 | |
151 | caller_ref_1 (value&: 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(lhs: 123, rhs: 456); // Call max_value template |
156 | max_value(lhs: std::string("abc" ), rhs: 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 | |