[Ada] Update spec for Compile_Time_Known_Value

Arnaud Charlet charlet@adacore.com
Tue Jan 21 08:01:00 GMT 2014


This is an internal change to documentation, and the interface
to one function in the compiler. No functional effect, so no
test needed.

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

2014-01-21  Robert Dewar  <dewar@adacore.com>

	* sem_eval.adb (Compile_Time_Known_Value): Add Ignore_CRT
	parameter.
	* sem_eval.ads (Compile_Time_Known_Value): Add Ignore_CRT
	parameter, completely rewrite spec.

-------------- next part --------------
Index: sem_eval.adb
===================================================================
--- sem_eval.adb	(revision 206841)
+++ sem_eval.adb	(working copy)
@@ -1287,7 +1287,10 @@
    -- Compile_Time_Known_Value --
    ------------------------------
 
-   function Compile_Time_Known_Value (Op : Node_Id) return Boolean is
+   function Compile_Time_Known_Value
+     (Op         : Node_Id;
+      Ignore_CRT : Boolean := False) return Boolean
+   is
       K      : constant Node_Kind := Nkind (Op);
       CV_Ent : CV_Entry renames CV_Cache (Nat (Op) mod CV_Cache_Size);
 
@@ -1311,9 +1314,9 @@
       --  time. This avoids anomalies where whether something is allowed with a
       --  given configurable run-time library depends on how good the compiler
       --  is at optimizing and knowing that things are constant when they are
-      --  nonstatic.
+      --  nonstatic. This check is suppressed if Ignore_CRT is True
 
-      if Configurable_Run_Time_Mode
+      if (Configurable_Run_Time_Mode and not Ignore_CRT)
         and then K /= N_Null
         and then not Is_Static_Expression (Op)
       then
@@ -1326,7 +1329,6 @@
            and then Etype (Entity (Op)) = Standard_Boolean
          then
             null;
-
          else
             return False;
          end if;
Index: sem_eval.ads
===================================================================
--- sem_eval.ads	(revision 206804)
+++ sem_eval.ads	(working copy)
@@ -85,14 +85,14 @@
    --  does not raise constraint error. In fact for certain legality checks not
    --  only do we need to ascertain that the expression is static, but we must
    --  also ensure that it does not raise constraint error.
-   --
+
    --  Neither of Is_Static_Expression and Is_OK_Static_Expression should be
    --  used for compile time evaluation purposes. In fact certain expression
-   --  whose value is known at compile time are not static in the RM 4.9 sense.
-   --  A typical example is:
-   --
+   --  whose value may be known at compile time are not static in the RM 4.9
+   --  sense. A typical example is:
+
    --     C : constant Integer := Record_Type'Size;
-   --
+
    --  The expression 'C' is not static in the technical RM sense, but for many
    --  simple record types, the size is in fact known at compile time. When we
    --  are trying to perform compile time constant folding (for instance for
@@ -100,8 +100,8 @@
    --  are not the right functions to test if folding is possible. Instead, we
    --  use Compile_Time_Known_Value. All static expressions that do not raise
    --  constraint error (i.e. those for which Is_OK_Static_Expression is true)
-   --  are known at compile time, but as shown by the above example, there are
-   --  cases of non-static expressions which are known at compile time.
+   --  are known at compile time, but as shown by the above example, there may
+   --  be cases of non-static expressions which are known at compile time.
 
    -----------------
    -- Subprograms --
@@ -224,15 +224,60 @@
    --  Determine whether two types T1, T2, which have the same base type,
    --  are statically matching subtypes (RM 4.9.1(1-2)).
 
-   function Compile_Time_Known_Value (Op : Node_Id) return Boolean;
+   function Compile_Time_Known_Value
+     (Op         : Node_Id;
+      Ignore_CRT : Boolean := False) return Boolean;
    --  Returns true if Op is an expression not raising Constraint_Error whose
-   --  value is known at compile time. This is true if Op is a static
+   --  value is known at compile time and for which a call to Expr_Value can
+   --  be used to determine this value. This is always true if Op is a static
    --  expression, but can also be true for expressions which are technically
-   --  non-static but which are in fact known at compile time, such as the
-   --  static lower bound of a non-static range or the value of a constant
-   --  object whose initial value is static. Note that this routine is defended
-   --  against unanalyzed expressions. Such expressions will not cause a
-   --  blowup, they may cause pessimistic (i.e. False) results to be returned.
+   --  non-static but which are in fact known at compile time. Some possible
+   --  examples of such expressions might be the static lower bound of a
+   --  non-static range or the value of a constant object whose initial
+   --  value is itself compile time known in the sense of this routine. Note
+   --  that this routine is defended against unanalyzed expressions. Such
+   --  expressions will not cause a blowup, they may cause pessimistic (i.e.
+   --  False) results to be returned. In general we take a pessimistic view.
+   --  False does not mean the value could not be known at compile time, but
+   --  True means that absolutely definition it is known at compile time and
+   --  it is safe to call Expr_Value on the expression Op.
+   --
+   --  Note that we don't define precisely the set of expressions that return
+   --  True. Callers should not make any assumptions regarding the value that
+   --  is returned for non-static expressions. Functional behavior should never
+   --  be affected by whether a given non-static expression returns True or
+   --  False when this function is called. In other words this is purely for
+   --  efficiency optimization purposes. The code generated can often be more
+   --  efficient with compile time known values, e.g. range analysis for the
+   --  purpose of removing checks is more effective if we know precise bounds.
+   --
+   --  The Ignore_CRT parameter has to do with the special case of configurable
+   --  runtime mode. Consider the following example:
+   --
+   --    X := B ** C;
+   --
+   --  Now if C is compile time known, and has the value 4, then inline code
+   --  can be generated at compile time, instead of calling a run-time routine.
+   --  That's fine in the normal case, but when we have a configurable run-time
+   --  the run-time routine may not be available. This means that the program
+   --  will be rejected if C is not known at compile time. We don't want the
+   --  legality of a program to depend on how clever the implementation of this
+   --  function is. If the run-time in use lacks the exponentiation routine,
+   --  then what we say is that exponentiation is permitted if the exponent is
+   --  officially static and has a value in the range 0 .. 4.
+   --
+   --  However, in the normal case, we want efficient code in the case where
+   --  a non-static exponent is known at compile time. To take care of this,
+   --  the normal default behavior is that in configurable run-time mode most
+   --  expressions are considered known at compile time ONLY in the case where
+   --  they are officially static. An exception is boolean objects which may
+   --  be considered known at compile time even in configurable run-time mode.
+   --
+   --  That loses optimization opportunities, and it would be better to look
+   --  case by case at each use of Compile_Time_Known_Value to see if this
+   --  configurable run-time mode special processing is needed. The Ignore_CRT
+   --  parameter can be set to True to ignore this special handling in cases
+   --  where it is known to be safe to do so.
 
    function Compile_Time_Known_Value_Or_Aggr (Op : Node_Id) return Boolean;
    --  Similar to Compile_Time_Known_Value, but also returns True if the value


More information about the Gcc-patches mailing list