Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include        "cc.h"

Node*
new(int t, Node *l, Node *r)
{
        Node *n;

        n = alloc(sizeof(*n));
        n->op = t;
        n->left = l;
        n->right = r;
        if(l && t != OGOTO)
                n->lineno = l->lineno;
        else if(r)
                n->lineno = r->lineno;
        else
                n->lineno = lineno;
        newflag = 1;
        return n;
}

Node*
new1(int o, Node *l, Node *r)
{
        Node *n;

        n = new(o, l, r);
        n->lineno = nearln;
        return n;
}

void
prtree(Node *n, char *s)
{

        print(" == %s ==\n", s);
        prtree1(n, 0, 0);
        print("\n");
}

void
prtree1(Node *n, int d, int f)
{
        int i;

        if(f)
        for(i=0; i<d; i++)
                print("   ");
        if(n == Z) {
                print("Z\n");
                return;
        }
        if(n->op == OLIST) {
                prtree1(n->left, d, 0);
                prtree1(n->right, d, 1);
                return;
        }
        d++;
        print("%O", n->op);
        i = 3;
        switch(n->op)
        {
        case ONAME:
                print(" \"%F\"", n);
                print(" %ld", n->xoffset);
                i = 0;
                break;

        case OINDREG:
                print(" %ld(R%d)", n->xoffset, n->reg);
                i = 0;
                break;

        case OREGISTER:
                if(n->xoffset)
                        print(" %ld+R%d", n->xoffset, n->reg);
                else
                        print(" R%d", n->reg);
                i = 0;
                break;

        case OSTRING:
                print(" \"%s\"", n->cstring);
                i = 0;
                break;

        case OLSTRING:
                if(sizeof(TRune) == sizeof(Rune))
                        print(" \"%S\"", (Rune*)n->rstring);
                else
                        print(" \"...\"");
                i = 0;
                break;

        case ODOT:
        case OELEM:
                print(" \"%F\"", n);
                break;

        case OCONST:
                if(typefd[n->type->etype])
                        print(" \"%.8e\"", n->fconst);
                else
                        print(" \"%lld\"", n->vconst);
                i = 0;
                break;
        }
        if(n->addable != 0)
                print(" <%d>", n->addable);
        if(n->type != T)
                print(" %T", n->type);
        if(n->complex != 0)
                print(" (%d)", n->complex);
        print(" %L\n", n->lineno);
        if(i & 2)
                prtree1(n->left, d, 1);
        if(i & 1)
                prtree1(n->right, d, 1);
}

Type*
typ(int et, Type *d)
{
        Type *t;

        t = alloc(sizeof(*t));
        t->etype = et;
        t->link = d;
        t->down = T;
        t->sym = S;
        t->width = ewidth[et];
        t->offset = 0;
        t->shift = 0;
        t->nbits = 0;
        t->garb = 0;
        return t;
}

Type*
copytyp(Type *t)
{
        Type *nt;

        nt = typ(TXXX, T);
        *nt = *t;
        return nt;
}

Type*
garbt(Type *t, long b)
{
        Type *t1;

        if(b & BGARB) {
                t1 = copytyp(t);
                t1->garb = simpleg(b);
                return t1;
        }
        return t;
}

int
simpleg(long b)
{

        b &= BGARB;
        switch(b) {
        case BCONSTNT:
                return GCONSTNT;
        case BVOLATILE:
                return GVOLATILE;
        case BVOLATILE|BCONSTNT:
                return GCONSTNT|GVOLATILE;
        }
        return GXXX;
}

int
simplec(long b)
{

        b &= BCLASS;
        switch(b) {
        case 0:
        case BREGISTER:
                return CXXX;
        case BAUTO:
        case BAUTO|BREGISTER:
                return CAUTO;
        case BEXTERN:
                return CEXTERN;
        case BEXTERN|BREGISTER:
                return CEXREG;
        case BSTATIC:
                return CSTATIC;
        case BTYPEDEF:
                return CTYPEDEF;
        case BTYPESTR:
                return CTYPESTR;
        }
        diag(Z, "illegal combination of classes %Q", b);
        return CXXX;
}

Type*
simplet(long b)
{

        b &= ~BCLASS & ~BGARB;
        switch(b) {
        case BCHAR:
        case BCHAR|BSIGNED:
                return types[TCHAR];

        case BCHAR|BUNSIGNED:
                return types[TUCHAR];

        case BSHORT:
        case BSHORT|BINT:
        case BSHORT|BSIGNED:
        case BSHORT|BINT|BSIGNED:
                return types[TSHORT];

        case BUNSIGNED|BSHORT:
        case BUNSIGNED|BSHORT|BINT:
                return types[TUSHORT];

        case 0:
        case BINT:
        case BINT|BSIGNED:
        case BSIGNED:
                return types[TINT];

        case BUNSIGNED:
        case BUNSIGNED|BINT:
                return types[TUINT];

        case BLONG:
        case BLONG|BINT:
        case BLONG|BSIGNED:
        case BLONG|BINT|BSIGNED:
                return types[TLONG];

        case BUNSIGNED|BLONG:
        case BUNSIGNED|BLONG|BINT:
                return types[TULONG];

        case BVLONG|BLONG:
        case BVLONG|BLONG|BINT:
        case BVLONG|BLONG|BSIGNED:
        case BVLONG|BLONG|BINT|BSIGNED:
                return types[TVLONG];

        case BVLONG|BLONG|BUNSIGNED:
        case BVLONG|BLONG|BINT|BUNSIGNED:
                return types[TUVLONG];

        case BFLOAT:
                return types[TFLOAT];

        case BDOUBLE:
        case BDOUBLE|BLONG:
        case BFLOAT|BLONG:
                return types[TDOUBLE];

        case BVOID:
                return types[TVOID];
        }

        diag(Z, "illegal combination of types %Q", b);
        return types[TINT];
}

int
stcompat(Node *n, Type *t1, Type *t2, long ttab[])
{
        int i;
        ulong b;

        i = 0;
        if(t2 != T)
                i = t2->etype;
        b = 1L << i;
        i = 0;
        if(t1 != T)
                i = t1->etype;
        if(b & ttab[i]) {
                if(ttab == tasign)
                        if(b == BSTRUCT || b == BUNION)
                                if(!sametype(t1, t2))
                                        return 1;
                if(n->op != OCAST)
                        if(b == BIND && i == TIND)
                                if(!sametype(t1, t2))
                                        return 1;
                return 0;
        }
        return 1;
}

int
tcompat(Node *n, Type *t1, Type *t2, long ttab[])
{

        if(stcompat(n, t1, t2, ttab)) {
                if(t1 == T)
                        diag(n, "incompatible type: \"%T\" for op \"%O\"",
                                t2, n->op);
                else
                        diag(n, "incompatible types: \"%T\" and \"%T\" for op \"%O\"",
                                t1, t2, n->op);
                return 1;
        }
        return 0;
}

