GNU Info

Info Node: (g77-300.info)Transforming SELECT CASE

(g77-300.info)Transforming SELECT CASE


Prev: Transforming Block IF Up: Transforming Statements
Enter node , (file) or (file)node

Transforming SELECT CASE
------------------------

   `SELECT CASE' poses a few interesting problems for code generation,
if efficiency and frugal stack management are important.

   Consider `SELECT CASE (I('PREFIX'//A))', where `A' is
`CHARACTER*(*)'.  In a case like this--basically, in any case where
largish temporaries are needed to evaluate the expression--those
temporaries should not be "live" during execution of any of the `CASE'
blocks.

   So, evaluation of the expression is best done within its own block,
which in turn is within the `SELECT CASE' block itself (which contains
the code for the CASE blocks as well, though each within their own
block).

   Otherwise, we'd have the rough equivalent of this pseudo-code:

     {
       char temp[large];
     
       libg77_catenate (temp, 'prefix', a);
     
       switch (i (temp))
         {
         case 0:
           ...
         }
     }

   And that would leave temp[large] in scope during the CASE blocks
(although a clever back end *could* see that it isn't referenced in
them, and thus free that temp before executing the blocks).

   So this approach is used instead:

     {
       int temp0;
     
       {
         char temp1[large];
     
         libg77_catenate (temp1, 'prefix', a);
         temp0 = i (temp1);
       }
     
       switch (temp0)
         {
         case 0:
           ...
         }
     }

   Note how `temp1' goes out of scope before starting the switch, thus
making it easy for a back end to free it.

   The problem _that_ solution has, however, is with `SELECT
CASE('prefix'//A)' (which is currently not supported).

   Unless the GBEL is extended to support arbitrarily long character
strings in its `case' facility, the FFE has to implement `SELECT CASE'
on `CHARACTER' (probably excepting `CHARACTER*1') using a cascade of
`if', `elseif', `else', and `endif' constructs in GBEL.

   To prevent the (potentially large) temporary, needed to hold the
selected expression itself (`'prefix'//A'), from being in scope during
execution of the `CASE' blocks, two approaches are available:

   * Pre-evaluate all the `CASE' tests, producing an integer ordinal
     that is used, a la `temp0' in the earlier example, as if `SELECT
     CASE(temp0)' had been written.

     Each corresponding `CASE' is replaced with `CASE(I)', where I is
     the ordinal for that case, determined while, or before, generating
     the cascade of `if'-related constructs to cope with `CHARACTER'
     selection.

   * Make `temp0' above just large enough to hold the longest `CASE'
     string that'll actually be compared against the expression (in
     this case, `'prefix'//A').

     Since that length must be constant (because `CASE' expressions are
     all constant), it won't be so large, and, further, `temp1' need
     not be dynamically allocated, since normal `CHARACTER' assignment
     can be used into the fixed-length `temp0'.

   Both of these solutions require `SELECT CASE' implementation to be
changed so all the corresponding `CASE' statements are seen during the
actual code generation for `SELECT CASE'.


automatically generated by info2www version 1.2.2.9