Skip to content

Commit c3b4cfc

Browse files
Add lab for GNATstack
1 parent 3d3bf76 commit c3b4cfc

File tree

3 files changed

+268
-5
lines changed

3 files changed

+268
-5
lines changed

courses/misc_tools/200_gnatstack.rst

+1-5
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,7 @@ Commonly Used Switches
196196
Lab
197197
=====
198198

199-
---------------------------
200-
TBD
201-
---------------------------
202-
203-
* include:: labs/200_gnatstack/lab.rst
199+
.. include:: labs/200_gnatstack/lab.rst
204200

205201
=========
206202
Summary
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
project Default is
2+
3+
package Compiler is
4+
for Default_Switches ("Ada") use ("-fcallgraph-info=su");
5+
end Compiler;
6+
7+
for Runtime ("ada") use "light";
8+
9+
end Default;
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
---------------------------
2+
:toolname:`GNATstack` Lab
3+
---------------------------
4+
5+
* We are going to perform stack analysis on some source code examples
6+
7+
* Although this is called a lab, it's more like a walk-through!
8+
9+
* Copy the :filename:`200_gnatstack` lab folder from the course materials location
10+
11+
* Contents of the folder:
12+
13+
* :filename:`simple` - folder containing a simple main procedure
14+
* :filename:`complicated` - folder containing multiple main procedures and some other packages
15+
16+
.. note:: We use animation - if you don't know the answer, Page Down should give it to you
17+
18+
---------------------------------------------
19+
Getting Familiar with :toolname:`GNATstack`
20+
---------------------------------------------
21+
22+
1. Open a command prompt window and navigate into the folder :filename:`simple`
23+
24+
2. Build the executable :ada:`main_unit`, making sure to generate call-graph information
25+
26+
* Don't forget to use the light-tasking runtime (switch :command:`--RTS=light`)
27+
28+
.. container:: animate 2-
29+
30+
:command:`gprbuild --RTS=light main_unit.adb -cargs -fcallgraph-info=su`
31+
32+
3. Perform the stack analysis
33+
34+
.. container:: animate 3-
35+
36+
:command:`gnatstack *.ci`
37+
38+
::
39+
40+
main : total 224 bytes
41+
+-> main
42+
+-> main_unit
43+
+-> main_unit.inverse
44+
45+
The numbers may be different, but the calls should match
46+
47+
---------------------------
48+
Adding Source Information
49+
---------------------------
50+
51+
To see where the total number of bytes comes from, run the analysis in :dfn:`verbose` mode
52+
53+
.. container:: animate 2-
54+
55+
:command:`gnatstack -v *.ci`
56+
57+
::
58+
59+
+-> main at main:b__main_unit.adb:20:4 : 64 bytes
60+
+-> main_unit at Main_Unit:L:\\main_unit.adb:1:1,
61+
ada_main_program:b__main_unit.adb:17:14 : 96 bytes
62+
+-> main_unit.inverse at Inverse:L:\\main_unit.adb:4:4 : 64 bytes
63+
64+
.. note:: Verbose mode also shows full path to the source
65+
66+
-----------------------------
67+
Working with Multiple Mains
68+
-----------------------------
69+
70+
1. Open a command prompt window and navigate into the folder :filename:`complicated`
71+
72+
2. Examine the GNAT Project file and notice the following:
73+
74+
* The :command:`-fcallgraph-info=su` switch is specified in the :ada:`Compiler` package
75+
* All main subprograma are specified using :ada:`for Main`
76+
77+
* Otherwise :command:`gprbuild` does not know what executables to build
78+
79+
* The runtime is specified using :ada:`for Runtime`
80+
81+
3. Build all the executables using the included :filename:`default.gpr`
82+
83+
:command:`gprbuild -P default.gpr`
84+
85+
--------------------------
86+
Recursive Calls (Cycles)
87+
--------------------------
88+
89+
.. code:: Ada
90+
91+
procedure Odd (Number : in out Integer) is
92+
begin
93+
Number := Number - 1;
94+
if Number > 0 then
95+
Cycles (Number);
96+
end if;
97+
end Odd;
98+
99+
procedure Even (Number : in out Integer) is
100+
begin
101+
Number := Number - 2;
102+
if Number > 0 then
103+
Cycles (Number);
104+
end if;
105+
end Even;
106+
107+
procedure Cycles (Number : in out Integer) is
108+
Half : constant Integer := Number / 2;
109+
begin
110+
if Half * 2 = Number then
111+
Even (Number);
112+
else
113+
Odd (Number);
114+
end if;
115+
end Cycles;
116+
117+
----------------------
118+
Investigating Cycles
119+
----------------------
120+
121+
.. container:: animate 1-
122+
123+
1. Perform the stack analysis for :ada:`Cycles_Main`
124+
125+
.. container:: animate 2-
126+
127+
:command:`gnatstack -e cycles_main *.ci`
128+
129+
::
130+
131+
Worst case analysis is *not* accurate because of cycles, external calls. Use -Wa for details.
132+
133+
Accumulated stack usage information for entry points
134+
135+
cycles_main : total 176+? bytes
136+
+-> cycles_main
137+
+-> cycles_example.cycles *
138+
+-> cycles_example.odd *
139+
+-> <__gnat_last_chance_handler> *
140+
141+
2. Notice the warning indicating to use :command:`-Wa` for details - try that.
142+
143+
.. container:: animate 3-
144+
145+
:command:`gnatstack -Wa -e cycles_main *.ci`
146+
147+
Notice the added information
148+
149+
::
150+
151+
List of reachable cycles:
152+
153+
<c1> cycles_example.cycles
154+
+-> cycles_example.cycles
155+
+-> cycles_example.even
156+
+-> cycles_example.cycles
157+
158+
<c2> cycles_example.cycles
159+
+-> cycles_example.cycles
160+
+-> cycles_example.odd
161+
+-> cycles_example.cycles
162+
163+
--------------------------------------
164+
Subprogram Pointers (Indirect Calls)
165+
--------------------------------------
166+
167+
.. code:: Ada
168+
169+
type Subprogram_Access_T is access procedure
170+
(A, B : Integer;
171+
C : out Boolean);
172+
procedure Procedure_One
173+
(A, B : Integer;
174+
C : out Boolean) is
175+
begin
176+
C := A > B;
177+
end Procedure_One;
178+
179+
procedure Procedure_Two
180+
(A, B : Integer;
181+
C : out Boolean) is
182+
begin
183+
C := A < B;
184+
end Procedure_Two;
185+
186+
Calls : array (Boolean) of Subprogram_Access_T :=
187+
(Procedure_One'Access,
188+
Procedure_Two'Access);
189+
190+
procedure Test (Flag : in out Boolean) is
191+
begin
192+
Calls (Flag).all (1, 2, Flag);
193+
end Test;
194+
195+
------------------------------
196+
Investigating Indirect Calls
197+
------------------------------
198+
199+
.. container:: animate 1-
200+
201+
1. Perform the stack analysis for :ada:`Indirect_Main`
202+
203+
.. container:: animate 2-
204+
205+
:command:`gnatstack -e indirect_main *.ci`
206+
207+
::
208+
209+
Worst case analysis is *not* accurate because of external calls, indirect calls. Use -Wa for details.
210+
211+
Accumulated stack usage information for entry points
212+
213+
indirect_main : total 112+? bytes
214+
+-> indirect_main
215+
+-> indirect_example.test
216+
+-> indirect call *
217+
218+
2. Notice the warning indicating to use :command:`-Wa` for details - try that.
219+
220+
.. container:: animate 3-
221+
222+
:command:`gnatstack -Wa -e indirect_main *.ci`
223+
224+
Notice the added information
225+
226+
::
227+
228+
List of reachable external subprograms:
229+
230+
<__gnat_last_chance_handler>
231+
232+
List of reachable and unresolved indirect (including dispatching) calls:
233+
234+
1 indirect call in: indirect_example.test
235+
at L:\indirect_example.adb:26
236+
237+
----------------------
238+
Using Other Switches
239+
----------------------
240+
241+
If you have time, experiment with some other switches
242+
243+
.. container:: animate 1-
244+
245+
* Show information for multiple main programs
246+
247+
.. container:: animate 2-
248+
249+
:command:`gnatstack -e indirect_main,cycles_main *.ci`
250+
251+
.. container:: animate 1-
252+
253+
* Show target for dispatching calls
254+
255+
.. container:: animate 3-
256+
257+
:command:`gnatstack -td -e dispatching_main *.ci`

0 commit comments

Comments
 (0)