void
makedot(Node *n, Type *t, long o)
{
        Node *n1, *n2;

        if(t->nbits) {
                n1 = new(OXXX, Z, Z);
                *n1 = *n;
                n->op = OBIT;
                n->left = n1;
                n->right = Z;
                n->type = t;
                n->addable = n1->left->addable;
                n = n1;
        }
        n->addable = n->left->addable;
        if(n->addable == 0) {
                n1 = new1(OCONST, Z, Z);
                n1->vconst = o;
                n1->type = types[TLONG];
                n->right = n1;
                n->type = t;
                return;
        }
        n->left->type = t;
        if(o == 0) {
                *n = *n->left;
                return;
        }
        n->type = t;
        n1 = new1(OCONST, Z, Z);
        n1->vconst = o;
        t = typ(TIND, t);
        t->width = types[TIND]->width;
        n1->type = t;

        n2 = new1(OADDR, n->left, Z);
        n2->type = t;

        n1 = new1(OADD, n1, n2);
        n1->type = t;

        n->op = OIND;
        n->left = n1;
        n->right = Z;
}

Type*
dotsearch(Sym *s, Type *t, Node *n, long *off)
{
        Type *t1, *xt, *rt;

        xt = T;

        /*
         * look it up by name
         */
        for(t1 = t; t1 != T; t1 = t1->down)
                if(t1->sym == s) {
                        if(xt != T)
                                goto ambig;
                        xt = t1;
                }

        /*
         * look it up by type
         */
        if(s->class == CTYPEDEF || s->class == CTYPESTR)
                for(t1 = t; t1 != T; t1 = t1->down)
                        if(t1->sym == S && typesu[t1->etype])
                                if(sametype(s->type, t1)) {
                                        if(xt != T)
                                                goto ambig;
                                        xt = t1;
                                }
        if(xt != T) {
                *off = xt->offset;
                return xt;
        }

        /*
         * look it up in unnamed substructures
         */
        for(t1 = t; t1 != T; t1 = t1->down)
                if(t1->sym == S && typesu[t1->etype]){
                        rt = dotsearch(s, t1->link, n, off);
                        if(rt != T) {
                                if(xt != T)
                                        goto ambig;
                                xt = rt;
                                *off += t1->offset;
                        }
                }
        return xt;

ambig:
        diag(n, "ambiguous structure element: %s", s->name);
        return xt;
}

long
dotoffset(Type *st, Type *lt, Node *n)
{
        Type *t;
        Sym *g;
        long o, o1;

        o = -1;
        /*
         * first try matching at the top level
         * for matching tag names
         */
        g = st->tag;
        if(g != S)
                for(t=lt->link; t!=T; t=t->down)
                        if(t->sym == S)
                                if(g == t->tag) {
                                        if(o >= 0)
                                                goto ambig;
                                        o = t->offset;
                                }
        if(o >= 0)
                return o;

        /*
         * second try matching at the top level
         * for similar types
         */
        for(t=lt->link; t!=T; t=t->down)
                if(t->sym == S)
                        if(sametype(st, t)) {
                                if(o >= 0)
                                        goto ambig;
                                o = t->offset;
                        }
        if(o >= 0)
                return o;

        /*
         * last try matching sub-levels
         */
        for(t=lt->link; t!=T; t=t->down)
                if(t->sym == S)
                if(typesu[t->etype]) {
                        o1 = dotoffset(st, t, n);
                        if(o1 >= 0) {
                                if(o >= 0)
                                        goto ambig;
                                o = o1 + t->offset;
                        }
                }
        return o;

ambig:
        diag(n, "ambiguous unnamed structure element");
        return o;
}

/*
 * look into tree for floating point constant expressions
 */
int
allfloat(Node *n, int flag)
{

        if(n != Z) {
                if(n->type->etype != TDOUBLE)
                        return 1;
                switch(n->op) {
                case OCONST:
                        if(flag)
                                n->type = types[TFLOAT];
                        return 1;
                case OADD:      /* no need to get more exotic than this */
                case OSUB:
                case OMUL:
                case ODIV:
                        if(!allfloat(n->right, flag))
                                break;
                case OCAST:
                        if(!allfloat(n->left, flag))
                                break;
                        if(flag)
                                n->type = types[TFLOAT];
                        return 1;
                }
        }
        return 0;
}

void
constas(Node *n, Type *il, Type *ir)
{
        Type *l, *r;

        l = il;
        r = ir;

        if(l == T)
                return;
        if(l->garb & GCONSTNT) {
                warn(n, "assignment to a constant type (%T)", il);
                return;
        }
        if(r == T)
                return;
        for(;;) {
                if(l->etype != TIND || r->etype != TIND)
                        break;
                l = l->link;
                r = r->link;
                if(l == T || r == T)
                        break;
                if(r->garb & GCONSTNT)
                        if(!(l->garb & GCONSTNT)) {
                                warn(n, "assignment of a constant pointer type (%T)", ir);
                                break;
                        }
        }
}

void
typeext1(Type *st, Node *l)
{
        if(st->etype == TFLOAT && allfloat(l, 0))
                allfloat(l, 1);
}

void
typeext(Type *st, Node *l)
{
        Type *lt;
        Node *n1, *n2;
        long o;

        lt = l->type;
        if(lt == T)
                return;
        if(st->etype == TIND && vconst(l) == 0) {
                l->type = st;
                l->vconst = 0;
                return;
        }
        typeext1(st, l);

        /*
         * extension of C
         * if assign of struct containing unnamed sub-struct
         * to type of sub-struct, insert the DOT.
         * if assign of *struct containing unnamed substruct
         * to type of *sub-struct, insert the add-offset
         */
        if(typesu[st->etype] && typesu[lt->etype]) {
                o = dotoffset(st, lt, l);
                if(o >= 0) {
                        n1 = new1(OXXX, Z, Z);
                        *n1 = *l;
                        l->op = ODOT;
                        l->left = n1;
                        l->right = Z;
                        makedot(l, st, o);
                }
                return;
        }
        if(st->etype == TIND && typesu[st->link->etype])
        if(lt->etype == TIND && typesu[lt->link->etype]) {
                o = dotoffset(st->link, lt->link, l);
                if(o >= 0) {
                        l->type = st;
                        if(o == 0)
                                return;
                        n1 = new1(OXXX, Z, Z);
                        *n1 = *l;
                        n2 = new1(OCONST, Z, Z);
                        n2->vconst = o;
                        n2->type = st;
                        l->op = OADD;
                        l->left = n1;
                        l->right = n2;
                }
                return;
        }
}

/*
 * a cast that generates no code
 * (same size move)
 */
