OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [s-stausa.adb] - Blame information for rev 729

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS               --
4
--                                                                          --
5
--                   S Y S T E M - S T A C K _ U S A G E                    --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--         Copyright (C) 2004-2011, Free Software Foundation, Inc.          --
10
--                                                                          --
11
-- GNARL is free software; you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- GNARL was developed by the GNARL team at Florida State University.       --
28
-- Extensive contributions were provided by Ada Core Technologies, Inc.     --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
with System.Parameters;
33
with System.CRTL;
34
with System.IO;
35
 
36
package body System.Stack_Usage is
37
   use System.Storage_Elements;
38
   use System;
39
   use System.IO;
40
   use Interfaces;
41
 
42
   -----------------
43
   -- Stack_Slots --
44
   -----------------
45
 
46
   --  Stackl_Slots is an internal data type to represent a sequence of real
47
   --  stack slots initialized with a provided pattern, with operations to
48
   --  abstract away the target call stack growth direction.
49
 
50
   type Stack_Slots is array (Integer range <>) of Pattern_Type;
51
   for Stack_Slots'Component_Size use Pattern_Type'Object_Size;
52
 
53
   --  We will carefully handle the initializations ourselves and might want
54
   --  to remap an initialized overlay later on with an address clause.
55
 
56
   pragma Suppress_Initialization (Stack_Slots);
57
 
58
   --  The abstract Stack_Slots operations all operate over the simple array
59
   --  memory model:
60
 
61
   --  memory addresses increasing ---->
62
 
63
   --  Slots('First)                                           Slots('Last)
64
   --    |                                                             |
65
   --    V                                                             V
66
   --  +------------------------------------------------------------------+
67
   --  |####|                                                        |####|
68
   --  +------------------------------------------------------------------+
69
 
70
   --  What we call Top or Bottom always denotes call chain leaves or entry
71
   --  points respectively, and their relative positions in the stack array
72
   --  depends on the target stack growth direction:
73
 
74
   --                           Stack_Grows_Down
75
 
76
   --                <----- calls push frames towards decreasing addresses
77
 
78
   --   Top(most) Slot                                   Bottom(most) Slot
79
   --    |                                                            |
80
   --    V                                                            V
81
   --  +------------------------------------------------------------------+
82
   --  |####|                            | leaf frame | ... | entry frame |
83
   --  +------------------------------------------------------------------+
84
 
85
   --                           Stack_Grows_Up
86
 
87
   --   calls push frames towards increasing addresses ----->
88
 
89
   --   Bottom(most) Slot                                    Top(most) Slot
90
   --    |                                                             |
91
   --    V                                                             V
92
   --  +------------------------------------------------------------------+
93
   --  | entry frame | ... | leaf frame |                            |####|
94
   --  +------------------------------------------------------------------+
95
 
96
   -------------------
97
   -- Unit Services --
98
   -------------------
99
 
100
   --  Now the implementation of the services offered by this unit, on top of
101
   --  the Stack_Slots abstraction above.
102
 
103
   Index_Str       : constant String  := "Index";
104
   Task_Name_Str   : constant String  := "Task Name";
105
   Stack_Size_Str  : constant String  := "Stack Size";
106
   Actual_Size_Str : constant String  := "Stack usage";
107
 
108
   procedure Output_Result
109
     (Result_Id          : Natural;
110
      Result             : Task_Result;
111
      Max_Stack_Size_Len : Natural;
112
      Max_Actual_Use_Len : Natural);
113
   --  Prints the result on the standard output. Result Id is the number of
114
   --  the result in the array, and Result the contents of the actual result.
115
   --  Max_Stack_Size_Len and Max_Actual_Use_Len are used for displaying the
116
   --  proper layout. They hold the maximum length of the string representing
117
   --  the Stack_Size and Actual_Use values.
118
 
119
   ----------------
120
   -- Initialize --
121
   ----------------
122
 
123
   procedure Initialize (Buffer_Size : Natural) is
124
      Stack_Size_Chars : System.Address;
125
 
126
   begin
127
      --  Initialize the buffered result array
128
 
129
      Result_Array := new Result_Array_Type (1 .. Buffer_Size);
