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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [par_sco.adb] - Blame information for rev 316

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

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                              P A R _ S C O                               --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--             Copyright (C) 2009, Free Software Foundation, Inc.           --
10
--                                                                          --
11
-- GNAT 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.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19
-- http://www.gnu.org/licenses for a complete copy of the license.          --
20
--                                                                          --
21
-- GNAT was originally developed  by the GNAT team at  New York University. --
22
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
23
--                                                                          --
24
------------------------------------------------------------------------------
25
 
26
with Atree;    use Atree;
27
with Debug;    use Debug;
28
with Lib;      use Lib;
29
with Lib.Util; use Lib.Util;
30
with Namet;    use Namet;
31
with Nlists;   use Nlists;
32
with Opt;      use Opt;
33
with Output;   use Output;
34
with Put_SCOs;
35
with SCOs;     use SCOs;
36
with Sinfo;    use Sinfo;
37
with Sinput;   use Sinput;
38
with Snames;   use Snames;
39
with Table;
40
 
41
with GNAT.HTable;      use GNAT.HTable;
42
with GNAT.Heap_Sort_G;
43
 
44
package body Par_SCO is
45
 
46
   -----------------------
47
   -- Unit Number Table --
48
   -----------------------
49
 
50
   --  This table parallels the SCO_Unit_Table, keeping track of the unit
51
   --  numbers corresponding to the entries made in this table, so that before
52
   --  writing out the SCO information to the ALI file, we can fill in the
53
   --  proper dependency numbers and file names.
54
 
55
   --  Note that the zero'th entry is here for convenience in sorting the
56
   --  table, the real lower bound is 1.
57
 
58
   package SCO_Unit_Number_Table is new Table.Table (
59
     Table_Component_Type => Unit_Number_Type,
60
     Table_Index_Type     => SCO_Unit_Index,
61
     Table_Low_Bound      => 0, -- see note above on sort
62
     Table_Initial        => 20,
63
     Table_Increment      => 200,
64
     Table_Name           => "SCO_Unit_Number_Entry");
65
 
66
   --------------------------
67
   -- Condition Hash Table --
68
   --------------------------
69
 
70
   --  We need to be able to get to conditions quickly for handling the calls
71
   --  to Set_SCO_Condition efficiently. For this purpose we identify the
72
   --  conditions in the table by their starting sloc, and use the following
73
   --  hash table to map from these starting sloc values to SCO_Table indexes.
74
 
75
   type Header_Num is new Integer range 0 .. 996;
76
   --  Type for hash table headers
77
 
78
   function Hash (F : Source_Ptr) return Header_Num;
79
   --  Function to Hash source pointer value
80
 
81
   function Equal (F1, F2 : Source_Ptr) return Boolean;
82
   --  Function to test two keys for equality
83
 
84
   package Condition_Hash_Table is new Simple_HTable
85
     (Header_Num, Int, 0, Source_Ptr, Hash, Equal);
86
   --  The actual hash table
87
 
88
   --------------------------
89
   -- Internal Subprograms --
90
   --------------------------
91
 
92
   function Has_Decision (N : Node_Id) return Boolean;
93
   --  N is the node for a subexpression. Returns True if the subexpression
94
   --  contains a nested decision (i.e. either is a logical operator, or
95
   --  contains a logical operator in its subtree).
96
 
97
   function Is_Logical_Operator (N : Node_Id) return Boolean;
98
   --  N is the node for a subexpression. This procedure just tests N to see
99
   --  if it is a logical operator (including short circuit conditions, but
100
   --  excluding OR and AND) and returns True if so, False otherwise, it does
101
   --  no other processing.
102
 
103
   procedure Process_Decisions (N : Node_Id; T : Character);
104
   --  If N is Empty, has no effect. Otherwise scans the tree for the node N,
105
   --  to output any decisions it contains. T is one of IEPWX (for context of
106
   --  expresion: if/exit when/pragma/while/expression). If T is other than X,
107
   --  then a decision is always present (at the very least a simple decision
108
   --  is present at the top level).
109
 
110
   procedure Process_Decisions (L : List_Id; T : Character);
111
   --  Calls above procedure for each element of the list L
112
 
113
   procedure Set_Table_Entry
114
     (C1   : Character;
115
      C2   : Character;
116
      From : Source_Ptr;
117
      To   : Source_Ptr;
118
      Last : Boolean);
119
   --  Append an entry to SCO_Table with fields set as per arguments
120
 
121
   procedure Traverse_Declarations_Or_Statements  (L : List_Id);
122
   procedure Traverse_Generic_Package_Declaration (N : Node_Id);
123
   procedure Traverse_Handled_Statement_Sequence  (N : Node_Id);
124
   procedure Traverse_Package_Body                (N : Node_Id);
125
   procedure Traverse_Package_Declaration         (N : Node_Id);
126
   procedure Traverse_Subprogram_Body             (N : Node_Id);
127
   --  Traverse the corresponding construct, generating SCO table entries
128
 
129
   procedure Write_SCOs_To_ALI_File is new Put_SCOs;
130
   --  Write SCO information to the ALI file using routines in Lib.Util
131
 
132
   ----------
133
   -- dsco --
134
   ----------
135
 
136
   procedure dsco is
137
   begin
138
      --  Dump SCO unit table
139
 
140
      Write_Line ("SCO Unit Table");
141
      Write_Line ("--------------");
142
 
143
      for Index in 1 .. SCO_Unit_Table.Last loop