int
nocast(Type *t1, Type *t2)
{
        int i, b;

        if(t1->nbits)
                return 0;
        i = 0;
        if(t2 != T)
                i = t2->etype;
        b = 1<<i;
        i = 0;
        if(t1 != T)
                i = t1->etype;
        if(b & ncast[i])
                return 1;
        return 0;
}

/*
 * a cast that has a noop semantic
 * (small to large, convert)
 */
int
nilcast(Type *t1, Type *t2)
{
        int et1, et2;

        if(t1 == T)
                return 0;
        if(t1->nbits)
                return 0;
        if(t2 == T)
                return 0;
        et1 = t1->etype;
        et2 = t2->etype;
        if(et1 == et2)
                return 1;
        if(typefd[et1] && typefd[et2]) {
                if(ewidth[et1] < ewidth[et2])
                        return 1;
                return 0;
        }
        if(typechlp[et1] && typechlp[et2]) {
                if(ewidth[et1] < ewidth[et2])
                        return 1;
                return 0;
        }
        return 0;
}

/*
 * "the usual arithmetic conversions are performed"
 */
void
arith(Node *n, int f)
{
        Type *t1, *t2;
        int i, j, k;
        Node *n1;
        long w;

        t1 = n->left->type;
        if(n->right == Z)
                t2 = t1;
        else
                t2 = n->right->type;
        i = TXXX;
        if(t1 != T)
                i = t1->etype;
        j = TXXX;
        if(t2 != T)
                j = t2->etype;
        k = tab[i][j];
        if(k == TIND) {
                if(i == TIND)
                        n->type = t1;
                else
                if(j == TIND)
                        n->type = t2;
        } else {
                /* convert up to at least int */
                if(f == 1)
                while(k < TINT)
                        k += 2;
                n->type = types[k];
        }
        if(n->op == OSUB)
        if(i == TIND && j == TIND) {
                w = n->right->type->link->width;
                if(w < 1 || n->left->type->link == T || n->left->type->link->width < 1)
                        goto bad;
                n->type = types[ewidth[TIND] <= ewidth[TLONG]? TLONG: TVLONG];
                if(1 && ewidth[TIND] > ewidth[TLONG]){
                        n1 = new1(OXXX, Z, Z);
                        *n1 = *n;
                        n->op = OCAST;
                        n->left = n1;
                        n->right = Z;
                        n->type = types[TLONG];
                }
                if(w > 1) {
                        n1 = new1(OXXX, Z, Z);
                        *n1 = *n;
                        n->op = ODIV;
                        n->left = n1;
                        n1 = new1(OCONST, Z, Z);
                        n1->vconst = w;
                        n1->type = n->type;
                        n->right = n1;
                        w = vlog(n1);
                        if(w >= 0) {
                                n->op = OASHR;
                                n1->vconst = w;
                        }
                }
                return;
        }
        if(!sametype(n->type, n->left->type)) {
                n->left = new1(OCAST, n->left, Z);
                n->left->type = n->type;
                if(n->type->etype == TIND) {
                        w = n->type->link->width;
                        if(w < 1) {
                                snap(n->type->link);
                                w = n->type->link->width;
                                if(w < 1)
                                        goto bad;
                        }
                        if(w > 1) {
                                n1 = new1(OCONST, Z, Z);
                                n1->vconst = w;
                                n1->type = n->type;
                                n->left = new1(OMUL, n->left, n1);
                                n->left->type = n->type;
                        }
                }
        }
        if(n->right != Z)
        if(!sametype(n->type, n->right->type)) {
                n->right = new1(OCAST, n->right, Z);
                n->right->type = n->type;
                if(n->type->etype == TIND) {
                        w = n->type->link->width;
                        if(w < 1) {
                                snap(n->type->link);
                                w = n->type->link->width;
                                if(w < 1)
                                        goto bad;
                        }
                        if(w != 1) {
                                n1 = new1(OCONST, Z, Z);
                                n1->vconst = w;
                                n1->type = n->type;
                                n->right = new1(OMUL, n->right, n1);
                                n->right->type = n->type;
                        }
                }
        }
        return;
bad:
        diag(n, "pointer addition not fully declared: %T", n->type->link);
}

/*
 * try to rewrite shift & mask
 */
void
simplifyshift(Node *n)
{
        ulong c3;
        int o, s1, s2, c1, c2;

        if(!typechlp[n->type->etype])
                return;
        switch(n->op) {
        default:
                return;
        case OASHL:
                s1 = 0;
                break;
        case OLSHR:
                s1 = 1;
                break;
        case OASHR:
                s1 = 2;
                break;
        }
        if(n->right->op != OCONST)
                return;
        if(n->left->op != OAND)
                return;
        if(n->left->right->op != OCONST)
                return;
        switch(n->left->left->op) {
        default:
                return;
        case OASHL:
                s2 = 0;
                break;
        case OLSHR:
                s2 = 1;
                break;
        case OASHR:
                s2 = 2;
                break;
        }
        if(n->left->left->right->op != OCONST)
                return;

        c1 = n->right->vconst;
        c2 = n->left->left->right->vconst;
        c3 = n->left->right->vconst;

/*
        if(debug['h'])
                print("%.3o %ld %ld %d #%.lux\n",
                        (s1<<3)|s2, c1, c2, topbit(c3), c3);
*/

        o = n->op;
        switch((s1<<3)|s2) {
        case 000:       /* (((e <<u c2) & c3) <<u c1) */
                c3 >>= c2;
                c1 += c2;
                if(c1 >= 32)
                        break;
                goto rewrite1;

        case 002:       /* (((e >>s c2) & c3) <<u c1) */
                if(topbit(c3) >= (32-c2))
                        break;
        case 001:       /* (((e >>u c2) & c3) <<u c1) */
                if(c1 > c2) {
                        c3 <<= c2;
                        c1 -= c2;
                        o = OASHL;
                        goto rewrite1;
                }
                c3 <<= c1;
                if(c1 == c2)
                        goto rewrite0;
                c1 = c2-c1;
                o = OLSHR;
                goto rewrite2;

        case 022:       /* (((e >>s c2) & c3) >>s c1) */
                if(c2 <= 0)
                        break;
        case 012:       /* (((e >>s c2) & c3) >>u c1) */
                if(topbit(c3) >= (32-c2))
                        break;
                goto s11;
        case 021:       /* (((e >>u c2) & c3) >>s c1) */
                if(topbit(c3) >= 31 && c2 <= 0)
                        break;
                goto s11;
        case 011:       /* (((e >>u c2) & c3) >>u c1) */
        s11:
                c3 <<= c2;
                c1 += c2;
                if(c1 >= 32)
                        break;
                o = OLSHR;
                goto rewrite1;

        case 020:       /* (((e <<u c2) & c3) >>s c1) */
                if(topbit(c3) >= 31)
                        break;
        case 010:       /* (((e <<u c2) & c3) >>u c1) */
                c3 >>= c1;
                if(c1 == c2)
                        goto rewrite0;
                if(c1 > c2) {
                        c1 -= c2;
                        goto rewrite2;
                }
                c1 = c2 - c1;
                o = OASHL;
                goto rewrite2;
        }
        return;

rewrite0:       /* get rid of both shifts */
if(debug['<'])prtree(n, "rewrite0");
        *n = *n->left;
        n->left = n->left->left;
        n->right->vconst = c3;
        return;
rewrite1:       /* get rid of lower shift */
if(debug['<'])prtree(n, "rewrite1");
        n->left->left = n->left->left->left;
        n->left->right->vconst = c3;
        n->right->vconst = c1;
        n->op = o;
        return;
rewrite2:       /* get rid of upper shift */
if(debug['<'])prtree(n, "rewrite2");
        *n = *n->left;
        n->right->vconst = c3;
        n->left->right->vconst = c1;
        n->left->op = o;
}

