Copyright (C) 2000-2012 |
GNU Info (g77-295.info)Transforming SELECT CASETransforming 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 |