diff options
Diffstat (limited to 'gcc/ada/checks.ads')
-rw-r--r-- | gcc/ada/checks.ads | 155 |
1 files changed, 132 insertions, 23 deletions
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads index 8ccafdea7c0..d6ad2bde5a5 100644 --- a/gcc/ada/checks.ads +++ b/gcc/ada/checks.ads @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2001 Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2002 Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -71,9 +71,8 @@ package Checks is -- operate anyway since they may generate useful compile time warnings. procedure Apply_Access_Check (N : Node_Id); - -- Determines whether an expression node should be flagged as needing - -- a runtime access check. If the node requires such a check, the - -- Do_Access_Check flag is turned on. + -- Determines whether an expression node requires a runtime access + -- check and if so inserts the appropriate run-time check. procedure Apply_Accessibility_Check (N : Node_Id; Typ : Entity_Id); -- Given a name N denoting an access parameter, emits a run-time @@ -171,6 +170,81 @@ package Checks is -- Thus the significance of OK being False on return is that no -- useful information is available on the range of the expression. + ------------------------------------------------------- + -- Control and Optimization of Range/Overflow Checks -- + ------------------------------------------------------- + + -- Range checks are controlled by the Do_Range_Check flag. The front end + -- is responsible for setting this flag in relevant nodes. Originally + -- the back end generated all corresponding range checks. But later on + -- we decided to generate all range checks in the front end. We are now + -- in the transitional phase where some of these checks are still done + -- by the back end, but many are done by the front end. + + -- Overflow checks are similarly controlled by the Do_Overflow_Check + -- flag. The difference here is that if Backend_Overflow_Checks is + -- is (Backend_Overflow_Checks_On_Target set False), then the actual + -- overflow checks are generated by the front end, but if back end + -- overflow checks are active (Backend_Overflow_Checks_On_Target + -- set True), then the back end does generate the checks. + + -- The following two routines are used to set these flags, they allow + -- for the possibility of eliminating checks. Checks can be eliminated + -- if an identical check has already been performed. + + procedure Enable_Overflow_Check (N : Node_Id); + -- First this routine determines if an overflow check is needed by doing + -- an appropriate range check. If a check is not needed, then the call + -- has no effect. If a check is needed then this routine sets the flag + -- Set Do_Overflow_Check in node N to True, unless it can be determined + -- that the check is not needed. The only condition under which this is + -- the case is if there was an identical check earlier on. + + procedure Enable_Range_Check (N : Node_Id); + -- Set Do_Range_Check flag in node N True, unless it can be determined + -- that the check is not needed. The only condition under which this is + -- the case is if there was an identical check earlier on. This routine + -- is not responsible for doing range analysis to determine whether or + -- not such a check is needed -- the caller is expected to do this. The + -- one other case in which the request to set the flag is ignored is + -- when Kill_Range_Check is set in an N_Unchecked_Conversion node. + + -- The following routines are used to keep track of processing sequences + -- of statements (e.g. the THEN statements of an IF statement). A check + -- that appears within such a sequence can eliminate an identical check + -- within this sequence of statements. However, after the end of the + -- sequence of statements, such a check is no longer of interest, since + -- it may not have been executed. + + procedure Conditional_Statements_Begin; + -- This call marks the start of processing of a sequence of statements. + -- Every call to this procedure must be followed by a matching call to + -- Conditional_Statements_End. + + procedure Conditional_Statements_End; + -- This call removes from consideration all saved checks since the + -- corresponding call to Conditional_Statements_Begin. These two + -- procedures operate in a stack like manner. + + -- The mechanism for optimizing checks works by remembering checks + -- that have already been made, but certain conditions, for example + -- an assignment to a variable involved in a check, may mean that the + -- remembered check is no longer valid, in the sense that if the same + -- expression appears again, another check is required because the + -- value may have changed. + + -- The following routines are used to note conditions which may render + -- some or all of the stored and remembered checks to be invalidated. + + procedure Kill_Checks (V : Entity_Id); + -- This procedure records an assignment or other condition that causes + -- the value of the variable to be changed, invalidating any stored + -- checks that reference the value. Note that all such checks must + -- be discarded, even if they are not in the current statement range. + + procedure Kill_All_Checks; + -- This procedure kills all remembered checks. + ----------------------------- -- Length and Range Checks -- ----------------------------- @@ -293,12 +367,6 @@ package Checks is -- flag. Checks_On is a boolean value that says if range and index checking -- is on or not. - procedure Enable_Range_Check (N : Node_Id); - pragma Inline (Enable_Range_Check); - -- Set Do_Range_Check flag in node N to True unless Kill_Range_Check flag - -- is set in N (the purpose of the latter flag is precisely to prevent - -- Do_Range_Check from being set). - procedure Insert_Range_Checks (Checks : Check_Result; Node : Node_Id; @@ -331,12 +399,65 @@ package Checks is -- in constructing the check. ----------------------- + -- Expander Routines -- + ----------------------- + + -- Some of the earlier processing for checks results in temporarily + -- setting the Do_Range_Check flag rather than actually generating + -- checks. Now we are moving the generation of such checks into the + -- front end for reasons of efficiency and simplicity (there were + -- difficutlies in handling this in the back end when side effects + -- were present in the expressions being checked). + + -- Probably we could eliminate the Do_Range_Check flag entirely and + -- generate the checks earlier, but this is a delicate area and it + -- seemed safer to implement the following routines, which are called + -- late on in the expansion process. They check the Do_Range_Check flag + -- and if it is set, generate the actual checks and reset the flag. + + procedure Generate_Range_Check + (N : Node_Id; + Target_Type : Entity_Id; + Reason : RT_Exception_Code); + -- This procedure is called to actually generate and insert a range + -- check. A check is generated to ensure that the value of N lies + -- within the range of the target type. Note that the base type of + -- N may be different from the base type of the target type. This + -- happens in the conversion case. The Reason parameter is the + -- exception code to be used for the exception if raised. + -- + -- Note on the relation of this routine to the Do_Range_Check flag. + -- Mostly for historical reasons, we often set the Do_Range_Check + -- flag and then later we call Generate_Range_Check if this flag is + -- set. Most probably we could eliminate this intermediate setting + -- of the flag (historically the back end dealt with range checks, + -- using this flag to indicate if a check was required, then we + -- moved checks into the front end). + + procedure Generate_Index_Checks (N : Node_Id); + -- This procedure is called to generate index checks on the subscripts + -- for the indexed component node N. Each subscript expression is + -- examined, and if the Do_Range_Check flag is set, an appropriate + -- index check is generated and the flag is reset. + + -- Similarly, we set the flag Do_Discriminant_Check in the semantic + -- analysis to indicate that a discriminant check is required for a + -- selected component of a discriminated type. The following routine + -- is called from the expander to actually generate the call. + + procedure Generate_Discriminant_Check (N : Node_Id); + -- N is a selected component for which a discriminant check is required + -- to make sure that the discriminants have appropriate values for the + -- selection. This is done by calling the appropriate discriminant + -- checking routine for the selector. + + ----------------------- -- Validity Checking -- ----------------------- -- In (RM 13.9.1(9-11)) we have the following rules on invalid values - -- 9 If the representation of a scalar object does not represent a + -- If the representation of a scalar object does not represent a -- value of the object's subtype (perhaps because the object was not -- initialized), the object is said to have an invalid representation. -- It is a bounded error to evaluate the value of such an object. If @@ -518,18 +639,6 @@ private -- For external clients, the required processing on this result is -- achieved using the Insert_Range_Checks routine. - pragma Inline (Access_Checks_Suppressed); - pragma Inline (Accessibility_Checks_Suppressed); - pragma Inline (Discriminant_Checks_Suppressed); - pragma Inline (Division_Checks_Suppressed); - pragma Inline (Elaboration_Checks_Suppressed); - pragma Inline (Index_Checks_Suppressed); - pragma Inline (Length_Checks_Suppressed); - pragma Inline (Overflow_Checks_Suppressed); - pragma Inline (Range_Checks_Suppressed); - pragma Inline (Storage_Checks_Suppressed); - pragma Inline (Tag_Checks_Suppressed); - pragma Inline (Apply_Length_Check); pragma Inline (Apply_Range_Check); pragma Inline (Apply_Static_Length_Check); |