144
         declare
145
            UTE : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (Index);
146
 
147
         begin
148
            Write_Str ("  ");
149
            Write_Int (Int (Index));
150
            Write_Str (".  Dep_Num = ");
151
            Write_Int (Int (UTE.Dep_Num));
152
            Write_Str ("  From = ");
153
            Write_Int (Int (UTE.From));
154
            Write_Str ("  To = ");
155
            Write_Int (Int (UTE.To));
156
 
157
            Write_Str ("  File_Name = """);
158
 
159
            if UTE.File_Name /= null then
160
               Write_Str (UTE.File_Name.all);
161
            end if;
162
 
163
            Write_Char ('"');
164
            Write_Eol;
165
         end;
166
      end loop;
167
 
168
      --  Dump SCO Unit number table if it contains any entries
169
 
170
      if SCO_Unit_Number_Table.Last >= 1 then
171
         Write_Eol;
172
         Write_Line ("SCO Unit Number Table");
173
         Write_Line ("---------------------");
174
 
175
         for Index in 1 .. SCO_Unit_Number_Table.Last loop
176
            Write_Str ("  ");
177
            Write_Int (Int (Index));
178
            Write_Str (". Unit_Number = ");
179
            Write_Int (Int (SCO_Unit_Number_Table.Table (Index)));
180
            Write_Eol;
181
         end loop;
182
      end if;
183
 
184
      --  Dump SCO table itself
185
 
186
      Write_Eol;
187
      Write_Line ("SCO Table");
188
      Write_Line ("---------");
189
 
190
      for Index in 1 .. SCO_Table.Last loop
191
         declare
192
            T : SCO_Table_Entry renames SCO_Table.Table (Index);
193
 
194
         begin
195
            Write_Str  ("  ");
196
            Write_Int  (Index);
197
            Write_Char ('.');
198
 
199
            if T.C1 /= ' ' then
200
               Write_Str  ("  C1 = '");
201
               Write_Char (T.C1);
202
               Write_Char (''');
203
            end if;
204
 
205
            if T.C2 /= ' ' then
206
               Write_Str  ("  C2 = '");
207
               Write_Char (T.C2);
208
               Write_Char (''');
209
            end if;
210
 
211
            if T.From /= No_Source_Location then
212
               Write_Str ("  From = ");
213
               Write_Int (Int (T.From.Line));
214
               Write_Char (':');
215
               Write_Int (Int (T.From.Col));
216
            end if;
217
 
218
            if T.To /= No_Source_Location then
219
               Write_Str ("  To = ");
220
               Write_Int (Int (T.To.Line));
221
               Write_Char (':');
222
               Write_Int (Int (T.To.Col));
223
            end if;
224
 
225
            if T.Last then
226
               Write_Str ("  True");
227
            else
228
               Write_Str ("  False");
229
            end if;
230
 
231
            Write_Eol;
232
         end;
233
      end loop;
234
   end dsco;
235
 
236
   -----------
237
   -- Equal --
238
   -----------
239
 
240
   function Equal (F1, F2 : Source_Ptr) return Boolean is
241
   begin
242
      return F1 = F2;
243
   end Equal;
244
 
245
   ------------------
246
   -- Has_Decision --
247
   ------------------
248
 
249
   function Has_Decision (N : Node_Id) return Boolean is
250
 
251
      function Check_Node (N : Node_Id) return Traverse_Result;
252
 
253
      ----------------
254
      -- Check_Node --
255
      ----------------
256
 
257
      function Check_Node (N : Node_Id) return Traverse_Result is
258
      begin
259
         if Is_Logical_Operator (N) then
260
            return Abandon;
261
         else
262
            return OK;
263
         end if;
264
      end Check_Node;
265
 
266
      function Traverse is new Traverse_Func (Check_Node);
267
 
268
   --  Start of processing for Has_Decision
269
 
270
   begin
271
      return Traverse (N) = Abandon;
272
   end Has_Decision;
273
 
274
   ----------
275
   -- Hash --
276
   ----------
277
 
278
   function Hash (F : Source_Ptr) return Header_Num is
279
   begin
280
      return Header_Num (Nat (F) mod 997);
281
   end Hash;
282
 
283
   ----------------
284
   -- Initialize --
285
   ----------------
286
 
287
   procedure Initialize is
288
   begin
289
      SCO_Unit_Number_Table.Init;
290
 
291
      --  Set dummy 0'th entry in place for sort
292
 
293
      SCO_Unit_Number_Table.Increment_Last;
294
   end Initialize;
295
 
296
   -------------------------
297
   -- Is_Logical_Operator --
298
   -------------------------
299
 
300
   function Is_Logical_Operator (N : Node_Id) return Boolean is
301
   begin
302
      return Nkind_In (N, N_Op_Xor,
303
                          N_Op_Not,
304
                          N_And_Then,
305
                          N_Or_Else);
306
   end Is_Logical_Operator;
307
 
308
   -----------------------
309
   -- Process_Decisions --
310
   -----------------------
311
 
312
   --  Version taking a list
313
 
314
   procedure Process_Decisions (L : List_Id; T : Character) is
315
      N : Node_Id;
316
   begin
317
      if L /= No_List then
318
         N := First (L);
319
         while Present (N) loop
320
            Process_Decisions (N, T);
321
            Next (N);
322
         end loop;
323
      end if;
324
   end Process_Decisions;
325
 
326
   --  Version taking a node
