home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / iconc / incheck.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  23KB  |  803 lines

  1. /*
  2.  * incheck.c - analyze a run-time operation using type information.
  3.  *   Determine wither the operation can be in-lined and what kinds
  4.  *   of parameter passing optimizations can be done.
  5.  */
  6. #include "::h:gsupport.h"
  7. #include "ctrans.h"
  8. #include "cglobals.h"
  9. #include "csym.h"
  10. #include "ctree.h"
  11. #include "ccode.h"
  12. #include "cproto.h"
  13.  
  14. struct op_symentry *cur_symtab; /* symbol table for current operation */
  15.  
  16. /*
  17.  * Prototypes for static functions.
  18.  */
  19. hidden struct code *and_cond Params((struct code *cd1, struct code *cd2));
  20. hidden int          cnv_anlz Params((unsigned int typcd, struct il_code *src,
  21.                                struct il_c *dflt, struct il_c *dest,
  22.                                struct code **cdp));
  23. hidden int          defer_il Params((struct il_code *il));
  24. hidden int          if_anlz  Params((struct il_code *il));
  25. hidden novalue      ilc_anlz Params((struct il_c *ilc));
  26. hidden int          il_anlz  Params((struct il_code *il));
  27. hidden novalue      ret_anlz Params((struct il_c *ilc));
  28. hidden int          tc_anlz  Params((struct il_code *il, int has_dflt));
  29.  
  30. static int n_branches;  /* number branches caused by run-time type checking */
  31. static int side_effect; /* abstract clause indicates side-effect */
  32. static int n_vararg;    /* size of variable part of arg list to operation */
  33. static int n_susp;      /* number of suspends */
  34. static int n_ret;       /* number of returns */
  35.  
  36. /*
  37.  * do_inlin - determine if this operation can be in-lined at the current
  38.  *  invocation. Also gather information about how arguments are used,
  39.  *  and determine where the success continuation for the operation
  40.  *  should be put.
  41.  */
  42. int do_inlin(impl, n, cont_loc, symtab, n_va) 
  43. struct implement *impl;
  44. nodeptr n;
  45. int *cont_loc;
  46. struct op_symentry *symtab;
  47. int n_va;
  48.    {
  49.    int nsyms;
  50.    int i;
  51.  
  52.    /*
  53.     * Copy arguments needed by other functions into globals and
  54.     *  initialize flags and counters for information to be gathered
  55.     *  during analysis.
  56.     */
  57.    cur_symtyps = n->symtyps; /* mapping from arguments to types */
  58.    cur_symtab = symtab;      /* parameter info to be filled in */
  59.    n_vararg = n_va;
  60.    n_branches = 0;
  61.    side_effect = 0;
  62.    n_susp = 0;
  63.    n_ret = 0;
  64.  
  65.    /*
  66.     * Analyze the code for this operation using type information for
  67.     *  the arguments to the invocation.
  68.     */
  69.    il_anlz(impl->in_line);
  70.  
  71.  
  72.    /*
  73.     * Don't in-line if there is more than one decision made based on
  74.     *  run-time type checks (this is a heuristic).
  75.     */
  76.    if (n_branches > 1)
  77.       return 0;
  78.  
  79.    /*
  80.     * If the operation (after eliminating code not used in this context)
  81.     *  has one suspend and no returns, the "success continuation" can
  82.     *  be placed in-line at the suspend site. Otherwise, any suspends
  83.     *  require a separate function for the continuation.
  84.     */
  85.    if (n_susp == 1 && n_ret == 0)
  86.      *cont_loc = SContIL;    /* in-line continuation */
  87.    else if (n_susp > 0)
  88.      *cont_loc = SepFnc;     /* separate function for continuation */
  89.    else
  90.      *cont_loc = EndOper;    /* place "continuation" after the operation */
  91.  
  92.    /*
  93.     * When an argument at the source level is an Icon variable, it is
  94.     *  sometimes safe to use it directly in the generated code as the
  95.     *  argument to the operation. However, it is NOT safe under the
  96.     *  following conditions:
  97.     *
  98.     *    - if the operation modifies the argument.
  99.     *    - if the operation suspends and resumes so that intervening
  100.     *      changes to the variable would be visible as changes to the
  101.     *      argument.
  102.     *    - if the operation has side effects that might involve the
  103.     *      variable and be visible as changes to the argument.
  104.     */
  105.    nsyms = (cur_symtyps == NULL ? 0 : cur_symtyps->nsyms);
  106.    for (i = 0; i < nsyms; ++i)
  107.       if (symtab[i].n_mods == 0 && n->intrnl_lftm == n && !side_effect)
  108.         symtab[i].var_safe = 1;
  109.  
  110.    return 1;
  111.    }
  112.  
  113. /*
  114.  * il_anlz - analyze a piece of RTL code. Return an indication of
  115.  *  whether execution can continue beyond it.
  116.  */
  117. static int il_anlz(il)
  118. struct il_code *il;
  119.    {
  120.    int fall_thru;
  121.    int ncases;
  122.    int condition;
  123.    int indx;
  124.    int i, j;
  125.  
  126.    if (il == NULL)
  127.        return 1;
  128.  
  129.    switch (il->il_type) {
  130.       case IL_Const: /* should have been replaced by literal node */
  131.          return 1;
  132.  
  133.       case IL_If1:
  134.          /*
  135.           * if-then statement. Determine whether the condition may
  136.           *  succeed or fail. Analyze the then clause if needed.
  137.           */
  138.          condition = if_anlz(il->u[0].fld);
  139.          fall_thru = 0;
  140.          if (condition & MaybeTrue)
  141.             fall_thru |= il_anlz(il->u[1].fld);
  142.          if (condition & MaybeFalse)
  143.             fall_thru = 1;
  144.          return fall_thru;
  145.  
  146.       case IL_If2:
  147.          /*
  148.           * if-then-else statement. Determine whether the condition may
  149.           *  succeed or fail. Analyze the "then" clause and the "else"
  150.           *  clause if needed.
  151.           */
  152.          condition = if_anlz(il->u[0].fld);
  153.          fall_thru = 0;
  154.          if (condition & MaybeTrue)
  155.             fall_thru |= il_anlz(il->u[1].fld);
  156.          if (condition & MaybeFalse)
  157.             fall_thru |= il_anlz(il->u[2].fld);
  158.          return fall_thru;
  159.  
  160.       case IL_Tcase1:
  161.          /*
  162.           * type_case statement with no default clause.
  163.           */
  164.          return tc_anlz(il, 0);
  165.  
  166.       case IL_Tcase2:
  167.          /*
  168.           * type_case statement with a default clause.
  169.           */
  170.          return tc_anlz(il, 1);
  171.  
  172.       case IL_Lcase:
  173.          /*
  174.           * len_case statement. Determine which case matches the number
  175.           *  of arguments.
  176.           */
  177.          ncases = il->u[0].n;
  178.          indx = 1;
  179.          for (i = 0; i < ncases; ++i) {
  180.             if (il->u[indx++].n == n_vararg)     /* selection number */
  181.                return il_anlz(il->u[indx].fld);  /* action */
  182.             ++indx;
  183.             }
  184.          return il_anlz(il->u[indx].fld);        /* default */
  185.  
  186.       case IL_Acase: {
  187.          /*
  188.           * arith_case statement.
  189.           */
  190.          struct il_code *var1;
  191.          struct il_code *var2;
  192.          int maybe_int;
  193.          int maybe_dbl;
  194.          int chk1;
  195.          int chk2;
  196.  
  197.          var1 = il->u[0].fld;
  198.          var2 = il->u[1].fld;
  199.          arth_anlz(var1, var2, &maybe_int, &maybe_dbl, &chk1, NULL,
  200.            &chk2, NULL);
  201.  
  202.          /*
  203.           * Analyze the selected case (note, large integer code is not
  204.           *  currently in-lined and can be ignored).
  205.           */
  206.          fall_thru = 0;
  207.          if (maybe_int)
  208.             fall_thru |= il_anlz(il->u[2].fld);     /* C_integer action */
  209.          if (maybe_dbl)
  210.             fall_thru |= il_anlz(il->u[4].fld);     /* C_double action */
  211.          return fall_thru;
  212.          }
  213.  
  214.       case IL_Err1:
  215.          /*
  216.           * runerr() with no offending value.
  217.           */
  218.          return 0;
  219.  
  220.       case IL_Err2:
  221.          /*
  222.           * runerr() with an offending value. Note the reference to
  223.           *  the offending value descriptor.
  224.           */
  225.          indx = il->u[1].fld->u[0].n;    /* symbol table index of variable */
  226.          if (indx < cur_symtyps->nsyms)
  227.             ++cur_symtab[indx].n_refs;
  228.          return 0;
  229.  
  230.       case IL_Block:
  231.          /*
  232.           * inline {...} statement.
  233.           */
  234.          i = il->u[1].n + 2;              /* skip declaration stuff */
  235.          ilc_anlz(il->u[i].c_cd);         /* body of block */
  236.          return il->u[0].n;
  237.  
  238.       case IL_Call:
  239.          /*
  240.           * call to body function.
  241.           */
  242.          if (il->u[3].n & DoesSusp)
  243.             n_susp = 2;  /* force continuation into separate function */
  244.  
  245.          /*
  246.           * Analyze the C code for prototype parameter declarations
  247.           *  and actual arguments. There are twice as many pieces of
  248.           *  C code to look at as there are parameters.
  249.           */
  250.          j = 2 * il->u[7].n;
  251.          i = 8;              /* index of first piece of C code */
  252.          while (j--)
  253.             ilc_anlz(il->u[i++].c_cd);
  254.          return ((il->u[3].n & DoesFThru) != 0);
  255.  
  256.       case IL_Lst:
  257.          /*
  258.           * Two consecutive pieces of RTL code.
  259.           */
  260.          fall_thru = il_anlz(il->u[0].fld);
  261.          if (fall_thru)
  262.             fall_thru = il_anlz(il->u[1].fld);
  263.          return fall_thru;
  264.  
  265.       case IL_Abstr:
  266.          /*
  267.           * abstract type computation. See if it indicates side effects.
  268.           */
  269.          if (il->u[0].fld != NULL)
  270.              side_effect = 1;
  271.          return 1;
  272.  
  273.       default:
  274.          fprintf(stderr, "compiler error: unknown info in data base\n");
  275.          exit(ErrorExit);
  276.          /* NOTREACHED */
  277.       }
  278.    }
  279.  
  280. /*
  281.  * if_anlz - analyze the condition of an if statement.
  282.  */
  283. static int if_anlz(il)
  284. struct il_code *il;
  285.    {
  286.    int cond;
  287.    int cond1;
  288.  
  289.    if (il->il_type == IL_Bang) {
  290.       /*
  291.        * ! <condition>, negate the result of the condition
  292.        */
  293.       cond1 = cond_anlz(il->u[0].fld, NULL);
  294.       cond = 0;
  295.       if (cond1 & MaybeTrue)
  296.          cond = MaybeFalse;
  297.       if (cond1 & MaybeFalse)
  298.          cond |= MaybeTrue;
  299.       }
  300.    else
  301.       cond = cond_anlz(il, NULL);
  302.    if (cond == (MaybeTrue | MaybeFalse))
  303.       ++n_branches;  /* must make a run-time decision */
  304.    return cond;
  305.    }
  306.  
  307. /*
  308.  * cond_anlz - analyze a simple condition or the conjunction of two
  309.  *   conditions. If cdp is not NULL, use it to return a pointer code
  310.  *   that implements the condition.
  311.  */
  312. int cond_anlz(il, cdp)
  313. struct il_code *il;
  314. struct code **cdp;
  315.    {
  316.    struct code *cd1;
  317.    struct code *cd2;
  318.    int cond1;
  319.    int cond2;
  320.    int indx;
  321.  
  322.    switch (il->il_type) {
  323.       case IL_And:
  324.          /*
  325.           * <cond> && <cond>
  326.           */
  327.          cond1 = cond_anlz(il->u[0].fld, (cdp == NULL ? NULL : &cd1));
  328.          if (cond1 & MaybeTrue) {
  329.             cond2 = cond_anlz(il->u[1].fld, (cdp == NULL ? NULL : &cd2));
  330.             if (cdp != NULL) {
  331.                if (!(cond2 & MaybeTrue))
  332.                   *cdp = NULL;
  333.                else
  334.                   *cdp = and_cond(cd1, cd2);
  335.                }
  336.             return (cond1 & MaybeFalse) | cond2;
  337.             }
  338.          else {
  339.             if (cdp != NULL)
  340.                *cdp = cd1;
  341.             return cond1;
  342.             }
  343.  
  344.       case IL_Cnv1:
  345.          /*
  346.           * cnv:<dest-type>(<source>)
  347.           */
  348.          return cnv_anlz(il->u[0].n, il->u[1].fld, NULL, NULL, cdp);
  349.  
  350.       case IL_Cnv2:
  351.          /*
  352.           * cnv:<dest-type>(<source>,<destination>)
  353.           */
  354.          return cnv_anlz(il->u[0].n, il->u[1].fld, NULL, il->u[2].c_cd, cdp);
  355.  
  356.       case IL_Def1:
  357.          /*
  358.           * def:<dest-type>(<source>,<default-value>)
  359.           */
  360.          return cnv_anlz(il->u[0].n, il->u[1].fld, il->u[2].c_cd, NULL, cdp);
  361.  
  362.       case IL_Def2:
  363.          /*
  364.           * def:<dest-type>(<source>,<default-value>,<destination>)
  365.           */
  366.          return cnv_anlz(il->u[0].n, il->u[1].fld, il->u[2].c_cd, il->u[3].c_cd,
  367.             cdp);
  368.  
  369.       case IL_Is:
  370.          /*
  371.           * is:<type-name>(<variable>)
  372.           */
  373.          indx = il->u[1].fld->u[0].n;
  374.          cond1 = eval_is(il->u[0].n, indx);
  375.          if (cdp == NULL) {
  376.             if (indx < cur_symtyps->nsyms && cond1 == (MaybeTrue | MaybeFalse))
  377.                ++cur_symtab[indx].n_refs;
  378.             }
  379.          else {
  380.             if (cond1 == (MaybeTrue | MaybeFalse))
  381.                *cdp = typ_chk(il->u[1].fld, il->u[0].n);
  382.             else
  383.                *cdp = NULL;
  384.             }
  385.          return cond1;
  386.  
  387.       default:
  388.          fprintf(stderr, "compiler error: unknown info in data base\n");
  389.          exit(ErrorExit);
  390.          /* NOTREACHED */
  391.       }
  392.    }
  393.  
  394.  
  395. /*
  396.  * and_cond - construct && of two conditions, either of which may have
  397.  *  been optimized away.
  398.  */
  399. static struct code *and_cond(cd1, cd2)
  400. struct code *cd1;
  401. struct code *cd2;
  402.    {
  403.    struct code *cd;
  404.  
  405.    if (cd1 == NULL)
  406.       return cd2;
  407.    else if (cd2 == NULL)
  408.       return cd1;
  409.    else {
  410.       cd = alc_ary(3);
  411.       cd->ElemTyp(0) = A_Ary;
  412.       cd->Array(0) =            cd1;
  413.       cd->ElemTyp(1) = A_Str;
  414.       cd->Str(1) =              " && ";
  415.       cd->ElemTyp(2) = A_Ary;
  416.       cd->Array(2) =            cd2;
  417.       return cd;
  418.       }
  419.    }
  420.  
  421. /*
  422.  * cnv_anlz - analyze a type conversion. Determine whether it can succeed
  423.  *  and, if requested, produce code to perform the conversion. Also
  424.  *  gather information about the variables it uses.
  425.  */
  426. static int cnv_anlz(typcd, src, dflt, dest, cdp)
  427. unsigned int typcd;
  428. struct il_code *src;
  429. struct il_c *dflt;
  430. struct il_c *dest;
  431. struct code **cdp;
  432.    {
  433.    struct val_loc *src_loc;
  434.    int cond;
  435.    int cnv_flags;
  436.    int indx;
  437.  
  438.    /*
  439.     * Find out what is going on in the default and destination subexpressions.
  440.     *  (The information is used elsewhere.)
  441.     */
  442.    ilc_anlz(dflt);
  443.    ilc_anlz(dest);
  444.  
  445.    if (cdp != NULL)
  446.       *cdp = NULL;   /* clear code pointer in case it is not set below */
  447.  
  448.    /*
  449.     * Determine whether the conversion may succeed, whether it may fail,
  450.     *  and whether it may actually convert a value or use the default
  451.     *  value when it succeeds.
  452.     */
  453.    indx = src->u[0].n;  /* symbol table index for source of conversion */
  454.    cond = eval_cnv(typcd, indx, dflt != NULL, &cnv_flags);
  455.  
  456.    /*
  457.     * Many optimizations are possible depending on whether a conversion
  458.     *  is actually needed, whether type checking is needed, whether defaulting
  459.     *  is done, and whether there is an explicit destination. Several
  460.     *  optimizations are performed here; more may be added in the future.
  461.     */
  462.    if (!(cnv_flags & MayDefault))
  463.       dflt = NULL;  /* demote defaulting to simple conversion */
  464.  
  465.    if (cond & MaybeTrue) {
  466.       if (cnv_flags == MayKeep && dest == NULL) {
  467.           /*
  468.            * No type conversion, defaulting, or copying is needed.
  469.            */
  470.          if (cond & MaybeFalse) {
  471.             /*
  472.              * A type check is needed.
  473.              */
  474.             ++cur_symtab[indx].n_refs; /* non-modifying reference to source. */
  475.             if (cdp != NULL) {
  476.                switch (typcd) {
  477.                   case TypECInt:
  478.                      *cdp = typ_chk(src, TypCInt);
  479.                      break;
  480.                   case TypEInt:
  481.                      *cdp = typ_chk(src, int_typ);
  482.                      break;
  483.                   case TypTStr:
  484.                      *cdp = typ_chk(src, str_typ);
  485.                      break;
  486.                   case TypTCset:
  487.                      *cdp = typ_chk(src, cset_typ);
  488.                      break;
  489.                   default:
  490.                      *cdp = typ_chk(src, typcd);
  491.                   }
  492.                }
  493.             }
  494.  
  495.          if (cdp != NULL) {
  496.             /*
  497.              * Conversion from an integer to a C_integer can be done without
  498.              *  any executable code; this is not considered a real conversion.
  499.              *  It is accomplished by changing the symbol table so only the
  500.              *  dword of the descriptor is accessed.
  501.              */
  502.             switch (typcd) {
  503.                case TypCInt:
  504.                case TypECInt:
  505.                   cur_symtab[indx].loc = loc_cpy(cur_symtab[indx].loc, M_CInt);
  506.                   break;
  507.                }
  508.             }
  509.          }
  510.       else if (dest != NULL && cnv_flags == MayKeep && cond == MaybeTrue) {
  511.          /*
  512.           *  There is an explicit destination, but no conversion, defaulting,
  513.           *   or type checking is needed. Just copy the value to the
  514.           *   destination.
  515.           */
  516.          ++cur_symtab[indx].n_refs; /* non-modifying reference to source */
  517.          if (cdp != NULL)  {
  518.             src_loc = cur_symtab[indx].loc;
  519.             switch (typcd) {
  520.                case TypCInt:
  521.                case TypECInt:
  522.                   /*
  523.                    * The value is in the dword of the descriptor.
  524.                    */
  525.                   src_loc = loc_cpy(src_loc, M_CInt);
  526.                   break;
  527.                }
  528.             *cdp = il_copy(dest, src_loc);
  529.             }
  530.          }
  531.       else if (cnv_flags == MayDefault) {
  532.          /*
  533.           * The default value is used.
  534.           */
  535.          if (dest == NULL)
  536.             ++cur_symtab[indx].n_mods; /* modifying reference */
  537.          if (cdp != NULL) 
  538.             *cdp = il_dflt(typcd, src, dflt, dest);
  539.          }
  540.       else {
  541.          /*
  542.           * Produce code to do the actual conversion.
  543.           *  Determine whether the source location is being modified
  544.           *  or just referenced.
  545.           */
  546.          if (dest == NULL) {
  547.             /*
  548.              * "In place" conversion.
  549.              */
  550.             switch (typcd) {
  551.                case TypCDbl:
  552.                case TypCInt:
  553.                case TypECInt:
  554.                   /*
  555.                    * not really converted in-place.
  556.                    */
  557.                   ++cur_symtab[indx].n_refs; /* non-modifying reference */
  558.                   break;
  559.                default:
  560.                   ++cur_symtab[indx].n_mods; /* modifying reference */
  561.                }
  562.             }
  563.          else
  564.             ++cur_symtab[indx].n_refs; /* non-modifying reference */
  565.  
  566.          if (cdp != NULL) 
  567.             *cdp = il_cnv(typcd, src, dflt, dest);
  568.          }
  569.       }
  570.    return cond;
  571.    }
  572.  
  573. /*
  574.  * ilc_anlz - gather information about in-line C code.
  575.  */
  576. static novalue ilc_anlz(ilc)
  577. struct il_c *ilc;
  578.    {
  579.    while (ilc != NULL) {
  580.       switch(ilc->il_c_type) {
  581.          case ILC_Ref:
  582.             /* 
  583.              * Non-modifying reference to variable
  584.              */
  585.             if (ilc->n != RsltIndx) {
  586.                ++cur_symtab[ilc->n].n_refs;
  587.                }
  588.             break;
  589.  
  590.          case ILC_Mod:
  591.             /* 
  592.              * Modifying reference to variable
  593.              */
  594.             if (ilc->n != RsltIndx) {
  595.                ++cur_symtab[ilc->n].n_mods;
  596.                }
  597.             break;
  598.  
  599.          case ILC_Ret:
  600.             /*
  601.              * Return statement.
  602.              */
  603.             ++n_ret;
  604.             ret_anlz(ilc);
  605.             break;
  606.  
  607.          case ILC_Susp:
  608.             /*
  609.              * Suspend statement.
  610.              */
  611.             ++n_susp;
  612.             ret_anlz(ilc);
  613.             break;
  614.  
  615.          case ILC_CGto:
  616.             /*
  617.              * Conditional goto.
  618.              */
  619.             ilc_anlz(ilc->code[0]);
  620.             break;
  621.          }
  622.       ilc = ilc->next;
  623.       }
  624.    }
  625.  
  626. /*
  627.  * ret_anlz - gather information about the in-line C code associated
  628.  *   with a return or suspend.
  629.  */
  630. static novalue ret_anlz(ilc)
  631. struct il_c *ilc;
  632.    {
  633.    int i;
  634.    int j;
  635.  
  636.    /*
  637.     * See if the code is simply returning a parameter.
  638.     */
  639.    if (ilc->n == RetDesc && ilc->code[0]->il_c_type == ILC_Ref &&
  640.       ilc->code[0]->next == NULL) {
  641.          j = ilc->code[0]->n;
  642.          ++cur_symtab[j].n_refs;
  643.          ++cur_symtab[j].n_rets;
  644.          }
  645.    else {
  646.       for (i = 0; i < 3 && ilc->code[i] != NULL; ++i)
  647.          ilc_anlz(ilc->code[i]);
  648.       }
  649.    }
  650.  
  651. /*
  652.  * deref_il - dummy routine to pass to a code walk.
  653.  */
  654. /*ARGSUSED*/
  655. static int defer_il(il)
  656. struct il_code *il;
  657.    {
  658.    /*
  659.     * Called for each case in a type_case statement that might be selected.
  660.     *  However, the actual analysis of the case, if it is needed,
  661.     *  is done elsewhere, so just return.
  662.     */
  663.    return 0;
  664.    }
  665.  
  666. /*
  667.  * findcases - determine how many cases of an type_case statement may
  668.  *   be true. If there are two or less, determine the "if" statement
  669.  *   that can be used (if there are more than two, the code is not
  670.  *   in-lined).
  671.  */
  672. novalue findcases(il, has_dflt, case_anlz)
  673. struct il_code *il;
  674. int has_dflt;
  675. struct case_anlz *case_anlz;
  676.    {
  677.    int i;
  678.  
  679.    case_anlz->n_cases = 0;
  680.    case_anlz->typcd = -1;
  681.    case_anlz->il_then = NULL;
  682.    case_anlz->il_else = NULL;
  683.    i = type_case(il, defer_il, case_anlz);
  684.    /*
  685.     * See if the explicit cases have accounted for all possible
  686.     *  types that might be present.
  687.     */
  688.    if (i == -1) {  /* all types accounted for */
  689.       if (case_anlz->il_else == NULL && case_anlz->il_then != NULL) {
  690.          /*   
  691.           * We don't need to actually check the type.
  692.           */
  693.          case_anlz->il_else = case_anlz->il_then;
  694.          case_anlz->il_then = NULL;
  695.          case_anlz->typcd = -1;
  696.          }
  697.       }
  698.     else {  /* not all types accounted for */
  699.       if (case_anlz->il_else != NULL)
  700.          case_anlz->n_cases = 3; /* force no inlining */
  701.       else if (has_dflt)
  702.          case_anlz->il_else = il->u[i].fld;         /* default */
  703.       }
  704.  
  705.    if (case_anlz->n_cases > 2)
  706.       n_branches = 2;  /* no in-lining */
  707.    else if (case_anlz->il_then != NULL)
  708.       ++n_branches;
  709.    }
  710.  
  711.  
  712. /*
  713.  * tc_anlz - analyze a type_case statement. It is only of interest for
  714.  *   in-lining if it can be reduced to an "if" statement or an
  715.  *   unconditional statement.
  716.  */
  717. static int tc_anlz(il, has_dflt)
  718. struct il_code *il;
  719. int has_dflt;
  720.    {
  721.    struct case_anlz case_anlz;
  722.    int fall_thru;
  723.    int indx;
  724.  
  725.    findcases(il, has_dflt, &case_anlz);
  726.  
  727.    if (case_anlz.il_else == NULL)
  728.       fall_thru = 1;   /* either no code at all or condition with no "else" */
  729.    else
  730.       fall_thru = 0;   /* either unconditional or if-then-else: check code  */
  731.  
  732.    if (case_anlz.il_then != NULL) {
  733.       fall_thru |= il_anlz(case_anlz.il_then);
  734.       indx = il->u[0].fld->u[0].n;    /* symbol table index of variable */
  735.       if (indx < cur_symtyps->nsyms)
  736.          ++cur_symtab[indx].n_refs;
  737.       }
  738.    if (case_anlz.il_else != NULL)
  739.       fall_thru |= il_anlz(case_anlz.il_else);
  740.    return fall_thru;
  741.    }
  742.  
  743. /*
  744.  * arth_anlz - analyze the type checking of an arith_case statement.
  745.  */
  746. novalue arth_anlz(var1, var2, maybe_int, maybe_dbl, chk1, conv1p, chk2, conv2p)
  747. struct il_code *var1;
  748. struct il_code *var2;
  749. int *maybe_int;
  750. int *maybe_dbl;
  751. int *chk1;
  752. struct code **conv1p;
  753. int *chk2;
  754. struct code **conv2p;
  755.    {
  756.    int cond;
  757.    int cnv_typ;
  758.  
  759.  
  760.    /*
  761.     * First do an analysis to find out which cases are needed. This is
  762.     *  more accurate than analysing the conversions separately, but does
  763.     *  not get all the information we need.
  764.     */
  765.    eval_arith(var1->u[0].n, var2->u[0].n, maybe_int, maybe_dbl);
  766.  
  767.    if (*maybe_int & (largeints | *maybe_dbl)) {
  768.       /*
  769.        * Too much type checking; don't bother with these cases. Force no
  770.        *   in-lining.
  771.        */
  772.       n_branches += 2;
  773.       }
  774.    else {
  775.       if (*maybe_int)
  776.          cnv_typ = TypCInt;
  777.       else
  778.          cnv_typ = TypCDbl;
  779.  
  780.       /*
  781.        * See exactly what kinds of conversions/type checks are needed and,
  782.        *  if requested, generate code for them.
  783.        */
  784.       *chk1 = 0;
  785.       *chk2 = 0;
  786.  
  787.       cond = cnv_anlz(cnv_typ, var1, NULL, NULL, conv1p);
  788.       if (cond & MaybeFalse) {
  789.          ++n_branches;          /* run-time decision */
  790.          *chk1 = 1;
  791.          if (var1->u[0].n < cur_symtyps->nsyms)
  792.             ++cur_symtab[var1->u[0].n].n_refs;  /* used in runerr2() */
  793.          }
  794.       cond = cnv_anlz(cnv_typ, var2, NULL, NULL, conv2p);
  795.       if (cond & MaybeFalse) {
  796.          ++n_branches;          /* run-time decision */
  797.          *chk2 = 1;
  798.          if (var2->u[0].n < cur_symtyps->nsyms)
  799.             ++cur_symtab[var2->u[0].n].n_refs;  /* used in runerr2() */
  800.          }
  801.       }
  802.    }
  803.