12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558 |
- #include "limbo.h"
- static Node* putinline(Node*);
- static void fpcall(Src*, int, Node*, Node*);
- void
- optabinit(void)
- {
- int i;
- for(i = 0; setisbyteinst[i] >= 0; i++)
- isbyteinst[setisbyteinst[i]] = 1;
- for(i = 0; setisused[i] >= 0; i++)
- isused[setisused[i]] = 1;
- for(i = 0; setsideeffect[i] >= 0; i++)
- sideeffect[setsideeffect[i]] = 1;
- opind[Tbyte] = 1;
- opind[Tint] = 2;
- opind[Tbig] = 3;
- opind[Treal] = 4;
- opind[Tstring] = 5;
- opind[Tfix] = 6;
- opcommute[Oeq] = Oeq;
- opcommute[Oneq] = Oneq;
- opcommute[Olt] = Ogt;
- opcommute[Ogt] = Olt;
- opcommute[Ogeq] = Oleq;
- opcommute[Oleq] = Ogeq;
- opcommute[Oadd] = Oadd;
- opcommute[Omul] = Omul;
- opcommute[Oxor] = Oxor;
- opcommute[Oor] = Oor;
- opcommute[Oand] = Oand;
- oprelinvert[Oeq] = Oneq;
- oprelinvert[Oneq] = Oeq;
- oprelinvert[Olt] = Ogeq;
- oprelinvert[Ogt] = Oleq;
- oprelinvert[Ogeq] = Olt;
- oprelinvert[Oleq] = Ogt;
- isrelop[Oeq] = 1;
- isrelop[Oneq] = 1;
- isrelop[Olt] = 1;
- isrelop[Oleq] = 1;
- isrelop[Ogt] = 1;
- isrelop[Ogeq] = 1;
- isrelop[Oandand] = 1;
- isrelop[Ooror] = 1;
- isrelop[Onot] = 1;
- precasttab[Tstring][Tbyte] = tint;
- precasttab[Tbyte][Tstring] = tint;
- precasttab[Treal][Tbyte] = tint;
- precasttab[Tbyte][Treal] = tint;
- precasttab[Tbig][Tbyte] = tint;
- precasttab[Tbyte][Tbig] = tint;
- precasttab[Tfix][Tbyte] = tint;
- precasttab[Tbyte][Tfix] = tint;
- precasttab[Tbig][Tfix] = treal;
- precasttab[Tfix][Tbig] = treal;
- precasttab[Tstring][Tfix] = treal;
- precasttab[Tfix][Tstring] = treal;
- casttab[Tint][Tint] = IMOVW;
- casttab[Tbig][Tbig] = IMOVL;
- casttab[Treal][Treal] = IMOVF;
- casttab[Tbyte][Tbyte] = IMOVB;
- casttab[Tstring][Tstring] = IMOVP;
- casttab[Tfix][Tfix] = ICVTXX; /* never same type */
- casttab[Tint][Tbyte] = ICVTWB;
- casttab[Tint][Treal] = ICVTWF;
- casttab[Tint][Tstring] = ICVTWC;
- casttab[Tint][Tfix] = ICVTXX;
- casttab[Tbyte][Tint] = ICVTBW;
- casttab[Treal][Tint] = ICVTFW;
- casttab[Tstring][Tint] = ICVTCW;
- casttab[Tfix][Tint] = ICVTXX;
- casttab[Tint][Tbig] = ICVTWL;
- casttab[Treal][Tbig] = ICVTFL;
- casttab[Tstring][Tbig] = ICVTCL;
- casttab[Tbig][Tint] = ICVTLW;
- casttab[Tbig][Treal] = ICVTLF;
- casttab[Tbig][Tstring] = ICVTLC;
- casttab[Treal][Tstring] = ICVTFC;
- casttab[Tstring][Treal] = ICVTCF;
- casttab[Treal][Tfix] = ICVTFX;
- casttab[Tfix][Treal] = ICVTXF;
- casttab[Tstring][Tarray] = ICVTCA;
- casttab[Tarray][Tstring] = ICVTAC;
- /*
- * placeholders; fixed in precasttab
- */
- casttab[Tbyte][Tstring] = 0xff;
- casttab[Tstring][Tbyte] = 0xff;
- casttab[Tbyte][Treal] = 0xff;
- casttab[Treal][Tbyte] = 0xff;
- casttab[Tbyte][Tbig] = 0xff;
- casttab[Tbig][Tbyte] = 0xff;
- casttab[Tfix][Tbyte] = 0xff;
- casttab[Tbyte][Tfix] = 0xff;
- casttab[Tfix][Tbig] = 0xff;
- casttab[Tbig][Tfix] = 0xff;
- casttab[Tfix][Tstring] = 0xff;
- casttab[Tstring][Tfix] = 0xff;
- }
- /*
- * global variable and constant initialization checking
- */
- int
- vcom(Decl *ids)
- {
- Decl *v;
- int ok;
- ok = 1;
- for(v = ids; v != nil; v = v->next)
- ok &= varcom(v);
- for(v = ids; v != nil; v = v->next)
- v->init = simplify(v->init);
- return ok;
- }
- Node*
- simplify(Node *n)
- {
- if(n == nil)
- return nil;
- if(debug['F'])
- print("simplify %n\n", n);
- n = efold(rewrite(n));
- if(debug['F'])
- print("simplified %n\n", n);
- return n;
- }
- static int
- isfix(Node *n)
- {
- if(n->ty->kind == Tint || n->ty->kind == Tfix){
- if(n->op == Ocast)
- return n->left->ty->kind == Tint || n->left->ty->kind == Tfix;
- return 1;
- }
- return 0;
- }
- /*
- * rewrite an expression to make it easiser to compile,
- * or give the correct results
- */
- Node*
- rewrite(Node *n)
- {
- Long v;
- Type *t;
- Decl *d;
- Node *nn, *left, *right;
- if(n == nil)
- return nil;
- left = n->left;
- right = n->right;
- /*
- * rewrites
- */
- switch(n->op){
- case Oname:
- d = n->decl;
- if(d->importid != nil){
- left = mkbin(Omdot, dupn(1, &n->src, d->eimport), mkdeclname(&n->src, d->importid));
- left->ty = n->ty;
- return rewrite(left);
- }
- if((t = n->ty)->kind == Texception){
- if(t->cons)
- fatal("cons in rewrite Oname");
- n = mkbin(Oadd, n, mkconst(&n->src, 2*IBY2WD));
- n = mkunary(Oind, n);
- n->ty = t;
- n->left->ty = n->left->left->ty = tint;
- return rewrite(n);
- }
- break;
- case Odas:
- n->op = Oas;
- return rewrite(n);
- case Oneg:
- n->left = rewrite(left);
- if(n->ty == treal)
- break;
- left = n->left;
- n->right = left;
- n->left = mkconst(&n->src, 0);
- n->left->ty = n->ty;
- n->op = Osub;
- break;
- case Ocomp:
- v = 0;
- v = ~v;
- n->right = mkconst(&n->src, v);
- n->right->ty = n->ty;
- n->left = rewrite(left);
- n->op = Oxor;
- break;
- case Oinc:
- case Odec:
- case Opreinc:
- case Opredec:
- n->left = rewrite(left);
- switch(n->ty->kind){
- case Treal:
- n->right = mkrconst(&n->src, 1.0);
- break;
- case Tint:
- case Tbig:
- case Tbyte:
- case Tfix:
- n->right = mkconst(&n->src, 1);
- n->right->ty = n->ty;
- break;
- default:
- fatal("can't rewrite inc/dec %n", n);
- break;
- }
- if(n->op == Opreinc)
- n->op = Oaddas;
- else if(n->op == Opredec)
- n->op = Osubas;
- break;
- case Oslice:
- if(right->left->op == Onothing)
- right->left = mkconst(&right->left->src, 0);
- n->left = rewrite(left);
- n->right = rewrite(right);
- break;
- case Oindex:
- n->op = Oindx;
- n->left = rewrite(left);
- n->right = rewrite(right);
- n = mkunary(Oind, n);
- n->ty = n->left->ty;
- n->left->ty = tint;
- break;
- case Oload:
- n->right = mkn(Oname, nil, nil);
- n->right->src = n->left->src;
- n->right->decl = n->ty->tof->decl;
- n->right->ty = n->ty;
- n->left = rewrite(left);
- break;
- case Ocast:
- if(left->ty->kind == Texception){
- n = rewrite(left);
- break;
- }
- n->op = Ocast;
- t = precasttab[left->ty->kind][n->ty->kind];
- if(t != nil){
- n->left = mkunary(Ocast, left);
- n->left->ty = t;
- return rewrite(n);
- }
- n->left = rewrite(left);
- break;
- case Oraise:
- if(left->ty == tstring)
- {}
- else if(!left->ty->cons)
- break;
- else if(left->op != Ocall || left->left->ty->kind == Tfn){
- left = mkunary(Ocall, left);
- left->ty = left->left->ty;
- }
- n->left = rewrite(left);
- break;
- case Ocall:
- t = left->ty;
- if(t->kind == Tref)
- t = t->tof;
- if(t->kind == Tfn){
- if(debug['U']) print("call %n\n", left);
- if(left->ty->kind == Tref){ /* call by function reference */
- n->left = mkunary(Oind, left);
- n->left->ty = t;
- return rewrite(n);
- }
- d = nil;
- if(left->op == Oname)
- d = left->decl;
- else if(left->op == Omdot && left->right->op == Odot)
- d = left->right->right->decl;
- else if(left->op == Omdot || left->op == Odot)
- d = left->right->decl;
- else if(left->op != Oind)
- fatal("cannot deal with call %n in rewrite", n);
- if(ispoly(d))
- addfnptrs(d, 0);
- n->left = rewrite(left);
- if(right != nil)
- n->right = rewrite(right);
- if(d != nil && d->caninline == 1)
- n = simplify(putinline(n));
- break;
- }
- switch(n->ty->kind){
- case Tref:
- n = mkunary(Oref, n);
- n->ty = n->left->ty;
- n->left->ty = n->left->ty->tof;
- n->left->left->ty = n->left->ty;
- return rewrite(n);
- case Tadt:
- n->op = Otuple;
- n->right = nil;
- if(n->ty->tags != nil){
- n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));
- if(right != nil){
- nn->right = right;
- nn->src.stop = right->src.stop;
- }
- n->ty = left->right->decl->ty->tof;
- }else
- n->left = right;
- return rewrite(n);
- case Tadtpick:
- n->op = Otuple;
- n->right = nil;
- n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));
- if(right != nil){
- nn->right = right;
- nn->src.stop = right->src.stop;
- }
- n->ty = left->right->decl->ty->tof;
- return rewrite(n);
- case Texception:
- if(!n->ty->cons)
- return n->left;
- if(left->op == Omdot){
- left->right->ty = left->ty;
- left = left->right;
- }
- n->op = Otuple;
- n->right = nil;
- n->left = nn = mkunary(Oseq, left->decl->init);
- nn->right = mkunary(Oseq, mkconst(&n->src, 0));
- nn->right->right = right;
- n->ty = mkexbasetype(n->ty);
- n = mkunary(Oref, n);
- n->ty = internaltype(mktype(&n->src.start, &n->src.stop, Tref, t, nil));
- return rewrite(n);
- default:
- fatal("can't deal with %n in rewrite/Ocall", n);
- break;
- }
- break;
- case Omdot:
- /*
- * what about side effects from left?
- */
- d = right->decl;
- switch(d->store){
- case Dfn:
- n->left = rewrite(left);
- if(right->op == Odot){
- n->right = dupn(1, &left->src, right->right);
- n->right->ty = d->ty;
- }
- break;
- case Dconst:
- case Dtag:
- case Dtype:
- /* handled by fold */
- return n;
- case Dglobal:
- right->op = Oconst;
- right->val = d->offset;
- right->ty = tint;
- n->left = left = mkunary(Oind, left);
- left->ty = tint;
- n->op = Oadd;
- n = mkunary(Oind, n);
- n->ty = n->left->ty;
- n->left->ty = tint;
- n->left = rewrite(n->left);
- return n;
- case Darg:
- return n;
- default:
- fatal("can't deal with %n in rewrite/Omdot", n);
- break;
- }
- break;
- case Odot:
- /*
- * what about side effects from left?
- */
- d = right->decl;
- switch(d->store){
- case Dfn:
- if(right->left != nil){
- n = mkbin(Omdot, dupn(1, &left->src, right->left), right);
- right->left = nil;
- n->ty = d->ty;
- return rewrite(n);
- }
- if(left->ty->kind == Tpoly){
- n = mkbin(Omdot, mkdeclname(&left->src, d->link), mkdeclname(&left->src, d->link->next));
- n->ty = d->ty;
- return rewrite(n);
- }
- n->op = Oname;
- n->decl = d;
- n->right = nil;
- n->left = nil;
- return n;
- case Dconst:
- case Dtag:
- case Dtype:
- /* handled by fold */
- return n;
- }
- if(istuple(left))
- return n; /* handled by fold */
- right->op = Oconst;
- right->val = d->offset;
- right->ty = tint;
- if(left->ty->kind != Tref){
- n->left = mkunary(Oadr, left);
- n->left->ty = tint;
- }
- n->op = Oadd;
- n = mkunary(Oind, n);
- n->ty = n->left->ty;
- n->left->ty = tint;
- n->left = rewrite(n->left);
- return n;
- case Oadr:
- left = rewrite(left);
- n->left = left;
- if(left->op == Oind)
- return left->left;
- break;
- case Otagof:
- if(n->decl == nil){
- n->op = Oind;
- return rewrite(n);
- }
- return n;
- case Omul:
- case Odiv:
- left = n->left = rewrite(left);
- right = n->right = rewrite(right);
- if(n->ty->kind == Tfix && isfix(left) && isfix(right)){
- if(left->op == Ocast && tequal(left->ty, n->ty))
- n->left = left->left;
- if(right->op == Ocast && tequal(right->ty, n->ty))
- n->right = right->left;
- }
- break;
- case Oself:
- if(newfnptr)
- return n;
- if(selfdecl == nil){
- d = selfdecl = mkids(&n->src, enter(strdup(".self"), 5), tany, nil);
- installids(Dglobal, d);
- d->refs++;
- }
- nn = mkn(Oload, nil, nil);
- nn->src = n->src;
- nn->left = mksconst(&n->src, enterstring(strdup("$self"), 5));
- nn->ty = impdecl->ty;
- usetype(nn->ty);
- usetype(nn->ty->tof);
- nn = rewrite(nn);
- nn->op = Oself;
- return nn;
- case Ofnptr:
- if(n->flags == 0){
- /* module */
- if(left == nil)
- left = mkn(Oself, nil, nil);
- return rewrite(left);
- }
- right->flags = n->flags;
- n = right;
- d = n->decl;
- if(n->flags == FNPTR2){
- if(left != nil && left->op != Oname)
- fatal("not Oname for addiface");
- if(left == nil){
- addiface(nil, d);
- if(newfnptr)
- n->flags |= FNPTRN;
- }
- else
- addiface(left->decl, d); /* is this necessary ? */
- n->ty = tint;
- return n;
- }
- if(n->flags == FNPTRA){
- n = mkdeclname(&n->src, d->link);
- n->ty = tany;
- return n;
- }
- if(n->flags == (FNPTRA|FNPTR2)){
- n = mkdeclname(&n->src, d->link->next);
- n->ty = tint;
- return n;
- }
- break;
- case Ochan:
- if(left == nil)
- left = n->left = mkconst(&n->src, 0);
- n->left = rewrite(left);
- break;
- default:
- n->left = rewrite(left);
- n->right = rewrite(right);
- break;
- }
- return n;
- }
- /*
- * label a node with sethi-ullman numbers and addressablity
- * genaddr interprets addable to generate operands,
- * so a change here mandates a change there.
- *
- * addressable:
- * const Rconst $value may also be Roff or Rdesc or Rnoff
- * Asmall(local) Rreg value(FP)
- * Asmall(global) Rmreg value(MP)
- * ind(Rareg) Rreg value(FP)
- * ind(Ramreg) Rmreg value(MP)
- * ind(Rreg) Radr *value(FP)
- * ind(Rmreg) Rmadr *value(MP)
- * ind(Raadr) Radr value(value(FP))
- * ind(Ramadr) Rmadr value(value(MP))
- *
- * almost addressable:
- * adr(Rreg) Rareg
- * adr(Rmreg) Ramreg
- * add(const, Rareg) Rareg
- * add(const, Ramreg) Ramreg
- * add(const, Rreg) Raadr
- * add(const, Rmreg) Ramadr
- * add(const, Raadr) Raadr
- * add(const, Ramadr) Ramadr
- * adr(Radr) Raadr
- * adr(Rmadr) Ramadr
- *
- * strangely addressable:
- * fn Rpc
- * mdot(module,exp) Rmpc
- */
- Node*
- sumark(Node *n)
- {
- Node *left, *right;
- long v;
- if(n == nil)
- return nil;
- n->temps = 0;
- n->addable = Rcant;
- left = n->left;
- right = n->right;
- if(left != nil){
- sumark(left);
- n->temps = left->temps;
- }
- if(right != nil){
- sumark(right);
- if(right->temps == n->temps)
- n->temps++;
- else if(right->temps > n->temps)
- n->temps = right->temps;
- }
- switch(n->op){
- case Oadr:
- switch(left->addable){
- case Rreg:
- n->addable = Rareg;
- break;
- case Rmreg:
- n->addable = Ramreg;
- break;
- case Radr:
- n->addable = Raadr;
- break;
- case Rmadr:
- n->addable = Ramadr;
- break;
- }
- break;
- case Oind:
- switch(left->addable){
- case Rreg:
- n->addable = Radr;
- break;
- case Rmreg:
- n->addable = Rmadr;
- break;
- case Rareg:
- n->addable = Rreg;
- break;
- case Ramreg:
- n->addable = Rmreg;
- break;
- case Raadr:
- n->addable = Radr;
- break;
- case Ramadr:
- n->addable = Rmadr;
- break;
- }
- break;
- case Oname:
- switch(n->decl->store){
- case Darg:
- case Dlocal:
- n->addable = Rreg;
- break;
- case Dglobal:
- n->addable = Rmreg;
- if(LDT && n->decl->ty->kind == Tiface)
- n->addable = Rldt;
- break;
- case Dtype:
- /*
- * check for inferface to load
- */
- if(n->decl->ty->kind == Tmodule)
- n->addable = Rmreg;
- break;
- case Dfn:
- if(n->flags & FNPTR){
- if(n->flags == FNPTR2)
- n->addable = Roff;
- else if(n->flags == (FNPTR2|FNPTRN))
- n->addable = Rnoff;
- }
- else
- n->addable = Rpc;
- break;
- default:
- fatal("cannot deal with %K in Oname in %n", n->decl, n);
- break;
- }
- break;
- case Omdot:
- n->addable = Rmpc;
- break;
- case Oconst:
- switch(n->ty->kind){
- case Tint:
- case Tfix:
- v = n->val;
- if(v < 0 && ((v >> 29) & 0x7) != 7
- || v > 0 && (v >> 29) != 0){
- n->decl = globalconst(n);
- n->addable = Rmreg;
- }else
- n->addable = Rconst;
- break;
- case Tbig:
- n->decl = globalBconst(n);
- n->addable = Rmreg;
- break;
- case Tbyte:
- n->decl = globalbconst(n);
- n->addable = Rmreg;
- break;
- case Treal:
- n->decl = globalfconst(n);
- n->addable = Rmreg;
- break;
- case Tstring:
- n->decl = globalsconst(n);
- n->addable = Rmreg;
- break;
- default:
- fatal("cannot %T const in sumark", n->ty);
- break;
- }
- break;
- case Oadd:
- if(right->addable == Rconst){
- switch(left->addable){
- case Rareg:
- n->addable = Rareg;
- break;
- case Ramreg:
- n->addable = Ramreg;
- break;
- case Rreg:
- case Raadr:
- n->addable = Raadr;
- break;
- case Rmreg:
- case Ramadr:
- n->addable = Ramadr;
- break;
- }
- }
- break;
- }
- if(n->addable < Rcant)
- n->temps = 0;
- else if(n->temps == 0)
- n->temps = 1;
- return n;
- }
- Node*
- mktn(Type *t)
- {
- Node *n;
- n = mkn(Oname, nil, nil);
- usedesc(mktdesc(t));
- n->ty = t;
- n->decl = t->decl;
- if(n->decl == nil)
- fatal("mktn t %T nil decl", t);
- n->addable = Rdesc;
- return n;
- }
- /* does a tuple of the form (a, b, ...) form a contiguous block
- * of memory on the stack when offsets are assigned later
- * - only when (a, b, ...) := rhs and none of the names nil
- * can we guarantee this
- */
- static int
- tupblk0(Node *n, Decl **dd)
- {
- Decl *d;
- int nid;
- switch(n->op){
- case Otuple:
- for(n = n->left; n != nil; n = n->right)
- if(!tupblk0(n->left, dd))
- return 0;
- return 1;
- case Oname:
- if(n->decl == nildecl)
- return 0;
- d = *dd;
- if(d != nil && d->next != n->decl)
- return 0;
- nid = n->decl->nid;
- if(d == nil && nid == 1)
- return 0;
- if(d != nil && nid != 0)
- return 0;
- *dd = n->decl;
- return 1;
- }
- return 0;
- }
- /* could force locals to be next to each other
- * - need to shuffle locals list
- * - later
- */
- static Node*
- tupblk(Node *n)
- {
- Decl *d;
- if(n->op != Otuple)
- return nil;
- d = nil;
- if(!tupblk0(n, &d))
- return nil;
- while(n->op == Otuple)
- n = n->left->left;
- if(n->op != Oname || n->decl->nid == 1)
- fatal("bad tupblk");
- return n;
- }
-
- /* for cprof */
- #define esrc(src, osrc, nto) (src != nil && nto != nil ? src : osrc)
- /*
- * compile an expression with an implicit assignment
- * note: you are not allowed to use to->src
- *
- * need to think carefully about the types used in moves
- * it particular, it would be nice to gen movp rather than movc sometimes.
- */
- Node*
- ecom(Src *src, Node *nto, Node *n)
- {
- Node *left, *right, *tn;
- Node tl, tr, tto, ttn;
- Type *t, *tt;
- Inst *p, *pp;
- int op;
- if(debug['e']){
- print("ecom: %n\n", n);
- if(nto != nil)
- print("ecom to: %n\n", nto);
- }
- if(n->addable < Rcant){
- /*
- * think carefully about the type used here
- */
- if(nto != nil)
- genmove(src, Mas, n->ty, n, nto);
- return nto;
- }
- tl.decl = nil;
- tr.decl = nil;
- tto.decl = nil;
- ttn.decl = nil;
- left = n->left;
- right = n->right;
- op = n->op;
- switch(op){
- default:
- case Oadr:
- fatal("can't %n in ecom", n);
- return nto;
- case Oif:
- p = bcom(left, 1, nil);
- ecom(&right->left->src, nto, right->left);
- if(right->right != nil){
- pp = p;
- p = genrawop(&right->left->src, IJMP, nil, nil, nil);
- patch(pp, nextinst());
- ecom(&right->right->src, nto, right->right);
- }
- patch(p, nextinst());
- break;
- case Ocomma:
- tn = left->left;
- ecom(&left->src, nil, left);
- ecom(&right->src, nto, right);
- tfree(tn);
- break;
- case Oname:
- if(n->addable == Rpc){
- if(nto != nil)
- genmove(src, Mas, n->ty, n, nto);
- return nto;
- }
- fatal("can't %n in ecom", n);
- break;
- case Onothing:
- break;
- case Oused:
- if(nto != nil)
- fatal("superfluous used %n to %n", left, nto);
- talloc(&tto, left->ty, nil);
- ecom(&left->src, &tto, left);
- tfree(&tto);
- break;
- case Oas:
- if(right->ty == tany)
- right->ty = n->ty;
- if(left->op == Oname && left->decl->ty == tany){
- if(nto == nil)
- nto = talloc(&tto, right->ty, nil);
- left = nto;
- nto = nil;
- }
- if(left->op == Oinds){
- indsascom(src, nto, n);
- tfree(&tto);
- break;
- }
- if(left->op == Oslice){
- slicelcom(src, nto, n);
- tfree(&tto);
- break;
- }
- if(left->op == Otuple){
- if(!tupsaliased(right, left)){
- if((tn = tupblk(left)) != nil){
- tn->ty = n->ty;
- ecom(&n->right->src, tn, right);
- if(nto != nil)
- genmove(src, Mas, n->ty, tn, nto);
- tfree(&tto);
- break;
- }
- if((tn = tupblk(right)) != nil){
- tn->ty = n->ty;
- tuplcom(tn, left);
- if(nto != nil)
- genmove(src, Mas, n->ty, tn, nto);
- tfree(&tto);
- break;
- }
- if(nto == nil && right->op == Otuple && left->ty->kind != Tadtpick){
- tuplrcom(right, left);
- tfree(&tto);
- break;
- }
- }
- if(right->addable >= Ralways
- || right->op != Oname
- || tupaliased(right, left)){
- talloc(&tr, n->ty, nil);
- ecom(&n->right->src, &tr, right);
- right = &tr;
- }
- tuplcom(right, n->left);
- if(nto != nil)
- genmove(src, Mas, n->ty, right, nto);
- tfree(&tr);
- tfree(&tto);
- break;
- }
- /*
- * check for left/right aliasing and build right into temporary
- */
- if(right->op == Otuple){
- if(!tupsaliased(left, right) && (tn = tupblk(right)) != nil){
- tn->ty = n->ty;
- right = tn;
- }
- else if(left->op != Oname || tupaliased(left, right))
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- }
- /*
- * think carefully about types here
- */
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- ecom(&n->src, left, right);
- if(nto != nil)
- genmove(src, Mas, nto->ty, left, nto);
- tfree(&tl);
- tfree(&tr);
- tfree(&tto);
- break;
- case Ochan:
- if(left && left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- genchan(src, left, n->ty->tof, nto);
- tfree(&tl);
- break;
- case Oinds:
- if(right->addable < Ralways){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else if(left->temps <= right->temps){
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nil);
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- }
- genop(&n->src, op, left, right, nto);
- tfree(&tl);
- tfree(&tr);
- break;
- case Osnd:
- if(right->addable < Rcant){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- }else if(left->temps < right->temps){
- right = eacom(right, &tr, nto);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nto);
- right = eacom(right, &tr, nil);
- }
- p = genrawop(&n->src, ISEND, right, nil, left);
- p->m.offset = n->ty->size; /* for optimizer */
- if(nto != nil)
- genmove(src, Mas, right->ty, right, nto);
- tfree(&tl);
- tfree(&tr);
- break;
- case Orcv:
- if(nto == nil){
- ecom(&n->src, talloc(&tto, n->ty, nil), n);
- tfree(&tto);
- return nil;
- }
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- if(left->ty->kind == Tchan){
- p = genrawop(src, IRECV, left, nil, nto);
- p->m.offset = n->ty->size; /* for optimizer */
- }else{
- recvacom(src, nto, n);
- }
- tfree(&tl);
- break;
- case Ocons:
- /*
- * another temp which can go with analysis
- */
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- if(!sameaddr(right, nto)){
- ecom(&right->src, talloc(&tto, n->ty, nto), right);
- genmove(src, Mcons, left->ty, left, &tto);
- if(!sameaddr(&tto, nto))
- genmove(src, Mas, nto->ty, &tto, nto);
- }else
- genmove(src, Mcons, left->ty, left, nto);
- tfree(&tl);
- tfree(&tto);
- break;
- case Ohd:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- genmove(src, Mhd, nto->ty, left, nto);
- tfree(&tl);
- break;
- case Otl:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- genmove(src, Mtl, left->ty, left, nto);
- tfree(&tl);
- break;
- case Otuple:
- if((tn = tupblk(n)) != nil){
- tn->ty = n->ty;
- genmove(src, Mas, n->ty, tn, nto);
- break;
- }
- tupcom(nto, n);
- break;
- case Oadd:
- case Osub:
- case Omul:
- case Odiv:
- case Omod:
- case Oand:
- case Oor:
- case Oxor:
- case Olsh:
- case Orsh:
- case Oexp:
- /*
- * check for 2 operand forms
- */
- if(sameaddr(nto, left)){
- if(right->addable >= Rcant)
- right = eacom(right, &tr, nto);
- genop(src, op, right, nil, nto);
- tfree(&tr);
- break;
- }
- if(opcommute[op] && sameaddr(nto, right) && n->ty != tstring){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- genop(src, opcommute[op], left, nil, nto);
- tfree(&tl);
- break;
- }
- if(right->addable < left->addable
- && opcommute[op]
- && n->ty != tstring){
- op = opcommute[op];
- left = right;
- right = n->left;
- }
- if(left->addable < Ralways){
- if(right->addable >= Rcant)
- right = eacom(right, &tr, nto);
- }else if(right->temps <= left->temps){
- left = ecom(&left->src, talloc(&tl, left->ty, nto), left);
- if(right->addable >= Rcant)
- right = eacom(right, &tr, nil);
- }else{
- right = eacom(right, &tr, nto);
- left = ecom(&left->src, talloc(&tl, left->ty, nil), left);
- }
- /*
- * check for 2 operand forms
- */
- if(sameaddr(nto, left))
- genop(src, op, right, nil, nto);
- else if(opcommute[op] && sameaddr(nto, right) && n->ty != tstring)
- genop(src, opcommute[op], left, nil, nto);
- else
- genop(src, op, right, left, nto);
- tfree(&tl);
- tfree(&tr);
- break;
- case Oaddas:
- case Osubas:
- case Omulas:
- case Odivas:
- case Omodas:
- case Oexpas:
- case Oandas:
- case Ooras:
- case Oxoras:
- case Olshas:
- case Orshas:
- if(left->op == Oinds){
- indsascom(src, nto, n);
- break;
- }
- if(right->addable < Rcant){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- }else if(left->temps < right->temps){
- right = eacom(right, &tr, nto);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nto);
- right = eacom(right, &tr, nil);
- }
- genop(&n->src, op, right, nil, left);
- if(nto != nil)
- genmove(src, Mas, left->ty, left, nto);
- tfree(&tl);
- tfree(&tr);
- break;
- case Olen:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- op = -1;
- t = left->ty;
- if(t == tstring)
- op = ILENC;
- else if(t->kind == Tarray)
- op = ILENA;
- else if(t->kind == Tlist)
- op = ILENL;
- else
- fatal("can't len %n", n);
- genrawop(src, op, left, nil, nto);
- tfree(&tl);
- break;
- case Oneg:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- genop(&n->src, op, left, nil, nto);
- tfree(&tl);
- break;
- case Oinc:
- case Odec:
- if(left->op == Oinds){
- indsascom(src, nto, n);
- break;
- }
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- if(nto != nil)
- genmove(src, Mas, left->ty, left, nto);
- if(right->addable >= Rcant)
- fatal("inc/dec amount not addressable: %n", n);
- genop(&n->src, op, right, nil, left);
- tfree(&tl);
- break;
- case Ospawn:
- if(left->left->op == Oind)
- fpcall(&n->src, op, left, nto);
- else
- callcom(&n->src, op, left, nto);
- break;
- case Oraise:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- genrawop(&n->src, IRAISE, left, nil, nil);
- tfree(&tl);
- break;
- case Ocall:
- if(left->op == Oind)
- fpcall(esrc(src, &n->src, nto), op, n, nto);
- else
- callcom(esrc(src, &n->src, nto), op, n, nto);
- break;
- case Oref:
- t = left->ty;
- if(left->op == Oname && left->decl->store == Dfn || left->op == Omdot && left->right->op == Oname && left->right->decl->store == Dfn){ /* create a function reference */
- Decl *d;
- Node *mod, *ind;
- d = left->decl;
- if(left->op == Omdot){
- d = left->right->decl;
- mod = left->left;
- }
- else if(d->eimport != nil)
- mod = d->eimport;
- else{
- mod = rewrite(mkn(Oself, nil, nil));
- addiface(nil, d);
- }
- sumark(mod);
- talloc(&tto, n->ty, nto);
- genrawop(src, INEW, mktn(usetype(tfnptr)), nil, &tto);
- tr.src = *src;
- tr.op = Oind;
- tr.left = &tto;
- tr.right = nil;
- tr.ty = tany;
- sumark(&tr);
- ecom(src, &tr, mod);
- ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, &tto), mkconst(src, IBY2WD)));
- ind->ty = ind->left->ty = ind->left->right->ty = tint;
- tr.op = Oas;
- tr.left = ind;
- tr.right = mkdeclname(src, d);
- tr.ty = tr.right->ty = tint;
- sumark(&tr);
- tr.right->addable = mod->op == Oself && newfnptr ? Rnoff : Roff;
- ecom(src, nil, &tr);
- if(!sameaddr(&tto, nto))
- genmove(src, Mas, n->ty, &tto, nto);
- tfree(&tto);
- break;
- }
- if(left->op == Oname && left->decl->store == Dtype){
- genrawop(src, INEW, mktn(t), nil, nto);
- break;
- }
- if(t->kind == Tadt && t->tags != nil){
- pickdupcom(src, nto, left);
- break;
- }
- tt = t;
- if(left->op == Oconst && left->decl->store == Dtag)
- t = left->decl->ty->tof;
- /*
- * could eliminate temp if to does not occur
- * in tuple initializer
- */
- talloc(&tto, n->ty, nto);
- genrawop(src, INEW, mktn(t), nil, &tto);
- tr.op = Oind;
- tr.left = &tto;
- tr.right = nil;
- tr.ty = tt;
- sumark(&tr);
- ecom(src, &tr, left);
- if(!sameaddr(&tto, nto))
- genmove(src, Mas, n->ty, &tto, nto);
- tfree(&tto);
- break;
- case Oload:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- talloc(&tr, tint, nil);
- if(LDT)
- genrawop(src, ILOAD, left, right, nto);
- else{
- genrawop(src, ILEA, right, nil, &tr);
- genrawop(src, ILOAD, left, &tr, nto);
- }
- tfree(&tl);
- tfree(&tr);
- break;
- case Ocast:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- t = left->ty;
- if(t->kind == Tfix || n->ty->kind == Tfix){
- op = casttab[t->kind][n->ty->kind];
- if(op == ICVTXX)
- genfixcastop(src, op, left, nto);
- else{
- tn = sumark(mkrconst(src, scale2(t, n->ty)));
- genrawop(src, op, left, tn, nto);
- }
- }
- else
- genrawop(src, casttab[t->kind][n->ty->kind], left, nil, nto);
- tfree(&tl);
- break;
- case Oarray:
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- genrawop(esrc(src, &left->src, nto), arrayz ? INEWAZ : INEWA, left, mktn(n->ty->tof), nto);
- if(right != nil)
- arraycom(nto, right);
- tfree(&tl);
- break;
- case Oslice:
- tn = right->right;
- right = right->left;
- /*
- * make the left node of the slice directly addressable
- * therefore, if it's len is taken (via tn),
- * left's tree won't be rewritten
- */
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- if(tn->op == Onothing){
- tn = mkn(Olen, left, nil);
- tn->src = *src;
- tn->ty = tint;
- sumark(tn);
- }
- if(tn->addable < Ralways){
- if(right->addable >= Rcant)
- right = eacom(right, &tr, nil);
- }else if(right->temps <= tn->temps){
- tn = ecom(&tn->src, talloc(&ttn, tn->ty, nil), tn);
- if(right->addable >= Rcant)
- right = eacom(right, &tr, nil);
- }else{
- right = eacom(right, &tr, nil);
- tn = ecom(&tn->src, talloc(&ttn, tn->ty, nil), tn);
- }
- op = ISLICEA;
- if(nto->ty == tstring)
- op = ISLICEC;
- /*
- * overwrite the destination last,
- * since it might be used in computing the slice bounds
- */
- if(!sameaddr(left, nto))
- ecom(&left->src, nto, left);
- genrawop(src, op, right, tn, nto);
- tfree(&tl);
- tfree(&tr);
- tfree(&ttn);
- break;
- case Oindx:
- if(right->addable < Rcant){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- }else if(left->temps < right->temps){
- right = eacom(right, &tr, nto);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nto);
- right = eacom(right, &tr, nil);
- }
- if(nto->addable >= Ralways)
- nto = ecom(src, talloc(&tto, nto->ty, nil), nto);
- op = IINDX;
- switch(left->ty->tof->size){
- case IBY2LG:
- op = IINDL;
- if(left->ty->tof == treal)
- op = IINDF;
- break;
- case IBY2WD:
- op = IINDW;
- break;
- case 1:
- op = IINDB;
- break;
- }
- genrawop(src, op, left, nto, right);
- // array[] of {....} [index] frees array too early (before index value used)
- // function(...) [index] frees array too early (before index value used)
- if(tl.decl != nil)
- tfreelater(&tl);
- else
- tfree(&tl);
- tfree(&tr);
- tfree(&tto);
- break;
- case Oind:
- n = eacom(n, &tl, nto);
- genmove(src, Mas, n->ty, n, nto);
- tfree(&tl);
- break;
- case Onot:
- case Oandand:
- case Ooror:
- case Oeq:
- case Oneq:
- case Olt:
- case Oleq:
- case Ogt:
- case Ogeq:
- p = bcom(n, 1, nil);
- genmove(src, Mas, tint, sumark(mkconst(src, 1)), nto);
- pp = genrawop(src, IJMP, nil, nil, nil);
- patch(p, nextinst());
- genmove(src, Mas, tint, sumark(mkconst(src, 0)), nto);
- patch(pp, nextinst());
- break;
- case Oself:
- if(newfnptr){
- if(nto != nil)
- genrawop(src, ISELF, nil, nil, nto);
- break;
- }
- tn = sumark(mkdeclname(src, selfdecl));
- p = genbra(src, Oneq, tn, sumark(mkdeclname(src, nildecl)));
- n->op = Oload;
- ecom(src, tn, n);
- patch(p, nextinst());
- genmove(src, Mas, n->ty, tn, nto);
- break;
- }
- return nto;
- }
- /*
- * compile exp n to yield an addressable expression
- * use reg to build a temporary; if t is a temp, it is usable
- * if dangle leaves the address dangling, generate into a temporary
- * this should only happen with arrays
- *
- * note that 0adr's are strange as they are only used
- * for calculating the addresses of fields within adt's.
- * therefore an Oind is the parent or grandparent of the Oadr,
- * and we pick off all of the cases where Oadr's argument is not
- * addressable by looking from the Oind.
- */
- Node*
- eacom(Node *n, Node *reg, Node *t)
- {
- Node *left, *tn;
- if(n->op == Ocomma){
- tn = n->left->left;
- ecom(&n->left->src, nil, n->left);
- n = eacom(n->right, reg, t);
- tfree(tn);
- return n;
- }
- if(debug['e'] || debug['E'])
- print("eacom: %n\n", n);
- left = n->left;
- if(n->op != Oind){
- ecom(&n->src, talloc(reg, n->ty, t), n);
- reg->src = n->src;
- return reg;
- }
-
- if(left->op == Oadd && left->right->op == Oconst){
- if(left->left->op == Oadr){
- left->left->left = eacom(left->left->left, reg, t);
- sumark(n);
- if(n->addable >= Rcant)
- fatal("eacom can't make node addressable: %n", n);
- return n;
- }
- talloc(reg, left->left->ty, t);
- ecom(&left->left->src, reg, left->left);
- left->left->decl = reg->decl;
- left->left->addable = Rreg;
- left->left = reg;
- left->addable = Raadr;
- n->addable = Radr;
- }else if(left->op == Oadr){
- talloc(reg, left->left->ty, t);
- ecom(&left->left->src, reg, left->left);
- /*
- * sleaze: treat the temp as the type of the field, not the enclosing structure
- */
- reg->ty = n->ty;
- reg->src = n->src;
- return reg;
- }else{
- talloc(reg, left->ty, t);
- ecom(&left->src, reg, left);
- n->left = reg;
- n->addable = Radr;
- }
- return n;
- }
- /*
- * compile an assignment to an array slice
- */
- Node*
- slicelcom(Src *src, Node *nto, Node *n)
- {
- Node *left, *right, *v;
- Node tl, tr, tv, tu;
- tl.decl = nil;
- tr.decl = nil;
- tv.decl = nil;
- tu.decl = nil;
- left = n->left->left;
- right = n->left->right->left;
- v = n->right;
- if(right->addable < Ralways){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- }else if(left->temps <= right->temps){
- right = ecom(&right->src, talloc(&tr, right->ty, nto), right);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nil); /* dangle on right and v */
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- }
- switch(n->op){
- case Oas:
- if(v->addable >= Rcant)
- v = eacom(v, &tv, nil);
- break;
- }
- genrawop(&n->src, ISLICELA, v, right, left);
- if(nto != nil)
- genmove(src, Mas, n->ty, left, nto);
- tfree(&tl);
- tfree(&tv);
- tfree(&tr);
- tfree(&tu);
- return nto;
- }
- /*
- * compile an assignment to a string location
- */
- Node*
- indsascom(Src *src, Node *nto, Node *n)
- {
- Node *left, *right, *u, *v;
- Node tl, tr, tv, tu;
- tl.decl = nil;
- tr.decl = nil;
- tv.decl = nil;
- tu.decl = nil;
- left = n->left->left;
- right = n->left->right;
- v = n->right;
- if(right->addable < Ralways){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nto);
- }else if(left->temps <= right->temps){
- right = ecom(&right->src, talloc(&tr, right->ty, nto), right);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nil); /* dangle on right and v */
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- }
- switch(n->op){
- case Oas:
- if(v->addable >= Rcant)
- v = eacom(v, &tv, nil);
- break;
- case Oinc:
- case Odec:
- if(v->addable >= Rcant)
- fatal("inc/dec amount not addable");
- u = talloc(&tu, tint, nil);
- genop(&n->left->src, Oinds, left, right, u);
- if(nto != nil)
- genmove(src, Mas, n->ty, u, nto);
- nto = nil;
- genop(&n->src, n->op, v, nil, u);
- v = u;
- break;
- case Oaddas:
- case Osubas:
- case Omulas:
- case Odivas:
- case Omodas:
- case Oexpas:
- case Oandas:
- case Ooras:
- case Oxoras:
- case Olshas:
- case Orshas:
- if(v->addable >= Rcant)
- v = eacom(v, &tv, nil);
- u = talloc(&tu, tint, nil);
- genop(&n->left->src, Oinds, left, right, u);
- genop(&n->src, n->op, v, nil, u);
- v = u;
- break;
- }
- genrawop(&n->src, IINSC, v, right, left);
- tfree(&tl);
- tfree(&tv);
- tfree(&tr);
- tfree(&tu);
- if(nto != nil)
- genmove(src, Mas, n->ty, v, nto);
- return nto;
- }
- void
- callcom(Src *src, int op, Node *n, Node *ret)
- {
- Node frame, tadd, toff, pass, *a, *mod, *ind, *nfn, *args, tmod, tind, *tn;
- Inst *in,*p;
- Decl *d, *callee;
- long off;
- int iop;
- args = n->right;
- nfn = n->left;
- switch(nfn->op){
- case Odot:
- callee = nfn->right->decl;
- nfn->addable = Rpc;
- break;
- case Omdot:
- callee = nfn->right->decl;
- break;
- case Oname:
- callee = nfn->decl;
- break;
- default:
- callee = nil;
- fatal("bad call op in callcom");
- }
- if(nfn->addable != Rpc && nfn->addable != Rmpc)
- fatal("can't gen call addresses");
- if(nfn->ty->tof != tnone && ret == nil){
- ecom(src, talloc(&tmod, nfn->ty->tof, nil), n);
- tfree(&tmod);
- return;
- }
- if(ispoly(callee))
- addfnptrs(callee, 0);
- if(nfn->ty->varargs){
- nfn->decl = dupdecl(nfn->right->decl);
- nfn->decl->desc = gendesc(nfn->right->decl, idoffsets(nfn->ty->ids, MaxTemp, MaxAlign), nfn->ty->ids);
- }
- talloc(&frame, tint, nil);
- mod = nfn->left;
- ind = nfn->right;
- tmod.decl = tind.decl = nil;
- if(nfn->addable == Rmpc){
- if(mod->addable >= Rcant)
- mod = eacom(mod, &tmod, nil); /* dangle always */
- if(ind->op != Oname && ind->addable >= Ralways){
- talloc(&tind, ind->ty, nil);
- ecom(&ind->src, &tind, ind);
- ind = &tind;
- }
- else if(ind->decl != nil && ind->decl->store != Darg)
- ind->addable = Roff;
- }
- /*
- * stop nested uncalled frames
- * otherwise exception handling very complicated
- */
- for(a = args; a != nil; a = a->right){
- if(hascall(a->left)){
- tn = mkn(0, nil, nil);
- talloc(tn, a->left->ty, nil);
- ecom(&a->left->src, tn, a->left);
- a->left = tn;
- tn->flags |= TEMP;
- }
- }
- /*
- * allocate the frame
- */
- if(nfn->addable == Rmpc && !nfn->ty->varargs){
- genrawop(src, IMFRAME, mod, ind, &frame);
- }else if(nfn->op == Odot){
- genrawop(src, IFRAME, nfn->left, nil, &frame);
- }else{
- in = genrawop(src, IFRAME, nil, nil, &frame);
- in->sm = Adesc;
- in->s.decl = nfn->decl;
- }
- /*
- * build a fake node for the argument area
- */
- toff = znode;
- tadd = znode;
- pass = znode;
- toff.op = Oconst;
- toff.addable = Rconst;
- toff.ty = tint;
- tadd.op = Oadd;
- tadd.addable = Raadr;
- tadd.left = &frame;
- tadd.right = &toff;
- tadd.ty = tint;
- pass.op = Oind;
- pass.addable = Radr;
- pass.left = &tadd;
- /*
- * compile all the args
- */
- d = nfn->ty->ids;
- off = 0;
- for(a = args; a != nil; a = a->right){
- off = d->offset;
- toff.val = off;
- if(d->ty->kind == Tpoly)
- pass.ty = a->left->ty;
- else
- pass.ty = d->ty;
- ecom(&a->left->src, &pass, a->left);
- d = d->next;
- if(a->left->flags & TEMP)
- tfree(a->left);
- }
- if(off > maxstack)
- maxstack = off;
- /*
- * pass return value
- */
- if(ret != nil){
- toff.val = REGRET*IBY2WD;
- pass.ty = nfn->ty->tof;
- p = genrawop(src, ILEA, ret, nil, &pass);
- p->m.offset = ret->ty->size; /* for optimizer */
- }
- /*
- * call it
- */
- if(nfn->addable == Rmpc){
- iop = IMCALL;
- if(op == Ospawn)
- iop = IMSPAWN;
- genrawop(src, iop, &frame, ind, mod);
- tfree(&tmod);
- tfree(&tind);
- }else if(nfn->op == Odot){
- iop = ICALL;
- if(op == Ospawn)
- iop = ISPAWN;
- genrawop(src, iop, &frame, nil, nfn->right);
- }else{
- iop = ICALL;
- if(op == Ospawn)
- iop = ISPAWN;
- in = genrawop(src, iop, &frame, nil, nil);
- in->d.decl = nfn->decl;
- in->dm = Apc;
- }
- tfree(&frame);
- }
- /*
- * initialization code for arrays
- * a must be addressable (< Rcant)
- */
- void
- arraycom(Node *a, Node *elems)
- {
- Node tindex, fake, tmp, ri, *e, *n, *q, *body, *wild;
- Inst *top, *out;
- /* Case *c; */
- if(debug['A'])
- print("arraycom: %n %n\n", a, elems);
- /* c = elems->ty->cse; */
- /* don't use c->wild in case we've been inlined */
- wild = nil;
- for(e = elems; e != nil; e = e->right)
- for(q = e->left->left; q != nil; q = q->right)
- if(q->left->op == Owild)
- wild = e->left;
- if(wild != nil)
- arraydefault(a, wild->right);
- tindex = znode;
- fake = znode;
- talloc(&tmp, tint, nil);
- tindex.op = Oindx;
- tindex.addable = Rcant;
- tindex.left = a;
- tindex.right = nil;
- tindex.ty = tint;
- fake.op = Oind;
- fake.addable = Radr;
- fake.left = &tmp;
- fake.ty = a->ty->tof;
- for(e = elems; e != nil; e = e->right){
- /*
- * just duplicate the initializer for Oor
- */
- for(q = e->left->left; q != nil; q = q->right){
- if(q->left->op == Owild)
- continue;
-
- body = e->left->right;
- if(q->right != nil)
- body = dupn(0, &nosrc, body);
- top = nil;
- out = nil;
- ri.decl = nil;
- if(q->left->op == Orange){
- /*
- * for(i := q.left.left; i <= q.left.right; i++)
- */
- talloc(&ri, tint, nil);
- ri.src = q->left->src;
- ecom(&q->left->src, &ri, q->left->left);
-
- /* i <= q.left.right; */
- n = mkn(Oleq, &ri, q->left->right);
- n->src = q->left->src;
- n->ty = tint;
- top = nextinst();
- out = bcom(n, 1, nil);
-
- tindex.right = &ri;
- }else{
- tindex.right = q->left;
- }
-
- tindex.addable = Rcant;
- tindex.src = q->left->src;
- ecom(&tindex.src, &tmp, &tindex);
-
- ecom(&body->src, &fake, body);
-
- if(q->left->op == Orange){
- /* i++ */
- n = mkbin(Oinc, &ri, sumark(mkconst(&ri.src, 1)));
- n->ty = tint;
- n->addable = Rcant;
- ecom(&n->src, nil, n);
-
- /* jump to test */
- patch(genrawop(&q->left->src, IJMP, nil, nil, nil), top);
- patch(out, nextinst());
- tfree(&ri);
- }
- }
- }
- tfree(&tmp);
- }
- /*
- * default initialization code for arrays.
- * compiles to
- * n = len a;
- * while(n){
- * n--;
- * a[n] = elem;
- * }
- */
- void
- arraydefault(Node *a, Node *elem)
- {
- Inst *out, *top;
- Node n, e, *t;
- if(debug['A'])
- print("arraydefault: %n %n\n", a, elem);
- t = mkn(Olen, a, nil);
- t->src = elem->src;
- t->ty = tint;
- t->addable = Rcant;
- talloc(&n, tint, nil);
- n.src = elem->src;
- ecom(&t->src, &n, t);
- top = nextinst();
- out = bcom(&n, 1, nil);
- t = mkbin(Odec, &n, sumark(mkconst(&elem->src, 1)));
- t->ty = tint;
- t->addable = Rcant;
- ecom(&t->src, nil, t);
- e.decl = nil;
- if(elem->addable >= Rcant)
- elem = eacom(elem, &e, nil);
- t = mkn(Oindx, a, &n);
- t->src = elem->src;
- t = mkbin(Oas, mkunary(Oind, t), elem);
- t->ty = elem->ty;
- t->left->ty = elem->ty;
- t->left->left->ty = tint;
- sumark(t);
- ecom(&t->src, nil, t);
- patch(genrawop(&t->src, IJMP, nil, nil, nil), top);
- tfree(&n);
- tfree(&e);
- patch(out, nextinst());
- }
- void
- tupcom(Node *nto, Node *n)
- {
- Node tadr, tadd, toff, fake, *e;
- Decl *d;
- if(debug['Y'])
- print("tupcom %n\nto %n\n", n, nto);
- /*
- * build a fake node for the tuple
- */
- toff = znode;
- tadd = znode;
- fake = znode;
- tadr = znode;
- toff.op = Oconst;
- toff.ty = tint;
- tadr.op = Oadr;
- tadr.left = nto;
- tadr.ty = tint;
- tadd.op = Oadd;
- tadd.left = &tadr;
- tadd.right = &toff;
- tadd.ty = tint;
- fake.op = Oind;
- fake.left = &tadd;
- sumark(&fake);
- if(fake.addable >= Rcant)
- fatal("tupcom: bad value exp %n", &fake);
- /*
- * compile all the exps
- */
- d = n->ty->ids;
- for(e = n->left; e != nil; e = e->right){
- toff.val = d->offset;
- fake.ty = d->ty;
- ecom(&e->left->src, &fake, e->left);
- d = d->next;
- }
- }
- void
- tuplcom(Node *n, Node *nto)
- {
- Node tadr, tadd, toff, fake, tas, *e, *as;
- Decl *d;
- if(debug['Y'])
- print("tuplcom %n\nto %n\n", n, nto);
- /*
- * build a fake node for the tuple
- */
- toff = znode;
- tadd = znode;
- fake = znode;
- tadr = znode;
- toff.op = Oconst;
- toff.ty = tint;
- tadr.op = Oadr;
- tadr.left = n;
- tadr.ty = tint;
- tadd.op = Oadd;
- tadd.left = &tadr;
- tadd.right = &toff;
- tadd.ty = tint;
- fake.op = Oind;
- fake.left = &tadd;
- sumark(&fake);
- if(fake.addable >= Rcant)
- fatal("tuplcom: bad value exp for %n", &fake);
- /*
- * compile all the exps
- */
- d = nto->ty->ids;
- if(nto->ty->kind == Tadtpick)
- d = nto->ty->tof->ids->next;
- for(e = nto->left; e != nil; e = e->right){
- as = e->left;
- if(as->op != Oname || as->decl != nildecl){
- toff.val = d->offset;
- fake.ty = d->ty;
- fake.src = as->src;
- if(as->addable < Rcant)
- genmove(&as->src, Mas, d->ty, &fake, as);
- else{
- tas.op = Oas;
- tas.ty = d->ty;
- tas.src = as->src;
- tas.left = as;
- tas.right = &fake;
- tas.addable = Rcant;
- ecom(&tas.src, nil, &tas);
- }
- }
- d = d->next;
- }
- }
- void
- tuplrcom(Node *n, Node *nto)
- {
- Node *s, *d, tas;
- Decl *de;
- de = nto->ty->ids;
- for(s = n->left, d = nto->left; s != nil && d != nil; s = s->right, d = d->right){
- if(d->left->op != Oname || d->left->decl != nildecl){
- tas.op = Oas;
- tas.ty = de->ty;
- tas.src = s->left->src;
- tas.left = d->left;
- tas.right = s->left;
- sumark(&tas);
- ecom(&tas.src, nil, &tas);
- }
- de = de->next;
- }
- if(s != nil || d != nil)
- fatal("tuplrcom");
- }
- /*
- * boolean compiler
- * fall through when condition == true
- */
- Inst*
- bcom(Node *n, int iftrue, Inst *b)
- {
- Inst *bb;
- Node tl, tr, *t, *left, *right, *tn;
- int op;
- if(n->op == Ocomma){
- tn = n->left->left;
- ecom(&n->left->src, nil, n->left);
- bb = bcom(n->right, iftrue, b);
- tfree(tn);
- return bb;
- }
- if(debug['b'])
- print("bcom %n %d\n", n, iftrue);
- left = n->left;
- right = n->right;
- op = n->op;
-
- switch(op){
- case Onothing:
- return b;
- case Onot:
- return bcom(n->left, !iftrue, b);
- case Oandand:
- if(!iftrue)
- return oror(n, iftrue, b);
- return andand(n, iftrue, b);
- case Ooror:
- if(!iftrue)
- return andand(n, iftrue, b);
- return oror(n, iftrue, b);
- case Ogt:
- case Ogeq:
- case Oneq:
- case Oeq:
- case Olt:
- case Oleq:
- break;
- default:
- if(n->ty->kind == Tint){
- right = mkconst(&n->src, 0);
- right->addable = Rconst;
- left = n;
- op = Oneq;
- break;
- }
- fatal("can't bcom %n", n);
- return b;
- }
- if(iftrue)
- op = oprelinvert[op];
- if(left->addable < right->addable){
- t = left;
- left = right;
- right = t;
- op = opcommute[op];
- }
- tl.decl = nil;
- tr.decl = nil;
- if(right->addable < Ralways){
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else if(left->temps <= right->temps){
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- if(left->addable >= Rcant)
- left = eacom(left, &tl, nil);
- }else{
- left = eacom(left, &tl, nil);
- right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
- }
- bb = genbra(&n->src, op, left, right);
- bb->branch = b;
- tfree(&tl);
- tfree(&tr);
- return bb;
- }
- Inst*
- andand(Node *n, int iftrue, Inst *b)
- {
- if(debug['b'])
- print("andand %n\n", n);
- b = bcom(n->left, iftrue, b);
- b = bcom(n->right, iftrue, b);
- return b;
- }
- Inst*
- oror(Node *n, int iftrue, Inst *b)
- {
- Inst *bb;
- if(debug['b'])
- print("oror %n\n", n);
- bb = bcom(n->left, !iftrue, nil);
- b = bcom(n->right, iftrue, b);
- patch(bb, nextinst());
- return b;
- }
- /*
- * generate code for a recva expression
- * this is just a hacked up small alt
- */
- void
- recvacom(Src *src, Node *nto, Node *n)
- {
- Label *labs;
- Case *c;
- Node which, tab, off, add, adr, slot, *left;
- Type *talt;
- Inst *p;
- left = n->left;
- labs = allocmem(1 * sizeof *labs);
- labs[0].isptr = left->addable >= Rcant;
- c = allocmem(sizeof *c);
- c->nlab = 1;
- c->labs = labs;
- talt = mktalt(c);
- talloc(&which, tint, nil);
- talloc(&tab, talt, nil);
- /*
- * build the node for the address of each channel,
- * the values to send, and the storage fro values received
- */
- off = znode;
- off.op = Oconst;
- off.ty = tint;
- off.addable = Rconst;
- adr = znode;
- adr.op = Oadr;
- adr.left = &tab;
- adr.ty = tint;
- add = znode;
- add.op = Oadd;
- add.left = &adr;
- add.right = &off;
- add.ty = tint;
- slot = znode;
- slot.op = Oind;
- slot.left = &add;
- sumark(&slot);
- /*
- * gen the channel
- * this sleaze is lying to the garbage collector
- */
- off.val = 2*IBY2WD;
- if(left->addable < Rcant)
- genmove(src, Mas, tint, left, &slot);
- else{
- slot.ty = left->ty;
- ecom(src, &slot, left);
- slot.ty = nil;
- }
- /*
- * gen the value
- */
- off.val += IBY2WD;
- p = genrawop(&left->src, ILEA, nto, nil, &slot);
- p->m.offset = nto->ty->size; /* for optimizer */
- /*
- * number of senders and receivers
- */
- off.val = 0;
- genmove(src, Mas, tint, sumark(mkconst(src, 0)), &slot);
- off.val += IBY2WD;
- genmove(src, Mas, tint, sumark(mkconst(src, 1)), &slot);
- off.val += IBY2WD;
- p = genrawop(src, IALT, &tab, nil, &which);
- p->m.offset = talt->size; /* for optimizer */
- tfree(&which);
- tfree(&tab);
- }
- /*
- * generate code to duplicate an adt with pick fields
- * this is just a hacked up small pick
- * n is Oind(exp)
- */
- void
- pickdupcom(Src *src, Node *nto, Node *n)
- {
- Node *start, *stop, *node, *orig, *dest, tmp, clab;
- Case *c;
- Inst *j, *jmps, *wild;
- Label *labs;
- Decl *d, *tg, *stg;
- Type *t;
- int i, nlab;
- char buf[32];
- if(n->op != Oind)
- fatal("pickdupcom not Oind: %n" ,n);
- t = n->ty;
- nlab = t->decl->tag;
- /*
- * generate global which has case labels
- */
- seprint(buf, buf+sizeof(buf), ".c%d", nlabel++);
- d = mkids(src, enter(buf, 0), mktype(&src->start, &src->stop, Tcase, nil, nil), nil);
- d->init = mkdeclname(src, d);
- clab.addable = Rmreg;
- clab.left = nil;
- clab.right = nil;
- clab.op = Oname;
- clab.ty = d->ty;
- clab.decl = d;
- /*
- * generate a temp to hold the real value
- * then generate a case on the tag
- */
- orig = n->left;
- talloc(&tmp, orig->ty, nil);
- ecom(src, &tmp, orig);
- orig = mkunary(Oind, &tmp);
- orig->ty = tint;
- sumark(orig);
- dest = mkunary(Oind, nto);
- dest->ty = nto->ty->tof;
- sumark(dest);
- genrawop(src, ICASE, orig, nil, &clab);
- labs = allocmem(nlab * sizeof *labs);
- i = 0;
- jmps = nil;
- for(tg = t->tags; tg != nil; tg = tg->next){
- stg = tg;
- for(; tg->next != nil; tg = tg->next)
- if(stg->ty != tg->next->ty)
- break;
- start = sumark(simplify(mkdeclname(src, stg)));
- stop = start;
- node = start;
- if(stg != tg){
- stop = sumark(simplify(mkdeclname(src, tg)));
- node = mkbin(Orange, start, stop);
- }
- labs[i].start = start;
- labs[i].stop = stop;
- labs[i].node = node;
- labs[i++].inst = nextinst();
- genrawop(src, INEW, mktn(tg->ty->tof), nil, nto);
- genmove(src, Mas, tg->ty->tof, orig, dest);
- j = genrawop(src, IJMP, nil, nil, nil);
- j->branch = jmps;
- jmps = j;
- }
- /*
- * this should really be a runtime error
- */
- wild = genrawop(src, IJMP, nil, nil, nil);
- patch(wild, wild);
- patch(jmps, nextinst());
- tfree(&tmp);
- if(i > nlab)
- fatal("overflowed label tab for pickdupcom");
- c = allocmem(sizeof *c);
- c->nlab = i;
- c->nsnd = 0;
- c->labs = labs;
- c->iwild = wild;
- d->ty->cse = c;
- usetype(d->ty);
- installids(Dglobal, d);
- }
- /*
- * see if name n occurs anywhere in e
- */
- int
- tupaliased(Node *n, Node *e)
- {
- for(;;){
- if(e == nil)
- return 0;
- if(e->op == Oname && e->decl == n->decl)
- return 1;
- if(tupaliased(n, e->left))
- return 1;
- e = e->right;
- }
- }
- /*
- * see if any name in n occurs anywere in e
- */
- int
- tupsaliased(Node *n, Node *e)
- {
- for(;;){
- if(n == nil)
- return 0;
- if(n->op == Oname && tupaliased(n, e))
- return 1;
- if(tupsaliased(n->left, e))
- return 1;
- n = n->right;
- }
- }
- /*
- * put unaddressable constants in the global data area
- */
- Decl*
- globalconst(Node *n)
- {
- Decl *d;
- Sym *s;
- char buf[32];
- seprint(buf, buf+sizeof(buf), ".i.%.8lux", (long)n->val);
- s = enter(buf, 0);
- d = s->decl;
- if(d == nil){
- d = mkids(&n->src, s, tint, nil);
- installids(Dglobal, d);
- d->init = n;
- d->refs++;
- }
- return d;
- }
- Decl*
- globalBconst(Node *n)
- {
- Decl *d;
- Sym *s;
- char buf[32];
- seprint(buf, buf+sizeof(buf), ".B.%.8lux.%8lux", (long)(n->val>>32), (long)n->val);
- s = enter(buf, 0);
- d = s->decl;
- if(d == nil){
- d = mkids(&n->src, s, tbig, nil);
- installids(Dglobal, d);
- d->init = n;
- d->refs++;
- }
- return d;
- }
- Decl*
- globalbconst(Node *n)
- {
- Decl *d;
- Sym *s;
- char buf[32];
- seprint(buf, buf+sizeof(buf), ".b.%.2lux", (long)n->val & 0xff);
- s = enter(buf, 0);
- d = s->decl;
- if(d == nil){
- d = mkids(&n->src, s, tbyte, nil);
- installids(Dglobal, d);
- d->init = n;
- d->refs++;
- }
- return d;
- }
- Decl*
- globalfconst(Node *n)
- {
- Decl *d;
- Sym *s;
- char buf[32];
- ulong dv[2];
- dtocanon(n->rval, dv);
- seprint(buf, buf+sizeof(buf), ".f.%.8lux.%8lux", dv[0], dv[1]);
- s = enter(buf, 0);
- d = s->decl;
- if(d == nil){
- d = mkids(&n->src, s, treal, nil);
- installids(Dglobal, d);
- d->init = n;
- d->refs++;
- }
- return d;
- }
- Decl*
- globalsconst(Node *n)
- {
- Decl *d;
- Sym *s;
- s = n->decl->sym;
- d = s->decl;
- if(d == nil){
- d = mkids(&n->src, s, tstring, nil);
- installids(Dglobal, d);
- d->init = n;
- }
- d->refs++;
- return d;
- }
- static Node*
- subst(Decl *d, Node *e, Node *n)
- {
- if(n == nil)
- return nil;
- if(n->op == Oname){
- if(d == n->decl){
- n = dupn(0, nil, e);
- n->ty = d->ty;
- }
- return n;
- }
- n->left = subst(d, e, n->left);
- n->right = subst(d, e, n->right);
- return n;
- }
- static Node*
- putinline(Node *n)
- {
- Node *e, *tn;
- Type *t;
- Decl *d;
- if(debug['z']) print("inline1: %n\n", n);
- if(n->left->op == Oname)
- d = n->left->decl;
- else
- d = n->left->right->decl;
- e = d->init;
- t = e->ty;
- e = dupn(1, &n->src, e->right->left->left);
- for(d = t->ids, n = n->right; d != nil && n != nil; d = d->next, n = n->right){
- if(hasside(n->left, 0) && occurs(d, e) != 1){
- tn = talloc(mkn(0, nil, nil), d->ty, nil);
- e = mkbin(Ocomma, mkbin(Oas, tn, n->left), subst(d, tn, e));
- e->ty = e->right->ty;
- e->left->ty = d->ty;
- }
- else
- e = subst(d, n->left, e);
- }
- if(d != nil || n != nil)
- fatal("bad arg match in putinline()");
- if(debug['z']) print("inline2: %n\n", e);
- return e;
- }
- static void
- fpcall(Src *src, int op, Node *n, Node *ret)
- {
- Node tp, *e, *mod, *ind;
- tp.decl = nil;
- e = n->left->left;
- if(e->addable >= Rcant)
- e = eacom(e, &tp, nil);
- mod = mkunary(Oind, e);
- ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, e), mkconst(src, IBY2WD)));
- n->left = mkbin(Omdot, mod, ind);
- n->left->ty = e->ty->tof;
- mod->ty = ind->ty = ind->left->ty = ind->left->right->ty = tint;
- sumark(n);
- callcom(src, op, n, ret);
- tfree(&tp);
- }
|