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, *n2, nod; 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(n2 = nn;; n2 = n2->left) { 173e12c5d1SDavid du Colombier if(n2 == Z) { 183e12c5d1SDavid du Colombier diag(nn, "cant find function name"); 193e12c5d1SDavid du Colombier return; 203e12c5d1SDavid du Colombier } 213e12c5d1SDavid du Colombier if(n2->op == ONAME) 223e12c5d1SDavid du Colombier break; 233e12c5d1SDavid du Colombier } 243e12c5d1SDavid du Colombier nearln = nn->lineno; 253e12c5d1SDavid du Colombier gpseudo(ATEXT, n2->sym, nodconst(stkoff)); 263e12c5d1SDavid du Colombier 273e12c5d1SDavid du Colombier /* 283e12c5d1SDavid du Colombier * isolate first argument 293e12c5d1SDavid du Colombier */ 303e12c5d1SDavid du Colombier if(REGARG) { 313e12c5d1SDavid du Colombier n1 = nn; 323e12c5d1SDavid du Colombier if(n1 != Z) 333e12c5d1SDavid du Colombier n1 = n1->right; 343e12c5d1SDavid du Colombier if(n1 != Z && n1->op == OLIST) 353e12c5d1SDavid du Colombier n1 = n1->left; 363e12c5d1SDavid du Colombier if(n1 != Z && n1->op == OPROTO) 373e12c5d1SDavid du Colombier n1 = n1->left; 383e12c5d1SDavid du Colombier if(n1 != Z && typelp[n1->type->etype]) { 393e12c5d1SDavid du Colombier nodreg(&nod, n1, REGARG); 403e12c5d1SDavid du Colombier gmove(&nod, n1); 413e12c5d1SDavid du Colombier } 423e12c5d1SDavid du Colombier } 433e12c5d1SDavid du Colombier 443e12c5d1SDavid du Colombier sp = p; 453e12c5d1SDavid du Colombier retok = 0; 463e12c5d1SDavid du Colombier gen(n); 473e12c5d1SDavid du Colombier if(!retok) 483e12c5d1SDavid du Colombier if(thisfn->link->etype != TVOID) 493e12c5d1SDavid du Colombier warn(Z, "no return at end of function: %s", n2->sym->name); 503e12c5d1SDavid du Colombier noretval(3); 51*219b2ee8SDavid du Colombier if(thisfn && thisfn->link && typefd[thisfn->link->etype]) 523e12c5d1SDavid du Colombier gins(AFLDZ, Z, Z); 533e12c5d1SDavid du Colombier gbranch(ORETURN); 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier if(!debug['N'] || debug['R'] || debug['P']) 563e12c5d1SDavid du Colombier regopt(sp); 573e12c5d1SDavid du Colombier sp->to.offset += maxargsafe; 583e12c5d1SDavid du Colombier } 593e12c5d1SDavid du Colombier 603e12c5d1SDavid du Colombier void 613e12c5d1SDavid du Colombier gen(Node *n) 623e12c5d1SDavid du Colombier { 633e12c5d1SDavid du Colombier Node *l, nod; 643e12c5d1SDavid du Colombier Prog *sp, *spc, *spb; 653e12c5d1SDavid du Colombier Case *cn; 663e12c5d1SDavid du Colombier long sbc, scc; 673e12c5d1SDavid du Colombier int o; 683e12c5d1SDavid du Colombier 693e12c5d1SDavid du Colombier loop: 703e12c5d1SDavid du Colombier if(n == Z) 713e12c5d1SDavid du Colombier return; 723e12c5d1SDavid du Colombier nearln = n->lineno; 733e12c5d1SDavid du Colombier o = n->op; 743e12c5d1SDavid du Colombier if(debug['G']) 753e12c5d1SDavid du Colombier if(o != OLIST) 763e12c5d1SDavid du Colombier print("%L %O\n", nearln, o); 773e12c5d1SDavid du Colombier 783e12c5d1SDavid du Colombier retok = 0; 793e12c5d1SDavid du Colombier switch(o) { 803e12c5d1SDavid du Colombier 813e12c5d1SDavid du Colombier default: 823e12c5d1SDavid du Colombier complex(n); 833e12c5d1SDavid du Colombier cgen(n, Z); 843e12c5d1SDavid du Colombier break; 853e12c5d1SDavid du Colombier 863e12c5d1SDavid du Colombier case OLIST: 873e12c5d1SDavid du Colombier gen(n->left); 883e12c5d1SDavid du Colombier 893e12c5d1SDavid du Colombier rloop: 903e12c5d1SDavid du Colombier n = n->right; 913e12c5d1SDavid du Colombier goto loop; 923e12c5d1SDavid du Colombier 933e12c5d1SDavid du Colombier case ORETURN: 943e12c5d1SDavid du Colombier retok = 1; 953e12c5d1SDavid du Colombier complex(n); 963e12c5d1SDavid du Colombier if(n->type == T) 973e12c5d1SDavid du Colombier break; 983e12c5d1SDavid du Colombier l = n->left; 993e12c5d1SDavid du Colombier if(l == Z) { 1003e12c5d1SDavid du Colombier noretval(3); 101*219b2ee8SDavid du Colombier if(typefd[n->type->etype]) 1023e12c5d1SDavid du Colombier gins(AFLDZ, Z, Z); 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 = REGRET; 3493e12c5d1SDavid du Colombier } 3503e12c5d1SDavid du Colombier if(n & 2) { 3513e12c5d1SDavid du Colombier gins(ANOP, Z, Z); 3523e12c5d1SDavid du Colombier p->to.type = FREGRET; 3533e12c5d1SDavid du Colombier } 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier 3563e12c5d1SDavid du Colombier /* 3573e12c5d1SDavid du Colombier * calculate addressability as follows 3583e12c5d1SDavid du Colombier * NAME ==> 10/11 name+value(SB/SP) 3593e12c5d1SDavid du Colombier * REGISTER ==> 12 register 3603e12c5d1SDavid du Colombier * CONST ==> 20 $value 3613e12c5d1SDavid du Colombier * *(20) ==> 21 value 3623e12c5d1SDavid du Colombier * &(10) ==> 13 $name+value(SB) 3633e12c5d1SDavid du Colombier * &(11) ==> 1 $name+value(SP) 3643e12c5d1SDavid du Colombier * (13) + (20) ==> 13 fold constants 3653e12c5d1SDavid du Colombier * (1) + (20) ==> 1 fold constants 3663e12c5d1SDavid du Colombier * *(13) ==> 10 back to name 3673e12c5d1SDavid du Colombier * *(1) ==> 11 back to name 3683e12c5d1SDavid du Colombier * 3693e12c5d1SDavid du Colombier * (20) * (X) ==> 7 multiplier in indexing 3703e12c5d1SDavid du Colombier * (X,7) + (13,1) ==> 8 adder in indexing (addresses) 3713e12c5d1SDavid du Colombier * (8) ==> &9(OINDEX) index, almost addressable 3723e12c5d1SDavid du Colombier * 3733e12c5d1SDavid du Colombier * calculate complexity (number of registers) 3743e12c5d1SDavid du Colombier */ 3753e12c5d1SDavid du Colombier void 3763e12c5d1SDavid du Colombier xcom(Node *n) 3773e12c5d1SDavid du Colombier { 3783e12c5d1SDavid du Colombier Node *l, *r; 3793e12c5d1SDavid du Colombier int g; 3803e12c5d1SDavid du Colombier 3813e12c5d1SDavid du Colombier if(n == Z) 3823e12c5d1SDavid du Colombier return; 3833e12c5d1SDavid du Colombier l = n->left; 3843e12c5d1SDavid du Colombier r = n->right; 3853e12c5d1SDavid du Colombier n->complex = 0; 3863e12c5d1SDavid du Colombier n->addable = 0; 3873e12c5d1SDavid du Colombier switch(n->op) { 3883e12c5d1SDavid du Colombier case OCONST: 3893e12c5d1SDavid du Colombier n->addable = 20; 3903e12c5d1SDavid du Colombier break; 3913e12c5d1SDavid du Colombier 3923e12c5d1SDavid du Colombier case ONAME: 3933e12c5d1SDavid du Colombier n->addable = 10; 3943e12c5d1SDavid du Colombier if(n->class == CPARAM || n->class == CAUTO) 3953e12c5d1SDavid du Colombier n->addable = 11; 3963e12c5d1SDavid du Colombier break; 3973e12c5d1SDavid du Colombier 3983e12c5d1SDavid du Colombier case OREGISTER: 3993e12c5d1SDavid du Colombier n->addable = 12; 4003e12c5d1SDavid du Colombier break; 4013e12c5d1SDavid du Colombier 4023e12c5d1SDavid du Colombier case OINDREG: 4033e12c5d1SDavid du Colombier n->addable = 12; 4043e12c5d1SDavid du Colombier break; 4053e12c5d1SDavid du Colombier 4063e12c5d1SDavid du Colombier case OADDR: 4073e12c5d1SDavid du Colombier xcom(l); 4083e12c5d1SDavid du Colombier if(l->addable == 10) 4093e12c5d1SDavid du Colombier n->addable = 13; 4103e12c5d1SDavid du Colombier else 4113e12c5d1SDavid du Colombier if(l->addable == 11) 4123e12c5d1SDavid du Colombier n->addable = 1; 4133e12c5d1SDavid du Colombier break; 4143e12c5d1SDavid du Colombier 4153e12c5d1SDavid du Colombier case OADD: 4163e12c5d1SDavid du Colombier xcom(l); 4173e12c5d1SDavid du Colombier xcom(r); 4183e12c5d1SDavid du Colombier if(n->type->etype != TIND) 4193e12c5d1SDavid du Colombier break; 4203e12c5d1SDavid du Colombier 4213e12c5d1SDavid du Colombier if(l->addable == 20) 4223e12c5d1SDavid du Colombier switch(r->addable) { 4233e12c5d1SDavid du Colombier case 13: 4243e12c5d1SDavid du Colombier case 1: 4253e12c5d1SDavid du Colombier n->addable = r->addable; 4263e12c5d1SDavid du Colombier goto brk; 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier if(r->addable == 20) 4293e12c5d1SDavid du Colombier switch(l->addable) { 4303e12c5d1SDavid du Colombier case 13: 4313e12c5d1SDavid du Colombier case 1: 4323e12c5d1SDavid du Colombier n->addable = l->addable; 4333e12c5d1SDavid du Colombier goto brk; 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier 4363e12c5d1SDavid du Colombier switch(r->addable) { 4373e12c5d1SDavid du Colombier case 13: 4383e12c5d1SDavid du Colombier case 1: 4393e12c5d1SDavid du Colombier n->addable = 8; 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier switch(l->addable) { 4423e12c5d1SDavid du Colombier case 13: 4433e12c5d1SDavid du Colombier case 1: 4443e12c5d1SDavid du Colombier n->addable = 8; 4453e12c5d1SDavid du Colombier } 4463e12c5d1SDavid du Colombier if(n->addable == 8) { 4473e12c5d1SDavid du Colombier indx(n); 4483e12c5d1SDavid du Colombier l = new1(OINDEX, idx.basetree, idx.regtree); 4493e12c5d1SDavid du Colombier l->scale = idx.scale; 4503e12c5d1SDavid du Colombier l->addable = 9; 4513e12c5d1SDavid du Colombier l->complex = l->right->complex; 4523e12c5d1SDavid du Colombier l->type = l->left->type; 4533e12c5d1SDavid du Colombier n->op = OADDR; 4543e12c5d1SDavid du Colombier n->left = l; 4553e12c5d1SDavid du Colombier n->right = Z; 4563e12c5d1SDavid du Colombier n->addable = 0; 4573e12c5d1SDavid du Colombier break; 4583e12c5d1SDavid du Colombier } 4593e12c5d1SDavid du Colombier break; 4603e12c5d1SDavid du Colombier 461bd389b36SDavid du Colombier case OINDEX: 462bd389b36SDavid du Colombier xcom(l); 463bd389b36SDavid du Colombier xcom(r); 464bd389b36SDavid du Colombier n->addable = 9; 465bd389b36SDavid du Colombier break; 466bd389b36SDavid du Colombier 4673e12c5d1SDavid du Colombier case OIND: 4683e12c5d1SDavid du Colombier xcom(l); 4693e12c5d1SDavid du Colombier if(l->op == OADDR) { 4703e12c5d1SDavid du Colombier l = l->left; 4713e12c5d1SDavid du Colombier l->type = n->type; 4723e12c5d1SDavid du Colombier *n = *l; 4733e12c5d1SDavid du Colombier return; 4743e12c5d1SDavid du Colombier } 4753e12c5d1SDavid du Colombier switch(l->addable) { 4763e12c5d1SDavid du Colombier case 20: 4773e12c5d1SDavid du Colombier n->addable = 21; 4783e12c5d1SDavid du Colombier break; 4793e12c5d1SDavid du Colombier case 1: 4803e12c5d1SDavid du Colombier n->addable = 11; 4813e12c5d1SDavid du Colombier break; 4823e12c5d1SDavid du Colombier case 13: 4833e12c5d1SDavid du Colombier n->addable = 10; 4843e12c5d1SDavid du Colombier break; 4853e12c5d1SDavid du Colombier } 4863e12c5d1SDavid du Colombier break; 4873e12c5d1SDavid du Colombier 4883e12c5d1SDavid du Colombier case OASHL: 4893e12c5d1SDavid du Colombier xcom(l); 4903e12c5d1SDavid du Colombier xcom(r); 4913e12c5d1SDavid du Colombier g = vconst(r); 4923e12c5d1SDavid du Colombier if(g >= 0 && g < 4) 4933e12c5d1SDavid du Colombier n->addable = 7; 4943e12c5d1SDavid du Colombier break; 4953e12c5d1SDavid du Colombier 4963e12c5d1SDavid du Colombier case OMUL: 4973e12c5d1SDavid du Colombier case OLMUL: 4983e12c5d1SDavid du Colombier xcom(l); 4993e12c5d1SDavid du Colombier xcom(r); 5003e12c5d1SDavid du Colombier g = vlog(r); 5013e12c5d1SDavid du Colombier if(g >= 0) { 5023e12c5d1SDavid du Colombier n->op = OASHL; 503*219b2ee8SDavid du Colombier r->vconst = g; 5043e12c5d1SDavid du Colombier if(g < 4) 5053e12c5d1SDavid du Colombier n->addable = 7; 5063e12c5d1SDavid du Colombier break; 5073e12c5d1SDavid du Colombier } 5083e12c5d1SDavid du Colombier g = vlog(l); 5093e12c5d1SDavid du Colombier if(g >= 0) { 5103e12c5d1SDavid du Colombier n->left = r; 5113e12c5d1SDavid du Colombier n->right = l; 5123e12c5d1SDavid du Colombier l = r; 5133e12c5d1SDavid du Colombier r = n->right; 5143e12c5d1SDavid du Colombier n->op = OASHL; 515*219b2ee8SDavid du Colombier r->vconst = g; 5163e12c5d1SDavid du Colombier if(g < 4) 5173e12c5d1SDavid du Colombier n->addable = 7; 5183e12c5d1SDavid du Colombier break; 5193e12c5d1SDavid du Colombier } 5203e12c5d1SDavid du Colombier break; 5213e12c5d1SDavid du Colombier 5223e12c5d1SDavid du Colombier case ODIV: 5233e12c5d1SDavid du Colombier case OLDIV: 5243e12c5d1SDavid du Colombier xcom(l); 5253e12c5d1SDavid du Colombier xcom(r); 5263e12c5d1SDavid du Colombier g = vlog(r); 5273e12c5d1SDavid du Colombier if(g >= 0) { 5283e12c5d1SDavid du Colombier if(n->op == ODIV) 5293e12c5d1SDavid du Colombier n->op = OASHR; 5303e12c5d1SDavid du Colombier else 5313e12c5d1SDavid du Colombier n->op = OLSHR; 532*219b2ee8SDavid du Colombier r->vconst = g; 5333e12c5d1SDavid du Colombier } 5343e12c5d1SDavid du Colombier break; 5353e12c5d1SDavid du Colombier 5363e12c5d1SDavid du Colombier case OASMUL: 5373e12c5d1SDavid du Colombier case OASLMUL: 5383e12c5d1SDavid du Colombier xcom(l); 5393e12c5d1SDavid du Colombier xcom(r); 5403e12c5d1SDavid du Colombier g = vlog(r); 5413e12c5d1SDavid du Colombier if(g >= 0) { 5423e12c5d1SDavid du Colombier n->op = OASASHL; 543*219b2ee8SDavid du Colombier r->vconst = g; 5443e12c5d1SDavid du Colombier } 5453e12c5d1SDavid du Colombier break; 5463e12c5d1SDavid du Colombier 5473e12c5d1SDavid du Colombier case OASDIV: 5483e12c5d1SDavid du Colombier case OASLDIV: 5493e12c5d1SDavid du Colombier xcom(l); 5503e12c5d1SDavid du Colombier xcom(r); 5513e12c5d1SDavid du Colombier g = vlog(r); 5523e12c5d1SDavid du Colombier if(g >= 0) { 5533e12c5d1SDavid du Colombier if(n->op == OASDIV) 5543e12c5d1SDavid du Colombier n->op = OASASHR; 5553e12c5d1SDavid du Colombier else 5563e12c5d1SDavid du Colombier n->op = OASLSHR; 557*219b2ee8SDavid du Colombier r->vconst = g; 5583e12c5d1SDavid du Colombier } 5593e12c5d1SDavid du Colombier break; 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier default: 5623e12c5d1SDavid du Colombier if(l != Z) 5633e12c5d1SDavid du Colombier xcom(l); 5643e12c5d1SDavid du Colombier if(r != Z) 5653e12c5d1SDavid du Colombier xcom(r); 5663e12c5d1SDavid du Colombier break; 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier brk: 5693e12c5d1SDavid du Colombier if(n->addable >= 10) 5703e12c5d1SDavid du Colombier return; 5713e12c5d1SDavid du Colombier if(l != Z) 5723e12c5d1SDavid du Colombier n->complex = l->complex; 5733e12c5d1SDavid du Colombier if(r != Z) { 5743e12c5d1SDavid du Colombier if(r->complex == n->complex) 5753e12c5d1SDavid du Colombier n->complex = r->complex+1; 5763e12c5d1SDavid du Colombier else 5773e12c5d1SDavid du Colombier if(r->complex > n->complex) 5783e12c5d1SDavid du Colombier n->complex = r->complex; 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier if(n->complex == 0) 5813e12c5d1SDavid du Colombier n->complex++; 582*219b2ee8SDavid du Colombier 583*219b2ee8SDavid du Colombier if(com64(n)) 584*219b2ee8SDavid du Colombier return; 585*219b2ee8SDavid du Colombier 5863e12c5d1SDavid du Colombier switch(n->op) { 5873e12c5d1SDavid du Colombier 5883e12c5d1SDavid du Colombier case OFUNC: 5893e12c5d1SDavid du Colombier n->complex = FNX; 5903e12c5d1SDavid du Colombier break; 5913e12c5d1SDavid du Colombier 5923e12c5d1SDavid du Colombier case OLMOD: 5933e12c5d1SDavid du Colombier case OMOD: 5943e12c5d1SDavid du Colombier case OLMUL: 5953e12c5d1SDavid du Colombier case OLDIV: 5963e12c5d1SDavid du Colombier case OMUL: 5973e12c5d1SDavid du Colombier case ODIV: 5983e12c5d1SDavid du Colombier case OASLMUL: 5993e12c5d1SDavid du Colombier case OASLDIV: 6003e12c5d1SDavid du Colombier case OASLMOD: 6013e12c5d1SDavid du Colombier case OASMUL: 6023e12c5d1SDavid du Colombier case OASDIV: 6033e12c5d1SDavid du Colombier case OASMOD: 6043e12c5d1SDavid du Colombier if(r->complex >= l->complex) { 6053e12c5d1SDavid du Colombier n->complex = l->complex + 3; 6063e12c5d1SDavid du Colombier if(r->complex > n->complex) 6073e12c5d1SDavid du Colombier n->complex = r->complex; 6083e12c5d1SDavid du Colombier } else { 6093e12c5d1SDavid du Colombier n->complex = r->complex + 3; 6103e12c5d1SDavid du Colombier if(l->complex > n->complex) 6113e12c5d1SDavid du Colombier n->complex = l->complex; 6123e12c5d1SDavid du Colombier } 6133e12c5d1SDavid du Colombier break; 6143e12c5d1SDavid du Colombier 6153e12c5d1SDavid du Colombier case OLSHR: 6163e12c5d1SDavid du Colombier case OASHL: 6173e12c5d1SDavid du Colombier case OASHR: 6183e12c5d1SDavid du Colombier case OASLSHR: 6193e12c5d1SDavid du Colombier case OASASHL: 6203e12c5d1SDavid du Colombier case OASASHR: 6213e12c5d1SDavid du Colombier if(r->complex >= l->complex) { 6223e12c5d1SDavid du Colombier n->complex = l->complex + 2; 6233e12c5d1SDavid du Colombier if(r->complex > n->complex) 6243e12c5d1SDavid du Colombier n->complex = r->complex; 6253e12c5d1SDavid du Colombier } else { 6263e12c5d1SDavid du Colombier n->complex = r->complex + 2; 6273e12c5d1SDavid du Colombier if(l->complex > n->complex) 6283e12c5d1SDavid du Colombier n->complex = l->complex; 6293e12c5d1SDavid du Colombier } 6303e12c5d1SDavid du Colombier break; 6313e12c5d1SDavid du Colombier 6323e12c5d1SDavid du Colombier case OADD: 6333e12c5d1SDavid du Colombier case OXOR: 6343e12c5d1SDavid du Colombier case OAND: 6353e12c5d1SDavid du Colombier case OOR: 6363e12c5d1SDavid du Colombier /* 6373e12c5d1SDavid du Colombier * immediate operators, make const on right 6383e12c5d1SDavid du Colombier */ 6393e12c5d1SDavid du Colombier if(l->op == OCONST) { 6403e12c5d1SDavid du Colombier n->left = r; 6413e12c5d1SDavid du Colombier n->right = l; 6423e12c5d1SDavid du Colombier } 6433e12c5d1SDavid du Colombier break; 6443e12c5d1SDavid du Colombier 6453e12c5d1SDavid du Colombier case OEQ: 6463e12c5d1SDavid du Colombier case ONE: 6473e12c5d1SDavid du Colombier case OLE: 6483e12c5d1SDavid du Colombier case OLT: 6493e12c5d1SDavid du Colombier case OGE: 6503e12c5d1SDavid du Colombier case OGT: 6513e12c5d1SDavid du Colombier case OHI: 6523e12c5d1SDavid du Colombier case OHS: 6533e12c5d1SDavid du Colombier case OLO: 6543e12c5d1SDavid du Colombier case OLS: 6553e12c5d1SDavid du Colombier /* 6563e12c5d1SDavid du Colombier * compare operators, make const on left 6573e12c5d1SDavid du Colombier */ 6583e12c5d1SDavid du Colombier if(r->op == OCONST) { 6593e12c5d1SDavid du Colombier n->left = r; 6603e12c5d1SDavid du Colombier n->right = l; 6613e12c5d1SDavid du Colombier n->op = invrel[relindex(n->op)]; 6623e12c5d1SDavid du Colombier } 6633e12c5d1SDavid du Colombier break; 6643e12c5d1SDavid du Colombier } 6653e12c5d1SDavid du Colombier } 6663e12c5d1SDavid du Colombier 6673e12c5d1SDavid du Colombier void 6683e12c5d1SDavid du Colombier indx(Node *n) 6693e12c5d1SDavid du Colombier { 6703e12c5d1SDavid du Colombier Node *l, *r; 6713e12c5d1SDavid du Colombier 6723e12c5d1SDavid du Colombier if(debug['x']) 6733e12c5d1SDavid du Colombier prtree(n, "indx"); 6743e12c5d1SDavid du Colombier 6753e12c5d1SDavid du Colombier l = n->left; 6763e12c5d1SDavid du Colombier r = n->right; 6773e12c5d1SDavid du Colombier if(l->addable == 1 || l->addable == 13) { 6783e12c5d1SDavid du Colombier n->right = l; 6793e12c5d1SDavid du Colombier n->left = r; 6803e12c5d1SDavid du Colombier l = r; 6813e12c5d1SDavid du Colombier r = n->right; 6823e12c5d1SDavid du Colombier } 6833e12c5d1SDavid du Colombier if(l->addable != 7) { 6843e12c5d1SDavid du Colombier idx.regtree = l; 6853e12c5d1SDavid du Colombier idx.scale = 1; 6863e12c5d1SDavid du Colombier } else 6873e12c5d1SDavid du Colombier if(l->right->addable == 20) { 6883e12c5d1SDavid du Colombier idx.regtree = l->left; 689*219b2ee8SDavid du Colombier idx.scale = 1 << l->right->vconst; 6903e12c5d1SDavid du Colombier } else 6913e12c5d1SDavid du Colombier if(l->left->addable == 20) { 6923e12c5d1SDavid du Colombier idx.regtree = l->right; 693*219b2ee8SDavid du Colombier idx.scale = 1 << l->left->vconst; 6943e12c5d1SDavid du Colombier } else 6953e12c5d1SDavid du Colombier diag(n, "bad index"); 6963e12c5d1SDavid du Colombier 6973e12c5d1SDavid du Colombier idx.basetree = r; 6983e12c5d1SDavid du Colombier if(debug['x']) { 6993e12c5d1SDavid du Colombier print("scale = %d\n", idx.scale); 7003e12c5d1SDavid du Colombier prtree(idx.regtree, "index"); 7013e12c5d1SDavid du Colombier prtree(idx.basetree, "base"); 7023e12c5d1SDavid du Colombier } 7033e12c5d1SDavid du Colombier } 7043e12c5d1SDavid du Colombier 7053e12c5d1SDavid du Colombier void 7063e12c5d1SDavid du Colombier bcomplex(Node *n) 7073e12c5d1SDavid du Colombier { 7083e12c5d1SDavid du Colombier 7093e12c5d1SDavid du Colombier complex(n); 7103e12c5d1SDavid du Colombier if(n->type != T) 7113e12c5d1SDavid du Colombier if(tcompat(n, T, n->type, tnot)) 7123e12c5d1SDavid du Colombier n->type = T; 7133e12c5d1SDavid du Colombier if(n->type != T) { 714*219b2ee8SDavid du Colombier bool64(n); 7153e12c5d1SDavid du Colombier boolgen(n, 1, Z); 7163e12c5d1SDavid du Colombier } else 7173e12c5d1SDavid du Colombier gbranch(OGOTO); 7183e12c5d1SDavid du Colombier } 719