130
      Result_Array.all :=
131
        (others =>
132
           (Task_Name   => (others => ASCII.NUL),
133
            Value       => 0,
134
            Stack_Size  => 0));
135
 
136
      --  Set the Is_Enabled flag to true, so that the task wrapper knows that
137
      --  it has to handle dynamic stack analysis
138
 
139
      Is_Enabled := True;
140
 
141
      Stack_Size_Chars := System.CRTL.getenv ("GNAT_STACK_LIMIT" & ASCII.NUL);
142
 
143
      --  If variable GNAT_STACK_LIMIT is set, then we will take care of the
144
      --  environment task, using GNAT_STASK_LIMIT as the size of the stack.
145
      --  It doesn't make sens to process the stack when no bound is set (e.g.
146
      --  limit is typically up to 4 GB).
147
 
148
      if Stack_Size_Chars /= Null_Address then
149
         declare
150
            My_Stack_Size : Integer;
151
 
152
         begin
153
            My_Stack_Size := System.CRTL.atoi (Stack_Size_Chars) * 1024;
154
 
155
            Initialize_Analyzer
156
              (Environment_Task_Analyzer,
157
               "ENVIRONMENT TASK",
158
               My_Stack_Size,
159
               0,
160
               My_Stack_Size);
161
 
162
            Fill_Stack (Environment_Task_Analyzer);
163
 
164
            Compute_Environment_Task := True;
165
         end;
166
 
167
      --  GNAT_STACK_LIMIT not set
168
 
169
      else
170
         Compute_Environment_Task := False;
171
      end if;
172
   end Initialize;
173
 
174
   ----------------
175
   -- Fill_Stack --
176
   ----------------
177
 
178
   procedure Fill_Stack (Analyzer : in out Stack_Analyzer) is
179
 
180
      --  Change the local variables and parameters of this function with
181
      --  super-extra care. The more the stack frame size of this function is
182
      --  big, the more an "instrumentation threshold at writing" error is
183
      --  likely to happen.
184
 
185
      Current_Stack_Level : aliased Integer;
186
 
187
      Guard : constant := 256;
188
      --  Guard space between the Current_Stack_Level'Address and the last
189
      --  allocated byte on the stack.
190
   begin
191
      if Parameters.Stack_Grows_Down then
192
         if Analyzer.Stack_Base - Stack_Address (Analyzer.Pattern_Size) >