int
side(Node *n)
{

loop:
        if(n != Z)
        switch(n->op) {
        case OCAST:
        case ONOT:
        case OADDR:
        case OIND:
                n = n->left;
                goto loop;

        case OCOND:
                if(side(n->left))
                        break;
                n = n->right;

        case OEQ:
        case ONE:
        case OLT:
        case OGE:
        case OGT:
        case OLE:
        case OADD:
        case OSUB:
        case OMUL:
        case OLMUL:
        case ODIV:
        case OLDIV:
        case OLSHR:
        case OASHL:
        case OASHR:
        case OAND:
        case OOR:
        case OXOR:
        case OMOD:
        case OLMOD:
        case OANDAND:
        case OOROR:
        case OCOMMA:
        case ODOT:
                if(side(n->left))
                        break;
                n = n->right;
                goto loop;

        case OSIGN:
        case OSIZE:
        case OCONST:
        case OSTRING:
        case OLSTRING:
        case ONAME:
                return 0;
        }
        return 1;
}

int
vconst(Node *n)
{
        int i;

        if(n == Z)
                goto no;
        if(n->op != OCONST)
                goto no;
        if(n->type == T)
                goto no;
        switch(n->type->etype)
        {
        case TFLOAT:
        case TDOUBLE:
                i = 100;
                if(n->fconst > i || n->fconst < -i)
                        goto no;
                i = n->fconst;
                if(i != n->fconst)
                        goto no;
                return i;

        case TVLONG:
        case TUVLONG:
                i = n->vconst;
                if(i != n->vconst)
                        goto no;
                return i;

        case TCHAR:
        case TUCHAR:
        case TSHORT:
        case TUSHORT:
        case TINT:
        case TUINT:
        case TLONG:
        case TULONG:
        case TIND:
                i = n->vconst;
                if(i != n->vconst)
                        goto no;
                return i;
        }
no:
        return -159;    /* first uninteresting constant */
}

/*
 * return log(n) if n is a power of 2 constant
 */
int
log2(uvlong v)
{
        int s, i;
        uvlong m;

        s = 0;
        m = MASK(8*sizeof(uvlong));
        for(i=32; i; i>>=1) {
                m >>= i;
                if(!(v & m)) {
                        v >>= i;
                        s += i;
                }
        }
        if(v == 1)
                return s;
        return -1;
}

int
vlog(Node *n)
{
        if(n->op != OCONST)
                goto bad;
        if(typefd[n->type->etype])
                goto bad;

        return log2(n->vconst);

bad:
        return -1;
}

int
topbit(ulong v)
{
        int i;

        for(i = -1; v; i++)
                v >>= 1;
        return i;
}

/*
 * try to cast a constant down
 * rather than cast a variable up
 * example:
 *      if(c == 'a')
 */
void
relcon(Node *l, Node *r)
{
        vlong v;

        if(l->op != OCONST)
                return;
        if(r->op != OCAST)
                return;
        if(!nilcast(r->left->type, r->type))
                return;
        switch(r->type->etype) {
        default:
                return;
        case TCHAR:
        case TUCHAR:
        case TSHORT:
        case TUSHORT:
                v = convvtox(l->vconst, r->type->etype);
                if(v != l->vconst)
                        return;
                break;
        }
        l->type = r->left->type;
        *r = *r->left;
}

int
relindex(int o)
{

        switch(o) {
        default:
                diag(Z, "bad in relindex: %O", o);
        case OEQ: return 0;
        case ONE: return 1;
        case OLE: return 2;
        case OLS: return 3;
        case OLT: return 4;
        case OLO: return 5;
        case OGE: return 6;
        case OHS: return 7;
        case OGT: return 8;
        case OHI: return 9;
        }
}

Node*
invert(Node *n)
{
        Node *i;

        if(n == Z || n->op != OLIST)
                return n;
        i = n;
        for(n = n->left; n != Z; n = n->left) {
                if(n->op != OLIST)
                        break;
                i->left = n->right;
                n->right = i;
                i = n;
        }
        i->left = n;
        return i;
}

int
bitno(long b)
{
        int i;

        for(i=0; i<32; i++)
                if(b & (1L<<i))
                        return i;
        diag(Z, "bad in bitno");
        return 0;
}

long
typebitor(long a, long b)
{
        long c;

        c = a | b;
        if(a & b)
                if((a & b) == BLONG)
                        c |= BVLONG;            /* long long => vlong */
                else
                        warn(Z, "once is enough: %Q", a & b);
        return c;
}

void
diag(Node *n, char *fmt, ...)
{
        char buf[STRINGSZ];
        va_list arg;

        va_start(arg, fmt);
        vseprint(buf, buf+sizeof(buf), fmt, arg);
        va_end(arg);
        Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);

        if(debug['X']){
                Bflush(&diagbuf);
                abort();
        }
        if(n != Z)
        if(debug['v'])
                prtree(n, "diagnostic");

        nerrors++;
        if(nerrors > 10) {
                Bprint(&diagbuf, "too many errors\n");
                errorexit();
        }
}

void
warn(Node *n, char *fmt, ...)
{
        char buf[STRINGSZ];
        va_list arg;

        if(debug['w'] || debug['W']) {
                va_start(arg, fmt);
                vseprint(buf, buf+sizeof(buf), fmt, arg);
                va_end(arg);
                if(debug['W']) {
                        diag(n, "%s", buf);
                        return;
                }
                Bprint(&diagbuf, "warning: %L %s\n", (n==Z)? nearln: n->lineno, buf);

                if(n != Z)
                if(debug['v'])
                        prtree(n, "warning");
        }
}

void
yyerror(char *fmt, ...)
{
        char buf[STRINGSZ];
        va_list arg;

        /*
         * hack to intercept message from yaccpar
         */
        if(strcmp(fmt, "syntax error") == 0) {
                yyerror("syntax error, last name: %s", symb);
                return;
        }
        va_start(arg, fmt);
        vseprint(buf, buf+sizeof(buf), fmt, arg);
        va_end(arg);
        Bprint(&diagbuf, "%L %s\n", lineno, buf);
        nerrors++;
        if(nerrors > 10) {
                Bprint(&diagbuf, "too many errors\n");
                errorexit();
        }
}

