IRBuilderAsmJs.cpp 173 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "BackEnd.h"
  6. #include "ByteCode\OpCodeUtilAsmJs.h"
  7. void
  8. IRBuilderAsmJs::Build()
  9. {
  10. m_funcAlloc = m_func->m_alloc;
  11. NoRecoverMemoryJitArenaAllocator localAlloc(L"BE-IRBuilder", m_funcAlloc->GetPageAllocator(), Js::Throw::OutOfMemory);
  12. m_tempAlloc = &localAlloc;
  13. uint32 offset;
  14. uint32 statementIndex = m_statementReader.GetStatementIndex();
  15. m_argStack = JitAnew(m_tempAlloc, SList<IR::Instr *>, m_tempAlloc);
  16. m_tempList = JitAnew(m_tempAlloc, SList<IR::Instr *>, m_tempAlloc);
  17. m_argOffsetStack = JitAnew(m_tempAlloc, SList<int32>, m_tempAlloc);
  18. m_branchRelocList = JitAnew(m_tempAlloc, SList<BranchReloc *>, m_tempAlloc);
  19. m_switchBuilder.Init(m_func, m_tempAlloc, true);
  20. m_firstVarConst = 0;
  21. m_firstIntConst = AsmJsRegSlots::RegCount + m_firstVarConst;
  22. m_firstFloatConst = m_asmFuncInfo->GetIntConstCount() + m_firstIntConst;
  23. m_firstDoubleConst = m_asmFuncInfo->GetFloatConstCount() + m_firstFloatConst;
  24. m_firstSimdConst = m_asmFuncInfo->GetDoubleConstCount() + m_firstDoubleConst;
  25. m_firstIntVar = m_asmFuncInfo->GetSimdConstCount() + m_firstSimdConst;
  26. m_firstFloatVar = m_asmFuncInfo->GetIntVarCount() + m_firstIntVar;
  27. m_firstDoubleVar = m_asmFuncInfo->GetFloatVarCount() + m_firstFloatVar;
  28. m_firstSimdVar = m_asmFuncInfo->GetDoubleVarCount() + m_firstDoubleVar;
  29. m_firstIntTemp = m_asmFuncInfo->GetSimdVarCount() + m_firstSimdVar;
  30. m_firstFloatTemp = m_asmFuncInfo->GetIntTmpCount() + m_firstIntTemp;
  31. m_firstDoubleTemp = m_asmFuncInfo->GetFloatTmpCount() + m_firstFloatTemp;
  32. m_firstSimdTemp = m_asmFuncInfo->GetDoubleTmpCount() + m_firstDoubleTemp;
  33. m_firstIRTemp = m_asmFuncInfo->GetSimdTmpCount() + m_firstSimdTemp;
  34. m_simdOpcodesMap = JitAnewArrayZ(m_tempAlloc, Js::OpCode, Js::Simd128AsmJsOpcodeCount());
  35. {
  36. #define MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) m_simdOpcodesMap[(uint32)(Js::OpCodeAsmJs::opcode - Js::OpCodeAsmJs::Simd128_Start)] = Js::OpCode::opcode;
  37. #define MACRO_SIMD_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr)
  38. // append extended opcodes
  39. #define MACRO_SIMD_EXTEND(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) \
  40. m_simdOpcodesMap[(uint32)(Js::OpCodeAsmJs::opcode - Js::OpCodeAsmJs::Simd128_Start_Extend) + (Js::OpCodeAsmJs::Simd128_End - Js::OpCodeAsmJs::Simd128_Start + 1)] = Js::OpCode::opcode;
  41. #define MACRO_SIMD_EXTEND_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_SIMD_EXTEND(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr)
  42. #include "ByteCode\OpCodesSimd.h"
  43. }
  44. // we will be using lower space for type specialized syms, so bump up where new temp syms can be created
  45. m_func->m_symTable->IncreaseStartingID(m_firstIRTemp - m_func->m_symTable->GetMaxSymID());
  46. Js::RegSlot tempCount = m_asmFuncInfo->GetDoubleTmpCount() + m_asmFuncInfo->GetFloatTmpCount() + m_asmFuncInfo->GetIntTmpCount();
  47. tempCount += m_asmFuncInfo->GetSimdTmpCount();
  48. if (tempCount > 0)
  49. {
  50. m_tempMap = (SymID*)m_tempAlloc->AllocZero(sizeof(SymID) * tempCount);
  51. m_fbvTempUsed = BVFixed::New<JitArenaAllocator>(tempCount, m_tempAlloc);
  52. }
  53. else
  54. {
  55. m_tempMap = nullptr;
  56. m_fbvTempUsed = nullptr;
  57. }
  58. m_func->m_headInstr = IR::EntryInstr::New(Js::OpCode::FunctionEntry, m_func);
  59. m_func->m_exitInstr = IR::ExitInstr::New(Js::OpCode::FunctionExit, m_func);
  60. m_func->m_tailInstr = m_func->m_exitInstr;
  61. m_func->m_headInstr->InsertAfter(m_func->m_tailInstr);
  62. m_func->m_isLeaf = true; // until proven otherwise
  63. m_functionStartOffset = m_jnReader.GetCurrentOffset();
  64. m_lastInstr = m_func->m_headInstr;
  65. AssertMsg(sizeof(SymID) >= sizeof(Js::RegSlot), "sizeof(SymID) != sizeof(Js::RegSlot)!!");
  66. offset = m_functionStartOffset;
  67. // Skip the last EndOfBlock opcode
  68. // EndOfBlock opcode has same value in Asm
  69. Assert(!OpCodeAttr::HasMultiSizeLayout(Js::OpCode::EndOfBlock));
  70. uint32 lastOffset = m_func->GetJnFunction()->GetByteCode()->GetLength() - Js::OpCodeUtil::EncodedSize(Js::OpCode::EndOfBlock, Js::SmallLayout);
  71. uint32 offsetToInstructionCount = lastOffset;
  72. Js::FunctionBody *funcBody = m_func->GetJnFunction()->GetFunctionBody();
  73. if (this->IsLoopBody())
  74. {
  75. // LdSlot needs to cover all the register, including the temps, because we might treat
  76. // those as if they are local for the value of the with statement
  77. this->m_ldSlots = BVFixed::New<JitArenaAllocator>(m_firstIntTemp + tempCount, m_tempAlloc);
  78. this->m_stSlots = BVFixed::New<JitArenaAllocator>(m_firstIntTemp, m_tempAlloc);
  79. this->m_loopBodyRetIPSym = StackSym::New(TyInt32, this->m_func);
  80. #if DBG
  81. if (funcBody->GetTempCount() != 0)
  82. {
  83. this->m_usedAsTemp = BVFixed::New<JitArenaAllocator>(funcBody->GetTempCount(), m_tempAlloc);
  84. }
  85. #endif
  86. JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
  87. lastOffset = loopBodyCodeGen->loopHeader->endOffset;
  88. // Ret is created at lastOffset + 1, so we need lastOffset + 2 entries
  89. offsetToInstructionCount = lastOffset + 2;
  90. }
  91. #if DBG
  92. m_offsetToInstructionCount = offsetToInstructionCount;
  93. #endif
  94. m_offsetToInstruction = JitAnewArrayZ(m_tempAlloc, IR::Instr *, offsetToInstructionCount);
  95. BuildConstantLoads();
  96. if (!this->IsLoopBody() && m_func->GetJnFunction()->GetHasImplicitArgIns())
  97. {
  98. BuildImplicitArgIns();
  99. }
  100. if (m_statementReader.AtStatementBoundary(&m_jnReader))
  101. {
  102. statementIndex = AddStatementBoundary(statementIndex, offset);
  103. }
  104. Js::LayoutSize layoutSize;
  105. for (Js::OpCodeAsmJs newOpcode = (Js::OpCodeAsmJs)m_jnReader.ReadOp(layoutSize); (uint)m_jnReader.GetCurrentOffset() <= lastOffset; newOpcode = (Js::OpCodeAsmJs)m_jnReader.ReadOp(layoutSize))
  106. {
  107. Assert(newOpcode != Js::OpCodeAsmJs::EndOfBlock);
  108. AssertMsg(Js::OpCodeUtilAsmJs::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()");
  109. uint layoutAndSize = layoutSize * Js::OpLayoutTypeAsmJs::Count + Js::OpCodeUtilAsmJs::GetOpCodeLayout(newOpcode);
  110. switch (layoutAndSize)
  111. {
  112. #define LAYOUT_TYPE(layout) \
  113. case Js::OpLayoutTypeAsmJs::layout: \
  114. Assert(layoutSize == Js::SmallLayout); \
  115. Build##layout(newOpcode, offset); \
  116. break;
  117. #define LAYOUT_TYPE_WMS(layout) \
  118. case Js::SmallLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
  119. Build##layout<Js::SmallLayoutSizePolicy>(newOpcode, offset); \
  120. break; \
  121. case Js::MediumLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
  122. Build##layout<Js::MediumLayoutSizePolicy>(newOpcode, offset); \
  123. break; \
  124. case Js::LargeLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
  125. Build##layout<Js::LargeLayoutSizePolicy>(newOpcode, offset); \
  126. break;
  127. #define EXCLUDE_FRONTEND_LAYOUT
  128. #include "ByteCode\LayoutTypesAsmJs.h"
  129. default:
  130. AssertMsg(UNREACHED, "Unimplemented layout");
  131. break;
  132. }
  133. offset = m_jnReader.GetCurrentOffset();
  134. if (m_statementReader.AtStatementBoundary(&m_jnReader))
  135. {
  136. statementIndex = AddStatementBoundary(statementIndex, offset);
  137. }
  138. }
  139. if (Js::Constants::NoStatementIndex != statementIndex)
  140. {
  141. statementIndex = AddStatementBoundary(statementIndex, Js::Constants::NoByteCodeOffset);
  142. }
  143. if (IsLoopBody())
  144. {
  145. // Insert the LdSlot/StSlot and Ret
  146. IR::Opnd * retOpnd = this->InsertLoopBodyReturnIPInstr(offset, offset);
  147. // Restore and Ret are at the last offset + 1
  148. GenerateLoopBodySlotAccesses(lastOffset + 1);
  149. IR::Instr * retInstr = IR::Instr::New(Js::OpCode::Ret, m_func);
  150. retInstr->SetSrc1(retOpnd);
  151. this->AddInstr(retInstr, lastOffset + 1);
  152. }
  153. // Now fix up the targets for all the branches we've introduced.
  154. InsertLabels();
  155. // Now that we know whether the func is a leaf or not, decide whether we'll emit fast paths.
  156. // Do this once and for all, per-func, since the source size on the ThreadContext will be
  157. // changing while we JIT.
  158. if (m_func->IsTopFunc())
  159. {
  160. m_func->SetDoFastPaths();
  161. }
  162. }
  163. void
  164. IRBuilderAsmJs::AddInstr(IR::Instr * instr, uint32 offset)
  165. {
  166. m_lastInstr->InsertAfter(instr);
  167. if (offset != Js::Constants::NoByteCodeOffset)
  168. {
  169. Assert(offset < m_offsetToInstructionCount);
  170. if (m_offsetToInstruction[offset] == nullptr)
  171. {
  172. m_offsetToInstruction[offset] = instr;
  173. }
  174. else
  175. {
  176. Assert(m_lastInstr->GetByteCodeOffset() == offset);
  177. }
  178. instr->SetByteCodeOffset(offset);
  179. }
  180. else if (m_lastInstr)
  181. {
  182. instr->SetByteCodeOffset(m_lastInstr->GetByteCodeOffset());
  183. }
  184. m_lastInstr = instr;
  185. Func *topFunc = m_func->GetTopFunc();
  186. if (!topFunc->GetHasTempObjectProducingInstr())
  187. {
  188. if (OpCodeAttr::TempObjectProducing(instr->m_opcode))
  189. {
  190. topFunc->SetHasTempObjectProducingInstr(true);
  191. }
  192. }
  193. #if DBG_DUMP
  194. if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::IRBuilderPhase, m_func->GetTopFunc()->GetSourceContextId(), m_func->GetTopFunc()->GetLocalFunctionId()))
  195. {
  196. instr->Dump();
  197. }
  198. #endif
  199. }
  200. IR::RegOpnd *
  201. IRBuilderAsmJs::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type)
  202. {
  203. SymID symID;
  204. if (RegIsTemp(dstRegSlot))
  205. {
  206. #if DBG
  207. if (this->IsLoopBody())
  208. {
  209. // If we are doing loop body, and a temp reg slot is loaded via LdSlot
  210. // That means that we have detected that the slot is live coming in to the loop.
  211. // This would only happen for the value of a "with" statement, so there shouldn't
  212. // be any def for those
  213. Assert(!this->m_ldSlots->Test(dstRegSlot));
  214. this->m_usedAsTemp->Set(dstRegSlot - m_firstIntTemp);
  215. }
  216. #endif
  217. // This is a def of a temp. Create a new sym ID for it if it's been used since its last def.
  218. // !!!NOTE: always process an instruction's temp uses before its temp defs!!!
  219. if (GetTempUsed(dstRegSlot))
  220. {
  221. symID = m_func->m_symTable->NewID();
  222. SetTempUsed(dstRegSlot, FALSE);
  223. SetMappedTemp(dstRegSlot, symID);
  224. }
  225. else
  226. {
  227. symID = GetMappedTemp(dstRegSlot);
  228. // The temp hasn't been used since its last def. There are 2 possibilities:
  229. if (symID == 0)
  230. {
  231. // First time we've seen the temp. Just use the number that the front end gave it.
  232. symID = static_cast<SymID>(dstRegSlot);
  233. SetMappedTemp(dstRegSlot, symID);
  234. }
  235. }
  236. }
  237. else
  238. {
  239. symID = static_cast<SymID>(dstRegSlot);
  240. if (RegIsConstant(dstRegSlot))
  241. {
  242. // Don't need to track constant registers for bailout. Don't set the byte code register for constant.
  243. dstRegSlot = Js::Constants::NoRegister;
  244. }
  245. else if (IsLoopBody() && RegIsVar(dstRegSlot))
  246. {
  247. // Loop body and not constants
  248. this->m_stSlots->Set(symID);
  249. // We need to make sure that the symbols is loaded as well
  250. // so that the sym will be defined on all path.
  251. this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
  252. }
  253. else
  254. {
  255. Assert(!IsLoopBody() || dstRegSlot == 0); // if loop body then one of the above two conditions should hold true
  256. }
  257. }
  258. StackSym * symDst = StackSym::FindOrCreate(symID, dstRegSlot, m_func, type);
  259. // Always reset isSafeThis to false. We'll set it to true for singleDef cases,
  260. // but want to reset it to false if it is multi-def.
  261. // NOTE: We could handle the multiDef if they are all safe, but it probably isn't very common.
  262. symDst->m_isSafeThis = false;
  263. IR::RegOpnd *regOpnd = IR::RegOpnd::New(symDst, type, m_func);
  264. return regOpnd;
  265. }
  266. IR::RegOpnd *
  267. IRBuilderAsmJs::BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type)
  268. {
  269. StackSym * symSrc = m_func->m_symTable->FindStackSym(BuildSrcStackSymID(srcRegSlot, type));
  270. AssertMsg(symSrc, "Tried to use an undefined stack slot?");
  271. IR::RegOpnd * regOpnd = IR::RegOpnd::New(symSrc, type, m_func);
  272. return regOpnd;
  273. }
  274. IR::RegOpnd *
  275. IRBuilderAsmJs::BuildIntConstOpnd(Js::RegSlot regSlot)
  276. {
  277. Js::Var * constTable = static_cast<Js::Var *>(m_func->GetJnFunction()->GetConstTable());
  278. int * intConstTable = reinterpret_cast<int *>(constTable + Js::AsmJsFunctionMemory::RequiredVarConstants - 1);
  279. uint32 intConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetIntConstCount();
  280. Assert(regSlot >= Js::FunctionBody::FirstRegSlot && regSlot < intConstCount);
  281. const int32 value = intConstTable[regSlot];
  282. IR::IntConstOpnd *opnd = IR::IntConstOpnd::New(value, TyInt32, m_func);
  283. return (IR::RegOpnd*)opnd;
  284. }
  285. SymID
  286. IRBuilderAsmJs::BuildSrcStackSymID(Js::RegSlot regSlot, IRType type /*= IRType::TyVar*/)
  287. {
  288. SymID symID;
  289. if (this->RegIsTemp(regSlot))
  290. {
  291. // This is a use of a temp. Map the reg slot to its sym ID.
  292. // !!!NOTE: always process an instruction's temp uses before its temp defs!!!
  293. symID = this->GetMappedTemp(regSlot);
  294. if (symID == 0)
  295. {
  296. // We might have temps that are live through the loop body via "with" statement
  297. // We need to treat those as if they are locals and don't remap them
  298. Assert(this->IsLoopBody());
  299. Assert(!this->m_usedAsTemp->Test(regSlot - m_firstIntTemp));
  300. symID = static_cast<SymID>(regSlot);
  301. this->SetMappedTemp(regSlot, symID);
  302. this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
  303. }
  304. this->SetTempUsed(regSlot, TRUE);
  305. }
  306. else
  307. {
  308. symID = static_cast<SymID>(regSlot);
  309. if (IsLoopBody() && RegIsVar(regSlot))
  310. {
  311. this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
  312. }
  313. else
  314. {
  315. Assert(!IsLoopBody() || this->RegIsConstant(regSlot) || regSlot == 0);
  316. }
  317. }
  318. return symID;
  319. }
  320. IR::SymOpnd *
  321. IRBuilderAsmJs::BuildFieldOpnd(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind, IRType type, bool scale)
  322. {
  323. Js::PropertyId scaledPropertyId = propertyId;
  324. if (scale)
  325. {
  326. scaledPropertyId *= TySize[type];
  327. }
  328. PropertySym * propertySym = BuildFieldSym(reg, scaledPropertyId, propertyKind);
  329. IR::SymOpnd * symOpnd = IR::SymOpnd::New(propertySym, type, m_func);
  330. return symOpnd;
  331. }
  332. PropertySym *
  333. IRBuilderAsmJs::BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind)
  334. {
  335. SymID symId = BuildSrcStackSymID(reg);
  336. AssertMsg(m_func->m_symTable->FindStackSym(symId), "Tried to use an undefined stacksym?");
  337. PropertySym * propertySym = PropertySym::FindOrCreate(symId, propertyId, (Js::PropertyIdIndexType)-1, (uint)-1, propertyKind, m_func);
  338. return propertySym;
  339. }
  340. uint
  341. IRBuilderAsmJs::AddStatementBoundary(uint statementIndex, uint offset)
  342. {
  343. IR::PragmaInstr* pragmaInstr = IR::PragmaInstr::New(Js::OpCode::StatementBoundary, statementIndex, m_func);
  344. this->AddInstr(pragmaInstr, offset);
  345. return m_statementReader.MoveNextStatementBoundary();
  346. }
  347. Js::RegSlot
  348. IRBuilderAsmJs::GetRegSlotFromIntReg(Js::RegSlot srcIntReg)
  349. {
  350. Assert(m_asmFuncInfo->GetIntConstCount() >= 0);
  351. Js::RegSlot reg;
  352. if (srcIntReg < (Js::RegSlot)m_asmFuncInfo->GetIntConstCount())
  353. {
  354. reg = srcIntReg + m_firstIntConst;
  355. Assert(reg >= m_firstIntConst && reg < m_firstFloatConst);
  356. }
  357. else if (srcIntReg < (Js::RegSlot)(m_asmFuncInfo->GetIntVarCount() + m_asmFuncInfo->GetIntConstCount()))
  358. {
  359. reg = srcIntReg - m_asmFuncInfo->GetIntConstCount() + m_firstIntVar;
  360. Assert(reg >= m_firstIntVar && reg < m_firstFloatVar);
  361. }
  362. else
  363. {
  364. reg = srcIntReg - (m_asmFuncInfo->GetIntVarCount() + m_asmFuncInfo->GetIntConstCount()) + m_firstIntTemp;
  365. Assert(reg >= m_firstIntTemp && reg < m_firstFloatTemp);
  366. }
  367. return reg;
  368. }
  369. Js::RegSlot
  370. IRBuilderAsmJs::GetRegSlotFromFloatReg(Js::RegSlot srcFloatReg)
  371. {
  372. Assert(m_asmFuncInfo->GetFloatConstCount() >= 0);
  373. Js::RegSlot reg;
  374. if (srcFloatReg < (Js::RegSlot)m_asmFuncInfo->GetFloatConstCount())
  375. {
  376. reg = srcFloatReg + m_firstFloatConst;
  377. Assert(reg >= m_firstFloatConst && reg < m_firstDoubleConst);
  378. }
  379. else if (srcFloatReg < (Js::RegSlot)(m_asmFuncInfo->GetFloatVarCount() + m_asmFuncInfo->GetFloatConstCount()))
  380. {
  381. reg = srcFloatReg - m_asmFuncInfo->GetFloatConstCount() + m_firstFloatVar;
  382. Assert(reg >= m_firstFloatVar && reg < m_firstDoubleVar);
  383. }
  384. else
  385. {
  386. reg = srcFloatReg - (m_asmFuncInfo->GetFloatVarCount() + m_asmFuncInfo->GetFloatConstCount()) + m_firstFloatTemp;
  387. Assert(reg >= m_firstFloatTemp && reg < m_firstDoubleTemp);
  388. }
  389. return reg;
  390. }
  391. Js::RegSlot
  392. IRBuilderAsmJs::GetRegSlotFromDoubleReg(Js::RegSlot srcDoubleReg)
  393. {
  394. Assert(m_asmFuncInfo->GetDoubleConstCount() >= 0);
  395. Js::RegSlot reg;
  396. if (srcDoubleReg < (Js::RegSlot)m_asmFuncInfo->GetDoubleConstCount())
  397. {
  398. reg = srcDoubleReg + m_firstDoubleConst;
  399. Assert(reg >= m_firstDoubleConst && reg < m_firstSimdConst);
  400. }
  401. else if (srcDoubleReg < (Js::RegSlot)(m_asmFuncInfo->GetDoubleVarCount() + m_asmFuncInfo->GetDoubleConstCount()))
  402. {
  403. reg = srcDoubleReg - m_asmFuncInfo->GetDoubleConstCount() + m_firstDoubleVar;
  404. Assert(reg >= m_firstDoubleVar && reg < m_firstSimdVar);
  405. }
  406. else
  407. {
  408. reg = srcDoubleReg - (m_asmFuncInfo->GetDoubleVarCount() + m_asmFuncInfo->GetDoubleConstCount()) + m_firstDoubleTemp;
  409. Assert(reg >= m_firstDoubleTemp && reg < m_firstSimdTemp);
  410. }
  411. return reg;
  412. }
  413. Js::RegSlot
  414. IRBuilderAsmJs::GetRegSlotFromSimd128Reg(Js::RegSlot srcSimd128Reg)
  415. {
  416. Js::RegSlot reg;
  417. if (srcSimd128Reg < (uint32)m_asmFuncInfo->GetSimdConstCount())
  418. {
  419. reg = srcSimd128Reg + m_firstSimdConst;
  420. Assert(reg >= m_firstSimdConst && reg < m_firstIntVar);
  421. }
  422. else if (srcSimd128Reg < (Js::RegSlot)(m_asmFuncInfo->GetSimdVarCount() + m_asmFuncInfo->GetSimdConstCount()))
  423. {
  424. reg = srcSimd128Reg - m_asmFuncInfo->GetSimdConstCount() + m_firstSimdVar;
  425. Assert(reg >= m_firstSimdVar && reg < m_firstIntTemp);
  426. }
  427. else
  428. {
  429. reg = srcSimd128Reg - (m_asmFuncInfo->GetSimdVarCount() + m_asmFuncInfo->GetSimdConstCount()) + m_firstSimdTemp;
  430. Assert(reg >= m_firstSimdTemp && reg < m_firstIRTemp);
  431. }
  432. return reg;
  433. }
  434. IR::Instr *
  435. IRBuilderAsmJs::AddExtendedArg(IR::RegOpnd *src1, IR::RegOpnd *src2, uint32 offset)
  436. {
  437. Assert(src1);
  438. IR::RegOpnd * dst = IR::RegOpnd::New(src1->GetType(), m_func);
  439. dst->SetValueType(src1->GetValueType());
  440. IR::Instr * instr = IR::Instr::New(Js::OpCode::ExtendArg_A, dst, src1, m_func);
  441. if (src2)
  442. {
  443. instr->SetSrc2(src2);
  444. }
  445. AddInstr(instr, offset);
  446. return instr;
  447. }
  448. Js::RegSlot
  449. IRBuilderAsmJs::GetRegSlotFromVarReg(Js::RegSlot srcVarReg)
  450. {
  451. Js::RegSlot reg;
  452. if (srcVarReg < (Js::RegSlot)(AsmJsRegSlots::RegCount - 1))
  453. {
  454. reg = srcVarReg + m_firstVarConst;
  455. Assert(reg >= m_firstVarConst && reg < m_firstIntConst);
  456. }
  457. else
  458. {
  459. reg = srcVarReg - AsmJsRegSlots::RegCount + m_firstIntTemp - 1;
  460. Assert(reg >= m_firstIntTemp);
  461. }
  462. return reg;
  463. }
  464. SymID
  465. IRBuilderAsmJs::GetMappedTemp(Js::RegSlot reg)
  466. {
  467. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  468. AssertMsg(m_tempMap, "Processing non-temp reg without a temp map?");
  469. return m_tempMap[reg - m_firstIntTemp];
  470. }
  471. void
  472. IRBuilderAsmJs::SetMappedTemp(Js::RegSlot reg, SymID tempId)
  473. {
  474. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  475. AssertMsg(m_tempMap, "Processing non-temp reg without a temp map?");
  476. m_tempMap[reg - m_firstIntTemp] = tempId;
  477. }
  478. BOOL
  479. IRBuilderAsmJs::GetTempUsed(Js::RegSlot reg)
  480. {
  481. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  482. AssertMsg(m_fbvTempUsed, "Processing non-temp reg without a used BV?");
  483. return m_fbvTempUsed->Test(reg - m_firstIntTemp);
  484. }
  485. void
  486. IRBuilderAsmJs::SetTempUsed(Js::RegSlot reg, BOOL used)
  487. {
  488. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  489. AssertMsg(m_fbvTempUsed, "Processing non-temp reg without a used BV?");
  490. if (used)
  491. {
  492. m_fbvTempUsed->Set(reg - m_firstIntTemp);
  493. }
  494. else
  495. {
  496. m_fbvTempUsed->Clear(reg - m_firstIntTemp);
  497. }
  498. }
  499. BOOL
  500. IRBuilderAsmJs::RegIsTemp(Js::RegSlot reg)
  501. {
  502. return reg >= m_firstIntTemp;
  503. }
  504. BOOL
  505. IRBuilderAsmJs::RegIsVar(Js::RegSlot reg)
  506. {
  507. BOOL result = RegIsIntVar(reg) || RegIsFloatVar(reg) || RegIsDoubleVar(reg);
  508. result = result || RegIsSimd128Var(reg);
  509. return result;
  510. }
  511. BOOL
  512. IRBuilderAsmJs::RegIsIntVar(Js::RegSlot reg)
  513. {
  514. Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetIntVarCount()) + m_firstIntVar;
  515. return reg >= m_firstIntVar && reg < endVarSlotCount;
  516. }
  517. BOOL
  518. IRBuilderAsmJs::RegIsFloatVar(Js::RegSlot reg)
  519. {
  520. Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetFloatVarCount()) + m_firstFloatVar;
  521. return reg >= m_firstFloatVar && reg < endVarSlotCount;
  522. }
  523. BOOL
  524. IRBuilderAsmJs::RegIsDoubleVar(Js::RegSlot reg)
  525. {
  526. Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetDoubleVarCount()) + m_firstDoubleVar;
  527. return reg >= m_firstDoubleVar && reg < endVarSlotCount;
  528. }
  529. BOOL
  530. IRBuilderAsmJs::RegIsSimd128Var(Js::RegSlot reg)
  531. {
  532. Js::RegSlot endVarSlotCount = (Js::RegSlot)(m_asmFuncInfo->GetSimdVarCount()) + m_firstSimdVar;
  533. return reg >= m_firstSimdVar && reg < endVarSlotCount;
  534. }
  535. BOOL
  536. IRBuilderAsmJs::RegIsConstant(Js::RegSlot reg)
  537. {
  538. return (reg > 0 && reg < m_firstIntVar);
  539. }
  540. BranchReloc *
  541. IRBuilderAsmJs::AddBranchInstr(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
  542. {
  543. //
  544. // Loop jitting would be done only till the LoopEnd
  545. // Any branches beyond that offset are for the return statement
  546. //
  547. if (IsLoopBodyOuterOffset(targetOffset))
  548. {
  549. // if we have loaded the loop IP sym from the ProfiledLoopEnd then don't add it here
  550. if (!IsLoopBodyReturnIPInstr(m_lastInstr))
  551. {
  552. this->InsertLoopBodyReturnIPInstr(targetOffset, offset);
  553. }
  554. // Jump the restore StSlot and Ret instruction
  555. targetOffset = GetLoopBodyExitInstrOffset();
  556. }
  557. BranchReloc * reloc = nullptr;
  558. reloc = CreateRelocRecord(branchInstr, offset, targetOffset);
  559. AddInstr(branchInstr, offset);
  560. return reloc;
  561. }
  562. BranchReloc *
  563. IRBuilderAsmJs::CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
  564. {
  565. BranchReloc * reloc = JitAnew(m_tempAlloc, BranchReloc, branchInstr, offset, targetOffset);
  566. m_branchRelocList->Prepend(reloc);
  567. return reloc;
  568. }
  569. void
  570. IRBuilderAsmJs::BuildHeapBufferReload(uint32 offset)
  571. {
  572. // ArrayBuffer
  573. IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::ArrayReg, TyVar);
  574. IR::Opnd * srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ModuleMemReg, TyVar), Js::AsmJsModuleMemory::MemoryTableBeginOffset, TyVar, m_func);
  575. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  576. AddInstr(instr, offset);
  577. // ArrayBuffer buffer
  578. dstOpnd = BuildDstOpnd(AsmJsRegSlots::BufferReg, TyVar);
  579. srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetBufferOffset(), TyVar, m_func);
  580. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  581. AddInstr(instr, offset);
  582. // ArrayBuffer length
  583. dstOpnd = BuildDstOpnd(AsmJsRegSlots::LengthReg, TyUint32);
  584. srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetByteLengthOffset(), TyUint32, m_func);
  585. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  586. AddInstr(instr, offset);
  587. }
  588. void
  589. IRBuilderAsmJs::BuildConstantLoads()
  590. {
  591. uint32 intConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetIntConstCount();
  592. uint32 floatConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetFloatConstCount();
  593. uint32 doubleConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetDoubleConstCount();
  594. Js::Var * constTable = static_cast<Js::Var *>(m_func->GetJnFunction()->GetConstTable());
  595. // Load FrameDisplay
  596. IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::ModuleMemReg, TyVar);
  597. IR::Instr * instr = IR::Instr::New(Js::OpCode::LdAsmJsEnv, dstOpnd, m_func);
  598. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  599. // Load heap buffer
  600. if (m_asmFuncInfo->UsesHeapBuffer())
  601. {
  602. BuildHeapBufferReload(Js::Constants::NoByteCodeOffset);
  603. }
  604. uint32 regAllocated = AsmJsRegSlots::RegCount;
  605. // build int const loads
  606. int * intConstTable = reinterpret_cast<int *>(constTable + Js::AsmJsFunctionMemory::RequiredVarConstants - 1);
  607. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < intConstCount; ++reg)
  608. {
  609. int32 intConst = intConstTable[reg];
  610. IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TyInt32);
  611. Assert(RegIsConstant(reg));
  612. dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
  613. dstOpnd->SetValueType(ValueType::GetInt(false));
  614. IR::Instr *instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, IR::IntConstOpnd::New(intConst, TyInt32, m_func), m_func);
  615. if (dstOpnd->m_sym->IsSingleDef())
  616. {
  617. dstOpnd->m_sym->SetIsIntConst(intConst);
  618. }
  619. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  620. ++regAllocated;
  621. }
  622. // do the same for float constants
  623. // Space for F0
  624. ++regAllocated;
  625. float * floatConstTable = reinterpret_cast<float *>(intConstTable + intConstCount);
  626. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < floatConstCount; ++reg)
  627. {
  628. float floatConst = floatConstTable[reg];
  629. IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TyFloat32);
  630. Assert(RegIsConstant(reg));
  631. dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
  632. dstOpnd->SetValueType(ValueType::Float);
  633. IR::Instr *instr = IR::Instr::New(Js::OpCode::LdC_F8_R8, dstOpnd, IR::FloatConstOpnd::New(floatConst, TyFloat32, m_func), m_func);
  634. #if _M_IX86
  635. if (dstOpnd->m_sym->IsSingleDef())
  636. {
  637. dstOpnd->m_sym->SetIsFloatConst();
  638. }
  639. #endif
  640. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  641. ++regAllocated;
  642. }
  643. // ... and doubles
  644. // Space for D0
  645. ++regAllocated;
  646. double * doubleConstTable = reinterpret_cast<double *>(floatConstTable + floatConstCount);
  647. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < doubleConstCount; ++reg)
  648. {
  649. double doubleConst = doubleConstTable[reg];
  650. IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TyFloat64);
  651. Assert(RegIsConstant(reg));
  652. dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
  653. dstOpnd->SetValueType(ValueType::Float);
  654. IR::Instr *instr = IR::Instr::New(Js::OpCode::LdC_F8_R8, dstOpnd, IR::FloatConstOpnd::New(doubleConst, TyFloat64, m_func), m_func);
  655. #if _M_IX86
  656. if (dstOpnd->m_sym->IsSingleDef())
  657. {
  658. dstOpnd->m_sym->SetIsFloatConst();
  659. }
  660. #endif
  661. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  662. ++regAllocated;
  663. }
  664. uint32 simdConstCount = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetSimdConstCount();
  665. // Space for SIMD0
  666. ++regAllocated;
  667. AsmJsSIMDValue *simdConstTable = reinterpret_cast<AsmJsSIMDValue *>(doubleConstTable + doubleConstCount);
  668. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < simdConstCount; ++reg)
  669. {
  670. AsmJsSIMDValue simdConst = simdConstTable[reg];
  671. // 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.
  672. IR::RegOpnd * dstOpnd = BuildDstOpnd(regAllocated + Js::FunctionBody::FirstRegSlot, TySimd128F4);
  673. Assert(RegIsConstant(reg));
  674. dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
  675. // 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.
  676. // However, for ASMJS, the IR type is enough to tell us it is a Simd128 value.
  677. dstOpnd->SetValueType(ValueType::UninitializedObject);
  678. IR::Instr *instr = IR::Instr::New(Js::OpCode::Simd128_LdC, dstOpnd, IR::Simd128ConstOpnd::New(simdConst, TySimd128F4, m_func), m_func);
  679. #if _M_IX86
  680. if (dstOpnd->m_sym->IsSingleDef())
  681. {
  682. dstOpnd->m_sym->SetIsSimd128Const();
  683. }
  684. #endif
  685. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  686. ++regAllocated;
  687. }
  688. }
  689. void
  690. IRBuilderAsmJs::BuildImplicitArgIns()
  691. {
  692. int32 intArgInCount = 0;
  693. int32 floatArgInCount = 0;
  694. int32 doubleArgInCount = 0;
  695. int32 simd128ArgInCount = 0;
  696. // formal params are offset from EBP by the EBP chain, return address, and function object
  697. int32 offset = 3 * MachPtr;
  698. for (Js::ArgSlot i = 1; i < m_func->GetJnFunction()->GetInParamsCount(); ++i)
  699. {
  700. StackSym * symSrc = nullptr;
  701. IR::Opnd * srcOpnd = nullptr;
  702. IR::RegOpnd * dstOpnd = nullptr;
  703. IR::Instr * instr = nullptr;
  704. // TODO: double args are not aligned on stack
  705. Js::AsmJsVarType varType = m_func->GetJnFunction()->GetAsmJsFunctionInfo()->GetArgType(i - 1);
  706. switch (varType.which())
  707. {
  708. case Js::AsmJsVarType::Which::Int:
  709. symSrc = StackSym::NewParamSlotSym(i, m_func, TyInt32);
  710. m_func->SetArgOffset(symSrc, offset);
  711. srcOpnd = IR::SymOpnd::New(symSrc, TyInt32, m_func);
  712. dstOpnd = BuildDstOpnd(m_firstIntVar + intArgInCount, TyInt32);
  713. dstOpnd->SetValueType(ValueType::GetInt(false));
  714. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  715. offset += MachPtr;
  716. ++intArgInCount;
  717. break;
  718. case Js::AsmJsVarType::Which::Float:
  719. symSrc = StackSym::NewParamSlotSym(i, m_func, TyFloat32);
  720. m_func->SetArgOffset(symSrc, offset);
  721. srcOpnd = IR::SymOpnd::New(symSrc, TyFloat32, m_func);
  722. dstOpnd = BuildDstOpnd(m_firstFloatVar + floatArgInCount, TyFloat32);
  723. dstOpnd->SetValueType(ValueType::Float);
  724. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  725. offset += MachPtr;
  726. ++floatArgInCount;
  727. break;
  728. case Js::AsmJsVarType::Which::Double:
  729. symSrc = StackSym::NewParamSlotSym(i, m_func, TyFloat64);
  730. m_func->SetArgOffset(symSrc, offset);
  731. srcOpnd = IR::SymOpnd::New(symSrc, TyFloat64, m_func);
  732. dstOpnd = BuildDstOpnd(m_firstDoubleVar + doubleArgInCount, TyFloat64);
  733. dstOpnd->SetValueType(ValueType::Float);
  734. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  735. offset += MachDouble;
  736. ++doubleArgInCount;
  737. break;
  738. case Js::AsmJsVarType::Which::Float32x4:
  739. case Js::AsmJsVarType::Which::Int32x4:
  740. case Js::AsmJsVarType::Which::Float64x2:
  741. {
  742. IRType argType;
  743. if (varType.which() == Js::AsmJsVarType::Which::Float32x4)
  744. {
  745. argType = TySimd128F4;
  746. }
  747. else if (varType.which() == Js::AsmJsVarType::Which::Int32x4)
  748. {
  749. argType = TySimd128I4;
  750. }
  751. else
  752. {
  753. Assert(varType.which() == Js::AsmJsVarType::Which::Float64x2);
  754. argType = TySimd128D2;
  755. }
  756. symSrc = StackSym::NewParamSlotSym(i, m_func, argType);
  757. m_func->SetArgOffset(symSrc, offset);
  758. srcOpnd = IR::SymOpnd::New(symSrc, argType, m_func);
  759. dstOpnd = BuildDstOpnd(m_firstSimdVar + simd128ArgInCount, argType);
  760. dstOpnd->SetValueType(ValueType::UninitializedObject);
  761. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  762. offset += sizeof(AsmJsSIMDValue);
  763. ++simd128ArgInCount;
  764. break;
  765. }
  766. default:
  767. Assume(UNREACHED);
  768. }
  769. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  770. }
  771. }
  772. void
  773. IRBuilderAsmJs::InsertLabels()
  774. {
  775. AssertMsg(m_branchRelocList, "Malformed branch reloc list");
  776. SList<BranchReloc *>::Iterator iter(m_branchRelocList);
  777. while (iter.Next())
  778. {
  779. IR::LabelInstr * labelInstr;
  780. BranchReloc * reloc = iter.Data();
  781. IR::BranchInstr * branchInstr = reloc->GetBranchInstr();
  782. uint offset = reloc->GetOffset();
  783. uint const branchOffset = reloc->GetBranchOffset();
  784. Assert(!IsLoopBody() || offset <= GetLoopBodyExitInstrOffset());
  785. if (branchInstr->m_opcode == Js::OpCode::MultiBr)
  786. {
  787. IR::MultiBranchInstr * multiBranchInstr = branchInstr->AsBranchInstr()->AsMultiBrInstr();
  788. multiBranchInstr->UpdateMultiBrTargetOffsets([&](uint32 offset) -> IR::LabelInstr *
  789. {
  790. labelInstr = this->CreateLabel(branchInstr, offset);
  791. multiBranchInstr->ChangeLabelRef(nullptr, labelInstr);
  792. return labelInstr;
  793. });
  794. }
  795. else
  796. {
  797. labelInstr = CreateLabel(branchInstr, offset);
  798. branchInstr->SetTarget(labelInstr);
  799. }
  800. if (!reloc->IsNotBackEdge() && branchOffset >= offset)
  801. {
  802. labelInstr->m_isLoopTop = true;
  803. }
  804. }
  805. }
  806. IR::LabelInstr *
  807. IRBuilderAsmJs::CreateLabel(IR::BranchInstr * branchInstr, uint & offset)
  808. {
  809. IR::Instr * targetInstr = nullptr;
  810. while (targetInstr == nullptr)
  811. {
  812. targetInstr = m_offsetToInstruction[offset];
  813. Assert(offset < m_offsetToInstructionCount);
  814. ++offset;
  815. }
  816. IR::Instr *instrPrev = targetInstr->m_prev;
  817. if (instrPrev)
  818. {
  819. instrPrev = targetInstr->GetPrevRealInstrOrLabel();
  820. }
  821. IR::LabelInstr * labelInstr;
  822. if (instrPrev && instrPrev->IsLabelInstr())
  823. {
  824. // Found an existing label at the right offset. Just reuse it.
  825. labelInstr = instrPrev->AsLabelInstr();
  826. }
  827. else
  828. {
  829. // No label at the desired offset. Create one.
  830. labelInstr = IR::LabelInstr::New(Js::OpCode::Label, m_func);
  831. labelInstr->SetByteCodeOffset(offset);
  832. if (instrPrev)
  833. {
  834. instrPrev->InsertAfter(labelInstr);
  835. }
  836. else
  837. {
  838. targetInstr->InsertBefore(labelInstr);
  839. }
  840. }
  841. return labelInstr;
  842. }
  843. void
  844. IRBuilderAsmJs::BuildEmpty(Js::OpCodeAsmJs newOpcode, uint32 offset)
  845. {
  846. m_jnReader.Empty();
  847. IR::Instr * instr = nullptr;
  848. IR::RegOpnd * regOpnd = nullptr;
  849. Js::RegSlot retSlot;
  850. switch (newOpcode)
  851. {
  852. case Js::OpCodeAsmJs::Ret:
  853. instr = IR::Instr::New(Js::OpCode::Ret, m_func);
  854. switch (m_asmFuncInfo->GetReturnType().which())
  855. {
  856. case Js::AsmJsRetType::Which::Signed:
  857. retSlot = GetRegSlotFromIntReg(0);
  858. regOpnd = BuildDstOpnd(retSlot, TyInt32);
  859. regOpnd->SetValueType(ValueType::GetInt(false));
  860. break;
  861. case Js::AsmJsRetType::Which::Float:
  862. retSlot = GetRegSlotFromFloatReg(0);
  863. regOpnd = BuildDstOpnd(retSlot, TyFloat32);
  864. regOpnd->SetValueType(ValueType::Float);
  865. break;
  866. case Js::AsmJsRetType::Which::Double:
  867. retSlot = GetRegSlotFromDoubleReg(0);
  868. regOpnd = BuildDstOpnd(retSlot, TyFloat64);
  869. regOpnd->SetValueType(ValueType::Float);
  870. break;
  871. case Js::AsmJsRetType::Which::Void:
  872. retSlot = GetRegSlotFromVarReg(0);
  873. regOpnd = BuildDstOpnd(retSlot, TyVar);
  874. break;
  875. case Js::AsmJsRetType::Which::Float32x4:
  876. retSlot = GetRegSlotFromSimd128Reg(0);
  877. regOpnd = BuildDstOpnd(retSlot, TySimd128F4);
  878. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  879. break;
  880. case Js::AsmJsRetType::Which::Int32x4:
  881. retSlot = GetRegSlotFromSimd128Reg(0);
  882. regOpnd = BuildDstOpnd(retSlot, TySimd128I4);
  883. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  884. break;
  885. case Js::AsmJsRetType::Which::Float64x2:
  886. retSlot = GetRegSlotFromSimd128Reg(0);
  887. regOpnd = BuildDstOpnd(retSlot, TySimd128D2);
  888. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  889. break;
  890. default:
  891. Assume(UNREACHED);
  892. }
  893. instr->SetSrc1(regOpnd);
  894. AddInstr(instr, offset);
  895. break;
  896. case Js::OpCodeAsmJs::Label:
  897. // NOP
  898. break;
  899. default:
  900. Assume(UNREACHED);
  901. }
  902. }
  903. template <typename SizePolicy>
  904. void
  905. IRBuilderAsmJs::BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset)
  906. {
  907. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  908. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_ElementSlot<SizePolicy>>();
  909. BuildElementSlot(newOpcode, offset, layout->SlotIndex, layout->Value, layout->Instance);
  910. }
  911. template <typename SizePolicy>
  912. void
  913. IRBuilderAsmJs::BuildAsmUnsigned1(Js::OpCodeAsmJs newOpcode, uint value)
  914. {
  915. // we do not support counter in loop body ,just read the layout here
  916. m_jnReader.GetLayout<Js::OpLayoutT_AsmUnsigned1<SizePolicy>>();
  917. }
  918. void
  919. IRBuilderAsmJs::BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 slotIndex, Js::RegSlot value, Js::RegSlot instance)
  920. {
  921. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  922. Assert(instance == 1 || newOpcode == Js::OpCodeAsmJs::LdArr_Func);
  923. Js::RegSlot valueRegSlot;
  924. IR::Opnd * slotOpnd;
  925. IR::RegOpnd * regOpnd;
  926. IR::Instr * instr = nullptr;
  927. switch (newOpcode)
  928. {
  929. case Js::OpCodeAsmJs::LdSlot_Int:
  930. valueRegSlot = GetRegSlotFromIntReg(value);
  931. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyInt32);
  932. regOpnd = BuildDstOpnd(valueRegSlot, TyInt32);
  933. regOpnd->SetValueType(ValueType::GetInt(false));
  934. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  935. break;
  936. case Js::OpCodeAsmJs::LdSlot_Flt:
  937. valueRegSlot = GetRegSlotFromFloatReg(value);
  938. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat32);
  939. regOpnd = BuildDstOpnd(valueRegSlot, TyFloat32);
  940. regOpnd->SetValueType(ValueType::Float);
  941. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  942. break;
  943. case Js::OpCodeAsmJs::LdSlot_Db:
  944. valueRegSlot = GetRegSlotFromDoubleReg(value);
  945. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat64);
  946. regOpnd = BuildDstOpnd(valueRegSlot, TyFloat64);
  947. regOpnd->SetValueType(ValueType::Float);
  948. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  949. break;
  950. case Js::OpCodeAsmJs::LdSlot:
  951. valueRegSlot = GetRegSlotFromVarReg(value);
  952. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlotArray, TyVar);
  953. regOpnd = BuildDstOpnd(valueRegSlot, TyVar);
  954. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  955. break;
  956. case Js::OpCodeAsmJs::LdSlotArr:
  957. valueRegSlot = GetRegSlotFromVarReg(value);
  958. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyVar);
  959. regOpnd = BuildDstOpnd(valueRegSlot, TyVar);
  960. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  961. break;
  962. case Js::OpCodeAsmJs::StSlot_Int:
  963. valueRegSlot = GetRegSlotFromIntReg(value);
  964. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyInt32);
  965. regOpnd = BuildSrcOpnd(valueRegSlot, TyInt32);
  966. regOpnd->SetValueType(ValueType::GetInt(false));
  967. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  968. break;
  969. case Js::OpCodeAsmJs::StSlot_Flt:
  970. valueRegSlot = GetRegSlotFromFloatReg(value);
  971. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat32);
  972. regOpnd = BuildSrcOpnd(valueRegSlot, TyFloat32);
  973. regOpnd->SetValueType(ValueType::Float);
  974. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  975. break;
  976. case Js::OpCodeAsmJs::StSlot_Db:
  977. valueRegSlot = GetRegSlotFromDoubleReg(value);
  978. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyFloat64);
  979. regOpnd = BuildSrcOpnd(valueRegSlot, TyFloat64);
  980. regOpnd->SetValueType(ValueType::Float);
  981. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  982. break;
  983. case Js::OpCodeAsmJs::LdArr_Func:
  984. {
  985. IR::RegOpnd * baseOpnd = BuildSrcOpnd(GetRegSlotFromVarReg(instance), TyVar);
  986. IR::RegOpnd * indexOpnd = BuildSrcOpnd(GetRegSlotFromIntReg(slotIndex), TyUint32);
  987. // we multiply indexOpnd by 2^scale for the actual location
  988. #if _M_IX86_OR_ARM32
  989. byte scale = 2;
  990. #elif _M_X64_OR_ARM64
  991. byte scale = 3;
  992. #endif
  993. IR::IndirOpnd * indirOpnd = IR::IndirOpnd::New(baseOpnd, indexOpnd, scale, TyVar, m_func);
  994. regOpnd = BuildDstOpnd(GetRegSlotFromVarReg(value), TyVar);
  995. instr = IR::Instr::New(Js::OpCode::Ld_A, regOpnd, indirOpnd, m_func);
  996. break;
  997. }
  998. case Js::OpCodeAsmJs::Simd128_LdSlot_I4:
  999. {
  1000. valueRegSlot = GetRegSlotFromSimd128Reg(value);
  1001. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128I4);
  1002. regOpnd = BuildDstOpnd(valueRegSlot, TySimd128I4);
  1003. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  1004. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  1005. break;
  1006. }
  1007. case Js::OpCodeAsmJs::Simd128_LdSlot_F4:
  1008. {
  1009. valueRegSlot = GetRegSlotFromSimd128Reg(value);
  1010. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128F4);
  1011. regOpnd = BuildDstOpnd(valueRegSlot, TySimd128F4);
  1012. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  1013. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  1014. break;
  1015. }
  1016. case Js::OpCodeAsmJs::Simd128_LdSlot_D2:
  1017. {
  1018. valueRegSlot = GetRegSlotFromSimd128Reg(value);
  1019. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128D2);
  1020. regOpnd = BuildDstOpnd(valueRegSlot, TySimd128D2);
  1021. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  1022. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  1023. break;
  1024. }
  1025. case Js::OpCodeAsmJs::Simd128_StSlot_I4:
  1026. {
  1027. valueRegSlot = GetRegSlotFromSimd128Reg(value);
  1028. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128I4);
  1029. regOpnd = BuildSrcOpnd(valueRegSlot, TySimd128I4);
  1030. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  1031. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  1032. break;
  1033. }
  1034. case Js::OpCodeAsmJs::Simd128_StSlot_F4:
  1035. {
  1036. valueRegSlot = GetRegSlotFromSimd128Reg(value);
  1037. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128F4);
  1038. regOpnd = BuildSrcOpnd(valueRegSlot, TySimd128F4);
  1039. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  1040. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  1041. break;
  1042. }
  1043. case Js::OpCodeAsmJs::Simd128_StSlot_D2:
  1044. {
  1045. valueRegSlot = GetRegSlotFromSimd128Reg(value);
  1046. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TySimd128D2);
  1047. regOpnd = BuildSrcOpnd(valueRegSlot, TySimd128D2);
  1048. regOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  1049. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  1050. break;
  1051. }
  1052. default:
  1053. Assume(UNREACHED);
  1054. }
  1055. AddInstr(instr, offset);
  1056. }
  1057. void
  1058. IRBuilderAsmJs::BuildStartCall(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1059. {
  1060. Assert(!OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1061. const unaligned Js::OpLayoutStartCall * layout = m_jnReader.StartCall();
  1062. IR::RegOpnd * dstOpnd = IR::RegOpnd::New(TyVar, m_func);
  1063. IR::IntConstOpnd * srcOpnd = IR::IntConstOpnd::New(layout->ArgCount, TyInt32, m_func);
  1064. IR::Instr * instr = nullptr;
  1065. StackSym * symDst = nullptr;
  1066. IR::SymOpnd * argDst = nullptr;
  1067. IR::AddrOpnd * addrOpnd = nullptr;
  1068. switch (newOpcode)
  1069. {
  1070. case Js::OpCodeAsmJs::I_StartCall:
  1071. instr = IR::Instr::New(Js::OpCode::StartCall, dstOpnd, srcOpnd, m_func);
  1072. AddInstr(instr, offset);
  1073. // save this so we can calculate arg offsets later on
  1074. m_argOffsetStack->Push(layout->ArgCount);
  1075. m_argStack->Push(instr);
  1076. break;
  1077. case Js::OpCodeAsmJs::StartCall:
  1078. instr = IR::Instr::New(Js::OpCode::StartCall, dstOpnd, srcOpnd, m_func);
  1079. AddInstr(instr, offset);
  1080. m_argStack->Push(instr);
  1081. // also need to add undefined as arg0
  1082. addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContext()->GetLibrary()->GetUndefined(), IR::AddrOpndKindDynamicVar, m_func, true);
  1083. addrOpnd->SetValueType(ValueType::Undefined);
  1084. symDst = m_func->m_symTable->GetArgSlotSym(1);
  1085. argDst = IR::SymOpnd::New(symDst, TyVar, m_func);
  1086. instr = IR::Instr::New(Js::OpCode::ArgOut_A, argDst, addrOpnd, m_func);
  1087. AddInstr(instr, offset);
  1088. m_argStack->Push(instr);
  1089. break;
  1090. default:
  1091. Assume(UNREACHED);
  1092. }
  1093. }
  1094. template <typename SizePolicy>
  1095. void
  1096. IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1097. {
  1098. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1099. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmTypedArr<SizePolicy>>();
  1100. BuildAsmTypedArr(newOpcode, offset, layout->SlotIndex, layout->Value, layout->ViewType);
  1101. }
  1102. void
  1103. IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, int8 viewType)
  1104. {
  1105. IRType type = TyInt32;
  1106. Js::RegSlot valueRegSlot = Js::Constants::NoRegister;
  1107. bool isLd = newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::LdArrConst;
  1108. Js::OpCode op = Js::OpCode::InvalidOpCode;
  1109. ValueType arrayType;
  1110. switch (viewType)
  1111. {
  1112. case Js::ArrayBufferView::TYPE_INT8:
  1113. valueRegSlot = GetRegSlotFromIntReg(value);
  1114. arrayType = ValueType::GetObject(ObjectType::Int8Array);
  1115. type = TyInt8;
  1116. op = isLd ? Js::OpCode::LdInt8ArrViewElem : Js::OpCode::StInt8ArrViewElem;
  1117. break;
  1118. case Js::ArrayBufferView::TYPE_UINT8:
  1119. valueRegSlot = GetRegSlotFromIntReg(value);
  1120. arrayType = ValueType::GetObject(ObjectType::Uint8Array);
  1121. type = TyUint8;
  1122. op = isLd ? Js::OpCode::LdUInt8ArrViewElem : Js::OpCode::StUInt8ArrViewElem;
  1123. break;
  1124. case Js::ArrayBufferView::TYPE_INT16:
  1125. valueRegSlot = GetRegSlotFromIntReg(value);
  1126. arrayType = ValueType::GetObject(ObjectType::Int16Array);
  1127. type = TyInt16;
  1128. op = isLd ? Js::OpCode::LdInt16ArrViewElem : Js::OpCode::StInt16ArrViewElem;
  1129. break;
  1130. case Js::ArrayBufferView::TYPE_UINT16:
  1131. valueRegSlot = GetRegSlotFromIntReg(value);
  1132. arrayType = ValueType::GetObject(ObjectType::Uint16Array);
  1133. type = TyUint16;
  1134. op = isLd ? Js::OpCode::LdUInt16ArrViewElem : Js::OpCode::StUInt16ArrViewElem;
  1135. break;
  1136. case Js::ArrayBufferView::TYPE_INT32:
  1137. valueRegSlot = GetRegSlotFromIntReg(value);
  1138. arrayType = ValueType::GetObject(ObjectType::Int32Array);
  1139. type = TyInt32;
  1140. op = isLd ? Js::OpCode::LdInt32ArrViewElem : Js::OpCode::StInt32ArrViewElem;
  1141. break;
  1142. case Js::ArrayBufferView::TYPE_UINT32:
  1143. valueRegSlot = GetRegSlotFromIntReg(value);
  1144. arrayType = ValueType::GetObject(ObjectType::Uint32Array);
  1145. type = TyUint32;
  1146. op = isLd ? Js::OpCode::LdUInt32ArrViewElem : Js::OpCode::StUInt32ArrViewElem;
  1147. break;
  1148. case Js::ArrayBufferView::TYPE_FLOAT32:
  1149. valueRegSlot = GetRegSlotFromFloatReg(value);
  1150. arrayType = ValueType::GetObject(ObjectType::Float32Array);
  1151. type = TyFloat32;
  1152. op = isLd ? Js::OpCode::LdFloat32ArrViewElem : Js::OpCode::StFloat32ArrViewElem;
  1153. break;
  1154. case Js::ArrayBufferView::TYPE_FLOAT64:
  1155. valueRegSlot = GetRegSlotFromDoubleReg(value);
  1156. arrayType = ValueType::GetObject(ObjectType::Float64Array);
  1157. type = TyFloat64;
  1158. op = isLd ? Js::OpCode::LdFloat64ArrViewElem : Js::OpCode::StFloat64ArrViewElem;
  1159. break;
  1160. default:
  1161. Assume(UNREACHED);
  1162. }
  1163. IR::Instr * instr = nullptr;
  1164. IR::Instr * maskInstr = nullptr;
  1165. IR::RegOpnd * regOpnd = nullptr;
  1166. IR::IndirOpnd * indirOpnd = nullptr;
  1167. if (newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::StArr)
  1168. {
  1169. uint32 mask = 0;
  1170. switch (type)
  1171. {
  1172. case TyInt8:
  1173. case TyUint8:
  1174. // don't need to mask
  1175. break;
  1176. case TyInt16:
  1177. case TyUint16:
  1178. mask = (uint32)~1;
  1179. break;
  1180. case TyInt32:
  1181. case TyUint32:
  1182. case TyFloat32:
  1183. mask = (uint32)~3;
  1184. break;
  1185. case TyFloat64:
  1186. mask = (uint32)~7;
  1187. break;
  1188. default:
  1189. Assume(UNREACHED);
  1190. }
  1191. Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
  1192. IR::RegOpnd * maskedOpnd = nullptr;
  1193. if (mask)
  1194. {
  1195. maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
  1196. maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
  1197. }
  1198. else
  1199. {
  1200. maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
  1201. }
  1202. indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), maskedOpnd, type, m_func);
  1203. indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
  1204. }
  1205. switch (newOpcode)
  1206. {
  1207. case Js::OpCodeAsmJs::LdArr:
  1208. if (IRType_IsFloat(type))
  1209. {
  1210. regOpnd = BuildDstOpnd(valueRegSlot, type);
  1211. regOpnd->SetValueType(ValueType::Float);
  1212. }
  1213. else
  1214. {
  1215. regOpnd = BuildDstOpnd(valueRegSlot, TyInt32);
  1216. regOpnd->SetValueType(ValueType::GetInt(false));
  1217. }
  1218. instr = IR::Instr::New(op, regOpnd, indirOpnd, m_func);
  1219. break;
  1220. case Js::OpCodeAsmJs::LdArrConst:
  1221. if (IRType_IsFloat(type))
  1222. {
  1223. regOpnd = BuildDstOpnd(valueRegSlot, type);
  1224. regOpnd->SetValueType(ValueType::Float);
  1225. }
  1226. else
  1227. {
  1228. regOpnd = BuildDstOpnd(valueRegSlot, TyInt32);
  1229. regOpnd->SetValueType(ValueType::GetInt(false));
  1230. }
  1231. indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), slotIndex, type, m_func);
  1232. indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
  1233. instr = IR::Instr::New(op, regOpnd, indirOpnd, m_func);
  1234. break;
  1235. case Js::OpCodeAsmJs::StArr:
  1236. if (IRType_IsFloat(type))
  1237. {
  1238. regOpnd = BuildSrcOpnd(valueRegSlot, type);
  1239. regOpnd->SetValueType(ValueType::Float);
  1240. }
  1241. else
  1242. {
  1243. regOpnd = BuildSrcOpnd(valueRegSlot, TyInt32);
  1244. regOpnd->SetValueType(ValueType::GetInt(false));
  1245. }
  1246. instr = IR::Instr::New(op, indirOpnd, regOpnd, m_func);
  1247. break;
  1248. case Js::OpCodeAsmJs::StArrConst:
  1249. if (IRType_IsFloat(type))
  1250. {
  1251. regOpnd = BuildSrcOpnd(valueRegSlot, type);
  1252. regOpnd->SetValueType(ValueType::Float);
  1253. }
  1254. else
  1255. {
  1256. regOpnd = BuildSrcOpnd(valueRegSlot, TyInt32);
  1257. regOpnd->SetValueType(ValueType::GetInt(false));
  1258. }
  1259. indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), slotIndex, type, m_func);
  1260. indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
  1261. instr = IR::Instr::New(op, indirOpnd, regOpnd, m_func);
  1262. break;
  1263. default:
  1264. Assume(UNREACHED);
  1265. }
  1266. // constant loads won't have mask instr
  1267. if (maskInstr)
  1268. {
  1269. AddInstr(maskInstr, offset);
  1270. }
  1271. #if _M_IX86
  1272. instr->SetSrc2(BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32));
  1273. #endif
  1274. AddInstr(instr, offset);
  1275. }
  1276. template <typename SizePolicy>
  1277. void
  1278. IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1279. {
  1280. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1281. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmCall<SizePolicy>>();
  1282. BuildAsmCall(newOpcode, offset, layout->ArgCount, layout->Return, layout->Function, layout->ReturnType);
  1283. }
  1284. void
  1285. IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSlot argCount, Js::RegSlot ret, Js::RegSlot function, int8 returnType)
  1286. {
  1287. #if DBG
  1288. int count = 0;
  1289. #endif
  1290. IR::Instr * instr = nullptr;
  1291. IR::RegOpnd * dstOpnd = nullptr;
  1292. IR::Opnd * srcOpnd = nullptr;
  1293. Js::RegSlot dstRegSlot;
  1294. Js::RegSlot srcRegSlot;
  1295. int32 argOffset = 0;
  1296. switch (newOpcode)
  1297. {
  1298. case Js::OpCodeAsmJs::I_Call:
  1299. srcRegSlot = GetRegSlotFromVarReg(function);
  1300. srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1301. switch ((Js::AsmJsRetType::Which)returnType)
  1302. {
  1303. case Js::AsmJsRetType::Which::Signed:
  1304. dstRegSlot = GetRegSlotFromIntReg(ret);
  1305. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1306. dstOpnd->SetValueType(ValueType::GetInt(false));
  1307. break;
  1308. case Js::AsmJsRetType::Which::Float:
  1309. dstRegSlot = GetRegSlotFromFloatReg(ret);
  1310. dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  1311. dstOpnd->SetValueType(ValueType::Float);
  1312. break;
  1313. case Js::AsmJsRetType::Which::Double:
  1314. dstRegSlot = GetRegSlotFromDoubleReg(ret);
  1315. dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1316. dstOpnd->SetValueType(ValueType::Float);
  1317. break;
  1318. case Js::AsmJsRetType::Which::Void:
  1319. break;
  1320. case Js::AsmJsRetType::Which::Float32x4:
  1321. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1322. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  1323. break;
  1324. case Js::AsmJsRetType::Which::Int32x4:
  1325. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1326. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  1327. break;
  1328. case Js::AsmJsRetType::Which::Float64x2:
  1329. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1330. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  1331. break;
  1332. default:
  1333. Assume(UNREACHED);
  1334. }
  1335. instr = IR::Instr::New(Js::OpCode::AsmJsCallI, m_func);
  1336. instr->SetSrc1(srcOpnd);
  1337. if (dstOpnd)
  1338. {
  1339. instr->SetDst(dstOpnd);
  1340. }
  1341. argOffset = m_argOffsetStack->Pop();
  1342. argOffset -= MachPtr;
  1343. break;
  1344. case Js::OpCodeAsmJs::Call:
  1345. srcRegSlot = GetRegSlotFromVarReg(function);
  1346. srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1347. dstRegSlot = GetRegSlotFromVarReg(ret);
  1348. dstOpnd = BuildDstOpnd(dstRegSlot, TyVar);
  1349. instr = IR::Instr::New(Js::OpCode::AsmJsCallE, dstOpnd, srcOpnd, m_func);
  1350. break;
  1351. default:
  1352. Assume(UNREACHED);
  1353. }
  1354. AddInstr(instr, offset);
  1355. IR::Instr * argInstr = nullptr;
  1356. IR::Instr * prevInstr = instr;
  1357. for (argInstr = m_argStack->Pop(); argInstr && argInstr->m_opcode != Js::OpCode::StartCall; argInstr = m_argStack->Pop())
  1358. {
  1359. if (newOpcode == Js::OpCodeAsmJs::I_Call)
  1360. {
  1361. #if _M_IX86
  1362. argOffset -= argInstr->GetDst()->GetSize();
  1363. #elif _M_X64
  1364. argOffset -= (argInstr->GetDst()->GetSize() <= MachPtr ? MachPtr : argInstr->GetDst()->GetSize());
  1365. #else
  1366. Assert(UNREACHED);
  1367. #endif
  1368. argInstr->GetDst()->GetStackSym()->m_offset = argOffset;
  1369. }
  1370. // associate the ArgOuts with this call via src2
  1371. prevInstr->SetSrc2(argInstr->GetDst());
  1372. prevInstr = argInstr;
  1373. #if defined(_M_X64)
  1374. if (m_func->GetScriptContext()->GetConfig()->IsSimdjsEnabled())
  1375. {
  1376. m_tempList->Push(argInstr);
  1377. }
  1378. #endif
  1379. #if DBG
  1380. count++;
  1381. #endif
  1382. }
  1383. Assert(argOffset == 0);
  1384. AnalysisAssert(argInstr);
  1385. prevInstr->SetSrc2(argInstr->GetDst());
  1386. #if defined(_M_X64)
  1387. // Without SIMD vars, all args are Var in size. So offset in Var = arg position in args list.
  1388. // 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.
  1389. if (m_func->GetScriptContext()->GetConfig()->IsSimdjsEnabled())
  1390. {
  1391. IR::Instr *instr;
  1392. for (uint i = 1; !m_tempList->Empty(); i++)
  1393. {
  1394. instr = m_tempList->Pop();
  1395. // record argument position and make room for implicit args
  1396. instr->GetDst()->GetStackSym()->m_argPosition = i;
  1397. if (newOpcode == Js::OpCodeAsmJs::I_Call)
  1398. {
  1399. // implicit func obj arg
  1400. instr->GetDst()->GetStackSym()->m_argPosition += 1;
  1401. }
  1402. else
  1403. {
  1404. // implicit func obj + callInfo args
  1405. Assert(newOpcode == Js::OpCodeAsmJs::Call);
  1406. instr->GetDst()->GetStackSym()->m_argPosition += 2;
  1407. }
  1408. }
  1409. }
  1410. #endif
  1411. if (m_func->m_argSlotsForFunctionsCalled < argCount)
  1412. {
  1413. m_func->m_argSlotsForFunctionsCalled = argCount;
  1414. }
  1415. if (m_asmFuncInfo->UsesHeapBuffer())
  1416. {
  1417. // if heap buffer can change, then we will insert reload after each call
  1418. if (!m_asmFuncInfo->IsHeapBufferConst())
  1419. {
  1420. BuildHeapBufferReload(offset);
  1421. }
  1422. // after foreign function call, we need to make sure that the heap hasn't been detached
  1423. if (newOpcode == Js::OpCodeAsmJs::Call)
  1424. {
  1425. IR::Instr * instr = IR::Instr::New(Js::OpCode::ArrayDetachedCheck, m_func);
  1426. instr->SetSrc1(IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetIsDetachedOffset(), TyInt8, m_func));
  1427. AddInstr(instr, offset);
  1428. }
  1429. }
  1430. }
  1431. void
  1432. IRBuilderAsmJs::BuildAsmBr(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1433. {
  1434. Assert(!OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1435. const unaligned Js::OpLayoutAsmBr * branchInsn = m_jnReader.AsmBr();
  1436. uint targetOffset = m_jnReader.GetCurrentOffset() + branchInsn->RelativeJumpOffset;
  1437. if (newOpcode == Js::OpCodeAsmJs::EndSwitch_Int)
  1438. {
  1439. m_switchBuilder.EndSwitch(offset, targetOffset);
  1440. return;
  1441. }
  1442. IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::Br, NULL, m_func);
  1443. AddBranchInstr(branchInstr, offset, targetOffset);
  1444. }
  1445. template <typename SizePolicy>
  1446. void
  1447. IRBuilderAsmJs::BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1448. {
  1449. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1450. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmReg1<SizePolicy>>();
  1451. BuildAsmReg1(newOpcode, offset, layout->R0);
  1452. }
  1453. void
  1454. IRBuilderAsmJs::BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg)
  1455. {
  1456. Assert(newOpcode == Js::OpCodeAsmJs::LdUndef);
  1457. Js::RegSlot dstRegSlot = GetRegSlotFromVarReg(dstReg);
  1458. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyVar);
  1459. if (dstOpnd->m_sym->m_isSingleDef)
  1460. {
  1461. dstOpnd->m_sym->m_isConst = true;
  1462. dstOpnd->m_sym->m_isNotInt = true;
  1463. }
  1464. IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContext()->GetLibrary()->GetUndefined(), IR::AddrOpndKindDynamicVar, m_func, true);
  1465. addrOpnd->SetValueType(ValueType::Undefined);
  1466. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, addrOpnd, m_func);
  1467. AddInstr(instr, offset);
  1468. }
  1469. template <typename SizePolicy>
  1470. void
  1471. IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1472. {
  1473. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1474. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Double1<SizePolicy>>();
  1475. BuildInt1Double1(newOpcode, offset, layout->I0, layout->D1);
  1476. }
  1477. void
  1478. IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstIntReg, Js::RegSlot srcDoubleReg)
  1479. {
  1480. Assert(newOpcode == Js::OpCodeAsmJs::Conv_DTI);
  1481. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstIntReg);
  1482. Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(srcDoubleReg);
  1483. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  1484. srcOpnd->SetValueType(ValueType::Float);
  1485. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1486. dstOpnd->SetValueType(ValueType::GetInt(false));
  1487. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1488. AddInstr(instr, offset);
  1489. }
  1490. template <typename SizePolicy>
  1491. void
  1492. IRBuilderAsmJs::BuildInt1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1493. {
  1494. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1495. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float1<SizePolicy>>();
  1496. BuildInt1Float1(newOpcode, offset, layout->I0, layout->F1);
  1497. }
  1498. void
  1499. IRBuilderAsmJs::BuildInt1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstIntReg, Js::RegSlot srcFloatReg)
  1500. {
  1501. Assert(newOpcode == Js::OpCodeAsmJs::Conv_FTI);
  1502. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstIntReg);
  1503. Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(srcFloatReg);
  1504. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  1505. srcOpnd->SetValueType(ValueType::Float);
  1506. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1507. dstOpnd->SetValueType(ValueType::GetInt(false));
  1508. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1509. AddInstr(instr, offset);
  1510. }
  1511. template <typename SizePolicy>
  1512. void
  1513. IRBuilderAsmJs::BuildDouble1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1514. {
  1515. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1516. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double1Int1<SizePolicy>>();
  1517. BuildDouble1Int1(newOpcode, offset, layout->D0, layout->I1);
  1518. }
  1519. void
  1520. IRBuilderAsmJs::BuildDouble1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstDoubleReg, Js::RegSlot srcIntReg)
  1521. {
  1522. Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(srcIntReg);
  1523. Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dstDoubleReg);
  1524. IR::RegOpnd * srcOpnd = nullptr;
  1525. switch (newOpcode)
  1526. {
  1527. case Js::OpCodeAsmJs::Conv_ITD:
  1528. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  1529. break;
  1530. case Js::OpCodeAsmJs::Conv_UTD:
  1531. srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint32);
  1532. break;
  1533. default:
  1534. Assume(UNREACHED);
  1535. }
  1536. srcOpnd->SetValueType(ValueType::GetInt(false));
  1537. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1538. dstOpnd->SetValueType(ValueType::Float);
  1539. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1540. AddInstr(instr, offset);
  1541. }
  1542. template <typename SizePolicy>
  1543. void
  1544. IRBuilderAsmJs::BuildDouble1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1545. {
  1546. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1547. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double1Float1<SizePolicy>>();
  1548. BuildDouble1Float1(newOpcode, offset, layout->D0, layout->F1);
  1549. }
  1550. void
  1551. IRBuilderAsmJs::BuildDouble1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstDoubleReg, Js::RegSlot srcFloatReg)
  1552. {
  1553. Assert(newOpcode == Js::OpCodeAsmJs::Conv_FTD);
  1554. Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dstDoubleReg);
  1555. Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(srcFloatReg);
  1556. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  1557. srcOpnd->SetValueType(ValueType::Float);
  1558. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1559. srcOpnd->SetValueType(ValueType::Float);
  1560. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1561. AddInstr(instr, offset);
  1562. }
  1563. template <typename SizePolicy>
  1564. void
  1565. IRBuilderAsmJs::BuildFloat1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1566. {
  1567. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1568. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Reg1<SizePolicy>>();
  1569. BuildFloat1Reg1(newOpcode, offset, layout->F0, layout->R1);
  1570. }
  1571. void
  1572. IRBuilderAsmJs::BuildFloat1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstFloatReg, Js::RegSlot srcVarReg)
  1573. {
  1574. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTF);
  1575. Js::RegSlot srcRegSlot = GetRegSlotFromVarReg(srcVarReg);
  1576. Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dstFloatReg);
  1577. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1578. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  1579. dstOpnd->SetValueType(ValueType::Float);
  1580. IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
  1581. AddInstr(instr, offset);
  1582. }
  1583. template <typename SizePolicy>
  1584. void
  1585. IRBuilderAsmJs::BuildDouble1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1586. {
  1587. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1588. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double1Reg1<SizePolicy>>();
  1589. BuildDouble1Reg1(newOpcode, offset, layout->D0, layout->R1);
  1590. }
  1591. void
  1592. IRBuilderAsmJs::BuildDouble1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstDoubleReg, Js::RegSlot srcVarReg)
  1593. {
  1594. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTD);
  1595. Js::RegSlot srcRegSlot = GetRegSlotFromVarReg(srcVarReg);
  1596. Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dstDoubleReg);
  1597. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1598. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1599. dstOpnd->SetValueType(ValueType::Float);
  1600. IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
  1601. AddInstr(instr, offset);
  1602. }
  1603. template <typename SizePolicy>
  1604. void
  1605. IRBuilderAsmJs::BuildInt1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1606. {
  1607. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1608. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Reg1<SizePolicy>>();
  1609. BuildInt1Reg1(newOpcode, offset, layout->I0, layout->R1);
  1610. }
  1611. void
  1612. IRBuilderAsmJs::BuildInt1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstIntReg, Js::RegSlot srcVarReg)
  1613. {
  1614. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTI);
  1615. Js::RegSlot srcRegSlot = GetRegSlotFromVarReg(srcVarReg);
  1616. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstIntReg);
  1617. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1618. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1619. dstOpnd->SetValueType(ValueType::GetInt(false));
  1620. IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
  1621. AddInstr(instr, offset);
  1622. }
  1623. template <typename SizePolicy>
  1624. void
  1625. IRBuilderAsmJs::BuildReg1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1626. {
  1627. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1628. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Double1<SizePolicy>>();
  1629. BuildReg1Double1(newOpcode, offset, layout->R0, layout->D1);
  1630. }
  1631. void
  1632. IRBuilderAsmJs::BuildReg1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcDoubleReg)
  1633. {
  1634. Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(srcDoubleReg);
  1635. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  1636. srcOpnd->SetValueType(ValueType::Float);
  1637. IR::Instr * instr = nullptr;
  1638. IR::Opnd * dstOpnd = nullptr;
  1639. IR::Opnd * tmpDst = nullptr;
  1640. StackSym * symDst = nullptr;
  1641. switch (newOpcode)
  1642. {
  1643. case Js::OpCodeAsmJs::ArgOut_Db:
  1644. symDst = m_func->m_symTable->GetArgSlotSym((uint16)(dstReg+1));
  1645. if (symDst == nullptr || (uint16)(dstReg + 1) != (dstReg + 1))
  1646. {
  1647. AssertMsg(UNREACHED, "Arg count too big...");
  1648. Fatal();
  1649. }
  1650. tmpDst = IR::RegOpnd::New(StackSym::New(m_func), TyVar, m_func);
  1651. instr = IR::Instr::New(Js::OpCode::ToVar, tmpDst, srcOpnd, m_func);
  1652. AddInstr(instr, offset);
  1653. dstOpnd = IR::SymOpnd::New(symDst, TyVar, m_func);
  1654. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, tmpDst, m_func);
  1655. AddInstr(instr, offset);
  1656. m_argStack->Push(instr);
  1657. break;
  1658. case Js::OpCodeAsmJs::I_ArgOut_Db:
  1659. symDst = StackSym::NewArgSlotSym((uint16)dstReg, m_func, TyFloat64);
  1660. symDst->m_allocated = true;
  1661. if (symDst == nullptr || (uint16)(dstReg) != (dstReg))
  1662. {
  1663. AssertMsg(UNREACHED, "Arg count too big...");
  1664. Fatal();
  1665. }
  1666. dstOpnd = IR::SymOpnd::New(symDst, TyFloat64, m_func);
  1667. dstOpnd->SetValueType(ValueType::Float);
  1668. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  1669. AddInstr(instr, offset);
  1670. m_argStack->Push(instr);
  1671. break;
  1672. default:
  1673. Assume(UNREACHED);
  1674. }
  1675. }
  1676. template <typename SizePolicy>
  1677. void
  1678. IRBuilderAsmJs::BuildReg1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1679. {
  1680. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1681. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Float1<SizePolicy>>();
  1682. BuildReg1Float1(newOpcode, offset, layout->R0, layout->F1);
  1683. }
  1684. void
  1685. IRBuilderAsmJs::BuildReg1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcFloatReg)
  1686. {
  1687. Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(srcFloatReg);
  1688. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  1689. srcOpnd->SetValueType(ValueType::Float);
  1690. IR::Instr * instr = nullptr;
  1691. IR::Opnd * dstOpnd = nullptr;
  1692. switch (newOpcode)
  1693. {
  1694. case Js::OpCodeAsmJs::I_ArgOut_Flt:
  1695. {
  1696. StackSym * symDst = StackSym::NewArgSlotSym((uint16)dstReg, m_func, TyFloat32);
  1697. symDst->m_allocated = true;
  1698. if (symDst == nullptr || (uint16)(dstReg) != (dstReg))
  1699. {
  1700. AssertMsg(UNREACHED, "Arg count too big...");
  1701. Fatal();
  1702. }
  1703. dstOpnd = IR::SymOpnd::New(symDst, TyFloat32, m_func);
  1704. dstOpnd->SetValueType(ValueType::Float);
  1705. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  1706. AddInstr(instr, offset);
  1707. m_argStack->Push(instr);
  1708. break;
  1709. }
  1710. default:
  1711. Assume(UNREACHED);
  1712. }
  1713. }
  1714. template <typename SizePolicy>
  1715. void
  1716. IRBuilderAsmJs::BuildReg1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1717. {
  1718. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1719. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Int1<SizePolicy>>();
  1720. BuildReg1Int1(newOpcode, offset, layout->R0, layout->I1);
  1721. }
  1722. void
  1723. IRBuilderAsmJs::BuildReg1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcIntReg)
  1724. {
  1725. Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(srcIntReg);
  1726. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  1727. srcOpnd->SetValueType(ValueType::GetInt(false));
  1728. IR::Opnd * dstOpnd;
  1729. IR::Opnd * tmpDst;
  1730. IR::Instr * instr;
  1731. StackSym * symDst;
  1732. switch (newOpcode)
  1733. {
  1734. case Js::OpCodeAsmJs::ArgOut_Int:
  1735. symDst = m_func->m_symTable->GetArgSlotSym((uint16)(dstReg + 1));
  1736. if (symDst == nullptr || (uint16)(dstReg + 1) != (dstReg + 1))
  1737. {
  1738. AssertMsg(UNREACHED, "Arg count too big...");
  1739. Fatal();
  1740. }
  1741. tmpDst = IR::RegOpnd::New(StackSym::New(m_func), TyVar, m_func);
  1742. instr = IR::Instr::New(Js::OpCode::ToVar, tmpDst, srcOpnd, m_func);
  1743. AddInstr(instr, offset);
  1744. dstOpnd = IR::SymOpnd::New(symDst, TyVar, m_func);
  1745. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, tmpDst, m_func);
  1746. AddInstr(instr, offset);
  1747. m_argStack->Push(instr);
  1748. break;
  1749. case Js::OpCodeAsmJs::I_ArgOut_Int:
  1750. symDst = StackSym::NewArgSlotSym((uint16)dstReg, m_func, TyInt32);
  1751. symDst->m_allocated = true;
  1752. if (symDst == nullptr || (uint16)(dstReg) != (dstReg))
  1753. {
  1754. AssertMsg(UNREACHED, "Arg count too big...");
  1755. Fatal();
  1756. }
  1757. dstOpnd = IR::SymOpnd::New(symDst, TyInt32, m_func);
  1758. dstOpnd->SetValueType(ValueType::GetInt(false));
  1759. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  1760. AddInstr(instr, offset);
  1761. m_argStack->Push(instr);
  1762. break;
  1763. default:
  1764. Assume(UNREACHED);
  1765. }
  1766. }
  1767. template <typename SizePolicy>
  1768. void
  1769. IRBuilderAsmJs::BuildInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1770. {
  1771. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1772. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Const1<SizePolicy>>();
  1773. BuildInt1Const1(newOpcode, offset, layout->I0, layout->C1);
  1774. }
  1775. void
  1776. IRBuilderAsmJs::BuildInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstInt, int constInt)
  1777. {
  1778. Assert(newOpcode == Js::OpCodeAsmJs::Ld_IntConst);
  1779. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstInt);
  1780. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1781. dstOpnd->SetValueType(ValueType::GetInt(false));
  1782. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, IR::IntConstOpnd::New(constInt, TyInt32, m_func), m_func);
  1783. if (dstOpnd->m_sym->IsSingleDef())
  1784. {
  1785. dstOpnd->m_sym->SetIsIntConst(constInt);
  1786. }
  1787. AddInstr(instr, offset);
  1788. }
  1789. template <typename SizePolicy>
  1790. void
  1791. IRBuilderAsmJs::BuildInt1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1792. {
  1793. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1794. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Double2<SizePolicy>>();
  1795. BuildInt1Double2(newOpcode, offset, layout->I0, layout->D1, layout->D2);
  1796. }
  1797. void
  1798. IRBuilderAsmJs::BuildInt1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
  1799. {
  1800. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
  1801. Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(src1);
  1802. Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(src2);
  1803. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  1804. src1Opnd->SetValueType(ValueType::Float);
  1805. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  1806. src2Opnd->SetValueType(ValueType::Float);
  1807. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1808. dstOpnd->SetValueType(ValueType::GetInt(false));
  1809. IR::Instr * instr = nullptr;
  1810. switch (newOpcode)
  1811. {
  1812. case Js::OpCodeAsmJs::CmLt_Db:
  1813. instr = IR::Instr::New(Js::OpCode::CmLt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1814. break;
  1815. case Js::OpCodeAsmJs::CmLe_Db:
  1816. instr = IR::Instr::New(Js::OpCode::CmLe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1817. break;
  1818. case Js::OpCodeAsmJs::CmGt_Db:
  1819. instr = IR::Instr::New(Js::OpCode::CmGt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1820. break;
  1821. case Js::OpCodeAsmJs::CmGe_Db:
  1822. instr = IR::Instr::New(Js::OpCode::CmGe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1823. break;
  1824. case Js::OpCodeAsmJs::CmEq_Db:
  1825. instr = IR::Instr::New(Js::OpCode::CmEq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1826. break;
  1827. case Js::OpCodeAsmJs::CmNe_Db:
  1828. instr = IR::Instr::New(Js::OpCode::CmNeq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1829. break;
  1830. default:
  1831. Assume(UNREACHED);
  1832. }
  1833. AddInstr(instr, offset);
  1834. }
  1835. template <typename SizePolicy>
  1836. void
  1837. IRBuilderAsmJs::BuildInt1Float2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1838. {
  1839. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1840. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float2<SizePolicy>>();
  1841. BuildInt1Float2(newOpcode, offset, layout->I0, layout->F1, layout->F2);
  1842. }
  1843. void
  1844. IRBuilderAsmJs::BuildInt1Float2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
  1845. {
  1846. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
  1847. Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(src1);
  1848. Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(src2);
  1849. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  1850. src1Opnd->SetValueType(ValueType::Float);
  1851. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  1852. src2Opnd->SetValueType(ValueType::Float);
  1853. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1854. dstOpnd->SetValueType(ValueType::GetInt(false));
  1855. IR::Instr * instr = nullptr;
  1856. switch (newOpcode)
  1857. {
  1858. case Js::OpCodeAsmJs::CmLt_Flt:
  1859. instr = IR::Instr::New(Js::OpCode::CmLt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1860. break;
  1861. case Js::OpCodeAsmJs::CmLe_Flt:
  1862. instr = IR::Instr::New(Js::OpCode::CmLe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1863. break;
  1864. case Js::OpCodeAsmJs::CmGt_Flt:
  1865. instr = IR::Instr::New(Js::OpCode::CmGt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1866. break;
  1867. case Js::OpCodeAsmJs::CmGe_Flt:
  1868. instr = IR::Instr::New(Js::OpCode::CmGe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1869. break;
  1870. case Js::OpCodeAsmJs::CmEq_Flt:
  1871. instr = IR::Instr::New(Js::OpCode::CmEq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1872. break;
  1873. case Js::OpCodeAsmJs::CmNe_Flt:
  1874. instr = IR::Instr::New(Js::OpCode::CmNeq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1875. break;
  1876. default:
  1877. Assume(UNREACHED);
  1878. }
  1879. AddInstr(instr, offset);
  1880. }
  1881. template <typename SizePolicy>
  1882. void
  1883. IRBuilderAsmJs::BuildInt2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1884. {
  1885. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1886. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int2<SizePolicy>>();
  1887. BuildInt2(newOpcode, offset, layout->I0, layout->I1);
  1888. }
  1889. void
  1890. IRBuilderAsmJs::BuildInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
  1891. {
  1892. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
  1893. Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(src);
  1894. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  1895. srcOpnd->SetValueType(ValueType::GetInt(false));
  1896. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1897. dstOpnd->SetValueType(ValueType::GetInt(false));
  1898. IR::Instr * instr = nullptr;
  1899. switch (newOpcode)
  1900. {
  1901. case Js::OpCodeAsmJs::BeginSwitch_Int:
  1902. m_switchBuilder.BeginSwitch();
  1903. // fall-through
  1904. case Js::OpCodeAsmJs::Ld_Int:
  1905. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  1906. break;
  1907. case Js::OpCodeAsmJs::Neg_Int:
  1908. instr = IR::Instr::New(Js::OpCode::Neg_I4, dstOpnd, srcOpnd, m_func);
  1909. break;
  1910. case Js::OpCodeAsmJs::Not_Int:
  1911. instr = IR::Instr::New(Js::OpCode::Not_I4, dstOpnd, srcOpnd, m_func);
  1912. break;
  1913. case Js::OpCodeAsmJs::LogNot_Int:
  1914. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
  1915. break;
  1916. case Js::OpCodeAsmJs::Conv_ITB:
  1917. instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
  1918. break;
  1919. case Js::OpCodeAsmJs::Abs_Int:
  1920. instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
  1921. break;
  1922. case Js::OpCodeAsmJs::Clz32_Int:
  1923. instr = IR::Instr::New(Js::OpCode::InlineMathClz32, dstOpnd, srcOpnd, m_func);
  1924. break;
  1925. case Js::OpCodeAsmJs::I_Conv_VTI:
  1926. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  1927. break;
  1928. case Js::OpCodeAsmJs::Return_Int:
  1929. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  1930. if (m_func->IsLoopBody())
  1931. {
  1932. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyInt32);
  1933. AddInstr(slotInstr, offset);
  1934. }
  1935. break;
  1936. default:
  1937. Assume(UNREACHED);
  1938. }
  1939. AddInstr(instr, offset);
  1940. }
  1941. template <typename SizePolicy>
  1942. void
  1943. IRBuilderAsmJs::BuildInt3(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1944. {
  1945. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1946. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int3<SizePolicy>>();
  1947. BuildInt3(newOpcode, offset, layout->I0, layout->I1, layout->I2);
  1948. }
  1949. void
  1950. IRBuilderAsmJs::BuildInt3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
  1951. {
  1952. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dst);
  1953. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
  1954. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(src2);
  1955. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  1956. src1Opnd->SetValueType(ValueType::GetInt(false));
  1957. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  1958. src2Opnd->SetValueType(ValueType::GetInt(false));
  1959. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1960. dstOpnd->SetValueType(ValueType::GetInt(false));
  1961. IR::Instr * instr = nullptr;
  1962. switch (newOpcode)
  1963. {
  1964. case Js::OpCodeAsmJs::Add_Int:
  1965. instr = IR::Instr::New(Js::OpCode::Add_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1966. break;
  1967. case Js::OpCodeAsmJs::Sub_Int:
  1968. instr = IR::Instr::New(Js::OpCode::Sub_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1969. break;
  1970. case Js::OpCodeAsmJs::Mul_UInt:
  1971. src1Opnd->SetType(TyUint32);
  1972. src2Opnd->SetType(TyUint32);
  1973. case Js::OpCodeAsmJs::Mul_Int:
  1974. instr = IR::Instr::New(Js::OpCode::Mul_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1975. break;
  1976. case Js::OpCodeAsmJs::Div_UInt:
  1977. src1Opnd->SetType(TyUint32);
  1978. src2Opnd->SetType(TyUint32);
  1979. case Js::OpCodeAsmJs::Div_Int:
  1980. instr = IR::Instr::New(Js::OpCode::Div_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1981. break;
  1982. case Js::OpCodeAsmJs::Rem_UInt:
  1983. src1Opnd->SetType(TyUint32);
  1984. src2Opnd->SetType(TyUint32);
  1985. case Js::OpCodeAsmJs::Rem_Int:
  1986. instr = IR::Instr::New(Js::OpCode::Rem_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1987. break;
  1988. case Js::OpCodeAsmJs::And_Int:
  1989. instr = IR::Instr::New(Js::OpCode::And_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1990. break;
  1991. case Js::OpCodeAsmJs::Or_Int:
  1992. instr = IR::Instr::New(Js::OpCode::Or_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1993. break;
  1994. case Js::OpCodeAsmJs::Xor_Int:
  1995. instr = IR::Instr::New(Js::OpCode::Xor_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1996. break;
  1997. case Js::OpCodeAsmJs::Shl_Int:
  1998. instr = IR::Instr::New(Js::OpCode::Shl_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  1999. break;
  2000. case Js::OpCodeAsmJs::Shr_Int:
  2001. instr = IR::Instr::New(Js::OpCode::Shr_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2002. break;
  2003. case Js::OpCodeAsmJs::ShrU_Int:
  2004. instr = IR::Instr::New(Js::OpCode::ShrU_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2005. break;
  2006. case Js::OpCodeAsmJs::CmLt_Int:
  2007. instr = IR::Instr::New(Js::OpCode::CmLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2008. break;
  2009. case Js::OpCodeAsmJs::CmLe_Int:
  2010. instr = IR::Instr::New(Js::OpCode::CmLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2011. break;
  2012. case Js::OpCodeAsmJs::CmGt_Int:
  2013. instr = IR::Instr::New(Js::OpCode::CmGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2014. break;
  2015. case Js::OpCodeAsmJs::CmGe_Int:
  2016. instr = IR::Instr::New(Js::OpCode::CmGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2017. break;
  2018. case Js::OpCodeAsmJs::CmEq_Int:
  2019. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2020. break;
  2021. case Js::OpCodeAsmJs::CmNe_Int:
  2022. instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2023. break;
  2024. case Js::OpCodeAsmJs::CmLt_UnInt:
  2025. instr = IR::Instr::New(Js::OpCode::CmUnLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2026. break;
  2027. case Js::OpCodeAsmJs::CmLe_UnInt:
  2028. instr = IR::Instr::New(Js::OpCode::CmUnLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2029. break;
  2030. case Js::OpCodeAsmJs::CmGt_UnInt:
  2031. instr = IR::Instr::New(Js::OpCode::CmUnGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2032. break;
  2033. case Js::OpCodeAsmJs::CmGe_UnInt:
  2034. instr = IR::Instr::New(Js::OpCode::CmUnGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2035. break;
  2036. case Js::OpCodeAsmJs::Min_Int:
  2037. instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
  2038. break;
  2039. case Js::OpCodeAsmJs::Max_Int:
  2040. instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
  2041. break;
  2042. case Js::OpCodeAsmJs::Imul_Int:
  2043. instr = IR::Instr::New(Js::OpCode::InlineMathImul, dstOpnd, src1Opnd, src2Opnd, m_func);
  2044. break;
  2045. default:
  2046. Assume(UNREACHED);
  2047. }
  2048. AddInstr(instr, offset);
  2049. }
  2050. template <typename SizePolicy>
  2051. void
  2052. IRBuilderAsmJs::BuildDouble2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2053. {
  2054. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2055. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double2<SizePolicy>>();
  2056. BuildDouble2(newOpcode, offset, layout->D0, layout->D1);
  2057. }
  2058. void
  2059. IRBuilderAsmJs::BuildDouble2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
  2060. {
  2061. Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dst);
  2062. Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(src);
  2063. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  2064. srcOpnd->SetValueType(ValueType::Float);
  2065. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  2066. dstOpnd->SetValueType(ValueType::Float);
  2067. IR::Instr * instr = nullptr;
  2068. switch (newOpcode)
  2069. {
  2070. case Js::OpCodeAsmJs::Ld_Db:
  2071. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2072. break;
  2073. case Js::OpCodeAsmJs::Neg_Db:
  2074. instr = IR::Instr::New(Js::OpCode::Neg_A, dstOpnd, srcOpnd, m_func);
  2075. break;
  2076. case Js::OpCodeAsmJs::Sin_Db:
  2077. instr = IR::Instr::New(Js::OpCode::InlineMathSin, dstOpnd, srcOpnd, m_func);
  2078. break;
  2079. case Js::OpCodeAsmJs::Cos_Db:
  2080. instr = IR::Instr::New(Js::OpCode::InlineMathCos, dstOpnd, srcOpnd, m_func);
  2081. break;
  2082. case Js::OpCodeAsmJs::Tan_Db:
  2083. instr = IR::Instr::New(Js::OpCode::InlineMathTan, dstOpnd, srcOpnd, m_func);
  2084. break;
  2085. case Js::OpCodeAsmJs::Asin_Db:
  2086. instr = IR::Instr::New(Js::OpCode::InlineMathAsin, dstOpnd, srcOpnd, m_func);
  2087. break;
  2088. case Js::OpCodeAsmJs::Acos_Db:
  2089. instr = IR::Instr::New(Js::OpCode::InlineMathAcos, dstOpnd, srcOpnd, m_func);
  2090. break;
  2091. case Js::OpCodeAsmJs::Atan_Db:
  2092. instr = IR::Instr::New(Js::OpCode::InlineMathAtan, dstOpnd, srcOpnd, m_func);
  2093. break;
  2094. case Js::OpCodeAsmJs::Abs_Db:
  2095. instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
  2096. break;
  2097. case Js::OpCodeAsmJs::Ceil_Db:
  2098. instr = IR::Instr::New(Js::OpCode::InlineMathCeil, dstOpnd, srcOpnd, m_func);
  2099. break;
  2100. case Js::OpCodeAsmJs::Floor_Db:
  2101. instr = IR::Instr::New(Js::OpCode::InlineMathFloor, dstOpnd, srcOpnd, m_func);
  2102. break;
  2103. case Js::OpCodeAsmJs::Exp_Db:
  2104. instr = IR::Instr::New(Js::OpCode::InlineMathExp, dstOpnd, srcOpnd, m_func);
  2105. break;
  2106. case Js::OpCodeAsmJs::Log_Db:
  2107. instr = IR::Instr::New(Js::OpCode::InlineMathLog, dstOpnd, srcOpnd, m_func);
  2108. break;
  2109. case Js::OpCodeAsmJs::Sqrt_Db:
  2110. instr = IR::Instr::New(Js::OpCode::InlineMathSqrt, dstOpnd, srcOpnd, m_func);
  2111. break;
  2112. case Js::OpCodeAsmJs::Return_Db:
  2113. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2114. if (m_func->IsLoopBody())
  2115. {
  2116. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyFloat64);
  2117. AddInstr(slotInstr, offset);
  2118. }
  2119. break;
  2120. case Js::OpCodeAsmJs::I_Conv_VTD:
  2121. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2122. break;
  2123. default:
  2124. Assume(UNREACHED);
  2125. }
  2126. AddInstr(instr, offset);
  2127. }
  2128. template <typename SizePolicy>
  2129. void
  2130. IRBuilderAsmJs::BuildFloat2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2131. {
  2132. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2133. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float2<SizePolicy>>();
  2134. BuildFloat2(newOpcode, offset, layout->F0, layout->F1);
  2135. }
  2136. void
  2137. IRBuilderAsmJs::BuildFloat2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
  2138. {
  2139. Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
  2140. Js::RegSlot srcRegSlot = GetRegSlotFromFloatReg(src);
  2141. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  2142. srcOpnd->SetValueType(ValueType::Float);
  2143. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2144. dstOpnd->SetValueType(ValueType::Float);
  2145. IR::Instr * instr = nullptr;
  2146. switch (newOpcode)
  2147. {
  2148. case Js::OpCodeAsmJs::Ld_Flt:
  2149. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2150. break;
  2151. case Js::OpCodeAsmJs::Neg_Flt:
  2152. instr = IR::Instr::New(Js::OpCode::Neg_A, dstOpnd, srcOpnd, m_func);
  2153. break;
  2154. case Js::OpCodeAsmJs::Ceil_Flt:
  2155. instr = IR::Instr::New(Js::OpCode::InlineMathCeil, dstOpnd, srcOpnd, m_func);
  2156. break;
  2157. case Js::OpCodeAsmJs::Floor_Flt:
  2158. instr = IR::Instr::New(Js::OpCode::InlineMathFloor, dstOpnd, srcOpnd, m_func);
  2159. break;
  2160. case Js::OpCodeAsmJs::Sqrt_Flt:
  2161. instr = IR::Instr::New(Js::OpCode::InlineMathSqrt, dstOpnd, srcOpnd, m_func);
  2162. break;
  2163. case Js::OpCodeAsmJs::Abs_Flt:
  2164. instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
  2165. break;
  2166. case Js::OpCodeAsmJs::Fround_Flt:
  2167. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2168. break;
  2169. case Js::OpCodeAsmJs::Return_Flt:
  2170. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2171. if (m_func->IsLoopBody())
  2172. {
  2173. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyFloat32);
  2174. AddInstr(slotInstr, offset);
  2175. }
  2176. break;
  2177. case Js::OpCodeAsmJs::I_Conv_VTF:
  2178. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2179. break;
  2180. default:
  2181. Assume(UNREACHED);
  2182. }
  2183. AddInstr(instr, offset);
  2184. }
  2185. template <typename SizePolicy>
  2186. void
  2187. IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2188. {
  2189. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2190. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float3<SizePolicy>>();
  2191. BuildFloat3(newOpcode, offset, layout->F0, layout->F1, layout->F2);
  2192. }
  2193. void
  2194. IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
  2195. {
  2196. Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
  2197. Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(src1);
  2198. Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(src2);
  2199. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  2200. src1Opnd->SetValueType(ValueType::Float);
  2201. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  2202. src2Opnd->SetValueType(ValueType::Float);
  2203. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2204. dstOpnd->SetValueType(ValueType::Float);
  2205. IR::Instr * instr = nullptr;
  2206. switch (newOpcode)
  2207. {
  2208. case Js::OpCodeAsmJs::Add_Flt:
  2209. instr = IR::Instr::New(Js::OpCode::Add_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2210. break;
  2211. case Js::OpCodeAsmJs::Sub_Flt:
  2212. instr = IR::Instr::New(Js::OpCode::Sub_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2213. break;
  2214. case Js::OpCodeAsmJs::Mul_Flt:
  2215. instr = IR::Instr::New(Js::OpCode::Mul_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2216. break;
  2217. case Js::OpCodeAsmJs::Div_Flt:
  2218. instr = IR::Instr::New(Js::OpCode::Div_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2219. break;
  2220. default:
  2221. Assume(UNREACHED);
  2222. }
  2223. AddInstr(instr, offset);
  2224. }
  2225. template <typename SizePolicy>
  2226. void
  2227. IRBuilderAsmJs::BuildFloat1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2228. {
  2229. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2230. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Double1<SizePolicy>>();
  2231. BuildFloat1Double1(newOpcode, offset, layout->F0, layout->D1);
  2232. }
  2233. void
  2234. IRBuilderAsmJs::BuildFloat1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
  2235. {
  2236. Assert(newOpcode == Js::OpCodeAsmJs::Fround_Db);
  2237. Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
  2238. Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(src);
  2239. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  2240. srcOpnd->SetValueType(ValueType::Float);
  2241. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2242. dstOpnd->SetValueType(ValueType::Float);
  2243. IR::Instr * instr = IR::Instr::New(Js::OpCode::InlineMathFround, dstOpnd, srcOpnd, m_func);
  2244. AddInstr(instr, offset);
  2245. }
  2246. template <typename SizePolicy>
  2247. void
  2248. IRBuilderAsmJs::BuildFloat1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2249. {
  2250. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2251. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Int1<SizePolicy>>();
  2252. BuildFloat1Int1(newOpcode, offset, layout->F0, layout->I1);
  2253. }
  2254. void
  2255. IRBuilderAsmJs::BuildFloat1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src)
  2256. {
  2257. Assert(newOpcode == Js::OpCodeAsmJs::Fround_Int);
  2258. Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(dst);
  2259. Js::RegSlot srcRegSlot = GetRegSlotFromIntReg(src);
  2260. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  2261. srcOpnd->SetValueType(ValueType::GetInt(false));
  2262. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2263. dstOpnd->SetValueType(ValueType::Float);
  2264. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  2265. AddInstr(instr, offset);
  2266. }
  2267. template <typename SizePolicy>
  2268. void
  2269. IRBuilderAsmJs::BuildDouble3(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2270. {
  2271. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2272. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Double3<SizePolicy>>();
  2273. BuildDouble3(newOpcode, offset, layout->D0, layout->D1, layout->D2);
  2274. }
  2275. void
  2276. IRBuilderAsmJs::BuildDouble3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dst, Js::RegSlot src1, Js::RegSlot src2)
  2277. {
  2278. Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dst);
  2279. Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(src1);
  2280. Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(src2);
  2281. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  2282. src1Opnd->SetValueType(ValueType::Float);
  2283. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  2284. src2Opnd->SetValueType(ValueType::Float);
  2285. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  2286. dstOpnd->SetValueType(ValueType::Float);
  2287. IR::Instr * instr = nullptr;
  2288. switch (newOpcode)
  2289. {
  2290. case Js::OpCodeAsmJs::Add_Db:
  2291. instr = IR::Instr::New(Js::OpCode::Add_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2292. break;
  2293. case Js::OpCodeAsmJs::Sub_Db:
  2294. instr = IR::Instr::New(Js::OpCode::Sub_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2295. break;
  2296. case Js::OpCodeAsmJs::Mul_Db:
  2297. instr = IR::Instr::New(Js::OpCode::Mul_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2298. break;
  2299. case Js::OpCodeAsmJs::Div_Db:
  2300. instr = IR::Instr::New(Js::OpCode::Div_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2301. break;
  2302. case Js::OpCodeAsmJs::Rem_Db:
  2303. instr = IR::Instr::New(Js::OpCode::Rem_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2304. break;
  2305. case Js::OpCodeAsmJs::Pow_Db:
  2306. instr = IR::Instr::New(Js::OpCode::InlineMathPow, dstOpnd, src1Opnd, src2Opnd, m_func);
  2307. break;
  2308. case Js::OpCodeAsmJs::Atan2_Db:
  2309. instr = IR::Instr::New(Js::OpCode::InlineMathAtan2, dstOpnd, src1Opnd, src2Opnd, m_func);
  2310. break;
  2311. case Js::OpCodeAsmJs::Min_Db:
  2312. instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
  2313. break;
  2314. case Js::OpCodeAsmJs::Max_Db:
  2315. instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
  2316. break;
  2317. default:
  2318. Assume(UNREACHED);
  2319. }
  2320. AddInstr(instr, offset);
  2321. }
  2322. template <typename SizePolicy>
  2323. void
  2324. IRBuilderAsmJs::BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2325. {
  2326. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2327. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt1<SizePolicy>>();
  2328. BuildBrInt1(newOpcode, offset, layout->RelativeJumpOffset, layout->I1);
  2329. }
  2330. void
  2331. IRBuilderAsmJs::BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src)
  2332. {
  2333. Assert(newOpcode == Js::OpCodeAsmJs::BrTrue_Int);
  2334. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src);
  2335. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  2336. src1Opnd->SetValueType(ValueType::GetInt(false));
  2337. uint targetOffset = m_jnReader.GetCurrentOffset() + relativeOffset;
  2338. IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrTrue_I4, nullptr, src1Opnd, m_func);
  2339. AddBranchInstr(branchInstr, offset, targetOffset);
  2340. }
  2341. template <typename SizePolicy>
  2342. void
  2343. IRBuilderAsmJs::BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2344. {
  2345. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2346. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt2<SizePolicy>>();
  2347. BuildBrInt2(newOpcode, offset, layout->RelativeJumpOffset, layout->I1, layout->I2);
  2348. }
  2349. void
  2350. IRBuilderAsmJs::BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, Js::RegSlot src2)
  2351. {
  2352. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
  2353. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(src2);
  2354. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  2355. src1Opnd->SetValueType(ValueType::GetInt(false));
  2356. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  2357. src2Opnd->SetValueType(ValueType::GetInt(false));
  2358. uint targetOffset = m_jnReader.GetCurrentOffset() + relativeOffset;
  2359. if (newOpcode == Js::OpCodeAsmJs::Case_Int)
  2360. {
  2361. // branches for cases are generated entirely by the switch builder
  2362. m_switchBuilder.OnCase(
  2363. src1Opnd,
  2364. src2Opnd,
  2365. offset,
  2366. targetOffset);
  2367. }
  2368. else
  2369. {
  2370. Assert(newOpcode == Js::OpCodeAsmJs::BrEq_Int);
  2371. IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrEq_I4, nullptr, src1Opnd, src2Opnd, m_func);
  2372. AddBranchInstr(branchInstr, offset, targetOffset);
  2373. }
  2374. }
  2375. ///Loop Body Code
  2376. bool
  2377. IRBuilderAsmJs::IsLoopBody() const
  2378. {
  2379. return m_func->IsLoopBody();
  2380. }
  2381. bool
  2382. IRBuilderAsmJs::IsLoopBodyReturnIPInstr(IR::Instr * instr) const
  2383. {
  2384. IR::Opnd * dst = instr->GetDst();
  2385. return (dst && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym == m_loopBodyRetIPSym);
  2386. }
  2387. bool
  2388. IRBuilderAsmJs::IsLoopBodyOuterOffset(uint offset) const
  2389. {
  2390. if (!IsLoopBody())
  2391. {
  2392. return false;
  2393. }
  2394. JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
  2395. return (offset >= loopBodyCodeGen->loopHeader->endOffset || offset < loopBodyCodeGen->loopHeader->startOffset);
  2396. }
  2397. uint
  2398. IRBuilderAsmJs::GetLoopBodyExitInstrOffset() const
  2399. {
  2400. // End of loop body, start of StSlot and Ret instruction at endOffset + 1
  2401. return ((JsLoopBodyCodeGen*)m_func->m_workItem)->loopHeader->endOffset + 1;
  2402. }
  2403. IR::Instr *
  2404. IRBuilderAsmJs::CreateLoopBodyReturnIPInstr(uint targetOffset, uint offset)
  2405. {
  2406. IR::RegOpnd * retOpnd = IR::RegOpnd::New(m_loopBodyRetIPSym, TyInt32, m_func);
  2407. IR::IntConstOpnd * exitOffsetOpnd = IR::IntConstOpnd::New(targetOffset, TyInt32, m_func);
  2408. return IR::Instr::New(Js::OpCode::Ld_I4, retOpnd, exitOffsetOpnd, m_func);
  2409. }
  2410. IR::Opnd *
  2411. IRBuilderAsmJs::InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset)
  2412. {
  2413. IR::Instr * setRetValueInstr = CreateLoopBodyReturnIPInstr(targetOffset, offset);
  2414. this->AddInstr(setRetValueInstr, offset);
  2415. return setRetValueInstr->GetDst();
  2416. }
  2417. IR::SymOpnd *
  2418. IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(SymID symId, IRType opndType)
  2419. {
  2420. // Get the interpreter frame instance that was passed in.
  2421. StackSym *loopParamSym = m_func->EnsureLoopParamSym();
  2422. // Compute the offset of the start of the locals array as a Var index.
  2423. size_t localsOffset = 0;
  2424. if (!m_IsTJLoopBody)
  2425. {
  2426. localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
  2427. }
  2428. Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
  2429. Js::PropertyId propOffSet = 0;
  2430. IRType type = IRType::TyInt32;
  2431. BOOL scale = true;
  2432. if (RegIsIntVar(symId))
  2433. {
  2434. const int intOffset = m_asmFuncInfo->GetIntByteOffset() / sizeof(int);
  2435. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(int));
  2436. // Get the bytecodeRegSlot
  2437. Js::PropertyId intRegSlot = symId - m_firstIntVar + m_asmFuncInfo->GetIntConstCount();
  2438. // Get the offset from m_localSlots
  2439. propOffSet = (Js::PropertyId)(intRegSlot + intOffset + localsStartSlot);
  2440. type = IRType::TyInt32;
  2441. }
  2442. else if (RegIsFloatVar(symId))
  2443. {
  2444. const int floatOffset = m_asmFuncInfo->GetFloatByteOffset() / sizeof(float);
  2445. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(float));
  2446. // Get the bytecodeRegSlot
  2447. Js::PropertyId fltRegSlot = symId - m_firstFloatVar + m_asmFuncInfo->GetFloatConstCount();
  2448. // Get the offset from m_localSlots
  2449. propOffSet = (Js::PropertyId)(fltRegSlot + floatOffset + localsStartSlot);
  2450. type = IRType::TyFloat32;
  2451. }
  2452. else if (RegIsDoubleVar(symId))
  2453. {
  2454. const int doubleOffset = m_asmFuncInfo->GetDoubleByteOffset() / sizeof(double);
  2455. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(double));
  2456. // Get the bytecodeRegSlot
  2457. Js::PropertyId dbRegSlot = symId - m_firstDoubleVar + m_asmFuncInfo->GetDoubleConstCount();
  2458. // Get the offset from m_localSlots
  2459. propOffSet = (Js::PropertyId)(dbRegSlot + doubleOffset + localsStartSlot);
  2460. type = IRType::TyFloat64;
  2461. }
  2462. else if (RegIsSimd128Var(symId))
  2463. {
  2464. // SimdByteOffset is not guaranteed to be divisible by Simd size. So we do computation in bytes.
  2465. const int simdOffset = m_asmFuncInfo->GetSimdByteOffset();
  2466. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset);
  2467. // Get the bytecodeRegSlot
  2468. Js::PropertyId dbRegSlot = symId - m_firstSimdVar + m_asmFuncInfo->GetSimdConstCount();
  2469. // Get the offset from m_localSlots
  2470. propOffSet = (Js::PropertyId)(dbRegSlot * sizeof(AsmJsSIMDValue) + simdOffset + localsStartSlot);
  2471. type = opndType;
  2472. scale = false;
  2473. }
  2474. else
  2475. {
  2476. Assert(UNREACHED);
  2477. }
  2478. if (scale)
  2479. {
  2480. // property ID is the offset
  2481. propOffSet = propOffSet * TySize[type];
  2482. }
  2483. PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
  2484. return IR::SymOpnd::New(fieldSym, type, m_func);
  2485. }
  2486. void
  2487. IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
  2488. {
  2489. if (this->m_ldSlots->TestAndSet(symId))
  2490. {
  2491. return;
  2492. }
  2493. IR::SymOpnd * fieldSymOpnd = this->BuildAsmJsLoopBodySlotOpnd(symId, type);
  2494. StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func, fieldSymOpnd->GetType());
  2495. IR::RegOpnd * dstOpnd = IR::RegOpnd::New(symDst, symDst->GetType(), m_func);
  2496. IR::Instr * ldSlotInstr;
  2497. JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
  2498. ValueType symValueType;
  2499. if (loopBodyCodeGen->symIdToValueTypeMap && loopBodyCodeGen->symIdToValueTypeMap->TryGetValue(symId, &symValueType))
  2500. {
  2501. ldSlotInstr = IR::ProfiledInstr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
  2502. ldSlotInstr->AsProfiledInstr()->u.FldInfo().valueType = symValueType;
  2503. }
  2504. else
  2505. {
  2506. ldSlotInstr = IR::Instr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
  2507. }
  2508. m_func->m_headInstr->InsertAfter(ldSlotInstr);
  2509. if (m_lastInstr == m_func->m_headInstr)
  2510. {
  2511. m_lastInstr = ldSlotInstr;
  2512. }
  2513. }
  2514. void
  2515. IRBuilderAsmJs::GenerateLoopBodySlotAccesses(uint offset)
  2516. {
  2517. //
  2518. // The interpreter instance is passed as 0th argument to the JITted loop body function.
  2519. // Always load the argument, then use it to generate any necessary store-slots.
  2520. //
  2521. uint16 argument = 0;
  2522. StackSym *symSrc = StackSym::NewParamSlotSym(argument + 1, m_func);
  2523. symSrc->m_offset = (argument + LowererMD::GetFormalParamOffset()) * MachPtr;
  2524. symSrc->m_allocated = true;
  2525. IR::SymOpnd *srcOpnd = IR::SymOpnd::New(symSrc, TyMachPtr, m_func);
  2526. StackSym *loopParamSym = m_func->EnsureLoopParamSym();
  2527. IR::RegOpnd *loopParamOpnd = IR::RegOpnd::New(loopParamSym, TyMachPtr, m_func);
  2528. IR::Instr *instrArgIn = IR::Instr::New(Js::OpCode::ArgIn_A, loopParamOpnd, srcOpnd, m_func);
  2529. m_func->m_headInstr->InsertAfter(instrArgIn);
  2530. GenerateLoopBodyStSlots(loopParamSym->m_id, offset);
  2531. }
  2532. void
  2533. IRBuilderAsmJs::GenerateLoopBodyStSlots(SymID loopParamSymId, uint offset)
  2534. {
  2535. if (this->m_stSlots->Count() == 0)
  2536. {
  2537. return;
  2538. }
  2539. // Compute the offset to the start of the interpreter frame's locals array as a Var index.
  2540. size_t localsOffset = 0;
  2541. if (!m_IsTJLoopBody)
  2542. {
  2543. localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
  2544. }
  2545. Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
  2546. // Offset m_localSlot
  2547. const int intOffset = m_asmFuncInfo->GetIntByteOffset() / sizeof(int);
  2548. const int doubleOffset = m_asmFuncInfo->GetDoubleByteOffset() / sizeof(double);
  2549. const int floatOffset = m_asmFuncInfo->GetFloatByteOffset() / sizeof(float);
  2550. BOOL scale = true;
  2551. FOREACH_BITSET_IN_FIXEDBV(regSlot, this->m_stSlots)
  2552. {
  2553. Assert(!this->RegIsConstant((Js::RegSlot)regSlot));
  2554. Js::PropertyId propOffSet = 0;
  2555. IRType type = IRType::TyInt32;
  2556. IR::RegOpnd * regOpnd = nullptr;
  2557. if (RegIsIntVar(regSlot))
  2558. {
  2559. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(int));
  2560. // Get the bytecodeRegSlot
  2561. Js::PropertyId intRegSlot = regSlot - m_firstIntVar + m_asmFuncInfo->GetIntConstCount();
  2562. // Get the offset from m_localSlots
  2563. propOffSet = (Js::PropertyId)(intRegSlot + intOffset + localsStartSlot);
  2564. type = IRType::TyInt32;
  2565. regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
  2566. regOpnd->SetValueType(ValueType::GetInt(false));
  2567. }
  2568. else if (RegIsFloatVar(regSlot))
  2569. {
  2570. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(float));
  2571. // Get the bytecodeRegSlot
  2572. Js::PropertyId fltRegSlot = regSlot - m_firstFloatVar + m_asmFuncInfo->GetFloatConstCount();
  2573. // Get the offset from m_localSlots
  2574. propOffSet = (Js::PropertyId)(fltRegSlot + floatOffset + localsStartSlot);
  2575. type = IRType::TyFloat32;
  2576. regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
  2577. regOpnd->SetValueType(ValueType::Float);
  2578. }
  2579. else if (RegIsDoubleVar(regSlot))
  2580. {
  2581. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(double));
  2582. // Get the bytecodeRegSlot
  2583. Js::PropertyId dbRegSlot = regSlot - m_firstDoubleVar + m_asmFuncInfo->GetDoubleConstCount();
  2584. // Get the bytecodeRegSlot and Get the offset from m_localSlots
  2585. propOffSet = (Js::PropertyId)(dbRegSlot + doubleOffset + localsStartSlot);
  2586. type = IRType::TyFloat64;
  2587. // for double change the offset to ensure we don't have the same propertyId as the ints or floats
  2588. // this will be corrected in the lowering code and the right offset will be used
  2589. regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
  2590. regOpnd->SetValueType(ValueType::Float);
  2591. }
  2592. else if (RegIsSimd128Var(regSlot))
  2593. {
  2594. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset);
  2595. int simdOffset = m_asmFuncInfo->GetSimdByteOffset();
  2596. // Get the bytecodeRegSlot
  2597. Js::PropertyId dbRegSlot = regSlot - m_firstSimdVar + m_asmFuncInfo->GetSimdConstCount();
  2598. // Get the bytecodeRegSlot and Get the offset from m_localSlots
  2599. propOffSet = (Js::PropertyId)(dbRegSlot * sizeof(AsmJsSIMDValue) + simdOffset + localsStartSlot);
  2600. // 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.
  2601. // However, at this point all src syms are already defined and assigned a type.
  2602. type = IRType::TySimd128F4;
  2603. regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
  2604. regOpnd->SetValueType(ValueType::GetObject(ObjectType::UninitializedObject));
  2605. scale = false;
  2606. }
  2607. else
  2608. {
  2609. AnalysisAssert(UNREACHED);
  2610. }
  2611. if (scale)
  2612. {
  2613. // we will use the actual offset as the propertyId
  2614. propOffSet = propOffSet * TySize[type];
  2615. }
  2616. PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSymId, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
  2617. IR::SymOpnd * fieldSymOpnd = IR::SymOpnd::New(fieldSym, regOpnd->GetType(), m_func);
  2618. Js::OpCode opcode = Js::OpCode::StSlot;
  2619. IR::Instr * stSlotInstr = IR::Instr::New(opcode, fieldSymOpnd, regOpnd, m_func);
  2620. this->AddInstr(stSlotInstr, offset);
  2621. }
  2622. NEXT_BITSET_IN_FIXEDBV;
  2623. }
  2624. IR::Instr* IRBuilderAsmJs::GenerateStSlotForReturn(IR::RegOpnd* srcOpnd, IRType retType)
  2625. {
  2626. // Compute the offset to the start of the interpreter frame's locals array as a Var index.
  2627. size_t localsOffset = 0;
  2628. if (!m_IsTJLoopBody)
  2629. {
  2630. localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
  2631. }
  2632. Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
  2633. StackSym *loopParamSym = m_func->EnsureLoopParamSym();
  2634. Js::PropertyId propOffSet = 0;
  2635. // Offset m_localSlot
  2636. const int intOffset = m_asmFuncInfo->GetIntByteOffset() / sizeof(int);
  2637. const int doubleOffset = m_asmFuncInfo->GetDoubleByteOffset() / sizeof(double);
  2638. const int floatOffset = m_asmFuncInfo->GetFloatByteOffset() / sizeof(float);
  2639. const int simdOffset = m_asmFuncInfo->GetSimdByteOffset();
  2640. BOOL scale = true;
  2641. Js::PropertyId localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(int));
  2642. IRType type = IRType::TyInt32;
  2643. switch (retType)
  2644. {
  2645. case IRType::TyInt32:
  2646. propOffSet = (Js::PropertyId)(intOffset + localsStartSlot);
  2647. type = IRType::TyInt32;
  2648. break;
  2649. case IRType::TyFloat32:
  2650. localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(float));
  2651. propOffSet = (Js::PropertyId)(floatOffset + localsStartSlot);
  2652. type = IRType::TyFloat32;
  2653. break;
  2654. case IRType::TyFloat64:
  2655. localsStartSlot = (Js::PropertyId)(localsOffset / sizeof(double));
  2656. propOffSet = (Js::PropertyId)(doubleOffset + localsStartSlot);
  2657. type = IRType::TyFloat64;
  2658. break;
  2659. case IRType::TySimd128F4:
  2660. case IRType::TySimd128I4:
  2661. case IRType::TySimd128D2:
  2662. localsStartSlot = (Js::PropertyId)(localsOffset);
  2663. propOffSet = (Js::PropertyId)(simdOffset + localsStartSlot);
  2664. type = retType;
  2665. scale = false;
  2666. break;
  2667. default:
  2668. Assume(false);
  2669. }
  2670. if (scale)
  2671. {
  2672. // we will use the actual offset as the propertyId
  2673. propOffSet = propOffSet * TySize[type];
  2674. }
  2675. // Get the bytecodeRegSlot and Get the offset from m_localSlots
  2676. PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
  2677. IR::SymOpnd * fieldSymOpnd = IR::SymOpnd::New(fieldSym, srcOpnd->GetType(), m_func);
  2678. Js::OpCode opcode = Js::OpCode::StSlot;
  2679. IR::Instr * stSlotInstr = IR::Instr::New(opcode, fieldSymOpnd, srcOpnd, m_func);
  2680. return stSlotInstr;
  2681. }
  2682. inline Js::OpCode IRBuilderAsmJs::GetSimdOpcode(Js::OpCodeAsmJs asmjsOpcode)
  2683. {
  2684. Js::OpCode opcode = (Js::OpCode) 0;
  2685. Assert(IsSimd128AsmJsOpcode(asmjsOpcode));
  2686. if (asmjsOpcode <= Js::OpCodeAsmJs::Simd128_End)
  2687. {
  2688. opcode = m_simdOpcodesMap[(uint32)((Js::OpCodeAsmJs)asmjsOpcode - Js::OpCodeAsmJs::Simd128_Start)];
  2689. }
  2690. else
  2691. {
  2692. Assert(asmjsOpcode >= Js::OpCodeAsmJs::Simd128_Start_Extend && asmjsOpcode <= Js::OpCodeAsmJs::Simd128_End_Extend);
  2693. opcode = m_simdOpcodesMap[(uint32)((Js::OpCodeAsmJs)asmjsOpcode - Js::OpCodeAsmJs::Simd128_Start_Extend) + (uint32)(Js::OpCodeAsmJs::Simd128_End - Js::OpCodeAsmJs::Simd128_Start) + 1];
  2694. }
  2695. Assert(IsSimd128Opcode(opcode));
  2696. return opcode;
  2697. }
  2698. // !!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.
  2699. // Float32x4
  2700. template <typename SizePolicy>
  2701. void
  2702. IRBuilderAsmJs::BuildFloat32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2703. {
  2704. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2705. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2<SizePolicy>>();
  2706. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2707. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2708. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  2709. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2710. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2711. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2712. Js::OpCode opcode;
  2713. switch (newOpcode)
  2714. {
  2715. case Js::OpCodeAsmJs::Simd128_Return_F4:
  2716. if (m_func->IsLoopBody())
  2717. {
  2718. IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128F4);
  2719. AddInstr(slotInstr, offset);
  2720. }
  2721. opcode = Js::OpCode::Ld_A;
  2722. break;
  2723. case Js::OpCodeAsmJs::Simd128_I_Conv_VTF4:
  2724. case Js::OpCodeAsmJs::Simd128_Ld_F4:
  2725. opcode = Js::OpCode::Ld_A;
  2726. break;
  2727. default:
  2728. opcode = GetSimdOpcode(newOpcode);
  2729. }
  2730. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  2731. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  2732. AddInstr(instr, offset);
  2733. }
  2734. template <typename SizePolicy>
  2735. void
  2736. IRBuilderAsmJs::BuildFloat32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2737. {
  2738. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2739. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_3<SizePolicy>>();
  2740. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2741. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
  2742. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2743. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  2744. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2745. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  2746. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2747. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2748. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2749. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2750. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  2751. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  2752. AddInstr(instr, offset);
  2753. }
  2754. template <typename SizePolicy>
  2755. void
  2756. IRBuilderAsmJs::BuildFloat32x4_4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2757. {
  2758. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2759. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_4<SizePolicy>>();
  2760. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2761. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2762. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
  2763. Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->F4_3);
  2764. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  2765. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  2766. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128F4);
  2767. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2768. IR::Instr * instr = nullptr;
  2769. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2770. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2771. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2772. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2773. // Given bytecode: dst = op s1, s2, s3
  2774. // Generate:
  2775. // t1 = ExtendedArg_A s1
  2776. // t2 = ExtendedArg_A s2, t1
  2777. // t3 = ExtendedArg_A s3, t2
  2778. // dst = op t3
  2779. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  2780. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  2781. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2782. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2783. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2784. AssertMsg(opcode == Js::OpCode::Simd128_Select_I4, "Unexpected opcode for this format.");
  2785. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  2786. }
  2787. template <typename SizePolicy>
  2788. void IRBuilderAsmJs::BuildFloat32x4_1Float4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2789. {
  2790. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2791. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Float4<SizePolicy>>();
  2792. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2793. Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(layout->F1);
  2794. Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(layout->F2);
  2795. Js::RegSlot src3RegSlot = GetRegSlotFromFloatReg(layout->F3);
  2796. Js::RegSlot src4RegSlot = GetRegSlotFromFloatReg(layout->F4);
  2797. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  2798. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  2799. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
  2800. IR::RegOpnd * src4Opnd = BuildSrcOpnd(src4RegSlot, TyFloat32);
  2801. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2802. IR::Instr * instr = nullptr;
  2803. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2804. src1Opnd->SetValueType(ValueType::Float);
  2805. src2Opnd->SetValueType(ValueType::Float);
  2806. src3Opnd->SetValueType(ValueType::Float);
  2807. src4Opnd->SetValueType(ValueType::Float);
  2808. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  2809. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2810. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2811. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2812. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2813. AssertMsg(opcode == Js::OpCode::Simd128_FloatsToF4, "Unexpected opcode for this format.");
  2814. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  2815. }
  2816. template <typename SizePolicy>
  2817. void
  2818. IRBuilderAsmJs::BuildFloat32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2819. {
  2820. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2821. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2Int4<SizePolicy>>();
  2822. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2823. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2824. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2825. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  2826. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(layout->I2);
  2827. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
  2828. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
  2829. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
  2830. IR::Instr * instr = nullptr;
  2831. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2832. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2833. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  2834. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2835. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2836. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2837. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2838. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_F4;
  2839. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  2840. }
  2841. template <typename SizePolicy>
  2842. void
  2843. IRBuilderAsmJs::BuildFloat32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2844. {
  2845. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2846. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_3Int4<SizePolicy>>();
  2847. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2848. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2849. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
  2850. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2851. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  2852. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  2853. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
  2854. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
  2855. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
  2856. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(layout->I6);
  2857. IR::Instr * instr = nullptr;
  2858. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2859. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2860. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2861. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  2862. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2863. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2864. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2865. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2866. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2867. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_F4;
  2868. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  2869. }
  2870. template <typename SizePolicy>
  2871. void
  2872. IRBuilderAsmJs::BuildFloat32x4_1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2873. {
  2874. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2875. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Float1<SizePolicy>>();
  2876. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2877. Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(layout->F1);
  2878. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  2879. src1Opnd->SetValueType(ValueType::Float);
  2880. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2881. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2882. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_F4);
  2883. Js::OpCode opcode = Js::OpCode::Simd128_Splat_F4;
  2884. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  2885. AddInstr(instr, offset);
  2886. }
  2887. template <typename SizePolicy>
  2888. void
  2889. IRBuilderAsmJs::BuildFloat32x4_2Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2890. {
  2891. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2892. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2Float1<SizePolicy>>();
  2893. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2894. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2895. Js::RegSlot src2RegSlot = GetRegSlotFromFloatReg(layout->F2);
  2896. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  2897. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2898. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  2899. src1Opnd->SetValueType(ValueType::Float);
  2900. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2901. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2902. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2903. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  2904. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  2905. AddInstr(instr, offset);
  2906. }
  2907. template <typename SizePolicy>
  2908. void
  2909. IRBuilderAsmJs::BuildFloat32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2910. {
  2911. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2912. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Float64x2_1<SizePolicy>>();
  2913. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2914. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  2915. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  2916. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  2917. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2918. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2919. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2920. AssertMsg(opcode == Js::OpCode::Simd128_FromFloat64x2_F4 || opcode == Js::OpCode::Simd128_FromFloat64x2Bits_F4, "Unexpected opcode for this format.");
  2921. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  2922. AddInstr(instr, offset);
  2923. }
  2924. template <typename SizePolicy>
  2925. void
  2926. IRBuilderAsmJs::BuildFloat32x4_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2927. {
  2928. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2929. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Int32x4_1<SizePolicy>>();
  2930. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2931. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  2932. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  2933. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  2934. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2935. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2936. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2937. AssertMsg(opcode == Js::OpCode::Simd128_FromInt32x4_F4 || opcode == Js::OpCode::Simd128_FromInt32x4Bits_F4, "Unexpected opcode for this format.");
  2938. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  2939. AddInstr(instr, offset);
  2940. }
  2941. template <typename SizePolicy>
  2942. void
  2943. IRBuilderAsmJs::BuildFloat32x4_1Int32x4_1Float32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2944. {
  2945. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2946. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_1Int32x4_1Float32x4_2<SizePolicy>>();
  2947. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  2948. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  2949. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->F4_2);
  2950. Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->F4_3);
  2951. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  2952. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  2953. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128F4);
  2954. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  2955. IR::Instr * instr = nullptr;
  2956. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2957. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  2958. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2959. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2960. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  2961. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2962. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  2963. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  2964. AssertMsg(opcode == Js::OpCode::Simd128_Select_F4, "Unexpected opcode for this format.");
  2965. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  2966. }
  2967. template <typename SizePolicy>
  2968. void IRBuilderAsmJs::BuildReg1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2969. {
  2970. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2971. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Float32x4_1<SizePolicy>>();
  2972. Js::RegSlot srcRegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  2973. Js::RegSlot dstRegSlot = layout->R0;
  2974. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TySimd128F4);
  2975. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2976. IR::Instr * instr = nullptr;
  2977. IR::Opnd * dstOpnd = nullptr;
  2978. StackSym * symDst = nullptr;
  2979. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_F4)
  2980. {
  2981. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128F4);
  2982. symDst->m_allocated = true;
  2983. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  2984. {
  2985. AssertMsg(UNREACHED, "Arg count too big...");
  2986. Fatal();
  2987. }
  2988. dstOpnd = IR::SymOpnd::New(symDst, TySimd128F4, m_func);
  2989. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  2990. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  2991. AddInstr(instr, offset);
  2992. m_argStack->Push(instr);
  2993. }
  2994. else
  2995. {
  2996. Assert(UNREACHED);
  2997. }
  2998. }
  2999. template <typename SizePolicy>
  3000. void IRBuilderAsmJs::BuildInt1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3001. {
  3002. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3003. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float32x4_1<SizePolicy>>();
  3004. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
  3005. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  3006. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3007. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3008. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  3009. dstOpnd->SetValueType(ValueType::GetInt(false));
  3010. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3011. AssertMsg(opcode == Js::OpCode::Simd128_LdSignMask_F4, "Unexpected opcode for this format.");
  3012. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3013. AddInstr(instr, offset);
  3014. }
  3015. //Int32x4
  3016. template <typename SizePolicy>
  3017. void
  3018. IRBuilderAsmJs::BuildInt32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3019. {
  3020. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3021. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2<SizePolicy>>();
  3022. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3023. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3024. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3025. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3026. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3027. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3028. Js::OpCode opcode;
  3029. switch (newOpcode)
  3030. {
  3031. case Js::OpCodeAsmJs::Simd128_Return_I4:
  3032. if (m_func->IsLoopBody())
  3033. {
  3034. IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128I4);
  3035. AddInstr(slotInstr, offset);
  3036. }
  3037. opcode = Js::OpCode::Ld_A;
  3038. break;
  3039. case Js::OpCodeAsmJs::Simd128_I_Conv_VTI4:
  3040. case Js::OpCodeAsmJs::Simd128_Ld_I4:
  3041. opcode = Js::OpCode::Ld_A;
  3042. break;
  3043. default:
  3044. opcode = GetSimdOpcode(newOpcode);
  3045. }
  3046. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3047. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3048. AddInstr(instr, offset);
  3049. }
  3050. template <typename SizePolicy>
  3051. void
  3052. IRBuilderAsmJs::BuildInt32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3053. {
  3054. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3055. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_3<SizePolicy>>();
  3056. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3057. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3058. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->I4_2);
  3059. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3060. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3061. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
  3062. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3063. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3064. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3065. Js::OpCode opcode;
  3066. opcode = GetSimdOpcode(newOpcode);
  3067. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3068. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3069. AddInstr(instr, offset);
  3070. }
  3071. template <typename SizePolicy>
  3072. void
  3073. IRBuilderAsmJs::BuildInt32x4_4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3074. {
  3075. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3076. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_4<SizePolicy>>();
  3077. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3078. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3079. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->I4_2);
  3080. Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->I4_3);
  3081. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3082. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
  3083. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128I4);
  3084. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3085. IR::Instr * instr = nullptr;
  3086. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3087. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3088. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3089. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3090. // Given bytecode: dst = op s1, s2, s3
  3091. // Generate:
  3092. // t1 = ExtendedArg_A s1
  3093. // t2 = ExtendedArg_A s2, t1
  3094. // t3 = ExtendedArg_A s3, t2
  3095. // dst = op t3
  3096. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3097. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3098. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3099. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3100. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3101. AssertMsg(opcode == Js::OpCode::Simd128_Select_I4, "Unexpected opcode for this format.");
  3102. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3103. }
  3104. template <typename SizePolicy>
  3105. void IRBuilderAsmJs::BuildInt32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3106. {
  3107. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3108. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Int4<SizePolicy>>();
  3109. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3110. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(layout->I1);
  3111. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
  3112. Js::RegSlot src3RegSlot = GetRegSlotFromIntReg(layout->I3);
  3113. Js::RegSlot src4RegSlot = GetRegSlotFromIntReg(layout->I4);
  3114. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  3115. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3116. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyInt32);
  3117. IR::RegOpnd * src4Opnd = BuildSrcOpnd(src4RegSlot, TyInt32);
  3118. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3119. IR::Instr * instr = nullptr;
  3120. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3121. src1Opnd->SetValueType(ValueType::GetInt(false));
  3122. src2Opnd->SetValueType(ValueType::GetInt(false));
  3123. src3Opnd->SetValueType(ValueType::GetInt(false));
  3124. src4Opnd->SetValueType(ValueType::GetInt(false));
  3125. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3126. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3127. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3128. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3129. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3130. AssertMsg(opcode == Js::OpCode::Simd128_IntsToI4, "Unexpected opcode for this format.");
  3131. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3132. }
  3133. template <typename SizePolicy>
  3134. void IRBuilderAsmJs::BuildInt32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3135. {
  3136. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3137. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2Int4<SizePolicy>>();
  3138. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3139. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3140. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3141. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3142. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(layout->I2);
  3143. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
  3144. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
  3145. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
  3146. IR::Instr * instr = nullptr;
  3147. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3148. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3149. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3150. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3151. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3152. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3153. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3154. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_I4);
  3155. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_I4;
  3156. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3157. }
  3158. template <typename SizePolicy>
  3159. void IRBuilderAsmJs::BuildInt32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3160. {
  3161. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3162. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_3Int4<SizePolicy>>();
  3163. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3164. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3165. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->I4_2);
  3166. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3167. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3168. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
  3169. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
  3170. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
  3171. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(layout->I5);
  3172. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(layout->I6);
  3173. IR::Instr * instr = nullptr;
  3174. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3175. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3176. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3177. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3178. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3179. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3180. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3181. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3182. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3183. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_I4);
  3184. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_I4;
  3185. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3186. }
  3187. template <typename SizePolicy>
  3188. void
  3189. IRBuilderAsmJs::BuildInt32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3190. {
  3191. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3192. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Int1<SizePolicy>>();
  3193. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3194. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(layout->I1);
  3195. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  3196. src1Opnd->SetValueType(ValueType::GetInt(false));
  3197. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3198. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3199. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_I4);
  3200. Js::OpCode opcode = Js::OpCode::Simd128_Splat_I4;
  3201. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3202. AddInstr(instr, offset);
  3203. }
  3204. template <typename SizePolicy>
  3205. void
  3206. IRBuilderAsmJs::BuildInt32x4_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3207. {
  3208. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3209. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2Int1<SizePolicy>>();
  3210. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3211. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3212. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
  3213. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3214. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3215. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3216. src2Opnd->SetValueType(ValueType::GetInt(false));
  3217. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3218. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3219. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3220. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3221. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3222. AddInstr(instr, offset);
  3223. }
  3224. //ExtractLane ReplaceLane
  3225. template <typename SizePolicy>
  3226. void
  3227. IRBuilderAsmJs::BuildInt32x4_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3228. {
  3229. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3230. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_2Int2<SizePolicy>>();
  3231. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3232. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3233. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
  3234. Js::RegSlot src3RegSlot = GetRegSlotFromIntReg(layout->I3);
  3235. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3236. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3237. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3238. src2Opnd->SetValueType(ValueType::GetInt(false));
  3239. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyInt32);
  3240. src3Opnd->SetValueType(ValueType::GetInt(false));
  3241. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3242. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3243. // Given bytecode: dst = op s1, s2, s3
  3244. // Generate:
  3245. // t1 = ExtendedArg_A s1
  3246. // t2 = ExtendedArg_A s2, t1
  3247. // t3 = ExtendedArg_A s3, t2
  3248. // dst = op t3
  3249. IR::Instr* instr = nullptr;
  3250. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3251. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3252. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3253. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3254. AssertMsg((opcode == Js::OpCode::Simd128_ReplaceLane_I4), "Unexpected opcode for this format.");
  3255. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3256. }
  3257. template <typename SizePolicy>
  3258. void
  3259. IRBuilderAsmJs::BuildInt1Int32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3260. {
  3261. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3262. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Int32x4_1Int1<SizePolicy>>();
  3263. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
  3264. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3265. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
  3266. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3267. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3268. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3269. src2Opnd->SetValueType(ValueType::GetInt(false));
  3270. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  3271. dstOpnd->SetValueType(ValueType::GetInt(false));
  3272. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3273. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_I4), "Unexpected opcode for this format.");
  3274. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3275. AddInstr(instr, offset);
  3276. }
  3277. template <typename SizePolicy>
  3278. void
  3279. IRBuilderAsmJs::BuildFloat32x4_2Int1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3280. {
  3281. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3282. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float32x4_2Int1Float1<SizePolicy>>();
  3283. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
  3284. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  3285. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
  3286. Js::RegSlot src3RegSlot = GetRegSlotFromFloatReg(layout->F3);
  3287. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3288. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3289. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3290. src2Opnd->SetValueType(ValueType::GetInt(false));
  3291. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
  3292. src3Opnd->SetValueType(ValueType::Float);
  3293. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3294. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3295. // Given bytecode: dst = op s1, s2, s3
  3296. // Generate:
  3297. // t1 = ExtendedArg_A s1
  3298. // t2 = ExtendedArg_A s2, t1
  3299. // t3 = ExtendedArg_A s3, t2
  3300. // dst = op t3
  3301. IR::Instr* instr = nullptr;
  3302. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3303. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3304. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3305. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3306. AssertMsg((opcode == Js::OpCode::Simd128_ReplaceLane_F4), "Unexpected opcode for this format.");
  3307. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3308. }
  3309. template <typename SizePolicy>
  3310. void
  3311. IRBuilderAsmJs::BuildFloat1Float32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3312. {
  3313. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3314. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float1Float32x4_1Int1<SizePolicy>>();
  3315. Js::RegSlot dstRegSlot = GetRegSlotFromFloatReg(layout->F0);
  3316. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  3317. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(layout->I2);
  3318. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3319. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3320. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3321. src2Opnd->SetValueType(ValueType::GetInt(false));
  3322. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  3323. dstOpnd->SetValueType(ValueType::Float);
  3324. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3325. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_F4), "Unexpected opcode for this format.");
  3326. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3327. AddInstr(instr, offset);
  3328. }
  3329. template <typename SizePolicy>
  3330. void
  3331. IRBuilderAsmJs::BuildInt32x4_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3332. {
  3333. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3334. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Float32x4_1<SizePolicy>>();
  3335. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3336. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  3337. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3338. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3339. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3340. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3341. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3342. AssertMsg(opcode == Js::OpCode::Simd128_FromFloat32x4_I4 || opcode == Js::OpCode::Simd128_FromFloat32x4Bits_I4, "Unexpected opcode for this format.");
  3343. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3344. AddInstr(instr, offset);
  3345. }
  3346. template <typename SizePolicy>
  3347. void
  3348. IRBuilderAsmJs::BuildInt32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3349. {
  3350. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3351. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int32x4_1Float64x2_1<SizePolicy>>();
  3352. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
  3353. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3354. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3355. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3356. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3357. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3358. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3359. AssertMsg(opcode == Js::OpCode::Simd128_FromFloat64x2_I4 || opcode == Js::OpCode::Simd128_FromFloat64x2Bits_I4, "Unexpected opcode for this format.");
  3360. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3361. AddInstr(instr, offset);
  3362. }
  3363. template <typename SizePolicy>
  3364. void IRBuilderAsmJs::BuildReg1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3365. {
  3366. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3367. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Int32x4_1<SizePolicy>>();
  3368. Js::RegSlot srcRegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3369. Js::RegSlot dstRegSlot = layout->R0;
  3370. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TySimd128I4);
  3371. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3372. IR::Instr * instr = nullptr;
  3373. IR::Opnd * dstOpnd = nullptr;
  3374. StackSym * symDst = nullptr;
  3375. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_I4)
  3376. {
  3377. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128I4);
  3378. symDst->m_allocated = true;
  3379. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  3380. {
  3381. AssertMsg(UNREACHED, "Arg count too big...");
  3382. Fatal();
  3383. }
  3384. dstOpnd = IR::SymOpnd::New(symDst, TySimd128I4, m_func);
  3385. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3386. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  3387. AddInstr(instr, offset);
  3388. m_argStack->Push(instr);
  3389. }
  3390. else
  3391. {
  3392. Assert(UNREACHED);
  3393. }
  3394. }
  3395. template <typename SizePolicy>
  3396. void IRBuilderAsmJs::BuildInt1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3397. {
  3398. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3399. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Int32x4_1<SizePolicy>>();
  3400. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
  3401. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3402. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3403. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3404. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  3405. dstOpnd->SetValueType(ValueType::GetInt(false));
  3406. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3407. AssertMsg(opcode == Js::OpCode::Simd128_LdSignMask_I4, "Unexpected opcode for this format.");
  3408. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3409. AddInstr(instr, offset);
  3410. }
  3411. // Float64x2
  3412. template <typename SizePolicy>
  3413. void
  3414. IRBuilderAsmJs::BuildFloat64x2_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3415. {
  3416. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3417. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_2<SizePolicy>>();
  3418. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3419. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3420. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3421. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3422. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3423. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3424. Js::OpCode opcode;
  3425. switch (newOpcode)
  3426. {
  3427. case Js::OpCodeAsmJs::Simd128_Return_D2:
  3428. if (m_func->IsLoopBody())
  3429. {
  3430. IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128D2);
  3431. AddInstr(slotInstr, offset);
  3432. }
  3433. opcode = Js::OpCode::Ld_A;
  3434. break;
  3435. case Js::OpCodeAsmJs::Simd128_I_Conv_VTD2:
  3436. case Js::OpCodeAsmJs::Simd128_Ld_D2:
  3437. opcode = Js::OpCode::Ld_A;
  3438. break;
  3439. default:
  3440. opcode = GetSimdOpcode(newOpcode);
  3441. }
  3442. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3443. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3444. AddInstr(instr, offset);
  3445. }
  3446. template <typename SizePolicy>
  3447. void
  3448. IRBuilderAsmJs::BuildFloat64x2_3(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3449. {
  3450. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3451. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_3<SizePolicy>>();
  3452. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3453. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3454. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
  3455. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3456. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3457. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3458. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3459. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3460. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3461. Js::OpCode opcode;
  3462. opcode = GetSimdOpcode(newOpcode);
  3463. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3464. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3465. AddInstr(instr, offset);
  3466. }
  3467. template <typename SizePolicy>
  3468. void
  3469. IRBuilderAsmJs::BuildFloat64x2_4(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3470. {
  3471. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3472. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_4<SizePolicy>>();
  3473. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3474. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3475. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
  3476. Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->D2_3);
  3477. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3478. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3479. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128D2);
  3480. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3481. IR::Instr * instr = nullptr;
  3482. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3483. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3484. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3485. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3486. // Given bytecode: dst = op s1, s2, s3
  3487. // Generate:
  3488. // t1 = ExtendedArg_A s1
  3489. // t2 = ExtendedArg_A s2, t1
  3490. // t3 = ExtendedArg_A s3, t2
  3491. // dst = op t3
  3492. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3493. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3494. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3495. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3496. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3497. AssertMsg(opcode == Js::OpCode::Simd128_Clamp_D2, "Unexpected opcode for this format.");
  3498. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3499. }
  3500. template <typename SizePolicy>
  3501. void IRBuilderAsmJs::BuildFloat64x2_1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3502. {
  3503. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3504. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Double2<SizePolicy >> ();
  3505. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3506. Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(layout->D1);
  3507. Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(layout->D2);
  3508. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  3509. src1Opnd->SetValueType(ValueType::Float);
  3510. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  3511. src2Opnd->SetValueType(ValueType::Float);
  3512. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3513. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3514. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3515. AssertMsg(opcode == Js::OpCode::Simd128_DoublesToD2, "Invalid backend SIMD opcode");
  3516. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3517. AddInstr(instr, offset);
  3518. }
  3519. template <typename SizePolicy>
  3520. void IRBuilderAsmJs::BuildFloat64x2_1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3521. {
  3522. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3523. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Double1<SizePolicy>>();
  3524. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3525. Js::RegSlot src1RegSlot = GetRegSlotFromDoubleReg(layout->D1);
  3526. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  3527. src1Opnd->SetValueType(ValueType::Float);
  3528. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3529. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3530. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3531. AssertMsg(opcode == Js::OpCode::Simd128_Splat_D2, "Invalid backend SIMD opcode");
  3532. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3533. AddInstr(instr, offset);
  3534. }
  3535. template <typename SizePolicy>
  3536. void
  3537. IRBuilderAsmJs::BuildFloat64x2_2Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3538. {
  3539. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3540. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_2Double1<SizePolicy>>();
  3541. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3542. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3543. Js::RegSlot src2RegSlot = GetRegSlotFromDoubleReg(layout->D2);
  3544. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3545. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3546. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  3547. src1Opnd->SetValueType(ValueType::Float);
  3548. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3549. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3550. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3551. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3552. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3553. AddInstr(instr, offset);
  3554. }
  3555. template <typename SizePolicy>
  3556. void
  3557. IRBuilderAsmJs::BuildFloat64x2_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3558. {
  3559. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3560. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_2Int2<SizePolicy>>();
  3561. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3562. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3563. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3564. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3565. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(layout->I2);
  3566. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
  3567. IR::Instr * instr = nullptr;
  3568. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3569. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3570. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3571. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3572. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3573. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_D2);
  3574. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_D2;
  3575. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3576. }
  3577. template <typename SizePolicy>
  3578. void
  3579. IRBuilderAsmJs::BuildFloat64x2_3Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3580. {
  3581. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3582. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_3Int2<SizePolicy>>();
  3583. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3584. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3585. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
  3586. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3587. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3588. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3589. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(layout->I3);
  3590. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(layout->I4);
  3591. IR::Instr * instr = nullptr;
  3592. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3593. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3594. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3595. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3596. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3597. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3598. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3599. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_D2);
  3600. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_D2;
  3601. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3602. }
  3603. template <typename SizePolicy>
  3604. void
  3605. IRBuilderAsmJs::BuildFloat64x2_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3606. {
  3607. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3608. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Float32x4_1<SizePolicy>>();
  3609. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3610. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->F4_1);
  3611. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3612. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3613. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3614. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3615. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3616. AssertMsg(opcode == Js::OpCode::Simd128_FromFloat32x4_D2 || opcode == Js::OpCode::Simd128_FromFloat32x4Bits_D2, "Unexpected opcode for this format.");
  3617. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3618. AddInstr(instr, offset);
  3619. }
  3620. template <typename SizePolicy>
  3621. void
  3622. IRBuilderAsmJs::BuildFloat64x2_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3623. {
  3624. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3625. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Int32x4_1<SizePolicy>>();
  3626. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3627. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3628. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3629. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3630. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3631. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3632. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3633. AssertMsg(opcode == Js::OpCode::Simd128_FromInt32x4_D2 || opcode == Js::OpCode::Simd128_FromInt32x4Bits_D2, "Unexpected opcode for this format.");
  3634. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3635. AddInstr(instr, offset);
  3636. }
  3637. template <typename SizePolicy>
  3638. void
  3639. IRBuilderAsmJs::BuildFloat64x2_1Int32x4_1Float64x2_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3640. {
  3641. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3642. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Float64x2_1Int32x4_1Float64x2_2<SizePolicy>>();
  3643. Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->D2_0);
  3644. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
  3645. Js::RegSlot src2RegSlot = GetRegSlotFromSimd128Reg(layout->D2_2);
  3646. Js::RegSlot src3RegSlot = GetRegSlotFromSimd128Reg(layout->D2_3);
  3647. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3648. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3649. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128D2);
  3650. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3651. IR::Instr * instr = nullptr;
  3652. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3653. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3654. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3655. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3656. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3657. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3658. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3659. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3660. AssertMsg(opcode == Js::OpCode::Simd128_Select_D2, "Unexpected opcode for this format.");
  3661. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3662. }
  3663. template <typename SizePolicy>
  3664. void IRBuilderAsmJs::BuildReg1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3665. {
  3666. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3667. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Reg1Float64x2_1<SizePolicy>>();
  3668. Js::RegSlot srcRegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3669. Js::RegSlot dstRegSlot = layout->R0;
  3670. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TySimd128D2);
  3671. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3672. IR::Instr * instr = nullptr;
  3673. IR::Opnd * dstOpnd = nullptr;
  3674. StackSym * symDst = nullptr;
  3675. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_D2)
  3676. {
  3677. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128D2);
  3678. symDst->m_allocated = true;
  3679. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  3680. {
  3681. AssertMsg(UNREACHED, "Arg count too big...");
  3682. Fatal();
  3683. }
  3684. dstOpnd = IR::SymOpnd::New(symDst, TySimd128D2, m_func);
  3685. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3686. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  3687. AddInstr(instr, offset);
  3688. m_argStack->Push(instr);
  3689. }
  3690. else
  3691. {
  3692. Assert(UNREACHED);
  3693. }
  3694. }
  3695. template <typename SizePolicy>
  3696. void IRBuilderAsmJs::BuildInt1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3697. {
  3698. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3699. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_Int1Float64x2_1<SizePolicy>>();
  3700. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(layout->I0);
  3701. Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->D2_1);
  3702. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3703. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3704. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  3705. dstOpnd->SetValueType(ValueType::GetInt(false));
  3706. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3707. AssertMsg(opcode == Js::OpCode::Simd128_LdSignMask_D2, "Unexpected opcode for this format.");
  3708. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3709. AddInstr(instr, offset);
  3710. }
  3711. template <typename SizePolicy>
  3712. void IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset)
  3713. {
  3714. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  3715. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmSimdTypedArr<SizePolicy>>();
  3716. BuildAsmSimdTypedArr(newOpcode, offset, layout->SlotIndex, layout->Value, layout->ViewType, layout->DataWidth);
  3717. }
  3718. void
  3719. IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, int8 viewType, uint8 dataWidth)
  3720. {
  3721. IRType type = TySimd128F4;
  3722. Js::RegSlot valueRegSlot = GetRegSlotFromSimd128Reg(value);
  3723. IR::RegOpnd * maskedOpnd = nullptr;
  3724. IR::Instr * maskInstr = nullptr;
  3725. Js::OpCode op = GetSimdOpcode(newOpcode);
  3726. ValueType arrayType, valueType;
  3727. bool isLd = false, isConst = false;
  3728. uint32 mask = 0;
  3729. switch (newOpcode)
  3730. {
  3731. case Js::OpCodeAsmJs::Simd128_LdArr_I4:
  3732. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  3733. isLd = true;
  3734. isConst = false;
  3735. type = TySimd128I4;
  3736. break;
  3737. case Js::OpCodeAsmJs::Simd128_LdArr_F4:
  3738. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  3739. isLd = true;
  3740. isConst = false;
  3741. type = TySimd128F4;
  3742. break;
  3743. case Js::OpCodeAsmJs::Simd128_LdArr_D2:
  3744. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  3745. isLd = true;
  3746. isConst = false;
  3747. type = TySimd128D2;
  3748. break;
  3749. case Js::OpCodeAsmJs::Simd128_StArr_I4:
  3750. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  3751. isLd = false;
  3752. isConst = false;
  3753. type = TySimd128I4;
  3754. break;
  3755. case Js::OpCodeAsmJs::Simd128_StArr_F4:
  3756. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  3757. isLd = false;
  3758. isConst = false;
  3759. type = TySimd128F4;
  3760. break;
  3761. case Js::OpCodeAsmJs::Simd128_StArr_D2:
  3762. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  3763. isLd = false;
  3764. isConst = false;
  3765. type = TySimd128D2;
  3766. break;
  3767. case Js::OpCodeAsmJs::Simd128_LdArrConst_I4:
  3768. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  3769. isLd = true;
  3770. isConst = true;
  3771. type = TySimd128I4;
  3772. break;
  3773. case Js::OpCodeAsmJs::Simd128_LdArrConst_F4:
  3774. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  3775. isLd = true;
  3776. isConst = true;
  3777. type = TySimd128F4;
  3778. break;
  3779. case Js::OpCodeAsmJs::Simd128_LdArrConst_D2:
  3780. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  3781. isLd = true;
  3782. isConst = true;
  3783. type = TySimd128D2;
  3784. break;
  3785. case Js::OpCodeAsmJs::Simd128_StArrConst_I4:
  3786. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  3787. isLd = false;
  3788. type = TySimd128I4;
  3789. isConst = true;
  3790. break;
  3791. case Js::OpCodeAsmJs::Simd128_StArrConst_F4:
  3792. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  3793. isLd = false;
  3794. isConst = true;
  3795. type = TySimd128F4;
  3796. break;
  3797. case Js::OpCodeAsmJs::Simd128_StArrConst_D2:
  3798. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  3799. isLd = false;
  3800. isConst = true;
  3801. type = TySimd128D2;
  3802. break;
  3803. default:
  3804. Assert(UNREACHED);
  3805. }
  3806. switch (viewType)
  3807. {
  3808. case Js::ArrayBufferView::TYPE_INT8:
  3809. arrayType = ValueType::GetObject(ObjectType::Int8Array);
  3810. break;
  3811. case Js::ArrayBufferView::TYPE_UINT8:
  3812. arrayType = ValueType::GetObject(ObjectType::Uint8Array);
  3813. break;
  3814. case Js::ArrayBufferView::TYPE_INT16:
  3815. arrayType = ValueType::GetObject(ObjectType::Int16Array);
  3816. mask = (uint32)~1;
  3817. break;
  3818. case Js::ArrayBufferView::TYPE_UINT16:
  3819. arrayType = ValueType::GetObject(ObjectType::Uint16Array);
  3820. mask = (uint32)~1;
  3821. break;
  3822. case Js::ArrayBufferView::TYPE_INT32:
  3823. arrayType = ValueType::GetObject(ObjectType::Int32Array);
  3824. mask = (uint32)~3;
  3825. break;
  3826. case Js::ArrayBufferView::TYPE_UINT32:
  3827. arrayType = ValueType::GetObject(ObjectType::Uint32Array);
  3828. mask = (uint32)~3;
  3829. break;
  3830. case Js::ArrayBufferView::TYPE_FLOAT32:
  3831. arrayType = ValueType::GetObject(ObjectType::Float32Array);
  3832. mask = (uint32)~3;
  3833. break;
  3834. case Js::ArrayBufferView::TYPE_FLOAT64:
  3835. arrayType = ValueType::GetObject(ObjectType::Float64Array);
  3836. mask = (uint32)~7;
  3837. break;
  3838. default:
  3839. Assert(UNREACHED);
  3840. }
  3841. IR::Opnd * sizeOpnd = BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32);
  3842. if (!isConst)
  3843. {
  3844. Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
  3845. if (mask)
  3846. {
  3847. // AND_I4 index, mask
  3848. maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
  3849. maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
  3850. }
  3851. else
  3852. {
  3853. maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
  3854. }
  3855. }
  3856. IR::Instr * instr = nullptr;
  3857. IR::RegOpnd * regOpnd = nullptr;
  3858. IR::IndirOpnd * indirOpnd = nullptr;
  3859. IR::RegOpnd * baseOpnd = BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar);
  3860. baseOpnd->SetValueType(arrayType);
  3861. baseOpnd->SetValueTypeFixed();
  3862. if (isLd)
  3863. {
  3864. regOpnd = BuildDstOpnd(valueRegSlot, type);
  3865. regOpnd->SetValueType(valueType);
  3866. if (!isConst)
  3867. {
  3868. Assert(maskedOpnd);
  3869. // Js::OpCodeAsmJs::Simd128_LdArr_I4:
  3870. // Js::OpCodeAsmJs::Simd128_LdArr_F4:
  3871. // Js::OpCodeAsmJs::Simd128_LdArr_D2:
  3872. indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
  3873. }
  3874. else
  3875. {
  3876. // Js::OpCodeAsmJs::Simd128_LdArrConst_I4:
  3877. // Js::OpCodeAsmJs::Simd128_LdArrConst_F4:
  3878. // Js::OpCodeAsmJs::Simd128_LdArrConst_D2:
  3879. indirOpnd = IR::IndirOpnd::New(baseOpnd, slotIndex, type, m_func);
  3880. }
  3881. instr = IR::Instr::New(op, regOpnd, indirOpnd, sizeOpnd, m_func);
  3882. }
  3883. else
  3884. {
  3885. regOpnd = BuildSrcOpnd(valueRegSlot, type);
  3886. regOpnd->SetValueType(valueType);
  3887. if (!isConst)
  3888. {
  3889. Assert(maskedOpnd);
  3890. // Js::OpCodeAsmJs::Simd128_StArr_I4:
  3891. // Js::OpCodeAsmJs::Simd128_StArr_F4:
  3892. // Js::OpCodeAsmJs::Simd128_StArr_D2:
  3893. indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
  3894. }
  3895. else
  3896. {
  3897. // Js::OpCodeAsmJs::Simd128_StArrConst_I4:
  3898. // Js::OpCodeAsmJs::Simd128_StArrConst_F4:
  3899. // Js::OpCodeAsmJs::Simd128_StArrConst_D2:
  3900. indirOpnd = IR::IndirOpnd::New(baseOpnd, slotIndex, type, m_func);
  3901. }
  3902. instr = IR::Instr::New(op, indirOpnd, regOpnd, sizeOpnd, m_func);
  3903. }
  3904. // REVIEW: Store dataWidth in the instruction itself instead of an argument to avoid using ExtendedArgs or excessive opcodes.
  3905. Assert(dataWidth >= 4 && dataWidth <= 16);
  3906. instr->dataWidth = dataWidth;
  3907. if (maskInstr)
  3908. {
  3909. AddInstr(maskInstr, offset);
  3910. }
  3911. AddInstr(instr, offset);
  3912. }