1 // Note: This test requires the SysV AMD64 ABI to be in use, and requires
2 // compiler support for DWARF entry values.
4 // Inhibit dead-arg-elim by using 'x'.
5 template<typename T> __attribute__((noinline)) void use(T x) {
13 // Destroy %rsi in the current frame.
15 asm volatile ("xorq %%rsi, %%rsi" \
18 /* Clobbers */ : "rsi" \
21 // Destroy %rbx in the current frame.
23 asm volatile ("xorq %%rbx, %%rbx" \
26 /* Clobbers */ : "rbx" \
31 int *field2 = &field1;
34 __attribute__((noinline))
35 void func1(int &sink, int x) {
38 // Destroy 'x' in the current frame.
41 // NOTE: Currently, we do not generate DW_OP_entry_value for the 'x',
42 // since it gets copied into a register that is not callee saved,
43 // and we can not guarantee that its value has not changed.
47 // Destroy 'sink' in the current frame.
50 //% self.filecheck("image lookup -va $pc", "main.cpp", "-check-prefix=FUNC1-DESC")
51 // FUNC1-DESC: name = "sink", type = "int &", location = DW_OP_entry_value(DW_OP_reg5 RDI)
54 __attribute__((noinline))
55 void func2(int &sink, int x) {
58 // Destroy 'x' in the current frame.
61 //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC2-EXPR-FAIL", expect_cmd_failure=True)
62 // FUNC2-EXPR-FAIL: couldn't get the value of variable x: variable not available
66 // Destroy 'sink' in the current frame.
69 //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC2-EXPR")
70 // FUNC2-EXPR: ${{.*}} = 2
73 __attribute__((noinline))
74 void func3(int &sink, int *p) {
77 // Destroy 'p' in the current frame.
80 //% self.filecheck("expr *p", "main.cpp", "-check-prefix=FUNC3-EXPR")
81 // FUNC3-EXPR: (int) ${{.*}} = 123
86 __attribute__((noinline))
87 void func4_amb(int &sink, int x) {
90 // Destroy 'x' in the current frame.
93 //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC4-EXPR-FAIL", expect_cmd_failure=True)
94 // FUNC4-EXPR-FAIL: couldn't get the value of variable x: variable not available
98 // Destroy 'sink' in the current frame.
101 //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC4-EXPR", expect_cmd_failure=True)
102 // FUNC4-EXPR: couldn't get the value of variable sink: Could not evaluate DW_OP_entry_value.
105 __attribute__((noinline))
108 __attribute__((noinline))
109 void func6(int &sink, int x) {
111 func4_amb(sink, x); /* tail (taken) */
113 func5_amb(); /* tail */
116 __attribute__((noinline))
117 void func7(int &sink, int x) {
118 //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC7-BT")
120 // FUNC7-BT-NEXT: [inlined] func8_inlined
121 // FUNC7-BT-NEXT: [inlined] func9_inlined
122 // FUNC7-BT-NEXT: func10
125 // Destroy 'x' in the current frame.
128 //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC7-EXPR-FAIL", expect_cmd_failure=True)
129 // FUNC7-EXPR-FAIL: couldn't get the value of variable x: variable not available
133 // Destroy 'sink' in the current frame.
136 //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC7-EXPR")
137 // FUNC7-EXPR: ${{.*}} = 4
140 __attribute__((always_inline))
141 void func8_inlined(int &sink, int x) {
145 __attribute__((always_inline))
146 void func9_inlined(int &sink, int x) {
147 func8_inlined(sink, x);
150 __attribute__((noinline, disable_tail_calls))
151 void func10(int &sink, int x) {
152 func9_inlined(sink, x);
155 __attribute__((noinline))
156 void func11_tailcalled(int &sink, int x) {
157 //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC11-BT")
158 // FUNC11-BT: func11_tailcalled{{.*}}
159 // FUNC11-BT-NEXT: func12{{.*}} [artificial]
162 // Destroy 'x' in the current frame.
165 //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC11-EXPR-FAIL", expect_cmd_failure=True)
166 // FUNC11-EXPR-FAIL: couldn't get the value of variable x: variable not available
170 // Destroy 'sink' in the current frame.
173 //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC11-EXPR")
174 // FUNC11-EXPR: ${{.*}} = 5
177 __attribute__((noinline))
178 void func12(int &sink, int x) {
179 func11_tailcalled(sink, x);
182 __attribute__((noinline))
183 void func13(int &sink, int x) {
184 //% self.filecheck("bt", "main.cpp", "-check-prefix=FUNC13-BT")
185 // FUNC13-BT: func13{{.*}}
186 // FUNC13-BT-NEXT: func14{{.*}}
189 // Destroy 'x' in the current frame.
192 //% self.filecheck("expr x", "main.cpp", "-check-prefix=FUNC13-EXPR-FAIL", expect_cmd_failure=True)
193 // FUNC13-EXPR-FAIL: couldn't get the value of variable x: variable not available
197 // Destroy 'sink' in the current frame.
200 //% self.filecheck("expr sink", "main.cpp", "-check-prefix=FUNC13-EXPR")
201 // FUNC13-EXPR: ${{.*}} = 5
204 __attribute__((noinline, disable_tail_calls))
205 void func14(int &sink, void (*target_no_tailcall)(int &, int)) {
206 // Move the call target into a register that won't get clobbered. Do this
207 // by calling the same indirect target twice, and hoping that regalloc is
208 // 'smart' enough to stash the call target in a non-clobbered register.
210 // llvm.org/PR43926 tracks work in the compiler to emit call targets which
211 // describe non-clobbered values.
212 target_no_tailcall(sink, 123);
213 target_no_tailcall(sink, 123);
216 __attribute__((disable_tail_calls))
221 // Test location dumping for DW_OP_entry_value.
224 // Test evaluation of "DW_OP_constu" in the parent frame.
227 // Test evaluation of "DW_OP_fbreg -24, DW_OP_deref" in the parent frame.
228 // Disabled for now, see: llvm.org/PR43343
230 func3(sink, s1.field2);
233 // The sequences `main -> func4 -> func{5,6}_amb -> sink` are both plausible.
234 // Test that lldb doesn't attempt to guess which one occurred: entry value
235 // evaluation should fail.
238 // Test that evaluation can "see through" inlining.
241 // Test that evaluation can "see through" tail calls.
244 // Test that evaluation can "see through" an indirect tail call.
245 func14(sink, func13);