327
 
328
   procedure Process_Decisions (N : Node_Id; T : Character) is
329
 
330
      function Process_Node (N : Node_Id) return Traverse_Result;
331
      --  Processes one node in the traversal, looking for logical operators,
332
      --  and if one is found, outputs the appropriate table entries.
333
 
334
      procedure Output_Decision_Operand (N : Node_Id);
335
      --  The node N is the top level logical operator of a decision, or it is
336
      --  one of the operands of a logical operator belonging to a single
337
      --  complex decision. This routine outputs the sequence of table entries
338
      --  corresponding to the node. Note that we do not process the sub-
339
      --  operands to look for further decisions, that processing is done in
340
      --  Process_Decision_Operand, because we can't get decisions mixed up in
341
      --  the global table. Call has no effect if N is Empty.
342
 
343
      procedure Output_Element (N : Node_Id; T : Character);
344
      --  Node N is an operand of a logical operator that is not itself a
345
      --  logical operator, or it is a simple decision. This routine outputs
346
      --  the table entry for the element, with C1 set to T (' ' for one of
347
      --  the elements of a complex decision, or 'I'/'W'/'E' for a simple
348
      --  decision (from an IF, WHILE, or EXIT WHEN). Last is set to False,
349
      --  and an entry is made in the condition hash table.
350
 
351
      procedure Process_Decision_Operand (N : Node_Id);
352
      --  This is called on node N, the top level node of a decision, or on one
353
      --  of its operands or suboperands after generating the full output for
354
      --  the complex decision. It process the suboperands of the decision
355
      --  looking for nested decisions.
356
 
357
      -----------------------------
358
      -- Output_Decision_Operand --
359
      -----------------------------
360
 
361
      procedure Output_Decision_Operand (N : Node_Id) is
362
         C : Character;
363
         L : Node_Id;
364
 
365
      begin
366
         if No (N) then
367
            return;
368
 
369
         --  Logical operator
370
 
371
         elsif Is_Logical_Operator (N) then
372
            if Nkind (N) = N_Op_Not then
373
               C := '!';
374
               L := Empty;
375
 
376
            else
377
               L := Left_Opnd (N);
378
 
379
               if Nkind (N) = N_Op_Xor then
380
                  C := '^';
381
               elsif Nkind_In (N, N_Op_Or, N_Or_Else) then
382
                  C := '|';
383
               else
384
                  C := '&';
385
               end if;
386
            end if;
387
 
388
            Set_Table_Entry (C, ' ', No_Location, No_Location, False);
389
 
390
            Output_Decision_Operand (L);
391
            Output_Decision_Operand (Right_Opnd (N));
392
 
393
         --  Not a logical operator
394
 
395
         else
396
            Output_Element (N, ' ');
397
         end if;
398
      end Output_Decision_Operand;
399
 
400
      --------------------
401
      -- Output_Element --
402
      --------------------
403
 
404
      procedure Output_Element (N : Node_Id; T : Character) is
405
         FSloc : Source_Ptr;
406
         LSloc : Source_Ptr;
407
      begin
408
         Sloc_Range (N, FSloc, LSloc);
409
         Set_Table_Entry (T, 'c', FSloc, LSloc, False);
410
         Condition_Hash_Table.Set (FSloc, SCO_Table.Last);
411
      end Output_Element;
412
 
413
      ------------------------------
414
      -- Process_Decision_Operand --
415
      ------------------------------
416
 
417
      procedure Process_Decision_Operand (N : Node_Id) is
418
      begin
419
         if Is_Logical_Operator (N) then
420
            if Nkind (N) /= N_Op_Not then
421
               Process_Decision_Operand (Left_Opnd (N));
422
            end if;
423
 
424
            Process_Decision_Operand (Right_Opnd (N));
425
 
426
         else
427
            Process_Decisions (N, 'X');
428
         end if;
429
      end Process_Decision_Operand;
430
 
431
      ------------------
432
      -- Process_Node --
433
      ------------------
434
 
435
      function Process_Node (N : Node_Id) return Traverse_Result is
436
      begin
437
         case Nkind (N) is
438
 
439
               --  Logical operators, output table entries and then process
440
               --  operands recursively to deal with nested conditions.
441
 
442
            when N_And_Then                    |
443
                 N_Or_Else                     |
444
                 N_Op_Not                      =>
445
 
446
               declare
447
                  T : Character;
448
 
449
               begin
450
                  --  If outer level, then type comes from call, otherwise it
451
                  --  is more deeply nested and counts as X for expression.
452
 
453
                  if N = Process_Decisions.N then
454
                     T := Process_Decisions.T;
455
                  else
456
                     T := 'X';
457
                  end if;
458
 
459
                  --  Output header for sequence
460
 
461
                  Set_Table_Entry (T, ' ', No_Location, No_Location, False);
462
 
463
                  --  Output the decision
464
 
465
                  Output_Decision_Operand (N);
466
 
467
                  --  Change Last in last table entry to True to mark end
468
 
469
                  SCO_Table.Table (SCO_Table.Last).Last := True;
470
 
471
                  --  Process any embedded decisions
472
 
473
                  Process_Decision_Operand (N);
474
                  return Skip;
475
               end;
476
 
477
            --  Conditional expression, processed like an if statement
478
 
479
            when N_Conditional_Expression      =>
480
               declare
481
                  Cond : constant Node_Id := First (Expressions (N));
482
                  Thnx : constant Node_Id := Next (Cond);
483
                  Elsx : constant Node_Id := Next (Thnx);
484
               begin
485
                  Process_Decisions (Cond, 'I');
486
                  Process_Decisions (Thnx, 'X');
487
                  Process_Decisions (Elsx, 'X');
488
                  return Skip;
489
               end;
490
 
491
            --  All other cases, continue scan
492
 
493
            when others =>
494
               return OK;
495
 
496
         end case;
497
      end Process_Node;
498
 
499
      procedure Traverse is new Traverse_Proc (Process_Node);
500
 
501
   --  Start of processing for Process_Decisions
502
 
503
   begin
504
      if No (N) then
505
         return;
506
      end if;
507
 
508
      --  See if we have simple decision at outer level and if so then
509
      --  generate the decision entry for this simple decision. A simple
510
      --  decision is a boolean expression (which is not a logical operator
511
      --  or short circuit form) appearing as the operand of an IF, WHILE
512
      --  or EXIT WHEN construct.
513
 
514
      if T /= 'X' and then not Is_Logical_Operator (N) then
515
         Output_Element (N, T);
516
 
517
         --  Change Last in last table entry to True to mark end of
518
         --  sequence, which is this case is only one element long.
519
 
520
         SCO_Table.Table (SCO_Table.Last).Last := True;
521
      end if;
522
 
523
      Traverse (N);
524
   end Process_Decisions;
525
 
526
   -----------
527
   -- pscos --
528
   -----------
529
 
530
   procedure pscos is
531
 
532
      procedure Write_Info_Char (C : Character) renames Write_Char;
533
      --  Write one character;
534
 
535
      procedure Write_Info_Initiate (Key : Character) renames Write_Char;
536
      --  Start new one and write one character;
537
 
538
      procedure Write_Info_Nat (N : Nat);
539
      --  Write value of N
540
 
541
      procedure Write_Info_Terminate renames Write_Eol;
542
      --  Terminate current line
543
 
544
      --------------------
545
      -- Write_Info_Nat --
546
      --------------------
547
 
548
      procedure Write_Info_Nat (N : Nat) is
549
      begin
550
         Write_Int (N);
551
      end Write_Info_Nat;
552
 
553
      procedure Debug_Put_SCOs is new Put_SCOs;
554
 
555
      --  Start of processing for pscos
556
 
557
   begin
558
      Debug_Put_SCOs;
559
   end pscos;
560
 
561
   ----------------
562
   -- SCO_Output --
563
   ----------------
564
 
565
   procedure SCO_Output is
566
   begin
567
      if Debug_Flag_Dot_OO then
568
         dsco;
569
      end if;
570
 
571
      --  Sort the unit tables based on dependency numbers
572
 
573
      Unit_Table_Sort : declare
574
 
575
         function Lt (Op1, Op2 : Natural) return Boolean;
576
         --  Comparison routine for sort call
577
 
578
         procedure Move (From : Natural; To : Natural);
579
         --  Move routine for sort call
580
 
581
         --------
582
         -- Lt --
583
         --------
584
 
585
         function Lt (Op1, Op2 : Natural) return Boolean is
586
         begin
587
            return
588
              Dependency_Num
589
                (SCO_Unit_Number_Table.Table (SCO_Unit_Index (Op1)))
590
                     <
591
              Dependency_Num
592
                (SCO_Unit_Number_Table.Table (SCO_Unit_Index (Op2)));
593
         end Lt;
594
 
595
         ----------
596
         -- Move --
597
         ----------
598
 
599
         procedure Move (From : Natural; To : Natural) is
600
         begin
601
            SCO_Unit_Table.Table (SCO_Unit_Index (To)) :=
602
              SCO_Unit_Table.Table (SCO_Unit_Index (From));
603
            SCO_Unit_Number_Table.Table (SCO_Unit_Index (To)) :=
604
              SCO_Unit_Number_Table.Table (SCO_Unit_Index (From));
605
         end Move;
606
 
607
         package Sorting is new GNAT.Heap_Sort_G (Move, Lt);
608
 
609
      --  Start of processing for Unit_Table_Sort
610
 
611
      begin
612
         Sorting.Sort (Integer (SCO_Unit_Table.Last));
613
      end Unit_Table_Sort;
614
 
615
      --  Loop through entries in the unit table to set file name and
616
      --  dependency number entries.
617
 
618
      for J in 1 .. SCO_Unit_Table.Last loop
619
         declare
620
            U   : constant Unit_Number_Type := SCO_Unit_Number_Table.Table (J);
621
            UTE : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J);
