Opnd.cpp 102 KB

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