void
fatal(Node *n, char *fmt, ...)
{
        char buf[STRINGSZ];
        va_list arg;

        va_start(arg, fmt);
        vseprint(buf, buf+sizeof(buf), fmt, arg);
        va_end(arg);
        Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);

        if(debug['X']){
                Bflush(&diagbuf);
                abort();
        }
        if(n != Z)
        if(debug['v'])
                prtree(n, "diagnostic");

        nerrors++;
        errorexit();
}

ulong   thash1  = 0x2edab8c9;
ulong   thash2  = 0x1dc74fb8;
ulong   thash3  = 0x1f241331;
ulong   thash[NALLTYPES];
Init    thashinit[] =
{
        TXXX,           0x17527bbd,     0,
        TCHAR,          0x5cedd32b,     0,
        TUCHAR,         0x552c4454,     0,
        TSHORT,         0x63040b4b,     0,
        TUSHORT,        0x32a45878,     0,
        TINT,           0x4151d5bd,     0,
        TUINT,          0x5ae707d6,     0,
        TLONG,          0x5ef20f47,     0,
        TULONG,         0x36d8eb8f,     0,
        TVLONG,         0x6e5e9590,     0,
        TUVLONG,        0x75910105,     0,
        TFLOAT,         0x25fd7af1,     0,
        TDOUBLE,        0x7c40a1b2,     0,
        TIND,           0x1b832357,     0,
        TFUNC,          0x6babc9cb,     0,
        TARRAY,         0x7c50986d,     0,
        TVOID,          0x44112eff,     0,
        TSTRUCT,        0x7c2da3bf,     0,
        TUNION,         0x3eb25e98,     0,
        TENUM,          0x44b54f61,     0,
        TFILE,          0x19242ac3,     0,
        TOLD,           0x22b15988,     0,
        TDOT,           0x0204f6b3,     0,
        -1,             0,              0,
};

char*   bnames[NALIGN];
Init    bnamesinit[] =
{
        Axxx,   0,      "Axxx",
        Ael1,   0,      "el1",
        Ael2,   0,      "el2",
        Asu2,   0,      "su2",
        Aarg0,  0,      "arg0",
        Aarg1,  0,      "arg1",
        Aarg2,  0,      "arg2",
        Aaut3,  0,      "aut3",
        -1,     0,      0,
};

char*   tnames[NALLTYPES];
Init    tnamesinit[] =
{
        TXXX,           0,      "TXXX",
        TCHAR,          0,      "CHAR",
        TUCHAR,         0,      "UCHAR",
        TSHORT,         0,      "SHORT",
        TUSHORT,        0,      "USHORT",
        TINT,           0,      "INT",
        TUINT,          0,      "UINT",
        TLONG,          0,      "LONG",
        TULONG,         0,      "ULONG",
        TVLONG,         0,      "VLONG",
        TUVLONG,        0,      "UVLONG",
        TFLOAT,         0,      "FLOAT",
        TDOUBLE,        0,      "DOUBLE",
        TIND,           0,      "IND",
        TFUNC,          0,      "FUNC",
        TARRAY,         0,      "ARRAY",
        TVOID,          0,      "VOID",
        TSTRUCT,        0,      "STRUCT",
        TUNION,         0,      "UNION",
        TENUM,          0,      "ENUM",
        TFILE,          0,      "FILE",
        TOLD,           0,      "OLD",
        TDOT,           0,      "DOT",
        -1,             0,      0,
};

char*   gnames[NGTYPES];
Init    gnamesinit[] =
{
        GXXX,                   0,      "GXXX",
        GCONSTNT,               0,      "CONST",
        GVOLATILE,              0,      "VOLATILE",
        GVOLATILE|GCONSTNT,     0,      "CONST-VOLATILE",
        -1,                     0,      0,
};

char*   qnames[NALLTYPES];
Init    qnamesinit[] =
{
        TXXX,           0,      "TXXX",
        TCHAR,          0,      "CHAR",
        TUCHAR,         0,      "UCHAR",
        TSHORT,         0,      "SHORT",
        TUSHORT,        0,      "USHORT",
        TINT,           0,      "INT",
        TUINT,          0,      "UINT",
        TLONG,          0,      "LONG",
        TULONG,         0,      "ULONG",
        TVLONG,         0,      "VLONG",
        TUVLONG,        0,      "UVLONG",
        TFLOAT,         0,      "FLOAT",
        TDOUBLE,        0,      "DOUBLE",
        TIND,           0,      "IND",
        TFUNC,          0,      "FUNC",
        TARRAY,         0,      "ARRAY",
        TVOID,          0,      "VOID",
        TSTRUCT,        0,      "STRUCT",
        TUNION,         0,      "UNION",
        TENUM,          0,      "ENUM",

        TAUTO,          0,      "AUTO",
        TEXTERN,        0,      "EXTERN",
        TSTATIC,        0,      "STATIC",
        TTYPEDEF,       0,      "TYPEDEF",
        TTYPESTR,       0,      "TYPESTR",
        TREGISTER,      0,      "REGISTER",
        TCONSTNT,       0,      "CONSTNT",
        TVOLATILE,      0,      "VOLATILE",
        TUNSIGNED,      0,      "UNSIGNED",
        TSIGNED,        0,      "SIGNED",
        TDOT,           0,      "DOT",
        TFILE,          0,      "FILE",
        TOLD,           0,      "OLD",
        -1,             0,      0,
};
char*   cnames[NCTYPES];
Init    cnamesinit[] =
{
        CXXX,           0,      "CXXX",
        CAUTO,          0,      "AUTO",
        CEXTERN,        0,      "EXTERN",
        CGLOBL,         0,      "GLOBL",
        CSTATIC,        0,      "STATIC",
        CLOCAL,         0,      "LOCAL",
        CTYPEDEF,       0,      "TYPEDEF",
        CTYPESTR,       0,      "TYPESTR",
        CPARAM,         0,      "PARAM",
        CSELEM,         0,      "SELEM",
        CLABEL,         0,      "LABEL",
        CEXREG,         0,      "EXREG",
        -1,             0,      0,
};

