| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "BackEnd.h"
- #include "ByteCode\OpCodeUtilAsmJs.h"
- void
- IRBuilderAsmJs::Build()
- {
- m_funcAlloc = m_func->m_alloc;
- NoRecoverMemoryJitArenaAllocator localAlloc(L"BE-IRBuilder", m_funcAlloc->GetPageAllocator(), Js::Throw::OutOfMemory);
- m_tempAlloc = &localAlloc;
- uint32 offset;
- uint32 statementIndex = m_statementReader.GetStatementIndex();
- m_argStack = JitAnew(m_tempAlloc, SList<IR::Instr *>, m_tempAlloc);
- m_tempList = JitAnew(m_tempAlloc, SList<IR::Instr *>, m_tempAlloc);
- m_argOffsetStack = JitAnew(m_tempAlloc, SList<int32>, m_tempAlloc);
- m_branchRelocList = JitAnew(m_tempAlloc, SList<BranchReloc *>, m_tempAlloc);
- m_switchBuilder.Init(m_func, m_tempAlloc, true);
- m_firstVarConst = 0;
- m_firstIntConst = AsmJsRegSlots::RegCount + m_firstVarConst;
- m_firstFloatConst = m_asmFuncInfo->GetIntConstCount() + m_firstIntConst;
- m_firstDoubleConst = m_asmFuncInfo->GetFloatConstCount() + m_firstFloatConst;
- m_firstSimdConst = m_asmFuncInfo->GetDoubleConstCount() + m_firstDoubleConst;
- m_firstIntVar = m_asmFuncInfo->GetSimdConstCount() + m_firstSimdConst;
- m_firstFloatVar = m_asmFuncInfo->GetIntVarCount() + m_firstIntVar;
- m_firstDoubleVar = m_asmFuncInfo->GetFloatVarCount() + m_firstFloatVar;
- m_firstSimdVar = m_asmFuncInfo->GetDoubleVarCount() + m_firstDoubleVar;
- m_firstIntTemp = m_asmFuncInfo->GetSimdVarCount() + m_firstSimdVar;
- m_firstFloatTemp = m_asmFuncInfo->GetIntTmpCount() + m_firstIntTemp;
- m_firstDoubleTemp = m_asmFuncInfo->GetFloatTmpCount() + m_firstFloatTemp;
- m_firstSimdTemp = m_asmFuncInfo->GetDoubleTmpCount() + m_firstDoubleTemp;
- m_firstIRTemp = m_asmFuncInfo->GetSimdTmpCount() + m_firstSimdTemp;
- m_simdOpcodesMap = JitAnewArrayZ(m_tempAlloc, Js::OpCode, Js::Simd128AsmJsOpcodeCount());
- {
- #define MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) m_simdOpcodesMap[(uint32)(Js::OpCodeAsmJs::opcode - Js::OpCodeAsmJs::Simd128_Start)] = Js::OpCode::opcode;
- #define MACRO_SIMD_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr)
- // append extended opcodes
- #define MACRO_SIMD_EXTEND(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) \
- m_simdOpcodesMap[(uint32)(Js::OpCodeAsmJs::opcode - Js::OpCodeAsmJs::Simd128_Start_Extend) + (Js::OpCodeAsmJs::Simd128_End - Js::OpCodeAsmJs::Simd128_Start + 1)] = Js::OpCode::opcode;
- #define MACRO_SIMD_EXTEND_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_SIMD_EXTEND(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr)
- #include "ByteCode\OpCodesSimd.h"
- }
- // we will be using lower space for type specialized syms, so bump up where new temp syms can be created
- m_func->m_symTable->IncreaseStartingID(m_firstIRTemp - m_func->m_symTable->GetMaxSymID());
- Js::RegSlot tempCount = m_asmFuncInfo->GetDoubleTmpCount() + m_asmFuncInfo->GetFloatTmpCount() + m_asmFuncInfo->GetIntTmpCount();
- tempCount += m_asmFuncInfo->GetSimdTmpCount();
- if (tempCount > 0)
- {
- m_tempMap = (SymID*)m_tempAlloc->AllocZero(sizeof(SymID) * tempCount);
- m_fbvTempUsed = BVFixed::New<JitArenaAllocator>(tempCount, m_tempAlloc);
- }
- else
- {
- m_tempMap = nullptr;
- m_fbvTempUsed = nullptr;
- }
- m_func->m_headInstr = IR::EntryInstr::New(Js::OpCode::FunctionEntry, m_func);
- m_func->m_exitInstr = IR::ExitInstr::New(Js::OpCode::FunctionExit, m_func);
- m_func->m_tailInstr = m_func->m_exitInstr;
- m_func->m_headInstr->InsertAfter(m_func->m_tailInstr);
- m_func->m_isLeaf = true; // until proven otherwise
- m_functionStartOffset = m_jnReader.GetCurrentOffset();
- m_lastInstr = m_func->m_headInstr;
- AssertMsg(sizeof(SymID) >= sizeof(Js::RegSlot), "sizeof(SymID) != sizeof(Js::RegSlot)!!");
- offset = m_functionStartOffset;
- // Skip the last EndOfBlock opcode
- // EndOfBlock opcode has same value in Asm
- Assert(!OpCodeAttr::HasMultiSizeLayout(Js::OpCode::EndOfBlock));
- uint32 lastOffset = m_func->GetJnFunction()->GetByteCode()->GetLength() - Js::OpCodeUtil::EncodedSize(Js::OpCode::EndOfBlock, Js::SmallLayout);
- uint32 offsetToInstructionCount = lastOffset;
- Js::FunctionBody *funcBody = m_func->GetJnFunction()->GetFunctionBody();
- if (this->IsLoopBody())
- {
- // LdSlot needs to cover all the register, including the temps, because we might treat
- // those as if they are local for the value of the with statement
- this->m_ldSlots = BVFixed::New<JitArenaAllocator>(m_firstIntTemp + tempCount, m_tempAlloc);
- this->m_stSlots = BVFixed::New<JitArenaAllocator>(m_firstIntTemp, m_tempAlloc);
- this->m_loopBodyRetIPSym = StackSym::New(TyInt32, this->m_func);
- #if DBG
- if (funcBody->GetTempCount() != 0)
- {
- this->m_usedAsTemp = BVFixed::New<JitArenaAllocator>(funcBody->GetTempCount(), m_tempAlloc);
- }
- #endif
- JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
- lastOffset = loopBodyCodeGen->loopHeader->endOffset;
- // Ret is created at lastOffset + 1, so we need lastOffset + 2 entries
- offsetToInstructionCount = lastOffset + 2;
- }
- #if DBG
- m_offsetToInstructionCount = offsetToInstructionCount;
- #endif
- m_offsetToInstruction = JitAnewArrayZ(m_tempAlloc, IR::Instr *, offsetToInstructionCount);
- BuildConstantLoads();
- if (!this->IsLoopBody() && m_func->GetJnFunction()->GetHasImplicitArgIns())
- {
- BuildImplicitArgIns();
- }
- if (m_statementReader.AtStatementBoundary(&m_jnReader))
- {
- statementIndex = AddStatementBoundary(statementIndex, offset);
- }
- Js::LayoutSize layoutSize;
- for (Js::OpCodeAsmJs newOpcode = (Js::OpCodeAsmJs)m_jnReader.ReadOp(layoutSize); (uint)m_jnReader.GetCurrentOffset() <= lastOffset; newOpcode = (Js::OpCodeAsmJs)m_jnReader.ReadOp(layoutSize))
- {
- Assert(newOpcode != Js::OpCodeAsmJs::EndOfBlock);
- AssertMsg(Js::OpCodeUtilAsmJs::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()");
- uint layoutAndSize = layoutSize * Js::OpLayoutTypeAsmJs::Count + Js::OpCodeUtilAsmJs::GetOpCodeLayout(newOpcode);
- switch (layoutAndSize)
- {
- #define LAYOUT_TYPE(layout) \
- case Js::OpLayoutTypeAsmJs::layout: \
- Assert(layoutSize == Js::SmallLayout); \
- Build##layout(newOpcode, offset); \
- break;
- #define LAYOUT_TYPE_WMS(layout) \
- case Js::SmallLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
- Build##layout<Js::SmallLayoutSizePolicy>(newOpcode, offset); \
- break; \
- case Js::MediumLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
- Build##layout<Js::MediumLayoutSizePolicy>(newOpcode, offset); \
- break; \
- case Js::LargeLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
- Build##layout<Js::LargeLayoutSizePolicy>(newOpcode, offset); \
- break;
- #define EXCLUDE_FRONTEND_LAYOUT
- #include "ByteCode\LayoutTypesAsmJs.h"
- default:
- AssertMsg(UNREACHED, "Unimplemented layout");
- break;
- }
- offset = m_jnReader.GetCurrentOffset();
- if (m_statementReader.AtStatementBoundary(&m_jnReader))
- {
- statementIndex = AddStatementBoundary(statementIndex, offset);
- }
- }
- if (Js::Constants::NoStatementIndex != statementIndex)
- {
- statementIndex = AddStatementBoundary(statementIndex, Js::Constants::NoByteCodeOffset);
- }
- if (IsLoopBody())
- {
- // Insert the LdSlot/StSlot and Ret
- IR::Opnd * retOpnd = this->InsertLoopBodyReturnIPInstr(offset, offset);
- // Restore and Ret are at the last offset + 1
- GenerateLoopBodySlotAccesses(lastOffset + 1);
- IR::Instr * retInstr = IR::Instr::New(Js::OpCode::Ret, m_func);
- retInstr->SetSrc1(retOpnd);
- this->AddInstr(retInstr, lastOffset + 1);
- }
- // Now fix up the targets for all the branches we've introduced.
- InsertLabels();
- // Now that we know whether the func is a leaf or not, decide whether we'll emit fast paths.
- // Do this once and for all, per-func, since the source size on the ThreadContext will be
- // changing while we JIT.
- if (m_func->IsTopFunc())
- {
- m_func->SetDoFastPaths();
- }
- }
- void
- IRBuilderAsmJs::AddInstr(IR::Instr * instr, uint32 offset)
- {
- m_lastInstr->InsertAfter(instr);
- if (offset != Js::Constants::NoByteCodeOffset)
- {
- Assert(offset < m_offsetToInstructionCount);
- if (m_offsetToInstruction[offset] == nullptr)
- {
- m_offsetToInstruction[offset] = instr;
- }
- else
- {
- Assert(m_lastInstr->GetByteCodeOffset() == offset);
- }
- instr->SetByteCodeOffset(offset);
- }
- else if (m_lastInstr)
- {
- instr->SetByteCodeOffset(m_lastInstr->GetByteCodeOffset());
- }
- m_lastInstr = instr;
- Func *topFunc = m_func->GetTopFunc();
- if (!topFunc->GetHasTempObjectProducingInstr())
- {
- if (OpCodeAttr::TempObjectProducing(instr->m_opcode))
- {
- topFunc->SetHasTempObjectProducingInstr(true);
- }
- }
- #if DBG_DUMP
- if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::IRBuilderPhase, m_func->GetTopFunc()->GetSourceContextId(), m_func->GetTopFunc()->GetLocalFunctionId()))
- {
- instr->Dump();
- }
- #endif
- }
- IR::RegOpnd *
- IRBuilderAsmJs::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type)
- {
- SymID symID;
- if (RegIsTemp(dstRegSlot))
- {
- #if DBG
- if (this->IsLoopBody())
- {
- // If we are doing loop body, and a temp reg slot is loaded via LdSlot
- // That means that we have detected that the slot is live coming in to the loop.
- // This would only happen for the value of a "with" statement, so there shouldn't
- // be any def for those
- Assert(!this->m_ldSlots->Test(dstRegSlot));
- this->m_usedAsTemp->Set(dstRegSlot - m_firstIntTemp);
- }
- #endif
- // This is a def of a temp. Create a new sym ID for it if it's been used since its last def.
- // !!!NOTE: always process an instruction's temp uses before its temp defs!!!
- if (GetTempUsed(dstRegSlot))
- {
- symID = m_func->m_symTable->NewID();
- SetTempUsed(dstRegSlot, FALSE);
- SetMappedTemp(dstRegSlot, symID);
- }
- else
- {
- symID = GetMappedTemp(dstRegSlot);
- // The temp hasn't been used since its last def. There are 2 possibilities:
- if (symID == 0)
- {
- // First time we've seen the temp. Just use the number that the front end gave it.
- symID = static_cast<SymID>(dstRegSlot);
- SetMappedTemp(dstRegSlot, symID);
- }
- }
- }
- else
- {
- symID = static_cast<SymID>(dstRegSlot);
- if (RegIsConstant(dstRegSlot))
- {
- // Don't need to track constant registers for bailout. Don't set the byte code register for constant.
- dstRegSlot = Js::Constants::NoRegister;
- }
- else if (IsLoopBody() && RegIsVar(dstRegSlot))
- {
- // Loop body and not constants
- this->m_stSlots->Set(symID);
- // We need to make sure that the symbols is loaded as well
- // so that the sym will be defined on all path.
- this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
- }
- else
- {
- Assert(!IsLoopBody() || dstRegSlot == 0); // if loop body then one of the above two conditions should hold true
- }
- }
- StackSym * symDst = StackSym::FindOrCreate(symID, dstRegSlot, m_func, type);
- // Always reset isSafeThis to false. We'll set it to true for singleDef cases,
- // but want to reset it to false if it is multi-def.
- // NOTE: We could handle the multiDef if they are all safe, but it probably isn't very common.
- symDst->m_isSafeThis = false;
- IR::RegOpnd *regOpnd = IR::RegOpnd::New(symDst, type, m_func);
- return regOpnd;
- }
- IR::RegOpnd *
- IRBuilderAsmJs::BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type)
- {
- StackSym * symSrc = m_func->m_symTable->FindStackSym(BuildSrcStackSymID(srcRegSlot, type));
- AssertMsg(symSrc, "Tried to use an undefined stack slot?");
- IR::RegOpnd * regOpnd = IR::RegOpnd::New(symSrc, type, m_func);
- return regOpnd;
- }
- IR::RegOpnd *
- IRBuilderAsmJs::BuildIntConstOpnd(Js::RegSlot regSlot)
- {
- Js::Var * constTable = static_cast<Js::Var *>(m_func->GetJnFunction()->GetConstTable());
- int * intConstTable = reinterpret_cast<int *>(constTable + Js::AsmJsFunctionMemory::RequiredVarConstants - 1);
- uint32 intConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetIntConstCount();
- Assert(regSlot >= Js::FunctionBody::FirstRegSlot && regSlot < intConstCount);
- const int32 value = intConstTable[regSlot];
- IR::IntConstOpnd *opnd = IR::IntConstOpnd::New(value, TyInt32, m_func);
- return (IR::RegOpnd*)opnd;
- }
- SymID
- IRBuilderAsmJs::BuildSrcStackSymID(Js::RegSlot regSlot, IRType type /*= IRType::TyVar*/)
- {
- SymID symID;
- if (this->RegIsTemp(regSlot))
- {
- // This is a use of a temp. Map the reg slot to its sym ID.
- // !!!NOTE: always process an instruction's temp uses before its temp defs!!!
- symID = this->GetMappedTemp(regSlot);
- if (symID == 0)
- {
- // We might have temps that are live through the loop body via "with" statement
- // We need to treat those as if they are locals and don't remap them
- Assert(this->IsLoopBody());
- Assert(!this->m_usedAsTemp->Test(regSlot - m_firstIntTemp));
- symID = static_cast<SymID>(regSlot);
- this->SetMappedTemp(regSlot, symID);
- this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
- }
- this->SetTempUsed(regSlot, TRUE);
- }
- else
- {
- symID = static_cast<SymID>(regSlot);
- if (IsLoopBody() && RegIsVar(regSlot))
- {
- this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
- }
- else
- {
- Assert(!IsLoopBody() || this->RegIsConstant(regSlot) || regSlot == 0);
- }
- }
- return symID;
- }
- IR::SymOpnd *
- IRBuilderAsmJs::BuildFieldOpnd(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind, IRType type, bool scale)
- {
- Js::PropertyId scaledPropertyId = propertyId;
- if (scale)
- {
- scaledPropertyId *= TySize[type];
- }
- PropertySym * propertySym = BuildFieldSym(reg, scaledPropertyId, propertyKind);
- IR::SymOpnd * symOpnd = IR::SymOpnd::New(propertySym, type, m_func);
- return symOpnd;
- }
- PropertySym *
- IRBuilderAsmJs::BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind)
- {
- SymID symId = BuildSrcStackSymID(reg);
- AssertMsg(m_func->m_symTable->FindStackSym(symId), "Tried to use an undefined stacksym?");
- PropertySym * propertySym = PropertySym::FindOrCreate(symId, propertyId, (Js::PropertyIdIndexType)-1, (uint)-1, propertyKind, m_func);
- return propertySym;
- }
- uint
- IRBuilderAsmJs::AddStatementBoundary(uint statementIndex, uint offset)
- {
- IR::PragmaInstr* pragmaInstr = IR::PragmaInstr::New(Js::OpCode::StatementBoundary, statementIndex, m_func);
- this->AddInstr(pragmaInstr, offset);
- return m_statementReader.MoveNextStatementBoundary();
- }
- Js::RegSlot
- IRBuilderAsmJs::GetRegSlotFromIntReg(Js::RegSlot srcIntReg)
- {
- Assert(m_asmFuncInfo->GetIntConstCount() >= 0);
- Js::RegSlot reg;
- if (srcIntReg < (Js::RegSlot)m_asmFuncInfo->GetIntConstCount())
- {
- reg = srcIntReg + m_firstIntConst;
- Assert(reg >= m_firstIntConst && reg < m_firstFloatConst);
- }
- else if (srcIntReg < (Js::RegSlot)(m_asmFuncInfo->GetIntVarCount() + m_asmFuncInfo->GetIntConstCount()))
- {
- reg = srcIntReg - m_asmFuncInfo->GetIntConstCount() + m_firstIntVar;
- Assert(reg >= m_firstIntVar && reg < m_firstFloatVar);
- }
- else
- {
- reg = srcIntReg - (m_asmFuncInfo->GetIntVarCount() + m_asmFuncInfo->GetIntConstCount()) + m_firstIntTemp;
- Assert(reg >= m_firstIntTemp && reg < m_firstFloatTemp);
- }
- return reg;
- }
- Js::RegSlot
- IRBuilderAsmJs::GetRegSlotFromFloatReg(Js::RegSlot srcFloatReg)
- {
- Assert(m_asmFuncInfo->GetFloatConstCount() >= 0);
- Js::RegSlot reg;
- if (srcFloatReg < (Js::RegSlot)m_asmFuncInfo->GetFloatConstCount())
- {
- reg = srcFloatReg + m_firstFloatConst;
- Assert(reg >= m_firstFloatConst && reg < m_firstDoubleConst);
- }
- else if (srcFloatReg < (Js::RegSlot)(m_asmFuncInfo->GetFloatVarCount() + m_asmFuncInfo->GetFloatConstCount()))
- {
- reg = srcFloatReg - m_asmFuncInfo->GetFloatConstCount() + m_firstFloatVar;
- Assert(reg >= m_firstFloatVar && reg < m_firstDoubleVar);
- }
- else
- {
- reg = srcFloatReg - (m_asmFuncInfo->GetFloatVarCount() + m_asmFuncInfo->GetFloatConstCount()) + m_firstFloatTemp;
- Assert(reg >= m_firstFloatTemp && reg < m_firstDoubleTemp);
- }
- return reg;
- }
- Js::RegSlot
- IRBuilderAsmJs::GetRegSlotFromDoubleReg(Js::RegSlot srcDoubleReg)
- {
- Assert(m_asmFuncInfo->GetDoubleConstCount() >= 0);
- Js::RegSlot reg;
- if (srcDoubleReg < (Js::RegSlot)m_asmFuncInfo->GetDoubleConstCount())
- {
- reg = srcDoubleReg + m_firstDoubleConst;
- Assert(reg >= m_firstDoubleConst && reg < m_firstSimdConst);
- }
- else if (srcDoubleReg < (Js::RegSlot)(m_asmFuncInfo->GetDoubleVarCount() + m_asmFuncInfo->GetDoubleConstCount()))
- {
- reg = srcDoubleReg - m_asmFuncInfo->GetDoubleConstCount() + m_firstDoubleVar;
- Assert(reg >= m_firstDoubleVar && reg < m_firstSimdVar);
- }
- else
- {
- reg = srcDoubleReg - (m_asmFuncInfo->GetDoubleVarCount() + m_asmFuncInfo->GetDoubleConstCount()) + m_firstDoubleTemp;
- Assert(reg >= m_firstDoubleTemp && reg < m_firstSimdTemp);
- }
- return reg;
- }
- Js::RegSlot
- IRBuilderAsmJs::GetRegSlotFromSimd128Reg(Js::RegSlot srcSimd128Reg)
- {
- Js::RegSlot reg;
- if (srcSimd128Reg < (uint32)m_asmFuncInfo->GetSimdConstCount())
- {
- reg = srcSimd128Reg + m_firstSimdConst;
- Assert(reg >= m_firstSimdConst && reg < m_firstIntVar);
- }
- else if (srcSimd128Reg < (Js::RegSlot)(m_asmFuncInfo->GetSimdVarCount() + m_asmFuncInfo->GetSimdConstCount()))
- {
- reg = srcSimd128Reg - m_asmFuncInfo->GetSimdConstCount() + m_firstSimdVar;
- Assert(reg >= m_firstSimdVar && reg < m_firstIntTemp);
- }
- else
- {
- reg = srcSimd128Reg - (m_asmFuncInfo->GetSimdVarCount() + m_asmFuncInfo->GetSimdConstCount()) + m_firstSimdTemp;
- Assert(reg >= m_firstSimdTemp && reg < m_firstIRTemp);
- }
- return reg;
- }
- IR::Instr *
- IRBuilderAsmJs::AddExtendedArg(IR::RegOpnd *src1, IR::RegOpnd *src2, uint32 offset)
- {
- Assert(src1);
- IR::RegOpnd * dst = IR::RegOpnd::New(src1->GetType(), m_func);
- dst->SetValueType(src1->GetValueType());
- IR::Instr * instr = IR::Instr::New(Js::OpCode::ExtendArg_A, dst, src1, m_func);
- if (src2)
- {
- instr->SetSrc2(src2);
- }
- AddInstr(instr, offset);
- return instr;
- }
- Js::RegSlot
- IRBuilderAsmJs::GetRegSlotFromVarReg(Js::RegSlot srcVarReg)
- {
- Js::RegSlot reg;
- if (srcVarReg < (Js::RegSlot)(AsmJsRegSlots::RegCount - 1))
- {
- reg = srcVarReg + m_firstVarConst;
- Assert(reg >= m_firstVarConst && reg < m_firstIntConst);
- }
- else
- {
- reg = srcVarReg - AsmJsRegSlots::RegCount + m_firstIntTemp - 1;
- Assert(reg >= m_firstIntTemp);
- }
- return reg;
- }
- SymID
- IRBuilderAsmJs::GetMappedTemp(Js::RegSlot reg)
- {
- AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
- AssertMsg(m_tempMap, "Processing non-temp reg without a temp map?");
- return m_tempMap[reg - m_firstIntTemp];
- }
- void
- IRBuilderAsmJs::SetMappedTemp(Js::RegSlot reg, SymID tempId)
- {
- AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
- AssertMsg(m_tempMap, "Processing non-temp reg without a temp map?");
- m_tempMap[reg - m_firstIntTemp] = tempId;
- }
- BOOL
- IRBuilderAsmJs::GetTempUsed(Js::RegSlot reg)
- {
- AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
- AssertMsg(m_fbvTempUsed, "Processing non-temp reg without a used BV?");
- return m_fbvTempUsed->Test(reg - m_firstIntTemp);
- }
- void
- IRBuilderAsmJs::SetTempUsed(Js::RegSlot reg, BOOL used)
- {
- AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
- AssertMsg(m_fbvTempUsed, "Processing non-temp reg without a used BV?");
- if (used)
- {
- m_fbvTempUsed->Set(reg - m_firstIntTemp);
- }
- else
- {
- m_fbvTempUsed->Clear(reg - m_firstIntTemp);
- }
- }
- BOOL
- IRBuilderAsmJs::RegIsTemp(Js::RegSlot reg)
- {
- return reg >= m_firstIntTemp;
- }
- BOOL
- IRBuilderAsmJs::RegIsVar(Js::RegSlot reg)
- {
- BOOL result = RegIsIntVar(reg) || RegIsFloatVar(reg) || RegIsDoubleVar(reg);
- result = result || RegIsSimd128Var(reg);
- return result;
- }
- BOOL
- IRBuilderAsmJs::RegIsIntVar(Js::RegSlot reg)
- {
- Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetIntVarCount()) + m_firstIntVar;
- return reg >= m_firstIntVar && reg < endVarSlotCount;
- }
- BOOL
- IRBuilderAsmJs::RegIsFloatVar(Js::RegSlot reg)
- {
- Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetFloatVarCount()) + m_firstFloatVar;
- return reg >= m_firstFloatVar && reg < endVarSlotCount;
- }
- BOOL
- IRBuilderAsmJs::RegIsDoubleVar(Js::RegSlot reg)
- {
- Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetDoubleVarCount()) + m_firstDoubleVar;
- return reg >= m_firstDoubleVar && reg < endVarSlotCount;
- }
- BOOL
- IRBuilderAsmJs::RegIsSimd128Var(Js::RegSlot reg)
- {
- Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetSimdVarCount()) + m_firstSimdVar;
- return reg >= m_firstSimdVar && reg < endVarSlotCount;
- }
- BOOL
- IRBuilderAsmJs::RegIsConstant(Js::RegSlot reg)
- {
- return (reg > 0 && reg < m_firstIntVar);
- }
- BranchReloc *
- IRBuilderAsmJs::AddBranchInstr(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
- {
- //
- // Loop jitting would be done only till the LoopEnd
- // Any branches beyond that offset are for the return statement
- //
- if (IsLoopBodyOuterOffset(targetOffset))
- {
- // if we have loaded the loop IP sym from the ProfiledLoopEnd then don't add it here
- if (!IsLoopBodyReturnIPInstr(m_lastInstr))
- {
- this->InsertLoopBodyReturnIPInstr(targetOffset, offset);
- }
- // Jump the restore StSlot and Ret instruction
- targetOffset = GetLoopBodyExitInstrOffset();
- }
- BranchReloc * reloc = nullptr;
- reloc = CreateRelocRecord(branchInstr, offset, targetOffset);
- AddInstr(branchInstr, offset);
- return reloc;
- }
- BranchReloc *
- IRBuilderAsmJs::CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
- {
- BranchReloc * reloc = JitAnew(m_tempAlloc, BranchReloc, branchInstr, offset, targetOffset);
- m_branchRelocList->Prepend(reloc);
- return reloc;
- }
- void
- IRBuilderAsmJs::BuildHeapBufferReload(uint32 offset)
- {
- // ArrayBuffer
- IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::ArrayReg, TyVar);
- IR::Opnd * srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ModuleMemReg, TyVar), Js::AsmJsModuleMemory::MemoryTableBeginOffset, TyVar, m_func);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- // ArrayBuffer buffer
- dstOpnd = BuildDstOpnd(AsmJsRegSlots::BufferReg, TyVar);
- srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetBufferOffset(), TyVar, m_func);
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- // ArrayBuffer length
- dstOpnd = BuildDstOpnd(AsmJsRegSlots::LengthReg, TyUint32);
- srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetByteLengthOffset(), TyUint32, m_func);
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- void
- IRBuilderAsmJs::BuildConstantLoads()
- {
- uint32 intConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetIntConstCount();
- uint32 floatConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetFloatConstCount();
- uint32 doubleConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetDoubleConstCount();
- Js::Var * constTable = static_cast<Js::Var *>(m_func->GetJnFunction()->GetConstTable());
- // Load FrameDisplay
- IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::ModuleMemReg, TyVar);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::LdAsmJsEnv, dstOpnd, m_func);
- AddInstr(instr, Js::Constants::NoByteCodeOffset);
- // Load heap buffer
- if (m_asmFuncInfo->UsesHeapBuffer())
- {
- BuildHeapBufferReload(Js::Constants::NoByteCodeOffset);
- }
- uint32 regAllocated = AsmJsRegSlots::RegCount;
- // build int const loads
- int * intConstTable = reinterpret_cast<int *>(constTable + Js::AsmJsFunctionMemory::RequiredVarConstants - 1);
- for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < intConstCount; ++reg)
- {
- int32 intConst = intConstTable[reg];
- IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TyInt32);
- Assert(RegIsConstant(reg));
- dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr *instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, IR::IntConstOpnd::New(intConst, TyInt32, m_func), m_func);
- if (dstOpnd->m_sym->IsSingleDef())
- {
- dstOpnd->m_sym->SetIsIntConst(intConst);
- }
- AddInstr(instr, Js::Constants::NoByteCodeOffset);
- ++regAllocated;
- }
- // do the same for float constants
- // Space for F0
- ++regAllocated;
- float * floatConstTable = reinterpret_cast<float *>(intConstTable + intConstCount);
- for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < floatConstCount; ++reg)
- {
- float floatConst = floatConstTable[reg];
- IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TyFloat32);
- Assert(RegIsConstant(reg));
- dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr *instr = IR::Instr::New(Js::OpCode::LdC_F8_R8, dstOpnd, IR::FloatConstOpnd::New(floatConst, TyFloat32, m_func), m_func);
- #if _M_IX86
- if (dstOpnd->m_sym->IsSingleDef())
- {
- dstOpnd->m_sym->SetIsFloatConst();
- }
- #endif
- AddInstr(instr, Js::Constants::NoByteCodeOffset);
- ++regAllocated;
- }
- // ... and doubles
- // Space for D0
- ++regAllocated;
- double * doubleConstTable = reinterpret_cast<double *>(floatConstTable + floatConstCount);
- for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < doubleConstCount; ++reg)
- {
- double doubleConst = doubleConstTable[reg];
- IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TyFloat64);
- Assert(RegIsConstant(reg));
- dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr *instr = IR::Instr::New(Js::OpCode::LdC_F8_R8, dstOpnd, IR::FloatConstOpnd::New(doubleConst, TyFloat64, m_func), m_func);
- #if _M_IX86
- if (dstOpnd->m_sym->IsSingleDef())
- {
- dstOpnd->m_sym->SetIsFloatConst();
- }
- #endif
- AddInstr(instr, Js::Constants::NoByteCodeOffset);
- ++regAllocated;
- }
- uint32 simdConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetSimdConstCount();
- // Space for SIMD0
- ++regAllocated;
- AsmJsSIMDValue *simdConstTable = reinterpret_cast<AsmJsSIMDValue *>(doubleConstTable + doubleConstCount);
- for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < simdConstCount; ++reg)
- {
- AsmJsSIMDValue simdConst = simdConstTable[reg];
- // Simd constants are not sub-typed, we pick any IR type for now, when the constant is actually used (Ld_A to a variable), we type the variable from the opcode.
- IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TySimd128F4);
- Assert(RegIsConstant(reg));
- dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
- // Constants vars are generic SIMD128 values, no sub-type. We currently don't have top SIMD128 type in ValueType, since it is not needed by globOpt.
- // However, for ASMJS, the IR type is enough to tell us it is a Simd128 value.
- dstOpnd->SetValueType(ValueType::UninitializedObject);
- IR::Instr *instr = IR::Instr::New(Js::OpCode::Simd128_LdC, dstOpnd, IR::Simd128ConstOpnd::New(simdConst, TySimd128F4, m_func), m_func);
- #if _M_IX86
- if (dstOpnd->m_sym->IsSingleDef())
- {
- dstOpnd->m_sym->SetIsSimd128Const();
- }
- #endif
- AddInstr(instr, Js::Constants::NoByteCodeOffset);
- ++regAllocated;
- }
- }
- void
- IRBuilderAsmJs::BuildImplicitArgIns()
- {
- int32 intArgInCount = 0;
- int32 floatArgInCount = 0;
- int32 doubleArgInCount = 0;
- int32 simd128ArgInCount = 0;
- // formal params are offset from EBP by the EBP chain, return address, and function object
- int32 offset = 3 * MachPtr;
- for (Js::ArgSlot i = 1; i < m_func->GetJnFunction()->GetInParamsCount(); ++i)
- {
- StackSym * symSrc = nullptr;
- IR::Opnd * srcOpnd = nullptr;
- IR::RegOpnd * dstOpnd = nullptr;
- IR::Instr * instr = nullptr;
- // TODO: double args are not aligned on stack
- Js::AsmJsVarType varType = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetArgType(i - 1);
- switch (varType.which())
- {
- case Js::AsmJsVarType::Which::Int:
- symSrc = StackSym::NewParamSlotSym(i, m_func, TyInt32);
- m_func->SetArgOffset(symSrc, offset);
- srcOpnd = IR::SymOpnd::New(symSrc, TyInt32, m_func);
- dstOpnd = BuildDstOpnd(m_firstIntVar + intArgInCount, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
- offset += MachPtr;
- ++intArgInCount;
- break;
- case Js::AsmJsVarType::Which::Float:
- symSrc = StackSym::NewParamSlotSym(i, m_func, TyFloat32);
- m_func->SetArgOffset(symSrc, offset);
- srcOpnd = IR::SymOpnd::New(symSrc, TyFloat32, m_func);
- dstOpnd = BuildDstOpnd(m_firstFloatVar + floatArgInCount, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
- offset += MachPtr;
- ++floatArgInCount;
- break;
- case Js::AsmJsVarType::Which::Double:
- symSrc = StackSym::NewParamSlotSym(i, m_func, TyFloat64);
- m_func->SetArgOffset(symSrc, offset);
- srcOpnd = IR::SymOpnd::New(symSrc, TyFloat64, m_func);
- dstOpnd = BuildDstOpnd(m_firstDoubleVar + doubleArgInCount, TyFloat64);
- dstOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
- offset += MachDouble;
- ++doubleArgInCount;
- break;
- case Js::AsmJsVarType::Which::Float32x4:
- case Js::AsmJsVarType::Which::Int32x4:
- case Js::AsmJsVarType::Which::Float64x2:
- {
- IRType argType;
- if (varType.which() == Js::AsmJsVarType::Which::Float32x4)
- {
- argType = TySimd128F4;
- }
- else if (varType.which() == Js::AsmJsVarType::Which::Int32x4)
- {
- argType = TySimd128I4;
- }
- else
- {
- Assert(varType.which() == Js::AsmJsVarType::Which::Float64x2);
- argType = TySimd128D2;
- }
- symSrc = StackSym::NewParamSlotSym(i, m_func, argType);
- m_func->SetArgOffset(symSrc, offset);
- srcOpnd = IR::SymOpnd::New(symSrc, argType, m_func);
- dstOpnd = BuildDstOpnd(m_firstSimdVar + simd128ArgInCount, argType);
- dstOpnd->SetValueType(ValueType::UninitializedObject);
- instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
- offset += sizeof(AsmJsSIMDValue);
- ++simd128ArgInCount;
- break;
- }
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, Js::Constants::NoByteCodeOffset);
- }
- }
- void
- IRBuilderAsmJs::InsertLabels()
- {
- AssertMsg(m_branchRelocList, "Malformed branch reloc list");
- SList<BranchReloc *>::Iterator iter(m_branchRelocList);
- while (iter.Next())
- {
- IR::LabelInstr * labelInstr;
- BranchReloc * reloc = iter.Data();
- IR::BranchInstr * branchInstr = reloc->GetBranchInstr();
- uint offset = reloc->GetOffset();
- uint const branchOffset = reloc->GetBranchOffset();
- Assert(!IsLoopBody() || offset <= GetLoopBodyExitInstrOffset());
- if (branchInstr->m_opcode == Js::OpCode::MultiBr)
- {
- IR::MultiBranchInstr * multiBranchInstr = branchInstr->AsBranchInstr()->AsMultiBrInstr();
- multiBranchInstr->UpdateMultiBrTargetOffsets([&](uint32 offset) -> IR::LabelInstr *
- {
- labelInstr = this->CreateLabel(branchInstr, offset);
- multiBranchInstr->ChangeLabelRef(nullptr, labelInstr);
- return labelInstr;
- });
- }
- else
- {
- labelInstr = CreateLabel(branchInstr, offset);
- branchInstr->SetTarget(labelInstr);
- }
- if (!reloc->IsNotBackEdge() && branchOffset >= offset)
- {
- labelInstr->m_isLoopTop = true;
- }
- }
- }
- IR::LabelInstr *
- IRBuilderAsmJs::CreateLabel(IR::BranchInstr * branchInstr, uint & offset)
- {
- IR::Instr * targetInstr = nullptr;
- while (targetInstr == nullptr)
- {
- targetInstr = m_offsetToInstruction[offset];
- Assert(offset < m_offsetToInstructionCount);
- ++offset;
- }
- IR::Instr *instrPrev = targetInstr->m_prev;
- if (instrPrev)
- {
- instrPrev = targetInstr->GetPrevRealInstrOrLabel();
- }
- IR::LabelInstr * labelInstr;
- if (instrPrev && instrPrev->IsLabelInstr())
- {
- // Found an existing label at the right offset. Just reuse it.
- labelInstr = instrPrev->AsLabelInstr();
- }
- else
- {
- // No label at the desired offset. Create one.
- labelInstr = IR::LabelInstr::New(Js::OpCode::Label, m_func);
- labelInstr->SetByteCodeOffset(offset);
- if (instrPrev)
- {
- instrPrev->InsertAfter(labelInstr);
- }
- else
- {
- targetInstr->InsertBefore(labelInstr);
- }
- }
- return labelInstr;
- }
- void
- IRBuilderAsmJs::BuildEmpty(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- m_jnReader.Empty();
- IR::Instr * instr = nullptr;
- IR::RegOpnd * regOpnd = nullptr;
- Js::RegSlot retSlot;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Ret:
- instr = IR::Instr::New(Js::OpCode::Ret, m_func);
- switch (m_asmFuncInfo->GetReturnType().which())
- {
- case Js::AsmJsRetType::Which::Signed:
- retSlot = GetRegSlotFromIntReg(0);
- regOpnd = BuildDstOpnd(retSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- break;
- case Js::AsmJsRetType::Which::Float:
- retSlot = GetRegSlotFromFloatReg(0);
- regOpnd = BuildDstOpnd(retSlot, TyFloat32);
- regOpnd->SetValueType(ValueType::Float);
- break;
- case Js::AsmJsRetType::Which::Double:
- retSlot = GetRegSlotFromDoubleReg(0);
- regOpnd = BuildDstOpnd(retSlot, TyFloat64);
- regOpnd->SetValueType(ValueType::Float);
- break;
- case Js::AsmJsRetType::Which::Void:
- retSlot = GetRegSlotFromVarReg(0);
- regOpnd = BuildDstOpnd(retSlot, TyVar);
- break;
- case Js::AsmJsRetType::Which::Float32x4:
- retSlot = GetRegSlotFromSimd128Reg(0);
- regOpnd = BuildDstOpnd(retSlot, TySimd128F4);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- break;
- case Js::AsmJsRetType::Which::Int32x4:
- retSlot = GetRegSlotFromSimd128Reg(0);
- regOpnd = BuildDstOpnd(retSlot, TySimd128I4);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- break;
- case Js::AsmJsRetType::Which::Float64x2:
- retSlot = GetRegSlotFromSimd128Reg(0);
- regOpnd = BuildDstOpnd(retSlot, TySimd128D2);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- break;
- default:
- Assume(UNREACHED);
- }
- instr->SetSrc1(regOpnd);
- AddInstr(instr, offset);
- break;
- case Js::OpCodeAsmJs::Label:
- // NOP
- break;
- default:
- Assume(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_ElementSlot<SizePolicy>>();
- BuildElementSlot(newOpcode, offset, layout->SlotIndex, layout->Value, layout->Instance);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildAsmUnsigned1(Js::OpCodeAsmJs newOpcode, uint value)
- {
- // we do not support counter in loop body ,just read the layout here
- m_jnReader.GetLayout<Js::OpLayoutT_AsmUnsigned1<SizePolicy>>();
- }
- void
- IRBuilderAsmJs::BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 slotIndex, Js::RegSlot value, Js::RegSlot instance)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- Assert(instance == 1 || newOpcode == Js::OpCodeAsmJs::LdArr_Func);
- Js::RegSlot valueRegSlot;
- IR::Opnd * slotOpnd;
- IR::RegOpnd * regOpnd;
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::LdSlot_Int:
- valueRegSlot = GetRegSlotFromIntReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyInt32);
- regOpnd = BuildDstOpnd(valueRegSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LdSlot_Flt:
- valueRegSlot = GetRegSlotFromFloatReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat32);
- regOpnd = BuildDstOpnd(valueRegSlot, TyFloat32);
- regOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LdSlot_Db:
- valueRegSlot = GetRegSlotFromDoubleReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat64);
- regOpnd = BuildDstOpnd(valueRegSlot, TyFloat64);
- regOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LdSlot:
- valueRegSlot = GetRegSlotFromVarReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlotArray, TyVar);
- regOpnd = BuildDstOpnd(valueRegSlot, TyVar);
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LdSlotArr:
- valueRegSlot = GetRegSlotFromVarReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyVar);
- regOpnd = BuildDstOpnd(valueRegSlot, TyVar);
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::StSlot_Int:
- valueRegSlot = GetRegSlotFromIntReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyInt32);
- regOpnd = BuildSrcOpnd(valueRegSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::StSlot_Flt:
- valueRegSlot = GetRegSlotFromFloatReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat32);
- regOpnd = BuildSrcOpnd(valueRegSlot, TyFloat32);
- regOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::StSlot_Db:
- valueRegSlot = GetRegSlotFromDoubleReg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat64);
- regOpnd = BuildSrcOpnd(valueRegSlot, TyFloat64);
- regOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LdArr_Func:
- {
- IR::RegOpnd * baseOpnd = BuildSrcOpnd(GetRegSlotFromVarReg(instance), TyVar);
- IR::RegOpnd * indexOpnd = BuildSrcOpnd(GetRegSlotFromIntReg(slotIndex), TyUint32);
- // we multiply indexOpnd by 2^scale for the actual location
- #if _M_IX86_OR_ARM32
- byte scale = 2;
- #elif _M_X64_OR_ARM64
- byte scale = 3;
- #endif
- IR::IndirOpnd * indirOpnd = IR::IndirOpnd::New(baseOpnd, indexOpnd, scale, TyVar, m_func);
- regOpnd = BuildDstOpnd(GetRegSlotFromVarReg(value), TyVar);
- instr = IR::Instr::New(Js::OpCode::Ld_A, regOpnd, indirOpnd, m_func);
- break;
- }
- case Js::OpCodeAsmJs::Simd128_LdSlot_I4:
- {
- valueRegSlot = GetRegSlotFromSimd128Reg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128I4);
- regOpnd = BuildDstOpnd(valueRegSlot, TySimd128I4);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- }
- case Js::OpCodeAsmJs::Simd128_LdSlot_F4:
- {
- valueRegSlot = GetRegSlotFromSimd128Reg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128F4);
- regOpnd = BuildDstOpnd(valueRegSlot, TySimd128F4);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- }
- case Js::OpCodeAsmJs::Simd128_LdSlot_D2:
- {
- valueRegSlot = GetRegSlotFromSimd128Reg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128D2);
- regOpnd = BuildDstOpnd(valueRegSlot, TySimd128D2);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
- break;
- }
- case Js::OpCodeAsmJs::Simd128_StSlot_I4:
- {
- valueRegSlot = GetRegSlotFromSimd128Reg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128I4);
- regOpnd = BuildSrcOpnd(valueRegSlot, TySimd128I4);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
- break;
- }
- case Js::OpCodeAsmJs::Simd128_StSlot_F4:
- {
- valueRegSlot = GetRegSlotFromSimd128Reg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128F4);
- regOpnd = BuildSrcOpnd(valueRegSlot, TySimd128F4);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
- break;
- }
- case Js::OpCodeAsmJs::Simd128_StSlot_D2:
- {
- valueRegSlot = GetRegSlotFromSimd128Reg(value);
- slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128D2);
- regOpnd = BuildSrcOpnd(valueRegSlot, TySimd128D2);
- regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
- break;
- }
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- void
- IRBuilderAsmJs::BuildStartCall(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(!OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- const unaligned Js::OpLayoutStartCall * layout = m_jnReader.StartCall();
- IR::RegOpnd * dstOpnd = IR::RegOpnd::New(TyVar, m_func);
- IR::IntConstOpnd * srcOpnd = IR::IntConstOpnd::New(layout->ArgCount, TyInt32, m_func);
- IR::Instr * instr = nullptr;
- StackSym * symDst = nullptr;
- IR::SymOpnd * argDst = nullptr;
- IR::AddrOpnd * addrOpnd = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::I_StartCall:
- instr = IR::Instr::New(Js::OpCode::StartCall, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- // save this so we can calculate arg offsets later on
- m_argOffsetStack->Push(layout->ArgCount);
- m_argStack->Push(instr);
- break;
- case Js::OpCodeAsmJs::StartCall:
- instr = IR::Instr::New(Js::OpCode::StartCall, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- // also need to add undefined as arg0
- addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContext()->GetLibrary()->GetUndefined(), IR::AddrOpndKindDynamicVar, m_func, true);
- addrOpnd->SetValueType(ValueType::Undefined);
- symDst = m_func->m_symTable->GetArgSlotSym(1);
- argDst = IR::SymOpnd::New(symDst, TyVar, m_func);
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, argDst, addrOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- break;
- default:
- Assume(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmTypedArr<SizePolicy>>();
- BuildAsmTypedArr(newOpcode, offset, layout->SlotIndex, layout->Value, layout->ViewType);
- }
- void
- IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, int8 viewType)
- {
- IRType type = TyInt32;
- Js::RegSlot valueRegSlot = Js::Constants::NoRegister;
- bool isLd = newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::LdArrConst;
- Js::OpCode op = Js::OpCode::InvalidOpCode;
- ValueType arrayType;
- switch (viewType)
- {
- case Js::ArrayBufferView::TYPE_INT8:
- valueRegSlot = GetRegSlotFromIntReg(value);
- arrayType = ValueType::GetObject(ObjectType::Int8Array);
- type = TyInt8;
- op = isLd ? Js::OpCode::LdInt8ArrViewElem : Js::OpCode::StInt8ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_UINT8:
- valueRegSlot = GetRegSlotFromIntReg(value);
- arrayType = ValueType::GetObject(ObjectType::Uint8Array);
- type = TyUint8;
- op = isLd ? Js::OpCode::LdUInt8ArrViewElem : Js::OpCode::StUInt8ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_INT16:
- valueRegSlot = GetRegSlotFromIntReg(value);
- arrayType = ValueType::GetObject(ObjectType::Int16Array);
- type = TyInt16;
- op = isLd ? Js::OpCode::LdInt16ArrViewElem : Js::OpCode::StInt16ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_UINT16:
- valueRegSlot = GetRegSlotFromIntReg(value);
- arrayType = ValueType::GetObject(ObjectType::Uint16Array);
- type = TyUint16;
- op = isLd ? Js::OpCode::LdUInt16ArrViewElem : Js::OpCode::StUInt16ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_INT32:
- valueRegSlot = GetRegSlotFromIntReg(value);
- arrayType = ValueType::GetObject(ObjectType::Int32Array);
- type = TyInt32;
- op = isLd ? Js::OpCode::LdInt32ArrViewElem : Js::OpCode::StInt32ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_UINT32:
- valueRegSlot = GetRegSlotFromIntReg(value);
- arrayType = ValueType::GetObject(ObjectType::Uint32Array);
- type = TyUint32;
- op = isLd ? Js::OpCode::LdUInt32ArrViewElem : Js::OpCode::StUInt32ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_FLOAT32:
- valueRegSlot = GetRegSlotFromFloatReg(value);
- arrayType = ValueType::GetObject(ObjectType::Float32Array);
- type = TyFloat32;
- op = isLd ? Js::OpCode::LdFloat32ArrViewElem : Js::OpCode::StFloat32ArrViewElem;
- break;
- case Js::ArrayBufferView::TYPE_FLOAT64:
- valueRegSlot = GetRegSlotFromDoubleReg(value);
- arrayType = ValueType::GetObject(ObjectType::Float64Array);
- type = TyFloat64;
- op = isLd ? Js::OpCode::LdFloat64ArrViewElem : Js::OpCode::StFloat64ArrViewElem;
- break;
- default:
- Assume(UNREACHED);
- }
- IR::Instr * instr = nullptr;
- IR::Instr * maskInstr = nullptr;
- IR::RegOpnd * regOpnd = nullptr;
- IR::IndirOpnd * indirOpnd = nullptr;
- if (newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::StArr)
- {
- uint32 mask = 0;
- switch (type)
- {
- case TyInt8:
- case TyUint8:
- // don't need to mask
- break;
- case TyInt16:
- case TyUint16:
- mask = (uint32)~1;
- break;
- case TyInt32:
- case TyUint32:
- case TyFloat32:
- mask = (uint32)~3;
- break;
- case TyFloat64:
- mask = (uint32)~7;
- break;
- default:
- Assume(UNREACHED);
- }
- Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
- IR::RegOpnd * maskedOpnd = nullptr;
- if (mask)
- {
- maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
- maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
- }
- else
- {
- maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
- }
- indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), maskedOpnd, type, m_func);
- indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
- }
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::LdArr:
- if (IRType_IsFloat(type))
- {
- regOpnd = BuildDstOpnd(valueRegSlot, type);
- regOpnd->SetValueType(ValueType::Float);
- }
- else
- {
- regOpnd = BuildDstOpnd(valueRegSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- }
- instr = IR::Instr::New(op, regOpnd, indirOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LdArrConst:
- if (IRType_IsFloat(type))
- {
- regOpnd = BuildDstOpnd(valueRegSlot, type);
- regOpnd->SetValueType(ValueType::Float);
- }
- else
- {
- regOpnd = BuildDstOpnd(valueRegSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- }
- indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), slotIndex, type, m_func);
- indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
- instr = IR::Instr::New(op, regOpnd, indirOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::StArr:
- if (IRType_IsFloat(type))
- {
- regOpnd = BuildSrcOpnd(valueRegSlot, type);
- regOpnd->SetValueType(ValueType::Float);
- }
- else
- {
- regOpnd = BuildSrcOpnd(valueRegSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- }
- instr = IR::Instr::New(op, indirOpnd, regOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::StArrConst:
- if (IRType_IsFloat(type))
- {
- regOpnd = BuildSrcOpnd(valueRegSlot, type);
- regOpnd->SetValueType(ValueType::Float);
- }
- else
- {
- regOpnd = BuildSrcOpnd(valueRegSlot, TyInt32);
- regOpnd->SetValueType(ValueType::GetInt(false));
- }
- indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), slotIndex, type, m_func);
- indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
- instr = IR::Instr::New(op, indirOpnd, regOpnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- // constant loads won't have mask instr
- if (maskInstr)
- {
- AddInstr(maskInstr, offset);
- }
- #if _M_IX86
- instr->SetSrc2(BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32));
- #endif
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmCall<SizePolicy>>();
- BuildAsmCall(newOpcode, offset, layout->ArgCount, layout->Return, layout->Function, layout->ReturnType);
- }
- void
- IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSlot argCount, Js::RegSlot ret, Js::RegSlot function, int8 returnType)
- {
- #if DBG
- int count = 0;
- #endif
- IR::Instr * instr = nullptr;
- IR::RegOpnd * dstOpnd = nullptr;
- IR::Opnd * srcOpnd = nullptr;
- Js::RegSlot dstRegSlot;
- Js::RegSlot srcRegSlot;
- int32 argOffset = 0;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::I_Call:
- srcRegSlot = GetRegSlotFromVarReg(function);
- srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
- switch ((Js::AsmJsRetType::Which)returnType)
- {
- case Js::AsmJsRetType::Which::Signed:
- dstRegSlot = GetRegSlotFromIntReg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- break;
- case Js::AsmJsRetType::Which::Float:
- dstRegSlot = GetRegSlotFromFloatReg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- break;
- case Js::AsmJsRetType::Which::Double:
- dstRegSlot = GetRegSlotFromDoubleReg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
- dstOpnd->SetValueType(ValueType::Float);
- break;
- case Js::AsmJsRetType::Which::Void:
- break;
- case Js::AsmJsRetType::Which::Float32x4:
- dstRegSlot = GetRegSlotFromSimd128Reg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- break;
- case Js::AsmJsRetType::Which::Int32x4:
- dstRegSlot = GetRegSlotFromSimd128Reg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- break;
- case Js::AsmJsRetType::Which::Float64x2:
- dstRegSlot = GetRegSlotFromSimd128Reg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- break;
- default:
- Assume(UNREACHED);
- }
- instr = IR::Instr::New(Js::OpCode::AsmJsCallI, m_func);
- instr->SetSrc1(srcOpnd);
- if (dstOpnd)
- {
- instr->SetDst(dstOpnd);
- }
- argOffset = m_argOffsetStack->Pop();
- argOffset -= MachPtr;
- break;
- case Js::OpCodeAsmJs::Call:
- srcRegSlot = GetRegSlotFromVarReg(function);
- srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
- dstRegSlot = GetRegSlotFromVarReg(ret);
- dstOpnd = BuildDstOpnd(dstRegSlot, TyVar);
- instr = IR::Instr::New(Js::OpCode::AsmJsCallE, dstOpnd, srcOpnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- IR::Instr * argInstr = nullptr;
- IR::Instr * prevInstr = instr;
- for (argInstr = m_argStack->Pop(); argInstr && argInstr->m_opcode != Js::OpCode::StartCall; argInstr = m_argStack->Pop())
- {
- if (newOpcode == Js::OpCodeAsmJs::I_Call)
- {
- #if _M_IX86
- argOffset -= argInstr->GetDst()->GetSize();
- #elif _M_X64
- argOffset -= (argInstr->GetDst()->GetSize() <= MachPtr ? MachPtr : argInstr->GetDst()->GetSize());
- #else
- Assert(UNREACHED);
- #endif
- argInstr->GetDst()->GetStackSym()->m_offset = argOffset;
- }
- // associate the ArgOuts with this call via src2
- prevInstr->SetSrc2(argInstr->GetDst());
- prevInstr = argInstr;
- #if defined(_M_X64)
- if (m_func->GetScriptContext()->GetConfig()->IsSimdjsEnabled())
- {
- m_tempList->Push(argInstr);
- }
- #endif
- #if DBG
- count++;
- #endif
- }
- Assert(argOffset == 0);
- AnalysisAssert(argInstr);
- prevInstr->SetSrc2(argInstr->GetDst());
- #if defined(_M_X64)
- // Without SIMD vars, all args are Var in size. So offset in Var = arg position in args list.
- // With SIMD, args have variable size, so we need to track argument position in the args list to be able to assign arg register for first four args on x64.
- if (m_func->GetScriptContext()->GetConfig()->IsSimdjsEnabled())
- {
- IR::Instr *instr;
- for (uint i = 1; !m_tempList->Empty(); i++)
- {
- instr = m_tempList->Pop();
- // record argument position and make room for implicit args
- instr->GetDst()->GetStackSym()->m_argPosition = i;
- if (newOpcode == Js::OpCodeAsmJs::I_Call)
- {
- // implicit func obj arg
- instr->GetDst()->GetStackSym()->m_argPosition += 1;
- }
- else
- {
- // implicit func obj + callInfo args
- Assert(newOpcode == Js::OpCodeAsmJs::Call);
- instr->GetDst()->GetStackSym()->m_argPosition += 2;
- }
- }
- }
- #endif
- if (m_func->m_argSlotsForFunctionsCalled < argCount)
- {
- m_func->m_argSlotsForFunctionsCalled = argCount;
- }
- if (m_asmFuncInfo->UsesHeapBuffer())
- {
- // if heap buffer can change, then we will insert reload after each call
- if (!m_asmFuncInfo->IsHeapBufferConst())
- {
- BuildHeapBufferReload(offset);
- }
- // after foreign function call, we need to make sure that the heap hasn't been detached
- if (newOpcode == Js::OpCodeAsmJs::Call)
- {
- IR::Instr * instr = IR::Instr::New(Js::OpCode::ArrayDetachedCheck, m_func);
- instr->SetSrc1(IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetIsDetachedOffset(), TyInt8, m_func));
- AddInstr(instr, offset);
- }
- }
- }
- void
- IRBuilderAsmJs::BuildAsmBr(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(!OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- const unaligned Js::OpLayoutAsmBr * branchInsn = m_jnReader.AsmBr();
- uint targetOffset = m_jnReader.GetCurrentOffset() + branchInsn->RelativeJumpOffset;
- if (newOpcode == Js::OpCodeAsmJs::EndSwitch_Int)
- {
- m_switchBuilder.EndSwitch(offset, targetOffset);
- return;
- }
- IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::Br, NULL, m_func);
- AddBranchInstr(branchInstr, offset, targetOffset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmReg1<SizePolicy>>();
- BuildAsmReg1(newOpcode, offset, layout->R0);
- }
- void
- IRBuilderAsmJs::BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::LdUndef);
- Js::RegSlot dstRegSlot = GetRegSlotFromVarReg(dstReg);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyVar);
- if (dstOpnd->m_sym->m_isSingleDef)
- {
- dstOpnd->m_sym->m_isConst = true;
- dstOpnd->m_sym->m_isNotInt = true;
- }
- IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContext()->GetLibrary()->GetUndefined(), IR::AddrOpndKindDynamicVar, m_func, true);
- addrOpnd->SetValueType(ValueType::Undefined);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, addrOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Double1<SizePolicy>>();
- BuildInt1Double1(newOpcode, offset, layout->I0, layout->D1);
- }
- void
- IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstIntReg, Js::RegSlot srcDoubleReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Conv_DTI);
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstIntReg);
- Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(srcDoubleReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
- srcOpnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float1<SizePolicy>>();
- BuildInt1Float1(newOpcode, offset, layout->I0, layout->F1);
- }
- void
- IRBuilderAsmJs::BuildInt1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstIntReg, Js::RegSlot srcFloatReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Conv_FTI);
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstIntReg);
- Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(srcFloatReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
- srcOpnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildDouble1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double1Int1<SizePolicy>>();
- BuildDouble1Int1(newOpcode, offset, layout->D0, layout->I1);
- }
- void
- IRBuilderAsmJs::BuildDouble1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstDoubleReg, Js::RegSlot srcIntReg)
- {
- Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(srcIntReg);
- Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dstDoubleReg);
- IR::RegOpnd * srcOpnd = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Conv_ITD:
- srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
- break;
- case Js::OpCodeAsmJs::Conv_UTD:
- srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint32);
- break;
- default:
- Assume(UNREACHED);
- }
- srcOpnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildDouble1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double1Float1<SizePolicy>>();
- BuildDouble1Float1(newOpcode, offset, layout->D0, layout->F1);
- }
- void
- IRBuilderAsmJs::BuildDouble1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstDoubleReg, Js::RegSlot srcFloatReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Conv_FTD);
- Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dstDoubleReg);
- Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(srcFloatReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
- srcOpnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
- srcOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Reg1<SizePolicy>>();
- BuildFloat1Reg1(newOpcode, offset, layout->F0, layout->R1);
- }
- void
- IRBuilderAsmJs::BuildFloat1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstFloatReg, Js::RegSlot srcVarReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTF);
- Js::RegSlot srcRegSlot = GetRegSlotFromVarReg(srcVarReg);
- Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dstFloatReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildDouble1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double1Reg1<SizePolicy>>();
- BuildDouble1Reg1(newOpcode, offset, layout->D0, layout->R1);
- }
- void
- IRBuilderAsmJs::BuildDouble1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstDoubleReg, Js::RegSlot srcVarReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTD);
- Js::RegSlot srcRegSlot = GetRegSlotFromVarReg(srcVarReg);
- Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dstDoubleReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Reg1<SizePolicy>>();
- BuildInt1Reg1(newOpcode, offset, layout->I0, layout->R1);
- }
- void
- IRBuilderAsmJs::BuildInt1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstIntReg, Js::RegSlot srcVarReg)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTI);
- Js::RegSlot srcRegSlot = GetRegSlotFromVarReg(srcVarReg);
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstIntReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildReg1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Double1<SizePolicy>>();
- BuildReg1Double1(newOpcode, offset, layout->R0, layout->D1);
- }
- void
- IRBuilderAsmJs::BuildReg1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcDoubleReg)
- {
- Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(srcDoubleReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
- srcOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = nullptr;
- IR::Opnd * dstOpnd = nullptr;
- IR::Opnd * tmpDst = nullptr;
- StackSym * symDst = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::ArgOut_Db:
- symDst = m_func->m_symTable->GetArgSlotSym((uint16)(dstReg+1));
- if (symDst == nullptr || (uint16)(dstReg + 1) != (dstReg + 1))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- tmpDst = IR::RegOpnd::New(StackSym::New(m_func), TyVar, m_func);
- instr = IR::Instr::New(Js::OpCode::ToVar, tmpDst, srcOpnd, m_func);
- AddInstr(instr, offset);
- dstOpnd = IR::SymOpnd::New(symDst, TyVar, m_func);
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, tmpDst, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- break;
- case Js::OpCodeAsmJs::I_ArgOut_Db:
- symDst = StackSym::NewArgSlotSym((uint16)dstReg, m_func, TyFloat64);
- symDst->m_allocated = true;
- if (symDst == nullptr || (uint16)(dstReg) != (dstReg))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- dstOpnd = IR::SymOpnd::New(symDst, TyFloat64, m_func);
- dstOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- break;
- default:
- Assume(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildReg1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Float1<SizePolicy>>();
- BuildReg1Float1(newOpcode, offset, layout->R0, layout->F1);
- }
- void
- IRBuilderAsmJs::BuildReg1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcFloatReg)
- {
- Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(srcFloatReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
- srcOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = nullptr;
- IR::Opnd * dstOpnd = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::I_ArgOut_Flt:
- {
- StackSym * symDst = StackSym::NewArgSlotSym((uint16)dstReg, m_func, TyFloat32);
- symDst->m_allocated = true;
- if (symDst == nullptr || (uint16)(dstReg) != (dstReg))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- dstOpnd = IR::SymOpnd::New(symDst, TyFloat32, m_func);
- dstOpnd->SetValueType(ValueType::Float);
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- break;
- }
- default:
- Assume(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildReg1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Int1<SizePolicy>>();
- BuildReg1Int1(newOpcode, offset, layout->R0, layout->I1);
- }
- void
- IRBuilderAsmJs::BuildReg1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcIntReg)
- {
- Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(srcIntReg);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
- srcOpnd->SetValueType(ValueType::GetInt(false));
- IR::Opnd * dstOpnd;
- IR::Opnd * tmpDst;
- IR::Instr * instr;
- StackSym * symDst;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::ArgOut_Int:
- symDst = m_func->m_symTable->GetArgSlotSym((uint16)(dstReg + 1));
- if (symDst == nullptr || (uint16)(dstReg + 1) != (dstReg + 1))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- tmpDst = IR::RegOpnd::New(StackSym::New(m_func), TyVar, m_func);
- instr = IR::Instr::New(Js::OpCode::ToVar, tmpDst, srcOpnd, m_func);
- AddInstr(instr, offset);
- dstOpnd = IR::SymOpnd::New(symDst, TyVar, m_func);
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, tmpDst, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- break;
- case Js::OpCodeAsmJs::I_ArgOut_Int:
- symDst = StackSym::NewArgSlotSym((uint16)dstReg, m_func, TyInt32);
- symDst->m_allocated = true;
- if (symDst == nullptr || (uint16)(dstReg) != (dstReg))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- dstOpnd = IR::SymOpnd::New(symDst, TyInt32, m_func);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- break;
- default:
- Assume(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Const1<SizePolicy>>();
- BuildInt1Const1(newOpcode, offset, layout->I0, layout->C1);
- }
- void
- IRBuilderAsmJs::BuildInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstInt, int constInt)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Ld_IntConst);
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstInt);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, IR::IntConstOpnd::New(constInt, TyInt32, m_func), m_func);
- if (dstOpnd->m_sym->IsSingleDef())
- {
- dstOpnd->m_sym->SetIsIntConst(constInt);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Double2<SizePolicy>>();
- BuildInt1Double2(newOpcode, offset, layout->I0, layout->D1, layout->D2);
- }
- void
- IRBuilderAsmJs::BuildInt1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
- Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(src1);
- Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(src2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
- src2Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::CmLt_Db:
- instr = IR::Instr::New(Js::OpCode::CmLt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmLe_Db:
- instr = IR::Instr::New(Js::OpCode::CmLe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGt_Db:
- instr = IR::Instr::New(Js::OpCode::CmGt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGe_Db:
- instr = IR::Instr::New(Js::OpCode::CmGe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmEq_Db:
- instr = IR::Instr::New(Js::OpCode::CmEq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmNe_Db:
- instr = IR::Instr::New(Js::OpCode::CmNeq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Float2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float2<SizePolicy>>();
- BuildInt1Float2(newOpcode, offset, layout->I0, layout->F1, layout->F2);
- }
- void
- IRBuilderAsmJs::BuildInt1Float2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
- Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(src1);
- Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(src2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
- src2Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::CmLt_Flt:
- instr = IR::Instr::New(Js::OpCode::CmLt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmLe_Flt:
- instr = IR::Instr::New(Js::OpCode::CmLe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGt_Flt:
- instr = IR::Instr::New(Js::OpCode::CmGt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGe_Flt:
- instr = IR::Instr::New(Js::OpCode::CmGe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmEq_Flt:
- instr = IR::Instr::New(Js::OpCode::CmEq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmNe_Flt:
- instr = IR::Instr::New(Js::OpCode::CmNeq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int2<SizePolicy>>();
- BuildInt2(newOpcode, offset, layout->I0, layout->I1);
- }
- void
- IRBuilderAsmJs::BuildInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
- Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(src);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
- srcOpnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::BeginSwitch_Int:
- m_switchBuilder.BeginSwitch();
- // fall-through
- case Js::OpCodeAsmJs::Ld_Int:
- instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Neg_Int:
- instr = IR::Instr::New(Js::OpCode::Neg_I4, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Not_Int:
- instr = IR::Instr::New(Js::OpCode::Not_I4, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::LogNot_Int:
- instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
- break;
- case Js::OpCodeAsmJs::Conv_ITB:
- instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
- break;
- case Js::OpCodeAsmJs::Abs_Int:
- instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Clz32_Int:
- instr = IR::Instr::New(Js::OpCode::InlineMathClz32, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::I_Conv_VTI:
- instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Return_Int:
- instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
- if (m_func->IsLoopBody())
- {
- IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyInt32);
- AddInstr(slotInstr, offset);
- }
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt3(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int3<SizePolicy>>();
- BuildInt3(newOpcode, offset, layout->I0, layout->I1, layout->I2);
- }
- void
- IRBuilderAsmJs::BuildInt3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
- Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(src2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
- src1Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Add_Int:
- instr = IR::Instr::New(Js::OpCode::Add_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Sub_Int:
- instr = IR::Instr::New(Js::OpCode::Sub_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Mul_UInt:
- src1Opnd->SetType(TyUint32);
- src2Opnd->SetType(TyUint32);
- case Js::OpCodeAsmJs::Mul_Int:
- instr = IR::Instr::New(Js::OpCode::Mul_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Div_UInt:
- src1Opnd->SetType(TyUint32);
- src2Opnd->SetType(TyUint32);
- case Js::OpCodeAsmJs::Div_Int:
- instr = IR::Instr::New(Js::OpCode::Div_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Rem_UInt:
- src1Opnd->SetType(TyUint32);
- src2Opnd->SetType(TyUint32);
- case Js::OpCodeAsmJs::Rem_Int:
- instr = IR::Instr::New(Js::OpCode::Rem_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::And_Int:
- instr = IR::Instr::New(Js::OpCode::And_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Or_Int:
- instr = IR::Instr::New(Js::OpCode::Or_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Xor_Int:
- instr = IR::Instr::New(Js::OpCode::Xor_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Shl_Int:
- instr = IR::Instr::New(Js::OpCode::Shl_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Shr_Int:
- instr = IR::Instr::New(Js::OpCode::Shr_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::ShrU_Int:
- instr = IR::Instr::New(Js::OpCode::ShrU_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmLt_Int:
- instr = IR::Instr::New(Js::OpCode::CmLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmLe_Int:
- instr = IR::Instr::New(Js::OpCode::CmLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGt_Int:
- instr = IR::Instr::New(Js::OpCode::CmGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGe_Int:
- instr = IR::Instr::New(Js::OpCode::CmGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmEq_Int:
- instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmNe_Int:
- instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmLt_UnInt:
- instr = IR::Instr::New(Js::OpCode::CmUnLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmLe_UnInt:
- instr = IR::Instr::New(Js::OpCode::CmUnLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGt_UnInt:
- instr = IR::Instr::New(Js::OpCode::CmUnGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::CmGe_UnInt:
- instr = IR::Instr::New(Js::OpCode::CmUnGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Min_Int:
- instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Max_Int:
- instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Imul_Int:
- instr = IR::Instr::New(Js::OpCode::InlineMathImul, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildDouble2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double2<SizePolicy>>();
- BuildDouble2(newOpcode, offset, layout->D0, layout->D1);
- }
- void
- IRBuilderAsmJs::BuildDouble2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dst);
- Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(src);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
- srcOpnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Ld_Db:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Neg_Db:
- instr = IR::Instr::New(Js::OpCode::Neg_A, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Sin_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathSin, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Cos_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathCos, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Tan_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathTan, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Asin_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathAsin, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Acos_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathAcos, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Atan_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathAtan, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Abs_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Ceil_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathCeil, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Floor_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathFloor, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Exp_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathExp, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Log_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathLog, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Sqrt_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathSqrt, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Return_Db:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- if (m_func->IsLoopBody())
- {
- IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyFloat64);
- AddInstr(slotInstr, offset);
- }
- break;
- case Js::OpCodeAsmJs::I_Conv_VTD:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float2<SizePolicy>>();
- BuildFloat2(newOpcode, offset, layout->F0, layout->F1);
- }
- void
- IRBuilderAsmJs::BuildFloat2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
- Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(src);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
- srcOpnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Ld_Flt:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Neg_Flt:
- instr = IR::Instr::New(Js::OpCode::Neg_A, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Ceil_Flt:
- instr = IR::Instr::New(Js::OpCode::InlineMathCeil, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Floor_Flt:
- instr = IR::Instr::New(Js::OpCode::InlineMathFloor, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Sqrt_Flt:
- instr = IR::Instr::New(Js::OpCode::InlineMathSqrt, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Abs_Flt:
- instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Fround_Flt:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- break;
- case Js::OpCodeAsmJs::Return_Flt:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- if (m_func->IsLoopBody())
- {
- IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyFloat32);
- AddInstr(slotInstr, offset);
- }
- break;
- case Js::OpCodeAsmJs::I_Conv_VTF:
- instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float3<SizePolicy>>();
- BuildFloat3(newOpcode, offset, layout->F0, layout->F1, layout->F2);
- }
- void
- IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
- Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(src1);
- Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(src2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
- src2Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Add_Flt:
- instr = IR::Instr::New(Js::OpCode::Add_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Sub_Flt:
- instr = IR::Instr::New(Js::OpCode::Sub_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Mul_Flt:
- instr = IR::Instr::New(Js::OpCode::Mul_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Div_Flt:
- instr = IR::Instr::New(Js::OpCode::Div_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Double1<SizePolicy>>();
- BuildFloat1Double1(newOpcode, offset, layout->F0, layout->D1);
- }
- void
- IRBuilderAsmJs::BuildFloat1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Fround_Db);
- Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
- Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(src);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
- srcOpnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::InlineMathFround, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Int1<SizePolicy>>();
- BuildFloat1Int1(newOpcode, offset, layout->F0, layout->I1);
- }
- void
- IRBuilderAsmJs::BuildFloat1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::Fround_Int);
- Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
- Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(src);
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
- srcOpnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildDouble3(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double3<SizePolicy>>();
- BuildDouble3(newOpcode, offset, layout->D0, layout->D1, layout->D2);
- }
- void
- IRBuilderAsmJs::BuildDouble3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
- {
- Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dst);
- Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(src1);
- Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(src2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
- src2Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
- dstOpnd->SetValueType(ValueType::Float);
- IR::Instr * instr = nullptr;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Add_Db:
- instr = IR::Instr::New(Js::OpCode::Add_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Sub_Db:
- instr = IR::Instr::New(Js::OpCode::Sub_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Mul_Db:
- instr = IR::Instr::New(Js::OpCode::Mul_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Div_Db:
- instr = IR::Instr::New(Js::OpCode::Div_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Rem_Db:
- instr = IR::Instr::New(Js::OpCode::Rem_A, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Pow_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathPow, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Atan2_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathAtan2, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Min_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- case Js::OpCodeAsmJs::Max_Db:
- instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
- break;
- default:
- Assume(UNREACHED);
- }
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt1<SizePolicy>>();
- BuildBrInt1(newOpcode, offset, layout->RelativeJumpOffset, layout->I1);
- }
- void
- IRBuilderAsmJs::BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src)
- {
- Assert(newOpcode == Js::OpCodeAsmJs::BrTrue_Int);
- Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
- src1Opnd->SetValueType(ValueType::GetInt(false));
- uint targetOffset = m_jnReader.GetCurrentOffset() + relativeOffset;
- IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrTrue_I4, nullptr, src1Opnd, m_func);
- AddBranchInstr(branchInstr, offset, targetOffset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt2<SizePolicy>>();
- BuildBrInt2(newOpcode, offset, layout->RelativeJumpOffset, layout->I1, layout->I2);
- }
- void
- IRBuilderAsmJs::BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, Js::RegSlot src2)
- {
- Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(src2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
- src1Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- uint targetOffset = m_jnReader.GetCurrentOffset() + relativeOffset;
- if (newOpcode == Js::OpCodeAsmJs::Case_Int)
- {
- // branches for cases are generated entirely by the switch builder
- m_switchBuilder.OnCase(
- src1Opnd,
- src2Opnd,
- offset,
- targetOffset);
- }
- else
- {
- Assert(newOpcode == Js::OpCodeAsmJs::BrEq_Int);
- IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrEq_I4, nullptr, src1Opnd, src2Opnd, m_func);
- AddBranchInstr(branchInstr, offset, targetOffset);
- }
- }
- ///Loop Body Code
- bool
- IRBuilderAsmJs::IsLoopBody() const
- {
- return m_func->IsLoopBody();
- }
- bool
- IRBuilderAsmJs::IsLoopBodyReturnIPInstr(IR::Instr * instr) const
- {
- IR::Opnd * dst = instr->GetDst();
- return (dst && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym == m_loopBodyRetIPSym);
- }
- bool
- IRBuilderAsmJs::IsLoopBodyOuterOffset(uint offset) const
- {
- if (!IsLoopBody())
- {
- return false;
- }
- JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
- return (offset >= loopBodyCodeGen->loopHeader->endOffset || offset < loopBodyCodeGen->loopHeader->startOffset);
- }
- uint
- IRBuilderAsmJs::GetLoopBodyExitInstrOffset() const
- {
- // End of loop body, start of StSlot and Ret instruction at endOffset + 1
- return ((JsLoopBodyCodeGen*)m_func->m_workItem)->loopHeader->endOffset + 1;
- }
- IR::Instr *
- IRBuilderAsmJs::CreateLoopBodyReturnIPInstr(uint targetOffset, uint offset)
- {
- IR::RegOpnd * retOpnd = IR::RegOpnd::New(m_loopBodyRetIPSym, TyInt32, m_func);
- IR::IntConstOpnd * exitOffsetOpnd = IR::IntConstOpnd::New(targetOffset, TyInt32, m_func);
- return IR::Instr::New(Js::OpCode::Ld_I4, retOpnd, exitOffsetOpnd, m_func);
- }
- IR::Opnd *
- IRBuilderAsmJs::InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset)
- {
- IR::Instr * setRetValueInstr = CreateLoopBodyReturnIPInstr(targetOffset, offset);
- this->AddInstr(setRetValueInstr, offset);
- return setRetValueInstr->GetDst();
- }
- IR::SymOpnd *
- IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(SymID symId, IRType opndType)
- {
- // Get the interpreter frame instance that was passed in.
- StackSym *loopParamSym = m_func->EnsureLoopParamSym();
- // Compute the offset of the start of the locals array as a Var index.
- size_t localsOffset = 0;
- if (!m_IsTJLoopBody)
- {
- localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
- }
- Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
- Js::PropertyId propOffSet = 0;
- IRType type = IRType::TyInt32;
- BOOL scale = true;
- if (RegIsIntVar(symId))
- {
- const int intOffset = m_asmFuncInfo->GetIntByteOffset() / sizeof(int);
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(int));
- // Get the bytecodeRegSlot
- Js::PropertyId intRegSlot = symId - m_firstIntVar + m_asmFuncInfo->GetIntConstCount();
- // Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(intRegSlot + intOffset + localsStartSlot);
- type = IRType::TyInt32;
- }
- else if (RegIsFloatVar(symId))
- {
- const int floatOffset = m_asmFuncInfo->GetFloatByteOffset() / sizeof(float);
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(float));
- // Get the bytecodeRegSlot
- Js::PropertyId fltRegSlot = symId - m_firstFloatVar + m_asmFuncInfo->GetFloatConstCount();
- // Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(fltRegSlot + floatOffset + localsStartSlot);
- type = IRType::TyFloat32;
- }
- else if (RegIsDoubleVar(symId))
- {
- const int doubleOffset = m_asmFuncInfo->GetDoubleByteOffset() / sizeof(double);
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(double));
- // Get the bytecodeRegSlot
- Js::PropertyId dbRegSlot = symId - m_firstDoubleVar + m_asmFuncInfo->GetDoubleConstCount();
- // Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(dbRegSlot + doubleOffset + localsStartSlot);
- type = IRType::TyFloat64;
- }
- else if (RegIsSimd128Var(symId))
- {
- // SimdByteOffset is not guaranteed to be divisible by Simd size. So we do computation in bytes.
- const int simdOffset = m_asmFuncInfo->GetSimdByteOffset();
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset);
- // Get the bytecodeRegSlot
- Js::PropertyId dbRegSlot = symId - m_firstSimdVar + m_asmFuncInfo->GetSimdConstCount();
- // Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(dbRegSlot * sizeof(AsmJsSIMDValue) + simdOffset + localsStartSlot);
- type = opndType;
- scale = false;
- }
- else
- {
- Assert(UNREACHED);
- }
- if (scale)
- {
- // property ID is the offset
- propOffSet = propOffSet * TySize[type];
- }
- PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
- return IR::SymOpnd::New(fieldSym, type, m_func);
- }
- void
- IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
- {
- if (this->m_ldSlots->TestAndSet(symId))
- {
- return;
- }
- IR::SymOpnd * fieldSymOpnd = this->BuildAsmJsLoopBodySlotOpnd(symId, type);
- StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func, fieldSymOpnd->GetType());
- IR::RegOpnd * dstOpnd = IR::RegOpnd::New(symDst, symDst->GetType(), m_func);
- IR::Instr * ldSlotInstr;
- JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
- ValueType symValueType;
- if (loopBodyCodeGen->symIdToValueTypeMap && loopBodyCodeGen->symIdToValueTypeMap->TryGetValue(symId, &symValueType))
- {
- ldSlotInstr = IR::ProfiledInstr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
- ldSlotInstr->AsProfiledInstr()->u.FldInfo().valueType = symValueType;
- }
- else
- {
- ldSlotInstr = IR::Instr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
- }
- m_func->m_headInstr->InsertAfter(ldSlotInstr);
- if (m_lastInstr == m_func->m_headInstr)
- {
- m_lastInstr = ldSlotInstr;
- }
- }
- void
- IRBuilderAsmJs::GenerateLoopBodySlotAccesses(uint offset)
- {
- //
- // The interpreter instance is passed as 0th argument to the JITted loop body function.
- // Always load the argument, then use it to generate any necessary store-slots.
- //
- uint16 argument = 0;
- StackSym *symSrc = StackSym::NewParamSlotSym(argument + 1, m_func);
- symSrc->m_offset = (argument + LowererMD::GetFormalParamOffset()) * MachPtr;
- symSrc->m_allocated = true;
- IR::SymOpnd *srcOpnd = IR::SymOpnd::New(symSrc, TyMachPtr, m_func);
- StackSym *loopParamSym = m_func->EnsureLoopParamSym();
- IR::RegOpnd *loopParamOpnd = IR::RegOpnd::New(loopParamSym, TyMachPtr, m_func);
- IR::Instr *instrArgIn = IR::Instr::New(Js::OpCode::ArgIn_A, loopParamOpnd, srcOpnd, m_func);
- m_func->m_headInstr->InsertAfter(instrArgIn);
- GenerateLoopBodyStSlots(loopParamSym->m_id, offset);
- }
- void
- IRBuilderAsmJs::GenerateLoopBodyStSlots(SymID loopParamSymId, uint offset)
- {
- if (this->m_stSlots->Count() == 0)
- {
- return;
- }
- // Compute the offset to the start of the interpreter frame's locals array as a Var index.
- size_t localsOffset = 0;
- if (!m_IsTJLoopBody)
- {
- localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
- }
- Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
- // Offset m_localSlot
- const int intOffset = m_asmFuncInfo->GetIntByteOffset() / sizeof(int);
- const int doubleOffset = m_asmFuncInfo->GetDoubleByteOffset() / sizeof(double);
- const int floatOffset = m_asmFuncInfo->GetFloatByteOffset() / sizeof(float);
- BOOL scale = true;
- FOREACH_BITSET_IN_FIXEDBV(regSlot, this->m_stSlots)
- {
- Assert(!this->RegIsConstant((Js::RegSlot)regSlot));
- Js::PropertyId propOffSet = 0;
- IRType type = IRType::TyInt32;
- IR::RegOpnd * regOpnd = nullptr;
- if (RegIsIntVar(regSlot))
- {
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(int));
- // Get the bytecodeRegSlot
- Js::PropertyId intRegSlot = regSlot - m_firstIntVar + m_asmFuncInfo->GetIntConstCount();
- // Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(intRegSlot + intOffset + localsStartSlot);
- type = IRType::TyInt32;
- regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
- regOpnd->SetValueType(ValueType::GetInt(false));
- }
- else if (RegIsFloatVar(regSlot))
- {
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(float));
- // Get the bytecodeRegSlot
- Js::PropertyId fltRegSlot = regSlot - m_firstFloatVar + m_asmFuncInfo->GetFloatConstCount();
- // Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(fltRegSlot + floatOffset + localsStartSlot);
- type = IRType::TyFloat32;
- regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
- regOpnd->SetValueType(ValueType::Float);
- }
- else if (RegIsDoubleVar(regSlot))
- {
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(double));
- // Get the bytecodeRegSlot
- Js::PropertyId dbRegSlot = regSlot - m_firstDoubleVar + m_asmFuncInfo->GetDoubleConstCount();
- // Get the bytecodeRegSlot and Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(dbRegSlot + doubleOffset + localsStartSlot);
- type = IRType::TyFloat64;
- // for double change the offset to ensure we don't have the same propertyId as the ints or floats
- // this will be corrected in the lowering code and the right offset will be used
- regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
- regOpnd->SetValueType(ValueType::Float);
- }
- else if (RegIsSimd128Var(regSlot))
- {
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset);
- int simdOffset = m_asmFuncInfo->GetSimdByteOffset();
- // Get the bytecodeRegSlot
- Js::PropertyId dbRegSlot = regSlot - m_firstSimdVar + m_asmFuncInfo->GetSimdConstCount();
- // Get the bytecodeRegSlot and Get the offset from m_localSlots
- propOffSet = (Js::PropertyId)(dbRegSlot * sizeof(AsmJsSIMDValue) + simdOffset + localsStartSlot);
- // SIMD regs are non-typed. There is no way to know the incoming SIMD type to a StSlot after a loop body, so we pick any type.
- // However, at this point all src syms are already defined and assigned a type.
- type = IRType::TySimd128F4;
- regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
- regOpnd->SetValueType(ValueType::GetObject(ObjectType::UninitializedObject));
- scale = false;
- }
- else
- {
- AnalysisAssert(UNREACHED);
- }
- if (scale)
- {
- // we will use the actual offset as the propertyId
- propOffSet = propOffSet * TySize[type];
- }
- PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSymId, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
- IR::SymOpnd * fieldSymOpnd = IR::SymOpnd::New(fieldSym, regOpnd->GetType(), m_func);
- Js::OpCode opcode = Js::OpCode::StSlot;
- IR::Instr * stSlotInstr = IR::Instr::New(opcode, fieldSymOpnd, regOpnd, m_func);
- this->AddInstr(stSlotInstr, offset);
- }
- NEXT_BITSET_IN_FIXEDBV;
- }
- IR::Instr* IRBuilderAsmJs::GenerateStSlotForReturn(IR::RegOpnd* srcOpnd, IRType retType)
- {
- // Compute the offset to the start of the interpreter frame's locals array as a Var index.
- size_t localsOffset = 0;
- if (!m_IsTJLoopBody)
- {
- localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
- }
- Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
- StackSym *loopParamSym = m_func->EnsureLoopParamSym();
- Js::PropertyId propOffSet = 0;
- // Offset m_localSlot
- const int intOffset = m_asmFuncInfo->GetIntByteOffset() / sizeof(int);
- const int doubleOffset = m_asmFuncInfo->GetDoubleByteOffset() / sizeof(double);
- const int floatOffset = m_asmFuncInfo->GetFloatByteOffset() / sizeof(float);
- const int simdOffset = m_asmFuncInfo->GetSimdByteOffset();
- BOOL scale = true;
- Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(int));
- IRType type = IRType::TyInt32;
- switch (retType)
- {
- case IRType::TyInt32:
- propOffSet = (Js::PropertyId)(intOffset + localsStartSlot);
- type = IRType::TyInt32;
- break;
- case IRType::TyFloat32:
- localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(float));
- propOffSet = (Js::PropertyId)(floatOffset + localsStartSlot);
- type = IRType::TyFloat32;
- break;
- case IRType::TyFloat64:
- localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(double));
- propOffSet = (Js::PropertyId)(doubleOffset + localsStartSlot);
- type = IRType::TyFloat64;
- break;
- case IRType::TySimd128F4:
- case IRType::TySimd128I4:
- case IRType::TySimd128D2:
- localsStartSlot = (Js::PropertyId)(localsOffset);
- propOffSet = (Js::PropertyId)(simdOffset + localsStartSlot);
- type = retType;
- scale = false;
- break;
- default:
- Assume(false);
- }
- if (scale)
- {
- // we will use the actual offset as the propertyId
- propOffSet = propOffSet * TySize[type];
- }
- // Get the bytecodeRegSlot and Get the offset from m_localSlots
- PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
- IR::SymOpnd * fieldSymOpnd = IR::SymOpnd::New(fieldSym, srcOpnd->GetType(), m_func);
- Js::OpCode opcode = Js::OpCode::StSlot;
- IR::Instr * stSlotInstr = IR::Instr::New(opcode, fieldSymOpnd, srcOpnd, m_func);
- return stSlotInstr;
- }
- inline Js::OpCode IRBuilderAsmJs::GetSimdOpcode(Js::OpCodeAsmJs asmjsOpcode)
- {
- Js::OpCode opcode = (Js::OpCode) 0;
- Assert(IsSimd128AsmJsOpcode(asmjsOpcode));
- if (asmjsOpcode <= Js::OpCodeAsmJs::Simd128_End)
- {
- opcode = m_simdOpcodesMap[(uint32)((Js::OpCodeAsmJs)asmjsOpcode - Js::OpCodeAsmJs::Simd128_Start)];
- }
- else
- {
- Assert(asmjsOpcode >= Js::OpCodeAsmJs::Simd128_Start_Extend && asmjsOpcode <= Js::OpCodeAsmJs::Simd128_End_Extend);
- opcode = m_simdOpcodesMap[(uint32)((Js::OpCodeAsmJs)asmjsOpcode - Js::OpCodeAsmJs::Simd128_Start_Extend) + (uint32)(Js::OpCodeAsmJs::Simd128_End - Js::OpCodeAsmJs::Simd128_Start) + 1];
- }
- Assert(IsSimd128Opcode(opcode));
- return opcode;
- }
- // !!NOTE: Always build the src opnds first, before dst. So we record the use of any temps before assigning new symId for the dst temp.
- // Float32x4
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- Js::OpCode opcode;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Simd128_Return_F4:
- if (m_func->IsLoopBody())
- {
- IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128F4);
- AddInstr(slotInstr, offset);
- }
- opcode = Js::OpCode::Ld_A;
- break;
- case Js::OpCodeAsmJs::Simd128_I_Conv_VTF4:
- case Js::OpCodeAsmJs::Simd128_Ld_F4:
- opcode = Js::OpCode::Ld_A;
- break;
- default:
- opcode = GetSimdOpcode(newOpcode);
- }
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_3<SizePolicy>>();
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
- Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->F4_3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128F4);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- // Given bytecode: dst = op s1, s2, s3
- // Generate:
- // t1 = ExtendedArg_A s1
- // t2 = ExtendedArg_A s2, t1
- // t3 = ExtendedArg_A s3, t2
- // dst = op t3
- // Later phases will chain the arguments by following singleDefInstr of each use of ti.
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_Select_I4, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildFloat32x4_1Float4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Float4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(layout->F1);
- Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(layout->F2);
- Js::RegSlot src3RegSlot = GetRegSlotFromFloatReg(layout->F3);
- Js::RegSlot src4RegSlot = GetRegSlotFromFloatReg(layout->F4);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
- IR::RegOpnd * src4Opnd = BuildSrcOpnd(src4RegSlot, TyFloat32);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src1Opnd->SetValueType(ValueType::Float);
- src2Opnd->SetValueType(ValueType::Float);
- src3Opnd->SetValueType(ValueType::Float);
- src4Opnd->SetValueType(ValueType::Float);
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FloatsToF4, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2Int4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- IR::RegOpnd * src2Opnd = BuildIntConstOpnd(layout->I2);
- IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
- IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
- IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_F4;
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_3Int4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
- IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
- IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
- IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
- IR::RegOpnd * src6Opnd = BuildIntConstOpnd(layout->I6);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_F4;
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Float1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(layout->F1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_F4);
- Js::OpCode opcode = Js::OpCode::Simd128_Splat_F4;
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_2Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2Float1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(layout->F2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Float64x2_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FromFloat64x2_F4 || opcode == Js::OpCode::Simd128_FromFloat64x2Bits_F4, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Int32x4_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FromInt32x4_F4 || opcode == Js::OpCode::Simd128_FromInt32x4Bits_F4, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_1Int32x4_1Float32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Int32x4_1Float32x4_2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
- Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->F4_3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128F4);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_Select_F4, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildReg1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Float32x4_1<SizePolicy>>();
- Js::RegSlot srcRegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot dstRegSlot = layout->R0;
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TySimd128F4);
- srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::Instr * instr = nullptr;
- IR::Opnd * dstOpnd = nullptr;
- StackSym * symDst = nullptr;
- if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_F4)
- {
- symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128F4);
- symDst->m_allocated = true;
- if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- dstOpnd = IR::SymOpnd::New(symDst, TySimd128F4, m_func);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- }
- else
- {
- Assert(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildInt1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float32x4_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_LdSignMask_F4, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- //Int32x4
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- Js::OpCode opcode;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Simd128_Return_I4:
- if (m_func->IsLoopBody())
- {
- IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128I4);
- AddInstr(slotInstr, offset);
- }
- opcode = Js::OpCode::Ld_A;
- break;
- case Js::OpCodeAsmJs::Simd128_I_Conv_VTI4:
- case Js::OpCodeAsmJs::Simd128_Ld_I4:
- opcode = Js::OpCode::Ld_A;
- break;
- default:
- opcode = GetSimdOpcode(newOpcode);
- }
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_3<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->I4_2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- Js::OpCode opcode;
- opcode = GetSimdOpcode(newOpcode);
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->I4_2);
- Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->I4_3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128I4);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- // Given bytecode: dst = op s1, s2, s3
- // Generate:
- // t1 = ExtendedArg_A s1
- // t2 = ExtendedArg_A s2, t1
- // t3 = ExtendedArg_A s3, t2
- // dst = op t3
- // Later phases will chain the arguments by following singleDefInstr of each use of ti.
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_Select_I4, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildInt32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Int4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(layout->I1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
- Js::RegSlot src3RegSlot = GetRegSlotFromIntReg(layout->I3);
- Js::RegSlot src4RegSlot = GetRegSlotFromIntReg(layout->I4);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyInt32);
- IR::RegOpnd * src4Opnd = BuildSrcOpnd(src4RegSlot, TyInt32);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src1Opnd->SetValueType(ValueType::GetInt(false));
- src2Opnd->SetValueType(ValueType::GetInt(false));
- src3Opnd->SetValueType(ValueType::GetInt(false));
- src4Opnd->SetValueType(ValueType::GetInt(false));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_IntsToI4, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildInt32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2Int4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- IR::RegOpnd * src2Opnd = BuildIntConstOpnd(layout->I2);
- IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
- IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
- IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_I4);
- Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_I4;
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildInt32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_3Int4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->I4_2);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
- IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
- IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
- IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
- IR::RegOpnd * src6Opnd = BuildIntConstOpnd(layout->I6);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_I4);
- Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_I4;
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Int1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(layout->I1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
- src1Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_I4);
- Js::OpCode opcode = Js::OpCode::Simd128_Splat_I4;
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2Int1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- //ExtractLane ReplaceLane
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2Int2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
- Js::RegSlot src3RegSlot = GetRegSlotFromIntReg(layout->I3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyInt32);
- src3Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- // Given bytecode: dst = op s1, s2, s3
- // Generate:
- // t1 = ExtendedArg_A s1
- // t2 = ExtendedArg_A s2, t1
- // t3 = ExtendedArg_A s3, t2
- // dst = op t3
- IR::Instr* instr = nullptr;
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((opcode == Js::OpCode::Simd128_ReplaceLane_I4), "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt1Int32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Int32x4_1Int1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_I4), "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat32x4_2Int1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2Int1Float1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
- Js::RegSlot src3RegSlot = GetRegSlotFromFloatReg(layout->F3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
- src3Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- // Given bytecode: dst = op s1, s2, s3
- // Generate:
- // t1 = ExtendedArg_A s1
- // t2 = ExtendedArg_A s2, t1
- // t3 = ExtendedArg_A s3, t2
- // dst = op t3
- IR::Instr* instr = nullptr;
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((opcode == Js::OpCode::Simd128_ReplaceLane_F4), "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat1Float32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Float32x4_1Int1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(layout->F0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
- src2Opnd->SetValueType(ValueType::GetInt(false));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
- dstOpnd->SetValueType(ValueType::Float);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_F4), "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Float32x4_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FromFloat32x4_I4 || opcode == Js::OpCode::Simd128_FromFloat32x4Bits_I4, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildInt32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Float64x2_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FromFloat64x2_I4 || opcode == Js::OpCode::Simd128_FromFloat64x2Bits_I4, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildReg1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Int32x4_1<SizePolicy>>();
- Js::RegSlot srcRegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot dstRegSlot = layout->R0;
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TySimd128I4);
- srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::Instr * instr = nullptr;
- IR::Opnd * dstOpnd = nullptr;
- StackSym * symDst = nullptr;
- if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_I4)
- {
- symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128I4);
- symDst->m_allocated = true;
- if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- dstOpnd = IR::SymOpnd::New(symDst, TySimd128I4, m_func);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- }
- else
- {
- Assert(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildInt1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Int32x4_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_LdSignMask_I4, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- // Float64x2
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Simd128_Return_D2:
- if (m_func->IsLoopBody())
- {
- IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128D2);
- AddInstr(slotInstr, offset);
- }
- opcode = Js::OpCode::Ld_A;
- break;
- case Js::OpCodeAsmJs::Simd128_I_Conv_VTD2:
- case Js::OpCodeAsmJs::Simd128_Ld_D2:
- opcode = Js::OpCode::Ld_A;
- break;
- default:
- opcode = GetSimdOpcode(newOpcode);
- }
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_3(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_3<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode;
- opcode = GetSimdOpcode(newOpcode);
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_4(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_4<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
- Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->D2_3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128D2);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- // Given bytecode: dst = op s1, s2, s3
- // Generate:
- // t1 = ExtendedArg_A s1
- // t2 = ExtendedArg_A s2, t1
- // t3 = ExtendedArg_A s3, t2
- // dst = op t3
- // Later phases will chain the arguments by following singleDefInstr of each use of ti.
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_Clamp_D2, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildFloat64x2_1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Double2<SizePolicy >> ();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(layout->D1);
- Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(layout->D2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
- src2Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_DoublesToD2, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildFloat64x2_1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Double1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(layout->D1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_Splat_D2, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_2Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_2Double1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(layout->D2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
- src1Opnd->SetValueType(ValueType::Float);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_2Int2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- IR::RegOpnd * src2Opnd = BuildIntConstOpnd(layout->I2);
- IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_D2);
- Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_D2;
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_3Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_3Int2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
- IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
- IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_D2);
- Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_D2;
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Float32x4_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FromFloat32x4_D2 || opcode == Js::OpCode::Simd128_FromFloat32x4Bits_D2, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Int32x4_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_FromInt32x4_D2 || opcode == Js::OpCode::Simd128_FromInt32x4Bits_D2, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void
- IRBuilderAsmJs::BuildFloat64x2_1Int32x4_1Float64x2_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Int32x4_1Float64x2_2<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
- Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
- Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->D2_3);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
- IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
- IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128D2);
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
- IR::Instr * instr = nullptr;
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
- src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- instr = AddExtendedArg(src1Opnd, nullptr, offset);
- instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
- instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_Select_D2, "Unexpected opcode for this format.");
- AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildReg1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Float64x2_1<SizePolicy>>();
- Js::RegSlot srcRegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- Js::RegSlot dstRegSlot = layout->R0;
- IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TySimd128D2);
- srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::Instr * instr = nullptr;
- IR::Opnd * dstOpnd = nullptr;
- StackSym * symDst = nullptr;
- if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_D2)
- {
- symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128D2);
- symDst->m_allocated = true;
- if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
- {
- AssertMsg(UNREACHED, "Arg count too big...");
- Fatal();
- }
- dstOpnd = IR::SymOpnd::New(symDst, TySimd128D2, m_func);
- dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
- AddInstr(instr, offset);
- m_argStack->Push(instr);
- }
- else
- {
- Assert(UNREACHED);
- }
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildInt1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float64x2_1<SizePolicy>>();
- Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
- Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
- IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
- src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
- IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
- dstOpnd->SetValueType(ValueType::GetInt(false));
- Js::OpCode opcode = GetSimdOpcode(newOpcode);
- AssertMsg(opcode == Js::OpCode::Simd128_LdSignMask_D2, "Unexpected opcode for this format.");
- IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
- AddInstr(instr, offset);
- }
- template <typename SizePolicy>
- void IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset)
- {
- Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
- auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmSimdTypedArr<SizePolicy>>();
- BuildAsmSimdTypedArr(newOpcode, offset, layout->SlotIndex, layout->Value, layout->ViewType, layout->DataWidth);
- }
- void
- IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, int8 viewType, uint8 dataWidth)
- {
- IRType type = TySimd128F4;
- Js::RegSlot valueRegSlot = GetRegSlotFromSimd128Reg(value);
- IR::RegOpnd * maskedOpnd = nullptr;
- IR::Instr * maskInstr = nullptr;
- Js::OpCode op = GetSimdOpcode(newOpcode);
- ValueType arrayType, valueType;
- bool isLd = false, isConst = false;
- uint32 mask = 0;
- switch (newOpcode)
- {
- case Js::OpCodeAsmJs::Simd128_LdArr_I4:
- valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
- isLd = true;
- isConst = false;
- type = TySimd128I4;
- break;
- case Js::OpCodeAsmJs::Simd128_LdArr_F4:
- valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
- isLd = true;
- isConst = false;
- type = TySimd128F4;
- break;
- case Js::OpCodeAsmJs::Simd128_LdArr_D2:
- valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
- isLd = true;
- isConst = false;
- type = TySimd128D2;
- break;
- case Js::OpCodeAsmJs::Simd128_StArr_I4:
- valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
- isLd = false;
- isConst = false;
- type = TySimd128I4;
- break;
- case Js::OpCodeAsmJs::Simd128_StArr_F4:
- valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
- isLd = false;
- isConst = false;
- type = TySimd128F4;
- break;
- case Js::OpCodeAsmJs::Simd128_StArr_D2:
- valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
- isLd = false;
- isConst = false;
- type = TySimd128D2;
- break;
- case Js::OpCodeAsmJs::Simd128_LdArrConst_I4:
- valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
- isLd = true;
- isConst = true;
- type = TySimd128I4;
- break;
- case Js::OpCodeAsmJs::Simd128_LdArrConst_F4:
- valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
- isLd = true;
- isConst = true;
- type = TySimd128F4;
- break;
- case Js::OpCodeAsmJs::Simd128_LdArrConst_D2:
- valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
- isLd = true;
- isConst = true;
- type = TySimd128D2;
- break;
- case Js::OpCodeAsmJs::Simd128_StArrConst_I4:
- valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
- isLd = false;
- type = TySimd128I4;
- isConst = true;
- break;
- case Js::OpCodeAsmJs::Simd128_StArrConst_F4:
- valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
- isLd = false;
- isConst = true;
- type = TySimd128F4;
- break;
- case Js::OpCodeAsmJs::Simd128_StArrConst_D2:
- valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
- isLd = false;
- isConst = true;
- type = TySimd128D2;
- break;
- default:
- Assert(UNREACHED);
- }
- switch (viewType)
- {
- case Js::ArrayBufferView::TYPE_INT8:
- arrayType = ValueType::GetObject(ObjectType::Int8Array);
- break;
- case Js::ArrayBufferView::TYPE_UINT8:
- arrayType = ValueType::GetObject(ObjectType::Uint8Array);
- break;
- case Js::ArrayBufferView::TYPE_INT16:
- arrayType = ValueType::GetObject(ObjectType::Int16Array);
- mask = (uint32)~1;
- break;
- case Js::ArrayBufferView::TYPE_UINT16:
- arrayType = ValueType::GetObject(ObjectType::Uint16Array);
- mask = (uint32)~1;
- break;
- case Js::ArrayBufferView::TYPE_INT32:
- arrayType = ValueType::GetObject(ObjectType::Int32Array);
- mask = (uint32)~3;
- break;
- case Js::ArrayBufferView::TYPE_UINT32:
- arrayType = ValueType::GetObject(ObjectType::Uint32Array);
- mask = (uint32)~3;
- break;
- case Js::ArrayBufferView::TYPE_FLOAT32:
- arrayType = ValueType::GetObject(ObjectType::Float32Array);
- mask = (uint32)~3;
- break;
- case Js::ArrayBufferView::TYPE_FLOAT64:
- arrayType = ValueType::GetObject(ObjectType::Float64Array);
- mask = (uint32)~7;
- break;
- default:
- Assert(UNREACHED);
- }
- IR::Opnd * sizeOpnd = BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32);
- if (!isConst)
- {
- Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
- if (mask)
- {
- // AND_I4 index, mask
- maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
- maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
- }
- else
- {
- maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
- }
- }
- IR::Instr * instr = nullptr;
- IR::RegOpnd * regOpnd = nullptr;
- IR::IndirOpnd * indirOpnd = nullptr;
- IR::RegOpnd * baseOpnd = BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar);
- baseOpnd->SetValueType(arrayType);
- baseOpnd->SetValueTypeFixed();
- if (isLd)
- {
- regOpnd = BuildDstOpnd(valueRegSlot, type);
- regOpnd->SetValueType(valueType);
- if (!isConst)
- {
- Assert(maskedOpnd);
- // Js::OpCodeAsmJs::Simd128_LdArr_I4:
- // Js::OpCodeAsmJs::Simd128_LdArr_F4:
- // Js::OpCodeAsmJs::Simd128_LdArr_D2:
- indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
- }
- else
- {
- // Js::OpCodeAsmJs::Simd128_LdArrConst_I4:
- // Js::OpCodeAsmJs::Simd128_LdArrConst_F4:
- // Js::OpCodeAsmJs::Simd128_LdArrConst_D2:
- indirOpnd = IR::IndirOpnd::New(baseOpnd, slotIndex, type, m_func);
- }
- instr = IR::Instr::New(op, regOpnd, indirOpnd, sizeOpnd, m_func);
- }
- else
- {
- regOpnd = BuildSrcOpnd(valueRegSlot, type);
- regOpnd->SetValueType(valueType);
- if (!isConst)
- {
- Assert(maskedOpnd);
- // Js::OpCodeAsmJs::Simd128_StArr_I4:
- // Js::OpCodeAsmJs::Simd128_StArr_F4:
- // Js::OpCodeAsmJs::Simd128_StArr_D2:
- indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
- }
- else
- {
- // Js::OpCodeAsmJs::Simd128_StArrConst_I4:
- // Js::OpCodeAsmJs::Simd128_StArrConst_F4:
- // Js::OpCodeAsmJs::Simd128_StArrConst_D2:
- indirOpnd = IR::IndirOpnd::New(baseOpnd, slotIndex, type, m_func);
- }
- instr = IR::Instr::New(op, indirOpnd, regOpnd, sizeOpnd, m_func);
- }
- // REVIEW: Store dataWidth in the instruction itself instead of an argument to avoid using ExtendedArgs or excessive opcodes.
- Assert(dataWidth >= 4 && dataWidth <= 16);
- instr->dataWidth = dataWidth;
- if (maskInstr)
- {
- AddInstr(maskInstr, offset);
- }
- AddInstr(instr, offset);
- }
|