193
              To_Stack_Address (Current_Stack_Level'Address) - Guard
194
         then
195
            --  No room for a pattern
196
 
197
            Analyzer.Pattern_Size := 0;
198
            return;
199
         end if;
200
 
201
         Analyzer.Pattern_Limit :=
202
           Analyzer.Stack_Base - Stack_Address (Analyzer.Pattern_Size);
203
 
204
         if Analyzer.Stack_Base >
205
              To_Stack_Address (Current_Stack_Level'Address) - Guard
206
         then
207
            --  Reduce pattern size to prevent local frame overwrite
208
 
209
            Analyzer.Pattern_Size :=
210
              Integer (To_Stack_Address (Current_Stack_Level'Address) - Guard
211
                         - Analyzer.Pattern_Limit);
212
         end if;
213
 
214
         Analyzer.Pattern_Overlay_Address :=
215
           To_Address (Analyzer.Pattern_Limit);
216
      else
217
         if Analyzer.Stack_Base + Stack_Address (Analyzer.Pattern_Size) <
218
              To_Stack_Address (Current_Stack_Level'Address) + Guard
219
         then
220
            --  No room for a pattern
221
 
222
            Analyzer.Pattern_Size := 0;
223
            return;
224
         end if;
225
 
226
         Analyzer.Pattern_Limit :=
227
           Analyzer.Stack_Base + Stack_Address (Analyzer.Pattern_Size);
228
 
229
         if Analyzer.Stack_Base <
230
           To_Stack_Address (Current_Stack_Level'Address) + Guard
231
         then
232
            --  Reduce pattern size to prevent local frame overwrite
233
 
234
            Analyzer.Pattern_Size :=
235
              Integer
236
                (Analyzer.Pattern_Limit -
237
                  (To_Stack_Address (Current_Stack_Level'Address) + Guard));
238
         end if;
239
 
240
         Analyzer.Pattern_Overlay_Address :=
241
           To_Address (Analyzer.Pattern_Limit -
242
                         Stack_Address (Analyzer.Pattern_Size));
243
      end if;
244
 
245
      --  Declare and fill the pattern buffer
246
 
247
      declare
248
         Pattern : aliased Stack_Slots
249
                     (1 .. Analyzer.Pattern_Size / Bytes_Per_Pattern);
250
         for Pattern'Address use Analyzer.Pattern_Overlay_Address;
251
 
252
      begin
253
         if System.Parameters.Stack_Grows_Down then
254
            for J in reverse Pattern'Range loop
255
               Pattern (J) := Analyzer.Pattern;
256
            end loop;
257
 
258
         else
259
            for J in Pattern'Range loop
260
               Pattern (J) := Analyzer.Pattern;
261
            end loop;
262
         end if;
263
      end;
264
   end Fill_Stack;
265
 
266
   -------------------------
267
   -- Initialize_Analyzer --
268
   -------------------------
269
 
270
   procedure Initialize_Analyzer
271
     (Analyzer         : in out Stack_Analyzer;
272
      Task_Name        : String;
273
      Stack_Size       : Natural;
274
      Stack_Base       : Stack_Address;
275
      Pattern_Size     : Natural;
276
      Pattern          : Interfaces.Unsigned_32 := 16#DEAD_BEEF#)
277
   is
278
   begin
279
      --  Initialize the analyzer fields
280
 
281
      Analyzer.Stack_Base    := Stack_Base;
282
      Analyzer.Stack_Size    := Stack_Size;
283
      Analyzer.Pattern_Size  := Pattern_Size;
284
      Analyzer.Pattern       := Pattern;
285
      Analyzer.Result_Id     := Next_Id;
286
      Analyzer.Task_Name     := (others => ' ');
287
 
288
      --  Compute the task name, and truncate if bigger than Task_Name_Length
289
 
290
      if Task_Name'Length <= Task_Name_Length then
291
         Analyzer.Task_Name (1 .. Task_Name'Length) := Task_Name;
292
      else
293
         Analyzer.Task_Name :=
294
           Task_Name (Task_Name'First ..
295
                      Task_Name'First + Task_Name_Length - 1);
296
      end if;
297
 
298
      Next_Id := Next_Id + 1;
299
   end Initialize_Analyzer;
300
 
301
   ----------------
302
   -- Stack_Size --
303
   ----------------
304
 
305
   function Stack_Size
306
     (SP_Low  : Stack_Address;
307
      SP_High : Stack_Address) return Natural
308
   is
309
   begin
310
      if SP_Low > SP_High then
311
         return Natural (SP_Low - SP_High);
312
      else
313
         return Natural (SP_High - SP_Low);
314
      end if;
315
   end Stack_Size;
316
 
317
   --------------------
318
   -- Compute_Result --
319
   --------------------
320
 
321
   procedure Compute_Result (Analyzer : in out Stack_Analyzer) is
322
 
323
      --  Change the local variables and parameters of this function with
324
      --  super-extra care. The larger the stack frame size of this function
325
      --  is, the more an "instrumentation threshold at reading" error is
326
      --  likely to happen.
327
 
328
      Stack : Stack_Slots (1 .. Analyzer.Pattern_Size / Bytes_Per_Pattern);
329
      for Stack'Address use Analyzer.Pattern_Overlay_Address;
330
 
331
   begin
332
      --  Value if the pattern was not modified
333
 
334
      if Parameters.Stack_Grows_Down then
335
         Analyzer.Topmost_Touched_Mark :=
336
           Analyzer.Pattern_Limit + Stack_Address (Analyzer.Pattern_Size);
337
      else
338
         Analyzer.Topmost_Touched_Mark :=
339
           Analyzer.Pattern_Limit - Stack_Address (Analyzer.Pattern_Size);
340
      end if;
341
 
342
      if Analyzer.Pattern_Size = 0 then
343
         return;
344
      end if;
345
 
346
      --  Look backward from the topmost possible end of the marked stack to
347
      --  the bottom of it. The first index not equals to the patterns marks
348
      --  the beginning of the used stack.
349
 
350
      if System.Parameters.Stack_Grows_Down then
351
         for J in Stack'Range loop
352
            if Stack (J) /= Analyzer.Pattern then
353
               Analyzer.Topmost_Touched_Mark :=
354
                 To_Stack_Address (Stack (J)'Address);
355
               exit;
356
            end if;
357
         end loop;
358
 
359
      else
360
         for J in reverse Stack'Range loop
361
            if Stack (J) /= Analyzer.Pattern then
362
               Analyzer.Topmost_Touched_Mark :=
363
                 To_Stack_Address (Stack (J)'Address);
364
               exit;
365
            end if;
366
         end loop;
367
 
368
      end if;
369
   end Compute_Result;
370
 
371
   ---------------------
372
   --  Output_Result --
373
   ---------------------
374
 
375
   procedure Output_Result
376
     (Result_Id          : Natural;
377
      Result             : Task_Result;
378
      Max_Stack_Size_Len : Natural;
379
      Max_Actual_Use_Len : Natural)
380
   is
381
      Result_Id_Str  : constant String := Natural'Image (Result_Id);
382
      Stack_Size_Str : constant String := Natural'Image (Result.Stack_Size);
383
      Actual_Use_Str : constant String := Natural'Image (Result.Value);
384
 
385
      Result_Id_Blanks  : constant
386
        String (1 .. Index_Str'Length - Result_Id_Str'Length)    :=
387
          (others => ' ');
388
 
389
      Stack_Size_Blanks : constant
390
        String (1 .. Max_Stack_Size_Len - Stack_Size_Str'Length) :=
391
          (others => ' ');
392
 
393
      Actual_Use_Blanks : constant
394
        String (1 .. Max_Actual_Use_Len - Actual_Use_Str'Length) :=
395
          (others => ' ');
396
 
397
   begin
398
      Set_Output (Standard_Error);
399
      Put (Result_Id_Blanks & Natural'Image (Result_Id));
400
      Put (" | ");
401
      Put (Result.Task_Name);
402
      Put (" | ");
403
      Put (Stack_Size_Blanks & Stack_Size_Str);
404
      Put (" | ");
405
      Put (Actual_Use_Blanks & Actual_Use_Str);
406
      New_Line;
407
   end Output_Result;
408
 
409
   ---------------------
410
   --  Output_Results --
411
   ---------------------
412
 
413
   procedure Output_Results is
414
      Max_Stack_Size                         : Natural := 0;
415
      Max_Stack_Usage                        : Natural := 0;
416
      Max_Stack_Size_Len, Max_Actual_Use_Len : Natural := 0;
417
 
418
      Task_Name_Blanks : constant
419
                           String
420
                             (1 .. Task_Name_Length - Task_Name_Str'Length) :=
421
                               (others => ' ');
422
 
423
   begin
424
      Set_Output (Standard_Error);
425
 
426
      if Compute_Environment_Task then
427
         Compute_Result (Environment_Task_Analyzer);
428
         Report_Result (Environment_Task_Analyzer);
429
      end if;
430
 
431
      if Result_Array'Length > 0 then
432
 
433
         --  Computes the size of the largest strings that will get displayed,
434
         --  in order to do correct column alignment.
435
 
436
         for J in Result_Array'Range loop
437
            exit when J >= Next_Id;
438
 
439
            if Result_Array (J).Value > Max_Stack_Usage then
440
               Max_Stack_Usage := Result_Array (J).Value;
441
            end if;
442
 
443
            if Result_Array (J).Stack_Size > Max_Stack_Size then
444
               Max_Stack_Size := Result_Array (J).Stack_Size;
445
            end if;
446
         end loop;
447
 
448
         Max_Stack_Size_Len := Natural'Image (Max_Stack_Size)'Length;
449
 
450
         Max_Actual_Use_Len := Natural'Image (Max_Stack_Usage)'Length;
451
 
452
         --  Display the output header. Blanks will be added in front of the
453
         --  labels if needed.
454
 
455
         declare
456
            Stack_Size_Blanks  : constant
457
                                   String (1 .. Max_Stack_Size_Len -
458
                                                  Stack_Size_Str'Length) :=
459
                                      (others => ' ');
460
 
461
            Stack_Usage_Blanks : constant
462
                                   String (1 .. Max_Actual_Use_Len -
463
                                                  Actual_Size_Str'Length) :=
464
                                      (others => ' ');
465
 
466
         begin
467
            if Stack_Size_Str'Length > Max_Stack_Size_Len then
468
               Max_Stack_Size_Len := Stack_Size_Str'Length;
469
            end if;
470
 
471
            if Actual_Size_Str'Length > Max_Actual_Use_Len then
472
               Max_Actual_Use_Len := Actual_Size_Str'Length;
473
            end if;
474
 
475
            Put
476
              (Index_Str & " | " & Task_Name_Str & Task_Name_Blanks & " | "
477
               & Stack_Size_Str & Stack_Size_Blanks & " | "
478
               & Stack_Usage_Blanks & Actual_Size_Str);
479
         end;
480
 
481
         New_Line;
482
 
483
         --  Now display the individual results
484
 
485
         for J in Result_Array'Range loop
486
            exit when J >= Next_Id;
487
            Output_Result
488
              (J, Result_Array (J), Max_Stack_Size_Len, Max_Actual_Use_Len);
489
         end loop;
490
 
491
      --  Case of no result stored, still display the labels
492
 
493
      else
494
         Put
495
           (Index_Str & " | " & Task_Name_Str & Task_Name_Blanks & " | "
496
            & Stack_Size_Str & " | " & Actual_Size_Str);
497
         New_Line;
498
      end if;
499
   end Output_Results;
500
 
501
   -------------------
502
   -- Report_Result --
503
   -------------------
504
 
505
   procedure Report_Result (Analyzer : Stack_Analyzer) is
506
      Result : Task_Result := (Task_Name  => Analyzer.Task_Name,
507
                               Stack_Size => Analyzer.Stack_Size,
508
                               Value      => 0);
509
   begin
510
      if Analyzer.Pattern_Size = 0 then
511
 
512
         --  If we have that result, it means that we didn't do any computation
513
         --  at all (i.e. we used at least everything (and possibly more).
514
 
515
         Result.Value := Analyzer.Stack_Size;
516
 
517
      else
518
         Result.Value := Stack_Size (Analyzer.Topmost_Touched_Mark,
519
                                     Analyzer.Stack_Base);
520
      end if;
521
 
522
      if Analyzer.Result_Id in Result_Array'Range then
523
 
524
         --  If the result can be stored, then store it in Result_Array
525
 
526
         Result_Array (Analyzer.Result_Id) := Result;
527
 
528
      else
529
         --  If the result cannot be stored, then we display it right away
530
 
531
         declare
532
            Result_Str_Len : constant Natural :=
533
                               Natural'Image (Result.Value)'Length;
534
            Size_Str_Len   : constant Natural :=
535
                               Natural'Image (Analyzer.Stack_Size)'Length;
536
 
537
            Max_Stack_Size_Len : Natural;
538
            Max_Actual_Use_Len : Natural;
539
 
540
         begin
541
            --  Take either the label size or the number image size for the
542
            --  size of the column "Stack Size".
543
 
544
            Max_Stack_Size_Len :=
545
              (if Size_Str_Len > Stack_Size_Str'Length
546
               then Size_Str_Len
547
               else Stack_Size_Str'Length);
548
 
549
            --  Take either the label size or the number image size for the
550
            --  size of the column "Stack Usage".
551
 
552
            Max_Actual_Use_Len :=
553
              (if Result_Str_Len > Actual_Size_Str'Length
554
               then Result_Str_Len
555
               else Actual_Size_Str'Length);
556
 
557
            Output_Result
558
              (Analyzer.Result_Id,
559
               Result,
560
               Max_Stack_Size_Len,
561
               Max_Actual_Use_Len);
562
         end;
563
      end if;
564
   end Report_Result;
565
 
566
end System.Stack_Usage;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.