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 / G3.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  12KB  |  567 lines

  1. /*
  2.     C* -- Code generation -- Low level routines.
  3.  
  4.     Routines that start with g_ actually add nodes to the code list.
  5.  
  6.     source: g3.c
  7.     started: February 3, 1986
  8.     version:
  9.         August 5, 1986
  10.         March 7, 1989
  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. #define ps_opcode(op) ((op <= Q_BRN)? xzp_tab[op] : (char *) NULL)
  29.  
  30. extern int nd_free;
  31.  
  32. /*
  33.     Externally visible routines:
  34. */
  35. void    g_init    (void);
  36. void    g_line    (int i);
  37. void    g_lit    (char *s);
  38. void    g_1lab    (int opcode, struct node *p);
  39. void    g_2lab    (int opcode, struct node  *p1, struct node *p2);
  40. void    g_0    (int opcode);
  41. void    g_1    (int opcode, struct node *p);
  42. void    g_1l    (int opcode, struct node *p);
  43. void    g_1l2    (int opcode, struct node *p);
  44. void    g_2    (int opcode, struct node *p1, struct node *p2);
  45. void    g_2l1    (int opcode, struct node *p1, struct node *p2);
  46. void    g_qmove    (struct node *loc1, struct node *loc2);
  47. void    g_2l2    (int opcode, struct node *p1, struct node *p2);
  48. void    g_label    (struct node * p);
  49. int    mlen    (struct node *p);
  50.  
  51. /*
  52.     Internal routines:
  53. */
  54. static void    gappend    (struct node *p);
  55.  
  56. void
  57. g_init(void)
  58. {
  59.     TICK("g_init");
  60. }
  61.  
  62. void
  63. g_lit(char *s)
  64. {
  65.     register struct node *q;
  66.  
  67.     /* Create an op node. */
  68.  
  69.     TRACEPB("g_lit", printf("(%s)\n", s));
  70.  
  71.     q = new_cnode();
  72.     q -> c_code = O_LITERAL;
  73.     q -> c_lit = s;
  74.  
  75.     /* Append to code list. */
  76.     gappend(q);
  77.  
  78.     TICKX("g_lit");
  79. }
  80.     
  81. void
  82. g_line(int i)
  83. {
  84.     register struct node *q;
  85.  
  86.     TRACEPB("g_line", printf("%d\n", i));
  87.  
  88.     /* Create an op node. */
  89.     q = new_cnode();
  90.     q -> c_code = O_LINENUM;
  91.     q -> c_linenum = i;
  92.  
  93.     /* Append to code list. */
  94.     gappend(q);
  95.  
  96.     TICKX("g_line");
  97. }
  98.     
  99. /*
  100.     Generate code node for a jump or call to a label.
  101. */
  102. void
  103. g_1lab(int opcode, struct node *p)
  104. {
  105.     register struct node *q;
  106.  
  107.     TRACEPB("g_1lab", printf("(%d, %p)\n", opcode, p));
  108.  
  109.     if (is_qtok(opcode)) {
  110.         RETURN_VOID("g_1lab");
  111.     }
  112.  
  113.     /* Bump the reference count in the target. */
  114.     if (p -> c_code != O_LABEL && p -> c_code != O_ULABEL) {
  115.         printf("bad code list code %d\n", p -> c_code);
  116.         fatal("g_1lab: bad label type");
  117.     }
  118.     else {
  119.         /* Bump the reference count in the target. */
  120.         p -> c_refcount++;
  121.     }
  122.  
  123.     /* Create a code node to handle the goto. */
  124.     q = new_cnode();
  125.     q -> c_code = opcode;
  126.     q -> c_arg1 = (void *) p;
  127.  
  128.     /* Append to code list. */
  129.     gappend(q);
  130.  
  131.     TICKX("g_1lab");
  132. }
  133.  
  134. /*
  135.     generate code for a location with a call/jump to label
  136.     used on 68000 for DBcc Dn, Label, with the location designating
  137.     Dn.
  138. */
  139. void
  140. g_2lab(int opcode, struct node  *p1, struct node *p2)
  141. {
  142.     register struct node *q;
  143.  
  144.     /* Bump the reference count in the target. */
  145.  
  146.     TRACEPB("g_2lab", printf("(%d, %p, %p)\n", opcode, p1, p2));
  147.  
  148.     if (p2 -> c_code != O_LABEL && p2 -> c_code != O_ULABEL) {
  149.         printf("bad code list code %d\n", p2 -> c_code);
  150.         fatal("g_2lab: bad label type");
  151.     }
  152.     else {
  153.         /* Bump the reference count in the target. */
  154.         p2 -> c_refcount++;
  155.     }
  156.  
  157.     /* Create a code node to handle the instruction. */
  158.     q = new_cnode();
  159.     q -> c_code = opcode;
  160.     q -> c_arg1 = p1;
  161.     q -> c_arg2 = p2;
  162.  
  163.     /* Append to code list. */
  164.     gappend(q);
  165.  
  166.     TICKX("g_2lab");
  167. }
  168.  
  169. /* 
  170.     Generate an explicit X_TOK, or a node having an unknown number
  171.     of arguments
  172. */
  173. void
  174. g_x(int op, struct node *arg1, struct node *arg2, byte len)
  175. {
  176.     register struct node *q;
  177.  
  178.     /* Create a new code_node. */
  179.  
  180.     TRACEPB("g_x", printf("(%d, %p, %p, %c)\n", 
  181.         op, arg1, arg2, len));
  182.  
  183.     q = new_cnode();
  184.     q -> c_code = op;
  185.     q -> c_arg1 = arg1;
  186.     q -> c_arg2 = arg2;
  187.     q -> c_len1 = len;
  188.  
  189.     /* Append to code list. */
  190.     gappend(q);
  191.  
  192.     TICKX("g_x");
  193. }
  194.  
  195. /*
  196.     Generate code node for a 0 argument instruction.
  197. */
  198. void
  199. g_0(int opcode)
  200. {
  201.     register struct node *q;
  202.  
  203.     TRACEPB("g_0", printf("%s (%d)\n", ps_opcode(opcode), opcode));
  204.  
  205.     /* Create an op node. */
  206.     q = new_cnode();
  207.     q -> c_code = opcode;
  208.  
  209.     /* Append to code list. */
  210.     gappend(q);
  211.  
  212.     TICKX("g_0");
  213. }
  214.  
  215. /*
  216.     Generate code node for a 1 argument instruction.
  217. */
  218. void
  219. g_1(int opcode, struct node *p)
  220. {
  221.     register struct node *q;
  222.  
  223.     TRACEPB("g_1",
  224.         printf("%s (%d) ", ps_opcode(opcode), opcode);
  225.         pr_loc(p); printf("\n"));
  226.  
  227.     /* Create a new code_node. */
  228.     q = new_cnode();
  229.     q -> c_code = opcode;
  230.     q -> c_arg1 = p;
  231.  
  232.     /* Append to code list. */
  233.     gappend(q);
  234.  
  235.     TICKX("g_1");
  236. }
  237.  
  238. /*
  239.     Generate code node for a 1 argument instruction involving a length.
  240. */
  241. void
  242. g_1l(int opcode, struct node *p)
  243. {
  244.     register struct node *q;
  245.     register struct type_node *t;
  246.  
  247.     TRACEPB("g_1l",
  248.         printf("%s (%d) ", ps_opcode(opcode), opcode);
  249.         pr_loc(p); printf("\n"));
  250.  
  251.     /* Create a new code_node. */
  252.     q = new_cnode();
  253.     q -> c_code = opcode;
  254.     q -> c_arg1 = p;
  255.     t = p -> n_cltype;
  256.  
  257.     switch (t -> t_typtok) {
  258.     case INT_TYPE:
  259.     case POINTER_TYPE:
  260.         q -> c_len1 = (char) t -> t_tsize;
  261.         break;
  262.     case ARRAY_TYPE:
  263.     case STRUCT_TYPE:
  264.         q -> c_len1 = POINTER_SIZE;
  265.         break;
  266.     default:
  267.         g_error(p, "g_1l: not int or address");
  268.     }
  269.     
  270.     /* Append to code list. */
  271.     gappend(q);
  272.  
  273.     TICKX("g_1l");
  274. }
  275.  
  276. /*
  277.     Generate code node for a 1 argument instruction involving a length.
  278.     The length is decreased one notch, as for the ext instruction.
  279. */
  280. void
  281. g_1l2(int opcode, struct node *p)
  282. {
  283.     register struct node *q;
  284.     register struct type_node *t;
  285.  
  286.     TRACEPB("g_1l2",
  287.         printf("%s (%d) ", ps_opcode(opcode), opcode);
  288.         pr_loc(p); printf("\n"));
  289.  
  290.     /* Create a new code_node. */
  291.     q = new_cnode();
  292.     q -> c_code = opcode;
  293.     q -> c_arg1 = p;
  294.     t = p -> n_cltype;
  295.  
  296.     switch (t -> t_typtok) {
  297.     case INT_TYPE:
  298.         q -> c_len1 = ((char) t -> t_tsize) >> 1;
  299.         break;
  300.     default:
  301.         g_error(p, "g_1l2: not an int");
  302.     }
  303.     
  304.     /* Append to code list. */
  305.     gappend(q);
  306.  
  307.     TICKX("g_1l2");    
  308. }
  309.  
  310. /*
  311.     Generate code node for a 2 argument instruction.
  312. */
  313. void
  314. g_2(int opcode, struct node *p1, struct node *p2)
  315. {
  316.     register struct node *q;
  317.  
  318.     TRACEPB("g_2",
  319.         printf("%s (%d) ", ps_opcode(opcode), opcode);
  320.         pr_loc(p1); printf("  "); pr_loc(p2); printf("\n"););
  321.  
  322.     /* Create a new code_node. */
  323.     q = new_cnode();
  324.     q -> c_code = opcode;
  325.     q -> c_arg1 = p1;
  326.     q -> c_arg2 = p2;
  327.  
  328.     /* Append to code list. */
  329.     gappend(q);
  330.  
  331.     TICKX("g_2");
  332. }
  333.  
  334. /*
  335.     Derive the effective machine length of a locnode
  336.     This is not the same as the length of the corresponding
  337.     c-language object because arrays and structures stand for
  338.     concealed pointer values in the contexts where this is used.
  339. */
  340. int
  341. mlen(struct node *p)
  342. {
  343.     register struct type_node *t;
  344.  
  345.     t = p -> n_cltype;
  346.  
  347.     TRACEPB("mlen",
  348.         pr_loc(p); printf("\n");
  349.         pr_type(t));
  350.  
  351. #ifdef DEBUG
  352.     if (t == NULL) {
  353.         fatal("mlen: untyped loc_node");
  354.     }
  355. #endif
  356.  
  357.     switch (t -> t_typtok) {
  358.     case INT_TYPE:
  359.         RETURN_INT("mlen", (int) t -> t_tsize);
  360.  
  361.     case POINTER_TYPE:
  362.     case ARRAY_TYPE:
  363.     case STRUCT_TYPE:
  364.         RETURN_INT("mlen", POINTER_SIZE);
  365.  
  366.     default:
  367.         g_error(NULL, "mlen: not int or address");
  368.         RETURN_INT("mlen", POINTER_SIZE);
  369.     }
  370. }
  371.  
  372. /*
  373.     Generate code node for a 2 argument instruction involving an
  374.     operator length.
  375. */
  376. void
  377. g_2l1(int opcode, struct node *p1, struct node *p2)
  378. {
  379.     register struct node *q;
  380.  
  381.     TRACEPB("g_2l1",
  382.         printf("(%s = %d, ", ps_opcode(opcode), opcode);
  383.         pr_loc(p1); printf("  ");
  384.         pr_loc(p2); printf("\n");
  385.         printf("%p, %p); length: %d: type %p: ",
  386.                 p1, p2, mlen(p1), p1 -> n_cltype);
  387.         pr_type(p1 -> n_cltype); printf("\n"));
  388.  
  389.     /* Create a new code_node. */
  390.     q = new_cnode();
  391.     q -> c_code = opcode;
  392.     q -> c_arg1 = p1;
  393.     q -> c_arg2 = p2;
  394.  
  395.     q -> c_len1 = (char) mlen(p1);
  396.     
  397.     /* Append to code list. */
  398.     gappend(q);
  399.  
  400.     TICKX("g_2l1");
  401. }
  402.  
  403. /*
  404.     Generate code node for a possibly quick move
  405.  
  406.     This handles cases that the peephole (ultimately the opcode
  407.     assigner) can't for one reason or another; e.g. the 
  408.     EXCESSLENOK option allows the semantics to be changed.
  409.  
  410.     Take length from the SOURCE operand, which must be properly
  411.     massaged
  412. */
  413. void
  414. g_qmove(register struct node *loc1, register struct node *loc2)
  415. {
  416.     register struct node *q;
  417.     register struct st_node *id;
  418.     register long i_cnst;
  419.     int f;
  420.  
  421.     /* Create a new code_node. */
  422.  
  423.     TRACEPB("g_qmove", printf("(%p, %p)\n", loc1, loc2));
  424.  
  425.     q = new_cnode();
  426.     q -> c_code = X_MOVE;
  427.     q -> c_arg1 = loc1;
  428.     q -> c_arg2 = loc2;
  429.  
  430.     q -> c_len1 = (char) mlen(loc1);
  431.     
  432.     /* Append to code list. */
  433.     gappend(q);
  434.  
  435.     if (is_cloc(loc1) && (
  436. #if EXCESSLENOK
  437.         /* if it is allowed to clobber upper part of dreg */
  438.         (f = is_dloc(loc2)) ||
  439. #endif
  440.        /* if it's faster to load via an available dreg */
  441.        (nd_free && loc2 -> n_mode != VALUE_MODE && mlen(loc2) == 4) ) 
  442.                                     ) {
  443.         i_cnst = loc1 -> n_const;
  444.         if (id = loc1 -> n_cid) {
  445.             if (is_rstack(id -> st_sclass) ||
  446.                         id->st_sclass == SUE_CLASS) {
  447.                 /* i_cnst is now the true constant */
  448.                 i_cnst += id -> st_offset;
  449.             
  450.             }
  451.             else {
  452.                 /* true constant is label and therefore unknown */
  453.                 /* prevent the operation */
  454.                 i_cnst = 256;
  455.             }
  456.         }
  457.         if (i_cnst <= 127 && i_cnst >= -128) {
  458.             q -> c_code = X_MOVEQ;
  459.             q -> c_len1 = 0;
  460.             if (!f) {
  461.                 /* load a non-value location by loading quick
  462.                     a dreg and moving that to the loc */
  463.                 q -> c_arg2 = get_dtemp();
  464.                 g_2l2(X_MOVE, q -> c_arg2, loc2);
  465.                 free_temp(q -> c_arg2);
  466.             }
  467.         }
  468.     }
  469.  
  470.     TICKX("g_qmove");
  471. }
  472.  
  473. /*
  474.     Generate code node for a 2 argument instruction involving an
  475.     operator length.
  476. */
  477. void
  478. g_2l2(int opcode, struct node *p1, struct node *p2)
  479. {
  480.     register struct node *q;
  481.  
  482.     TRACEPB("g_2",
  483.         printf("%s (%d) ", ps_opcode(opcode), opcode);
  484.         pr_loc(p1); printf("  ");
  485.         pr_loc(p2); printf("\n"));
  486.  
  487.     /* Create a new code_node. */
  488.     q = new_cnode();
  489.     q -> c_code = opcode;
  490.     q -> c_arg1 = p1;
  491.     q -> c_arg2 = p2;
  492.  
  493.     q -> c_len1 = (char) mlen(p2);
  494.     
  495.     /* Append to code list. */
  496.     gappend(q);
  497.  
  498.     TICKX("g_2");
  499. }
  500.  
  501. /*
  502.     ----- L A B E L    R O U T I N E S ----
  503.  
  504.     Label nodes are created during code generation to represent all labels
  505.     generated by the program.   Label nodes are created when first 
  506.     referenced and are linked into the code linked when and if needed.
  507.     
  508.     Label nodes contain a reference count field so that unneeded labels are
  509.     not output.
  510.  
  511.     Internal (non-user) label nodes contain a count used eventually to 
  512.     generate a unique label.  The count needs to be assigned when the label 
  513.     is first generated so that jumps to the label can be output before the 
  514.     label is actually output.
  515. */
  516.  
  517. /*
  518.     Link the label node into the code list.
  519. */
  520. void
  521. g_label(struct node * p)
  522. {
  523.     TRACEPB("g_label", printf("(%p)\n", p));
  524.  
  525.     if (p -> c_code != O_LABEL && p -> c_code != O_ULABEL) {
  526.         printf("bad label type %d\n", p -> c_code);
  527.         fatal("g_label: bad label type");
  528.     }
  529.  
  530.     TRACEP("g_label",
  531.         if (p -> c_code == O_LABEL) {
  532.             printf("L%d:\n", p -> c_labnum);
  533.         }
  534.         else {
  535.             printf("%s:\n", p -> c_labsym);
  536.         }) /* End of TRACE macro. */
  537.  
  538.     /* Append to code list. */
  539.     gappend(p);
  540.  
  541.     TICKX("g_label");
  542. }
  543.  
  544. /*
  545.     Append a single code node to the end of the global code list.
  546. */
  547. static void
  548. gappend(struct node *p)
  549. {
  550.     TRACEP("gappend",
  551.         printf("(%p)\n", p);
  552.         out_list(p));
  553.  
  554.     if (p == NULL) {
  555.         return;
  556.     }
  557.     else if (code_head == NULL) {
  558.         code_head = p;
  559.         code_tail = p;
  560.     }
  561.     else {
  562.         p -> c_back = code_tail;
  563.         code_tail -> c_next = p;
  564.         code_tail = p;
  565.     }
  566. }
  567.