622
         begin
623
            Get_Name_String (Reference_Name (Source_Index (U)));
624
            UTE.File_Name := new String'(Name_Buffer (1 .. Name_Len));
625
            UTE.Dep_Num := Dependency_Num (U);
626
         end;
627
      end loop;
628
 
629
      --  Now the tables are all setup for output to the ALI file
630
 
631
      Write_SCOs_To_ALI_File;
632
   end SCO_Output;
633
 
634
   ----------------
635
   -- SCO_Record --
636
   ----------------
637
 
638
   procedure SCO_Record (U : Unit_Number_Type) is
639
      Lu   : Node_Id;
640
      From : Nat;
641
 
642
   begin
643
      --  Ignore call if not generating code and generating SCO's
644
 
645
      if not (Generate_SCO and then Operating_Mode = Generate_Code) then
646
         return;
647
      end if;
648
 
649
      --  Ignore call if this unit already recorded
650
 
651
      for J in 1 .. SCO_Unit_Number_Table.Last loop
652
         if U = SCO_Unit_Number_Table.Table (J) then
653
            return;
654
         end if;
655
      end loop;
656
 
657
      --  Otherwise record starting entry
658
 
659
      From := SCO_Table.Last + 1;
660
 
661
      --  Get Unit (checking case of subunit)
