Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / test / API / lang / c / register_variables / TestRegisterVariables.py
blob0f91aa5d044eefa0da7c640533ddb4065fa469e9
1 """Check that compiler-generated register values work correctly"""
3 import re
4 import lldb
5 from lldbsuite.test.decorators import *
6 from lldbsuite.test.lldbtest import *
7 from lldbsuite.test import lldbutil
10 def re_expr_equals(val_type, val):
11 # Match ({val_type}) ${sum_digits} = {val}
12 return re.compile(r"\(" + val_type + "\) \$\d+ = " + str(val))
15 class RegisterVariableTestCase(TestBase):
16 @expectedFailureAll(compiler="clang", compiler_version=["<", "3.5"])
17 @expectedFailureAll(
18 compiler="gcc", compiler_version=[">=", "4.8.2"], archs=["i386"]
20 @expectedFailureAll(compiler="gcc", compiler_version=["<", "4.9"], archs=["x86_64"])
21 def test_and_run_command(self):
22 """Test expressions on register values."""
24 # This test now ensures that each probable
25 # register variable location is actually a register, and
26 # if so, whether we can print out the variable there.
27 # It only requires one of them to be handled in a non-error
28 # way.
29 register_variables_count = 0
31 self.build()
32 exe = self.getBuildArtifact("a.out")
33 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
35 # Break inside the main.
36 lldbutil.run_break_set_by_source_regexp(self, "break", num_expected_locations=3)
38 ####################
39 # First breakpoint
41 self.runCmd("run", RUN_SUCCEEDED)
43 # The stop reason of the thread should be breakpoint.
44 self.expect(
45 "thread list",
46 STOPPED_DUE_TO_BREAKPOINT,
47 substrs=["stopped", "stop reason = breakpoint"],
50 # The breakpoint should have a hit count of 1.
51 lldbutil.check_breakpoint(
52 self, bpno=1, location_id=1, expected_location_hit_count=1
55 # Try some variables that should be visible
56 frame = (
57 self.dbg.GetSelectedTarget()
58 .GetProcess()
59 .GetSelectedThread()
60 .GetSelectedFrame()
62 if self.is_variable_in_register(frame, "a"):
63 register_variables_count += 1
64 self.expect(
65 "expr a",
66 VARIABLES_DISPLAYED_CORRECTLY,
67 patterns=[re_expr_equals("int", 2)],
70 if self.is_struct_pointer_in_register(frame, "b", self.TraceOn()):
71 register_variables_count += 1
72 self.expect(
73 "expr b->m1",
74 VARIABLES_DISPLAYED_CORRECTLY,
75 patterns=[re_expr_equals("int", 3)],
78 #####################
79 # Second breakpoint
81 self.runCmd("continue")
83 # The stop reason of the thread should be breakpoint.
84 self.expect(
85 "thread list",
86 STOPPED_DUE_TO_BREAKPOINT,
87 substrs=["stopped", "stop reason = breakpoint"],
90 # The breakpoint should have a hit count of 1.
91 lldbutil.check_breakpoint(
92 self, bpno=1, location_id=2, expected_location_hit_count=1
95 # Try some variables that should be visible
96 frame = (
97 self.dbg.GetSelectedTarget()
98 .GetProcess()
99 .GetSelectedThread()
100 .GetSelectedFrame()
102 if self.is_struct_pointer_in_register(frame, "b", self.TraceOn()):
103 register_variables_count += 1
104 self.expect(
105 "expr b->m2",
106 VARIABLES_DISPLAYED_CORRECTLY,
107 patterns=[re_expr_equals("int", 5)],
110 if self.is_variable_in_register(frame, "c"):
111 register_variables_count += 1
112 self.expect(
113 "expr c",
114 VARIABLES_DISPLAYED_CORRECTLY,
115 patterns=[re_expr_equals("int", 5)],
118 #####################
119 # Third breakpoint
121 self.runCmd("continue")
123 # The stop reason of the thread should be breakpoint.
124 self.expect(
125 "thread list",
126 STOPPED_DUE_TO_BREAKPOINT,
127 substrs=["stopped", "stop reason = breakpoint"],
130 # The breakpoint should have a hit count of 1.
131 lldbutil.check_breakpoint(
132 self, bpno=1, location_id=3, expected_location_hit_count=1
135 # Try some variables that should be visible
136 frame = (
137 self.dbg.GetSelectedTarget()
138 .GetProcess()
139 .GetSelectedThread()
140 .GetSelectedFrame()
142 if self.is_variable_in_register(frame, "f"):
143 register_variables_count += 1
144 self.expect(
145 "expr f",
146 VARIABLES_DISPLAYED_CORRECTLY,
147 patterns=[re_expr_equals("float", "3.1")],
150 # Validate that we verified at least one register variable
151 self.assertTrue(
152 register_variables_count > 0,
153 "expected to verify at least one variable in a register",
155 self.trace(
156 "executed {} expressions with values in registers".format(
157 register_variables_count
161 self.runCmd("kill")
163 def is_variable_in_register(self, frame, var_name):
164 # Ensure we can lookup the variable.
165 var = frame.FindVariable(var_name)
166 self.trace("\nchecking {}...".format(var_name))
167 if var is None or not var.IsValid():
168 self.trace("{} cannot be found".format(var_name))
169 return False
171 # Check that we can get its value. If not, this
172 # may be a variable that is just out of scope at this point.
173 value = var.GetValue()
174 self.trace("checking value...")
175 if value is None:
176 self.trace("value is invalid")
177 return False
178 else:
179 self.trace("value is {}".format(value))
181 # We have a variable and we can get its value. The variable is in a
182 # register if we cannot get an address for it, assuming it is not a
183 # struct pointer. (This is an approximation - compilers can do other
184 # things with spitting up a value into multiple parts of multiple
185 # registers, but what we're verifying here is much more than it was
186 # doing before).
187 var_addr = var.GetAddress()
188 self.trace("checking address...")
189 if var_addr.IsValid():
190 # We have an address, it must not be in a register.
191 self.trace(
192 "var {} is not in a register: has a valid address {}".format(
193 var_name, var_addr
196 return False
197 else:
198 # We don't have an address but we can read the value.
199 # It is likely stored in a register.
200 self.trace(
201 "var {} is in a register (we don't have an address for it)".format(
202 var_name
205 return True
207 def is_struct_pointer_in_register(self, frame, var_name, trace):
208 # Ensure we can lookup the variable.
209 var = frame.FindVariable(var_name)
210 if trace:
211 print("\nchecking {}...".format(var_name))
213 if var is None or not var.IsValid():
214 self.trace("{} cannot be found".format(var_name))
215 return False
217 # Check that we can get its value. If not, this
218 # may be a variable that is just out of scope at this point.
219 value = var.GetValue()
220 self.trace("checking value...")
221 if value is None:
222 if trace:
223 print("value is invalid")
224 return False
225 else:
226 if trace:
227 print("value is {}".format(value))
229 var_loc = var.GetLocation()
230 if trace:
231 print("checking location: {}".format(var_loc))
232 if var_loc is None or var_loc.startswith("0x"):
233 # The frame var is not in a register but rather a memory location.
234 self.trace("frame var {} is not in a register".format(var_name))
235 return False
236 else:
237 self.trace("frame var {} is in a register".format(var_name))
238 return True