home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  11.7 KB  |  466 lines

  1. #include "c.h"
  2.  
  3.  
  4. static int curseg;        /* current segment */
  5. static struct structexp {    /* current structure expression: */
  6.     Symbol var;            /* temporary variable */
  7.     int off;            /* offset in var */
  8.     Tree tree;            /* evolving tree */
  9.     struct structexp *link;        /* outer structure expression */
  10. } *current;
  11.  
  12. static int genasgn ARGS((Tree, struct structexp *));
  13. static void genchar ARGS((Symbol, struct structexp *));
  14. static int genconst ARGS((Tree, int));
  15. static void genspace ARGS((int, struct structexp *));
  16. static int initarray ARGS((int, Type, int));
  17. static int initchar ARGS((int, Type));
  18. static void initend ARGS((int, char []));
  19. static int initfields ARGS((Field, Field));
  20. static int initstruct ARGS((int, Type, int));
  21. static Tree initvalue ARGS((Type));
  22.  
  23. /* defpointer - initialize a pointer to p or to 0 if p==0 */
  24. void defpointer(Symbol p)
  25. {
  26.     if (p)
  27.         (*IR->defaddress)(p);
  28.     else {
  29.         Value v;
  30.         (*IR->defconst)(P, (v.p = 0, v));
  31.     }
  32. }
  33.  
  34. /* genasgn - append tree for assignment of e to evolving structure expression in *sp */
  35. static int genasgn(Tree e, struct structexp *sp)
  36. {
  37.     Tree p;
  38.  
  39.     sp->off = roundup(sp->off, e->type->size);
  40.     p = simplify(ADD+P, ptr(e->type), lvalue(idtree(sp->var)), consttree(sp->off, inttype));
  41.     if (isarray(e->type)) {
  42.         p = tree(ASGN+B, e->type, p, e);
  43.         p->u.sym = intconst(e->type->size);
  44.     } else
  45.         p = asgntree(ASGN, retype(rvalue(p), e->type), e);
  46.     sp->tree = tree(RIGHT, voidtype, sp->tree, p);
  47.     sp->off += e->type->size;
  48.     return e->type->size;
  49. }
  50.  
  51. /* genchar - generate assignment of string constant p to array in *sp */
  52. static void genchar(Symbol p, struct structexp *sp)
  53. {
  54.     char *s = p->u.c.v.p;
  55.     int n;
  56.  
  57.     for (n = p->type->size; n > 0 && sp->off%inttype->align; n--)
  58.         genasgn(consttree((*s++)&0377, chartype), sp);
  59.     if (n > 0) {
  60.         static Value v;
  61.         Type ty = array(chartype, p->type->size - (s - (char *)p->u.c.v.p), 0);
  62.         Tree e;
  63.         v.p = stringn(s, ty->size);
  64.         p = constant(ty, v);
  65.         if (p->u.c.loc == NULL)
  66.             p->u.c.loc = genident(STATIC, ty, GLOBAL);
  67.         e = tree(INDIR+B, ty, pointer(idtree(p)), 0);
  68.         e->u.sym = intconst(ty->size);
  69.         genasgn(e, sp);
  70.     }
  71. }
  72.  
  73. /* genconst - generate/check constant expression e; return size */
  74. static int genconst(Tree e, int def)
  75. {
  76.     for (;;)
  77.         switch (generic(e->op)) {
  78.         case ADDRG:
  79.             if (def)
  80.                 (*IR->defaddress)(e->u.sym);
  81.             return e->type->size;
  82.         case CNST:
  83.             if (e->op == CNST+P && isarray(e->type)) {
  84.                 e = cvtconst(e);
  85.                 continue;
  86.             }
  87.             if (def)
  88.                 (*IR->defconst)(ttob(e->type), e->u.v);
  89.             return e->type->size;
  90.         case RIGHT:
  91.             assert(e->kids[0] || e->kids[1]);
  92.             if (e->kids[1] && e->kids[0])
  93.                 error("initializer must be constant\n");
  94.             e = e->kids[1] ? e->kids[1] : e->kids[0];
  95.             continue;
  96.         case CVP:
  97.             if (isarith(e->type))
  98.                 error("cast from `%t' to `%t' is illegal in constant expressions\n",
  99.                     e->kids[0]->type, e->type);
  100.             /* fall thru */
  101.         case CVC: case CVI: case CVS: case CVU:
  102.         case CVD: case CVF:
  103.             e = e->kids[0];
  104.             continue;
  105.         default:
  106.             error("initializer must be constant\n");
  107.             if (def)
  108.                 genconst(consttree(0, inttype), def);
  109.             return inttype->size;
  110.         }
  111. }
  112.  
  113. /* genspace - generate n bytes of space or 0's */
  114. static void genspace(int n, struct structexp *sp)
  115. {
  116.     if (sp == 0)
  117.         (*IR->space)(n);
  118.     else if (n <= inttype->size)
  119.         for ( ; n > 0; n--)
  120.             genasgn(consttree(0, chartype), sp);
  121.     else {
  122.         Tree e;
  123.         static Symbol zeros;
  124.         if (zeros == 0) {
  125.             zeros = install(stringd(genlabel(1)), &globals, GLOBAL, PERM);
  126.             zeros->sclass = STATIC;
  127.             zeros->type = array(chartype, n, 0);
  128.             zeros->generated = 1;
  129.             (*IR->defsymbol)(zeros);
  130.         }
  131.         if (n > zeros->type->size)
  132.             zeros->type = array(chartype, n, 0);
  133.         e = tree(INDIR+B, zeros->type, idtree(zeros), 0);
  134.         e->u.sym = intconst(n);
  135.         genasgn(e, sp);
  136.     }
  137. }
  138.  
  139. /* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
  140. static int initarray(int len,Type ty,int lev)
  141. {
  142.     int n = 0;
  143.  
  144.     do {
  145.         initializer(ty, lev);
  146.         n += ty->size;
  147.         if (len > 0 && n >= len || t != ',')
  148.             break;
  149.         t = gettok();
  150.     } while (t != '}');
  151.     return n;
  152. }
  153.  
  154. /* initchar - initialize array of <= len ty characters; if len == 0, go to } */
  155. static int initchar(int len,Type ty)
  156. {
  157.     int n = 0;
  158.     char buf[16], *s = buf;
  159.  
  160.     do {
  161.         if (current) {
  162.             Type aty;
  163.             Tree e = expr1(0);
  164.             if ((aty = assign(ty, e)) != NULL)
  165.                 genasgn(cast(e, aty), current);
  166.             else
  167.                 error("invalid initialization type; found `%t' expected `%s'\n",
  168.                     e->type, ty);
  169.             ++n;
  170.         } else {
  171.             *s++ = initvalue(ty)->u.v.sc;
  172.             if (++n%inttype->size == 0) {
  173.                 (*IR->defstring)(inttype->size, buf);
  174.                 s = buf;
  175.             }
  176.         }
  177.         if (len > 0 && n >= len || t != ',')
  178.             break;
  179.         t = gettok();
  180.     } while (t != '}');
  181.     if (s > buf)
  182.         (*IR->defstring)(s - buf, buf);
  183.     return n;
  184. }
  185.  
  186. /* initend - finish off an initialization at level lev; accepts trailing comma */
  187. static void initend(int lev,char follow[])
  188. {
  189.     if (lev == 0 && t == ',')
  190.         t = gettok();
  191.     test('}', follow);
  192. }
  193.  
  194. /* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
  195. static int initfields(Field p,Field q)
  196. {
  197.     unsigned int bits = 0;
  198.     int i, n = 0;
  199.  
  200.     if (current) {
  201.         Tree e = consttree(0, unsignedtype);
  202.         do {
  203.             Tree x = expr1(0);
  204.             if (fieldsize(p) < 8*p->type->size)
  205.                 x = (*optree['&'])(BAND, x,
  206.                     consttree(fieldmask(p), unsignedtype));
  207.             e = (*optree['|'])(BOR, e,
  208.                 (*optree[LSHIFT])(LSH, x, consttree(fieldright(p), inttype)));
  209.             if (p->link == q)
  210.                 break;
  211.             p = p->link;
  212.         } while (t == ',' && (t = gettok()) != 0);
  213.         if (q && (n = q->offset - p->offset) < unsignedtype->size)
  214.             if (IR->little_endian)
  215.                 for (i = 0; i < n; i++) {
  216.                     genasgn(retype(e, chartype), current);
  217.                     e = (*optree[RSHIFT])(RSH, e, consttree(8, inttype));
  218.                 }
  219.             else /* a big endian */
  220.                 for (i = n - 1; i >= 0; i--) {
  221.                     Tree x = (*optree[RSHIFT])(RSH, e,
  222.                         consttree(8*(unsignedtype->size - n + i), inttype));
  223.                     genasgn(retype(x, chartype), current);
  224.                 }
  225.         else
  226.             n = genasgn(e, current);
  227.         return n;
  228.     }
  229.     do {
  230.         i = initvalue(inttype)->u.v.i;
  231.         if (fieldsize(p) < 8*p->type->size) {
  232.             if (p->type == inttype && i >= 0 && (i&~(fieldmask(p)>>1)) !=  0
  233.             ||  p->type == inttype && i <  0 && (i| (fieldmask(p)>>1)) != ~(unsigned)0
  234.             ||  p->type == unsignedtype      && (i& ~fieldmask(p))     !=  0)
  235.                 warning("initializer exceeds bit-field width\n");
  236.             i &= fieldmask(p);
  237.         }
  238.         bits |= i<<fieldright(p);
  239.         if (IR->little_endian) {
  240.             if (fieldsize(p) + fieldright(p) > n)
  241.                 n = fieldsize(p) + fieldright(p);
  242.         } else {
  243.             if (fieldsize(p) + fieldleft(p) > n)
  244.                 n = fieldsize(p) + fieldleft(p);
  245.         }
  246.         if (p->link == q)
  247.             break;
  248.         p = p->link;
  249.     } while (t == ',' && (t = gettok()) != 0);
  250.     n = (n + 7)/8;
  251.     for (i = 0; i < n; i++) {
  252.         Value v;
  253.         if (IR->little_endian) {
  254.             v.uc = bits;
  255.             bits >>= 8;
  256.         } else {    /* a big endian */
  257.             v.uc = bits>>(8*(unsignedtype->size - 1));
  258.             bits <<= 8;
  259.         }
  260.         (*IR->defconst)(C, v);
  261.     }
  262.     return n;
  263. }
  264.  
  265. /* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
  266. Type initializer(Type ty,int lev)
  267. {
  268.     int n = 0;
  269.     Tree e;
  270.     Type aty = NULL;
  271.     static char follow[] = { IF, CHAR, STATIC, 0 };
  272.  
  273.     ty = unqual(ty);
  274.     if (isscalar(ty)) {
  275.         if (!current)
  276.             needconst++;
  277.         if (t == '{') {
  278.             t = gettok();
  279.             e = expr1(0);
  280.             initend(lev, follow);
  281.         } else
  282.             e = expr1(0);
  283.         e = pointer(e);
  284.         if ((aty = assign(ty, e)) != NULL)
  285.             e = cast(e, aty);
  286.         else
  287.             error("invalid initialization type; found `%t' expected `%t'\n",
  288.                 e->type, ty);
  289.         if (current)
  290.             n = genasgn(e, current);
  291.         else {
  292.             n = genconst(e, 1);
  293.             deallocate(STMT);
  294.             needconst--;
  295.         }
  296.     }
  297.     if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
  298.         static char follow[] = { CHAR, STATIC, 0 };
  299.         error("cannot initialize undefined `%t'\n", ty);
  300.         skipto(';', follow);
  301.         return ty;
  302.     } else if (isunion(ty)) {
  303.         if (t == '{') {
  304.             t = gettok();
  305.             n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
  306.             initend(lev, follow);
  307.         } else {
  308.             if (lev == 0)
  309.                 error("missing { in initialization of `%t'\n", ty);
  310.             n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
  311.         }
  312.     } else if (isstruct(ty)) {
  313.         if (t == '{') {
  314.             t = gettok();
  315.             n = initstruct(0, ty, lev + 1);
  316.             test('}', follow);
  317.         } else if (current) {
  318.             e = expr1(0);
  319.             if (assign(ty, e))
  320.                 genasgn(e, current);
  321.             else
  322.                 error("invalid initialization type; found `%t' expected `%t'\n",
  323.                     e->type, ty);
  324.             n = ty->size;
  325.         } else if (lev > 0)
  326.             n = initstruct(ty->size, ty, lev + 1);
  327.         else {
  328.             error("missing { in initialization of `%t'\n", ty);
  329.             n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
  330.         }
  331.     }
  332.     if (isarray(ty))
  333.         aty = unqual(ty->type);
  334.     if (isarray(ty) && ischar(aty)) {
  335.         if (t == SCON) {
  336.             if (ty->size > 0 && ty->size == tsym->type->size - 1)
  337.                 tsym->type = array(chartype, ty->size, 0);
  338.             n = tsym->type->size;
  339.             if (current)
  340.                 genchar(tsym, current);
  341.             else
  342.                 (*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
  343.             t = gettok();
  344.         } else if (t == '{') {
  345.             t = gettok();
  346.             if (t == SCON) {
  347.                 ty = initializer(ty, lev + 1);
  348.                 initend(lev, follow);
  349.                 return ty;
  350.             }
  351.             n = initchar(0, aty);
  352.             test('}', follow);
  353.         } else if (lev > 0 && ty->size > 0)
  354.             n = initchar(ty->size, aty);
  355.         else {    /* eg, char c[] = 0; */
  356.             error("missing { in initialization of `%t'\n", ty);
  357.             n = initchar(1, aty);
  358.         }
  359.     } else if (isarray(ty)) {
  360.         if (t == '{') {
  361.             t = gettok();
  362.             n = initarray(0, aty, lev + 1);
  363.             test('}', follow);
  364.         } else if (lev > 0 && ty->size > 0)
  365.             n = initarray(ty->size, aty, lev + 1);
  366.         else {
  367.             error("missing { in initialization of `%t'\n", ty);
  368.             n = initarray(aty->size, aty, lev + 1);
  369.         }
  370.     }
  371.     if (ty->size) {
  372.         if (n > ty->size)
  373.             error("too many initializers\n");
  374.         else if (n < ty->size)
  375.             genspace(ty->size - n, current);
  376.     } else if (isarray(ty) && ty->type->size > 0)
  377.         ty = array(ty->type, n/ty->type->size, 0);
  378.     else
  379.         ty->size = n;
  380.     return ty;
  381. }
  382.  
  383. /* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
  384. static int initstruct(int len,Type ty,int lev)
  385. {
  386.     int a, n = 0;
  387.     Field p = ty->u.sym->u.s.flist;
  388.  
  389.     do {
  390.         if (p->offset > n) {
  391.             genspace(p->offset - n, current);
  392.             n += p->offset - n;
  393.         }
  394.         if (p->lsb) {
  395.             Field q = p;
  396.             while (q->link && q->link->offset == p->offset)
  397.                 q = q->link;
  398.             n += initfields(p, q->link);
  399.             p = q;
  400.         } else {
  401.             initializer(p->type, lev);
  402.             n += p->type->size;
  403.         }
  404.         if (p->link) {
  405.             p = p->link;
  406.             a = p->type->align;
  407.         } else
  408.             a = ty->align;
  409.         if (a > DefaultAlignment) a = DefaultAlignment;
  410.         if (a && n%a) {
  411.             genspace(a - n%a, current);
  412.             n = roundup(n, a);
  413.         }
  414.         if (len > 0 && n >= len || t != ',')
  415.             break;
  416.         t = gettok();
  417.     } while (t != '}');
  418.     return n;
  419. }
  420.  
  421. /* initvalue - evaluate a constant expression for a value of integer type ty */
  422. static Tree initvalue(Type ty)
  423. {
  424.     Type aty;
  425.     Tree e;
  426.  
  427.     needconst++;
  428.     e = expr1(0);
  429.     if ((aty = assign(ty, e)) != NULL)
  430.         e = cast(e, aty);
  431.     else {
  432.         error("invalid initialization type; found `%t' expected `%s'\n",
  433.             e->type,  ty);
  434.         e = consttree(0, ty);
  435.     }
  436.     needconst--;
  437.     if (generic(e->op) != CNST) {
  438.         error("initializer must be constant\n");
  439.         e = consttree(0, ty);
  440.     }
  441.     return e;
  442. }
  443.  
  444. /* structexp - in-line structure expression '{' expr ( , expr )* [ , ] '}' */
  445. Tree structexp(Type ty, Symbol t1)
  446. {
  447.     struct structexp e;
  448.  
  449.     e.var = t1;
  450.     e.off = 0;
  451.     e.tree = 0;
  452.     e.link = current;
  453.     current = &e;
  454.     initializer(ty, 0);
  455.     current = e.link;
  456.     return e.tree;
  457. }
  458.  
  459. /* swtoseg - switch to segment seg, if necessary */
  460. void swtoseg(int seg)
  461. {
  462.     if (curseg != seg)
  463.         (*IR->segment)(seg);
  464.     curseg = seg;
  465. }
  466.