char*   onames[OEND+1];
Init    onamesinit[] =
{
        OXXX,           0,      "OXXX",
        OADD,           0,      "ADD",
        OADDR,          0,      "ADDR",
        OAND,           0,      "AND",
        OANDAND,        0,      "ANDAND",
        OARRAY,         0,      "ARRAY",
        OAS,            0,      "AS",
        OASI,           0,      "ASI",
        OASADD,         0,      "ASADD",
        OASAND,         0,      "ASAND",
        OASASHL,        0,      "ASASHL",
        OASASHR,        0,      "ASASHR",
        OASDIV,         0,      "ASDIV",
        OASHL,          0,      "ASHL",
        OASHR,          0,      "ASHR",
        OASLDIV,        0,      "ASLDIV",
        OASLMOD,        0,      "ASLMOD",
        OASLMUL,        0,      "ASLMUL",
        OASLSHR,        0,      "ASLSHR",
        OASMOD,         0,      "ASMOD",
        OASMUL,         0,      "ASMUL",
        OASOR,          0,      "ASOR",
        OASSUB,         0,      "ASSUB",
        OASXOR,         0,      "ASXOR",
        OBIT,           0,      "BIT",
        OBREAK,         0,      "BREAK",
        OCASE,          0,      "CASE",
        OCAST,          0,      "CAST",
        OCOMMA,         0,      "COMMA",
        OCOND,          0,      "COND",
        OCONST,         0,      "CONST",
        OCONTINUE,      0,      "CONTINUE",
        ODIV,           0,      "DIV",
        ODOT,           0,      "DOT",
        ODOTDOT,        0,      "DOTDOT",
        ODWHILE,        0,      "DWHILE",
        OENUM,          0,      "ENUM",
        OEQ,            0,      "EQ",
        OFOR,           0,      "FOR",
        OFUNC,          0,      "FUNC",
        OGE,            0,      "GE",
        OGOTO,          0,      "GOTO",
        OGT,            0,      "GT",
        OHI,            0,      "HI",
        OHS,            0,      "HS",
        OIF,            0,      "IF",
        OIND,           0,      "IND",
        OINDREG,        0,      "INDREG",
        OINIT,          0,      "INIT",
        OLABEL,         0,      "LABEL",
        OLDIV,          0,      "LDIV",
        OLE,            0,      "LE",
        OLIST,          0,      "LIST",
        OLMOD,          0,      "LMOD",
        OLMUL,          0,      "LMUL",
        OLO,            0,      "LO",
        OLS,            0,      "LS",
        OLSHR,          0,      "LSHR",
        OLT,            0,      "LT",
        OMOD,           0,      "MOD",
        OMUL,           0,      "MUL",
        ONAME,          0,      "NAME",
        ONE,            0,      "NE",
        ONOT,           0,      "NOT",
        OOR,            0,      "OR",
        OOROR,          0,      "OROR",
        OPOSTDEC,       0,      "POSTDEC",
        OPOSTINC,       0,      "POSTINC",
        OPREDEC,        0,      "PREDEC",
        OPREINC,        0,      "PREINC",
        OPROTO,         0,      "PROTO",
        OREGISTER,      0,      "REGISTER",
        ORETURN,        0,      "RETURN",
        OSET,           0,      "SET",
        OSIGN,          0,      "SIGN",
        OSIZE,          0,      "SIZE",
        OSTRING,        0,      "STRING",
        OLSTRING,       0,      "LSTRING",
        OSTRUCT,        0,      "STRUCT",
        OSUB,           0,      "SUB",
        OSWITCH,        0,      "SWITCH",
        OUNION,         0,      "UNION",
        OUSED,          0,      "USED",
        OWHILE,         0,      "WHILE",
        OXOR,           0,      "XOR",
        OPOS,           0,      "POS",
        ONEG,           0,      "NEG",
        OCOM,           0,      "COM",
        OELEM,          0,      "ELEM",
        OTST,           0,      "TST",
        OINDEX,         0,      "INDEX",
        OFAS,           0,      "FAS",
        OREGPAIR,       0,      "REGPAIR",
        OEXREG,         0,      "EXREG",
        OEND,           0,      "END",
        -1,             0,      0,
};

/*      OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */
char    comrel[12] =
{
        ONE, OEQ, OGT, OHI, OGE, OHS, OLT, OLO, OLE, OLS,
};
char    invrel[12] =
{
        OEQ, ONE, OGE, OHS, OGT, OHI, OLE, OLS, OLT, OLO,
};
char    logrel[12] =
{
        OEQ, ONE, OLS, OLS, OLO, OLO, OHS, OHS, OHI, OHI,
};

char    typei[NTYPE];
int     typeiinit[] =
{
        TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TVLONG, TUVLONG, -1,
};
char    typeu[NTYPE];
int     typeuinit[] =
{
        TUCHAR, TUSHORT, TUINT, TULONG, TUVLONG, TIND, -1,
};

char    typesuv[NTYPE];
int     typesuvinit[] =
{
        TVLONG, TUVLONG, TSTRUCT, TUNION, -1,
};

char    typeilp[NTYPE];
int     typeilpinit[] =
{
        TINT, TUINT, TLONG, TULONG, TIND, -1
};

char    typechl[NTYPE];
char    typechlv[NTYPE];
char typechlvp[NTYPE];
int     typechlinit[] =
{
        TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, -1,
};

char    typechlp[NTYPE];
int     typechlpinit[] =
{
        TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TIND, -1,
};

char    typechlpfd[NTYPE];
int     typechlpfdinit[] =
{
        TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TFLOAT, TDOUBLE, TIND, -1,
};

char    typec[NTYPE];
int     typecinit[] =
{
        TCHAR, TUCHAR, -1
};

char    typeh[NTYPE];
int     typehinit[] =
{
        TSHORT, TUSHORT, -1,
};

char    typeil[NTYPE];
int     typeilinit[] =
{
        TINT, TUINT, TLONG, TULONG, -1,
};

char    typev[NTYPE];
int     typevinit[] =
{
        TVLONG, TUVLONG, -1,
};

char    typefd[NTYPE];
int     typefdinit[] =
{
        TFLOAT, TDOUBLE, -1,
};

char    typeaf[NTYPE];
int     typeafinit[] =
{
        TFUNC, TARRAY, -1,
};

char    typesu[NTYPE];
int     typesuinit[] =
{
        TSTRUCT, TUNION, -1,
};

long    tasign[NTYPE];
Init    tasigninit[] =
{
        TCHAR,          BNUMBER,        0,
        TUCHAR,         BNUMBER,        0,
        TSHORT,         BNUMBER,        0,
        TUSHORT,        BNUMBER,        0,
        TINT,           BNUMBER,        0,
        TUINT,          BNUMBER,        0,
        TLONG,          BNUMBER,        0,
        TULONG,         BNUMBER,        0,
        TVLONG,         BNUMBER,        0,
        TUVLONG,        BNUMBER,        0,
        TFLOAT,         BNUMBER,        0,
        TDOUBLE,        BNUMBER,        0,
        TIND,           BIND,           0,
        TSTRUCT,        BSTRUCT,        0,
        TUNION,         BUNION,         0,
        -1,             0,              0,
};

