13e12c5d1SDavid du Colombier #include "gc.h" 23e12c5d1SDavid du Colombier 33e12c5d1SDavid du Colombier void 43e12c5d1SDavid du Colombier codgen(Node *n, Node *nn) 53e12c5d1SDavid du Colombier { 63e12c5d1SDavid du Colombier Prog *sp; 73e12c5d1SDavid du Colombier Node *n1, nod, nod1; 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier cursafe = 0; 103e12c5d1SDavid du Colombier curarg = 0; 113e12c5d1SDavid du Colombier maxargsafe = 0; 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier /* 143e12c5d1SDavid du Colombier * isolate name 153e12c5d1SDavid du Colombier */ 163e12c5d1SDavid du Colombier for(n1 = nn;; n1 = n1->left) { 173e12c5d1SDavid du Colombier if(n1 == Z) { 183e12c5d1SDavid du Colombier diag(nn, "cant find function name"); 193e12c5d1SDavid du Colombier return; 203e12c5d1SDavid du Colombier } 213e12c5d1SDavid du Colombier if(n1->op == ONAME) 223e12c5d1SDavid du Colombier break; 233e12c5d1SDavid du Colombier } 243e12c5d1SDavid du Colombier nearln = nn->lineno; 253e12c5d1SDavid du Colombier gpseudo(ATEXT, n1->sym, nodconst(stkoff)); 263e12c5d1SDavid du Colombier sp = p; 273e12c5d1SDavid du Colombier 283e12c5d1SDavid du Colombier /* 293e12c5d1SDavid du Colombier * isolate first argument 303e12c5d1SDavid du Colombier */ 313e12c5d1SDavid du Colombier if(REGARG) { 32*219b2ee8SDavid du Colombier if(typesu[thisfn->link->etype] || typev[thisfn->link->etype]) { 333e12c5d1SDavid du Colombier nod1 = *nodret->left; 343e12c5d1SDavid du Colombier nodreg(&nod, &nod1, REGARG); 353e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod1); 363e12c5d1SDavid du Colombier } else 373e12c5d1SDavid du Colombier if(firstarg && typechlp[firstargtype->etype]) { 383e12c5d1SDavid du Colombier nod1 = *nodret->left; 393e12c5d1SDavid du Colombier nod1.sym = firstarg; 403e12c5d1SDavid du Colombier nod1.type = firstargtype; 413e12c5d1SDavid du Colombier if(firstargtype->width < tint->width) 42*219b2ee8SDavid du Colombier nod1.xoffset += endian(firstargtype->width); 433e12c5d1SDavid du Colombier nod1.etype = firstargtype->etype; 443e12c5d1SDavid du Colombier nodreg(&nod, &nod1, REGARG); 453e12c5d1SDavid du Colombier gopcode(OAS, &nod, Z, &nod1); 463e12c5d1SDavid du Colombier } 473e12c5d1SDavid du Colombier } 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier retok = 0; 503e12c5d1SDavid du Colombier gen(n); 513e12c5d1SDavid du Colombier if(!retok) 523e12c5d1SDavid du Colombier if(thisfn->link->etype != TVOID) 533e12c5d1SDavid du Colombier warn(Z, "no return at end of function: %s", n1->sym->name); 543e12c5d1SDavid du Colombier noretval(3); 553e12c5d1SDavid du Colombier gbranch(ORETURN); 563e12c5d1SDavid du Colombier 573e12c5d1SDavid du Colombier if(!debug['N'] || debug['R'] || debug['P']) 583e12c5d1SDavid du Colombier regopt(sp); 593e12c5d1SDavid du Colombier 603e12c5d1SDavid du Colombier sp->to.offset += maxargsafe; 613e12c5d1SDavid du Colombier } 623e12c5d1SDavid du Colombier 633e12c5d1SDavid du Colombier void 643e12c5d1SDavid du Colombier gen(Node *n) 653e12c5d1SDavid du Colombier { 663e12c5d1SDavid du Colombier Node *l, nod; 673e12c5d1SDavid du Colombier Prog *sp, *spc, *spb; 683e12c5d1SDavid du Colombier Case *cn; 693e12c5d1SDavid du Colombier long sbc, scc; 703e12c5d1SDavid du Colombier int o; 713e12c5d1SDavid du Colombier 723e12c5d1SDavid du Colombier loop: 733e12c5d1SDavid du Colombier if(n == Z) 743e12c5d1SDavid du Colombier return; 753e12c5d1SDavid du Colombier nearln = n->lineno; 763e12c5d1SDavid du Colombier o = n->op; 773e12c5d1SDavid du Colombier if(debug['G']) 783e12c5d1SDavid du Colombier if(o != OLIST) 793e12c5d1SDavid du Colombier print("%L %O\n", nearln, o); 803e12c5d1SDavid du Colombier retok = 0; 813e12c5d1SDavid du Colombier switch(o) { 823e12c5d1SDavid du Colombier 833e12c5d1SDavid du Colombier default: 843e12c5d1SDavid du Colombier complex(n); 853e12c5d1SDavid du Colombier cgen(n, Z); 863e12c5d1SDavid du Colombier break; 873e12c5d1SDavid du Colombier 883e12c5d1SDavid du Colombier case OLIST: 893e12c5d1SDavid du Colombier gen(n->left); 903e12c5d1SDavid du Colombier 913e12c5d1SDavid du Colombier rloop: 923e12c5d1SDavid du Colombier n = n->right; 933e12c5d1SDavid du Colombier goto loop; 943e12c5d1SDavid du Colombier 953e12c5d1SDavid du Colombier case ORETURN: 963e12c5d1SDavid du Colombier retok = 1; 973e12c5d1SDavid du Colombier complex(n); 983e12c5d1SDavid du Colombier if(n->type == T) 993e12c5d1SDavid du Colombier break; 1003e12c5d1SDavid du Colombier l = n->left; 1013e12c5d1SDavid du Colombier if(l == Z) { 1023e12c5d1SDavid du Colombier noretval(3); 1033e12c5d1SDavid du Colombier gbranch(ORETURN); 1043e12c5d1SDavid du Colombier break; 1053e12c5d1SDavid du Colombier } 106*219b2ee8SDavid du Colombier if(typesu[n->type->etype] || typev[n->type->etype]) { 1073e12c5d1SDavid du Colombier sugen(l, nodret, n->type->width); 1083e12c5d1SDavid du Colombier noretval(3); 1093e12c5d1SDavid du Colombier gbranch(ORETURN); 1103e12c5d1SDavid du Colombier break; 1113e12c5d1SDavid du Colombier } 1123e12c5d1SDavid du Colombier regret(&nod, n); 1133e12c5d1SDavid du Colombier cgen(l, &nod); 1143e12c5d1SDavid du Colombier regfree(&nod); 115*219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 1163e12c5d1SDavid du Colombier noretval(1); 1173e12c5d1SDavid du Colombier else 1183e12c5d1SDavid du Colombier noretval(2); 1193e12c5d1SDavid du Colombier gbranch(ORETURN); 1203e12c5d1SDavid du Colombier break; 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier case OLABEL: 1233e12c5d1SDavid du Colombier l = n->left; 1243e12c5d1SDavid du Colombier if(l) { 125*219b2ee8SDavid du Colombier l->xoffset = pc; 1263e12c5d1SDavid du Colombier if(l->label) 1273e12c5d1SDavid du Colombier patch(l->label, pc); 1283e12c5d1SDavid du Colombier } 1293e12c5d1SDavid du Colombier gbranch(OGOTO); /* prevent self reference in reg */ 1303e12c5d1SDavid du Colombier patch(p, pc); 1313e12c5d1SDavid du Colombier goto rloop; 1323e12c5d1SDavid du Colombier 1333e12c5d1SDavid du Colombier case OGOTO: 1343e12c5d1SDavid du Colombier retok = 1; 1353e12c5d1SDavid du Colombier n = n->left; 1363e12c5d1SDavid du Colombier if(n == Z) 1373e12c5d1SDavid du Colombier return; 1383e12c5d1SDavid du Colombier if(n->complex == 0) { 1393e12c5d1SDavid du Colombier diag(Z, "label undefined: %s", n->sym->name); 1403e12c5d1SDavid du Colombier return; 1413e12c5d1SDavid du Colombier } 1423e12c5d1SDavid du Colombier gbranch(OGOTO); 143*219b2ee8SDavid du Colombier if(n->xoffset) { 144*219b2ee8SDavid du Colombier patch(p, n->xoffset); 1453e12c5d1SDavid du Colombier return; 1463e12c5d1SDavid du Colombier } 1473e12c5d1SDavid du Colombier if(n->label) 1483e12c5d1SDavid du Colombier patch(n->label, pc-1); 1493e12c5d1SDavid du Colombier n->label = p; 1503e12c5d1SDavid du Colombier return; 1513e12c5d1SDavid du Colombier 1523e12c5d1SDavid du Colombier case OCASE: 1533e12c5d1SDavid du Colombier l = n->left; 1543e12c5d1SDavid du Colombier if(cases == C) 1553e12c5d1SDavid du Colombier diag(n, "case/default outside a switch"); 1563e12c5d1SDavid du Colombier if(l == Z) { 1573e12c5d1SDavid du Colombier cas(); 1583e12c5d1SDavid du Colombier cases->val = 0; 1593e12c5d1SDavid du Colombier cases->def = 1; 1603e12c5d1SDavid du Colombier cases->label = pc; 1613e12c5d1SDavid du Colombier goto rloop; 1623e12c5d1SDavid du Colombier } 1633e12c5d1SDavid du Colombier complex(l); 1643e12c5d1SDavid du Colombier if(l->type == T) 1653e12c5d1SDavid du Colombier goto rloop; 1663e12c5d1SDavid du Colombier if(l->op == OCONST) 1673e12c5d1SDavid du Colombier if(typechl[l->type->etype]) { 1683e12c5d1SDavid du Colombier cas(); 169*219b2ee8SDavid du Colombier cases->val = l->vconst; 1703e12c5d1SDavid du Colombier cases->def = 0; 1713e12c5d1SDavid du Colombier cases->label = pc; 1723e12c5d1SDavid du Colombier goto rloop; 1733e12c5d1SDavid du Colombier } 1743e12c5d1SDavid du Colombier diag(n, "case expression must be integer constant"); 1753e12c5d1SDavid du Colombier goto rloop; 1763e12c5d1SDavid du Colombier 1773e12c5d1SDavid du Colombier case OSWITCH: 1783e12c5d1SDavid du Colombier l = n->left; 1793e12c5d1SDavid du Colombier complex(l); 1803e12c5d1SDavid du Colombier if(l->type == T) 1813e12c5d1SDavid du Colombier break; 1823e12c5d1SDavid du Colombier if(!typechl[l->type->etype]) { 1833e12c5d1SDavid du Colombier diag(n, "switch expression must be integer"); 1843e12c5d1SDavid du Colombier break; 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier gbranch(OGOTO); /* entry */ 1883e12c5d1SDavid du Colombier sp = p; 1893e12c5d1SDavid du Colombier 1903e12c5d1SDavid du Colombier cn = cases; 1913e12c5d1SDavid du Colombier cases = C; 1923e12c5d1SDavid du Colombier cas(); 1933e12c5d1SDavid du Colombier 1943e12c5d1SDavid du Colombier sbc = breakpc; 1953e12c5d1SDavid du Colombier breakpc = pc; 1963e12c5d1SDavid du Colombier gbranch(OGOTO); 1973e12c5d1SDavid du Colombier spb = p; 1983e12c5d1SDavid du Colombier 1993e12c5d1SDavid du Colombier gen(n->right); 2003e12c5d1SDavid du Colombier gbranch(OGOTO); 2013e12c5d1SDavid du Colombier patch(p, breakpc); 2023e12c5d1SDavid du Colombier 2033e12c5d1SDavid du Colombier patch(sp, pc); 2043e12c5d1SDavid du Colombier regalloc(&nod, l, Z); 2053e12c5d1SDavid du Colombier nod.type = types[TLONG]; 2063e12c5d1SDavid du Colombier cgen(l, &nod); 2073e12c5d1SDavid du Colombier doswit(&nod); 2083e12c5d1SDavid du Colombier regfree(&nod); 2093e12c5d1SDavid du Colombier patch(spb, pc); 2103e12c5d1SDavid du Colombier 2113e12c5d1SDavid du Colombier cases = cn; 2123e12c5d1SDavid du Colombier breakpc = sbc; 2133e12c5d1SDavid du Colombier break; 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier case OWHILE: 2163e12c5d1SDavid du Colombier case ODWHILE: 2173e12c5d1SDavid du Colombier l = n->left; 2183e12c5d1SDavid du Colombier gbranch(OGOTO); /* entry */ 2193e12c5d1SDavid du Colombier sp = p; 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier scc = continpc; 2223e12c5d1SDavid du Colombier continpc = pc; 2233e12c5d1SDavid du Colombier gbranch(OGOTO); 2243e12c5d1SDavid du Colombier spc = p; 2253e12c5d1SDavid du Colombier 2263e12c5d1SDavid du Colombier sbc = breakpc; 2273e12c5d1SDavid du Colombier breakpc = pc; 2283e12c5d1SDavid du Colombier gbranch(OGOTO); 2293e12c5d1SDavid du Colombier spb = p; 2303e12c5d1SDavid du Colombier 2313e12c5d1SDavid du Colombier patch(spc, pc); 2323e12c5d1SDavid du Colombier if(n->op == OWHILE) 2333e12c5d1SDavid du Colombier patch(sp, pc); 2343e12c5d1SDavid du Colombier bcomplex(l); /* test */ 2353e12c5d1SDavid du Colombier patch(p, breakpc); 2363e12c5d1SDavid du Colombier 2373e12c5d1SDavid du Colombier if(n->op == ODWHILE) 2383e12c5d1SDavid du Colombier patch(sp, pc); 2393e12c5d1SDavid du Colombier gen(n->right); /* body */ 2403e12c5d1SDavid du Colombier gbranch(OGOTO); 2413e12c5d1SDavid du Colombier patch(p, continpc); 2423e12c5d1SDavid du Colombier 2433e12c5d1SDavid du Colombier patch(spb, pc); 2443e12c5d1SDavid du Colombier continpc = scc; 2453e12c5d1SDavid du Colombier breakpc = sbc; 2463e12c5d1SDavid du Colombier break; 2473e12c5d1SDavid du Colombier 2483e12c5d1SDavid du Colombier case OFOR: 2493e12c5d1SDavid du Colombier l = n->left; 2503e12c5d1SDavid du Colombier gen(l->right->left); /* init */ 2513e12c5d1SDavid du Colombier gbranch(OGOTO); /* entry */ 2523e12c5d1SDavid du Colombier sp = p; 2533e12c5d1SDavid du Colombier 2543e12c5d1SDavid du Colombier scc = continpc; 2553e12c5d1SDavid du Colombier continpc = pc; 2563e12c5d1SDavid du Colombier gbranch(OGOTO); 2573e12c5d1SDavid du Colombier spc = p; 2583e12c5d1SDavid du Colombier 2593e12c5d1SDavid du Colombier sbc = breakpc; 2603e12c5d1SDavid du Colombier breakpc = pc; 2613e12c5d1SDavid du Colombier gbranch(OGOTO); 2623e12c5d1SDavid du Colombier spb = p; 2633e12c5d1SDavid du Colombier 2643e12c5d1SDavid du Colombier patch(spc, pc); 2653e12c5d1SDavid du Colombier gen(l->right->right); /* inc */ 2663e12c5d1SDavid du Colombier patch(sp, pc); 2673e12c5d1SDavid du Colombier if(l->left != Z) { /* test */ 2683e12c5d1SDavid du Colombier bcomplex(l->left); 2693e12c5d1SDavid du Colombier patch(p, breakpc); 2703e12c5d1SDavid du Colombier } 2713e12c5d1SDavid du Colombier gen(n->right); /* body */ 2723e12c5d1SDavid du Colombier gbranch(OGOTO); 2733e12c5d1SDavid du Colombier patch(p, continpc); 2743e12c5d1SDavid du Colombier 2753e12c5d1SDavid du Colombier patch(spb, pc); 2763e12c5d1SDavid du Colombier continpc = scc; 2773e12c5d1SDavid du Colombier breakpc = sbc; 2783e12c5d1SDavid du Colombier break; 2793e12c5d1SDavid du Colombier 2803e12c5d1SDavid du Colombier case OCONTINUE: 2813e12c5d1SDavid du Colombier if(continpc < 0) { 2823e12c5d1SDavid du Colombier diag(n, "continue not in a loop"); 2833e12c5d1SDavid du Colombier break; 2843e12c5d1SDavid du Colombier } 2853e12c5d1SDavid du Colombier gbranch(OGOTO); 2863e12c5d1SDavid du Colombier patch(p, continpc); 2873e12c5d1SDavid du Colombier break; 2883e12c5d1SDavid du Colombier 2893e12c5d1SDavid du Colombier case OBREAK: 2903e12c5d1SDavid du Colombier if(breakpc < 0) { 2913e12c5d1SDavid du Colombier diag(n, "break not in a loop"); 2923e12c5d1SDavid du Colombier break; 2933e12c5d1SDavid du Colombier } 2943e12c5d1SDavid du Colombier gbranch(OGOTO); 2953e12c5d1SDavid du Colombier patch(p, breakpc); 2963e12c5d1SDavid du Colombier break; 2973e12c5d1SDavid du Colombier 2983e12c5d1SDavid du Colombier case OIF: 2993e12c5d1SDavid du Colombier l = n->left; 3003e12c5d1SDavid du Colombier bcomplex(l); 3013e12c5d1SDavid du Colombier sp = p; 3023e12c5d1SDavid du Colombier if(n->right->left != Z) 3033e12c5d1SDavid du Colombier gen(n->right->left); 3043e12c5d1SDavid du Colombier if(n->right->right != Z) { 3053e12c5d1SDavid du Colombier gbranch(OGOTO); 3063e12c5d1SDavid du Colombier patch(sp, pc); 3073e12c5d1SDavid du Colombier sp = p; 3083e12c5d1SDavid du Colombier gen(n->right->right); 3093e12c5d1SDavid du Colombier } 3103e12c5d1SDavid du Colombier patch(sp, pc); 3113e12c5d1SDavid du Colombier break; 3123e12c5d1SDavid du Colombier 3133e12c5d1SDavid du Colombier case OSET: 3143e12c5d1SDavid du Colombier case OUSED: 3153e12c5d1SDavid du Colombier n = n->left; 3163e12c5d1SDavid du Colombier for(;;) { 3173e12c5d1SDavid du Colombier if(n->op == OLIST) { 3183e12c5d1SDavid du Colombier l = n->right; 3193e12c5d1SDavid du Colombier n = n->left; 3203e12c5d1SDavid du Colombier complex(l); 3213e12c5d1SDavid du Colombier if(l->op == ONAME) { 3223e12c5d1SDavid du Colombier if(o == OSET) 3233e12c5d1SDavid du Colombier gins(ANOP, Z, l); 3243e12c5d1SDavid du Colombier else 3253e12c5d1SDavid du Colombier gins(ANOP, l, Z); 3263e12c5d1SDavid du Colombier } 3273e12c5d1SDavid du Colombier } else { 3283e12c5d1SDavid du Colombier complex(n); 3293e12c5d1SDavid du Colombier if(n->op == ONAME) { 3303e12c5d1SDavid du Colombier if(o == OSET) 3313e12c5d1SDavid du Colombier gins(ANOP, Z, n); 3323e12c5d1SDavid du Colombier else 3333e12c5d1SDavid du Colombier gins(ANOP, n, Z); 3343e12c5d1SDavid du Colombier } 3353e12c5d1SDavid du Colombier break; 3363e12c5d1SDavid du Colombier } 3373e12c5d1SDavid du Colombier } 3383e12c5d1SDavid du Colombier break; 3393e12c5d1SDavid du Colombier } 3403e12c5d1SDavid du Colombier } 3413e12c5d1SDavid du Colombier 3423e12c5d1SDavid du Colombier void 3433e12c5d1SDavid du Colombier noretval(int n) 3443e12c5d1SDavid du Colombier { 3453e12c5d1SDavid du Colombier 3463e12c5d1SDavid du Colombier if(n & 1) { 3473e12c5d1SDavid du Colombier gins(ANOP, Z, Z); 3483e12c5d1SDavid du Colombier p->to.type = D_REG; 3493e12c5d1SDavid du Colombier p->to.reg = REGRET; 3503e12c5d1SDavid du Colombier } 3513e12c5d1SDavid du Colombier if(n & 2) { 3523e12c5d1SDavid du Colombier gins(ANOP, Z, Z); 3533e12c5d1SDavid du Colombier p->to.type = D_FREG; 3543e12c5d1SDavid du Colombier p->to.reg = FREGRET; 3553e12c5d1SDavid du Colombier } 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier 3583e12c5d1SDavid du Colombier /* 3593e12c5d1SDavid du Colombier * calculate addressability as follows 3603e12c5d1SDavid du Colombier * CONST ==> 20 $value 3613e12c5d1SDavid du Colombier * NAME ==> 10 name 3623e12c5d1SDavid du Colombier * REGISTER ==> 11 register 3633e12c5d1SDavid du Colombier * INDREG ==> 12 *[(reg)+offset] 3643e12c5d1SDavid du Colombier * &10 ==> 2 $name 3653e12c5d1SDavid du Colombier * ADD(2, 20) ==> 2 $name+offset 3663e12c5d1SDavid du Colombier * ADD(3, 20) ==> 3 $(reg)+offset 3673e12c5d1SDavid du Colombier * &12 ==> 3 $(reg)+offset 3683e12c5d1SDavid du Colombier * *11 ==> 11 ?? 3693e12c5d1SDavid du Colombier * *2 ==> 10 name 3703e12c5d1SDavid du Colombier * *3 ==> 12 *(reg)+offset 3713e12c5d1SDavid du Colombier * calculate complexity (number of registers) 3723e12c5d1SDavid du Colombier */ 3733e12c5d1SDavid du Colombier void 3743e12c5d1SDavid du Colombier xcom(Node *n) 3753e12c5d1SDavid du Colombier { 3763e12c5d1SDavid du Colombier Node *l, *r; 3773e12c5d1SDavid du Colombier int v; 3783e12c5d1SDavid du Colombier 3793e12c5d1SDavid du Colombier if(n == Z) 3803e12c5d1SDavid du Colombier return; 3813e12c5d1SDavid du Colombier l = n->left; 3823e12c5d1SDavid du Colombier r = n->right; 3833e12c5d1SDavid du Colombier n->addable = 0; 3843e12c5d1SDavid du Colombier n->complex = 0; 3853e12c5d1SDavid du Colombier switch(n->op) { 3863e12c5d1SDavid du Colombier case OCONST: 3873e12c5d1SDavid du Colombier n->addable = 20; 3883e12c5d1SDavid du Colombier return; 3893e12c5d1SDavid du Colombier 3903e12c5d1SDavid du Colombier case OREGISTER: 3913e12c5d1SDavid du Colombier n->addable = 11; 3923e12c5d1SDavid du Colombier return; 3933e12c5d1SDavid du Colombier 3943e12c5d1SDavid du Colombier case OINDREG: 3953e12c5d1SDavid du Colombier n->addable = 12; 3963e12c5d1SDavid du Colombier return; 3973e12c5d1SDavid du Colombier 3983e12c5d1SDavid du Colombier case ONAME: 3993e12c5d1SDavid du Colombier n->addable = 10; 4003e12c5d1SDavid du Colombier return; 4013e12c5d1SDavid du Colombier 4023e12c5d1SDavid du Colombier case OADDR: 4033e12c5d1SDavid du Colombier xcom(l); 4043e12c5d1SDavid du Colombier if(l->addable == 10) 4053e12c5d1SDavid du Colombier n->addable = 2; 4063e12c5d1SDavid du Colombier if(l->addable == 12) 4073e12c5d1SDavid du Colombier n->addable = 3; 4083e12c5d1SDavid du Colombier break; 4093e12c5d1SDavid du Colombier 4103e12c5d1SDavid du Colombier case OIND: 4113e12c5d1SDavid du Colombier xcom(l); 4123e12c5d1SDavid du Colombier if(l->addable == 11) 4133e12c5d1SDavid du Colombier n->addable = 12; 4143e12c5d1SDavid du Colombier if(l->addable == 3) 4153e12c5d1SDavid du Colombier n->addable = 12; 4163e12c5d1SDavid du Colombier if(l->addable == 2) 4173e12c5d1SDavid du Colombier n->addable = 10; 4183e12c5d1SDavid du Colombier break; 4193e12c5d1SDavid du Colombier 4203e12c5d1SDavid du Colombier case OADD: 4213e12c5d1SDavid du Colombier xcom(l); 4223e12c5d1SDavid du Colombier xcom(r); 4233e12c5d1SDavid du Colombier if(l->addable == 20) { 4243e12c5d1SDavid du Colombier if(r->addable == 2) 4253e12c5d1SDavid du Colombier n->addable = 2; 4263e12c5d1SDavid du Colombier if(r->addable == 3) 4273e12c5d1SDavid du Colombier n->addable = 3; 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier if(r->addable == 20) { 4303e12c5d1SDavid du Colombier if(l->addable == 2) 4313e12c5d1SDavid du Colombier n->addable = 2; 4323e12c5d1SDavid du Colombier if(l->addable == 3) 4333e12c5d1SDavid du Colombier n->addable = 3; 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier break; 4363e12c5d1SDavid du Colombier 4373e12c5d1SDavid du Colombier case OASMUL: 4383e12c5d1SDavid du Colombier case OASLMUL: 4393e12c5d1SDavid du Colombier xcom(l); 4403e12c5d1SDavid du Colombier xcom(r); 4413e12c5d1SDavid du Colombier v = vlog(r); 4423e12c5d1SDavid du Colombier if(v >= 0) { 4433e12c5d1SDavid du Colombier n->op = OASASHL; 444*219b2ee8SDavid du Colombier r->vconst = v; 445*219b2ee8SDavid du Colombier r->type = tint; 4463e12c5d1SDavid du Colombier } 4473e12c5d1SDavid du Colombier break; 4483e12c5d1SDavid du Colombier 4493e12c5d1SDavid du Colombier case OMUL: 4503e12c5d1SDavid du Colombier case OLMUL: 4513e12c5d1SDavid du Colombier xcom(l); 4523e12c5d1SDavid du Colombier xcom(r); 4533e12c5d1SDavid du Colombier v = vlog(r); 4543e12c5d1SDavid du Colombier if(v >= 0) { 4553e12c5d1SDavid du Colombier n->op = OASHL; 456*219b2ee8SDavid du Colombier r->vconst = v; 457*219b2ee8SDavid du Colombier r->type = tint; 4583e12c5d1SDavid du Colombier } 4593e12c5d1SDavid du Colombier v = vlog(l); 4603e12c5d1SDavid du Colombier if(v >= 0) { 4613e12c5d1SDavid du Colombier n->op = OASHL; 4623e12c5d1SDavid du Colombier n->left = r; 4633e12c5d1SDavid du Colombier n->right = l; 4643e12c5d1SDavid du Colombier r = l; 4653e12c5d1SDavid du Colombier l = n->left; 466*219b2ee8SDavid du Colombier r->vconst = v; 467*219b2ee8SDavid du Colombier r->type = tint; 4683e12c5d1SDavid du Colombier } 4693e12c5d1SDavid du Colombier break; 4703e12c5d1SDavid du Colombier 4713e12c5d1SDavid du Colombier case OASLDIV: 4723e12c5d1SDavid du Colombier xcom(l); 4733e12c5d1SDavid du Colombier xcom(r); 4743e12c5d1SDavid du Colombier v = vlog(r); 4753e12c5d1SDavid du Colombier if(v >= 0) { 4763e12c5d1SDavid du Colombier n->op = OASLSHR; 477*219b2ee8SDavid du Colombier r->vconst = v; 478*219b2ee8SDavid du Colombier r->type = tint; 4793e12c5d1SDavid du Colombier } 4803e12c5d1SDavid du Colombier break; 4813e12c5d1SDavid du Colombier 4823e12c5d1SDavid du Colombier case OLDIV: 4833e12c5d1SDavid du Colombier xcom(l); 4843e12c5d1SDavid du Colombier xcom(r); 4853e12c5d1SDavid du Colombier v = vlog(r); 4863e12c5d1SDavid du Colombier if(v >= 0) { 4873e12c5d1SDavid du Colombier n->op = OLSHR; 488*219b2ee8SDavid du Colombier r->vconst = v; 489*219b2ee8SDavid du Colombier r->type = tint; 4903e12c5d1SDavid du Colombier } 4913e12c5d1SDavid du Colombier break; 4923e12c5d1SDavid du Colombier 4933e12c5d1SDavid du Colombier case OASLMOD: 4943e12c5d1SDavid du Colombier xcom(l); 4953e12c5d1SDavid du Colombier xcom(r); 4963e12c5d1SDavid du Colombier v = vlog(r); 4973e12c5d1SDavid du Colombier if(v >= 0) { 4983e12c5d1SDavid du Colombier n->op = OASAND; 499*219b2ee8SDavid du Colombier r->vconst--; 5003e12c5d1SDavid du Colombier } 5013e12c5d1SDavid du Colombier break; 5023e12c5d1SDavid du Colombier 5033e12c5d1SDavid du Colombier case OLMOD: 5043e12c5d1SDavid du Colombier xcom(l); 5053e12c5d1SDavid du Colombier xcom(r); 5063e12c5d1SDavid du Colombier v = vlog(r); 5073e12c5d1SDavid du Colombier if(v >= 0) { 5083e12c5d1SDavid du Colombier n->op = OAND; 509*219b2ee8SDavid du Colombier r->vconst--; 5103e12c5d1SDavid du Colombier } 5113e12c5d1SDavid du Colombier break; 5123e12c5d1SDavid du Colombier 5133e12c5d1SDavid du Colombier default: 5143e12c5d1SDavid du Colombier if(l != Z) 5153e12c5d1SDavid du Colombier xcom(l); 5163e12c5d1SDavid du Colombier if(r != Z) 5173e12c5d1SDavid du Colombier xcom(r); 5183e12c5d1SDavid du Colombier break; 5193e12c5d1SDavid du Colombier } 5203e12c5d1SDavid du Colombier if(n->addable >= 10) 5213e12c5d1SDavid du Colombier return; 5223e12c5d1SDavid du Colombier if(l != Z) 5233e12c5d1SDavid du Colombier n->complex = l->complex; 5243e12c5d1SDavid du Colombier if(r != Z) { 5253e12c5d1SDavid du Colombier if(r->complex == n->complex) 5263e12c5d1SDavid du Colombier n->complex = r->complex+1; 5273e12c5d1SDavid du Colombier else 5283e12c5d1SDavid du Colombier if(r->complex > n->complex) 5293e12c5d1SDavid du Colombier n->complex = r->complex; 5303e12c5d1SDavid du Colombier } 5313e12c5d1SDavid du Colombier if(n->complex == 0) 5323e12c5d1SDavid du Colombier n->complex++; 533*219b2ee8SDavid du Colombier 534*219b2ee8SDavid du Colombier if(com64(n)) 535*219b2ee8SDavid du Colombier return; 536*219b2ee8SDavid du Colombier 5373e12c5d1SDavid du Colombier switch(n->op) { 5383e12c5d1SDavid du Colombier 5393e12c5d1SDavid du Colombier case OFUNC: 5403e12c5d1SDavid du Colombier n->complex = FNX; 5413e12c5d1SDavid du Colombier break; 5423e12c5d1SDavid du Colombier 5433e12c5d1SDavid du Colombier case OEQ: 5443e12c5d1SDavid du Colombier case ONE: 5453e12c5d1SDavid du Colombier case OLE: 5463e12c5d1SDavid du Colombier case OLT: 5473e12c5d1SDavid du Colombier case OGE: 5483e12c5d1SDavid du Colombier case OGT: 5493e12c5d1SDavid du Colombier case OHI: 5503e12c5d1SDavid du Colombier case OHS: 5513e12c5d1SDavid du Colombier case OLO: 5523e12c5d1SDavid du Colombier case OLS: 5533e12c5d1SDavid du Colombier /* 5543e12c5d1SDavid du Colombier * immediate operators, make const on right 5553e12c5d1SDavid du Colombier */ 5563e12c5d1SDavid du Colombier if(l->op == OCONST) { 5573e12c5d1SDavid du Colombier n->left = r; 5583e12c5d1SDavid du Colombier n->right = l; 5593e12c5d1SDavid du Colombier n->op = invrel[relindex(n->op)]; 5603e12c5d1SDavid du Colombier } 5613e12c5d1SDavid du Colombier break; 5623e12c5d1SDavid du Colombier 5633e12c5d1SDavid du Colombier case OADD: 5643e12c5d1SDavid du Colombier case OXOR: 5653e12c5d1SDavid du Colombier case OAND: 5663e12c5d1SDavid du Colombier case OOR: 5673e12c5d1SDavid du Colombier /* 5683e12c5d1SDavid du Colombier * immediate operators, make const on right 5693e12c5d1SDavid du Colombier */ 5703e12c5d1SDavid du Colombier if(l->op == OCONST) { 5713e12c5d1SDavid du Colombier n->left = r; 5723e12c5d1SDavid du Colombier n->right = l; 5733e12c5d1SDavid du Colombier } 5743e12c5d1SDavid du Colombier break; 5753e12c5d1SDavid du Colombier } 5763e12c5d1SDavid du Colombier } 5773e12c5d1SDavid du Colombier 5783e12c5d1SDavid du Colombier void 5793e12c5d1SDavid du Colombier bcomplex(Node *n) 5803e12c5d1SDavid du Colombier { 5813e12c5d1SDavid du Colombier 5823e12c5d1SDavid du Colombier complex(n); 5833e12c5d1SDavid du Colombier if(n->type != T) 5843e12c5d1SDavid du Colombier if(tcompat(n, T, n->type, tnot)) 5853e12c5d1SDavid du Colombier n->type = T; 5863e12c5d1SDavid du Colombier if(n->type != T) { 587*219b2ee8SDavid du Colombier bool64(n); 5883e12c5d1SDavid du Colombier boolgen(n, 1, Z); 5893e12c5d1SDavid du Colombier } else 5903e12c5d1SDavid du Colombier gbranch(OGOTO); 5913e12c5d1SDavid du Colombier } 592