662
 
663
      Lu := Unit (Cunit (U));
664
 
665
      if Nkind (Lu) = N_Subunit then
666
         Lu := Proper_Body (Lu);
667
      end if;
668
 
669
      --  Traverse the unit
670
 
671
      if Nkind (Lu) = N_Subprogram_Body then
672
         Traverse_Subprogram_Body (Lu);
673
 
674
      elsif Nkind (Lu) = N_Package_Declaration then
675
         Traverse_Package_Declaration (Lu);
676
 
677
      elsif Nkind (Lu) = N_Package_Body then
678
         Traverse_Package_Body (Lu);
679
 
680
      elsif Nkind (Lu) = N_Generic_Package_Declaration then
681
         Traverse_Generic_Package_Declaration (Lu);
682
 
683
      --  For anything else, the only issue is default expressions for
684
      --  parameters, where we have to worry about possible embedded decisions
685
      --  but nothing else.
686
 
687
      else
688
         Process_Decisions (Lu, 'X');
689
      end if;
690
 
691
      --  Make entry for new unit in unit tables, we will fill in the file
692
      --  name and dependency numbers later.
693
 
694
      SCO_Unit_Table.Append (
695
        (Dep_Num   => 0,
696
         File_Name => null,
697
         From      => From,
698
         To        => SCO_Table.Last));
699
 
700
      SCO_Unit_Number_Table.Append (U);
701
   end SCO_Record;
702
 
703
   -----------------------
704
   -- Set_SCO_Condition --
705
   -----------------------
706
 
707
   procedure Set_SCO_Condition (First_Loc : Source_Ptr; Typ : Character) is
708
      Index : constant Nat := Condition_Hash_Table.Get (First_Loc);
709
   begin
710
      if Index /= 0 then
711
         SCO_Table.Table (Index).C2 := Typ;
712
      end if;
713
   end Set_SCO_Condition;
714
 
715
   ---------------------
716
   -- Set_Table_Entry --
717
   ---------------------
718
 
719
   procedure Set_Table_Entry
720
     (C1   : Character;
721
      C2   : Character;
722
      From : Source_Ptr;
723
      To   : Source_Ptr;
724
      Last : Boolean)
725
   is
726
      function To_Source_Location (S : Source_Ptr) return Source_Location;
727
      --  Converts Source_Ptr value to Source_Location (line/col) format
728
 
729
      ------------------------
730
      -- To_Source_Location --
731
      ------------------------
732
 
733
      function To_Source_Location (S : Source_Ptr) return Source_Location is
734
      begin
735
         if S = No_Location then
736
            return No_Source_Location;
737
         else
738
            return
739
              (Line => Get_Logical_Line_Number (S),
740
               Col  => Get_Column_Number (S));
741
         end if;
742
      end To_Source_Location;
743
 
744
   --  Start of processing for Set_Table_Entry
745
 
746
   begin
747
      Add_SCO
748
        (C1   => C1,
749
         C2   => C2,
750
         From => To_Source_Location (From),
751
         To   => To_Source_Location (To),
752
         Last => Last);
753
   end Set_Table_Entry;
754
 
755
   -----------------------------------------
756
   -- Traverse_Declarations_Or_Statements --
757
   -----------------------------------------
758
 
759
   procedure Traverse_Declarations_Or_Statements (L : List_Id) is
760
      N     : Node_Id;
761
      Dummy : Source_Ptr;
762
 
763
      type SC_Entry is record
764
         From : Source_Ptr;
765
         To   : Source_Ptr;
766
         Typ  : Character;
767
      end record;
768
      --  Used to store a single entry in the following array
769
 
770
      SC_Array : array (Nat range 1 .. 10_000) of SC_Entry;
771
      SC_Last  : Nat;
772
      --  Used to store statement components for a CS entry to be output
773
      --  as a result of the call to this procedure. SC_Last is the last
774
      --  entry stored, so the current statement sequence is represented
775
      --  by SC_Array (1 .. SC_Last). Extend_Statement_Sequence adds an
776
      --  entry to this array, and Set_Statement_Entry clears it, copying
777
      --  the entries to the main SCO output table. The reason that we do
778
      --  the temporary caching of results in this array is that we want
779
      --  the SCO table entries for a given CS line to be contiguous, and
780
      --  the processing may output intermediate entries such as decision
781
      --  entries. Note that the limit of 10_000 here is arbitrary, but does
782
      --  not cause any trouble, if we encounter more than 10_000 statements
783
      --  we simply break the current CS sequence at that point, which is
784
      --  harmless, since this is only used for back annotation and it is
785
      --  not critical that back annotation always work in all cases. Anyway
786
      --  exceeding 10,000 statements in a basic block is very unlikely.
787
 
788
      procedure Extend_Statement_Sequence (N : Node_Id; Typ : Character);
789
      --  Extend the current statement sequence to encompass the node N. Typ
790
      --  is the letter that identifies the type of statement/declaration that
791
      --  is being added to the sequence.
792
 
793
      procedure Extend_Statement_Sequence