long    tasadd[NTYPE];
Init    tasaddinit[] =
{
        TCHAR,          BNUMBER,        0,
        TUCHAR,         BNUMBER,        0,
        TSHORT,         BNUMBER,        0,
        TUSHORT,        BNUMBER,        0,
        TINT,           BNUMBER,        0,
        TUINT,          BNUMBER,        0,
        TLONG,          BNUMBER,        0,
        TULONG,         BNUMBER,        0,
        TVLONG,         BNUMBER,        0,
        TUVLONG,        BNUMBER,        0,
        TFLOAT,         BNUMBER,        0,
        TDOUBLE,        BNUMBER,        0,
        TIND,           BINTEGER,       0,
        -1,             0,              0,
};

long    tcast[NTYPE];
Init    tcastinit[] =
{
        TCHAR,          BNUMBER|BIND|BVOID,     0,
        TUCHAR,         BNUMBER|BIND|BVOID,     0,
        TSHORT,         BNUMBER|BIND|BVOID,     0,
        TUSHORT,        BNUMBER|BIND|BVOID,     0,
        TINT,           BNUMBER|BIND|BVOID,     0,
        TUINT,          BNUMBER|BIND|BVOID,     0,
        TLONG,          BNUMBER|BIND|BVOID,     0,
        TULONG,         BNUMBER|BIND|BVOID,     0,
        TVLONG,         BNUMBER|BIND|BVOID,     0,
        TUVLONG,        BNUMBER|BIND|BVOID,     0,
        TFLOAT,         BNUMBER|BVOID,          0,
        TDOUBLE,        BNUMBER|BVOID,          0,
        TIND,           BINTEGER|BIND|BVOID,    0,
        TVOID,          BVOID,                  0,
        TSTRUCT,        BSTRUCT|BVOID,          0,
        TUNION,         BUNION|BVOID,           0,
        -1,             0,                      0,
};

long    tadd[NTYPE];
Init    taddinit[] =
{
        TCHAR,          BNUMBER|BIND,   0,
        TUCHAR,         BNUMBER|BIND,   0,
        TSHORT,         BNUMBER|BIND,   0,
        TUSHORT,        BNUMBER|BIND,   0,
        TINT,           BNUMBER|BIND,   0,
        TUINT,          BNUMBER|BIND,   0,
        TLONG,          BNUMBER|BIND,   0,
        TULONG,         BNUMBER|BIND,   0,
        TVLONG,         BNUMBER|BIND,   0,
        TUVLONG,        BNUMBER|BIND,   0,
        TFLOAT,         BNUMBER,        0,
        TDOUBLE,        BNUMBER,        0,
        TIND,           BINTEGER,       0,
        -1,             0,              0,
};

long    tsub[NTYPE];
Init    tsubinit[] =
{
        TCHAR,          BNUMBER,        0,
        TUCHAR,         BNUMBER,        0,
        TSHORT,         BNUMBER,        0,
        TUSHORT,        BNUMBER,        0,
        TINT,           BNUMBER,        0,
        TUINT,          BNUMBER,        0,
        TLONG,          BNUMBER,        0,
        TULONG,         BNUMBER,        0,
        TVLONG,         BNUMBER,        0,
        TUVLONG,        BNUMBER,        0,
        TFLOAT,         BNUMBER,        0,
        TDOUBLE,        BNUMBER,        0,
        TIND,           BINTEGER|BIND,  0,
        -1,             0,              0,
};

long    tmul[NTYPE];
Init    tmulinit[] =
{
        TCHAR,          BNUMBER,        0,
        TUCHAR,         BNUMBER,        0,
        TSHORT,         BNUMBER,        0,
        TUSHORT,        BNUMBER,        0,
        TINT,           BNUMBER,        0,
        TUINT,          BNUMBER,        0,
        TLONG,          BNUMBER,        0,
        TULONG,         BNUMBER,        0,
        TVLONG,         BNUMBER,        0,
        TUVLONG,        BNUMBER,        0,
        TFLOAT,         BNUMBER,        0,
        TDOUBLE,        BNUMBER,        0,
        -1,             0,              0,
};

long    tand[NTYPE];
Init    tandinit[] =
{
        TCHAR,          BINTEGER,       0,
        TUCHAR,         BINTEGER,       0,
        TSHORT,         BINTEGER,       0,
        TUSHORT,        BINTEGER,       0,
        TINT,           BNUMBER,        0,
        TUINT,          BNUMBER,        0,
        TLONG,          BINTEGER,       0,
        TULONG,         BINTEGER,       0,
        TVLONG,         BINTEGER,       0,
        TUVLONG,        BINTEGER,       0,
        -1,             0,              0,
};

long    trel[NTYPE];
Init    trelinit[] =
{
        TCHAR,          BNUMBER,        0,
        TUCHAR,         BNUMBER,        0,
        TSHORT,         BNUMBER,        0,
        TUSHORT,        BNUMBER,        0,
        TINT,           BNUMBER,        0,
        TUINT,          BNUMBER,        0,
        TLONG,          BNUMBER,        0,
        TULONG,         BNUMBER,        0,
        TVLONG,         BNUMBER,        0,
        TUVLONG,        BNUMBER,        0,
        TFLOAT,         BNUMBER,        0,
        TDOUBLE,        BNUMBER,        0,
        TIND,           BIND,           0,
        -1,             0,              0,
};

long    tfunct[1] =
{
        BFUNC,
};

long    tindir[1] =
{
        BIND,
};

long    tdot[1] =
{
        BSTRUCT|BUNION,
};

long    tnot[1] =
{
        BNUMBER|BIND,
};

long    targ[1] =
{
        BNUMBER|BIND|BSTRUCT|BUNION,
};

