IRBuilderAsmJs.cpp 173 KB

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