794
        (From : Node_Id;
795
         To   : Node_Id;
796
         Typ  : Character);
797
      --  This version extends the current statement sequence with an entry
798
      --  that starts with the first token of From, and ends with the last
799
      --  token of To. It is used for example in a CASE statement to cover
800
      --  the range from the CASE token to the last token of the expression.
801
 
802
      procedure Set_Statement_Entry;
803
      --  If Start is No_Location, does nothing, otherwise outputs a SCO_Table
804
      --  statement entry for the range Start-Stop and then sets both Start
805
      --  and Stop to No_Location. Unconditionally sets Term to True. This is
806
      --  called when we find a statement or declaration that generates its
807
      --  own table entry, so that we must end the current statement sequence.
808
 
809
      -------------------------
810
      -- Set_Statement_Entry --
811
      -------------------------
812
 
813
      procedure Set_Statement_Entry is
814
         C1   : Character;
815
 
816
      begin
817
         if SC_Last /= 0 then
818
            for J in 1 .. SC_Last loop
819
               if J = 1 then
820
                  C1 := 'S';
821
               else
822
                  C1 := 's';
823
               end if;
824
 
825
               Set_Table_Entry
826
                 (C1   => C1,
827
                  C2   => SC_Array (J).Typ,
828
                  From => SC_Array (J).From,
829
                  To   => SC_Array (J).To,
830
                  Last => (J = SC_Last));
831
            end loop;
832
 
833
            SC_Last := 0;
834
         end if;
835
      end Set_Statement_Entry;
836
 
837
      -------------------------------
838
      -- Extend_Statement_Sequence --
839
      -------------------------------
840
 
841
      procedure Extend_Statement_Sequence (N : Node_Id; Typ : Character) is
842
      begin
843
         --  Clear out statement sequence if array full
844
 
845
         if SC_Last = SC_Array'Last then
846
            Set_Statement_Entry;
847
         else
848
            SC_Last := SC_Last + 1;
849
         end if;
850
 
851
         --  Record new entry
852
 
853
         Sloc_Range
854
           (N, SC_Array (SC_Last).From, SC_Array (SC_Last).To);
855
         SC_Array (SC_Last).Typ := Typ;
856
      end Extend_Statement_Sequence;
857
 
858
      procedure Extend_Statement_Sequence
859
        (From : Node_Id;
860
         To   : Node_Id;
861
         Typ  : Character)
862
      is
863
      begin
864
         --  Clear out statement sequence if array full
865
 
866
         if SC_Last = SC_Array'Last then
867
            Set_Statement_Entry;
868
         else
869
            SC_Last := SC_Last + 1;
870
         end if;
871
 
872
         --  Make new entry
873
 
874
         Sloc_Range (From, SC_Array (SC_Last).From, Dummy);
875
         Sloc_Range (To, Dummy, SC_Array (SC_Last).To);
876
         SC_Array (SC_Last).Typ := Typ;
877
      end Extend_Statement_Sequence;
878
 
879
   --  Start of processing for Traverse_Declarations_Or_Statements
880
 
881
   begin
882
      if Is_Non_Empty_List (L) then
883
         SC_Last := 0;
884
 
885
         --  Loop through statements or declarations
886
 
887
         N := First (L);
888
         while Present (N) loop
889
 
890
            --  Initialize or extend current statement sequence. Note that for
891
            --  special cases such as IF and Case statements we will modify
892
            --  the range to exclude internal statements that should not be
893
            --  counted as part of the current statement sequence.
894
 
895
            case Nkind (N) is
896
 
897
               --  Package declaration
898
 
899
               when N_Package_Declaration =>
900
                  Set_Statement_Entry;
901
                  Traverse_Package_Declaration (N);
902
 
903
               --  Generic package declaration
904
 
905
               when N_Generic_Package_Declaration =>
906
                  Set_Statement_Entry;
907
                  Traverse_Generic_Package_Declaration (N);
908
 
909
               --  Package body
910
 
911
               when N_Package_Body =>
912
                  Set_Statement_Entry;
913
                  Traverse_Package_Body (N);
914
 
915
               --  Subprogram declaration
916
 
917
               when N_Subprogram_Declaration =>
918
                  Set_Statement_Entry;
919
                  Process_Decisions
920
                    (Parameter_Specifications (Specification (N)), 'X');
921
 
922
               --  Generic subprogram declaration
923
 
924
               when N_Generic_Subprogram_Declaration =>
925
                  Set_Statement_Entry;
926
                  Process_Decisions (Generic_Formal_Declarations (N), 'X');
927
                  Process_Decisions
928
                    (Parameter_Specifications (Specification (N)), 'X');
929
 
930
               --  Subprogram_Body
931
 
932
               when N_Subprogram_Body =>
933
                  Set_Statement_Entry;
934
                  Traverse_Subprogram_Body (N);
935
 
936
               --  Exit statement, which is an exit statement in the SCO sense,
937
               --  so it is included in the current statement sequence, but
938
               --  then it terminates this sequence. We also have to process
939
               --  any decisions in the exit statement expression.
940
 
941
               when N_Exit_Statement =>
942
                  Extend_Statement_Sequence (N, ' ');
943
                  Set_Statement_Entry;
944
                  Process_Decisions (Condition (N), 'E');
945
 
946
               --  Label, which breaks the current statement sequence, but the
947
               --  label itself is not included in the next statement sequence,
948
               --  since it generates no code.
949
 