char    tab[NTYPE][NTYPE] =
{
/*TXXX*/        { 0,
                },

/*TCHAR*/       { 0,    TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG,
                        TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TUCHAR*/      { 0,    TUCHAR, TUCHAR, TUSHORT, TUSHORT, TUINT, TUINT, TULONG,
                        TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TSHORT*/      { 0,    TSHORT, TUSHORT, TSHORT, TUSHORT, TINT, TUINT, TLONG,
                        TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TUSHORT*/     { 0,    TUSHORT, TUSHORT, TUSHORT, TUSHORT, TUINT, TUINT, TULONG,
                        TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TINT*/        { 0,    TINT, TUINT, TINT, TUINT, TINT, TUINT, TLONG,
                        TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TUINT*/       { 0,    TUINT, TUINT, TUINT, TUINT, TUINT, TUINT, TULONG,
                        TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TLONG*/       { 0,    TLONG, TULONG, TLONG, TULONG, TLONG, TULONG, TLONG,
                        TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TULONG*/      { 0,    TULONG, TULONG, TULONG, TULONG, TULONG, TULONG, TULONG,
                        TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TVLONG*/      { 0,    TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG,
                        TUVLONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TUVLONG*/     { 0,    TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG,
                        TUVLONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
                },
/*TFLOAT*/      { 0,    TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT,
                        TFLOAT, TFLOAT, TFLOAT, TFLOAT, TDOUBLE, TIND,
                },
/*TDOUBLE*/     { 0,    TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE,
                        TDOUBLE, TDOUBLE, TDOUBLE, TFLOAT, TDOUBLE, TIND,
                },
/*TIND*/        { 0,    TIND, TIND, TIND, TIND, TIND, TIND, TIND,
                         TIND, TIND, TIND, TIND, TIND, TIND,
                },
};

void
urk(char *name, int max, int i)
{
        if(i >= max) {
                fprint(2, "bad tinit: %s %d>=%d\n", name, i, max);
                exits("init");
        }
}

void
tinit(void)
{
        int *ip;
        Init *p;

        for(p=thashinit; p->code >= 0; p++) {
                urk("thash", nelem(thash), p->code);
                thash[p->code] = p->value;
        }
        for(p=bnamesinit; p->code >= 0; p++) {
                urk("bnames", nelem(bnames), p->code);
                bnames[p->code] = p->s;
        }
        for(p=tnamesinit; p->code >= 0; p++) {
                urk("tnames", nelem(tnames), p->code);
                tnames[p->code] = p->s;
        }
        for(p=gnamesinit; p->code >= 0; p++) {
                urk("gnames", nelem(gnames), p->code);
                gnames[p->code] = p->s;
        }
        for(p=qnamesinit; p->code >= 0; p++) {
                urk("qnames", nelem(qnames), p->code);
                qnames[p->code] = p->s;
        }
        for(p=cnamesinit; p->code >= 0; p++) {
                urk("cnames", nelem(cnames), p->code);
                cnames[p->code] = p->s;
        }
        for(p=onamesinit; p->code >= 0; p++) {
                urk("onames", nelem(onames), p->code);
                onames[p->code] = p->s;
        }
        for(ip=typeiinit; *ip>=0; ip++) {
                urk("typei", nelem(typei), *ip);
                typei[*ip] = 1;
        }
        for(ip=typeuinit; *ip>=0; ip++) {
                urk("typeu", nelem(typeu), *ip);
                typeu[*ip] = 1;
        }
        for(ip=typesuvinit; *ip>=0; ip++) {
                urk("typesuv", nelem(typesuv), *ip);
                typesuv[*ip] = 1;
        }
        for(ip=typeilpinit; *ip>=0; ip++) {
                urk("typeilp", nelem(typeilp), *ip);
                typeilp[*ip] = 1;
        }
        for(ip=typechlinit; *ip>=0; ip++) {
                urk("typechl", nelem(typechl), *ip);
                typechl[*ip] = 1;
                typechlv[*ip] = 1;
                typechlvp[*ip] = 1;
        }
        for(ip=typechlpinit; *ip>=0; ip++) {
                urk("typechlp", nelem(typechlp), *ip);
                typechlp[*ip] = 1;
                typechlvp[*ip] = 1;
        }
        for(ip=typechlpfdinit; *ip>=0; ip++) {
                urk("typechlpfd", nelem(typechlpfd), *ip);
                typechlpfd[*ip] = 1;
        }
        for(ip=typecinit; *ip>=0; ip++) {
                urk("typec", nelem(typec), *ip);
                typec[*ip] = 1;
        }
        for(ip=typehinit; *ip>=0; ip++) {
                urk("typeh", nelem(typeh), *ip);
                typeh[*ip] = 1;
        }
        for(ip=typeilinit; *ip>=0; ip++) {
                urk("typeil", nelem(typeil), *ip);
                typeil[*ip] = 1;
        }
        for(ip=typevinit; *ip>=0; ip++) {
                urk("typev", nelem(typev), *ip);
                typev[*ip] = 1;
                typechlv[*ip] = 1;
                typechlvp[*ip] = 1;
        }
        for(ip=typefdinit; *ip>=0; ip++) {
                urk("typefd", nelem(typefd), *ip);
                typefd[*ip] = 1;
        }
        for(ip=typeafinit; *ip>=0; ip++) {
                urk("typeaf", nelem(typeaf), *ip);
                typeaf[*ip] = 1;
        }
        for(ip=typesuinit; *ip >= 0; ip++) {
                urk("typesu", nelem(typesu), *ip);
                typesu[*ip] = 1;
        }
        for(p=tasigninit; p->code >= 0; p++) {
                urk("tasign", nelem(tasign), p->code);
                tasign[p->code] = p->value;
        }
        for(p=tasaddinit; p->code >= 0; p++) {
                urk("tasadd", nelem(tasadd), p->code);
                tasadd[p->code] = p->value;
        }
        for(p=tcastinit; p->code >= 0; p++) {
                urk("tcast", nelem(tcast), p->code);
                tcast[p->code] = p->value;
        }
        for(p=taddinit; p->code >= 0; p++) {
                urk("tadd", nelem(tadd), p->code);
                tadd[p->code] = p->value;
        }
        for(p=tsubinit; p->code >= 0; p++) {
                urk("tsub", nelem(tsub), p->code);
                tsub[p->code] = p->value;
        }
        for(p=tmulinit; p->code >= 0; p++) {
                urk("tmul", nelem(tmul), p->code);
                tmul[p->code] = p->value;
        }
        for(p=tandinit; p->code >= 0; p++) {
                urk("tand", nelem(tand), p->code);
                tand[p->code] = p->value;
        }
        for(p=trelinit; p->code >= 0; p++) {
                urk("trel", nelem(trel), p->code);
                trel[p->code] = p->value;
        }
        
        /* 32-bit defaults */
        typeword = typechlp;
        typeswitch = typechl;
        typecmplx = typesuv;
}

/*
 * return 1 if it is impossible to jump into the middle of n.
 */
static int
deadhead(Node *n, int caseok)
{
loop:
        if(n == Z)
                return 1;
        switch(n->op) {
        case OLIST:
                if(!deadhead(n->left, caseok))
                        return 0;
        rloop:
                n = n->right;
                goto loop;

        case ORETURN:
                break;

        case OLABEL:
                return 0;

        case OGOTO:
                break;

        case OCASE:
                if(!caseok)
                        return 0;
                goto rloop;

        case OSWITCH:
                return deadhead(n->right, 1);

        case OWHILE:
        case ODWHILE:
                goto rloop;

        case OFOR:
                goto rloop;

        case OCONTINUE:
                break;

        case OBREAK:
                break;

        case OIF:
                return deadhead(n->right->left, caseok) && deadhead(n->right->right, caseok);

        case OSET:
        case OUSED:
                break;
        }
        return 1;
}

int
deadheads(Node *c)
{
        return deadhead(c->left, 0) && deadhead(c->right, 0);
}

int
mixedasop(Type *l, Type *r)
{
        return !typefd[l->etype] && typefd[r->etype];
}