changeset 7169: | 94fca26a23d8 |
parent: | 1c857cff1d86 |
child: | b3b84087ac92 |
author: | cinap_lenrek@felloff.net |
date: | Wed, 17 Apr 2019 23:38:00 +0200 |
permissions: | -rw-r--r-- |
description: | 7c: fix long to vlong/pointer conversion, avoid negative immediate offsets we have to explicitely convert to vlong by sign or zero extending as not every operation leaves a proper zero/sign extended result in the register. for example NEGW will zero extend, breaking negative int offsets on pointers. we explicitely insert SXTW or MOVWU instructions which the peephole optimizer takes out again when it is safe todo so. when promoting constant offsets to immediate offsets, make sure the offset will be in range. otherwise the linker will produce not so optimal pointer arithmetic instructions to calculate the offset. |
1 #include "gc.h"3 void4 cgen(Node *n, Node *nn)5 {6 cgenrel(n, nn, 0);7 }9 void10 cgenrel(Node *n, Node *nn, int inrel)11 {12 Node *l, *r;13 Prog *p1;14 Node nod, nod1, nod2, nod3, nod4;15 int o, t;16 long v, curs;18 if(debug['g']) {19 prtree(nn, "cgen lhs");20 prtree(n, "cgen");21 }22 if(n == Z || n->type == T)23 return;24 if(typesu[n->type->etype]) {25 sugen(n, nn, n->type->width);26 return;27 }28 l = n->left;29 r = n->right;30 o = n->op;31 if(n->addable >= INDEXED) {32 if(nn == Z) {33 switch(o) {34 default:35 nullwarn(Z, Z);36 break;37 case OINDEX:38 nullwarn(l, r);39 break;40 }41 return;42 }43 gmove(n, nn);44 return;45 }46 curs = cursafe;48 if(n->complex >= FNX)49 if(l->complex >= FNX)50 if(r != Z && r->complex >= FNX)51 switch(o) {52 default:53 if(cond(o) && typesu[l->type->etype])54 break;56 regret(&nod, r);57 cgen(r, &nod);59 regsalloc(&nod1, r);60 gopcode(OAS, &nod, Z, &nod1);62 regfree(&nod);63 nod = *n;64 nod.right = &nod1;65 cgen(&nod, nn);66 return;68 case OFUNC:69 case OCOMMA:70 case OANDAND:71 case OOROR:72 case OCOND:73 case ODOT:74 break;75 }77 switch(o) {78 default:79 diag(n, "unknown op in cgen: %O", o);80 break;82 case ONEG:83 case OCOM:84 if(nn == Z) {85 nullwarn(l, Z);86 break;87 }88 regalloc(&nod, l, nn);89 cgen(l, &nod);90 gopcode(o, &nod, Z, &nod);91 gmove(&nod, nn);92 regfree(&nod);93 break;95 case OAS:96 if(l->op == OBIT)97 goto bitas;98 if(l->addable >= INDEXED && l->complex < FNX) {99 if(nn != Z || r->addable < INDEXED) { /* || hardconst(r) */100 if(r->complex >= FNX && nn == Z)101 regret(&nod, r);102 else103 regalloc(&nod, r, nn);104 cgen(r, &nod);105 gmove(&nod, l);106 if(nn != Z)107 gmove(&nod, nn);108 regfree(&nod);109 } else110 gmove(r, l);111 break;112 }113 if(l->complex >= r->complex) {114 /* TO DO: see 6c for OINDEX && immconst(r) */115 reglcgen(&nod1, l, Z);116 if(r->addable >= INDEXED) { /* && !hardconst(r) */117 gmove(r, &nod1);118 if(nn != Z)119 gmove(r, nn);120 regfree(&nod1);121 break;122 }123 regalloc(&nod, r, nn);124 cgen(r, &nod);125 } else {126 regalloc(&nod, r, nn);127 cgen(r, &nod);128 reglcgen(&nod1, l, Z);129 }130 gmove(&nod, &nod1);131 regfree(&nod);132 regfree(&nod1);133 break;135 bitas:136 n = l->left;137 regalloc(&nod, r, nn);138 if(l->complex >= r->complex) {139 reglcgen(&nod1, n, Z);140 cgen(r, &nod);141 } else {142 cgen(r, &nod);143 reglcgen(&nod1, n, Z);144 }145 regalloc(&nod2, n, Z);146 gopcode(OAS, &nod1, Z, &nod2);147 bitstore(l, &nod, &nod1, &nod2, nn);148 break;150 case OBIT:151 if(nn == Z) {152 nullwarn(l, Z);153 break;154 }155 bitload(n, &nod, Z, Z, nn);156 gopcode(OAS, &nod, Z, nn);157 regfree(&nod);158 break;160 case ODIV:161 case OMOD:162 if(nn != Z)163 if((t = vlog(r)) >= 0) {164 /* signed div/mod by constant power of 2 */165 cgen(l, nn);166 gopcode(OGE, nodconst(0), nn, Z);167 p1 = p;168 if(o == ODIV) {169 gopcode(OADD, nodconst((1<<t)-1), Z, nn);170 patch(p1, pc);171 gopcode(OASHR, nodconst(t), Z, nn);172 } else {173 gopcode(ONEG, nn, Z, nn);174 gopcode(OAND, nodconst((1<<t)-1), Z, nn);175 gopcode(ONEG, nn, Z, nn);176 gbranch(OGOTO);177 patch(p1, pc);178 p1 = p;179 gopcode(OAND, nodconst((1<<t)-1), Z, nn);180 patch(p1, pc);181 }182 break;183 }184 goto muldiv;186 case OXOR:187 #ifdef NOTYET188 if(nn != Z)189 if(r->op == OCONST && r->vconst == -1){190 cgen(l, nn);191 gopcode(OCOM, nn, Z, nn);192 break;193 }194 #endif196 case OSUB:197 case OADD:198 case OAND:199 case OOR:200 case OLSHR:201 case OASHL:202 case OASHR:203 /*204 * immediate operands205 */206 if(nn != Z)207 if(r->op == OCONST)208 if(!typefd[n->type->etype]) {209 cgen(l, nn);210 if(r->vconst == 0)211 if(o != OAND)212 break;213 if(nn != Z)214 gopcode(o, r, Z, nn);215 break;216 }218 case OLMUL:219 case OLDIV:220 case OLMOD:221 case OMUL:222 muldiv:223 if(nn == Z) {224 nullwarn(l, r);225 break;226 }227 if(o == OMUL || o == OLMUL) {228 if(mulcon(n, nn))229 break;230 }231 if(l->complex >= r->complex) {232 regalloc(&nod, l, nn);233 cgen(l, &nod);234 regalloc(&nod1, l, Z); /* note: l used for type, so shifts work! */235 cgen(r, &nod1);236 gopcode(o, &nod1, Z, &nod);237 } else {238 regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */239 cgen(r, &nod);240 regalloc(&nod1, l, Z);241 cgen(l, &nod1);242 gopcode(o, &nod, &nod1, &nod);243 }244 gopcode(OAS, &nod, Z, nn);245 regfree(&nod);246 regfree(&nod1);247 break;249 case OASLSHR:250 case OASASHL:251 case OASASHR:252 case OASAND:253 case OASADD:254 case OASSUB:255 case OASXOR:256 case OASOR:257 if(l->op == OBIT)258 goto asbitop;259 if(r->op == OCONST)260 if(!typefd[r->type->etype])261 if(!typefd[n->type->etype]) {262 if(l->addable < INDEXED)263 reglcgen(&nod2, l, Z);264 else265 nod2 = *l;266 regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */267 gopcode(OAS, &nod2, Z, &nod);268 gopcode(o, r, Z, &nod);269 gopcode(OAS, &nod, Z, &nod2);271 regfree(&nod);272 if(l->addable < INDEXED)273 regfree(&nod2);274 break;275 }277 case OASLMUL:278 case OASLDIV:279 case OASLMOD:280 case OASMUL:281 case OASDIV:282 case OASMOD:283 if(l->op == OBIT)284 goto asbitop;285 if(l->complex >= r->complex) {286 if(l->addable < INDEXED)287 reglcgen(&nod2, l, Z);288 else289 nod2 = *l;290 regalloc(&nod, n, nn);291 cgen(r, &nod);292 } else {293 regalloc(&nod, n, nn);294 cgen(r, &nod);295 if(l->addable < INDEXED)296 reglcgen(&nod2, l, Z);297 else298 nod2 = *l;299 }300 regalloc(&nod1, n, Z);301 gopcode(OAS, &nod2, Z, &nod1);302 if(nod1.type->etype != nod.type->etype){303 regalloc(&nod3, &nod, Z);304 gmove(&nod1, &nod3);305 regfree(&nod1);306 nod1 = nod3;307 }308 gopcode(o, &nod, &nod1, &nod);309 gmove(&nod, &nod2);310 if(nn != Z)311 gmove(&nod, nn);312 regfree(&nod);313 regfree(&nod1);314 if(l->addable < INDEXED)315 regfree(&nod2);316 break;318 asbitop:319 regalloc(&nod4, n, nn);320 regalloc(&nod3, r, Z);321 if(l->complex >= r->complex) {322 bitload(l, &nod, &nod1, &nod2, &nod4);323 cgen(r, &nod3);324 } else {325 cgen(r, &nod3);326 bitload(l, &nod, &nod1, &nod2, &nod4);327 }328 gmove(&nod, &nod4);329 gopcode(o, &nod3, Z, &nod4);330 regfree(&nod3);331 gmove(&nod4, &nod);332 regfree(&nod4);333 bitstore(l, &nod, &nod1, &nod2, nn);334 break;336 case OADDR:337 if(nn == Z) {338 nullwarn(l, Z);339 break;340 }341 lcgen(l, nn);342 break;344 case OFUNC:345 l = uncomma(l);346 if(l->complex >= FNX) {347 if(l->op != OIND)348 diag(n, "bad function call");350 regret(&nod, l->left);351 cgen(l->left, &nod);352 regsalloc(&nod1, l->left);353 gopcode(OAS, &nod, Z, &nod1);354 regfree(&nod);356 nod = *n;357 nod.left = &nod2;358 nod2 = *l;359 nod2.left = &nod1;360 nod2.complex = 1;361 cgen(&nod, nn);363 return;364 }365 if(REGARG >= 0)366 o = reg[REGARG];367 gargs(r, &nod, &nod1);368 if(l->addable < INDEXED) {369 reglcgen(&nod, l, Z);370 gopcode(OFUNC, Z, Z, &nod);371 regfree(&nod);372 } else373 gopcode(OFUNC, Z, Z, l);374 if(REGARG >= 0)375 if(o != reg[REGARG])376 reg[REGARG]--;377 if(nn != Z) {378 regret(&nod, n);379 gopcode(OAS, &nod, Z, nn);380 regfree(&nod);381 }382 break;384 case OIND:385 if(nn == Z) {386 nullwarn(l, Z);387 break;388 }389 regialloc(&nod, n, nn);390 r = l;391 while(r->op == OADD)392 r = r->right;393 if(usableoffset(n, nod.xoffset, r)){394 v = r->vconst;395 r->vconst = 0;396 cgen(l, &nod);397 nod.xoffset += v;398 r->vconst = v;399 } else400 cgen(l, &nod);401 regind(&nod, n);402 gopcode(OAS, &nod, Z, nn);403 regfree(&nod);404 break;406 case OEQ:407 case ONE:408 case OLE:409 case OLT:410 case OGE:411 case OGT:412 case OLO:413 case OLS:414 case OHI:415 case OHS:416 if(nn == Z) {417 nullwarn(l, r);418 break;419 }420 boolgen(n, 1, nn);421 break;423 case OANDAND:424 case OOROR:425 boolgen(n, 1, nn);426 if(nn == Z)427 patch(p, pc);428 break;430 case ONOT:431 if(nn == Z) {432 nullwarn(l, Z);433 break;434 }435 boolgen(n, 1, nn);436 break;438 case OCOMMA:439 cgen(l, Z);440 cgen(r, nn);441 break;443 case OCAST:444 if(nn == Z) {445 nullwarn(l, Z);446 break;447 }448 /*449 * convert from types l->n->nn450 */451 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {452 /* both null, gen l->nn */453 cgen(l, nn);454 break;455 }456 if(ewidth[n->type->etype] < ewidth[l->type->etype]){457 if(l->type->etype == TIND && typechlp[n->type->etype])458 warn(n, "conversion of pointer to shorter integer");459 }else if(0){460 if(nocast(n->type, nn->type) || castup(n->type, nn->type)){461 if(typefd[l->type->etype] != typefd[nn->type->etype])462 regalloc(&nod, l, nn);463 else464 regalloc(&nod, nn, nn);465 cgen(l, &nod);466 gmove(&nod, nn);467 regfree(&nod);468 break;469 }470 }471 regalloc(&nod, l, nn);472 cgen(l, &nod);473 regalloc(&nod1, n, &nod);474 if(inrel)475 gmover(&nod, &nod1);476 else477 gopcode(OAS, &nod, Z, &nod1);478 gopcode(OAS, &nod1, Z, nn);479 regfree(&nod1);480 regfree(&nod);481 break;483 case ODOT:484 sugen(l, nodrat, l->type->width);485 if(nn != Z) {486 warn(n, "non-interruptable temporary");487 nod = *nodrat;488 if(!r || r->op != OCONST) {489 diag(n, "DOT and no offset");490 break;491 }492 nod.xoffset += (long)r->vconst;493 nod.type = n->type;494 cgen(&nod, nn);495 }496 break;498 case OCOND:499 bcgen(l, 1);500 p1 = p;501 cgen(r->left, nn);502 gbranch(OGOTO);503 patch(p1, pc);504 p1 = p;505 cgen(r->right, nn);506 patch(p1, pc);507 break;509 case OPOSTINC:510 case OPOSTDEC:511 v = 1;512 if(l->type->etype == TIND)513 v = l->type->link->width;514 if(o == OPOSTDEC)515 v = -v;516 if(l->op == OBIT)517 goto bitinc;518 if(nn == Z)519 goto pre;521 if(l->addable < INDEXED)522 reglcgen(&nod2, l, Z);523 else524 nod2 = *l;526 regalloc(&nod, l, nn);527 gopcode(OAS, &nod2, Z, &nod);528 regalloc(&nod1, l, Z);529 if(typefd[l->type->etype]) {530 regalloc(&nod3, l, Z);531 if(v < 0) {532 gopcode(OAS, nodfconst(-v), Z, &nod3);533 gopcode(OSUB, &nod3, &nod, &nod1);534 } else {535 gopcode(OAS, nodfconst(v), Z, &nod3);536 gopcode(OADD, &nod3, &nod, &nod1);537 }538 regfree(&nod3);539 } else540 gopcode(OADD, nodconst(v), &nod, &nod1);541 gopcode(OAS, &nod1, Z, &nod2);543 regfree(&nod);544 regfree(&nod1);545 if(l->addable < INDEXED)546 regfree(&nod2);547 break;549 case OPREINC:550 case OPREDEC:551 v = 1;552 if(l->type->etype == TIND)553 v = l->type->link->width;554 if(o == OPREDEC)555 v = -v;556 if(l->op == OBIT)557 goto bitinc;559 pre:560 if(l->addable < INDEXED)561 reglcgen(&nod2, l, Z);562 else563 nod2 = *l;565 regalloc(&nod, l, nn);566 gopcode(OAS, &nod2, Z, &nod);567 if(typefd[l->type->etype]) {568 regalloc(&nod3, l, Z);569 if(v < 0) {570 gopcode(OAS, nodfconst(-v), Z, &nod3);571 gopcode(OSUB, &nod3, Z, &nod);572 } else {573 gopcode(OAS, nodfconst(v), Z, &nod3);574 gopcode(OADD, &nod3, Z, &nod);575 }576 regfree(&nod3);577 } else578 gopcode(OADD, nodconst(v), Z, &nod);579 gopcode(OAS, &nod, Z, &nod2);580 if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */581 gins(ANOP, l, Z);583 regfree(&nod);584 if(l->addable < INDEXED)585 regfree(&nod2);586 break;588 bitinc:589 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {590 bitload(l, &nod, &nod1, &nod2, Z);591 gopcode(OAS, &nod, Z, nn);592 gopcode(OADD, nodconst(v), Z, &nod);593 bitstore(l, &nod, &nod1, &nod2, Z);594 break;595 }596 bitload(l, &nod, &nod1, &nod2, nn);597 gopcode(OADD, nodconst(v), Z, &nod);598 bitstore(l, &nod, &nod1, &nod2, nn);599 break;600 }601 cursafe = curs;602 return;603 }605 void606 reglcgen(Node *t, Node *n, Node *nn)607 {608 Node *r;609 long v;611 regialloc(t, n, nn);612 if(n->op == OIND) {613 r = n->left;614 while(r->op == OADD)615 r = r->right;616 if(usableoffset(n, t->xoffset, r)) {617 v = r->vconst;618 r->vconst = 0;619 lcgen(n, t);620 t->xoffset += v;621 r->vconst = v;622 regind(t, n);623 return;624 }625 } else if(n->op == OINDREG) {626 if(usableoffset(n, t->xoffset+n->xoffset, nil)) {627 Type *tt = n->type;628 n->type = types[TIND];629 n->op = OREGISTER;630 v = n->xoffset;631 n->xoffset = 0;632 cgen(n, t);633 t->xoffset += v;634 n->xoffset = v;635 n->op = OINDREG;636 n->type = tt;637 regind(t, n);638 return;639 }640 }641 lcgen(n, t);642 regind(t, n);643 }645 void646 lcgen(Node *n, Node *nn)647 {648 Prog *p1;649 Node nod;651 if(debug['g']) {652 prtree(nn, "lcgen lhs");653 prtree(n, "lcgen");654 }655 if(n == Z || n->type == T)656 return;657 if(nn == Z) {658 nn = &nod;659 regalloc(&nod, n, Z);660 }661 switch(n->op) {662 default:663 if(n->addable < INDEXED) {664 diag(n, "unknown op in lcgen: %O", n->op);665 break;666 }667 nod = *n;668 nod.op = OADDR;669 nod.left = n;670 nod.right = Z;671 nod.type = types[TIND];672 gopcode(OAS, &nod, Z, nn);673 break;675 case OCOMMA:676 cgen(n->left, n->left);677 lcgen(n->right, nn);678 break;680 case OIND:681 cgen(n->left, nn);682 break;684 case OCOND:685 bcgen(n->left, 1);686 p1 = p;687 lcgen(n->right->left, nn);688 gbranch(OGOTO);689 patch(p1, pc);690 p1 = p;691 lcgen(n->right->right, nn);692 patch(p1, pc);693 break;694 }695 }697 void698 bcgen(Node *n, int true)699 {701 if(n->type == T)702 gbranch(OGOTO);703 else704 boolgen(n, true, Z);705 }707 void708 boolgen(Node *n, int true, Node *nn)709 {710 int o;711 Prog *p1, *p2;712 Node *l, *r, nod, nod1;713 long curs;715 if(debug['g']) {716 prtree(nn, "boolgen lhs");717 prtree(n, "boolgen");718 }719 curs = cursafe;720 l = n->left;721 r = n->right;722 switch(n->op) {724 default:725 regalloc(&nod, n, nn);726 cgen(n, &nod);727 o = ONE;728 if(true)729 o = OEQ;730 if(typefd[n->type->etype]) {731 gopcode(true ? o | BTRUE : o, nodfconst(0), &nod, Z);732 } else733 gopcode(o, nodconst(0), &nod, Z);734 regfree(&nod);735 goto com;737 case OCONST:738 o = vconst(n);739 if(!true)740 o = !o;741 gbranch(OGOTO);742 if(o) {743 p1 = p;744 gbranch(OGOTO);745 patch(p1, pc);746 }747 goto com;749 case OCOMMA:750 cgen(l, Z);751 boolgen(r, true, nn);752 break;754 case ONOT:755 boolgen(l, !true, nn);756 break;758 case OCOND:759 bcgen(l, 1);760 p1 = p;761 bcgen(r->left, true);762 p2 = p;763 gbranch(OGOTO);764 patch(p1, pc);765 p1 = p;766 bcgen(r->right, !true);767 patch(p2, pc);768 p2 = p;769 gbranch(OGOTO);770 patch(p1, pc);771 patch(p2, pc);772 goto com;774 case OANDAND:775 if(!true)776 goto caseor;778 caseand:779 bcgen(l, true);780 p1 = p;781 bcgen(r, !true);782 p2 = p;783 patch(p1, pc);784 gbranch(OGOTO);785 patch(p2, pc);786 goto com;788 case OOROR:789 if(!true)790 goto caseand;792 caseor:793 bcgen(l, !true);794 p1 = p;795 bcgen(r, !true);796 p2 = p;797 gbranch(OGOTO);798 patch(p1, pc);799 patch(p2, pc);800 goto com;802 case OEQ:803 case ONE:804 case OLE:805 case OLT:806 case OGE:807 case OGT:808 case OHI:809 case OHS:810 case OLO:811 case OLS:812 o = n->op;813 if(true)814 o = comrel[relindex(o)];815 if(l->complex >= FNX && r->complex >= FNX) {816 regret(&nod, r);817 cgenrel(r, &nod, 1);818 regsalloc(&nod1, r);819 gopcode(OAS, &nod, Z, &nod1);820 regfree(&nod);821 nod = *n;822 nod.right = &nod1;823 boolgen(&nod, true, nn);824 break;825 }826 if(sconst(l)) {827 regalloc(&nod, r, nn);828 cgenrel(r, &nod, 1);829 o = invrel[relindex(o)];830 gopcode(true ? o | BTRUE : o, l, &nod, Z);831 regfree(&nod);832 goto com;833 }834 if(sconst(r)) {835 regalloc(&nod, l, nn);836 cgenrel(l, &nod, 1);837 gopcode(true ? o | BTRUE : o, r, &nod, Z);838 regfree(&nod);839 goto com;840 }841 if(l->complex >= r->complex) {842 regalloc(&nod1, l, nn);843 cgenrel(l, &nod1, 1);844 regalloc(&nod, r, Z);845 cgenrel(r, &nod, 1);846 } else {847 regalloc(&nod, r, nn);848 cgenrel(r, &nod, 1);849 regalloc(&nod1, l, Z);850 cgenrel(l, &nod1, 1);851 }852 gopcode(true ? o | BTRUE : o, &nod, &nod1, Z);853 regfree(&nod);854 regfree(&nod1);856 com:857 if(nn != Z) {858 p1 = p;859 gopcode(OAS, nodconst(1), Z, nn);860 gbranch(OGOTO);861 p2 = p;862 patch(p1, pc);863 gopcode(OAS, nodconst(0), Z, nn);864 patch(p2, pc);865 }866 break;867 }868 cursafe = curs;869 }871 void872 sugen(Node *n, Node *nn, long w)873 {874 Prog *p1;875 Node nod0, nod1, nod2, nod3, nod4, *l, *r;876 Type *t;877 long pc1;878 int i, m, c;880 if(n == Z || n->type == T)881 return;882 if(debug['g']) {883 prtree(nn, "sugen lhs");884 prtree(n, "sugen");885 }886 if(nn == nodrat)887 if(w > nrathole)888 nrathole = w;889 switch(n->op) {890 case OIND:891 if(nn == Z) {892 nullwarn(n->left, Z);893 break;894 }896 default:897 goto copy;899 case OCONST:900 if(n->type && typev[n->type->etype]) {901 if(nn == Z) {902 nullwarn(n->left, Z);903 break;904 }906 t = nn->type;907 nn->type = types[TLONG];908 reglcgen(&nod1, nn, Z);909 nn->type = t;911 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */912 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);913 else914 gopcode(OAS, nod32const(n->vconst), Z, &nod1);915 nod1.xoffset += SZ_LONG;916 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */917 gopcode(OAS, nod32const(n->vconst), Z, &nod1);918 else919 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);921 regfree(&nod1);922 break;923 }924 goto copy;926 case ODOT:927 l = n->left;928 sugen(l, nodrat, l->type->width);929 if(nn != Z) {930 warn(n, "non-interruptable temporary");931 nod1 = *nodrat;932 r = n->right;933 if(!r || r->op != OCONST) {934 diag(n, "DOT and no offset");935 break;936 }937 nod1.xoffset += (long)r->vconst;938 nod1.type = n->type;939 sugen(&nod1, nn, w);940 }941 break;943 case OSTRUCT:944 /*945 * rewrite so lhs has no side effects946 */947 if(nn != Z && side(nn)) {948 nod1 = *n;949 nod1.type = typ(TIND, n->type);950 regret(&nod2, &nod1);951 lcgen(nn, &nod2);952 regsalloc(&nod0, &nod1);953 gopcode(OAS, &nod2, Z, &nod0);954 regfree(&nod2);956 nod1 = *n;957 nod1.op = OIND;958 nod1.left = &nod0;959 nod1.right = Z;960 nod1.complex = 1;962 sugen(n, &nod1, w);963 return;964 }966 r = n->left;967 for(t = n->type->link; t != T; t = t->down) {968 l = r;969 if(r->op == OLIST) {970 l = r->left;971 r = r->right;972 }973 if(nn == Z) {974 cgen(l, nn);975 continue;976 }977 /*978 * hand craft *(&nn + o) = l979 */980 nod0 = znode;981 nod0.op = OAS;982 nod0.type = t;983 nod0.left = &nod1;984 nod0.right = l;986 nod1 = znode;987 nod1.op = OIND;988 nod1.type = t;989 nod1.left = &nod2;991 nod2 = znode;992 nod2.op = OADD;993 nod2.type = typ(TIND, t);994 nod2.left = &nod3;995 nod2.right = &nod4;997 nod3 = znode;998 nod3.op = OADDR;999 nod3.type = nod2.type;1000 nod3.left = nn;1002 nod4 = znode;1003 nod4.op = OCONST;1004 nod4.type = nod2.type;1005 nod4.vconst = t->offset;1007 ccom(&nod0);1008 acom(&nod0);1009 xcom(&nod0);1010 nod0.addable = 0;1012 cgen(&nod0, Z);1013 }1014 break;1016 case OAS:1017 if(nn == Z) {1018 if(n->addable < INDEXED)1019 sugen(n->right, n->left, w);1020 break;1021 }1022 sugen(n->right, nodrat, w);1023 warn(n, "non-interruptable temporary");1024 sugen(nodrat, n->left, w);1025 sugen(nodrat, nn, w);1026 break;1028 case OFUNC:1029 if(nn == Z) {1030 sugen(n, nodrat, w);1031 break;1032 }1033 if(nn->op != OIND) {1034 nn = new1(OADDR, nn, Z);1035 nn->type = types[TIND];1036 nn->addable = 0;1037 } else1038 nn = nn->left;1039 n = new(OFUNC, n->left, new(OLIST, nn, n->right));1040 n->type = types[TVOID];1041 n->left->type = types[TVOID];1042 cgen(n, Z);1043 break;1045 case OCOND:1046 bcgen(n->left, 1);1047 p1 = p;1048 sugen(n->right->left, nn, w);1049 gbranch(OGOTO);1050 patch(p1, pc);1051 p1 = p;1052 sugen(n->right->right, nn, w);1053 patch(p1, pc);1054 break;1056 case OCOMMA:1057 cgen(n->left, Z);1058 sugen(n->right, nn, w);1059 break;1060 }1061 return;1063 copy:1064 if(nn == Z)1065 return;1066 if(n->complex >= FNX && nn->complex >= FNX) {1067 t = nn->type;1068 nn->type = types[TLONG];1069 regialloc(&nod1, nn, Z);1070 lcgen(nn, &nod1);1071 regsalloc(&nod2, nn);1072 nn->type = t;1074 gopcode(OAS, &nod1, Z, &nod2);1075 regfree(&nod1);1077 nod2.type = typ(TIND, t);1079 nod1 = nod2;1080 nod1.op = OIND;1081 nod1.left = &nod2;1082 nod1.right = Z;1083 nod1.complex = 1;1084 nod1.type = t;1086 sugen(n, &nod1, w);1087 return;1088 }1090 /* TO DO: use AMOV/VLONG when possible */1091 if(n->complex > nn->complex) {1092 t = n->type;1093 n->type = types[TLONG];1094 reglcgen(&nod1, n, Z);1095 n->type = t;1097 t = nn->type;1098 nn->type = types[TLONG];1099 reglcgen(&nod2, nn, Z);1100 nn->type = t;1101 } else {1102 t = nn->type;1103 nn->type = types[TLONG];1104 reglcgen(&nod2, nn, Z);1105 nn->type = t;1107 t = n->type;1108 n->type = types[TLONG];1109 reglcgen(&nod1, n, Z);1110 n->type = t;1111 }1113 w /= SZ_LONG;1114 if(w <= 5) {1115 layout(&nod1, &nod2, w, 0, Z);1116 goto out;1117 }1119 /*1120 * minimize space for unrolling loop1121 * 3,4,5 times. (6 or more is never minimum)1122 * if small structure, try 2 also.1123 */1124 c = 0; /* set */1125 m = 100;1126 i = 3;1127 if(w <= 15)1128 i = 2;1129 for(; i<=5; i++)1130 if(i + w%i <= m) {1131 c = i;1132 m = c + w%c;1133 }1135 regalloc(&nod3, ®node, Z);1136 layout(&nod1, &nod2, w%c, w/c, &nod3);1138 pc1 = pc;1139 layout(&nod1, &nod2, c, 0, Z);1141 gopcode(OSUB, nodconst(1L), Z, &nod3);1142 nod1.op = OREGISTER;1143 t = nod1.type;1144 nod1.type = types[TIND];1145 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);1146 nod1.type = t;1147 nod2.op = OREGISTER;1148 t = nod2.type;1149 nod2.type = types[TIND];1150 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);1151 nod2.type = t;1153 gopcode(OGT, nodconst(0), &nod3, Z);1154 patch(p, pc1);1156 regfree(&nod3);1157 out:1158 regfree(&nod1);1159 regfree(&nod2);1160 }1162 void1163 layout(Node *f, Node *t, int c, int cv, Node *cn)1164 {1165 Node t1, t2;1167 while(c > 3) {1168 layout(f, t, 2, 0, Z);1169 c -= 2;1170 }1172 regalloc(&t1, ®node, Z);1173 regalloc(&t2, ®node, Z);1174 if(c > 0) {1175 gopcode(OAS, f, Z, &t1);1176 f->xoffset += SZ_LONG;1177 }1178 if(cn != Z)1179 gopcode(OAS, nodconst(cv), Z, cn);1180 if(c > 1) {1181 gopcode(OAS, f, Z, &t2);1182 f->xoffset += SZ_LONG;1183 }1184 if(c > 0) {1185 gopcode(OAS, &t1, Z, t);1186 t->xoffset += SZ_LONG;1187 }1188 if(c > 2) {1189 gopcode(OAS, f, Z, &t1);1190 f->xoffset += SZ_LONG;1191 }1192 if(c > 1) {1193 gopcode(OAS, &t2, Z, t);1194 t->xoffset += SZ_LONG;1195 }1196 if(c > 2) {1197 gopcode(OAS, &t1, Z, t);1198 t->xoffset += SZ_LONG;1199 }1200 regfree(&t1);1201 regfree(&t2);1202 }1204 /*1205 * if a constant and vlong, doesn't fit as 32-bit signed immediate1206 */1207 int1208 hardconst(Node *n)1209 {1210 return n->op == OCONST && !sconst(n);1211 }1213 /*1214 * casting up to t2 covers an intermediate cast to t11215 */1216 int1217 castup(Type *t1, Type *t2)1218 {1219 int ft;1221 if(!nilcast(t1, t2))1222 return 0;1223 /* known to be small to large */1224 ft = t1->etype;1225 switch(t2->etype){1226 case TINT:1227 case TLONG:1228 return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;1229 case TUINT:1230 case TULONG:1231 return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;1232 case TVLONG:1233 return ft == TLONG || ft == TINT || ft == TSHORT;1234 case TUVLONG:1235 return ft == TULONG || ft == TUINT || ft == TUSHORT;1236 }1237 return 0;1238 }1240 int1241 cond(int op)1242 {1243 switch(op) {1244 case OANDAND:1245 case OOROR:1246 case ONOT:1247 return 1;1249 case OEQ:1250 case ONE:1251 case OLE:1252 case OLT:1253 case OGE:1254 case OGT:1255 case OHI:1256 case OHS:1257 case OLO:1258 case OLS:1259 return 1;1260 }1261 return 0;1262 }