950
               when N_Label =>
951
                  Set_Statement_Entry;
952
 
953
               --  Block statement, which breaks the current statement sequence
954
 
955
               when N_Block_Statement =>
956
                  Set_Statement_Entry;
957
                  Traverse_Declarations_Or_Statements (Declarations (N));
958
                  Traverse_Handled_Statement_Sequence
959
                    (Handled_Statement_Sequence (N));
960
 
961
               --  If statement, which breaks the current statement sequence,
962
               --  but we include the condition in the current sequence.
963
 
964
               when N_If_Statement =>
965
                  Extend_Statement_Sequence (N, Condition (N), 'I');
966
                  Set_Statement_Entry;
967
                  Process_Decisions (Condition (N), 'I');
968
                  Traverse_Declarations_Or_Statements (Then_Statements (N));
969
 
970
                  if Present (Elsif_Parts (N)) then
971
                     declare
972
                        Elif : Node_Id := First (Elsif_Parts (N));
973
                     begin
974
                        while Present (Elif) loop
975
                           Process_Decisions (Condition (Elif), 'I');
976
                           Traverse_Declarations_Or_Statements
977
                             (Then_Statements (Elif));
978
                           Next (Elif);
979
                        end loop;
980
                     end;
981
                  end if;
982
 
983
                  Traverse_Declarations_Or_Statements (Else_Statements (N));
984
 
985
               --  Case statement, which breaks the current statement sequence,
986
               --  but we include the expression in the current sequence.
987
 
988
               when N_Case_Statement =>
989
                  Extend_Statement_Sequence (N, Expression (N), 'C');
990
                  Set_Statement_Entry;
991
                  Process_Decisions (Expression (N), 'X');
992
 
993
                  --  Process case branches
994
 
995
                  declare
996
                     Alt : Node_Id;
997
 
998
                  begin
999
                     Alt := First (Alternatives (N));
1000
                     while Present (Alt) loop
1001
                        Traverse_Declarations_Or_Statements (Statements (Alt));
1002
                        Next (Alt);
1003
                     end loop;
1004
                  end;
1005
 
1006
               --  Unconditional exit points, which are included in the current
1007
               --  statement sequence, but then terminate it
1008
 
1009
               when N_Requeue_Statement |
1010
                    N_Goto_Statement    |
1011
                    N_Raise_Statement   =>
1012
                  Extend_Statement_Sequence (N, ' ');
1013
                  Set_Statement_Entry;
1014
 
1015
               --  Simple return statement. which is an exit point, but we
1016
               --  have to process the return expression for decisions.
1017
 
1018
               when N_Simple_Return_Statement =>
1019
                  Extend_Statement_Sequence (N, ' ');
1020
                  Set_Statement_Entry;
1021
                  Process_Decisions (Expression (N), 'X');
1022
 
1023
               --  Extended return statement
1024
 
1025
               when N_Extended_Return_Statement =>
1026
                  declare
1027
                     Odecl : constant Node_Id :=
1028
                               First (Return_Object_Declarations (N));
1029
                  begin
1030
                     if Present (Expression (Odecl)) then
1031
                        Extend_Statement_Sequence
1032
                          (N, Expression (Odecl), 'R');
1033
                        Process_Decisions (Expression (Odecl), 'X');
1034
                     end if;
1035
                  end;
1036
 
1037
                  Traverse_Handled_Statement_Sequence
1038
                    (Handled_Statement_Sequence (N));
1039
 
1040
               --  Loop ends the current statement sequence, but we include
1041
               --  the iteration scheme if present in the current sequence.
1042
               --  But the body of the loop starts a new sequence, since it
1043
               --  may not be executed as part of the current sequence.
1044
 
1045
               when N_Loop_Statement =>
1046
                  if Present (Iteration_Scheme (N)) then
1047
 
1048
                     --  If iteration scheme present, extend the current
1049
                     --  statement sequence to include the iteration scheme
1050
                     --  and process any decisions it contains.
1051
 
1052
                     declare
1053
                        ISC : constant Node_Id := Iteration_Scheme (N);
1054
 
1055
                     begin
1056
                        --  While statement
1057
 
1058
                        if Present (Condition (ISC)) then
1059
                           Extend_Statement_Sequence (N, ISC, 'W');
1060
                           Process_Decisions (Condition (ISC), 'W');
1061
 
1062
                        --  For statement
1063
 
1064
                        else
1065
                           Extend_Statement_Sequence (N, ISC, 'F');
1066
                           Process_Decisions
1067
                             (Loop_Parameter_Specification (ISC), 'X');
1068
                        end if;
1069
                     end;
1070
                  end if;
1071
 
1072
                  Set_Statement_Entry;
1073
                  Traverse_Declarations_Or_Statements (Statements (N));
1074
 
1075
               --  Pragma
1076
 
1077
               when N_Pragma =>
1078
                  Extend_Statement_Sequence (N, 'P');
1079
 
1080
                  --  For pragmas Assert, Check, Precondition, and
1081
                  --  Postcondition, we generate decision entries for the
1082
                  --  condition only if the pragma is enabled. For now, we just
1083
                  --  check Assertions_Enabled, which will be set to reflect
1084
                  --  the presence of -gnata.
1085
 
1086
                  --  Later we should move processing of the relevant pragmas
1087
                  --  to Par_Prag, and properly set the flag Pragma_Enabled at
1088
                  --  parse time, so that we can check this flag instead ???
