Opnd.cpp 110 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. namespace IR
  7. {
  8. ///----------------------------------------------------------------------------
  9. ///
  10. /// Opnd::UseWithNewType
  11. ///
  12. /// Creates a Use (a copy if already in use or returns the same)
  13. /// and sets it type
  14. ///
  15. ///----------------------------------------------------------------------------
  16. Opnd*
  17. Opnd::UseWithNewType(IRType type, Func * func)
  18. {
  19. Opnd * res = this->Use(func);
  20. res->SetType(type);
  21. StackSym* sym = res->GetStackSym();
  22. if (sym)
  23. {
  24. if (TySize[sym->GetType()] < TySize[type])
  25. {
  26. Assert(!sym->IsAllocated());
  27. sym->m_type = type;
  28. }
  29. }
  30. return res;
  31. }
  32. bool
  33. Opnd::IsTaggedInt() const
  34. {
  35. return GetValueType().IsTaggedInt();
  36. }
  37. bool
  38. Opnd::IsTaggedValue() const
  39. {
  40. CompileAssert(!FLOATVAR || INT32VAR);
  41. #if FLOATVAR
  42. return GetValueType().IsNumber();
  43. #else
  44. return IsTaggedInt();
  45. #endif
  46. }
  47. bool
  48. Opnd::IsNotNumber() const
  49. {
  50. if (this->GetValueType().IsNotNumber())
  51. {
  52. return true;
  53. }
  54. if (this->IsRegOpnd())
  55. {
  56. const IR::RegOpnd* regOpnd = this->AsRegOpnd();
  57. if (regOpnd->m_sym == nullptr)
  58. {
  59. return true;
  60. }
  61. if (regOpnd->m_sym->m_isNotInt)
  62. {
  63. // m_isNotInt actually means "is not number". It should not be set to true for definitely-float values.
  64. return true;
  65. }
  66. }
  67. return false;
  68. }
  69. bool
  70. Opnd::IsNotInt() const
  71. {
  72. return IsNotNumber() || IsFloat();
  73. }
  74. bool
  75. Opnd::IsNotTaggedValue() const
  76. {
  77. if (!PHASE_OFF1(Js::OptTagChecksPhase) && this->GetValueType().IsNotTaggedValue())
  78. {
  79. return true;
  80. }
  81. return this->IsNotNumber();
  82. }
  83. bool
  84. Opnd::IsWriteBarrierTriggerableValue()
  85. {
  86. // Determines whether if an operand is used as a source in a store instruction, whether the store needs a write barrier
  87. // If it's a tagged value, we don't need a write barrier
  88. if (this->IsTaggedValue())
  89. {
  90. return false;
  91. }
  92. // If this operand is known address, then it doesn't need a write barrier, the address is either not a GC address or is pinned
  93. if (this->IsAddrOpnd() && static_cast<AddrOpndKind>(this->AsAddrOpnd()->GetKind()) == AddrOpndKindDynamicVar)
  94. {
  95. return false;
  96. }
  97. if (TySize[this->GetType()] != sizeof(void*))
  98. {
  99. return false;
  100. }
  101. #if DBG
  102. if (CONFIG_FLAG(ForceSoftwareWriteBarrier) && CONFIG_FLAG(VerifyBarrierBit))
  103. {
  104. return true; // No further optimization if we are in verification
  105. }
  106. #endif
  107. // If its null/boolean/undefined, we don't need a write barrier since the javascript library will keep those guys alive
  108. return !(this->GetValueType().IsBoolean() || this->GetValueType().IsNull() || this->GetValueType().IsUndefined());
  109. }
  110. /*
  111. * This is a devirtualized functions See the note above Opnd:Copy()
  112. */
  113. OpndKind Opnd::GetKind() const
  114. {
  115. return this->m_kind;
  116. }
  117. /*
  118. * This is a devirtualized functions See the note above Opnd:Copy()
  119. */
  120. Opnd *
  121. Opnd::CloneDef(Func *func)
  122. {
  123. switch (this->m_kind)
  124. {
  125. case OpndKindSym:
  126. if ((*static_cast<SymOpnd*>(this)).IsPropertySymOpnd())
  127. {
  128. return static_cast<PropertySymOpnd*>(this)->CloneDefInternalSub(func);
  129. }
  130. return static_cast<SymOpnd*>(this)->CloneDefInternal(func);
  131. case OpndKindReg:
  132. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  133. {
  134. return static_cast<ArrayRegOpnd*>(this)->CloneDefInternalSub(func);
  135. }
  136. return static_cast<RegOpnd*>(this)->CloneDefInternal(func);
  137. case OpndKindIndir:
  138. return static_cast<IndirOpnd*>(this)->CloneDefInternal(func);
  139. default:
  140. return this->Copy(func);
  141. };
  142. }
  143. /*
  144. * This is a devirtualized functions See the note above Opnd:Copy()
  145. */
  146. Opnd *
  147. Opnd::CloneUse(Func *func)
  148. {
  149. switch (this->m_kind)
  150. {
  151. case OpndKindSym:
  152. if ((*static_cast<SymOpnd*>(this)).IsPropertySymOpnd())
  153. {
  154. return static_cast<PropertySymOpnd*>(this)->CloneUseInternalSub(func);
  155. }
  156. return static_cast<SymOpnd*>(this)->CloneUseInternal(func);
  157. case OpndKindReg:
  158. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  159. {
  160. return static_cast<ArrayRegOpnd*>(this)->CloneUseInternalSub(func);
  161. }
  162. return static_cast<RegOpnd*>(this)->CloneUseInternal(func);
  163. case OpndKindIndir:
  164. return static_cast<IndirOpnd*>(this)->CloneUseInternal(func);
  165. default:
  166. return this->Copy(func);
  167. };
  168. }
  169. /*
  170. * This is a devirtualized functions See the note above Opnd:Copy()
  171. */
  172. void Opnd::Free(Func *func)
  173. {
  174. switch (this->m_kind)
  175. {
  176. case OpndKindIntConst:
  177. //NOTE: use to be Sealed do not do sub class checks like in CloneUse
  178. static_cast<IntConstOpnd*>(this)->FreeInternal(func);
  179. break;
  180. case OpndKindInt64Const:
  181. return static_cast<Int64ConstOpnd*>(this)->FreeInternal(func);
  182. case OpndKindSimd128Const:
  183. static_cast<Simd128ConstOpnd*>(this)->FreeInternal(func);
  184. break;
  185. case OpndKindFloatConst:
  186. static_cast<FloatConstOpnd*>(this)->FreeInternal(func);
  187. break;
  188. case OpndKindHelperCall:
  189. static_cast<HelperCallOpnd*>(this)->FreeInternal(func);
  190. break;
  191. case OpndKindSym:
  192. static_cast<SymOpnd*>(this)->FreeInternal(func);
  193. break;
  194. case OpndKindReg:
  195. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  196. {
  197. static_cast<ArrayRegOpnd*>(this)->FreeInternalSub(func);
  198. break;
  199. }
  200. static_cast<RegOpnd*>(this)->FreeInternal(func);
  201. break;
  202. case OpndKindAddr:
  203. static_cast<AddrOpnd*>(this)->FreeInternal(func);
  204. break;
  205. case OpndKindIndir:
  206. static_cast<IndirOpnd*>(this)->FreeInternal(func);
  207. break;
  208. case OpndKindMemRef:
  209. static_cast<MemRefOpnd*>(this)->FreeInternal(func);
  210. break;
  211. case OpndKindLabel:
  212. static_cast<LabelOpnd*>(this)->FreeInternal(func);
  213. break;
  214. case OpndKindRegBV:
  215. static_cast<RegBVOpnd*>(this)->FreeInternal(func);
  216. break;
  217. default:
  218. Assert(UNREACHED);
  219. __assume(UNREACHED);
  220. };
  221. #if DBG
  222. if (func->m_alloc->HasDelayFreeList())
  223. {
  224. this->isDeleted = true;
  225. }
  226. #endif
  227. }
  228. /*
  229. * This is a devirtualized functions See the note above Opnd:Copy()
  230. */
  231. bool Opnd::IsEqual(Opnd *opnd)
  232. {
  233. switch (this->m_kind)
  234. {
  235. case OpndKindIntConst:
  236. return static_cast<IntConstOpnd*>(this)->IsEqualInternal(opnd);
  237. case OpndKindInt64Const:
  238. return static_cast<Int64ConstOpnd*>(this)->IsEqualInternal(opnd);
  239. case OpndKindFloatConst:
  240. return static_cast<FloatConstOpnd*>(this)->IsEqualInternal(opnd);
  241. case OpndKindHelperCall:
  242. if ((*static_cast<HelperCallOpnd*>(this)).IsDiagHelperCallOpnd())
  243. {
  244. return static_cast<DiagHelperCallOpnd*>(this)->IsEqualInternalSub(opnd);
  245. }
  246. return static_cast<HelperCallOpnd*>(this)->IsEqualInternal(opnd);
  247. case OpndKindSym:
  248. //NOTE: use to be Sealed do not do sub class checks like in CloneUse
  249. return static_cast<SymOpnd*>(this)->IsEqualInternal(opnd);
  250. case OpndKindReg:
  251. //NOTE: not sealed but ArrayRegOpnd::isEqual function does not exist, default to RegOpnd only
  252. return static_cast<RegOpnd*>(this)->IsEqualInternal(opnd);
  253. case OpndKindAddr:
  254. return static_cast<AddrOpnd*>(this)->IsEqualInternal(opnd);
  255. case OpndKindIndir:
  256. return static_cast<IndirOpnd*>(this)->IsEqualInternal(opnd);
  257. case OpndKindMemRef:
  258. return static_cast<MemRefOpnd*>(this)->IsEqualInternal(opnd);
  259. case OpndKindLabel:
  260. return static_cast<LabelOpnd*>(this)->IsEqualInternal(opnd);
  261. case OpndKindRegBV:
  262. return static_cast<RegBVOpnd*>(this)->IsEqualInternal(opnd);
  263. default:
  264. Assert(UNREACHED);
  265. __assume(UNREACHED);
  266. };
  267. }
  268. /*
  269. * This is a devirtualized functions If you inherit from any of the child classes of Opnd
  270. * And would like to override the default method behavior you must add an
  271. * Is<your new Opnd Type>Opnd() call and check for it like in examples
  272. * HelperCallOpnd, PropertySymOpnd, & RegOpnd
  273. */
  274. Opnd * Opnd::Copy(Func *func)
  275. {
  276. switch (this->m_kind)
  277. {
  278. case OpndKindIntConst:
  279. return static_cast<IntConstOpnd*>(this)->CopyInternal(func);
  280. case OpndKindInt64Const:
  281. return static_cast<Int64ConstOpnd*>(this)->CopyInternal(func);
  282. case OpndKindFloatConst:
  283. return static_cast<FloatConstOpnd*>(this)->CopyInternal(func);
  284. case OpndKindHelperCall:
  285. if ((*static_cast<HelperCallOpnd*>(this)).IsDiagHelperCallOpnd())
  286. {
  287. return static_cast<DiagHelperCallOpnd*>(this)->CopyInternalSub(func);
  288. }
  289. return static_cast<HelperCallOpnd*>(this)->CopyInternal(func);
  290. case OpndKindSym:
  291. if ((*static_cast<SymOpnd*>(this)).IsPropertySymOpnd())
  292. {
  293. return static_cast<PropertySymOpnd*>(this)->CopyInternalSub(func);
  294. }
  295. return static_cast<SymOpnd*>(this)->CopyInternal(func);
  296. case OpndKindReg:
  297. if ((*static_cast<RegOpnd*>(this)).IsArrayRegOpnd())
  298. {
  299. return static_cast<ArrayRegOpnd*>(this)->CopyInternalSub(func);
  300. }
  301. return static_cast<RegOpnd*>(this)->CopyInternal(func);
  302. case OpndKindAddr:
  303. return static_cast<AddrOpnd*>(this)->CopyInternal(func);
  304. case OpndKindIndir:
  305. return static_cast<IndirOpnd*>(this)->CopyInternal(func);
  306. case OpndKindMemRef:
  307. return static_cast<MemRefOpnd*>(this)->CopyInternal(func);
  308. case OpndKindLabel:
  309. return static_cast<LabelOpnd*>(this)->CopyInternal(func);
  310. case OpndKindRegBV:
  311. return static_cast<RegBVOpnd*>(this)->CopyInternal(func);
  312. default:
  313. Assert(UNREACHED);
  314. __assume(UNREACHED);
  315. };
  316. }
  317. StackSym *
  318. Opnd::GetStackSym() const
  319. {
  320. switch (this->GetKind())
  321. {
  322. case OpndKindSym:
  323. return static_cast<SymOpnd const *>(this)->GetStackSymInternal();
  324. case OpndKindReg:
  325. return static_cast<RegOpnd const *>(this)->GetStackSymInternal();
  326. default:
  327. return nullptr;
  328. }
  329. }
  330. Sym*
  331. Opnd::GetSym() const
  332. {
  333. switch (this->GetKind())
  334. {
  335. case OpndKindSym:
  336. return static_cast<SymOpnd const *>(this)->m_sym;
  337. case OpndKindReg:
  338. return static_cast<RegOpnd const *>(this)->m_sym;
  339. default:
  340. return nullptr;
  341. }
  342. }
  343. int64
  344. Opnd::GetImmediateValue(Func* func)
  345. {
  346. switch (this->GetKind())
  347. {
  348. case OpndKindIntConst:
  349. return this->AsIntConstOpnd()->GetValue();
  350. case OpndKindInt64Const:
  351. return this->AsInt64ConstOpnd()->GetValue();
  352. case OpndKindAddr:
  353. return (intptr_t)this->AsAddrOpnd()->m_address;
  354. case OpndKindHelperCall:
  355. return (intptr_t)IR::GetMethodAddress(func->GetThreadContextInfo(), this->AsHelperCallOpnd());
  356. default:
  357. AssertMsg(UNREACHED, "Unexpected immediate opnd kind");
  358. return 0;
  359. }
  360. }
  361. #if TARGET_32 && !defined(_M_IX86)
  362. int32
  363. Opnd::GetImmediateValueAsInt32(Func * func)
  364. {
  365. Assert(!IRType_IsInt64(this->GetType()));
  366. Assert(this->GetKind() != OpndKindInt64Const);
  367. return (int32)this->GetImmediateValue(func);
  368. }
  369. #endif
  370. BailoutConstantValue Opnd::GetConstValue()
  371. {
  372. BailoutConstantValue value;
  373. if (this->IsIntConstOpnd())
  374. {
  375. value.InitIntConstValue(this->AsIntConstOpnd()->GetValue(), this->m_type);
  376. }
  377. else if (this->IsFloatConstOpnd())
  378. {
  379. value.InitFloatConstValue(this->AsFloatConstOpnd()->m_value);
  380. }
  381. else
  382. {
  383. AssertMsg(this->IsAddrOpnd(), "Unexpected const sym");
  384. value.InitVarConstValue(this->AsAddrOpnd()->m_address);
  385. }
  386. return value;
  387. }
  388. void Opnd::SetValueType(const ValueType valueType)
  389. {
  390. if(m_isValueTypeFixed)
  391. {
  392. return;
  393. }
  394. // ArrayRegOpnd has information specific to the array type, so make sure that doesn't change
  395. Assert(
  396. !IsRegOpnd() ||
  397. !AsRegOpnd()->IsArrayRegOpnd() ||
  398. valueType.IsObject() && valueType.GetObjectType() == m_valueType.GetObjectType());
  399. m_valueType = valueType;
  400. }
  401. bool Opnd::IsScopeObjOpnd(Func * func)
  402. {
  403. if (IsRegOpnd())
  404. {
  405. return this->GetStackSym() == func->GetScopeObjSym();
  406. }
  407. else if(IsSymOpnd() && AsSymOpnd()->m_sym->IsPropertySym())
  408. {
  409. return this->AsSymOpnd()->m_sym->AsPropertySym()->m_stackSym == func->GetScopeObjSym();
  410. }
  411. return false;
  412. }
  413. ValueType Opnd::FindProfiledValueType()
  414. {
  415. if (!this->GetValueType().IsUninitialized())
  416. {
  417. return this->GetValueType();
  418. }
  419. // could be expanded to cover additional opnd kinds as well.
  420. if (this->IsRegOpnd() && this->AsRegOpnd()->m_sym->IsSingleDef())
  421. {
  422. IR::Instr * defInstr = this->AsRegOpnd()->m_sym->GetInstrDef();
  423. IR::Opnd * src1 = defInstr->GetSrc1();
  424. while(defInstr->m_opcode == Js::OpCode::Ld_A)
  425. {
  426. if (!src1->IsRegOpnd() || !src1->AsRegOpnd()->m_sym->IsSingleDef())
  427. {
  428. return ValueType::Uninitialized;
  429. }
  430. defInstr = src1->AsRegOpnd()->m_sym->GetInstrDef();
  431. src1 = defInstr->GetSrc1();
  432. }
  433. if (defInstr->GetDst()->GetValueType().IsAnyArray())
  434. {
  435. return defInstr->GetDst()->GetValueType().ToLikely();
  436. }
  437. else
  438. {
  439. return defInstr->GetDst()->GetValueType();
  440. }
  441. }
  442. return ValueType::Uninitialized;
  443. }
  444. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  445. void Opnd::DumpValueType()
  446. {
  447. if(m_valueType.IsUninitialized())
  448. {
  449. return;
  450. }
  451. if(!CONFIG_FLAG(Verbose))
  452. {
  453. // Skip printing the value type when it's obvious since verbose mode is off
  454. switch(this->GetKind())
  455. {
  456. case OpndKindIntConst:
  457. case OpndKindInt64Const:
  458. case OpndKindFloatConst:
  459. return;
  460. case OpndKindReg:
  461. {
  462. StackSym *const sym = this->AsRegOpnd()->m_sym;
  463. if(sym && (
  464. sym->IsInt32() ||
  465. sym->IsFloat32() ||
  466. sym->IsFloat64() ||
  467. sym->IsInt64() ||
  468. sym->IsUint64()
  469. ))
  470. {
  471. return;
  472. }
  473. break;
  474. }
  475. case OpndKindAddr:
  476. if(this->AsAddrOpnd()->m_address && this->AsAddrOpnd()->IsVar())
  477. {
  478. IR::AddrOpnd *addrOpnd = this->AsAddrOpnd();
  479. Js::Var address = addrOpnd->decodedValue ? addrOpnd->decodedValue : addrOpnd->m_address;
  480. // Tagged int might be encoded here, so check the type
  481. if (addrOpnd->GetAddrOpndKind() == AddrOpndKindConstantVar
  482. || Js::TaggedInt::Is(address) || (
  483. #if !FLOATVAR
  484. !JITManager::GetJITManager()->IsOOPJITEnabled() &&
  485. #endif
  486. Js::JavascriptNumber::Is_NoTaggedIntCheck(address)))
  487. {
  488. return;
  489. }
  490. }
  491. break;
  492. }
  493. }
  494. DumpValueType(m_valueType);
  495. }
  496. void Opnd::DumpValueType(const ValueType valueType)
  497. {
  498. if(valueType.IsUninitialized())
  499. {
  500. return;
  501. }
  502. char valueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
  503. valueType.ToString(valueTypeStr);
  504. Output::Print(_u("[%S]"), valueTypeStr);
  505. }
  506. #endif
  507. IntConstOpnd *Opnd::CreateUint32Opnd(const uint i, Func *const func)
  508. {
  509. return IntConstOpnd::New(i, TyUint32, func, true);
  510. }
  511. IntConstOpnd *Opnd::CreateProfileIdOpnd(const Js::ProfileId profileId, Func *const func)
  512. {
  513. CompileAssert(sizeof(profileId) == sizeof(uint16));
  514. return IntConstOpnd::New(profileId, TyUint16, func, true);
  515. }
  516. IntConstOpnd *Opnd::CreateInlineCacheIndexOpnd(const Js::InlineCacheIndex inlineCacheIndex, Func *const func)
  517. {
  518. CompileAssert(sizeof(inlineCacheIndex) == sizeof(uint));
  519. return CreateUint32Opnd(inlineCacheIndex, func);
  520. }
  521. RegOpnd *Opnd::CreateFramePointerOpnd(Func *const func)
  522. {
  523. return RegOpnd::New(nullptr, LowererMD::GetRegFramePointer(), TyMachPtr, func);
  524. }
  525. ///----------------------------------------------------------------------------
  526. ///
  527. /// SymOpnd::New
  528. ///
  529. /// Creates a new SymOpnd.
  530. ///
  531. ///----------------------------------------------------------------------------
  532. SymOpnd *
  533. SymOpnd::New(Sym *sym, IRType type, Func *func)
  534. {
  535. return SymOpnd::New(sym, 0, type, func);
  536. }
  537. SymOpnd *
  538. SymOpnd::New(Sym *sym, uint32 offset, IRType type, Func *func)
  539. {
  540. SymOpnd * symOpnd;
  541. AssertMsg(sym, "A SymOpnd needs a valid symbol.");
  542. symOpnd = JitAnew(func->m_alloc, IR::SymOpnd);
  543. symOpnd->m_sym = sym;
  544. symOpnd->m_offset = offset;
  545. symOpnd->m_type = type;
  546. symOpnd->SetIsJITOptimizedReg(false);
  547. symOpnd->m_kind = OpndKindSym;
  548. return symOpnd;
  549. }
  550. ///----------------------------------------------------------------------------
  551. ///
  552. /// SymOpnd::Copy
  553. ///
  554. /// Returns a copy of this opnd.
  555. ///
  556. ///----------------------------------------------------------------------------
  557. SymOpnd *
  558. SymOpnd::CopyInternal(Func *func)
  559. {
  560. Assert(m_kind == OpndKindSym);
  561. SymOpnd * newOpnd;
  562. newOpnd = SymOpnd::New(m_sym, m_offset, m_type, func);
  563. newOpnd->m_valueType = m_valueType;
  564. newOpnd->canStoreTemp = this->canStoreTemp;
  565. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  566. return newOpnd;
  567. }
  568. SymOpnd *
  569. SymOpnd::CloneDefInternal(Func *func)
  570. {
  571. Assert(m_kind == OpndKindSym);
  572. Sym *sym = this->m_sym;
  573. if (sym->IsStackSym() && sym->AsStackSym()->m_isSingleDef)
  574. {
  575. StackSym * oldSym = sym->AsStackSym();
  576. StackSym * newSym = oldSym->CloneDef(func)->AsStackSym();
  577. if (func->GetCloner()->clonedInstrGetOrigArgSlotSym && oldSym->IsArgSlotSym())
  578. {
  579. Assert(newSym != oldSym);
  580. this->m_sym = newSym;
  581. newSym->m_instrDef = oldSym->m_instrDef;
  582. oldSym->m_instrDef = nullptr;
  583. sym = oldSym;
  584. }
  585. else
  586. {
  587. sym = newSym;
  588. }
  589. }
  590. SymOpnd * newOpnd = SymOpnd::New(sym, m_offset, m_type, func);
  591. return newOpnd;
  592. }
  593. SymOpnd *
  594. SymOpnd::CloneUseInternal(Func *func)
  595. {
  596. Assert(m_kind == OpndKindSym);
  597. Sym *sym = this->m_sym;
  598. if (sym->IsStackSym() && sym->AsStackSym()->m_isSingleDef)
  599. {
  600. StackSym * oldSym = sym->AsStackSym();
  601. StackSym * newSym = oldSym->CloneUse(func)->AsStackSym();
  602. if (func->GetCloner()->clonedInstrGetOrigArgSlotSym && oldSym->IsArgSlotSym())
  603. {
  604. Assert(newSym != oldSym);
  605. this->m_sym = newSym;
  606. sym = oldSym;
  607. }
  608. else
  609. {
  610. sym = newSym;
  611. }
  612. }
  613. SymOpnd * newOpnd = SymOpnd::New(sym, m_offset, m_type, func);
  614. return newOpnd;
  615. }
  616. StackSym *
  617. SymOpnd::GetStackSymInternal() const
  618. {
  619. return (this->m_sym && this->m_sym->IsStackSym()) ? this->m_sym->AsStackSym() : nullptr;
  620. }
  621. ///----------------------------------------------------------------------------
  622. ///
  623. /// SymOpnd::IsEqual
  624. /// The SymOpnd's offset is 0 if it is called before regalloc. For Stack symopnd,
  625. /// compare the type and symbol's offsets only when the symbol's isAllocated is true.
  626. /// For other cases, compare the type, syms and offsets.
  627. /// For example, following two instructions after RegAlloc phase:
  628. /// iarg65535(s534)<0>.i32 = MOV (NULL).var
  629. /// iarg65535(s533)<0>.i32 = MOV (NULL).var
  630. /// are actually same instructions after encoding: mov dword ptr[ebp-0x1c], 0x0
  631. /// Here for dst stack symOpnd, m_sym are different: s534 vs. s533, but offsets and
  632. /// types are the same. So this function will report true if isAllocated is true.
  633. /// Note: for property symopnd, still compare type, offset and sym.
  634. ///
  635. ///----------------------------------------------------------------------------
  636. bool
  637. SymOpnd::IsEqualInternal(Opnd *opnd)
  638. {
  639. Assert(m_kind == OpndKindSym);
  640. Assert(opnd);
  641. if (!opnd->IsSymOpnd() || this->GetType() != opnd->GetType())
  642. {
  643. return false;
  644. }
  645. SymOpnd *opndSym = opnd->AsSymOpnd();
  646. Assert(opndSym);
  647. StackSym *thisStackSym = this->GetStackSymInternal();
  648. StackSym *opndStackSym = opndSym->GetStackSymInternal();
  649. if (thisStackSym && opndStackSym && thisStackSym->IsAllocated() && opndStackSym->IsAllocated())
  650. {
  651. return thisStackSym->m_offset == opndStackSym->m_offset;
  652. }
  653. else
  654. {
  655. return m_sym == opndSym->m_sym && m_offset == opndSym->m_offset;
  656. }
  657. }
  658. void
  659. SymOpnd::FreeInternal(Func *func)
  660. {
  661. Assert(m_kind == OpndKindSym);
  662. JitAdelete(func->m_alloc, this);
  663. }
  664. RegOpnd *SymOpnd::CreatePropertyOwnerOpnd(Func *const func) const
  665. {
  666. Assert(m_sym->IsPropertySym());
  667. Assert(func);
  668. StackSym *const propertyOwnerSym = m_sym->AsPropertySym()->m_stackSym;
  669. RegOpnd *const propertyOwnerOpnd = RegOpnd::New(propertyOwnerSym, propertyOwnerSym->GetType(), func);
  670. propertyOwnerOpnd->SetValueType(GetPropertyOwnerValueType());
  671. return propertyOwnerOpnd;
  672. }
  673. PropertySymOpnd *
  674. PropertySymOpnd::New(PropertySym *propertySym, uint inlineCacheIndex, IRType type, Func *func)
  675. {
  676. PropertySymOpnd *newOpnd = IR::PropertySymOpnd::New(propertySym, type, func);
  677. newOpnd->Init(inlineCacheIndex, func);
  678. return newOpnd;
  679. }
  680. void
  681. PropertySymOpnd::Init(uint inlineCacheIndex, Func *func)
  682. {
  683. this->Init(inlineCacheIndex,
  684. inlineCacheIndex != -1 ? func->GetRuntimeInlineCache(inlineCacheIndex) : 0,
  685. inlineCacheIndex != -1 ? func->GetRuntimePolymorphicInlineCache(inlineCacheIndex) : nullptr,
  686. inlineCacheIndex != -1 ? func->GetObjTypeSpecFldInfo(inlineCacheIndex) : nullptr,
  687. inlineCacheIndex != -1 ? func->GetPolyCacheUtilToInitialize(inlineCacheIndex) : PolymorphicInlineCacheUtilizationMinValue);
  688. }
  689. PropertySymOpnd *
  690. PropertySymOpnd::New(PropertySym *propertySym, IRType type, Func *func)
  691. {
  692. PropertySymOpnd *newOpnd = JitAnew(func->m_alloc, IR::PropertySymOpnd);
  693. newOpnd->m_sym = propertySym;
  694. newOpnd->m_offset = 0;
  695. newOpnd->m_type = type;
  696. newOpnd->SetObjTypeSpecFldInfo(nullptr);
  697. newOpnd->finalType = JITTypeHolder(nullptr);
  698. newOpnd->monoGuardType = JITTypeHolder(nullptr);
  699. newOpnd->guardedPropOps = nullptr;
  700. newOpnd->writeGuards = nullptr;
  701. newOpnd->objTypeSpecFlags = 0;
  702. newOpnd->isPropertySymOpnd = true;
  703. newOpnd->checkedTypeSetIndex = (uint16)-1;
  704. newOpnd->m_kind = OpndKindSym;
  705. return newOpnd;
  706. }
  707. void
  708. PropertySymOpnd::Init(uint inlineCacheIndex, intptr_t runtimeInlineCache, JITTimePolymorphicInlineCache * runtimePolymorphicInlineCache, ObjTypeSpecFldInfo* objTypeSpecFldInfo, byte polyCacheUtil)
  709. {
  710. this->m_inlineCacheIndex = inlineCacheIndex;
  711. this->m_runtimeInlineCache = runtimeInlineCache;
  712. this->m_runtimePolymorphicInlineCache = runtimePolymorphicInlineCache;
  713. this->m_polyCacheUtil = polyCacheUtil;
  714. this->SetObjTypeSpecFldInfo(objTypeSpecFldInfo);
  715. this->SetIsJITOptimizedReg(false);
  716. }
  717. PropertySymOpnd *
  718. PropertySymOpnd::CopyCommon(Func *func)
  719. {
  720. PropertySymOpnd *newOpnd = PropertySymOpnd::New(this->m_sym->AsPropertySym(), this->m_type, func);
  721. newOpnd->m_valueType = this->m_valueType;
  722. newOpnd->m_inlineCacheIndex = this->m_inlineCacheIndex;
  723. newOpnd->m_runtimeInlineCache = this->m_runtimeInlineCache;
  724. newOpnd->m_runtimePolymorphicInlineCache = this->m_runtimePolymorphicInlineCache;
  725. newOpnd->canStoreTemp = this->canStoreTemp;
  726. return newOpnd;
  727. }
  728. PropertySymOpnd *
  729. PropertySymOpnd::CopyWithoutFlowSensitiveInfo(Func *func)
  730. {
  731. PropertySymOpnd *newOpnd = CopyCommon(func);
  732. newOpnd->SetObjTypeSpecFldInfo(this->objTypeSpecFldInfo);
  733. // This field is not flow sensitive. It is only on if the instruction is CheckFixedMethodFld. If we ever
  734. // hoist CheckFixedMethodFld (or otherwise copy it), we must make sure not to change the opcode.
  735. newOpnd->usesFixedValue = this->usesFixedValue;
  736. // Note that the following fields are flow sensitive. If we're cloning this operand in order to attach it to
  737. // an instruction elsewhere in the flow (e.g. field hoisting or copy propagation), these fields cannot be copied.
  738. // If the caller knows some of them can be safely copied, the caller must do so manually.
  739. Assert(newOpnd->typeCheckSeqFlags == 0);
  740. Assert(newOpnd->finalType == nullptr);
  741. Assert(newOpnd->guardedPropOps == nullptr);
  742. Assert(newOpnd->writeGuards == nullptr);
  743. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  744. return newOpnd;
  745. }
  746. PropertySymOpnd *
  747. PropertySymOpnd::CopyInternalSub(Func *func)
  748. {
  749. Assert(m_kind == OpndKindSym && this->IsPropertySymOpnd());
  750. PropertySymOpnd *newOpnd = CopyCommon(func);
  751. newOpnd->objTypeSpecFldInfo = this->objTypeSpecFldInfo;
  752. newOpnd->usesAuxSlot = usesAuxSlot;
  753. newOpnd->slotIndex = slotIndex;
  754. newOpnd->checkedTypeSetIndex = checkedTypeSetIndex;
  755. newOpnd->objTypeSpecFlags = this->objTypeSpecFlags;
  756. newOpnd->finalType = this->finalType;
  757. newOpnd->guardedPropOps = this->guardedPropOps != nullptr ? this->guardedPropOps->CopyNew() : nullptr;
  758. newOpnd->writeGuards = this->writeGuards != nullptr ? this->writeGuards->CopyNew() : nullptr;
  759. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  760. return newOpnd;
  761. }
  762. bool
  763. PropertySymOpnd::IsObjectHeaderInlined() const
  764. {
  765. JITTypeHolder type(nullptr);
  766. if (this->IsMono())
  767. {
  768. type = this->GetType();
  769. }
  770. else if (this->HasEquivalentTypeSet())
  771. {
  772. type = this->GetFirstEquivalentType();
  773. }
  774. if (type != nullptr && Js::DynamicType::Is(type->GetTypeId()))
  775. {
  776. return type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler();
  777. }
  778. return false;
  779. }
  780. bool
  781. PropertySymOpnd::ChangesObjectLayout() const
  782. {
  783. JITTypeHolder cachedType = this->IsMono() ? this->GetType() : this->GetFirstEquivalentType();
  784. JITTypeHolder finalType = this->GetFinalType();
  785. if (finalType != nullptr && Js::DynamicType::Is(finalType->GetTypeId()))
  786. {
  787. // This is the case where final type opt may cause pro-active type transition to take place.
  788. Assert(cachedType != nullptr && Js::DynamicType::Is(cachedType->GetTypeId()));
  789. return cachedType->GetTypeHandler()->GetInlineSlotCapacity() != finalType->GetTypeHandler()->GetInlineSlotCapacity() ||
  790. cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() != finalType->GetTypeHandler()->GetOffsetOfInlineSlots();
  791. }
  792. if (!this->HasInitialType())
  793. {
  794. return false;
  795. }
  796. JITTypeHolder initialType = this->GetInitialType();
  797. if (initialType != nullptr && Js::DynamicType::Is(initialType->GetTypeId()))
  798. {
  799. // This is the case where the type transition actually occurs. (This is the only case that's detectable
  800. // during the loop pre-pass, since final types are not in place yet.)
  801. Assert(cachedType != nullptr && Js::DynamicType::Is(cachedType->GetTypeId()));
  802. const JITTypeHandler * cachedTypeHandler = cachedType->GetTypeHandler();
  803. const JITTypeHandler * initialTypeHandler = initialType->GetTypeHandler();
  804. return cachedTypeHandler->GetInlineSlotCapacity() != initialTypeHandler->GetInlineSlotCapacity() ||
  805. cachedTypeHandler->GetOffsetOfInlineSlots() != initialTypeHandler->GetOffsetOfInlineSlots();
  806. }
  807. return false;
  808. }
  809. void
  810. PropertySymOpnd::UpdateSlotForFinalType()
  811. {
  812. JITTypeHolder finalType = this->GetFinalType();
  813. Assert(this->IsMono() || this->checkedTypeSetIndex != (uint16)-1);
  814. JITTypeHolder cachedType =
  815. this->IsMono() ? this->GetType() : this->GetEquivalentTypeSet()->GetType(checkedTypeSetIndex);
  816. Assert(finalType != nullptr && Js::DynamicType::Is(finalType->GetTypeId()));
  817. Assert(cachedType != nullptr && Js::DynamicType::Is(cachedType->GetTypeId()));
  818. if (finalType == cachedType)
  819. {
  820. return;
  821. }
  822. // TODO: OOP JIT: should assert about runtime type handler addr
  823. Assert(cachedType->GetTypeHandler() != finalType->GetTypeHandler());
  824. if (cachedType->GetTypeHandler()->GetInlineSlotCapacity() == finalType->GetTypeHandler()->GetInlineSlotCapacity() &&
  825. cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() == finalType->GetTypeHandler()->GetOffsetOfInlineSlots())
  826. {
  827. // Nothing can change, since the variables aren't changing.
  828. return;
  829. }
  830. // Get the slot index and figure out the property index
  831. uint16 index = this->GetSlotIndex();
  832. if (this->UsesAuxSlot())
  833. {
  834. index += cachedType->GetTypeHandler()->GetInlineSlotCapacity();
  835. }
  836. else
  837. {
  838. index -= cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() / sizeof(Js::Var);
  839. }
  840. // Figure out the slot index and aux-ness from the property index
  841. if (index >= finalType->GetTypeHandler()->GetInlineSlotCapacity())
  842. {
  843. this->SetUsesAuxSlot(true);
  844. index -= finalType->GetTypeHandler()->GetInlineSlotCapacity();
  845. }
  846. else
  847. {
  848. this->SetUsesAuxSlot(false);
  849. index += finalType->GetTypeHandler()->GetOffsetOfInlineSlots() / sizeof(Js::Var);
  850. }
  851. this->SetSlotIndex(index);
  852. }
  853. bool PropertySymOpnd::HasFinalType() const
  854. {
  855. return this->finalType != nullptr;
  856. }
  857. PropertySymOpnd *
  858. PropertySymOpnd::CloneDefInternalSub(Func *func)
  859. {
  860. return this->CopyInternalSub(func);
  861. }
  862. PropertySymOpnd *
  863. PropertySymOpnd::CloneUseInternalSub(Func *func)
  864. {
  865. return this->CopyInternalSub(func);
  866. }
  867. RegOpnd::RegOpnd(StackSym *sym, RegNum reg, IRType type)
  868. {
  869. Initialize(sym, reg, type);
  870. }
  871. RegOpnd::RegOpnd(const RegOpnd &other, StackSym *const sym)
  872. {
  873. Initialize(sym, other.m_reg, other.m_type);
  874. m_valueType = other.m_valueType;
  875. SetIsJITOptimizedReg(other.GetIsJITOptimizedReg());
  876. m_dontDeadStore = other.m_dontDeadStore;
  877. m_wasNegativeZeroPreventedByBailout = other.m_wasNegativeZeroPreventedByBailout;
  878. #if DBG
  879. m_symValueFrozen = other.m_symValueFrozen;
  880. #endif
  881. }
  882. void RegOpnd::Initialize(StackSym *sym, RegNum reg, IRType type)
  883. {
  884. AssertMsg(sym || reg != RegNOREG, "A RegOpnd needs a valid symbol or register.");
  885. Assert(!sym || sym->GetType() != TyMisc);
  886. m_kind = OpndKindReg;
  887. m_sym = sym;
  888. SetReg(reg);
  889. m_type = type;
  890. m_isTempLastUse = false;
  891. m_isCallArg = false;
  892. SetIsJITOptimizedReg(false);
  893. m_dontDeadStore = false;
  894. m_fgPeepTmp = false;
  895. m_wasNegativeZeroPreventedByBailout = false;
  896. m_isArrayRegOpnd = false;
  897. #if DBG
  898. m_symValueFrozen = false;
  899. #endif
  900. }
  901. ///----------------------------------------------------------------------------
  902. ///
  903. /// RegOpnd::New
  904. ///
  905. /// Creates a new RegOpnd.
  906. ///
  907. ///----------------------------------------------------------------------------
  908. RegOpnd *
  909. RegOpnd::New(IRType type, Func *func)
  910. {
  911. return RegOpnd::New(StackSym::New(type, func), RegNOREG, type, func);
  912. }
  913. RegOpnd *
  914. RegOpnd::New(StackSym *sym, IRType type, Func *func)
  915. {
  916. return RegOpnd::New(sym, RegNOREG, type, func);
  917. }
  918. ///----------------------------------------------------------------------------
  919. ///
  920. /// RegOpnd::New
  921. ///
  922. /// Creates a new RegOpnd.
  923. ///
  924. ///----------------------------------------------------------------------------
  925. RegOpnd *
  926. RegOpnd::New(StackSym *sym, RegNum reg, IRType type, Func *func)
  927. {
  928. return JitAnew(func->m_alloc, IR::RegOpnd, sym, reg, type);
  929. }
  930. ///----------------------------------------------------------------------------
  931. ///
  932. /// RegOpnd::Copy
  933. ///
  934. /// Returns a copy of this opnd.
  935. ///
  936. ///----------------------------------------------------------------------------
  937. RegOpnd *
  938. RegOpnd::CopyInternal(StackSym * sym, Func *func)
  939. {
  940. Assert(m_kind == OpndKindReg);
  941. return JitAnew(func->m_alloc, IR::RegOpnd, *this, sym);
  942. }
  943. RegOpnd *
  944. RegOpnd::CopyInternal(Func *func)
  945. {
  946. return CopyInternal(m_sym, func);
  947. }
  948. RegOpnd *
  949. RegOpnd::CloneDefInternal(Func *func)
  950. {
  951. StackSym * sym = m_sym ? m_sym->CloneDef(func) : nullptr;
  952. return CopyInternal(sym, func);
  953. }
  954. RegOpnd *
  955. RegOpnd::CloneUseInternal(Func *func)
  956. {
  957. StackSym * sym = m_sym ? m_sym->CloneUse(func) : nullptr;
  958. return CopyInternal(sym, func);
  959. }
  960. StackSym *
  961. RegOpnd::GetStackSymInternal() const
  962. {
  963. return this->m_sym;
  964. }
  965. StackSym *
  966. RegOpnd::TryGetStackSym(Opnd *const opnd)
  967. {
  968. return opnd && opnd->IsRegOpnd() ? opnd->AsRegOpnd()->m_sym : nullptr;
  969. }
  970. ///----------------------------------------------------------------------------
  971. ///
  972. /// RegOpnd::IsEqual
  973. ///
  974. ///----------------------------------------------------------------------------
  975. bool
  976. RegOpnd::IsEqualInternal(Opnd *opnd)
  977. {
  978. Assert(m_kind == OpndKindReg);
  979. return IsSameRegUntyped(opnd) && (this->GetType() == opnd->GetType());
  980. }
  981. void
  982. RegOpnd::FreeInternal(Func *func)
  983. {
  984. Assert(m_kind == OpndKindReg);
  985. JitAdelete(func->m_alloc, this);
  986. }
  987. ///----------------------------------------------------------------------------
  988. ///
  989. /// RegOpnd::IsSameReg
  990. ///
  991. /// Same as IsEqual except the type only need to be equal size
  992. ///
  993. ///----------------------------------------------------------------------------
  994. bool
  995. RegOpnd::IsSameReg(Opnd *opnd)
  996. {
  997. return IsSameRegUntyped(opnd) && (TySize[this->GetType()] == TySize[opnd->GetType()]);
  998. }
  999. ///----------------------------------------------------------------------------
  1000. ///
  1001. /// RegOpnd::IsSameRegUntyped
  1002. ///
  1003. /// Same as IsEqual but without any types comparison
  1004. ///
  1005. ///----------------------------------------------------------------------------
  1006. bool
  1007. RegOpnd::IsSameRegUntyped(Opnd *opnd)
  1008. {
  1009. if (!opnd->IsRegOpnd())
  1010. {
  1011. return false;
  1012. }
  1013. RegOpnd *regOpnd = opnd->AsRegOpnd();
  1014. if (m_reg != RegNOREG)
  1015. {
  1016. return m_reg == regOpnd->m_reg;
  1017. }
  1018. return m_sym == regOpnd->m_sym && regOpnd->m_reg == RegNOREG;
  1019. }
  1020. ///----------------------------------------------------------------------------
  1021. ///
  1022. /// ArrayRegOpnd
  1023. ///
  1024. ///----------------------------------------------------------------------------
  1025. ArrayRegOpnd::ArrayRegOpnd(
  1026. StackSym *const arraySym,
  1027. const ValueType valueType,
  1028. StackSym *const headSegmentSym,
  1029. StackSym *const headSegmentLengthSym,
  1030. StackSym *const lengthSym,
  1031. const bool eliminatedLowerBoundCheck,
  1032. const bool eliminatedUpperBoundCheck)
  1033. : RegOpnd(arraySym, RegNOREG, TyVar),
  1034. headSegmentSym(headSegmentSym),
  1035. headSegmentLengthSym(headSegmentLengthSym),
  1036. lengthSym(lengthSym),
  1037. eliminatedLowerBoundCheck(eliminatedLowerBoundCheck),
  1038. eliminatedUpperBoundCheck(eliminatedUpperBoundCheck)
  1039. {
  1040. Assert(valueType.IsAnyOptimizedArray());
  1041. m_valueType = valueType;
  1042. m_isArrayRegOpnd = true;
  1043. }
  1044. ArrayRegOpnd::ArrayRegOpnd(
  1045. const RegOpnd &other,
  1046. StackSym *const arraySym,
  1047. const ValueType valueType,
  1048. StackSym *const headSegmentSym,
  1049. StackSym *const headSegmentLengthSym,
  1050. StackSym *const lengthSym,
  1051. const bool eliminatedLowerBoundCheck,
  1052. const bool eliminatedUpperBoundCheck)
  1053. : RegOpnd(other, arraySym),
  1054. headSegmentSym(headSegmentSym),
  1055. headSegmentLengthSym(headSegmentLengthSym),
  1056. lengthSym(lengthSym),
  1057. eliminatedLowerBoundCheck(eliminatedLowerBoundCheck),
  1058. eliminatedUpperBoundCheck(eliminatedUpperBoundCheck)
  1059. {
  1060. Assert(valueType.IsAnyOptimizedArray());
  1061. m_valueType = valueType;
  1062. m_isArrayRegOpnd = true;
  1063. }
  1064. ArrayRegOpnd *ArrayRegOpnd::New(
  1065. StackSym *const arraySym,
  1066. const ValueType valueType,
  1067. StackSym *const headSegmentSym,
  1068. StackSym *const headSegmentLengthSym,
  1069. StackSym *const lengthSym,
  1070. const bool eliminatedLowerBoundCheck,
  1071. const bool eliminatedUpperBoundCheck,
  1072. Func *const func)
  1073. {
  1074. Assert(func);
  1075. return
  1076. JitAnew(
  1077. func->m_alloc,
  1078. ArrayRegOpnd,
  1079. arraySym,
  1080. valueType,
  1081. headSegmentSym,
  1082. headSegmentLengthSym,
  1083. lengthSym,
  1084. eliminatedLowerBoundCheck,
  1085. eliminatedUpperBoundCheck);
  1086. }
  1087. ArrayRegOpnd *ArrayRegOpnd::New(
  1088. const RegOpnd *const other,
  1089. const ValueType valueType,
  1090. StackSym *const headSegmentSym,
  1091. StackSym *const headSegmentLengthSym,
  1092. StackSym *const lengthSym,
  1093. const bool eliminatedLowerBoundCheck,
  1094. const bool eliminatedUpperBoundCheck,
  1095. Func *const func)
  1096. {
  1097. Assert(func);
  1098. return
  1099. JitAnew(
  1100. func->m_alloc,
  1101. ArrayRegOpnd,
  1102. *other,
  1103. other->m_sym,
  1104. valueType,
  1105. headSegmentSym,
  1106. headSegmentLengthSym,
  1107. lengthSym,
  1108. eliminatedLowerBoundCheck,
  1109. eliminatedUpperBoundCheck);
  1110. }
  1111. RegOpnd *ArrayRegOpnd::CopyAsRegOpnd(Func *func)
  1112. {
  1113. RegOpnd *const regOpndCopy = RegOpnd::CopyInternal(func);
  1114. Assert(!regOpndCopy->IsArrayRegOpnd());
  1115. return regOpndCopy;
  1116. }
  1117. ArrayRegOpnd *ArrayRegOpnd::CopyInternalSub(Func *func)
  1118. {
  1119. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1120. return Clone(m_sym, headSegmentSym, headSegmentLengthSym, lengthSym, func);
  1121. }
  1122. ArrayRegOpnd *ArrayRegOpnd::CloneDefInternalSub(Func *func)
  1123. {
  1124. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1125. return
  1126. Clone(
  1127. m_sym ? m_sym->CloneDef(func) : nullptr,
  1128. headSegmentSym ? headSegmentSym->CloneUse(func) : nullptr,
  1129. headSegmentLengthSym ? headSegmentLengthSym->CloneUse(func) : nullptr,
  1130. lengthSym ? lengthSym->CloneUse(func) : nullptr,
  1131. func);
  1132. }
  1133. ArrayRegOpnd *ArrayRegOpnd::CloneUseInternalSub(Func *func)
  1134. {
  1135. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1136. return
  1137. Clone(
  1138. m_sym ? m_sym->CloneUse(func) : nullptr,
  1139. headSegmentSym ? headSegmentSym->CloneUse(func) : nullptr,
  1140. headSegmentLengthSym ? headSegmentLengthSym->CloneUse(func) : nullptr,
  1141. lengthSym ? lengthSym->CloneUse(func) : nullptr,
  1142. func);
  1143. }
  1144. ArrayRegOpnd *ArrayRegOpnd::Clone(
  1145. StackSym *const arraySym,
  1146. StackSym *const headSegmentSym,
  1147. StackSym *const headSegmentLengthSym,
  1148. StackSym *const lengthSym,
  1149. Func *const func) const
  1150. {
  1151. Assert(func);
  1152. // Careful how clones are used. Only GlobOpt knows when it's valid to use the information in this class, so ideally cloning
  1153. // should be done only at lowering time.
  1154. return
  1155. JitAnew(
  1156. func->m_alloc,
  1157. ArrayRegOpnd,
  1158. *this,
  1159. arraySym,
  1160. m_valueType,
  1161. headSegmentSym,
  1162. headSegmentLengthSym,
  1163. lengthSym,
  1164. eliminatedLowerBoundCheck,
  1165. eliminatedUpperBoundCheck);
  1166. }
  1167. void ArrayRegOpnd::FreeInternalSub(Func *func)
  1168. {
  1169. Assert(m_kind == OpndKindReg && this->IsArrayRegOpnd());
  1170. JitAdelete(func->m_alloc, this);
  1171. }
  1172. ///----------------------------------------------------------------------------
  1173. ///
  1174. /// IntConstOpnd::New
  1175. ///
  1176. /// Creates a new IntConstOpnd.
  1177. ///
  1178. ///----------------------------------------------------------------------------
  1179. IntConstOpnd *
  1180. IntConstOpnd::New(IntConstType value, IRType type, Func *func, bool dontEncode)
  1181. {
  1182. IntConstOpnd * intConstOpnd;
  1183. Assert(TySize[type] <= sizeof(IntConstType));
  1184. intConstOpnd = JitAnew(func->m_alloc, IR::IntConstOpnd);
  1185. intConstOpnd->m_type = type;
  1186. intConstOpnd->m_kind = OpndKindIntConst;
  1187. intConstOpnd->m_dontEncode = dontEncode;
  1188. intConstOpnd->SetValue(value);
  1189. return intConstOpnd;
  1190. }
  1191. ///----------------------------------------------------------------------------
  1192. ///
  1193. /// IntConstOpnd::CreateIntConstOpndFromType
  1194. ///
  1195. /// Create an IntConstOpnd or Int64ConstOpnd depending on the IRType.
  1196. ///
  1197. ///----------------------------------------------------------------------------
  1198. IR::Opnd* IntConstOpnd::NewFromType(int64 value, IRType type, Func* func)
  1199. {
  1200. if (IRType_IsInt64(type))
  1201. {
  1202. return Int64ConstOpnd::New(value, type, func);
  1203. }
  1204. Assert(value < (int64)UINT_MAX);
  1205. return IntConstOpnd::New((IntConstType)value, type, func);
  1206. }
  1207. ///----------------------------------------------------------------------------
  1208. ///
  1209. /// IntConstOpnd::Copy
  1210. ///
  1211. /// Returns a copy of this opnd.
  1212. ///
  1213. ///----------------------------------------------------------------------------
  1214. IntConstOpnd *
  1215. IntConstOpnd::CopyInternal(Func *func)
  1216. {
  1217. Assert(m_kind == OpndKindIntConst);
  1218. IntConstOpnd * newOpnd;
  1219. newOpnd = IntConstOpnd::New(m_value, m_type, func, m_dontEncode);
  1220. newOpnd->m_valueType = m_valueType;
  1221. return newOpnd;
  1222. }
  1223. ///----------------------------------------------------------------------------
  1224. ///
  1225. /// IntConstOpnd::IsEqual
  1226. ///
  1227. ///----------------------------------------------------------------------------
  1228. bool
  1229. IntConstOpnd::IsEqualInternal(Opnd *opnd)
  1230. {
  1231. Assert(m_kind == OpndKindIntConst);
  1232. if (!opnd->IsIntConstOpnd() || this->GetType() != opnd->GetType())
  1233. {
  1234. return false;
  1235. }
  1236. return m_value == opnd->AsIntConstOpnd()->m_value;
  1237. }
  1238. void
  1239. IntConstOpnd::FreeInternal(Func *func)
  1240. {
  1241. Assert(m_kind == OpndKindIntConst);
  1242. JitAdelete(func->m_alloc, this);
  1243. }
  1244. ///----------------------------------------------------------------------------
  1245. ///
  1246. /// IntConstOpnd::SetValue
  1247. ///
  1248. /// Modifies the value of the IntConstOpnd
  1249. ///
  1250. ///----------------------------------------------------------------------------
  1251. void
  1252. IntConstOpnd::SetValue(IntConstType value)
  1253. {
  1254. if (sizeof(IntConstType) > sizeof(int32))
  1255. {
  1256. Assert(m_type != TyInt32 || (value >= INT32_MIN && value <= INT32_MAX));
  1257. Assert(m_type != TyUint32 || (value >= 0 && value <= UINT32_MAX));
  1258. }
  1259. // TODO: These should be uncommented, unfortunately, Lowerer::UseWithNewType
  1260. // can change m_type (by calling SetType) in such a way that it violates these constraints.
  1261. // If CopyInternal is later called on the IntConstOpnd, these will fail.
  1262. // Assert(m_type != TyInt16 || (value >= INT16_MIN && value <= INT16_MAX));
  1263. // Assert(m_type != TyUint16 || (value >= 0 && value <= UINT16_MAX));
  1264. // Assert(m_type != TyInt8 || (value >= INT8_MIN && value <= INT8_MAX));
  1265. // Assert(m_type != TyUint8 || (value >= 0 && value <= UINT8_MAX));
  1266. m_value = value;
  1267. }
  1268. ///----------------------------------------------------------------------------
  1269. ///
  1270. /// IntConstOpnd::AsInt32
  1271. ///
  1272. /// Retrieves the value of the int const opnd as a signed 32-bit integer.
  1273. ///
  1274. ///----------------------------------------------------------------------------
  1275. int32
  1276. IntConstOpnd::AsInt32()
  1277. {
  1278. // TODO: Currently, there are cases where we construct IntConstOpnd with TyInt32
  1279. // and retrieve value out as uint32 (or vice versa). Because of these, we allow
  1280. // AsInt32/AsUint32 to cast between int32/uint32 in a lossy manner for now.
  1281. // In the future, we should tighten up usage of IntConstOpnd to avoid these casts
  1282. if (sizeof(IntConstType) == sizeof(int32))
  1283. {
  1284. return (int32)m_value;
  1285. }
  1286. if (m_type == TyUint32)
  1287. {
  1288. Assert(m_value >= 0 && m_value <= UINT32_MAX);
  1289. return (int32)(uint32)m_value;
  1290. }
  1291. Assert(Math::FitsInDWord(m_value));
  1292. return (int32)m_value;
  1293. }
  1294. ///----------------------------------------------------------------------------
  1295. ///
  1296. /// IntConstOpnd::AsUint32
  1297. ///
  1298. /// Retrieves the value of the int const opnd as an unsigned 32-bit integer.
  1299. ///
  1300. ///----------------------------------------------------------------------------
  1301. uint32
  1302. IntConstOpnd::AsUint32()
  1303. {
  1304. // TODO: See comment in AsInt32() regarding casts from int32 to uint32
  1305. if (sizeof(uint32) == sizeof(IntConstType))
  1306. {
  1307. return (uint32)m_value;
  1308. }
  1309. Assert(sizeof(uint32) < sizeof(IntConstType));
  1310. Assert(m_value >= 0 && m_value <= UINT32_MAX);
  1311. return (uint32)m_value;
  1312. }
  1313. ///----------------------------------------------------------------------------
  1314. ///
  1315. /// Int64ConstOpnd Methods
  1316. ///
  1317. ///----------------------------------------------------------------------------
  1318. IR::Int64ConstOpnd* Int64ConstOpnd::New(int64 value, IRType type, Func *func)
  1319. {
  1320. AssertMsg(func->GetJITFunctionBody()->IsWasmFunction(), "Only WebAssembly functions should have int64 const operands. Use IntConstOpnd for size_t type");
  1321. Int64ConstOpnd * intConstOpnd;
  1322. Assert(TySize[type] == sizeof(int64));
  1323. intConstOpnd = JitAnew(func->m_alloc, IR::Int64ConstOpnd);
  1324. intConstOpnd->m_type = type;
  1325. intConstOpnd->m_kind = OpndKindInt64Const;
  1326. intConstOpnd->m_value = value;
  1327. return intConstOpnd;
  1328. }
  1329. IR::Int64ConstOpnd* Int64ConstOpnd::CopyInternal(Func *func)
  1330. {
  1331. Assert(m_kind == OpndKindInt64Const);
  1332. Int64ConstOpnd * newOpnd;
  1333. newOpnd = Int64ConstOpnd::New(m_value, m_type, func);
  1334. newOpnd->m_valueType = m_valueType;
  1335. return newOpnd;
  1336. }
  1337. bool Int64ConstOpnd::IsEqualInternal(Opnd *opnd)
  1338. {
  1339. Assert(m_kind == OpndKindInt64Const);
  1340. if (!opnd->IsInt64ConstOpnd() || this->GetType() != opnd->GetType())
  1341. {
  1342. return false;
  1343. }
  1344. return m_value == opnd->AsInt64ConstOpnd()->m_value;
  1345. }
  1346. void Int64ConstOpnd::FreeInternal(Func * func)
  1347. {
  1348. Assert(m_kind == OpndKindInt64Const);
  1349. JitAdelete(func->m_alloc, this);
  1350. }
  1351. ///----------------------------------------------------------------------------
  1352. ///
  1353. /// RegBVOpnd::New
  1354. ///
  1355. /// Creates a new IntConstOpnd.
  1356. ///
  1357. ///----------------------------------------------------------------------------
  1358. RegBVOpnd *
  1359. RegBVOpnd::New(BVUnit32 value, IRType type, Func *func)
  1360. {
  1361. RegBVOpnd * regBVOpnd;
  1362. regBVOpnd = JitAnew(func->m_alloc, IR::RegBVOpnd);
  1363. regBVOpnd->m_value.Copy(value);
  1364. regBVOpnd->m_type = type;
  1365. regBVOpnd->m_kind = OpndKindRegBV;
  1366. return regBVOpnd;
  1367. }
  1368. ///----------------------------------------------------------------------------
  1369. ///
  1370. /// RegBVOpnd::Copy
  1371. ///
  1372. /// Returns a copy of this opnd.
  1373. ///
  1374. ///----------------------------------------------------------------------------
  1375. RegBVOpnd *
  1376. RegBVOpnd::CopyInternal(Func *func)
  1377. {
  1378. Assert(m_kind == OpndKindRegBV);
  1379. RegBVOpnd * newOpnd;
  1380. newOpnd = RegBVOpnd::New(m_value, m_type, func);
  1381. newOpnd->m_valueType = m_valueType;
  1382. return newOpnd;
  1383. }
  1384. ///----------------------------------------------------------------------------
  1385. ///
  1386. /// RegBVOpnd::IsEqual
  1387. ///
  1388. ///----------------------------------------------------------------------------
  1389. bool
  1390. RegBVOpnd::IsEqualInternal(Opnd *opnd)
  1391. {
  1392. Assert(m_kind == OpndKindRegBV);
  1393. if (!opnd->IsRegBVOpnd() || this->GetType() != opnd->GetType())
  1394. {
  1395. return false;
  1396. }
  1397. return m_value.Equal(opnd->AsRegBVOpnd()->m_value);
  1398. }
  1399. void
  1400. RegBVOpnd::FreeInternal(Func *func)
  1401. {
  1402. Assert(m_kind == OpndKindRegBV);
  1403. JitAdelete(func->m_alloc, this);
  1404. }
  1405. ///----------------------------------------------------------------------------
  1406. ///
  1407. /// FloatConstOpnd::New
  1408. ///
  1409. /// Creates a new FloatConstOpnd.
  1410. ///
  1411. ///----------------------------------------------------------------------------
  1412. FloatConstOpnd *
  1413. FloatConstOpnd::New(FloatConstType value, IRType type, Func *func)
  1414. {
  1415. FloatConstOpnd * floatConstOpnd;
  1416. floatConstOpnd = JitAnew(func->m_alloc, IR::FloatConstOpnd);
  1417. floatConstOpnd->m_value = value;
  1418. floatConstOpnd->m_type = type;
  1419. #if !FLOATVAR
  1420. floatConstOpnd->m_number = nullptr;
  1421. #endif
  1422. floatConstOpnd->m_kind = OpndKindFloatConst;
  1423. return floatConstOpnd;
  1424. }
  1425. FloatConstOpnd *
  1426. FloatConstOpnd::New(Js::Var floatVar, IRType type, Func *func, Js::Var varLocal /*= nullptr*/)
  1427. {
  1428. Assert((varLocal && Js::JavascriptNumber::Is(varLocal)) || Js::JavascriptNumber::Is(floatVar));
  1429. FloatConstType value = Js::JavascriptNumber::GetValue(varLocal ? varLocal : floatVar);
  1430. FloatConstOpnd * floatConstOpnd = FloatConstOpnd::New(value, type, func);
  1431. #if !FLOATVAR
  1432. floatConstOpnd->m_number = floatVar;
  1433. floatConstOpnd->m_numberCopy = (Js::JavascriptNumber*)varLocal;
  1434. #endif
  1435. return floatConstOpnd;
  1436. }
  1437. AddrOpnd *
  1438. FloatConstOpnd::GetAddrOpnd(Func *func, bool dontEncode)
  1439. {
  1440. #if !FLOATVAR
  1441. if (this->m_number)
  1442. {
  1443. return AddrOpnd::New(this->m_number, (Js::TaggedNumber::Is(this->m_number) ? AddrOpndKindConstantVar : AddrOpndKindDynamicVar), func, dontEncode, this->m_numberCopy);
  1444. }
  1445. #endif
  1446. IR::AddrOpnd *opnd = AddrOpnd::NewFromNumber(this->m_value, func, dontEncode);
  1447. #if !FLOATVAR
  1448. this->m_number = opnd->m_address;
  1449. #endif
  1450. return opnd;
  1451. }
  1452. ///----------------------------------------------------------------------------
  1453. ///
  1454. /// FloatConstOpnd::Copy
  1455. ///
  1456. /// Returns a copy of this opnd.
  1457. ///
  1458. ///----------------------------------------------------------------------------
  1459. FloatConstOpnd *
  1460. FloatConstOpnd::CopyInternal(Func *func)
  1461. {
  1462. Assert(m_kind == OpndKindFloatConst);
  1463. FloatConstOpnd * newOpnd;
  1464. newOpnd = FloatConstOpnd::New(m_value, m_type, func);
  1465. newOpnd->m_valueType = m_valueType;
  1466. return newOpnd;
  1467. }
  1468. ///----------------------------------------------------------------------------
  1469. ///
  1470. /// FloatConstOpnd::IsEqual
  1471. ///
  1472. ///----------------------------------------------------------------------------
  1473. bool
  1474. FloatConstOpnd::IsEqualInternal(Opnd *opnd)
  1475. {
  1476. Assert(m_kind == OpndKindFloatConst);
  1477. if (!opnd->IsFloatConstOpnd() || this->GetType() != opnd->GetType())
  1478. {
  1479. return false;
  1480. }
  1481. return m_value == opnd->AsFloatConstOpnd()->m_value;
  1482. }
  1483. void
  1484. FloatConstOpnd::FreeInternal(Func *func)
  1485. {
  1486. Assert(m_kind == OpndKindFloatConst);
  1487. JitAdelete(func->m_alloc, this);
  1488. }
  1489. ///----------------------------------------------------------------------------
  1490. ///
  1491. /// Simd128ConstOpnd::New
  1492. ///
  1493. /// Creates a new FloatConstOpnd.
  1494. ///
  1495. ///----------------------------------------------------------------------------
  1496. Simd128ConstOpnd *
  1497. Simd128ConstOpnd::New(AsmJsSIMDValue value, IRType type, Func *func)
  1498. {
  1499. Simd128ConstOpnd * simd128ConstOpnd;
  1500. simd128ConstOpnd = JitAnew(func->m_alloc, IR::Simd128ConstOpnd);
  1501. simd128ConstOpnd->m_value = value;
  1502. simd128ConstOpnd->m_type = type;
  1503. simd128ConstOpnd->m_kind = OpndKindSimd128Const;
  1504. return simd128ConstOpnd;
  1505. }
  1506. ///----------------------------------------------------------------------------
  1507. ///
  1508. /// Simd128ConstOpnd::Copy
  1509. ///
  1510. /// Returns a copy of this opnd.
  1511. ///
  1512. ///----------------------------------------------------------------------------
  1513. Simd128ConstOpnd *
  1514. Simd128ConstOpnd::CopyInternal(Func *func)
  1515. {
  1516. Assert(m_kind == OpndKindSimd128Const);
  1517. Simd128ConstOpnd * newOpnd;
  1518. newOpnd = Simd128ConstOpnd::New(m_value, m_type, func);
  1519. newOpnd->m_valueType = m_valueType;
  1520. return newOpnd;
  1521. }
  1522. ///----------------------------------------------------------------------------
  1523. ///
  1524. /// Simd128ConstOpnd::IsEqual
  1525. ///
  1526. ///----------------------------------------------------------------------------
  1527. bool
  1528. Simd128ConstOpnd::IsEqualInternal(Opnd *opnd)
  1529. {
  1530. Assert(m_kind == OpndKindSimd128Const);
  1531. if (!opnd->IsSimd128ConstOpnd() || this->GetType() != opnd->GetType())
  1532. {
  1533. return false;
  1534. }
  1535. return m_value == opnd->AsSimd128ConstOpnd()->m_value;
  1536. }
  1537. void
  1538. Simd128ConstOpnd::FreeInternal(Func *func)
  1539. {
  1540. Assert(m_kind == OpndKindSimd128Const);
  1541. JitAdelete(func->m_alloc, this);
  1542. }
  1543. ///----------------------------------------------------------------------------
  1544. ///
  1545. /// HelperCallOpnd::New
  1546. ///
  1547. /// Creates a new HelperCallOpnd.
  1548. ///
  1549. ///----------------------------------------------------------------------------
  1550. HelperCallOpnd *
  1551. HelperCallOpnd::New(JnHelperMethod fnHelper, Func *func)
  1552. {
  1553. HelperCallOpnd *helperCallOpnd = JitAnew(func->m_alloc, IR::HelperCallOpnd);
  1554. helperCallOpnd->Init(fnHelper);
  1555. return helperCallOpnd;
  1556. }
  1557. void
  1558. HelperCallOpnd::Init(JnHelperMethod fnHelper)
  1559. {
  1560. Assert(fnHelper != IR::HelperInvalid);
  1561. this->m_fnHelper = fnHelper;
  1562. this->m_type = TyMachPtr;
  1563. this->m_kind = OpndKindHelperCall;
  1564. }
  1565. ///----------------------------------------------------------------------------
  1566. ///
  1567. /// HelperCallOpnd::Copy
  1568. ///
  1569. /// Returns a copy of this opnd.
  1570. ///
  1571. ///----------------------------------------------------------------------------
  1572. HelperCallOpnd *
  1573. HelperCallOpnd::CopyInternal(Func *func)
  1574. {
  1575. Assert(m_kind == OpndKindHelperCall);
  1576. HelperCallOpnd *const newOpnd = HelperCallOpnd::New(m_fnHelper, func);
  1577. newOpnd->m_valueType = m_valueType;
  1578. return newOpnd;
  1579. }
  1580. ///----------------------------------------------------------------------------
  1581. ///
  1582. /// HelperCallOpnd::IsEqual
  1583. ///
  1584. ///----------------------------------------------------------------------------
  1585. bool
  1586. HelperCallOpnd::IsEqualInternal(Opnd *opnd)
  1587. {
  1588. Assert(m_kind == OpndKindHelperCall);
  1589. if (!opnd->IsHelperCallOpnd())
  1590. {
  1591. return false;
  1592. }
  1593. return m_fnHelper == opnd->AsHelperCallOpnd()->m_fnHelper;
  1594. }
  1595. void
  1596. HelperCallOpnd::FreeInternal(Func *func)
  1597. {
  1598. Assert(m_kind == OpndKindHelperCall);
  1599. JitAdelete(func->m_alloc, this);
  1600. }
  1601. DiagHelperCallOpnd *
  1602. DiagHelperCallOpnd::New(JnHelperMethod fnHelper, Func *func, int argCount)
  1603. {
  1604. DiagHelperCallOpnd *helperCallOpnd = JitAnew(func->m_alloc, IR::DiagHelperCallOpnd);
  1605. helperCallOpnd->Init(fnHelper);
  1606. helperCallOpnd->m_argCount = argCount;
  1607. helperCallOpnd->isDiagHelperCallOpnd = true;
  1608. return helperCallOpnd;
  1609. }
  1610. DiagHelperCallOpnd *
  1611. DiagHelperCallOpnd::CopyInternalSub(Func *func)
  1612. {
  1613. Assert(m_kind == OpndKindHelperCall && this->IsDiagHelperCallOpnd());
  1614. DiagHelperCallOpnd *const newOpnd = DiagHelperCallOpnd::New(m_fnHelper, func, m_argCount);
  1615. newOpnd->m_valueType = m_valueType;
  1616. return newOpnd;
  1617. }
  1618. bool
  1619. DiagHelperCallOpnd::IsEqualInternalSub(Opnd *opnd)
  1620. {
  1621. Assert(m_kind == OpndKindHelperCall && this->IsDiagHelperCallOpnd());
  1622. if (!opnd->IsHelperCallOpnd() || !opnd->AsHelperCallOpnd()->IsDiagHelperCallOpnd())
  1623. {
  1624. return false;
  1625. }
  1626. return
  1627. m_fnHelper == opnd->AsHelperCallOpnd()->m_fnHelper &&
  1628. m_argCount == static_cast<DiagHelperCallOpnd*>(opnd)->m_argCount;
  1629. }
  1630. ///----------------------------------------------------------------------------
  1631. ///
  1632. /// AddrOpnd::New
  1633. ///
  1634. /// Creates a new AddrOpnd.
  1635. ///
  1636. ///----------------------------------------------------------------------------
  1637. AddrOpnd *
  1638. AddrOpnd::New(intptr_t address, AddrOpndKind addrOpndKind, Func *func, bool dontEncode /* = false */, Js::Var varLocal /* = nullptr*/)
  1639. {
  1640. AddrOpnd * addrOpnd;
  1641. addrOpnd = JitAnew(func->m_alloc, IR::AddrOpnd);
  1642. // TODO (michhol): OOP JIT, use intptr_t instead of Js::Var by default so people don't try to dereference
  1643. addrOpnd->m_address = (Js::Var)address;
  1644. addrOpnd->m_localAddress = func->IsOOPJIT() ? varLocal : (Js::Var)address;
  1645. addrOpnd->addrOpndKind = addrOpndKind;
  1646. addrOpnd->m_type = addrOpnd->IsVar() ? TyVar : TyMachPtr;
  1647. addrOpnd->m_dontEncode = dontEncode;
  1648. addrOpnd->m_isFunction = false;
  1649. if (address && addrOpnd->IsVar())
  1650. {
  1651. if (Js::TaggedInt::Is(address))
  1652. {
  1653. addrOpnd->m_valueType = ValueType::GetTaggedInt();
  1654. addrOpnd->SetValueTypeFixed();
  1655. }
  1656. else if (
  1657. #if !FLOATVAR
  1658. !func->IsOOPJIT() && CONFIG_FLAG(OOPJITMissingOpts) &&
  1659. #endif
  1660. Js::JavascriptNumber::Is_NoTaggedIntCheck(addrOpnd->m_address))
  1661. {
  1662. addrOpnd->m_valueType =
  1663. Js::JavascriptNumber::IsInt32_NoChecks(addrOpnd->m_address)
  1664. ? ValueType::GetInt(false)
  1665. : ValueType::Float;
  1666. addrOpnd->SetValueTypeFixed();
  1667. }
  1668. }
  1669. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1670. addrOpnd->decodedValue = 0;
  1671. addrOpnd->wasVar = addrOpnd->IsVar();
  1672. #endif
  1673. addrOpnd->m_kind = OpndKindAddr;
  1674. return addrOpnd;
  1675. }
  1676. AddrOpnd *
  1677. AddrOpnd::New(Js::Var address, AddrOpndKind addrOpndKind, Func *func, bool dontEncode /* = false */, Js::Var varLocal /* = nullptr*/)
  1678. {
  1679. AddrOpnd * addrOpnd;
  1680. addrOpnd = JitAnew(func->m_alloc, IR::AddrOpnd);
  1681. addrOpnd->m_address = address;
  1682. addrOpnd->m_localAddress = func->IsOOPJIT() ? varLocal : address;
  1683. addrOpnd->addrOpndKind = addrOpndKind;
  1684. addrOpnd->m_type = addrOpnd->IsVar()? TyVar : TyMachPtr;
  1685. addrOpnd->m_dontEncode = dontEncode;
  1686. addrOpnd->m_isFunction = false;
  1687. addrOpnd->m_metadata = nullptr;
  1688. if(address && addrOpnd->IsVar())
  1689. {
  1690. if(Js::TaggedInt::Is(address))
  1691. {
  1692. addrOpnd->m_valueType = ValueType::GetTaggedInt();
  1693. addrOpnd->SetValueTypeFixed();
  1694. }
  1695. else
  1696. {
  1697. Js::Var var = varLocal ? varLocal : address;
  1698. if (
  1699. #if !FLOATVAR
  1700. varLocal || (!func->IsOOPJIT() && CONFIG_FLAG(OOPJITMissingOpts)) &&
  1701. #endif
  1702. Js::JavascriptNumber::Is_NoTaggedIntCheck(var))
  1703. {
  1704. addrOpnd->m_valueType =
  1705. Js::JavascriptNumber::IsInt32_NoChecks(var)
  1706. ? ValueType::GetInt(false)
  1707. : ValueType::Float;
  1708. addrOpnd->SetValueTypeFixed();
  1709. }
  1710. }
  1711. }
  1712. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1713. addrOpnd->decodedValue = 0;
  1714. addrOpnd->wasVar = addrOpnd->IsVar();
  1715. #endif
  1716. addrOpnd->m_kind = OpndKindAddr;
  1717. return addrOpnd;
  1718. }
  1719. AddrOpnd *
  1720. AddrOpnd::NewFromNumber(int32 value, Func *func, bool dontEncode /* = false */)
  1721. {
  1722. if (!Js::TaggedInt::IsOverflow(value))
  1723. {
  1724. return New(Js::TaggedInt::ToVarUnchecked(value), AddrOpndKindConstantVar, func, dontEncode);
  1725. }
  1726. else
  1727. {
  1728. return NewFromNumberVar(value, func, dontEncode);
  1729. }
  1730. }
  1731. AddrOpnd *
  1732. AddrOpnd::NewFromNumber(int64 value, Func *func, bool dontEncode /* = false */)
  1733. {
  1734. if (!Js::TaggedInt::IsOverflow(value))
  1735. {
  1736. return New(Js::TaggedInt::ToVarUnchecked((int)value), AddrOpndKindConstantVar, func, dontEncode);
  1737. }
  1738. else
  1739. {
  1740. return NewFromNumberVar((double)value, func, dontEncode);
  1741. }
  1742. }
  1743. AddrOpnd *
  1744. AddrOpnd::NewFromNumber(double value, Func *func, bool dontEncode /* = false */)
  1745. {
  1746. //
  1747. // Check if a well-known value:
  1748. // - This significantly cuts down on the below floating-point to integer conversions.
  1749. //
  1750. if (Js::JavascriptNumber::IsNegZero(value))
  1751. {
  1752. return New(func->GetScriptContextInfo()->GetNegativeZeroAddr(), AddrOpndKindDynamicVar, func, dontEncode);
  1753. }
  1754. if (value == +0.0)
  1755. {
  1756. return New(Js::TaggedInt::ToVarUnchecked(0), AddrOpndKindConstantVar, func, dontEncode);
  1757. }
  1758. if (value == 1.0)
  1759. {
  1760. return New(Js::TaggedInt::ToVarUnchecked(1), AddrOpndKindConstantVar, func, dontEncode);
  1761. }
  1762. //
  1763. // Check if number can be reduced back into a TaggedInt:
  1764. // - This avoids extra GC.
  1765. //
  1766. int nValue = (int) value;
  1767. double dblCheck = (double) nValue;
  1768. if ((dblCheck == value) && (!Js::TaggedInt::IsOverflow(nValue)))
  1769. {
  1770. return New(Js::TaggedInt::ToVarUnchecked(nValue), AddrOpndKindConstantVar, func, dontEncode);
  1771. }
  1772. return NewFromNumberVar(value, func, dontEncode);
  1773. }
  1774. AddrOpnd *
  1775. AddrOpnd::NewFromNumberVar(double value, Func *func, bool dontEncode /* = false */)
  1776. {
  1777. Js::Var var = func->AllocateNumber((double)value);
  1778. AddrOpnd* addrOpnd = New((intptr_t)var, AddrOpndKindDynamicVar, func, dontEncode);
  1779. addrOpnd->m_valueType =
  1780. Js::JavascriptNumber::IsInt32(value)
  1781. ? ValueType::GetInt(false)
  1782. : ValueType::Float;
  1783. addrOpnd->SetValueTypeFixed();
  1784. return addrOpnd;
  1785. }
  1786. AddrOpnd *
  1787. AddrOpnd::NewNull(Func *func)
  1788. {
  1789. return AddrOpnd::New((Js::Var)0, AddrOpndKindConstantAddress, func, true);
  1790. }
  1791. ///----------------------------------------------------------------------------
  1792. ///
  1793. /// AddrOpnd::Copy
  1794. ///
  1795. /// Returns a copy of this opnd.
  1796. ///
  1797. ///----------------------------------------------------------------------------
  1798. AddrOpnd *
  1799. AddrOpnd::CopyInternal(Func *func)
  1800. {
  1801. Assert(m_kind == OpndKindAddr);
  1802. AddrOpnd * newOpnd;
  1803. newOpnd = AddrOpnd::New(nullptr, addrOpndKind, func, m_dontEncode);
  1804. // Constructor evaluates address for type, but this is invalid if the address has been encoded, so we wait to set it
  1805. newOpnd->m_address = m_address;
  1806. newOpnd->m_valueType = m_valueType;
  1807. newOpnd->m_isFunction = m_isFunction;
  1808. newOpnd->m_metadata = m_metadata;
  1809. newOpnd->SetType(m_type);
  1810. if (IsValueTypeFixed())
  1811. {
  1812. newOpnd->SetValueTypeFixed();
  1813. }
  1814. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1815. newOpnd->decodedValue = this->decodedValue;
  1816. newOpnd->wasVar = this->wasVar;
  1817. #endif
  1818. return newOpnd;
  1819. }
  1820. ///----------------------------------------------------------------------------
  1821. ///
  1822. /// AddrOpnd::IsEqual
  1823. ///
  1824. ///----------------------------------------------------------------------------
  1825. bool
  1826. AddrOpnd::IsEqualInternal(Opnd *opnd)
  1827. {
  1828. Assert(m_kind == OpndKindAddr);
  1829. if (!opnd->IsAddrOpnd())
  1830. {
  1831. return false;
  1832. }
  1833. return m_address == opnd->AsAddrOpnd()->m_address;
  1834. }
  1835. void
  1836. AddrOpnd::FreeInternal(Func *func)
  1837. {
  1838. Assert(m_kind == OpndKindAddr);
  1839. JitAdelete(func->m_alloc, this);
  1840. }
  1841. void
  1842. AddrOpnd::SetEncodedValue(Js::Var address, AddrOpndKind addrOpndKind)
  1843. {
  1844. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1845. this->decodedValue = this->m_address;
  1846. #endif
  1847. this->SetAddress(address, addrOpndKind);
  1848. }
  1849. void
  1850. AddrOpnd::SetAddress(Js::Var address, AddrOpndKind addrOpndKind)
  1851. {
  1852. this->m_address = address;
  1853. this->addrOpndKind = addrOpndKind;
  1854. }
  1855. ///----------------------------------------------------------------------------
  1856. ///
  1857. /// IndirOpnd::New
  1858. ///
  1859. /// Creates a new IndirOpnd.
  1860. ///
  1861. ///----------------------------------------------------------------------------
  1862. IndirOpnd *
  1863. IndirOpnd::New(RegOpnd *baseOpnd, RegOpnd *indexOpnd, IRType type, Func *func)
  1864. {
  1865. IndirOpnd * indirOpnd;
  1866. AssertMsg(baseOpnd, "An IndirOpnd needs a valid baseOpnd.");
  1867. indirOpnd = JitAnew(func->m_alloc, IndirOpnd);
  1868. indirOpnd->m_func = func;
  1869. indirOpnd->SetBaseOpnd(baseOpnd);
  1870. indirOpnd->SetIndexOpnd(indexOpnd);
  1871. indirOpnd->m_type = type;
  1872. indirOpnd->SetIsJITOptimizedReg(false);
  1873. indirOpnd->m_kind = OpndKindIndir;
  1874. return indirOpnd;
  1875. }
  1876. ///----------------------------------------------------------------------------
  1877. ///
  1878. /// IndirOpnd::New
  1879. ///
  1880. /// Creates a new IndirOpnd.
  1881. ///
  1882. ///----------------------------------------------------------------------------
  1883. IndirOpnd *
  1884. IndirOpnd::New(RegOpnd *baseOpnd, RegOpnd *indexOpnd, byte scale, IRType type, Func *func)
  1885. {
  1886. IndirOpnd * indirOpnd = IndirOpnd::New(baseOpnd, indexOpnd, type, func);
  1887. indirOpnd->m_scale = scale;
  1888. return indirOpnd;
  1889. }
  1890. ///----------------------------------------------------------------------------
  1891. ///
  1892. /// IndirOpnd::New
  1893. ///
  1894. /// Creates a new IndirOpnd.
  1895. ///
  1896. ///----------------------------------------------------------------------------
  1897. IndirOpnd *
  1898. IndirOpnd::New(RegOpnd *indexOpnd, int32 offset, byte scale, IRType type, Func *func)
  1899. {
  1900. IndirOpnd * indirOpnd;
  1901. indirOpnd = JitAnew(func->m_alloc, IndirOpnd);
  1902. indirOpnd->m_func = func;
  1903. indirOpnd->SetBaseOpnd(nullptr);
  1904. indirOpnd->SetOffset(offset, true);
  1905. indirOpnd->SetIndexOpnd(indexOpnd);
  1906. indirOpnd->m_type = type;
  1907. indirOpnd->SetIsJITOptimizedReg(false);
  1908. indirOpnd->m_kind = OpndKindIndir;
  1909. indirOpnd->m_scale = scale;
  1910. return indirOpnd;
  1911. }
  1912. ///----------------------------------------------------------------------------
  1913. ///
  1914. /// IndirOpnd::New
  1915. ///
  1916. /// Creates a new IndirOpnd.
  1917. ///
  1918. ///----------------------------------------------------------------------------
  1919. IndirOpnd *
  1920. IndirOpnd::New(RegOpnd *baseOpnd, int32 offset, IRType type, Func *func, bool dontEncode /* = false */)
  1921. {
  1922. IndirOpnd * indirOpnd;
  1923. indirOpnd = JitAnew(func->m_alloc, IndirOpnd);
  1924. indirOpnd->m_func = func;
  1925. indirOpnd->SetBaseOpnd(baseOpnd);
  1926. indirOpnd->SetOffset(offset, dontEncode);
  1927. indirOpnd->m_type = type;
  1928. indirOpnd->SetIsJITOptimizedReg(false);
  1929. indirOpnd->m_kind = OpndKindIndir;
  1930. return indirOpnd;
  1931. }
  1932. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  1933. ///----------------------------------------------------------------------------
  1934. ///
  1935. /// IndirOpnd::New
  1936. ///
  1937. /// Creates a new IndirOpnd.
  1938. ///
  1939. ///----------------------------------------------------------------------------
  1940. IndirOpnd *
  1941. IndirOpnd::New(RegOpnd *baseOpnd, int32 offset, IRType type, const char16 *desc, Func *func, bool dontEncode /* = false */)
  1942. {
  1943. IndirOpnd * indirOpnd = IndirOpnd::New(baseOpnd, offset, type, func);
  1944. indirOpnd->m_desc = desc;
  1945. indirOpnd->m_dontEncode = dontEncode;
  1946. return indirOpnd;
  1947. }
  1948. #endif
  1949. IndirOpnd::~IndirOpnd()
  1950. {
  1951. if (m_baseOpnd != nullptr)
  1952. {
  1953. m_baseOpnd->Free(m_func);
  1954. }
  1955. if (m_indexOpnd != nullptr)
  1956. {
  1957. m_indexOpnd->Free(m_func);
  1958. }
  1959. }
  1960. ///----------------------------------------------------------------------------
  1961. ///
  1962. /// IndirOpnd::Copy
  1963. ///
  1964. /// Returns a copy of this opnd.
  1965. ///
  1966. ///----------------------------------------------------------------------------
  1967. IndirOpnd *
  1968. IndirOpnd::CopyInternal(Func *func)
  1969. {
  1970. Assert(m_kind == OpndKindIndir);
  1971. IndirOpnd * newOpnd;
  1972. newOpnd = IndirOpnd::New(m_baseOpnd, m_indexOpnd, m_scale, m_type, func);
  1973. newOpnd->m_valueType = m_valueType;
  1974. newOpnd->canStoreTemp = this->canStoreTemp;
  1975. newOpnd->SetOffset(m_offset, m_dontEncode);
  1976. newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
  1977. #if DBG_DUMP
  1978. newOpnd->m_addrKind = m_addrKind;
  1979. newOpnd->m_originalAddress = m_originalAddress;
  1980. #endif
  1981. return newOpnd;
  1982. }
  1983. IndirOpnd *
  1984. IndirOpnd::CloneDefInternal(Func *func)
  1985. {
  1986. Assert(m_kind == OpndKindIndir);
  1987. IndirOpnd * newOpnd;
  1988. // The components of an IndirOpnd are always uses, even if the IndirOpnd itself is a def.
  1989. RegOpnd * newBaseOpnd = m_baseOpnd ? m_baseOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  1990. RegOpnd * newIndexOpnd = m_indexOpnd ? m_indexOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  1991. newOpnd = IndirOpnd::New(newBaseOpnd, newIndexOpnd, m_scale, m_type, func);
  1992. newOpnd->SetOffset(m_offset, m_dontEncode);
  1993. #if DBG_DUMP
  1994. newOpnd->m_addrKind = m_addrKind;
  1995. newOpnd->m_originalAddress = m_originalAddress;
  1996. #endif
  1997. return newOpnd;
  1998. }
  1999. IndirOpnd *
  2000. IndirOpnd::CloneUseInternal(Func *func)
  2001. {
  2002. Assert(m_kind == OpndKindIndir);
  2003. IndirOpnd * newOpnd;
  2004. RegOpnd * newBaseOpnd = m_baseOpnd ? m_baseOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  2005. RegOpnd * newIndexOpnd = m_indexOpnd ? m_indexOpnd->CloneUse(func)->AsRegOpnd() : nullptr;
  2006. newOpnd = IndirOpnd::New(newBaseOpnd, newIndexOpnd, m_scale, m_type, func);
  2007. newOpnd->SetOffset(m_offset, m_dontEncode);
  2008. #if DBG_DUMP
  2009. newOpnd->m_addrKind = m_addrKind;
  2010. newOpnd->m_originalAddress = m_originalAddress;
  2011. #endif
  2012. return newOpnd;
  2013. }
  2014. bool
  2015. IndirOpnd::TryGetIntConstIndexValue(bool trySym, IntConstType *pValue, bool * pIsNotInt)
  2016. {
  2017. *pIsNotInt = false;
  2018. IR::RegOpnd * indexOpnd = this->GetIndexOpnd();
  2019. if (!indexOpnd)
  2020. {
  2021. *pValue = (IntConstType)this->GetOffset();
  2022. return true;
  2023. }
  2024. if (!trySym)
  2025. {
  2026. return false;
  2027. }
  2028. StackSym * indexSym = indexOpnd->m_sym;
  2029. *pIsNotInt = indexOpnd->IsNotInt();
  2030. // Const flags for type-specialized syms are not accurate during the forward pass, so the forward pass cannot use that info
  2031. // while the lowerer can. Additionally, due to value transfers being conservative in a loop prepass, the const flags can
  2032. // show that a sym has a constant value even though the value during the forward pass did not. Skip checking const flags for
  2033. // type-specialized index syms and instead, expect that once the above issues are fixed, that the forward pass would fold a
  2034. // constant index into the indir's offset.
  2035. if (!*pIsNotInt && !indexSym->IsTypeSpec() && indexSym->IsIntConst())
  2036. {
  2037. *pValue = indexSym->GetIntConstValue();
  2038. return true;
  2039. }
  2040. return false;
  2041. }
  2042. ///----------------------------------------------------------------------------
  2043. ///
  2044. /// IndirOpnd::IsEqual
  2045. ///
  2046. ///----------------------------------------------------------------------------
  2047. bool
  2048. IndirOpnd::IsEqualInternal(Opnd *opnd)
  2049. {
  2050. Assert(m_kind == OpndKindIndir);
  2051. Assert(opnd);
  2052. if (!opnd->IsIndirOpnd() || this->GetType() != opnd->GetType())
  2053. {
  2054. return false;
  2055. }
  2056. IndirOpnd *indirOpnd = opnd->AsIndirOpnd();
  2057. return m_offset == indirOpnd->m_offset
  2058. && ((m_baseOpnd == nullptr && indirOpnd->m_baseOpnd == nullptr) || (m_baseOpnd && indirOpnd->m_baseOpnd && m_baseOpnd->IsEqual(indirOpnd->m_baseOpnd)))
  2059. && ((m_indexOpnd == nullptr && indirOpnd->m_indexOpnd == nullptr) || (m_indexOpnd && indirOpnd->m_indexOpnd && m_indexOpnd->IsEqual(indirOpnd->m_indexOpnd)));
  2060. }
  2061. void
  2062. IndirOpnd::FreeInternal(Func *func)
  2063. {
  2064. Assert(m_kind == OpndKindIndir);
  2065. JitAdelete(func->m_alloc, this);
  2066. }
  2067. ///----------------------------------------------------------------------------
  2068. ///
  2069. /// IndirOpnd::SetBaseOpnd
  2070. ///
  2071. ///----------------------------------------------------------------------------
  2072. void
  2073. IndirOpnd::SetBaseOpnd(RegOpnd *baseOpnd)
  2074. {
  2075. if (m_baseOpnd)
  2076. {
  2077. m_baseOpnd->UnUse();
  2078. }
  2079. if (baseOpnd)
  2080. {
  2081. baseOpnd = baseOpnd->Use(m_func)->AsRegOpnd();
  2082. }
  2083. m_baseOpnd = baseOpnd;
  2084. }
  2085. ///----------------------------------------------------------------------------
  2086. ///
  2087. /// IndirOpnd::UnlinkBaseOpnd
  2088. ///
  2089. ///----------------------------------------------------------------------------
  2090. RegOpnd *
  2091. IndirOpnd::UnlinkBaseOpnd()
  2092. {
  2093. RegOpnd * baseOpnd = this->m_baseOpnd;
  2094. // This will also call UnUse()...
  2095. this->SetBaseOpnd(nullptr);
  2096. return baseOpnd;
  2097. }
  2098. void
  2099. IndirOpnd::ReplaceBaseOpnd(RegOpnd *newBase)
  2100. {
  2101. RegOpnd * baseOpnd = this->m_baseOpnd;
  2102. this->UnlinkBaseOpnd();
  2103. baseOpnd->Free(this->m_func);
  2104. this->SetBaseOpnd(newBase);
  2105. }
  2106. ///----------------------------------------------------------------------------
  2107. ///
  2108. /// IndirOpnd::SetIndexOpnd
  2109. ///
  2110. ///----------------------------------------------------------------------------
  2111. void
  2112. IndirOpnd::SetIndexOpnd(RegOpnd *indexOpnd)
  2113. {
  2114. if (m_indexOpnd)
  2115. {
  2116. m_indexOpnd->UnUse();
  2117. }
  2118. if (indexOpnd)
  2119. {
  2120. indexOpnd = indexOpnd->Use(m_func)->AsRegOpnd();
  2121. }
  2122. m_indexOpnd = indexOpnd;
  2123. }
  2124. ///----------------------------------------------------------------------------
  2125. ///
  2126. /// IndirOpnd::UnlinkIndexOpnd
  2127. ///
  2128. ///----------------------------------------------------------------------------
  2129. RegOpnd *
  2130. IndirOpnd::UnlinkIndexOpnd()
  2131. {
  2132. RegOpnd * indexOpnd = this->m_indexOpnd;
  2133. // This will also call UnUse()...
  2134. this->SetIndexOpnd(nullptr);
  2135. return indexOpnd;
  2136. }
  2137. void
  2138. IndirOpnd::ReplaceIndexOpnd(RegOpnd *newIndex)
  2139. {
  2140. RegOpnd * indexOpnd = this->m_indexOpnd;
  2141. this->UnlinkIndexOpnd();
  2142. indexOpnd->Free(this->m_func);
  2143. this->SetIndexOpnd(newIndex);
  2144. }
  2145. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  2146. const char16 *
  2147. IndirOpnd::GetDescription()
  2148. {
  2149. return this->m_desc;
  2150. }
  2151. bool
  2152. IndirOpnd::HasAddrKind() const
  2153. {
  2154. #if DBG_DUMP
  2155. return m_addrKind != (IR::AddrOpndKind) - 1;
  2156. #else
  2157. return false;
  2158. #endif
  2159. }
  2160. IR::AddrOpndKind
  2161. IndirOpnd::GetAddrKind() const
  2162. {
  2163. Assert(HasAddrKind());
  2164. #if DBG_DUMP
  2165. return m_addrKind;
  2166. #else
  2167. return IR::AddrOpndKindDynamicMisc;
  2168. #endif
  2169. }
  2170. void *
  2171. IndirOpnd::GetOriginalAddress() const
  2172. {
  2173. Assert(HasAddrKind());
  2174. #if DBG_DUMP
  2175. Assert(m_originalAddress != nullptr);
  2176. return m_originalAddress;
  2177. #else
  2178. return nullptr;
  2179. #endif
  2180. }
  2181. #endif
  2182. #if DBG_DUMP
  2183. void
  2184. IndirOpnd::SetAddrKind(IR::AddrOpndKind kind, void * originalAddress)
  2185. {
  2186. Assert(originalAddress != nullptr);
  2187. this->m_addrKind = kind;
  2188. this->m_originalAddress = originalAddress;
  2189. }
  2190. #endif
  2191. ///----------------------------------------------------------------------------
  2192. ///
  2193. /// MemRefOpnd::New
  2194. ///
  2195. /// Creates a new MemRefOpnd.
  2196. ///
  2197. ///----------------------------------------------------------------------------
  2198. MemRefOpnd *
  2199. MemRefOpnd::New(intptr_t pMemLoc, IRType type, Func *func, AddrOpndKind addrOpndKind)
  2200. {
  2201. MemRefOpnd * memRefOpnd = JitAnew(func->m_alloc, IR::MemRefOpnd);
  2202. memRefOpnd->m_memLoc = pMemLoc;
  2203. memRefOpnd->m_type = type;
  2204. memRefOpnd->m_kind = OpndKindMemRef;
  2205. #if DBG_DUMP
  2206. memRefOpnd->m_addrKind = addrOpndKind;
  2207. #endif
  2208. return memRefOpnd;
  2209. }
  2210. // TODO: michhol OOP JIT, remove this signature
  2211. MemRefOpnd *
  2212. MemRefOpnd::New(void * pMemLoc, IRType type, Func *func, AddrOpndKind addrOpndKind)
  2213. {
  2214. MemRefOpnd * memRefOpnd = JitAnew(func->m_alloc, IR::MemRefOpnd);
  2215. memRefOpnd->m_memLoc = (intptr_t)pMemLoc;
  2216. memRefOpnd->m_type = type;
  2217. memRefOpnd->m_kind = OpndKindMemRef;
  2218. #if DBG_DUMP
  2219. memRefOpnd->m_addrKind = addrOpndKind;
  2220. #endif
  2221. return memRefOpnd;
  2222. }
  2223. IR::AddrOpndKind
  2224. MemRefOpnd::GetAddrKind() const
  2225. {
  2226. #if DBG_DUMP
  2227. return this->m_addrKind;
  2228. #else
  2229. return AddrOpndKindDynamicMisc;
  2230. #endif
  2231. }
  2232. ///----------------------------------------------------------------------------
  2233. ///
  2234. /// MemRefOpnd::Copy
  2235. ///
  2236. /// Returns a copy of this opnd.
  2237. ///
  2238. ///----------------------------------------------------------------------------
  2239. MemRefOpnd *
  2240. MemRefOpnd::CopyInternal(Func *func)
  2241. {
  2242. Assert(m_kind == OpndKindMemRef);
  2243. MemRefOpnd * newOpnd;
  2244. newOpnd = MemRefOpnd::New(m_memLoc, m_type, func);
  2245. newOpnd->m_valueType = m_valueType;
  2246. newOpnd->m_memLoc = m_memLoc;
  2247. #if DBG_DUMP
  2248. newOpnd->m_addrKind = m_addrKind;
  2249. #endif
  2250. return newOpnd;
  2251. }
  2252. ///----------------------------------------------------------------------------
  2253. ///
  2254. /// MemRefOpnd::IsEqual
  2255. ///
  2256. ///----------------------------------------------------------------------------
  2257. bool
  2258. MemRefOpnd::IsEqualInternal(Opnd *opnd)
  2259. {
  2260. Assert(m_kind == OpndKindMemRef);
  2261. if (!opnd->IsMemRefOpnd() || this->GetType() != opnd->GetType())
  2262. {
  2263. return false;
  2264. }
  2265. MemRefOpnd *memRefOpnd = opnd->AsMemRefOpnd();
  2266. return m_memLoc == memRefOpnd->m_memLoc;
  2267. }
  2268. void
  2269. MemRefOpnd::FreeInternal(Func *func)
  2270. {
  2271. Assert(m_kind == OpndKindMemRef);
  2272. JitAdelete(func->m_alloc, this);
  2273. }
  2274. LabelOpnd *
  2275. LabelOpnd::New(LabelInstr * labelInstr, Func * func)
  2276. {
  2277. LabelOpnd * labelOpnd = JitAnew(func->m_alloc, IR::LabelOpnd);
  2278. labelOpnd->m_label = labelInstr;
  2279. labelOpnd->m_type = TyMachPtr;
  2280. labelInstr->m_hasNonBranchRef = true;
  2281. labelOpnd->m_kind = OpndKindLabel;
  2282. return labelOpnd;
  2283. }
  2284. LabelOpnd *
  2285. LabelOpnd::CopyInternal(Func * func)
  2286. {
  2287. Assert(m_kind == OpndKindLabel);
  2288. LabelOpnd * newOpnd;
  2289. newOpnd = LabelOpnd::New(m_label, func);
  2290. newOpnd->m_valueType = m_valueType;
  2291. return newOpnd;
  2292. }
  2293. bool
  2294. LabelOpnd::IsEqualInternal(Opnd * opnd)
  2295. {
  2296. Assert(m_kind == OpndKindLabel);
  2297. if (!opnd->IsLabelOpnd())
  2298. {
  2299. return false;
  2300. }
  2301. LabelOpnd * newOpnd = opnd->AsLabelOpnd();
  2302. return m_label == newOpnd->GetLabel();
  2303. }
  2304. void
  2305. LabelOpnd::FreeInternal(Func *func)
  2306. {
  2307. Assert(m_kind == OpndKindLabel);
  2308. JitAdelete(func->m_alloc, this);
  2309. }
  2310. IR::RegOpnd *
  2311. Opnd::FindRegUse(IR::RegOpnd *regOpnd)
  2312. {
  2313. StackSym *regSym = regOpnd->m_sym;
  2314. if (this->IsRegOpnd())
  2315. {
  2316. if (this->AsRegOpnd()->m_sym == regSym)
  2317. {
  2318. return this->AsRegOpnd();
  2319. }
  2320. }
  2321. else if (this->IsIndirOpnd())
  2322. {
  2323. IndirOpnd *indirOpnd = this->AsIndirOpnd();
  2324. if (indirOpnd->GetBaseOpnd() && indirOpnd->GetBaseOpnd()->m_sym == regSym)
  2325. {
  2326. return indirOpnd->GetBaseOpnd();
  2327. }
  2328. if (indirOpnd->GetIndexOpnd() && indirOpnd->GetIndexOpnd()->m_sym == regSym)
  2329. {
  2330. return indirOpnd->GetIndexOpnd();
  2331. }
  2332. }
  2333. return nullptr;
  2334. }
  2335. bool
  2336. Opnd::IsArgumentsObject()
  2337. {
  2338. // returns "false" if the sym is not single def (happens when the parent function has formals); the opnd can still be the arguments object.
  2339. // Since we need this information in the inliner where we don't track arguments object sym, going with single def is the best option.
  2340. StackSym * sym = this->GetStackSym();
  2341. return sym && sym->IsSingleDef() && sym->GetInstrDef()->HasAnyLoadHeapArgsOpCode();
  2342. }
  2343. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  2344. void
  2345. Opnd::DumpAddress(void *address, bool printToConsole, bool skipMaskedAddress)
  2346. {
  2347. if (!printToConsole)
  2348. {
  2349. return;
  2350. }
  2351. if (!Js::Configuration::Global.flags.DumpIRAddresses)
  2352. {
  2353. if (skipMaskedAddress)
  2354. {
  2355. return;
  2356. }
  2357. Output::Print(_u("0xXXXXXXXX"));
  2358. }
  2359. else
  2360. {
  2361. #ifdef _M_X64
  2362. Output::Print(_u("0x%012I64X"), address);
  2363. #else
  2364. Output::Print(_u("0x%08X"), address);
  2365. #endif
  2366. }
  2367. }
  2368. void
  2369. Opnd::DumpFunctionInfo(_Outptr_result_buffer_(*count) char16 ** buffer, size_t * count, Js::FunctionInfo * info, bool printToConsole, _In_opt_z_ char16 const * type)
  2370. {
  2371. char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
  2372. if (info->HasBody())
  2373. {
  2374. if (type == nullptr)
  2375. {
  2376. type = _u("FunctionBody");
  2377. }
  2378. Js::FunctionProxy * proxy = info->GetFunctionProxy();
  2379. WriteToBuffer(buffer, count, _u(" (%s [%s%s])"), type, proxy->GetDisplayName(), proxy->GetDebugNumberSet(debugStringBuffer));
  2380. }
  2381. else
  2382. {
  2383. if (type == nullptr)
  2384. {
  2385. type = _u("FunctionInfo");
  2386. }
  2387. WriteToBuffer(buffer, count, _u(" (%s)"), type);
  2388. }
  2389. }
  2390. template<>
  2391. void EncodableOpnd<int32>::DumpEncodable() const
  2392. {
  2393. if (name != nullptr)
  2394. {
  2395. Output::Print(_u("<%s> (value: 0x%X)"), name, m_value);
  2396. }
  2397. else if (decodedValue != 0)
  2398. {
  2399. Output::Print(_u("%d (0x%X) [encoded: 0x%X]"), decodedValue, decodedValue, m_value);
  2400. }
  2401. else
  2402. {
  2403. Output::Print(_u("%d (0x%X)"), m_value, m_value);
  2404. }
  2405. }
  2406. template<>
  2407. void EncodableOpnd<int64>::DumpEncodable() const
  2408. {
  2409. if (name != nullptr)
  2410. {
  2411. Output::Print(_u("<%s> (value: 0x%llX)"), name, m_value);
  2412. }
  2413. else if (decodedValue != 0)
  2414. {
  2415. Output::Print(_u("%lld (0x%llX) [encoded: 0x%llX]"), decodedValue, decodedValue, m_value);
  2416. }
  2417. else
  2418. {
  2419. Output::Print(_u("%lld (0x%llX)"), m_value, m_value);
  2420. }
  2421. }
  2422. ///----------------------------------------------------------------------------
  2423. ///
  2424. /// Opnd::Dump
  2425. ///
  2426. /// Dump this opnd.
  2427. ///
  2428. ///----------------------------------------------------------------------------
  2429. void
  2430. Opnd::Dump(IRDumpFlags flags, Func *func)
  2431. {
  2432. bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
  2433. bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
  2434. FloatConstType floatValue;
  2435. SymOpnd * symOpnd;
  2436. RegOpnd * regOpnd;
  2437. JnHelperMethod helperMethod;
  2438. bool dumpValueType = !SimpleForm;
  2439. switch(GetKind())
  2440. {
  2441. case OpndKindSym:
  2442. symOpnd = this->AsSymOpnd();
  2443. if(symOpnd->m_sym->IsPropertySym() && !SimpleForm)
  2444. {
  2445. symOpnd->m_sym->Dump(flags, symOpnd->GetPropertyOwnerValueType());
  2446. }
  2447. else
  2448. {
  2449. symOpnd->m_sym->Dump(flags);
  2450. }
  2451. if (symOpnd->m_sym->IsStackSym())
  2452. {
  2453. StackSym * stackSym = symOpnd->m_sym->AsStackSym();
  2454. bool hasOffset = stackSym->IsArgSlotSym()?
  2455. ((stackSym->m_offset != -1) || !stackSym->m_isInlinedArgSlot) :
  2456. (stackSym->m_offset != 0);
  2457. if (hasOffset)
  2458. {
  2459. int offset = stackSym->m_offset;
  2460. if(symOpnd->m_offset != 0)
  2461. {
  2462. Assert(static_cast<int>(offset + symOpnd->m_offset) >= offset);
  2463. offset += symOpnd->m_offset;
  2464. }
  2465. Output::Print(_u("<%d>"), offset);
  2466. }
  2467. }
  2468. else if (symOpnd->IsPropertySymOpnd() && !SimpleForm)
  2469. {
  2470. PropertySymOpnd *propertySymOpnd = symOpnd->AsPropertySymOpnd();
  2471. Output::Print(_u("<"));
  2472. if (propertySymOpnd->HasObjTypeSpecFldInfo())
  2473. {
  2474. Output::Print(_u("%u,%s%s%s%s,"), propertySymOpnd->GetObjTypeSpecFldId(), propertySymOpnd->IsPoly() ? _u("p") : _u("m"),
  2475. propertySymOpnd->IsLoadedFromProto() ? _u("~") : _u(""), propertySymOpnd->UsesFixedValue() ? _u("=") : _u(""),
  2476. propertySymOpnd->IsBeingAdded() ? _u("+") : _u(""));
  2477. }
  2478. else
  2479. {
  2480. Output::Print(_u("?,,"));
  2481. }
  2482. Output::Print(_u("%s%s,"), propertySymOpnd->MayNeedTypeCheckProtection() ?
  2483. propertySymOpnd->IsMono() ? _u("+") : _u("=") :
  2484. propertySymOpnd->IsRootObjectNonConfigurableFieldLoad() ? _u("~") : _u("-"),
  2485. propertySymOpnd->IsTypeCheckSeqCandidate() ? _u("+") : _u("-"));
  2486. if (propertySymOpnd->HasObjectTypeSym())
  2487. {
  2488. Output::Print(_u("s%d"), propertySymOpnd->GetObjectTypeSym()->m_id);
  2489. if (propertySymOpnd->IsTypeChecked())
  2490. {
  2491. Output::Print(_u("+%s"), propertySymOpnd->IsMono() ? _u("m") : _u("p"));
  2492. }
  2493. else if (propertySymOpnd->IsTypeAvailable())
  2494. {
  2495. Output::Print(_u("*"));
  2496. }
  2497. if (propertySymOpnd->IsTypeDead())
  2498. {
  2499. Output::Print(_u("!"));
  2500. }
  2501. }
  2502. else
  2503. {
  2504. Output::Print(_u("s?"));
  2505. }
  2506. if (propertySymOpnd->m_sym->AsPropertySym()->m_writeGuardSym != nullptr)
  2507. {
  2508. Output::Print(_u(",s%d"), propertySymOpnd->m_sym->AsPropertySym()->m_writeGuardSym->m_id);
  2509. if (propertySymOpnd->IsWriteGuardChecked())
  2510. {
  2511. Output::Print(_u("+"));
  2512. }
  2513. }
  2514. else
  2515. {
  2516. Output::Print(_u(",s?"));
  2517. }
  2518. if (propertySymOpnd->HasFinalType())
  2519. {
  2520. Output::Print(_u(",final:"));
  2521. this->DumpAddress((void*)propertySymOpnd->GetFinalType()->GetAddr(), /* printToConsole */ true, /* skipMaskedAddress */ false);
  2522. }
  2523. if (propertySymOpnd->GetGuardedPropOps() != nullptr)
  2524. {
  2525. Output::Print(_u(",{"));
  2526. if (func != nullptr)
  2527. {
  2528. int i = 0;
  2529. auto guardedPropOps = propertySymOpnd->GetGuardedPropOps();
  2530. FOREACH_BITSET_IN_SPARSEBV(propertyOpId, guardedPropOps)
  2531. {
  2532. if (i++ > 0)
  2533. {
  2534. Output::Print(_u(","));
  2535. }
  2536. const ObjTypeSpecFldInfo* propertyOpInfo = func->GetTopFunc()->GetGlobalObjTypeSpecFldInfo(propertyOpId);
  2537. if (!JITManager::GetJITManager()->IsOOPJITEnabled())
  2538. {
  2539. Output::Print(_u("%s"), func->GetInProcThreadContext()->GetPropertyRecord(propertyOpInfo->GetPropertyId())->GetBuffer(), propertyOpId);
  2540. }
  2541. Output::Print(_u("(%u)"), propertyOpId);
  2542. if (propertyOpInfo->IsLoadedFromProto())
  2543. {
  2544. Output::Print(_u("~"));
  2545. }
  2546. if (propertyOpInfo->HasFixedValue())
  2547. {
  2548. Output::Print(_u("="));
  2549. }
  2550. if (propertyOpInfo->IsBeingAdded())
  2551. {
  2552. Output::Print(_u("+"));
  2553. }
  2554. }
  2555. NEXT_BITSET_IN_SPARSEBV;
  2556. }
  2557. else
  2558. {
  2559. Output::Print(_u("(no func)"));
  2560. }
  2561. Output::Print(_u("}"));
  2562. }
  2563. if (propertySymOpnd->GetWriteGuards() != nullptr)
  2564. {
  2565. Output::Print(_u(",{"));
  2566. int i = 0;
  2567. auto writeGuards = propertySymOpnd->GetWriteGuards();
  2568. FOREACH_BITSET_IN_SPARSEBV(writeGuardSymId, writeGuards)
  2569. {
  2570. if (i++ > 0)
  2571. {
  2572. Output::Print(_u(","));
  2573. }
  2574. Output::Print(_u("s%d"), writeGuardSymId);
  2575. }
  2576. NEXT_BITSET_IN_SPARSEBV;
  2577. Output::Print(_u("}"));
  2578. }
  2579. if (propertySymOpnd->canStoreTemp)
  2580. {
  2581. Output::Print(_u(",t"));
  2582. }
  2583. Output::Print(_u(">"));
  2584. }
  2585. break;
  2586. case OpndKindReg:
  2587. regOpnd = this->AsRegOpnd();
  2588. if (regOpnd->m_sym)
  2589. {
  2590. regOpnd->m_sym->Dump(flags);
  2591. }
  2592. if(AsmDumpMode)
  2593. {
  2594. //
  2595. // Print no brackets
  2596. //
  2597. Output::Print(_u("%S"), RegNames[regOpnd->GetReg()]);
  2598. }
  2599. else
  2600. {
  2601. if (regOpnd->GetReg() != RegNOREG)
  2602. {
  2603. Output::Print(_u("(%S)"), RegNames[regOpnd->GetReg()]);
  2604. }
  2605. if (regOpnd->m_isTempLastUse)
  2606. {
  2607. Output::Print(_u("[isTempLastUse]"));
  2608. }
  2609. StackSym *sym = regOpnd->GetStackSym();
  2610. if (sym && func)
  2611. {
  2612. if (sym == func->GetScriptContextSym())
  2613. {
  2614. Output::Print(_u("[ScriptContext]"));
  2615. }
  2616. else if (sym == func->GetFuncObjSym())
  2617. {
  2618. Output::Print(_u("[FuncObj]"));
  2619. }
  2620. else if (sym == func->GetFunctionBodySym())
  2621. {
  2622. Output::Print(_u("[FunctionBody]"));
  2623. }
  2624. }
  2625. if(regOpnd->IsArrayRegOpnd())
  2626. {
  2627. if(dumpValueType)
  2628. {
  2629. // Dump the array value type before the associated syms
  2630. DumpValueType();
  2631. dumpValueType = false;
  2632. }
  2633. const ArrayRegOpnd *const arrayRegOpnd = regOpnd->AsArrayRegOpnd();
  2634. if(arrayRegOpnd->HeadSegmentSym())
  2635. {
  2636. Output::Print(_u("[seg: "));
  2637. arrayRegOpnd->HeadSegmentSym()->Dump();
  2638. Output::Print(_u("]"));
  2639. }
  2640. if(arrayRegOpnd->HeadSegmentLengthSym())
  2641. {
  2642. Output::Print(_u("[segLen: "));
  2643. arrayRegOpnd->HeadSegmentLengthSym()->Dump();
  2644. Output::Print(_u("]"));
  2645. }
  2646. if(arrayRegOpnd->LengthSym() && arrayRegOpnd->LengthSym() != arrayRegOpnd->HeadSegmentLengthSym())
  2647. {
  2648. Output::Print(_u("[len: "));
  2649. arrayRegOpnd->LengthSym()->Dump();
  2650. Output::Print(_u("]"));
  2651. }
  2652. if(arrayRegOpnd->EliminatedLowerBoundCheck() || arrayRegOpnd->EliminatedUpperBoundCheck())
  2653. {
  2654. Output::Print(_u("["));
  2655. if(arrayRegOpnd->EliminatedLowerBoundCheck())
  2656. {
  2657. Output::Print(_u(">"));
  2658. }
  2659. if(arrayRegOpnd->EliminatedUpperBoundCheck())
  2660. {
  2661. Output::Print(_u("<"));
  2662. }
  2663. Output::Print(_u("]"));
  2664. }
  2665. }
  2666. }
  2667. break;
  2668. case OpndKindInt64Const:
  2669. {
  2670. Int64ConstOpnd * intConstOpnd = this->AsInt64ConstOpnd();
  2671. intConstOpnd->DumpEncodable();
  2672. break;
  2673. }
  2674. case OpndKindIntConst:
  2675. {
  2676. IntConstOpnd * intConstOpnd = this->AsIntConstOpnd();
  2677. intConstOpnd->DumpEncodable();
  2678. break;
  2679. }
  2680. case OpndKindRegBV:
  2681. {
  2682. RegBVOpnd * regBVOpnd = this->AsRegBVOpnd();
  2683. regBVOpnd->m_value.Dump();
  2684. break;
  2685. }
  2686. case OpndKindHelperCall:
  2687. helperMethod = this->AsHelperCallOpnd()->m_fnHelper;
  2688. Output::Print(_u("%s"), IR::GetMethodName(helperMethod));
  2689. break;
  2690. case OpndKindFloatConst:
  2691. floatValue = this->AsFloatConstOpnd()->m_value;
  2692. Output::Print(_u("%G"), floatValue);
  2693. break;
  2694. case OpndKindAddr:
  2695. DumpOpndKindAddr(AsmDumpMode, func);
  2696. break;
  2697. case OpndKindIndir:
  2698. {
  2699. IndirOpnd * indirOpnd = this->AsIndirOpnd();
  2700. RegOpnd * baseOpnd = indirOpnd->GetBaseOpnd();
  2701. RegOpnd * indexOpnd = indirOpnd->GetIndexOpnd();
  2702. const int32 offset = indirOpnd->GetOffset();
  2703. Output::Print(_u("["));
  2704. if (baseOpnd != nullptr)
  2705. {
  2706. baseOpnd->Dump(flags, func);
  2707. }
  2708. else
  2709. {
  2710. Output::Print(_u("<null>"));
  2711. }
  2712. if (indexOpnd != nullptr)
  2713. {
  2714. Output::Print(_u("+"));
  2715. indexOpnd->Dump(flags, func);
  2716. if (indirOpnd->GetScale() > 0)
  2717. {
  2718. Output::Print(_u("*%d"), 1 << indirOpnd->GetScale());
  2719. }
  2720. }
  2721. if (offset != 0)
  2722. {
  2723. if (!Js::Configuration::Global.flags.DumpIRAddresses && indirOpnd->HasAddrKind())
  2724. {
  2725. Output::Print(_u("+XX"));
  2726. }
  2727. else
  2728. {
  2729. const auto sign = offset >= 0 ? _u("+") : _u("");
  2730. if (AsmDumpMode)
  2731. {
  2732. Output::Print(_u("%sXXXX%04d"), sign, offset & 0xffff);
  2733. }
  2734. else
  2735. {
  2736. Output::Print(_u("%s%d"), sign, offset);
  2737. }
  2738. }
  2739. }
  2740. if (indirOpnd->GetDescription())
  2741. {
  2742. Output::Print(_u(" <%s>"), indirOpnd->GetDescription());
  2743. }
  2744. if (indirOpnd->HasAddrKind())
  2745. {
  2746. INT_PTR address = (INT_PTR)indirOpnd->GetOriginalAddress();
  2747. Output::Print(_u(" <"));
  2748. const size_t BUFFER_LEN = 128;
  2749. char16 buffer[BUFFER_LEN];
  2750. GetAddrDescription(buffer, BUFFER_LEN, (void *)address, indirOpnd->GetAddrKind(), AsmDumpMode, /*printToConsole */ true, func, /* skipMaskedAddress */true);
  2751. Output::Print(_u("%s"), buffer);
  2752. Output::Print(_u(">"));
  2753. }
  2754. Output::Print(_u("]"));
  2755. break;
  2756. }
  2757. case OpndKindMemRef:
  2758. {
  2759. DumpOpndKindMemRef(AsmDumpMode, func);
  2760. break;
  2761. }
  2762. case OpndKindLabel:
  2763. {
  2764. LabelOpnd * labelOpnd = this->AsLabelOpnd();
  2765. LabelInstr * labelInstr = labelOpnd->GetLabel();
  2766. if (labelInstr == nullptr)
  2767. {
  2768. Output::Print(_u("??"));
  2769. }
  2770. else
  2771. {
  2772. Output::Print(_u("&$L%d"), labelInstr->m_id);
  2773. }
  2774. break;
  2775. }
  2776. }
  2777. if(!AsmDumpMode && dumpValueType)
  2778. {
  2779. DumpValueType();
  2780. }
  2781. if (!SimpleForm || this->GetType() != TyVar)
  2782. {
  2783. Output::Print(_u("."));
  2784. IRType_Dump(this->GetType());
  2785. }
  2786. if (this->m_isDead && !SimpleForm)
  2787. {
  2788. Output::Print(_u("!"));
  2789. }
  2790. }
  2791. ///----------------------------------------------------------------------------
  2792. ///
  2793. /// Opnd::DumpOpndKindAddr
  2794. ///
  2795. /// Dump this opnd as an address.
  2796. ///
  2797. ///----------------------------------------------------------------------------
  2798. void
  2799. Opnd::DumpOpndKindAddr(bool AsmDumpMode, Func *func)
  2800. {
  2801. const size_t BUFFER_LEN = 128;
  2802. char16 buffer[BUFFER_LEN];
  2803. GetAddrDescription(buffer, BUFFER_LEN, AsmDumpMode, true, func);
  2804. Output::Print(_u("%s"), buffer);
  2805. }
  2806. void
  2807. Opnd::DumpOpndKindMemRef(bool AsmDumpMode, Func *func)
  2808. {
  2809. MemRefOpnd *memRefOpnd = this->AsMemRefOpnd();
  2810. Output::Print(_u("["));
  2811. const size_t BUFFER_LEN = 128;
  2812. char16 buffer[BUFFER_LEN];
  2813. // TODO: michhol, make this intptr_t
  2814. GetAddrDescription(buffer, BUFFER_LEN, (void*)memRefOpnd->GetMemLoc(), memRefOpnd->GetAddrKind(), AsmDumpMode, true, func);
  2815. Output::Print(_u("%s"), buffer);
  2816. Output::Print(_u("]"));
  2817. }
  2818. /**
  2819. WriteToBuffer
  2820. Write <fmt> with applicable replacements into <buffer>.
  2821. Subtract the number of characters written from <count>, and increment the address
  2822. <buffer> so that subsequent calls to this function will continue writing at the point
  2823. in the buffer where this function left off and will respect the maximum length specified
  2824. by count.
  2825. @param buffer
  2826. A pointer to a buffer which will hold the result.
  2827. @param count
  2828. The maximum number of characters that should be returned in <buffer>.
  2829. @param fmt
  2830. A format string.
  2831. @param ...
  2832. Additional parameters to be passed to the formatter.
  2833. */
  2834. void
  2835. Opnd::WriteToBuffer(_Outptr_result_buffer_(*count) char16 **buffer, size_t *count, const char16 *fmt, ...)
  2836. {
  2837. va_list argptr;
  2838. va_start(argptr, fmt);
  2839. int len = _vsnwprintf_s(*buffer, *count, _TRUNCATE, fmt, argptr);
  2840. *count -= len;
  2841. *buffer += len;
  2842. va_end(argptr);
  2843. }
  2844. void
  2845. Opnd::GetAddrDescription(__out_ecount(count) char16 *const description, const size_t count,
  2846. void * address, IR::AddrOpndKind addressKind, bool AsmDumpMode, bool printToConsole, Func *func, bool skipMaskedAddress)
  2847. {
  2848. char16 *buffer = description;
  2849. size_t n = count;
  2850. if (address)
  2851. {
  2852. switch (addressKind)
  2853. {
  2854. case IR::AddrOpndKindConstantAddress:
  2855. {
  2856. #ifdef _M_X64_OR_ARM64
  2857. char16 const * format = _u("0x%012I64X");
  2858. #else
  2859. char16 const * format = _u("0x%08X");
  2860. #endif
  2861. WriteToBuffer(&buffer, &n, format, address);
  2862. }
  2863. break;
  2864. case IR::AddrOpndKindDynamicVar:
  2865. if (Js::TaggedInt::Is(address))
  2866. {
  2867. #ifdef _M_X64_OR_ARM64
  2868. char16 const * format = _u("0x%012I64X (value: %d)");
  2869. #else
  2870. char16 const * format = _u("0x%08X (value: %d)");
  2871. #endif
  2872. WriteToBuffer(&buffer, &n, format, address, Js::TaggedInt::ToInt32(address));
  2873. }
  2874. #if FLOATVAR
  2875. else if (Js::JavascriptNumber::Is_NoTaggedIntCheck(address))
  2876. #else
  2877. else if (!func->IsOOPJIT() && Js::JavascriptNumber::Is_NoTaggedIntCheck(address))
  2878. #endif
  2879. {
  2880. WriteToBuffer(&buffer, &n, _u(" (value: %f)"), Js::JavascriptNumber::GetValue(address));
  2881. }
  2882. else
  2883. {
  2884. DumpAddress(address, printToConsole, skipMaskedAddress);
  2885. // TODO: michhol OOP JIT, fix dumping these
  2886. if (func->IsOOPJIT())
  2887. {
  2888. WriteToBuffer(&buffer, &n, _u(" (unknown)"));
  2889. }
  2890. else
  2891. {
  2892. switch (Js::RecyclableObject::FromVar(address)->GetTypeId())
  2893. {
  2894. case Js::TypeIds_Boolean:
  2895. WriteToBuffer(&buffer, &n, Js::JavascriptBoolean::FromVar(address)->GetValue() ? _u(" (true)") : _u(" (false)"));
  2896. break;
  2897. case Js::TypeIds_String:
  2898. WriteToBuffer(&buffer, &n, _u(" (\"%s\")"), Js::JavascriptString::FromVar(address)->GetSz());
  2899. break;
  2900. case Js::TypeIds_Number:
  2901. WriteToBuffer(&buffer, &n, _u(" (value: %f)"), Js::JavascriptNumber::GetValue(address));
  2902. break;
  2903. case Js::TypeIds_Undefined:
  2904. WriteToBuffer(&buffer, &n, _u(" (undefined)"));
  2905. break;
  2906. case Js::TypeIds_Null:
  2907. WriteToBuffer(&buffer, &n, _u(" (null)"));
  2908. break;
  2909. case Js::TypeIds_GlobalObject:
  2910. WriteToBuffer(&buffer, &n, _u(" (GlobalObject)"));
  2911. break;
  2912. case Js::TypeIds_UndeclBlockVar:
  2913. WriteToBuffer(&buffer, &n, _u(" (UndeclBlockVar)"));
  2914. break;
  2915. case Js::TypeIds_Function:
  2916. DumpFunctionInfo(&buffer, &n, ((Js::JavascriptFunction *)address)->GetFunctionInfo(), printToConsole, _u("FunctionObject"));
  2917. break;
  2918. default:
  2919. WriteToBuffer(&buffer, &n, _u(" (DynamicObject)"));
  2920. break;
  2921. }
  2922. }
  2923. }
  2924. break;
  2925. case IR::AddrOpndKindConstantVar:
  2926. {
  2927. #ifdef _M_X64_OR_ARM64
  2928. char16 const * format = _u("0x%012I64X%s");
  2929. #else
  2930. char16 const * format = _u("0x%08X%s");
  2931. #endif
  2932. char16 const * addressName = _u("");
  2933. if (address == Js::JavascriptArray::MissingItem)
  2934. {
  2935. addressName = _u(" (MissingItem)");
  2936. }
  2937. #if FLOATVAR
  2938. else if (address == (Js::Var)Js::FloatTag_Value)
  2939. {
  2940. addressName = _u(" (FloatTag)");
  2941. }
  2942. #endif
  2943. WriteToBuffer(&buffer, &n, format, address, addressName);
  2944. break;
  2945. }
  2946. case IR::AddrOpndKindDynamicScriptContext:
  2947. Assert(func == nullptr || (intptr_t)address == func->GetScriptContextInfo()->GetAddr());
  2948. // The script context pointer is unstable allocated from the CRT
  2949. DumpAddress(address, printToConsole, skipMaskedAddress);
  2950. WriteToBuffer(&buffer, &n, _u(" (ScriptContext)"));
  2951. break;
  2952. case IR::AddrOpndKindDynamicCharStringCache:
  2953. Assert(func == nullptr || (intptr_t)address == func->GetScriptContextInfo()->GetCharStringCacheAddr());
  2954. DumpAddress(address, printToConsole, skipMaskedAddress);
  2955. WriteToBuffer(&buffer, &n, _u(" (CharStringCache)"));
  2956. break;
  2957. case IR::AddrOpndKindDynamicBailOutRecord:
  2958. DumpAddress(address, printToConsole, skipMaskedAddress);
  2959. WriteToBuffer(&buffer, &n, _u(" (BailOutRecord)"));
  2960. break;
  2961. case IR::AddrOpndKindDynamicInlineCache:
  2962. DumpAddress(address, printToConsole, skipMaskedAddress);
  2963. WriteToBuffer(&buffer, &n, _u(" (InlineCache)"));
  2964. break;
  2965. case IR::AddrOpndKindDynamicIsInstInlineCacheFunctionRef:
  2966. DumpAddress(address, printToConsole, skipMaskedAddress);
  2967. WriteToBuffer(&buffer, &n, _u(" (&IsInstInlineCache.function)"));
  2968. break;
  2969. case IR::AddrOpndKindDynamicIsInstInlineCacheTypeRef:
  2970. DumpAddress(address, printToConsole, skipMaskedAddress);
  2971. WriteToBuffer(&buffer, &n, _u(" (&IsInstInlineCache.type)"));
  2972. break;
  2973. case IR::AddrOpndKindDynamicIsInstInlineCacheResultRef:
  2974. DumpAddress(address, printToConsole, skipMaskedAddress);
  2975. WriteToBuffer(&buffer, &n, _u(" (&IsInstInlineCache.result)"));
  2976. break;
  2977. case AddrOpndKindDynamicGuardValueRef:
  2978. DumpAddress(address, printToConsole, skipMaskedAddress);
  2979. WriteToBuffer(&buffer, &n, _u(" (&GuardValue)"));
  2980. break;
  2981. case AddrOpndKindDynamicAuxSlotArrayRef:
  2982. DumpAddress(address, printToConsole, skipMaskedAddress);
  2983. WriteToBuffer(&buffer, &n, _u(" (&AuxSlotArray)"));
  2984. break;
  2985. case AddrOpndKindDynamicPropertySlotRef:
  2986. DumpAddress(address, printToConsole, skipMaskedAddress);
  2987. WriteToBuffer(&buffer, &n, _u(" (&PropertySlot)"));
  2988. break;
  2989. case AddrOpndKindDynamicBailOutKindRef:
  2990. DumpAddress(address, printToConsole, skipMaskedAddress);
  2991. WriteToBuffer(&buffer, &n, _u(" (&BailOutKind)"));
  2992. break;
  2993. case AddrOpndKindDynamicArrayCallSiteInfo:
  2994. DumpAddress(address, printToConsole, skipMaskedAddress);
  2995. WriteToBuffer(&buffer, &n, _u(" (ArrayCallSiteInfo)"));
  2996. break;
  2997. case AddrOpndKindDynamicTypeCheckGuard:
  2998. DumpAddress(address, printToConsole, skipMaskedAddress);
  2999. WriteToBuffer(&buffer, &n, _u(" (TypeCheckGuard)"));
  3000. break;
  3001. case AddrOpndKindDynamicRecyclerAllocatorEndAddressRef:
  3002. DumpAddress(address, printToConsole, skipMaskedAddress);
  3003. WriteToBuffer(&buffer, &n, _u(" (&RecyclerAllocatorEndAddress)"));
  3004. break;
  3005. case AddrOpndKindDynamicAuxBufferRef:
  3006. DumpAddress(address, printToConsole, skipMaskedAddress);
  3007. WriteToBuffer(&buffer, &n, _u(" (AuxBufferRef)"));
  3008. break;
  3009. case AddrOpndKindDynamicRecyclerAllocatorFreeListRef:
  3010. DumpAddress(address, printToConsole, skipMaskedAddress);
  3011. WriteToBuffer(&buffer, &n, _u(" (&RecyclerAllocatorFreeList)"));
  3012. break;
  3013. case IR::AddrOpndKindDynamicFunctionInfo:
  3014. DumpAddress(address, printToConsole, skipMaskedAddress);
  3015. if (func->IsOOPJIT())
  3016. {
  3017. // TODO: OOP JIT, dump more info
  3018. WriteToBuffer(&buffer, &n, _u(" (FunctionInfo)"));
  3019. }
  3020. else
  3021. {
  3022. DumpFunctionInfo(&buffer, &n, (Js::FunctionInfo *)address, printToConsole);
  3023. }
  3024. break;
  3025. case IR::AddrOpndKindDynamicFunctionBody:
  3026. DumpAddress(address, printToConsole, skipMaskedAddress);
  3027. if (func->IsOOPJIT())
  3028. {
  3029. // TODO: OOP JIT, dump more info
  3030. WriteToBuffer(&buffer, &n, _u(" (FunctionBody)"));
  3031. }
  3032. else
  3033. {
  3034. DumpFunctionInfo(&buffer, &n, ((Js::FunctionBody *)address)->GetFunctionInfo(), printToConsole);
  3035. }
  3036. break;
  3037. case IR::AddrOpndKindDynamicFunctionBodyWeakRef:
  3038. DumpAddress(address, printToConsole, skipMaskedAddress);
  3039. if (func->IsOOPJIT())
  3040. {
  3041. // TODO: OOP JIT, dump more info
  3042. WriteToBuffer(&buffer, &n, _u(" (FunctionBodyWeakRef)"));
  3043. }
  3044. else
  3045. {
  3046. DumpFunctionInfo(&buffer, &n, ((RecyclerWeakReference<Js::FunctionBody> *)address)->FastGet()->GetFunctionInfo(), printToConsole, _u("FunctionBodyWeakRef"));
  3047. }
  3048. break;
  3049. case IR::AddrOpndKindDynamicFunctionEnvironmentRef:
  3050. DumpAddress(address, printToConsole, skipMaskedAddress);
  3051. DumpFunctionInfo(&buffer, &n, ((Js::ScriptFunction *)((intptr_t)address - Js::ScriptFunction::GetOffsetOfEnvironment()))->GetFunctionInfo(),
  3052. printToConsole, _u("ScriptFunctionEnvironmentRef"));
  3053. break;
  3054. case IR::AddrOpndKindDynamicVtable:
  3055. if ((INT_PTR)address == Js::ScriptContextOptimizationOverrideInfo::InvalidVtable)
  3056. {
  3057. WriteToBuffer(&buffer, &n, _u("%d (Invalid Vtable)"), Js::ScriptContextOptimizationOverrideInfo::InvalidVtable);
  3058. }
  3059. else
  3060. {
  3061. DumpAddress(address, printToConsole, skipMaskedAddress);
  3062. WriteToBuffer(&buffer, &n, _u(" (%S Vtable)"), func->GetVtableName((INT_PTR)address));
  3063. }
  3064. break;
  3065. case IR::AddrOpndKindDynamicTypeHandler:
  3066. DumpAddress(address, printToConsole, skipMaskedAddress);
  3067. WriteToBuffer(&buffer, &n, _u(" (TypeHandler)"));
  3068. break;
  3069. case IR::AddrOpndKindDynamicObjectTypeRef:
  3070. DumpAddress(address, printToConsole, skipMaskedAddress);
  3071. {
  3072. Js::RecyclableObject * dynamicObject = (Js::RecyclableObject *)((intptr_t)address - Js::RecyclableObject::GetOffsetOfType());
  3073. if (!func->IsOOPJIT() && Js::JavascriptFunction::Is(dynamicObject))
  3074. {
  3075. DumpFunctionInfo(&buffer, &n, Js::JavascriptFunction::FromVar((void *)((intptr_t)address - Js::RecyclableObject::GetOffsetOfType()))->GetFunctionInfo(),
  3076. printToConsole, _u("FunctionObjectTypeRef"));
  3077. }
  3078. else
  3079. {
  3080. // TODO: OOP JIT, dump more info
  3081. WriteToBuffer(&buffer, &n, _u(" (ObjectTypeRef)"));
  3082. }
  3083. }
  3084. break;
  3085. case IR::AddrOpndKindDynamicType:
  3086. DumpAddress(address, printToConsole, skipMaskedAddress);
  3087. // TODO: OOP JIT, dump more info
  3088. if(!func->IsOOPJIT())
  3089. {
  3090. Js::TypeId typeId = ((Js::Type*)address)->GetTypeId();
  3091. switch (typeId)
  3092. {
  3093. case Js::TypeIds_Number:
  3094. WriteToBuffer(&buffer, &n, _u(" (Type: StaticNumber)"));
  3095. break;
  3096. case Js::TypeIds_String:
  3097. WriteToBuffer(&buffer, &n, _u(" (Type: StaticString)"));
  3098. break;
  3099. case Js::TypeIds_Object:
  3100. WriteToBuffer(&buffer, &n, _u(" (Type: Object)"));
  3101. break;
  3102. case Js::TypeIds_RegEx:
  3103. WriteToBuffer(&buffer, &n, _u(" (Type: Regex)"));
  3104. break;
  3105. case Js::TypeIds_Array:
  3106. WriteToBuffer(&buffer, &n, _u(" (Type: Array)"));
  3107. break;
  3108. case Js::TypeIds_NativeIntArray:
  3109. WriteToBuffer(&buffer, &n, _u(" (Type: NativeIntArray)"));
  3110. break;
  3111. case Js::TypeIds_NativeFloatArray:
  3112. WriteToBuffer(&buffer, &n, _u(" (Type: NativeFltArray)"));
  3113. break;
  3114. default:
  3115. WriteToBuffer(&buffer, &n, _u(" (Type: Id %d)"), typeId);
  3116. break;
  3117. }
  3118. }
  3119. break;
  3120. case AddrOpndKindDynamicFrameDisplay:
  3121. DumpAddress(address, printToConsole, skipMaskedAddress);
  3122. if (!func->IsOOPJIT())
  3123. {
  3124. Js::FrameDisplay * frameDisplay = (Js::FrameDisplay *)address;
  3125. WriteToBuffer(&buffer, &n, (frameDisplay->GetStrictMode() ? _u(" (StrictFrameDisplay len %d)") : _u(" (FrameDisplay len %d)")),
  3126. frameDisplay->GetLength());
  3127. }
  3128. else
  3129. {
  3130. WriteToBuffer(&buffer, &n, _u(" (FrameDisplay)"));
  3131. }
  3132. break;
  3133. case AddrOpndKindSz:
  3134. WriteToBuffer(&buffer, &n, wcslen((char16 const *)address) > 30 ? _u("\"%.30s...\"") : _u("\"%.30s\""), address);
  3135. break;
  3136. case AddrOpndKindDynamicFloatRef:
  3137. DumpAddress(address, printToConsole, skipMaskedAddress);
  3138. WriteToBuffer(&buffer, &n, _u(" (&(float)%f)"), *(float *)address);
  3139. break;
  3140. case AddrOpndKindDynamicDoubleRef:
  3141. DumpAddress(address, printToConsole, skipMaskedAddress);
  3142. WriteToBuffer(&buffer, &n, _u(" (&(double)%f)"), *(double *)address);
  3143. break;
  3144. case AddrOpndKindForInCache:
  3145. DumpAddress(address, printToConsole, skipMaskedAddress);
  3146. WriteToBuffer(&buffer, &n, _u(" (ForInCache)"));
  3147. break;
  3148. case AddrOpndKindForInCacheType:
  3149. DumpAddress(address, printToConsole, skipMaskedAddress);
  3150. WriteToBuffer(&buffer, &n, _u(" (&ForInCache->type)"));
  3151. break;
  3152. case AddrOpndKindForInCacheData:
  3153. DumpAddress(address, printToConsole, skipMaskedAddress);
  3154. WriteToBuffer(&buffer, &n, _u(" (&ForInCache->data)"));
  3155. break;
  3156. case AddrOpndKindDynamicNativeCodeDataRef:
  3157. DumpAddress(address, printToConsole, skipMaskedAddress);
  3158. WriteToBuffer(&buffer, &n, _u(" (&NativeCodeData)"));
  3159. break;
  3160. default:
  3161. DumpAddress(address, printToConsole, skipMaskedAddress);
  3162. if ((intptr_t)address == func->GetThreadContextInfo()->GetNullFrameDisplayAddr())
  3163. {
  3164. WriteToBuffer(&buffer, &n, _u(" (NullFrameDisplay)"));
  3165. }
  3166. else if ((intptr_t)address == func->GetThreadContextInfo()->GetStrictNullFrameDisplayAddr())
  3167. {
  3168. WriteToBuffer(&buffer, &n, _u(" (StrictNullFrameDisplay)"));
  3169. }
  3170. else if ((intptr_t)address == func->GetScriptContextInfo()->GetNumberAllocatorAddr())
  3171. {
  3172. WriteToBuffer(&buffer, &n, _u(" (NumberAllocator)"));
  3173. }
  3174. else if ((intptr_t)address == func->GetScriptContextInfo()->GetRecyclerAddr())
  3175. {
  3176. WriteToBuffer(&buffer, &n, _u(" (Recycler)"));
  3177. }
  3178. else if (func->GetWorkItem()->Type() == JsFunctionType && (intptr_t)address == func->GetWorkItem()->GetCallsCountAddress())
  3179. {
  3180. WriteToBuffer(&buffer, &n, _u(" (&CallCount)"));
  3181. }
  3182. else if ((intptr_t)address == func->GetThreadContextInfo()->GetImplicitCallFlagsAddr())
  3183. {
  3184. WriteToBuffer(&buffer, &n, _u(" (&ImplicitCallFlags)"));
  3185. }
  3186. else if ((intptr_t)address == func->GetThreadContextInfo()->GetDisableImplicitFlagsAddr())
  3187. {
  3188. WriteToBuffer(&buffer, &n, _u(" (&DisableImplicitCallFlags)"));
  3189. }
  3190. else if ((intptr_t)address == func->GetThreadContextInfo()->GetThreadStackLimitAddr())
  3191. {
  3192. WriteToBuffer(&buffer, &n, _u(" (&StackLimit)"));
  3193. }
  3194. else if (func->CanAllocInPreReservedHeapPageSegment() &&
  3195. #if ENABLE_OOP_NATIVE_CODEGEN
  3196. (func->IsOOPJIT()
  3197. ? func->GetOOPThreadContext()->GetPreReservedSectionAllocator()->IsPreReservedEndAddress(address)
  3198. : func->GetInProcThreadContext()->GetPreReservedVirtualAllocator()->IsPreReservedEndAddress(address)
  3199. )
  3200. #else
  3201. func->GetInProcThreadContext()->GetPreReservedVirtualAllocator()->IsPreReservedEndAddress(address)
  3202. #endif
  3203. )
  3204. {
  3205. WriteToBuffer(&buffer, &n, _u(" (PreReservedCodeSegmentEnd)"));
  3206. }
  3207. else if ((intptr_t)address == func->GetScriptContextInfo()->GetSideEffectsAddr())
  3208. {
  3209. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_SideEffects)"));
  3210. }
  3211. else if ((intptr_t)address == func->GetScriptContextInfo()->GetArraySetElementFastPathVtableAddr())
  3212. {
  3213. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_ArraySetElementFastPathVtable)"));
  3214. }
  3215. else if ((intptr_t)address == func->GetScriptContextInfo()->GetIntArraySetElementFastPathVtableAddr())
  3216. {
  3217. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_IntArraySetElementFastPathVtable)"));
  3218. }
  3219. else if ((intptr_t)address == func->GetScriptContextInfo()->GetFloatArraySetElementFastPathVtableAddr())
  3220. {
  3221. WriteToBuffer(&buffer, &n, _u(" (&OptimizationOverrides_FloatArraySetElementFastPathVtable)"));
  3222. }
  3223. else
  3224. {
  3225. WriteToBuffer(&buffer, &n, _u(" (Unknown)"));
  3226. }
  3227. }
  3228. }
  3229. else
  3230. {
  3231. WriteToBuffer(&buffer, &n, _u("(NULL)"));
  3232. }
  3233. }
  3234. /**
  3235. GetAddrDescription
  3236. Determine the type of the address and place at most <count> wide chars of the
  3237. description into <description>.
  3238. Force null termination of <description>.
  3239. @param description
  3240. A buffer which will hold the description.
  3241. @param count
  3242. The maximum number of characters that should be returned in <description>.
  3243. @param AsmDumpMode
  3244. @param func
  3245. */
  3246. void
  3247. Opnd::GetAddrDescription(__out_ecount(count) char16 *const description, const size_t count, bool AsmDumpMode,
  3248. bool printToConsole, Func *func)
  3249. {
  3250. char16 *buffer = description;
  3251. size_t n = count;
  3252. IR::AddrOpnd * addrOpnd = this->AsAddrOpnd();
  3253. Js::Var address;
  3254. bool isEncoded = false;
  3255. if (addrOpnd->decodedValue != 0)
  3256. {
  3257. address = addrOpnd->decodedValue;
  3258. isEncoded = true;
  3259. }
  3260. else
  3261. {
  3262. address = addrOpnd->m_address;
  3263. }
  3264. GetAddrDescription(description, count, address, addrOpnd->GetAddrOpndKind(), AsmDumpMode, printToConsole, func);
  3265. if (isEncoded)
  3266. {
  3267. if (AsmDumpMode)
  3268. {
  3269. WriteToBuffer(&buffer, &n, _u(" [encoded]"));
  3270. }
  3271. else
  3272. {
  3273. WriteToBuffer(&buffer, &n, _u(" [encoded: 0x%08X"), addrOpnd->m_address);
  3274. }
  3275. }
  3276. description[count-1] = 0; // force null termination
  3277. }
  3278. void
  3279. Opnd::Dump()
  3280. {
  3281. this->Dump(IRDumpFlags_None, nullptr);
  3282. }
  3283. #endif
  3284. } // namespace IR