home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 357_01 / cstar1.exe / G1.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  17KB  |  830 lines

  1. /*
  2.     C* -- Code generation -- machine independent part.
  3.  
  4.     source:  g1.c
  5.     started: November 9, 1985
  6.     version:
  7.         March 6, 1987
  8.         February 22, 1989:
  9.             all out_* routines moved to out.c
  10.             out_nl, out_lit replaced by sysnlput, syssput
  11.  
  12.     PUBLIC DOMAIN SOFTWARE
  13.  
  14.     The CSTAR program was placed in    the public domain on June 15, 1991,
  15.     by its author and sole owner,
  16.  
  17.         Edward K. Ream
  18.         1617 Monroe Street
  19.         Madison, WI 53711
  20.         (608) 257-0802
  21.  
  22.     CSTAR may be used for any commercial or non-commercial purpose.
  23.  
  24.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  25. */
  26. #include "cstar.h"
  27.  
  28. /*
  29.     Externally visible functions
  30. */
  31. void    gen_init(void);
  32. void    gen_function(struct fbody *p);
  33.  
  34. /*
  35.     Internal functions
  36. */
  37. static void    gen_do        (struct node *p);
  38. static void    gen_if        (struct node *p);
  39. static void    gen_for        (struct node *p);
  40. static void    gen_switch    (struct node *p);
  41. static void    gen_while    (struct node *p);
  42. static void    gen_break    (struct node *p);
  43. static void    gen_case    (struct node *p);
  44. static void    gen_continue    (struct node *p);
  45. static void    gen_default    (struct node *p);
  46. static void    gen_return    (struct node *p);
  47. static void    gen_goto    (struct node *p);
  48. static void    gen_label    (struct node *p);
  49. static void    gen_ldef    (struct node *p);
  50. static void    gen_x        (struct node *p);
  51. static void    gen_z        (struct node *p);
  52. static bool    is_vbool    (struct node *p);
  53.  
  54. /*
  55.     Shared register data
  56. */
  57. extern int sa_used [8];
  58. extern int sd_used [8];
  59. extern int sa_push[8];
  60. extern int sd_push[8];
  61.  
  62. #define g_bra(p) g_1lab(X_BRA, p)
  63.  
  64. /*
  65.     Data structures used only by this module.
  66. */
  67. static struct node *    brk_lab;
  68. static struct node *    cont_lab;
  69. static struct node *    ret_lab;
  70. static int ret_a, ret_d;
  71.  
  72. /*
  73.     Initialize this module.
  74. */
  75. void
  76. gen_init(void)
  77. {
  78.     TICK("gen_init");
  79.  
  80.     brk_lab  = NULL;
  81.     cont_lab = NULL;
  82.     ret_lab  = NULL;
  83.  
  84.     code_head = NULL;    
  85.     code_tail = NULL;
  86.  
  87.     g_init();
  88.  
  89.     int_type = new_tnode();
  90.     byte_type = new_tnode();
  91.     byte_type -> t_tsize = 1;
  92.     byte_type -> t_mclass |= CHAR_MOD;
  93.     long_type = new_tnode();
  94.     long_type -> t_tsize = LONG_SIZE;
  95.     long_type -> t_mclass |= LONG_MOD;
  96.  
  97.     segment = -1;
  98. }
  99.  
  100. /*
  101.     Generate code for a list of local definitions/declarations.
  102.  
  103.     WARNING:  not ready yet.
  104. */
  105. void
  106. gen_ldef(register struct node *p)
  107. {
  108.     TICK("gen_ldef");
  109. }
  110.  
  111. /*
  112.     Append code generated for a list of statements to the global code list.
  113. */
  114. static void
  115. gen_list(register struct node * p)
  116. {
  117.     TRACEPB("gen_list", printf("(%p)\n", p));
  118.  
  119.     for (; p; p = p -> n_next) {
  120.         g_line(p -> n_linno);
  121.  
  122.         TRACEP("gen_list",
  123.             printf("token %d %s\n", p -> n_type,
  124.                 ps_tok(p -> n_type)));
  125.  
  126.         switch (p -> n_type) {
  127.         case K_IF:        gen_if(p);        break;
  128.         case K_DO:        gen_do(p);        break;
  129.         case K_WHILE:        gen_while(p);        break;
  130.         case K_FOR:        gen_for(p);        break;
  131.         case K_SWITCH:        gen_switch(p);        break;
  132.         case K_CASE:        gen_case(p);        break;
  133.         case K_RETURN:        gen_return(p);        break;
  134.         case K_GOTO:        gen_goto(p);        break;
  135.         case K_BREAK:        gen_break(p);        break;
  136.         case K_CONTINUE:    gen_continue(p);    break;
  137.         case K_DEFAULT:        gen_default(p);        break;
  138.         case Z_TOK:        gen_z(p);        break;
  139.         case X_TOK:        gen_x(p);        break;
  140.         case LABEL_TOK:        gen_label(p);        break;
  141.  
  142.         default:
  143.             /* must be an expr, if not, gen_expr will catch it */
  144.             TRACEP("gen_list", printf("expression %p->%p\n",
  145.                             p, p -> n_cltype));
  146.             gen_expr(p);
  147.         }
  148.     }
  149.  
  150.     TICKX("gen_list");
  151. }
  152.  
  153. /*
  154.     Generate code for a function.
  155.  
  156.     1. Generate the entry code, body, and exit code.
  157.     2. Do optimization
  158.     3. Output the code
  159.  
  160.     The caller does gen_init.
  161.  
  162.     CAUTION: the long link frame size is of an unsigned type; it is not
  163.     signed long.  It causes the stack to be offset by an unsigned
  164.     negative amount, although it is not itself treated as unsigned 
  165.     negative.  See note in reg.c/decl_alloc().
  166. */
  167. void
  168. gen_function(register struct fbody * p)
  169. {
  170.     register unsigned long link_size;
  171.     register int i;
  172.     int r_push, do_addq;
  173.     static unsigned long t_err = 0;
  174.  
  175.     TRACEPB("gen_function",
  176.         printf("%p: %s; call_1arg %d\n", p, p -> fname, call_1arg));
  177.  
  178.     if (tree_flag) {
  179.         sysnlput();
  180.         syssput(">>>>> Parse Tree for ");
  181.         syssput(p -> fname);
  182.         syssput("()");
  183.         sysnlput();
  184.         out_tree(p -> parse);
  185.         sysnlput();
  186.     }
  187.  
  188.     if (nogen_flag) {
  189.         /* Suppress code generation. */
  190.         RETURN_VOID("gen_function");
  191.     }
  192.  
  193.     if (t_errcount) {
  194.         if (t_err == 0) {
  195.             /* do something to guarantee an assembler error */
  196.             /* this way it shows up on the "comp" printout */
  197.             sysnlput();
  198.             syssput("&& error");
  199.             sysnlput();
  200.         }
  201.         syssput("* ");
  202.         syssput(p -> fname);
  203.         sysnlput();
  204.         t_err = t_errcount;
  205.         RETURN_VOID("gen_function");
  206.     }
  207.  
  208.     /* if call_1arg optimization is unwanted, set call_1arg=0 here */
  209.  
  210.     link_size = p -> lcl_size;
  211.  
  212.     /* decide about return register */
  213.     TRACEP("gen_function",
  214.         printf("function returns type: ");    
  215.         pr_type(p -> ftype -> t_link);
  216.         printf("\n");
  217.     );
  218.         
  219.     i = p -> ftype -> t_link -> t_typtok;
  220.     if (i == INT_TYPE) {
  221.         ret_a = FALSE;
  222.         ret_d = TRUE;
  223.     }
  224.     else if (i != VOID_TYPE) {
  225. #ifdef D0_ONLY
  226.         ret_a = FALSE;
  227.         ret_d = TRUE;
  228. #else
  229.         ret_a = TRUE;
  230.         ret_d = FALSE;
  231. #endif /* D0_ONLY */
  232.     }
  233.     else {
  234.         ret_a = ret_d = FALSE;
  235.     }
  236.     TRACEP("gen_function",printf("ret_d = %d  ret_a = %d\n", ret_d,ret_a));
  237.     
  238.     /* Set the global return label for this function. */
  239.     ret_lab = new_clabel();
  240.  
  241.     /* Generate the body. */
  242.     gen_list(p -> parse);
  243.  
  244.     /* Generate the exit */
  245.     g_label(ret_lab);
  246.  
  247.  
  248.     /* ------------ register allocation ------------ */
  249.  
  250.     /* identify the registers which need to be pushed */
  251.     r_push = FALSE;
  252.     for (i = 0; i <= 7; i++) {
  253.         sa_push[i] = sa_used[i];
  254.         sd_push[i] = sd_used[i];
  255.     }
  256.  
  257.     TRACEP("gen_function",
  258.         printf("used: d:");
  259.         for (i = 0; i <= 7; i++) {
  260.             printf(" %d", sd_push[i]);
  261.         }
  262.         printf("  a:");
  263.         for (i = 0; i <= 7; i++) {
  264.             printf(" %d", sa_push[i]);
  265.         }
  266.         printf("\n");
  267.     );
  268.  
  269.     /* do not push those registers treated as SCRATCH, no matter how
  270.        they got used (drawn as temps or named explicitly;)
  271.        the caller is responsible for them */
  272.     for (i = 0; i <= ASCRATCH; i++) {
  273.         sa_push[i] = FALSE;
  274.     }
  275.     for (i = 0; i <= DSCRATCH; i++) {
  276.         sd_push[i] = FALSE;
  277.     }
  278.  
  279.     /* do not push the return register, since popping it would
  280.                             clobber the return */
  281.     if (ret_a) {
  282.         sa_push[0] = FALSE;
  283.     }
  284.     else if (ret_d) {
  285.         sd_push[0] = FALSE;
  286.     }      
  287.  
  288.     TRACEP("gen_function",
  289.         printf("push: d:");
  290.         for (i = 0; i <= 7; i++) {
  291.             printf(" %d", sd_push[i]);
  292.         }
  293.         printf("  a:");
  294.         for (i = 0; i <= 7; i++) {
  295.             printf(" %d", sa_push[i]);
  296.         }
  297.         printf("\n");
  298.     );
  299.  
  300.     for (i = 0; i <= 7; i++) {
  301.         if (sa_push[i] || sd_push[i]) {
  302.             r_push = TRUE;
  303.             break;
  304.         }
  305.     }
  306.     TRACEP("gen_function", printf("r_push = %d\n", r_push));
  307.  
  308.     /*
  309.         insert an extra register to push, or flag an extra addq.
  310.         this obviates the need for calls to functions with one
  311.         argument to adjust the stack.  it saves a significant amount
  312.         of code, several percent.
  313.     */
  314.     do_addq = FALSE;
  315.  
  316.     /* NOTE: for speed, >= 2 may be better if there are few calls */
  317.     if (call_1arg >= 1) {
  318.         if (r_push) {
  319.             if (ret_d) {
  320.                 if (sd_push[1]) {
  321.                     /* no possible extra push */
  322.                     do_addq = TRUE;
  323.                     /* WARNING */
  324.                     t_error("gen_function: case not done yet");
  325.                 }
  326.                 else {
  327.                     sd_push[1] = TRUE;
  328.                 }
  329.             }
  330.             else {
  331.                 /* d0 is the extra push */
  332.                 sd_push[0] = TRUE;
  333.             }
  334.         }
  335.         else {
  336.             link_size += 4;
  337.         }
  338.     }
  339.     out_function(p, link_size, r_push, do_addq);
  340.  
  341.     TICKX("gen_function");
  342. }
  343.  
  344. /*
  345.     Generate code for the do statement.
  346. */
  347. static void
  348. gen_do(register struct node * p)
  349. {
  350.     struct node *loop1_lab, *loop2_lab;
  351.     struct node *old_cont, *old_brk;
  352.  
  353.     /* Save old values. */
  354.  
  355.     TRACEPB("gen_do", printf("(%p)\n", p));
  356.  
  357.     old_brk  = brk_lab;
  358.     old_cont = cont_lab;
  359.  
  360.     /* Get new values. */
  361.     loop1_lab = new_clabel();
  362.     loop2_lab = new_clabel();
  363.     cont_lab  = new_clabel();
  364.     brk_lab   = new_clabel();
  365.  
  366.     gen_pp(p -> n_dbool);
  367.     if (is_vbool(p -> n_dbool)) {
  368.         g_bra(loop2_lab);
  369.         g_label(loop1_lab);
  370.         gen_bpost(p -> n_dbool);
  371.         g_label(loop2_lab);
  372.         gen_list(p -> n_dbdy);
  373.         g_label(cont_lab);
  374.         gen_bool(p -> n_dbool, loop1_lab, FALL_THROUGH);
  375.         gen_bpost(p -> n_dbool);
  376.         g_label(brk_lab);
  377.     }
  378.     else {
  379.         g_label(cont_lab);
  380.         gen_list(p -> n_dbdy);
  381.         g_bra(cont_lab);
  382.         g_label(brk_lab);
  383.     }
  384.  
  385.     /* Restore old values. */
  386.     brk_lab  = old_brk;
  387.     cont_lab = old_cont;
  388.  
  389.     TICKX("gen_do");
  390. }
  391.  
  392. /*
  393.     Generate code for an "if" statement.
  394.  
  395.     In general, we need to generate an else clause even if none was
  396.     given explicitly so that there will be a place to put the sequence
  397.     points for each branch of the boolean expression.
  398. */
  399. static void
  400. gen_if(register struct node * p)
  401. {
  402.     struct node *else_lab, *end_lab;
  403.  
  404.     TRACEPB("gen_if", printf("(%p)\n", p));
  405.  
  406.     else_lab  = new_clabel();
  407.     gen_pp(p -> n_ibool);
  408.  
  409.     gen_bool(p -> n_ibool, FALL_THROUGH, else_lab);
  410.     gen_bpost(p -> n_ibool);
  411.     gen_list(p -> n_ithen);
  412.  
  413.     /* cut down on generation of spurious nodes since a missing
  414.         else clause is quite common */
  415.     if (p -> n_ielse) {
  416.         g_bra(end_lab = new_clabel());
  417.         g_label(else_lab);
  418.         gen_bpost(p -> n_ibool);
  419.         gen_list(p -> n_ielse);
  420.         g_label(end_lab);
  421.     }
  422.     else {
  423.         g_label(else_lab);
  424.     }
  425.  
  426.     TICKX("gen_if");
  427. }
  428.  
  429. /*
  430.     Generate code for the for statement.
  431. */
  432. static void
  433. gen_for(register struct node * p)
  434. {
  435.     struct node *lab0, *lab1;
  436.     struct node *old_brk, *old_cont;
  437.  
  438.     /* Save old values. */
  439.  
  440.     TRACEPB("gen_for", printf("(%p)\n", p));
  441.  
  442.     old_brk  = brk_lab;
  443.     old_cont = cont_lab;
  444.  
  445.     lab0     = new_clabel();
  446.     lab1     = new_clabel();
  447.     brk_lab  = new_clabel();
  448.     cont_lab = new_clabel();
  449.  
  450.     gen_pp(p -> n_fbool);
  451.     if (is_vbool(p -> n_fbool)) {
  452.         gen_expr(p -> n_f1list);
  453.         g_bra(lab0);
  454.         g_label(lab1);
  455.         gen_bpost(p -> n_fbool);
  456.         gen_list(p -> n_fbdy);
  457.         g_label(cont_lab);
  458.         gen_expr(p -> n_f2list);
  459.         g_label(lab0);
  460.         gen_bool(p -> n_fbool, lab1, FALL_THROUGH);
  461.         gen_bpost(p -> n_fbool);
  462.         g_label(brk_lab);
  463.     }
  464.     else {
  465.         gen_expr(p -> n_f1list);
  466.         g_label(lab1);
  467.         gen_list(p -> n_fbdy);
  468.         g_label(cont_lab);
  469.         gen_expr(p -> n_f2list);
  470.         g_bra(lab1);
  471.         g_label(brk_lab);
  472.     }
  473.  
  474.     /* Restore old values. */
  475.     brk_lab  = old_brk;
  476.     cont_lab = old_cont;
  477.  
  478.     TICKX("gen_for");
  479. }
  480.  
  481. /*
  482.     Generate code for the switch statement.
  483.  
  484.     Note:    this may end up handling long cases if no fundamental
  485.         problems turn up
  486. */
  487. static void
  488. gen_switch(register struct node * p)
  489. {
  490.     struct node * old_brk;
  491.     register struct node *q;
  492.     register struct node *loc1;
  493.  
  494.     /* Save old value. */
  495.  
  496.     TRACEPB("gen_switch", printf("(%p)\n", p));
  497.  
  498.     old_brk = brk_lab;
  499.  
  500.     /* Generate break label. */
  501.     brk_lab = new_clabel();
  502.  
  503.     /* Generate labels for all case statements. */
  504.     for (q = p -> n_slist; q; q = q -> n_clist) {
  505.         q -> n_clab = new_clabel();
  506.     }
  507.  
  508.     /* Generate label for the default case. */
  509.     q = p -> n_sdef;
  510.     if (q) {
  511.         q -> n_clab = new_clabel();
  512.     }
  513.         
  514.     /* Generate code to evaluate the switch expression. */
  515.     loc1 = gen_dexpr(p -> n_sval);    /* not necessarily a dtemp! */
  516.  
  517.     /*
  518.         There are a number of possible ways of going to the cases: 
  519.  
  520.         1. The obvious chain of compares and branches.
  521.  
  522.         2. A binary tree of compares and branches.
  523.  
  524.         3. A well-balanced binary tree of compares and branches.
  525.  
  526.         4. An index-table jump.
  527.  
  528.         5. A serial-search-table jump.
  529.  
  530.         6. A binary-search-table jump.
  531.     */
  532.  
  533.     /* Generate using method (1). */
  534.     for (q = p -> n_slist; q; q = q -> n_clist) {
  535.         g_2l2(X_CMP, locn_xconst(q -> n_ccon), loc1);
  536.         g_1lab(X_BEQ, q -> n_clab);
  537.     }
  538.     q = p -> n_sdef;
  539.     if (q) {
  540.         g_bra(q -> n_clab);
  541.     }
  542.     else {
  543.         g_bra(brk_lab);
  544.     }
  545.     
  546.     /* Generate the body. */
  547.     gen_list(p -> n_sbdy);
  548.     g_label(brk_lab);
  549.  
  550.     /* Restore old break label. */
  551.     brk_lab = old_brk;
  552.  
  553.     TICKX("gen_switch");
  554. }
  555.  
  556. /*
  557.     Generate code for the while statement.
  558. */
  559. static void
  560. gen_while(register struct node * p)
  561. {
  562.     struct node *loop_lab;
  563.     struct node *old_cont, *old_brk;
  564.  
  565.     /* Save old values. */
  566.  
  567.     TRACEPB("gen_while", printf("(%p)\n", p));
  568.  
  569.     old_brk  = brk_lab;
  570.     old_cont = cont_lab;
  571.  
  572.     /* Generate new labels. */
  573.     loop_lab = new_clabel();
  574.     cont_lab = new_clabel();
  575.     brk_lab  = new_clabel();
  576.  
  577.     gen_pp(p -> n_wbool);
  578.     if (is_vbool(p -> n_wbool)) {
  579.         g_bra(cont_lab);
  580.         gen_bpost(p -> n_wbool);
  581.         g_label(loop_lab);
  582.         gen_list(p -> n_wbdy);
  583.         g_label(cont_lab);
  584.         gen_bool(p -> n_wbool, loop_lab, FALL_THROUGH);
  585.         gen_bpost(p -> n_wbool);
  586.         g_label(brk_lab);
  587.     }
  588.     else {
  589.         g_label(cont_lab);
  590.         gen_list(p -> n_wbdy);
  591.         g_bra(cont_lab);
  592.     }
  593.  
  594.     /* Restore old values. */
  595.     brk_lab  = old_brk;
  596.     cont_lab = old_cont;
  597.  
  598.     TICKX("gen_while");
  599. }
  600.  
  601. /*
  602.     Generate code for the break statement.
  603. */
  604. static void
  605. gen_break(struct node *p)
  606. {
  607.     TRACEPB("gen_break", printf("(%p)\n", p));
  608.  
  609.     g_bra(brk_lab);
  610.  
  611.     TICKX("gen_break");
  612. }
  613.  
  614. /*
  615.     Generate code for the case statement.
  616. */
  617. static void
  618. gen_case(register struct node * p)
  619. {
  620.     TRACEPB("gen_case", printf("(%p)\n", p));
  621.  
  622.     g_label(p -> n_clab);
  623.  
  624.     TICKX("gen_case");
  625. }
  626.  
  627. /*
  628.     Generate code for the continue statement.
  629. */
  630. static void
  631. gen_continue(struct node *p)
  632. {
  633.     TRACEPB("gen_continue", printf("(%p)\n", p));
  634.  
  635.     g_bra(cont_lab);
  636.  
  637.     TICKX("gen_continue");
  638. }
  639.  
  640. /*
  641.     Generate code for the default statement.
  642. */
  643. static void
  644. gen_default(struct node *p)
  645. {
  646.     TRACEPB("gen_default", printf("(%p)\n", p));
  647.  
  648.     g_label(p -> n_clab);
  649.  
  650.     TICKX("gen_default");
  651. }
  652.  
  653. /*
  654.     Generate code for the return statement.
  655. */
  656. static void
  657. gen_return(register struct node * p)
  658. {
  659.     TRACEPB("gen_return", printf("(%p)\n", p));
  660.  
  661.     if (p -> n_rval) {
  662.         if (ret_a) {
  663.             gen_a0exp(p -> n_rval);
  664.         }
  665.         else if (ret_d) {
  666.             gen_d0exp(p -> n_rval);
  667.         }
  668.     }
  669.  
  670.     /* Jump to the return label. */
  671.     g_bra(ret_lab);
  672.  
  673.     TICKX("gen_return");
  674. }
  675.  
  676. /*
  677.     Generate code for a goto to a user defined label.
  678. */
  679. static void
  680. gen_goto(struct node * p)
  681. {
  682.     TRACEPB("gen_goto", printf("(%p)\n", p));
  683.  
  684.     g_bra(p -> n_plab);
  685.  
  686.     TICKX("gen_goto");
  687. }
  688.  
  689. /*
  690.     Generate a user defined label from a parse label node.
  691. */
  692. static void
  693. gen_label(struct node *p)
  694. {
  695.     TRACEPB("gen_label", printf("(%p)\n", p));
  696.  
  697.     g_label(p -> n_plab);
  698.  
  699.     TICKX("gen_label");
  700. }
  701.  
  702. /*
  703.     Generate a machine-language mnemonic.
  704.  
  705.     NOTE: x_exists() gives the error messages now.  This way it can be
  706.     more specific and give the line numbers as well.
  707. */
  708. static void
  709. gen_x(register struct node *p)
  710. {
  711.     register struct x_ex *x;
  712.     register int type;
  713.  
  714.     TRACEPB("gen_x", printf("(%p)\n", p));
  715.  
  716.     type = p -> n_xtype;
  717.  
  718.     switch(type) {
  719.  
  720.     case X_JMP:
  721.     case X_JSR:
  722.  
  723.         if (p -> n_xarg1) {
  724.             /* these arguments will have to be generated somehow */
  725.             /* the representation isn't clear right now */
  726.             if (x_exists(p)) {
  727.                 g_1(type, p -> n_xarg1);
  728.             }
  729.         }
  730.         else {
  731.             g_1lab(type, p -> n_arg2);
  732.         }
  733.         break;
  734.  
  735.     case X_DBCC:    case X_DBCS:    case X_DBEQ:
  736.     case X_DBF :    case X_DBGE:    case X_DBGT:
  737.     case X_DBHI:    case X_DBLE:    case X_DBLS:
  738.     case X_DBLT:    case X_DBMI:    case X_DBNE:
  739.     case X_DBPL:    case X_DBT:    case X_DBVC:
  740.     case X_DBVS:
  741.  
  742.         if (x_exists(p)) {
  743.             g_2lab(type, p -> n_xarg1, p -> n_arg2);
  744.         }
  745.         break;
  746.  
  747.     case X_BRA:    case X_BSR:
  748.     case X_BCC:    case X_BCS:    case X_BEQ:
  749.     case X_BGE:    case X_BGT:    case X_BHI:
  750.     case X_BLE:    case X_BLS:    case X_BLT:
  751.     case X_BMI:    case X_BNE:    case X_BPL:
  752.     case X_BVC:    case X_BVS:
  753.  
  754.         if (x_exists(p)) {
  755.             g_1lab(type, p -> n_arg1);
  756.         }
  757.         break;
  758.  
  759.     default:
  760.         /* verify that arguments are loc_node's */
  761.         /* in C, arguments will be addresses of something */
  762.         /* that something will be set up in assembler */
  763.         gen_pp(p -> n_xarg1);
  764.         gen_pp(p -> n_xarg2);
  765.  
  766.         /* See if the specified address modes exist for the function. */
  767.         if (x = x_exists(p)) {
  768.              g_x(p -> n_xtype, p -> n_xarg1,
  769.                         p -> n_xarg2, x -> xlen);
  770.         }
  771.         break;
  772.     }
  773.     RETURN_VOID("gen_x");
  774. }
  775.  
  776. /*
  777.     Generate a machine-language pseudo operation.
  778. */
  779. static void
  780. gen_z(register struct node *p)
  781. {
  782.     TRACEPB("gen_z", printf("(%p)\n", p));
  783.  
  784.     /* CAUTION: see note in io.c, am_match(), about equates */
  785.  
  786.     switch (p -> n_ztype) {
  787.  
  788.     case Z_BSS:    g_lit("BSS");    RETURN_VOID("gen_z");
  789.     case Z_DATA:    g_lit("DATA");    RETURN_VOID("gen_z");
  790.     case Z_TEXT:    g_lit("TEXT");    RETURN_VOID("gen_z");
  791.  
  792.     case Z_ORG:    case Z_PUSH:    case Z_POP:
  793.     case Z_ADDSP:    case Z_ADJSP:    case Z_SUBSP:
  794.  
  795.         p -> n_zarg1 = pe_expr();
  796.         RETURN_VOID("gen_z");
  797.  
  798.     case Z_DC:    case Z_DCB:    case Z_DCW:    case Z_DCL:
  799.     case Z_DS:    case Z_DSB:    case Z_DSW:    case Z_DSL:
  800.  
  801.         p -> n_zarg1 = pe_list(CONST_EXPR);
  802.         RETURN_VOID("gen_z");
  803.     default:
  804.         fatal("gen_z: unknown type");
  805.     }
  806.  
  807.     TICKX("gen_z");
  808. }
  809.  
  810. /*
  811.     Return true if the parse tree that p points to is a variable boolean
  812.     expression, i.e.,  it must be evaluated at run-time to see whether it
  813.     is true or false.
  814. */
  815. bool
  816. is_vbool(register struct node * p)
  817. {
  818.     /*
  819.         NOT READY YET:  see if root is a constant loc_node.
  820.     */
  821.     TRACEPB("is_vbool", printf("(%p)\n", p));
  822.  
  823.     if (p == NULL) {
  824.         RETURN_BOOL("is_vbool", FALSE);
  825.     }
  826.     else {
  827.         RETURN_BOOL("is_vbool", TRUE);
  828.     }
  829. }
  830.