public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Ada] SCO generation for pragma Debug
@ 2011-08-05 14:30 Arnaud Charlet
  0 siblings, 0 replies; only message in thread
From: Arnaud Charlet @ 2011-08-05 14:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: Thomas Quinot

[-- Attachment #1: Type: text/plain, Size: 1496 bytes --]

This change improves the SCO generation circuitry for pragma Debug.
Specific support is added for dyadic pragma Debug (where the first argument
is now treated as a P decision). SCO generation is suppressed altogether
for any pragma Debug, or decision nested therein, if the pragma is not
enabled.

The below unit must produce the indicated SCOs:

$ gcc -c -gnateS pragma_debug_scos.adb
CS 8:4-8:4

$ gcc -c -gnata -gnateS pragma_debug_scos.adb
CS P4:4-4:28 P5:4-5:65 P6:4-6:31 P7:4-7:74 8:4-8:4
CX &5:56 c5:54-5:54 c5:65-5:65
CP 6:4 c6:18-6:18
CP 7:4 c7:18-7:18
CX |7:66 c7:64-7:64 c7:74-7:74

with Ada.Text_IO; use Ada.Text_IO;
procedure Pragma_Debug_SCOs (A, B : Boolean) is
begin
   pragma Debug (Put_Line ("foo"));
   pragma Debug (Put_Line ("A&&B: " & Boolean'Image (A and then B)));
   pragma Debug (A, Put_Line ("A is True"));
   pragma Debug (B, Put_Line ("B True, A||B:" & Boolean'Image (A or else B)));
   null;
end Pragma_Debug_SCOs;

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-05  Thomas Quinot  <quinot@adacore.com>

	* scos.ads: Update documentation of SCO table. Pragma statements can now
	be marked as disabled (using 'p' instead of 'P' as the statement kind).
	* par_sco.ads, par_sco.adb: Implement the above change.
	(Process_Decisions_Defer): Generate a P decision for the first parameter
	of a dyadic pragma Debug.
	* sem_prag.adb (Analyze_Pragma, case Debug): Mark pragma as enabled if
	necessary.
	* put_scos.adb: Code simplification based on above change.


[-- Attachment #2: difs --]
[-- Type: text/plain, Size: 21432 bytes --]

Index: par_sco.adb
===================================================================
--- par_sco.adb	(revision 177431)
+++ par_sco.adb	(working copy)
@@ -69,9 +69,9 @@
 
    --  We need to be able to get to conditions quickly for handling the calls
    --  to Set_SCO_Condition efficiently, and similarly to get to pragmas to
-   --  handle calls to Set_SCO_Pragma_Enabled. For this purpose we identify the
-   --  conditions and pragmas in the table by their starting sloc, and use this
-   --  hash table to map from these starting sloc values to SCO_Table indexes.
+   --  handle calls to Set_SCO_Pragma_Enabled. For this purpose we identify
+   --  the conditions and pragmas in the table by their starting sloc, and use
+   --  this hash table to map from these sloc values to SCO_Table indexes.
 
    type Header_Num is new Integer range 0 .. 996;
    --  Type for hash table headers
@@ -101,7 +101,10 @@
    --  excluding OR and AND) and returns True if so, False otherwise, it does
    --  no other processing.
 
-   procedure Process_Decisions (N : Node_Id; T : Character);
+   procedure Process_Decisions
+     (N           : Node_Id;
+      T           : Character;
+      Pragma_Sloc : Source_Ptr);
    --  If N is Empty, has no effect. Otherwise scans the tree for the node N,
    --  to output any decisions it contains. T is one of IEGPWX (for context of
    --  expression: if/exit when/entry guard/pragma/while/expression). If T is
@@ -109,7 +112,10 @@
    --  decision is always present (at the very least a simple decision is
    --  present at the top level).
 
-   procedure Process_Decisions (L : List_Id; T : Character);
+   procedure Process_Decisions
+     (L           : List_Id;
+      T           : Character;
+      Pragma_Sloc : Source_Ptr);
    --  Calls above procedure for each element of the list L
 
    procedure Set_Table_Entry
@@ -316,13 +322,17 @@
 
    --  Version taking a list
 
-   procedure Process_Decisions (L : List_Id; T : Character) is
+   procedure Process_Decisions
+     (L           : List_Id;
+      T           : Character;
+      Pragma_Sloc : Source_Ptr)
+   is
       N : Node_Id;
    begin
       if L /= No_List then
          N := First (L);
          while Present (N) loop
-            Process_Decisions (N, T);
+            Process_Decisions (N, T, Pragma_Sloc);
             Next (N);
          end loop;
       end if;
@@ -330,11 +340,14 @@
 
    --  Version taking a node
 
-   Pragma_Sloc : Source_Ptr := No_Location;
-   --  While processing decisions within a pragma Assert/Debug/PPC, this is set
-   --  to the sloc of the pragma.
+   Current_Pragma_Sloc : Source_Ptr := No_Location;
+   --  While processing a pragma, this is set to the sloc of the N_Pragma node
 
-   procedure Process_Decisions (N : Node_Id; T : Character) is
+   procedure Process_Decisions
+     (N           : Node_Id;
+      T           : Character;
+      Pragma_Sloc : Source_Ptr)
+   is
       Mark : Nat;
       --  This is used to mark the location of a decision sequence in the SCO
       --  table. We use it for backing out a simple decision in an expression
@@ -466,14 +479,6 @@
 
                Loc := Sloc (Parent (Parent (N)));
 
-               if T = 'P' then
-
-                  --  Record sloc of pragma (pragmas don't nest)
-
-                  pragma Assert (Pragma_Sloc = No_Location);
-                  Pragma_Sloc := Loc;
-               end if;
-
             when 'X' =>
 
                --  For an expression, no Sloc
@@ -493,17 +498,6 @@
             To          => No_Location,
             Last        => False,
             Pragma_Sloc => Pragma_Sloc);
-
-         if T = 'P' then
-
-            --  For pragmas we also must make an entry in the hash table for
-            --  later access by Set_SCO_Pragma_Enabled. We set the pragma as
-            --  disabled now, the call will change C2 to 'e' to enable the
-            --  pragma header entry.
-
-            SCO_Table.Table (SCO_Table.Last).C2 := 'd';
-            Condition_Pragma_Hash_Table.Set (Loc, SCO_Table.Last);
-         end if;
       end Output_Header;
 
       ------------------------------
@@ -521,7 +515,7 @@
             Process_Decision_Operand (Right_Opnd (N));
 
          else
-            Process_Decisions (N, 'X');
+            Process_Decisions (N, 'X', Pragma_Sloc);
          end if;
       end Process_Decision_Operand;
 
@@ -595,9 +589,9 @@
                   Thnx : constant Node_Id := Next (Cond);
                   Elsx : constant Node_Id := Next (Thnx);
                begin
-                  Process_Decisions (Cond, 'I');
-                  Process_Decisions (Thnx, 'X');
-                  Process_Decisions (Elsx, 'X');
+                  Process_Decisions (Cond, 'I', Pragma_Sloc);
+                  Process_Decisions (Thnx, 'X', Pragma_Sloc);
+                  Process_Decisions (Elsx, 'X', Pragma_Sloc);
                   return Skip;
                end;
 
@@ -635,12 +629,6 @@
       end if;
 
       Traverse (N);
-
-      --  Reset Pragma_Sloc after full subtree traversal
-
-      if T = 'P' then
-         Pragma_Sloc := No_Location;
-      end if;
    end Process_Decisions;
 
    -----------
@@ -771,8 +759,12 @@
       --  disabled.
 
       if Index /= 0 then
-         pragma Assert (SCO_Table.Table (Index).C1 = 'P');
-         return SCO_Table.Table (Index).C2 = 'd';
+         declare
+            T : SCO_Table_Entry renames SCO_Table.Table (Index);
+         begin
+            pragma Assert (T.C1 = 'S' or else T.C1 = 's');
+            return T.C2 = 'p';
+         end;
 
       else
          return False;
@@ -899,8 +891,17 @@
       --  The test here for zero is to deal with possible previous errors
 
       if Index /= 0 then
-         pragma Assert (SCO_Table.Table (Index).C1 = 'P');
-         SCO_Table.Table (Index).C2 := 'e';
+         declare
+            T : SCO_Table_Entry renames SCO_Table.Table (Index);
+         begin
+            --  Called multiple times for the same sloc (need to allow for
+            --  C2 = 'P') ???
+
+            pragma Assert ((T.C1 = 'S' or else T.C1 = 's')
+                             and then
+                           (T.C2 = 'p' or else T.C2 = 'P'));
+            T.C2 := 'P';
+         end;
       end if;
    end Set_SCO_Pragma_Enabled;
 
@@ -987,12 +988,14 @@
       Nod : Node_Id;
       Lst : List_Id;
       Typ : Character;
+      Plo : Source_Ptr;
    end record;
    --  Used to store a single entry in the following table. Nod is the node to
    --  be searched for decisions for the case of Process_Decisions_Defer with a
    --  node argument (with Lst set to No_List. Lst is the list to be searched
    --  for decisions for the case of Process_Decisions_Defer with a List
-   --  argument (in which case Nod is set to Empty).
+   --  argument (in which case Nod is set to Empty). Plo is the sloc of the
+   --  enclosing pragma, if any.
 
    package SD is new Table.Table (
      Table_Component_Type => SD_Entry,
@@ -1077,11 +1080,15 @@
                SCE         : SC_Entry renames SC.Table (J);
                Pragma_Sloc : Source_Ptr := No_Location;
             begin
-               --  For the statement SCO for a pragma, set Pragma_Sloc so that
-               --  the SCO can be omitted if the pragma is disabled.
+               --  For the statement SCO for a pragma controlled by
+               --  Set_SCO_Pragma_Enable, set Pragma_Sloc so that the SCO (and
+               --  those of any nested decision) is emitted only if the pragma
+               --  is enabled.
 
-               if SCE.Typ = 'P' then
+               if SCE.Typ = 'p' then
                   Pragma_Sloc := SCE.From;
+                  Condition_Pragma_Hash_Table.Set
+                    (Pragma_Sloc, SCO_Table.Last + 1);
                end if;
 
                Set_Table_Entry
@@ -1105,9 +1112,9 @@
                SDE : SD_Entry renames SD.Table (J);
             begin
                if Present (SDE.Nod) then
-                  Process_Decisions (SDE.Nod, SDE.Typ);
+                  Process_Decisions (SDE.Nod, SDE.Typ, SDE.Plo);
                else
-                  Process_Decisions (SDE.Lst, SDE.Typ);
+                  Process_Decisions (SDE.Lst, SDE.Typ, SDE.Plo);
                end if;
             end;
          end loop;
@@ -1148,12 +1155,12 @@
 
       procedure Process_Decisions_Defer (N : Node_Id; T : Character) is
       begin
-         SD.Append ((N, No_List, T));
+         SD.Append ((N, No_List, T, Current_Pragma_Sloc));
       end Process_Decisions_Defer;
 
       procedure Process_Decisions_Defer (L : List_Id; T : Character) is
       begin
-         SD.Append ((Empty, L, T));
+         SD.Append ((Empty, L, T, Current_Pragma_Sloc));
       end Process_Decisions_Defer;
 
    --  Start of processing for Traverse_Declarations_Or_Statements
@@ -1391,43 +1398,71 @@
                --  Pragma
 
                when N_Pragma =>
-                  Extend_Statement_Sequence (N, 'P');
 
+                  --  Record sloc of pragma (pragmas don't nest)
+
+                  pragma Assert (Current_Pragma_Sloc = No_Location);
+                  Current_Pragma_Sloc := Sloc (N);
+
                   --  Processing depends on the kind of pragma
 
-                  case Pragma_Name (N) is
-                     when Name_Assert        |
-                          Name_Check         |
-                          Name_Precondition  |
-                          Name_Postcondition =>
+                  declare
+                     Nam : constant Name_Id := Pragma_Name (N);
+                     Arg : Node_Id := First (Pragma_Argument_Associations (N));
+                     Typ : Character;
 
-                        --  For Assert/Check/Precondition/Postcondition, we
-                        --  must generate a P entry for the decision. Note that
-                        --  this is done unconditionally at this stage. Output
-                        --  for disabled pragmas is suppressed later on, when
-                        --  we output the decision line in Put_SCOs.
+                  begin
+                     case Nam is
+                        when Name_Assert        |
+                             Name_Check         |
+                             Name_Precondition  |
+                             Name_Postcondition =>
 
-                        declare
-                           Nam : constant Name_Id :=
-                                   Chars (Pragma_Identifier (N));
-                           Arg : Node_Id :=
-                                   First (Pragma_Argument_Associations (N));
+                           --  For Assert/Check/Precondition/Postcondition, we
+                           --  must generate a P entry for the decision. Note
+                           --  that this is done unconditionally at this stage.
+                           --  Output for disabled pragmas is suppressed later
+                           --  on, when we output the decision line in
+                           --  Put_SCOs, depending on marker sets by
+                           --  Set_SCO_Pragma_Disabled.
 
-                        begin
                            if Nam = Name_Check then
                               Next (Arg);
                            end if;
 
                            Process_Decisions_Defer (Expression (Arg), 'P');
-                        end;
+                           Typ := 'p';
 
-                     --  For all other pragmas, we generate decision entries
-                     --  for any embedded expressions.
+                        when Name_Debug =>
+                           if Present (Arg) and then Present (Next (Arg)) then
 
-                     when others =>
-                        Process_Decisions_Defer (N, 'X');
-                  end case;
+                              --  Case of a dyadic pragma Debug: first argument
+                              --  is a P decision, any nested decision in the
+                              --  second argument is an X decision.
 
+                              Process_Decisions_Defer (Expression (Arg), 'P');
+                              Next (Arg);
+                           end if;
+
+                           Process_Decisions_Defer (Expression (Arg), 'X');
+                           Typ := 'p';
+
+                        --  For all other pragmas, we generate decision entries
+                        --  for any embedded expressions, and the pragma is
+                        --  never disabled.
+
+                        when others =>
+                           Process_Decisions_Defer (N, 'X');
+                           Typ := 'P';
+                     end case;
+
+                     --  Add statement SCO
+
+                     Extend_Statement_Sequence (N, Typ);
+
+                     Current_Pragma_Sloc := No_Location;
+                  end;
+
                --  Object declaration. Ignored if Prev_Ids is set, since the
                --  parser generates multiple instances of the whole declaration
                --  if there is more than one identifier declared, and we only
@@ -1512,7 +1547,7 @@
 
       --  Now output any embedded decisions
 
-      Process_Decisions (N, 'X');
+      Process_Decisions (N, 'X', No_Location);
    end Traverse_Generic_Instantiation;
 
    ------------------------------------------
@@ -1521,7 +1556,7 @@
 
    procedure Traverse_Generic_Package_Declaration (N : Node_Id) is
    begin
-      Process_Decisions (Generic_Formal_Declarations (N), 'X');
+      Process_Decisions (Generic_Formal_Declarations (N), 'X', No_Location);
       Traverse_Package_Declaration (N);
    end Traverse_Generic_Package_Declaration;
 
Index: par_sco.ads
===================================================================
--- par_sco.ads	(revision 177431)
+++ par_sco.ads	(working copy)
@@ -50,9 +50,9 @@
    --  original tree associated with Cond.
 
    procedure Set_SCO_Pragma_Enabled (Loc : Source_Ptr);
-   --  This procedure is called from Sem_Prag when a pragma is enabled (i.e.
-   --  when the Pragma_Enabled flag is set). Loc is the Sloc of the N_Pragma
-   --  node. This is used to enable the corresponding SCO table entry. Note
+   --  This procedure is called from Sem_Prag when a pragma is disabled (i.e.
+   --  when the Pragma_Enabled flag is unset). Loc is the Sloc of the N_Pragma
+   --  node. This is used to disable the corresponding SCO table entry. Note
    --  that we use the Sloc as the key here, since in the generic case, the
    --  analysis is on a copy of the node, which is different from the node
    --  seen by Par_SCO in the parse tree (but the Sloc values are the same).
Index: scos.ads
===================================================================
--- scos.ads	(revision 177431)
+++ scos.ads	(working copy)
@@ -152,6 +152,7 @@
    --      E  EXIT statement
    --      F  FOR loop statement (from FOR through end of iteration scheme)
    --      I  IF statement (from IF through end of condition)
+   --      p  disabled PRAGMA
    --      P  PRAGMA
    --      R  extended RETURN statement
    --      W  WHILE loop statement (from WHILE through end of condition)
@@ -194,12 +195,12 @@
    --    Decisions are either simple or complex. A simple decision is a top
    --    level boolean expression that has only one condition and that occurs
    --    in the context of a control structure in the source program, including
-   --    WHILE, IF, EXIT WHEN, or in an Assert, Check, Pre_Condition or
-   --    Post_Condition pragma. For pragmas, decision SCOs are generated only
-   --    if the corresponding pragma is enabled. Note that a top level boolean
-   --    expression with only one condition that occurs in any other context,
-   --    for example as right hand side of an assignment, is not considered to
-   --    be a (simple) decision.
+   --    WHILE, IF, EXIT WHEN, or immediately within an Assert, Check,
+   --    Pre_Condition or Post_Condition pragma, or as the first argument of a
+   --    dyadic pragma Debug. Note that a top level boolean expression with
+   --    only one condition that occurs in any other context, for example as
+   --    right hand side of an assignment, is not considered to be a (simple)
+   --    decision.
 
    --    A complex decision is a top level boolean expression that has more
    --    than one condition. A complex decision may occur in any boolean
@@ -336,6 +337,10 @@
    --    entries appear in one logical statement sequence, continuation lines
    --    are marked by Cc and appear immediately after the CC line.
 
+   --  Disabled pragmas
+
+   --    No SCO is generated for disabled pragmas.
+
    ---------------------------------------------------------------------
    -- Internal table used to store Source Coverage Obligations (SCOs) --
    ---------------------------------------------------------------------
@@ -392,7 +397,7 @@
 
    --    Decision (PRAGMA)
    --      C1   = 'P'
-   --      C2   = 'e'/'d' for enabled/disabled
+   --      C2   = ' '
    --      From = PRAGMA token
    --      To   = No_Source_Location
    --      Last = unused
@@ -400,14 +405,11 @@
    --      Note: when the parse tree is first scanned, we unconditionally build
    --      a pragma decision entry for any decision in a pragma (here as always
    --      in SCO contexts, the only pragmas with decisions are Assert, Check,
-   --      Precondition and Postcondition), and we mark the pragma as disabled.
+   --      dyadic Debug, Precondition and Postcondition).
    --
-   --      During analysis, if the pragma is enabled, Set_SCO_Pragma_Enabled to
-   --      mark the SCO decision table entry as enabled (C2 set to 'e'). Then
-   --      in Put_SCOs, we only output the decision for a pragma if C2 is 'e'.
-   --
-   --      When we read SCOs from an ALI file (in Get_SCOs), we always set C2
-   --      to 'e', since clearly the pragma is enabled if it was written out.
+   --      During analysis, if the pragma is enabled, Set_SCO_Pragma_Enabled
+   --      marks the statement SCO table entry as enaabled (C1 changed from 'p'
+   --      to 'P') to cause the entry to be emitted in Put_SCOs.
 
    --    Decision (Expression)
    --      C1   = 'X'
Index: sem_prag.adb
===================================================================
--- sem_prag.adb	(revision 177434)
+++ sem_prag.adb	(working copy)
@@ -1794,7 +1794,7 @@
               (Get_Pragma_Arg (Arg2), Standard_String);
          end if;
 
-         --  Record if pragma is enabled
+         --  Record if pragma is disabled
 
          if Check_Enabled (Pname) then
             Set_SCO_Pragma_Enabled (Loc);
@@ -7604,6 +7604,10 @@
                 (Boolean_Literals (Debug_Pragmas_Enabled and Expander_Active),
                  Loc);
 
+            if Debug_Pragmas_Enabled then
+               Set_SCO_Pragma_Enabled (Loc);
+            end if;
+
             if Arg_Count = 2 then
                Cond :=
                  Make_And_Then (Loc,
Index: put_scos.adb
===================================================================
--- put_scos.adb	(revision 177431)
+++ put_scos.adb	(working copy)
@@ -107,9 +107,8 @@
                      Ctr := 0;
                      Continuation := False;
                      loop
-                        if SCO_Table.Table (Start).C2 = 'P'
-                             and then SCO_Pragma_Disabled
-                                        (SCO_Table.Table (Start).Pragma_Sloc)
+                        if SCO_Pragma_Disabled
+                             (SCO_Table.Table (Start).Pragma_Sloc)
                         then
                            goto Next_Statement;
                         end if;
@@ -160,13 +159,10 @@
                   when 'I' | 'E' | 'G' | 'P' | 'W' | 'X' =>
                      Start := Start + 1;
 
-                     --  For disabled pragma, or nested decision nested, skip
+                     --  For disabled pragma, or nested decision therein, skip
                      --  decision output.
 
-                     if (T.C1 = 'P' and then T.C2 = 'd')
-                          or else
-                        SCO_Pragma_Disabled (T.Pragma_Sloc)
-                     then
+                     if SCO_Pragma_Disabled (T.Pragma_Sloc) then
                         while not SCO_Table.Table (Start).Last loop
                            Start := Start + 1;
                         end loop;
Index: get_scos.adb
===================================================================
--- get_scos.adb	(revision 177431)
+++ get_scos.adb	(working copy)
@@ -315,7 +315,6 @@
 
             declare
                Loc : Source_Location;
-               C2v : Character;
 
             begin
                --  Acquire location information
@@ -326,18 +325,9 @@
                   Get_Source_Location (Loc);
                end if;
 
-               --  C2 is a space except for pragmas where it is 'e' since
-               --  clearly the pragma is enabled if it was written out.
-
-               if C = 'P' then
-                  C2v := 'e';
-               else
-                  C2v := ' ';
-               end if;
-
                Add_SCO
                  (C1   => Dtyp,
-                  C2   => C2v,
+                  C2   => ' ',
                   From => Loc,
                   To   => No_Source_Location,
                   Last => False);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-08-05 14:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-05 14:30 [Ada] SCO generation for pragma Debug Arnaud Charlet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).