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

  1. #include "c.h"
  2.  
  3. static Tree addtree ARGS((int, Tree, Tree));
  4. static Tree andtree ARGS((int, Tree, Tree));
  5. static Tree cmptree ARGS((int, Tree, Tree));
  6. static int compatible ARGS((Type, Type));
  7. static int isnullptr ARGS((Tree e));
  8. static Tree multree ARGS((int, Tree, Tree));
  9. static Tree subtree ARGS((int, Tree, Tree));
  10. #define isvoidptr(ty) \
  11.     (isptr(ty) && unqual(ty->type) == voidtype)
  12.  
  13. Tree (*optree[]) ARGS((int, Tree, Tree)) = {
  14. #define xx(a,b,c,d,e,f,g) e,
  15. #define yy(a,b,c,d,e,f,g) e,
  16. #include "token.h"
  17. };
  18.  
  19. void typewarning(int op,Tree l,Tree r);
  20.  
  21. Tree call(Tree f,Type fty,Coordinate src)
  22. {
  23.     int n = 0;
  24.     Tree args = NULL, r = NULL;
  25.     Type *proto, rty = unqual(freturn(fty));
  26.     Symbol t3 = NULL;
  27.     Tree result;
  28.     Type functionCallType;
  29.     int isIntrinsic=0,nestedCall,intrinsicArgsTableIdx=0;
  30.     Tree intrinsicArgsTable[10];
  31.  
  32.     if (fty->u.f.oldstyle)
  33.         proto = NULL;
  34.     else
  35.         proto = fty->u.f.proto;
  36.     if (f->u.sym) {
  37.         if (f->Flags) {
  38.             isIntrinsic = IsIntrinsic(f->u.sym->name);
  39.         }
  40.         f->u.sym->x.callused++;
  41.     }
  42.     if (hascall(f))
  43.         r = f;
  44.     if (isstruct(rty))
  45.         {
  46.             t3 = temporary(AUTO, unqual(rty), level);
  47.             if (rty->size == 0)
  48.                 error("illegal use of incomplete type `%t'\n", rty);
  49.         }
  50.     if (t != ')')
  51.         for (;;) {
  52.             Tree q = pointer(expr1(0));
  53.             if (proto && *proto && *proto != voidtype)
  54.                 {
  55.                     Type aty;
  56.                     q = value(q);
  57.                     aty = assign(*proto, q);
  58.                     if (aty)
  59.                         q = cast(q, aty);
  60.                     else
  61.                         error("type error in argument %d to %s; found `%t' expected `%t'\n", n + 1, funcname(f),
  62.  
  63.                             q->type, *proto);
  64.                     if ((isint(q->type) || isenum(q->type))
  65.                     && q->type->size != inttype->size)
  66.                         q = cast(q, promote(q->type));
  67.                     ++proto;
  68.                 }
  69.             else
  70.                 {
  71.                     if (!fty->u.f.oldstyle && *proto == NULL)
  72.                         error("too many arguments to %s\n", funcname(f));
  73.                     q = value(q);
  74.                     if (q->type == floattype)
  75.                         q = cast(q, doubletype);
  76.                     else if (isarray(q->type) || q->type->size == 0)
  77.                         error("type error in argument %d to %s; `%t' is illegal\n", n + 1, funcname(f), q->type);
  78.  
  79.                     else
  80.                         q = cast(q, promote(q->type));
  81.                 }
  82.             if (!IR->wants_argb && isstruct(q->type))
  83.                 if (iscallb(q))
  84.                     q = addrof(q);
  85.                 else {
  86.                     Symbol t1 = temporary(AUTO, unqual(q->type), level);
  87.                     q = asgn(t1, q);
  88.                     q = tree(RIGHT, ptr(t1->type),
  89.                         root(q), lvalue(idtree(t1)));
  90.                 }
  91.             if (q->type->size == 0)
  92.                 q->type = inttype;
  93.             nestedCall = 0;
  94.             if (hascall(q)) {
  95.                 FunctionInfo.NestedCalls = 1;
  96.                 r = r ? tree(RIGHT, voidtype, r, q) : q;
  97.                 nestedCall = 1;
  98.             }
  99.             args = tree(ARG + widen(q->type), q->type, q, args);
  100.             if (isIntrinsic) {
  101.                 args->intrinsicArg=isIntrinsic;
  102.                 args->nestedCall = nestedCall;
  103.                 assert(intrinsicArgsTableIdx < 10);
  104.                 intrinsicArgsTable[intrinsicArgsTableIdx++] = args;
  105.             }
  106.             n++;
  107.             if (Aflag >= 2 && n == 32)
  108.                 warning("more than 31 arguments in a call to %s\n",
  109.                     funcname(f));
  110.             if (t != ',')
  111.                 break;
  112.             t = gettok();
  113.         }
  114.     expect(')');
  115.     if (proto && *proto && *proto != voidtype)
  116.         error("insufficient number of arguments to %s\n",
  117.             funcname(f));
  118.     if (r)
  119.         args = tree(RIGHT, voidtype, r, args);
  120.     if (events.calls)
  121.         apply(events.calls, &src, &f);
  122.     result = calltree(f, rty, args, t3);
  123.     functionCallType = f->type;
  124.     if (functionCallType->op == POINTER)
  125.         functionCallType = functionCallType->type;
  126.     if (functionCallType->u.f.isStdCall) {
  127.         result->Flags = 1;
  128.     }
  129.     if (f->Flags) {
  130.         if (f->u.sym && f->u.sym->name && IsIntrinsic(f->u.sym->name)) {
  131.             int i;
  132.  
  133.             nestedCall = 0;
  134.             for (i=0; i<intrinsicArgsTableIdx;i++) {
  135.                 if (intrinsicArgsTable[i]->nestedCall) {
  136.                     nestedCall = 1;
  137.                     break;
  138.                 }
  139.             }
  140.             for (i=0; i<intrinsicArgsTableIdx;i++) {
  141.                 intrinsicArgsTable[i]->nestedCall = nestedCall;
  142.             }
  143.  
  144.             result->intrinsic=isIntrinsic;
  145.             result->nestedCall = nestedCall;
  146.         }
  147.         result->Flags = 1;
  148.     }
  149.     return(result);
  150. }
  151. Tree calltree(Tree f,Type ty,Tree args,Symbol t3)
  152. {
  153.     Tree p;
  154.  
  155.     if (args)
  156.         f = tree(RIGHT, f->type, args, f);
  157.     if (isstruct(ty))
  158. #ifndef NDEBUG
  159.         assert(t3),
  160. #endif
  161.         p = tree(RIGHT, ty,
  162.             tree(CALL+B, ty, f, addrof(idtree(t3))),
  163.             idtree(t3));
  164.     else {
  165.         Type rty = ty;
  166.         if (isenum(ty))
  167.             rty = unqual(ty)->type;
  168.         else if (isptr(ty))
  169.             rty = unsignedtype;
  170.         p = tree(CALL + widen(rty), promote(rty), f, NULL);
  171.         if (isptr(ty) || p->type->size > ty->size)
  172.             p = cast(p, ty);
  173.     }
  174.     return p;
  175. }
  176. int iscallb(Tree e)
  177. {
  178.     return e->op == RIGHT && e->kids[0] && e->kids[1]
  179.         && e->kids[0]->op == CALL+B
  180.         && e->kids[1]->op == INDIR+B
  181.         && isaddrop(e->kids[1]->kids[0]->op)
  182.         && e->kids[1]->kids[0]->u.sym->temporary;
  183. }
  184.  
  185. static Tree addtree(int op,Tree l,Tree r)
  186. {
  187.     Type ty = inttype;
  188.  
  189.     if (isarith(l->type) && isarith(r->type)) {
  190.         ty = binary(l->type, r->type);
  191.         l = cast(l, ty);
  192.         r = cast(r, ty);
  193.     } else if (isptr(l->type) && isint(r->type))
  194.         return addtree(ADD, r, l);
  195.     else if (  isptr(r->type) && isint(l->type)
  196.     && !isfunc(r->type->type))
  197.         {
  198.             int n;
  199.             ty = unqual(r->type);
  200.             n = ty->type->size;
  201.             if (n == 0)
  202.                 error("unknown size for type `%t'\n", ty->type);
  203.             l = cast(l, promote(l->type));
  204.             if (n > 1)
  205.                 l = multree(MUL, consttree(n, inttype), l);
  206.             if (YYcheck && !isaddrop(r->op))        /* omit */
  207.                 return nullcall(ty, YYcheck, r, l);    /* omit */
  208.             return simplify(ADD+P, ty, l, r);
  209.         }
  210.  
  211.     else
  212.         typeerror(op, l, r);
  213.     return simplify(op, ty, l, r);
  214. }
  215.  
  216. Tree consttree(unsigned n,Type ty)
  217. {
  218.     Tree p;
  219.  
  220.     if (isarray(ty))
  221.         ty = atop(ty);
  222.     p = tree(CNST + ttob(ty), ty, NULL, NULL);
  223.     p->u.v.u = n;
  224.     return p;
  225. }
  226. static Tree cmptree(int op,Tree l,Tree r)
  227. {
  228.     Type ty;
  229.  
  230.     if (isarith(l->type) && isarith(r->type)) {
  231.         if (l->type->size != r->type->size &&
  232.             (r->op == CNSTI || r->op == CNSTU)) {
  233.             if (optype(l->op) == C &&
  234.                 r->u.v.i > 255) {
  235.                 warning("overflow in char comparison with constant %d\n",r->u.v.i);
  236.             }
  237.             else if (optype(l->op) == S &&
  238.                 r->u.v.i > 65535) {
  239.                 warning("overflow in short comparison with constant %d\n",r->u.v.i);
  240.             }
  241.  
  242.         }
  243.         ty = binary(l->type, r->type);
  244.         l = cast(l, ty);
  245.         r = cast(r, ty);
  246.     } else if (compatible(l->type, r->type)) {
  247.         ty = unsignedtype;
  248.         l = cast(l, ty);
  249.         r = cast(r, ty);
  250.     } else {
  251.         ty = unsignedtype;
  252.         typeerror(op, l, r);
  253.     }
  254.     return simplify(op + ttob(ty), inttype, l, r);
  255. }
  256. static int compatible(Type ty1,Type ty2)
  257. {
  258.     return isptr(ty1) && !isfunc(ty1->type)
  259.         && isptr(ty2) && !isfunc(ty2->type)
  260.         && eqtype(unqual(ty1->type), unqual(ty2->type), 0);
  261. }
  262. static int isnullptr(Tree e)
  263. {
  264.     return (isint(e->type) && generic(e->op) == CNST
  265.             && cast(e, unsignedtype)->u.v.u == 0)
  266.         || (isvoidptr(e->type) && e->op == CNST+P
  267.             && e->u.v.p == NULL);
  268. }
  269. Tree eqtree(int op,Tree l,Tree r) 
  270. {
  271.     Type xty = l->type, yty = r->type;
  272.  
  273.     if (isptr(xty) && isnullptr(r)
  274.     ||  isptr(xty) && !isfunc(xty->type) && isvoidptr(yty)
  275.     ||  (isptr(xty) && isptr(yty)
  276.         && eqtype(unqual(xty->type), unqual(yty->type), 1))) {
  277.         Type ty = unsignedtype;
  278.         l = cast(l, ty);
  279.         r = cast(r, ty);
  280.         return simplify(op + U, inttype, l, r);
  281.     }
  282.     if (isptr(yty) && isnullptr(l)
  283.     ||  isptr(yty) && !isfunc(yty->type) && isvoidptr(xty))
  284.         return eqtree(op, r, l);
  285.     return cmptree(op, l, r);
  286. }
  287.  
  288. Type assign(Type xty,Tree e)
  289. {
  290.     Type yty = unqual(e->type);
  291.  
  292.     xty = unqual(xty);
  293.     if (isenum(xty))
  294.         xty = xty->type;
  295.     if (xty->size == 0 || yty->size == 0)
  296.         return NULL;
  297.     if ( isarith(xty) && isarith(yty)
  298.     ||  isstruct(xty) && xty == yty)
  299.         return xty;
  300.     if (isstruct(xty) && isstruct(yty) && extends(yty, xty))
  301.         return xty;
  302.     if (isptr(xty) && isstruct(xty->type)
  303.     &&  isptr(yty) && isstruct(yty->type)
  304.     &&  extends(yty->type, xty->type))
  305.         return xty;
  306.     if (isptr(xty) && isnullptr(e))
  307.         return xty;
  308.     if ((isvoidptr(xty) && isptr(yty)
  309.       || isptr(xty)     && isvoidptr(yty))
  310.     && (  (isconst(xty->type)    || !isconst(yty->type))
  311.        && (isvolatile(xty->type) || !isvolatile(yty->type))))
  312.         return xty;
  313.  
  314.     if ((isptr(xty) && isptr(yty)
  315.         && eqtype(unqual(xty->type), unqual(yty->type), 1))
  316.     &&  (  (isconst(xty->type)    || !isconst(yty->type))
  317.         && (isvolatile(xty->type) || !isvolatile(yty->type))))
  318.         return xty;
  319.     if (isptr(xty) && isptr(yty)
  320.     && (  (isconst(xty->type)    || !isconst(yty->type))
  321.        && (isvolatile(xty->type) || !isvolatile(yty->type)))) {
  322.         Type lty = unqual(xty->type), rty = unqual(yty->type);
  323.         if (isenum(lty) && rty == inttype
  324.         ||  isenum(rty) && lty == inttype) {
  325.             if (Aflag >= 1)
  326.                 warning("assignment between `%t' and `%t' is compiler-dependent\n",
  327.                     xty, yty);
  328.             return xty;
  329.         }
  330.     }
  331.     /* Any pointer can be assigned to any other This is a laxist
  332.        point of view... jn */
  333.     if (isptr(xty) && isptr(yty)) {
  334.         Type t1,t2;
  335.         t1 = unqual(xty->type);
  336.         t2 = unqual(yty->type);
  337.         if (t1 != t2 && !eqtype(t1,t2,1)) {
  338.             if ((t1 != signedchar && t1 != unsignedchar) &&
  339.                 (t2 != signedchar && t2 != unsignedchar))
  340.                 warning("assignment of %t to %t\n",xty,yty);
  341.         }
  342.         return xty;
  343.     }
  344.     return NULL;
  345. }
  346. Tree asgntree(int op,Tree l,Tree r)
  347. {
  348.     Type aty, ty;
  349.  
  350.     r = pointer(r);
  351.     ty = assign(l->type, r);
  352.     if (ty)
  353.         r = cast(r, ty);
  354.     else {
  355.         if (isptr(l->type) && isptr(r->type)) {
  356.             typewarning(ASGN,l,r);
  357.         }
  358.         else
  359.         typeerror(ASGN, l, r);
  360.         if (r->type == voidtype)
  361.             r = retype(r, inttype);
  362.         ty = r->type;
  363.     }
  364.     if (l->op != FIELD)
  365.         l = lvalue(l);
  366.     aty = l->type;
  367.     if (isptr(aty))
  368.         aty = unqual(aty)->type;
  369.     if ( isconst(aty)
  370.     ||  isstruct(aty) && unqual(aty)->u.sym->u.s.cfields)
  371.         if (isaddrop(l->op)
  372.         && !l->u.sym->computed && !l->u.sym->generated)
  373.             error("assignment to const identifier `%s'\n",
  374.                 l->u.sym->name);
  375.         else
  376.             error("assignment to const location\n");
  377.     if (l->op == FIELD) {
  378.         int n = 8*l->u.field->type->size - fieldsize(l->u.field);
  379.         if (n > 0 && isunsigned(l->u.field->type))
  380.             r = bittree(BAND, r,
  381.                 consttree(fieldmask(l->u.field), unsignedtype));
  382.         else if (n > 0) {
  383.             if (r->op == CNST+I)
  384.                 r = consttree(r->u.v.i<<n, inttype);
  385.             else
  386.                 r = shtree(LSH, r, consttree(n, inttype));
  387.             r = shtree(RSH, r, consttree(n, inttype));
  388.         }
  389.     }
  390.     if (isstruct(ty) && isaddrop(l->op) && iscallb(r))
  391.         return tree(RIGHT, ty,
  392.             tree(CALL+B, ty, r->kids[0]->kids[0], l),
  393.             idtree(l->u.sym));
  394.     return tree(op + (isunsigned(ty) ? I : ttob(ty)),
  395.         ty, l, r);
  396. }
  397. Tree condtree(Tree e,Tree l,Tree r)
  398. {
  399.     Symbol t1;
  400.     Type ty, xty = l->type, yty = r->type;
  401.     Tree p;
  402.  
  403.     if (isarith(xty) && isarith(yty))
  404.         ty = binary(xty, yty);
  405.     else if (eqtype(xty, yty, 1))
  406.         ty = unqual(xty);
  407.     else if (isptr(xty)   && isnullptr(r))
  408.         ty = xty;
  409.     else if (isnullptr(l) && isptr(yty))
  410.         ty = yty;
  411.     else if (isptr(xty) && !isfunc(xty->type) && isvoidptr(yty)
  412.     ||       isptr(yty) && !isfunc(yty->type) && isvoidptr(xty))
  413.         ty = voidptype;
  414.     else if ((isptr(xty) && isptr(yty)
  415.          && eqtype(unqual(xty->type), unqual(yty->type), 1)))
  416.         ty = xty;
  417.     else {
  418.         typeerror(COND, l, r);
  419.         return consttree(0, inttype);
  420.     }
  421.     if (isptr(ty)) {
  422.         ty = unqual(unqual(ty)->type);
  423.         if (isptr(xty) && isconst(unqual(xty)->type)
  424.         ||  isptr(yty) && isconst(unqual(yty)->type))
  425.             ty = qual(CONST, ty);
  426.         if (isptr(xty) && isvolatile(unqual(xty)->type)
  427.         ||  isptr(yty) && isvolatile(unqual(yty)->type))
  428.             ty = qual(VOLATILE, ty);
  429.         ty = ptr(ty);
  430.     }
  431.     if (e->op == CNST+D || e->op == CNST+F) {
  432.         e = cast(e, doubletype);
  433.         return retype(e->u.v.d != 0.0 ? l : r, ty);
  434.     }
  435.     if (generic(e->op) == CNST) {
  436.         e = cast(e, unsignedtype);
  437.         return retype(e->u.v.u ? l : r, ty);
  438.     }
  439.     if (ty != voidtype && ty->size > 0) {
  440.         t1 = temporary(REGISTER, unqual(ty), level);
  441.         l = asgn(t1, l);
  442.         r = asgn(t1, r);
  443.     } else
  444.         t1 = NULL;
  445.     p = tree(COND, ty, cond(e),
  446.         tree(RIGHT, ty, root(l), root(r)));
  447.     p->u.sym = t1;
  448.     return p;
  449. }
  450. /* addrof - address of p */
  451. Tree addrof(Tree p)
  452. {
  453.     Tree q = p;
  454.  
  455.     for (;;)
  456.         switch (generic(q->op)) {
  457.         case RIGHT:
  458.             assert(q->kids[0] || q->kids[1]);
  459.             q = q->kids[1] ? q->kids[1] : q->kids[0];
  460.             continue;
  461.         case ASGN:
  462.             q = q->kids[1];
  463.             continue;
  464.         case COND: {
  465.             Symbol t1 = q->u.sym;
  466.             q->u.sym = 0;
  467.             q = idtree(t1);
  468.             /* fall thru */
  469.             }
  470.         case INDIR:
  471.             if (p == q)
  472.                 return q->kids[0];
  473.             q = q->kids[0];
  474.             return tree(RIGHT, q->type, root(p), q);
  475.         default:
  476.             error("addressable object required\n");
  477.             return value(p);
  478.         }
  479. }
  480.  
  481. /* andtree - construct tree for l [&& ||] r */
  482. static Tree andtree(int op,Tree l,Tree r)
  483. {
  484.     if (!isscalar(l->type) || !isscalar(r->type))
  485.         typeerror(op, l, r);
  486.     return simplify(op, inttype, cond(l), cond(r));
  487. }
  488.  
  489. /* asgn - generate tree for assignment of expr e to symbol p sans qualifiers */
  490. Tree asgn(Symbol p,Tree e)
  491. {
  492.     if (isarray(p->type))
  493.         e = tree(ASGN+B, p->type, idtree(p),
  494.             tree(INDIR+B, e->type, e, NULL));
  495.     else {
  496.         Type ty = p->type;
  497.         p->type = unqual(p->type);
  498.         if (isstruct(p->type) && p->type->u.sym->u.s.cfields) {
  499.             p->type->u.sym->u.s.cfields = 0;
  500.             e = asgntree(ASGN, idtree(p), e);
  501.             p->type->u.sym->u.s.cfields = 1;
  502.         } else
  503.             e = asgntree(ASGN, idtree(p), e);
  504.         p->type = ty;
  505.     }
  506.     return e;
  507. }
  508.  
  509. /* bittree - construct tree for l [& | ^ %] r */
  510. Tree bittree(int op,Tree l,Tree r)
  511. {
  512.     Type ty = inttype;
  513.  
  514.     if ((isint(l->type) && isint(r->type)) ||
  515.         ((l->type == longlongtype || l->type == ulonglongtype)
  516.             && isint(r->type)) ||
  517.         (isint(l->type) && (r->type == longlongtype ||
  518.                     r->type == ulonglongtype))) {
  519.          ty = binary(l->type, r->type);
  520.         l = cast(l, ty);
  521.         r = cast(r, ty);
  522.         if (op != MOD) {
  523.             l = cast(l, unsignedtype);
  524.             r = cast(r, unsignedtype);
  525.         }
  526.     } else
  527.         typeerror(op, l, r);
  528.     if (op == MOD)
  529.         return simplify(op, ty, l, r);
  530.     return cast(simplify(op, unsignedtype, l, r), ty);
  531. }
  532.  
  533. /* multree - construct tree for l [* /] r */
  534. static Tree multree(int op,Tree l,Tree r)
  535. {
  536.     Type ty = inttype;
  537.  
  538.     if (isarith(l->type) && isarith(r->type)) {
  539.         ty = binary(l->type, r->type);
  540.         l = cast(l, ty);
  541.         r = cast(r, ty);
  542.     } else
  543.         typeerror(op, l, r);
  544.     return simplify(op, ty, l, r);
  545. }
  546.  
  547. /* shtree - construct tree for l [>> <<] r */
  548. Tree shtree(int op,Tree l,Tree r)
  549. {
  550.     Type ty = inttype;
  551.  
  552.     if (isint(l->type) && isint(r->type)) {
  553.         ty = promote(l->type);
  554.         l = cast(l, ty);
  555.         r = cast(r, inttype);
  556.     } 
  557.     else if ((l->type == ulonglongtype || l->type == longlongtype)
  558.         && ((r->type == ulonglongtype || r->type == longlongtype) ||
  559.         isint(r->type)))
  560.         return simplify((op == LSH)?LSHL:RSHL,l->type,l,r);
  561.     else
  562.         typeerror(op, l, r);
  563.     return simplify(op, ty, l, r);
  564. }
  565.  
  566. /* subtree - construct tree for l - r */
  567. static Tree subtree(int op,Tree l,Tree r)
  568. {
  569.     int n;
  570.     Type ty = inttype;
  571.  
  572.     if (isarith(l->type) && isarith(r->type)) {
  573.         ty = binary(l->type, r->type);
  574.         l = cast(l, ty);
  575.         r = cast(r, ty);
  576.     } else if (isptr(l->type) && !isfunc(l->type->type) && isint(r->type)) {
  577.         ty = unqual(l->type);
  578.         n = ty->type->size;
  579.         if (n == 0)
  580.             error("unknown size for type `%t'\n", ty->type);
  581.         r = cast(r, promote(r->type));
  582.         if (n > 1)
  583.             r = multree(MUL, consttree(n, inttype), r);
  584.         return simplify(SUB+P, ty, l, r);
  585.     } else if (compatible(l->type, r->type)) {
  586.         ty = unqual(l->type);
  587.         n = ty->type->size;
  588.         if (n == 0)
  589.             error("unknown size for type `%t'\n", ty->type);
  590.         l = simplify(SUB+U, unsignedtype, cast(l, unsignedtype),
  591.             cast(r, unsignedtype));
  592.         return simplify(DIV+I, inttype, cast(l, inttype), consttree(n, inttype));
  593.     } else
  594.         typeerror(op, l, r);
  595.     return simplify(op, ty, l, r);
  596. }
  597.     static struct { int op; char *name; } ops[] = {
  598.         ASGN, "=",    INDIR, "*",    NEG,  "-",
  599.         ADD,  "+",    SUB,   "-",    LSH,  "<<",
  600.         MOD,  "%",    RSH,   ">>",    BAND, "&",
  601.         BCOM, "~",    BOR,   "|",    BXOR, "^",
  602.         DIV,  "/",    MUL,   "*",    EQ,   "==",
  603.         GE,   ">=",    GT,    ">",    LE,   "<=",
  604.         LT,   "<",    NE,    "!=",    AND,  "&&",
  605.         NOT,  "!",    OR,    "||",    COND, "?:",
  606.         0, 0
  607.     };
  608.  
  609. /* typeerror - issue "operands of op have illegal types `l' and `r'" */
  610. void typeerror(int op,Tree l,Tree r) {
  611.     int i;
  612.  
  613.     op = generic(op);
  614.     for (i = 0; ops[i].op; i++)
  615.         if (op == ops[i].op)
  616.             break;
  617.     assert(ops[i].name);
  618.     if (r)
  619.         error("operands of %s have illegal types `%t' and `%t'\n",
  620.             ops[i].name, l->type, r->type);
  621.     else
  622.         error("operand of unary %s has illegal type `%t'\n", ops[i].name,
  623.             l->type);
  624. }
  625. /* typewarning - issue "operands of op have different types `l' and `r'" */
  626. void typewarning(int op,Tree l,Tree r) {
  627.     int i;
  628.  
  629.     op = generic(op);
  630.     for (i = 0; ops[i].op; i++)
  631.         if (op == ops[i].op)
  632.             break;
  633.     assert(ops[i].name);
  634.     assert(r);
  635.     warning("operands of %s have different types `%t' and `%t'\n",
  636.             ops[i].name, l->type, r->type);
  637. }
  638.