[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / cross-project-tests / debuginfo-tests / dexter / README.md
blob1da6fa160273281d4544fb7374c90e83b9ec82c6
1 # DExTer (Debugging Experience Tester)
3 ## Introduction
5 DExTer is a suite of tools used to evaluate the "User Debugging Experience". DExTer drives an external debugger, running on small test programs, and collects information on the behavior at each debugger step to provide quantitative values that indicate the quality of the debugging experience.
7 ## Supported Debuggers
9 DExTer currently supports the Visual Studio 2015 and Visual Studio 2017 debuggers via the [DTE interface](https://docs.microsoft.com/en-us/dotnet/api/envdte.dte), and LLDB via its [Python interface](https://lldb.llvm.org/python-reference.html). GDB is not currently supported.
11 The following command evaluates your environment, listing the available and compatible debuggers:
13     dexter.py list-debuggers
15 ## Dependencies
16 [TODO] Add a requirements.txt or an install.py and document it here.
18 ### Python 3.6
20 DExTer requires python version 3.6 or greater.
22 ### pywin32 python package
24 This is required to access the DTE interface for the Visual Studio debuggers.
26     <python-executable> -m pip install pywin32
28 ### clang
30 DExTer is current compatible with 'clang' and 'clang-cl' compiler drivers.  The compiler must be available for DExTer, for example the following command should successfully build a runnable executable.
32      <compiler-executable> tests/nostdlib/fibonacci/test.cpp
34 ## Running a test case
36 The following DExTer commands build the test.cpp from the tests/nostdlib/fibonacci directory and quietly runs it on the Visual Studio debugger, reporting the debug experience heuristic.  The first command builds with no optimizations (/Od) and scores 1.0000.  The second command builds with optimizations (/Ox) and scores 0.2832 which suggests a worse debugging experience.
38     dexter.py test --builder clang-cl_vs2015 --debugger vs2017 --cflags="/Od /Zi" --ldflags="/Zi" -- tests/nostdlib/fibonacci
39     fibonacci = (1.0000)
41     dexter.py test --builder clang-cl_vs2015 --debugger vs2017 --cflags="/Ox /Zi" --ldflags="/Zi" -- tests/nostdlib/fibonacci
42     fibonacci = (0.2832)
44 ## An example test case
46 The sample test case (tests/nostdlib/fibonacci) looks like this:
48     1.  #ifdef _MSC_VER
49     2.  # define DEX_NOINLINE __declspec(noinline)
50     3.  #else
51     4.  # define DEX_NOINLINE __attribute__((__noinline__))
52     5.  #endif
53     6.
54     7.  DEX_NOINLINE
55     8.  void Fibonacci(int terms, int& total)
56     9.  {
57     0.      int first = 0;
58     11.     int second = 1;
59     12.     for (int i = 0; i < terms; ++i)
60     13.     {
61     14.         int next = first + second; // DexLabel('start')
62     15.         total += first;
63     16.         first = second;
64     17.         second = next;             // DexLabel('end')
65     18.     }
66     19. }
67     20.
68     21. int main()
69     22. {
70     23.     int total = 0;
71     24.     Fibonacci(5, total);
72     25.     return total;
73     26. }
74     27.
75     28. /*
76     29. DexExpectWatchValue('i', '0', '1', '2', '3', '4',
77     30.                     from_line='start', to_line='end')
78     31. DexExpectWatchValue('first', '0', '1', '2', '3', '5',
79     32.                     from_line='start', to_line='end')
80     33. DexExpectWatchValue('second', '1', '2', '3', '5',
81     34                      from_line='start', to_line='end')
82     35. DexExpectWatchValue('total', '0', '1', '2', '4', '7',
83     36.                     from_line='start', to_line='end')
84     37. DexExpectWatchValue('next', '1', '2', '3', '5', '8',
85     38.                     from_line='start', to_line='end')
86     39. DexExpectWatchValue('total', '7', on_line=25)
87     40. DexExpectStepKind('FUNC_EXTERNAL', 0)
88     41. */
90 [DexLabel][1] is used to give a name to a line number.
92 The [DexExpectWatchValue][2] command states that an expression, e.g. `i`, should
93 have particular values, `'0', '1', '2', '3','4'`, sequentially over the program
94 lifetime on particular lines. You can refer to a named line or simply the line
95 number (See line 39).
97 At the end of the test is the following line:
99     DexExpectStepKind('FUNC_EXTERNAL', 0)
101 This [DexExpectStepKind][3] command indicates that we do not expect the debugger
102 to step into a file outside of the test directory.
104 [1]: Commands.md#DexLabel
105 [2]: Commands.md#DexExpectWatchValue
106 [3]: Commands.md#DexExpectStepKind
108 ## Detailed DExTer reports
110 Running the command below launches the tests/nostdlib/fibonacci test case in DExTer, using clang-cl as the compiler, Visual Studio 2017 as the debugger, and producing a detailed report:
112     $ dexter.py test --builder clang-cl_vs2015 --debugger vs2017 --cflags="/Ox /Zi" --ldflags="/Zi" -v -- tests/nostdlib/fibonacci
114 The detailed report is enabled by `-v` and shows a breakdown of the information from each debugger step. For example:
116     fibonacci = (0.2832)
118     ## BEGIN ##
119     [1, "main", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 23, 1, "BREAKPOINT", "FUNC", {}]
120     [2, "main", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 24, 1, "BREAKPOINT", "VERTICAL_FORWARD", {}]
121     [3, "main", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 25, 1, "BREAKPOINT", "VERTICAL_FORWARD", {}]
122     .   [4, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "FUNC", {}]
123     .   [5, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
124     .   [6, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {}]
125     .   [7, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 15, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
126     .   [8, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
127     .   [9, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 15, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {"i": "Variable is optimized away and not available.", "second": "1", "total": "0", "first": "0"}]
128     .   [10, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {}]
129     .   [11, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
130     .   [12, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 15, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {"i": "Variable is optimized away and not available.", "second": "1", "total": "0", "first": "1"}]
131     .   [13, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {}]
132     .   [14, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
133     .   [15, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 15, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {"i": "Variable is optimized away and not available.", "second": "2", "total": "0", "first": "1"}]
134     .   [16, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {}]
135     .   [17, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
136     .   [18, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 15, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {"i": "Variable is optimized away and not available.", "second": "3", "total": "0", "first": "2"}]
137     .   [19, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {}]
138     .   [20, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
139     .   [21, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 15, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {"i": "Variable is optimized away and not available.", "second": "5", "total": "0", "first": "3"}]
140     .   [22, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 13, 1, "BREAKPOINT", "VERTICAL_BACKWARD", {}]
141     .   [23, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 16, 1, "BREAKPOINT", "VERTICAL_FORWARD", {"i": "Variable is optimized away and not available.", "next": "Variable is optimized away and not available.", "second": "Variable is optimized away and not available.", "total": "0", "first": "Variable is optimized away and not available."}]
142     .   [24, "Fibonacci", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 20, 1, "BREAKPOINT", "VERTICAL_FORWARD", {}]
143     [25, "main", "c:\\dexter\\tests\\nostdlib\\fibonacci\\test.cpp", 26, 1, "BREAKPOINT", "FUNC", {"total": "7"}]
144     ## END (25 steps) ##
147     step kind differences [0/1]
148         FUNC_EXTERNAL:
149         0
151     test.cpp:15-18 [first] [9/21]
152         expected encountered values:
153         0
154         1
155         2
156         3
158         missing values:
159         5 [-6]
161         result optimized away:
162         step 5 (Variable is optimized away and not available.) [-3]
163         step 7 (Variable is optimized away and not available.)
164         step 8 (Variable is optimized away and not available.)
165         step 11 (Variable is optimized away and not available.)
166         step 14 (Variable is optimized away and not available.)
167         step 17 (Variable is optimized away and not available.)
168         step 20 (Variable is optimized away and not available.)
169         step 23 (Variable is optimized away and not available.)
171     test.cpp:15-18 [i] [15/21]
172         result optimized away:
173         step 5 (Variable is optimized away and not available.) [-3]
174         step 7 (Variable is optimized away and not available.) [-3]
175         step 8 (Variable is optimized away and not available.) [-3]
176         step 9 (Variable is optimized away and not available.) [-3]
177         step 11 (Variable is optimized away and not available.) [-3]
178         step 12 (Variable is optimized away and not available.)
179         step 14 (Variable is optimized away and not available.)
180         step 15 (Variable is optimized away and not available.)
181         step 17 (Variable is optimized away and not available.)
182         step 18 (Variable is optimized away and not available.)
183         step 20 (Variable is optimized away and not available.)
184         step 21 (Variable is optimized away and not available.)
185         step 23 (Variable is optimized away and not available.)
187     test.cpp:15-18 [second] [21/21]
188         expected encountered values:
189         1
190         2
191         3
192         5
194         result optimized away:
195         step 5 (Variable is optimized away and not available.) [-3]
196         step 7 (Variable is optimized away and not available.) [-3]
197         step 8 (Variable is optimized away and not available.) [-3]
198         step 11 (Variable is optimized away and not available.) [-3]
199         step 14 (Variable is optimized away and not available.) [-3]
200         step 17 (Variable is optimized away and not available.) [-3]
201         step 20 (Variable is optimized away and not available.) [-3]
202         step 23 (Variable is optimized away and not available.)
204     test.cpp:15-18 [total] [21/21]
205         expected encountered values:
206         0
208         missing values:
209         1 [-6]
210         2 [-6]
211         4 [-6]
212         7 [-3]
214     test.cpp:16-18 [next] [15/21]
215         result optimized away:
216         step 5 (Variable is optimized away and not available.) [-3]
217         step 8 (Variable is optimized away and not available.) [-3]
218         step 11 (Variable is optimized away and not available.) [-3]
219         step 14 (Variable is optimized away and not available.) [-3]
220         step 17 (Variable is optimized away and not available.) [-3]
221         step 20 (Variable is optimized away and not available.)
222         step 23 (Variable is optimized away and not available.)
224     test.cpp:26 [total] [0/7]
225         expected encountered values:
226         7
228 The first line
230     fibonacci =  (0.2832)
232 shows a score of 0.2832 suggesting that unexpected behavior has been seen.  This score is on scale of 0.0000 to 1.000, with 0.000 being the worst score possible and 1.000 being the best score possible.  The verbose output shows the reason for any scoring.  For example:
234     test.cpp:15-18 [first] [9/21]
235         expected encountered values:
236         0
237         1
238         2
239         3
241         missing values:
242         5 [-6]
244         result optimized away:
245         step 5 (Variable is optimized away and not available.) [-3]
246         step 7 (Variable is optimized away and not available.)
247         step 8 (Variable is optimized away and not available.)
248         step 11 (Variable is optimized away and not available.)
249         step 14 (Variable is optimized away and not available.)
250         step 17 (Variable is optimized away and not available.)
251         step 20 (Variable is optimized away and not available.)
252         step 23 (Variable is optimized away and not available.)
254 shows that for `first` the expected values 0, 1, 2 and 3 were seen, 5 was not.  On some steps the variable was reported as being optimized away.
256 ## Writing new test cases
258 Each test requires a `test.cfg` file.  Currently the contents of this file are not read, but its presence is used to determine the root directory of a test. In the future, configuration variables for the test such as supported language modes may be stored in this file. Use the various [commands](Commands.md) to encode debugging expectations.
260 ## Additional tools
262 For clang-based compilers, the `clang-opt-bisect` tool can be used to get a breakdown of which LLVM passes may be contributing to debugging experience issues.  For example:
264     $ dexter.py clang-opt-bisect tests/nostdlib/fibonacci --builder clang-cl --debugger vs2017 --cflags="/Ox /Zi" --ldflags="/Zi"
266     pass 1/211 =  (1.0000)  (0.0000) [Simplify the CFG on function (?Fibonacci@@YAXHAEAH@Z)]
267     pass 2/211 =  (0.7611) (-0.2389) [SROA on function (?Fibonacci@@YAXHAEAH@Z)]
268     pass 3/211 =  (0.7611)  (0.0000) [Early CSE on function (?Fibonacci@@YAXHAEAH@Z)]
269     pass 4/211 =  (0.7611)  (0.0000) [Simplify the CFG on function (main)]
270     pass 5/211 =  (0.7611)  (0.0000) [SROA on function (main)]
271     pass 6/211 =  (0.7611)  (0.0000) [Early CSE on function (main)]
272     pass 7/211 =  (0.7611)  (0.0000) [Infer set function attributes on module (c:\dexter\tests\fibonacci\test.cpp)]
273     pass 8/211 =  (0.7611)  (0.0000) [Interprocedural Sparse Conditional Constant Propagation on module (c:\dexter\tests\fibonacci\test.cpp)]
274     pass 9/211 =  (0.7611)  (0.0000) [Called Value Propagation on module (c:\dexter\tests\fibonacci\test.cpp)]
275     pass 10/211 =  (0.7611)  (0.0000) [Global Variable Optimizer on module (c:\dexter\tests\fibonacci\test.cpp)]
276     pass 11/211 =  (0.7611)  (0.0000) [Promote Memory to Register on function (?Fibonacci@@YAXHAEAH@Z)]
277     pass 12/211 =  (0.7611)  (0.0000) [Promote Memory to Register on function (main)]
278     pass 13/211 =  (0.7611)  (0.0000) [Dead Argument Elimination on module (c:\dexter\tests\fibonacci\test.cpp)]
279     pass 14/211 =  (0.7611)  (0.0000) [Combine redundant instructions on function (?Fibonacci@@YAXHAEAH@Z)]
280     pass 15/211 =  (0.7611)  (0.0000) [Simplify the CFG on function (?Fibonacci@@YAXHAEAH@Z)]a
281     pass 16/211 =  (0.7345) (-0.0265) [Combine redundant instructions on function (main)]
282     pass 17/211 =  (0.7345)  (0.0000) [Simplify the CFG on function (main)]
283     pass 18/211 =  (0.7345)  (0.0000) [Remove unused exception handling info on SCC (?Fibonacci@@YAXHAEAH@Z)]
284     pass 19/211 =  (0.7345)  (0.0000) [Function Integration/Inlining on SCC (?Fibonacci@@YAXHAEAH@Z)]
285     pass 20/211 =  (0.7345)  (0.0000) [Deduce function attributes on SCC (?Fibonacci@@YAXHAEAH@Z)]
286     pass 21/211 =  (0.7345)  (0.0000) [SROA on function (?Fibonacci@@YAXHAEAH@Z)]
287     pass 22/211 =  (0.7345)  (0.0000) [Early CSE w/ MemorySSA on function (?Fibonacci@@YAXHAEAH@Z)]
288     pass 23/211 =  (0.7345)  (0.0000) [Speculatively execute instructions if target has divergent branches on function (?Fibonacci@@YAXHAEAH@Z)]
289     pass 24/211 =  (0.7345)  (0.0000) [Jump Threading on function (?Fibonacci@@YAXHAEAH@Z)]
290     pass 25/211 =  (0.7345)  (0.0000) [Value Propagation on function (?Fibonacci@@YAXHAEAH@Z)]
291     pass 26/211 =  (0.7345)  (0.0000) [Simplify the CFG on function (?Fibonacci@@YAXHAEAH@Z)]
292     pass 27/211 =  (0.7345)  (0.0000) [Combine redundant instructions on function (?Fibonacci@@YAXHAEAH@Z)]
293     pass 28/211 =  (0.7345)  (0.0000) [Tail Call Elimination on function (?Fibonacci@@YAXHAEAH@Z)]
294     pass 29/211 =  (0.7345)  (0.0000) [Simplify the CFG on function (?Fibonacci@@YAXHAEAH@Z)]
295     pass 30/211 =  (0.7345)  (0.0000) [Reassociate expressions on function (?Fibonacci@@YAXHAEAH@Z)]
296     pass 31/211 =  (0.8673)  (0.1327) [Rotate Loops on loop]
297     pass 32/211 =  (0.5575) (-0.3097) [Loop Invariant Code Motion on loop]
298     pass 33/211 =  (0.5575)  (0.0000) [Unswitch loops on loop]
299     pass 34/211 =  (0.5575)  (0.0000) [Simplify the CFG on function (?Fibonacci@@YAXHAEAH@Z)]
300     pass 35/211 =  (0.5575)  (0.0000) [Combine redundant instructions on function (?Fibonacci@@YAXHAEAH@Z)]
301     pass 36/211 =  (0.5575)  (0.0000) [Induction Variable Simplification on loop]
302     pass 37/211 =  (0.5575)  (0.0000) [Recognize loop idioms on loop]
303     <output-snipped>