1089
 
1090
                  --  For all other pragmas, we always generate decision
1091
                  --  entries for any embedded expressions.
1092
 
1093
                  declare
1094
                     Nam : constant Name_Id :=
1095
                             Chars (Pragma_Identifier (N));
1096
                     Arg : Node_Id := First (Pragma_Argument_Associations (N));
1097
                  begin
1098
                     case Nam is
1099
                        when Name_Assert        |
1100
                             Name_Check         |
1101
                             Name_Precondition  |
1102
                             Name_Postcondition =>
1103
 
1104
                           if Nam = Name_Check then
1105
                              Next (Arg);
1106
                           end if;
1107
 
1108
                           if Assertions_Enabled then
1109
                              Process_Decisions (Expression (Arg), 'P');
1110
                           end if;
1111
 
1112
                        when others =>
1113
                           Process_Decisions (N, 'X');
1114
                     end case;
1115
                  end;
1116
 
1117
               --  All other cases, which extend the current statement sequence
1118
               --  but do not terminate it, even if they have nested decisions.
1119
 
1120
               when others =>
1121
 
1122
                  --  Determine required type character code
1123
 
1124
                  declare
1125
                     Typ : Character;
1126
 
1127
                  begin
1128
                     case Nkind (N) is
1129
                        when N_Full_Type_Declaration         |
1130
                             N_Incomplete_Type_Declaration   |
1131
                             N_Private_Type_Declaration      |
1132
                             N_Private_Extension_Declaration =>
1133
                           Typ := 't';
1134
 
1135
                        when N_Subtype_Declaration           =>
1136
                           Typ := 's';
1137
 
1138
                        when N_Object_Declaration            =>
1139
                           Typ := 'o';
1140
 
1141
                        when N_Renaming_Declaration          =>
1142
                           Typ := 'r';
1143
 
1144
                        when N_Generic_Instantiation         =>
1145
                           Typ := 'i';
1146
 
1147
                        when others                          =>
1148
                           Typ := ' ';
1149
                     end case;
1150
 
1151
                     Extend_Statement_Sequence (N, Typ);
1152
                  end;
1153
 
1154
                  --  Process any embedded decisions
1155
 
1156
                  if Has_Decision (N) then
1157
                     Process_Decisions (N, 'X');
1158
                  end if;
1159
            end case;
1160
 
1161
            Next (N);
1162
         end loop;
1163
 
1164
         Set_Statement_Entry;
1165
      end if;
1166
   end Traverse_Declarations_Or_Statements;
1167
 
1168
   ------------------------------------------
1169
   -- Traverse_Generic_Package_Declaration --
1170
   ------------------------------------------
1171
 
1172
   procedure Traverse_Generic_Package_Declaration (N : Node_Id) is
1173
   begin
1174
      Process_Decisions (Generic_Formal_Declarations (N), 'X');
1175
      Traverse_Package_Declaration (N);
1176
   end Traverse_Generic_Package_Declaration;
1177
 
1178
   -----------------------------------------
1179
   -- Traverse_Handled_Statement_Sequence --
1180
   -----------------------------------------
1181
 
1182
   procedure Traverse_Handled_Statement_Sequence (N : Node_Id) is
1183
      Handler : Node_Id;
1184
 
1185
   begin
1186
 
1187
      --  For package bodies without a statement part, the parser adds an empty
1188
      --  one, to normalize the representation. The null statement therein,
1189
      --  which does not come from source, does not get a SCO.
1190
 
1191
      if Present (N) and then Comes_From_Source (N) then
1192
         Traverse_Declarations_Or_Statements (Statements (N));
1193
 
1194
         if Present (Exception_Handlers (N)) then
1195
            Handler := First (Exception_Handlers (N));
1196
            while Present (Handler) loop
1197
               Traverse_Declarations_Or_Statements (Statements (Handler));
1198
               Next (Handler);
1199
            end loop;
1200
         end if;
1201
      end if;
1202
   end Traverse_Handled_Statement_Sequence;
1203
 
1204
   ---------------------------
1205
   -- Traverse_Package_Body --
1206
   ---------------------------
1207
 
1208
   procedure Traverse_Package_Body (N : Node_Id) is
1209
   begin
1210
      Traverse_Declarations_Or_Statements (Declarations (N));
1211
      Traverse_Handled_Statement_Sequence (Handled_Statement_Sequence (N));
1212
   end Traverse_Package_Body;
1213
 
1214
   ----------------------------------
1215
   -- Traverse_Package_Declaration --
1216
   ----------------------------------
1217
 
1218
   procedure Traverse_Package_Declaration (N : Node_Id) is
1219
      Spec : constant Node_Id := Specification (N);
1220
   begin
1221
      Traverse_Declarations_Or_Statements (Visible_Declarations (Spec));
1222
      Traverse_Declarations_Or_Statements (Private_Declarations (Spec));
1223
   end Traverse_Package_Declaration;
1224
 
1225
   ------------------------------
1226
   -- Traverse_Subprogram_Body --
1227
   ------------------------------
1228
 
1229
   procedure Traverse_Subprogram_Body (N : Node_Id) is
1230
   begin
1231
      Traverse_Declarations_Or_Statements (Declarations (N));
1232
      Traverse_Handled_Statement_Sequence (Handled_Statement_Sequence (N));
1233
   end Traverse_Subprogram_Body;
1234
 
1235
end Par_SCO;

powered by: WebSVN 2.1.0

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