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