IR.inl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  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. #pragma once
  6. namespace IR {
  7. inline IRKind
  8. Instr::GetKind() const
  9. {
  10. return this->m_kind;
  11. }
  12. ///----------------------------------------------------------------------------
  13. ///
  14. /// Instr::IsEntryInstr
  15. ///
  16. ///----------------------------------------------------------------------------
  17. inline bool
  18. Instr::IsEntryInstr() const
  19. {
  20. return this->GetKind() == InstrKindEntry;
  21. }
  22. ///----------------------------------------------------------------------------
  23. ///
  24. /// Instr::AsEntryInstr
  25. ///
  26. /// Return this as a EntryInstr *
  27. ///
  28. ///----------------------------------------------------------------------------
  29. inline EntryInstr *
  30. Instr::AsEntryInstr()
  31. {
  32. AssertMsg(this->IsEntryInstr(), "Bad call to AsEntryInstr()");
  33. return reinterpret_cast<EntryInstr *>(this);
  34. }
  35. ///----------------------------------------------------------------------------
  36. ///
  37. /// Instr::IsExitInstr
  38. ///
  39. ///----------------------------------------------------------------------------
  40. inline bool
  41. Instr::IsExitInstr() const
  42. {
  43. return this->GetKind() == InstrKindExit;
  44. }
  45. ///----------------------------------------------------------------------------
  46. ///
  47. /// Instr::AsExitInstr
  48. ///
  49. /// Return this as a ExitInstr *
  50. ///
  51. ///----------------------------------------------------------------------------
  52. inline ExitInstr *
  53. Instr::AsExitInstr()
  54. {
  55. AssertMsg(this->IsExitInstr(), "Bad call to AsExitInstr()");
  56. return reinterpret_cast<ExitInstr *>(this);
  57. }
  58. ///----------------------------------------------------------------------------
  59. ///
  60. /// Instr::IsBranchInstr
  61. ///
  62. ///----------------------------------------------------------------------------
  63. inline bool
  64. Instr::IsBranchInstr() const
  65. {
  66. return this->GetKind() == InstrKindBranch;
  67. }
  68. ///----------------------------------------------------------------------------
  69. ///
  70. /// Instr::AsBranchInstr
  71. ///
  72. /// Return this as a BranchInstr *
  73. ///
  74. ///----------------------------------------------------------------------------
  75. inline BranchInstr *
  76. Instr::AsBranchInstr()
  77. {
  78. AssertMsg(this->IsBranchInstr(), "Bad call to AsBranchInstr()");
  79. return reinterpret_cast<BranchInstr *>(this);
  80. }
  81. ///----------------------------------------------------------------------------
  82. ///
  83. /// Instr::IsLabelInstr
  84. ///
  85. ///----------------------------------------------------------------------------
  86. __forceinline bool
  87. Instr::IsLabelInstr() const
  88. {
  89. return this->GetKind() == InstrKindLabel || this->IsProfiledLabelInstr();
  90. }
  91. ///----------------------------------------------------------------------------
  92. ///
  93. /// Instr::AsLabelInstr
  94. ///
  95. /// Return this as a LabelInstr *
  96. ///
  97. ///----------------------------------------------------------------------------
  98. inline LabelInstr *
  99. Instr::AsLabelInstr()
  100. {
  101. AssertMsg(this->IsLabelInstr(), "Bad call to AsLabelInstr()");
  102. return reinterpret_cast<LabelInstr *>(this);
  103. }
  104. ///----------------------------------------------------------------------------
  105. ///
  106. /// Instr::AsMultiBrInstr
  107. ///
  108. /// Return this as a MultiBrInstr *
  109. ///
  110. ///----------------------------------------------------------------------------
  111. inline MultiBranchInstr *
  112. BranchInstr::AsMultiBrInstr()
  113. {
  114. AssertMsg(this->IsMultiBranch(), "Bad call to AsMultiBrInstr()");
  115. return static_cast<MultiBranchInstr *>(this);
  116. }
  117. ///----------------------------------------------------------------------------
  118. ///
  119. /// Instr::IsPragmaInstr
  120. ///
  121. ///----------------------------------------------------------------------------
  122. inline bool
  123. Instr::IsPragmaInstr() const
  124. {
  125. return this->GetKind() == InstrKindPragma;
  126. }
  127. inline PragmaInstr *
  128. Instr::AsPragmaInstr()
  129. {
  130. AssertMsg(this->IsPragmaInstr(), "Bad call to AsPragmaInstr()");
  131. return reinterpret_cast<PragmaInstr *>(this);
  132. }
  133. inline bool
  134. Instr::IsJitProfilingInstr() const
  135. {
  136. return this->GetKind() == InstrKindJitProfiling;
  137. }
  138. inline JitProfilingInstr *
  139. Instr::AsJitProfilingInstr()
  140. {
  141. AssertMsg(this->IsJitProfilingInstr(), "Bad call to AsProfiledInstr()");
  142. return reinterpret_cast<JitProfilingInstr *>(this);
  143. }
  144. inline bool
  145. Instr::IsProfiledInstr() const
  146. {
  147. return this->GetKind() == InstrKindProfiled;
  148. }
  149. inline ProfiledInstr *
  150. Instr::AsProfiledInstr()
  151. {
  152. AssertMsg(this->IsProfiledInstr(), "Bad call to AsProfiledInstr()");
  153. return reinterpret_cast<ProfiledInstr *>(this);
  154. }
  155. inline bool
  156. Instr::IsProfiledLabelInstr() const
  157. {
  158. return this->GetKind() == InstrKindProfiledLabel;
  159. }
  160. inline ProfiledLabelInstr *
  161. Instr::AsProfiledLabelInstr()
  162. {
  163. AssertMsg(this->IsProfiledLabelInstr(), "Bad call to AsProfiledlLabelInstr()");
  164. return reinterpret_cast<ProfiledLabelInstr *>(this);
  165. }
  166. inline bool
  167. Instr::IsByteCodeUsesInstr() const
  168. {
  169. return GetKind() == IR::InstrKindByteCodeUses;
  170. }
  171. inline ByteCodeUsesInstr *
  172. Instr::AsByteCodeUsesInstr()
  173. {
  174. AssertMsg(this->IsByteCodeUsesInstr(), "Bad call to AsByteCodeUsesInstr()");
  175. return (ByteCodeUsesInstr *)this;
  176. }
  177. ///----------------------------------------------------------------------------
  178. ///
  179. /// Instr::IsLowered
  180. ///
  181. /// Is this instr lowered to machine dependent opcode?
  182. ///
  183. ///----------------------------------------------------------------------------
  184. inline bool
  185. Instr::IsLowered() const
  186. {
  187. return m_opcode > Js::OpCode::MDStart;
  188. }
  189. ///----------------------------------------------------------------------------
  190. ///
  191. /// Instr::StartsBasicBlock
  192. ///
  193. /// Does this instruction mark the beginning of a basic block?
  194. ///
  195. ///----------------------------------------------------------------------------
  196. inline bool
  197. Instr::StartsBasicBlock() const
  198. {
  199. return this->IsLabelInstr() || this->IsEntryInstr();
  200. }
  201. ///----------------------------------------------------------------------------
  202. ///
  203. /// Instr::EndsBasicBlock
  204. ///
  205. /// Does this instruction mark the end of a basic block?
  206. ///
  207. ///----------------------------------------------------------------------------
  208. inline bool
  209. Instr::EndsBasicBlock() const
  210. {
  211. return
  212. this->IsBranchInstr() ||
  213. this->IsExitInstr() ||
  214. this->m_opcode == Js::OpCode::Ret ||
  215. this->m_opcode == Js::OpCode::Throw ||
  216. this->m_opcode == Js::OpCode::RuntimeTypeError ||
  217. this->m_opcode == Js::OpCode::RuntimeReferenceError;
  218. }
  219. ///----------------------------------------------------------------------------
  220. ///
  221. /// Instr::HasFallThrough
  222. ///
  223. /// Can execution fall through to the next instruction?
  224. ///
  225. ///----------------------------------------------------------------------------
  226. inline bool
  227. Instr::HasFallThrough() const
  228. {
  229. return (!(this->IsBranchInstr() && const_cast<Instr*>(this)->AsBranchInstr()->IsUnconditional())
  230. && OpCodeAttr::HasFallThrough(this->m_opcode));
  231. }
  232. inline bool
  233. Instr::IsNewScObjectInstr() const
  234. {
  235. return this->m_opcode == Js::OpCode::NewScObject || this->m_opcode == Js::OpCode::NewScObjectNoCtor;
  236. }
  237. inline bool
  238. Instr::IsInvalidInstr() const
  239. {
  240. return this == (Instr*)InvalidInstrLayout;
  241. }
  242. inline Instr*
  243. Instr::GetInvalidInstr()
  244. {
  245. return (Instr*)InvalidInstrLayout;
  246. }
  247. ///----------------------------------------------------------------------------
  248. ///
  249. /// Instr::GetDst
  250. ///
  251. ///----------------------------------------------------------------------------
  252. inline Opnd *
  253. Instr::GetDst() const
  254. {
  255. return this->m_dst;
  256. }
  257. ///----------------------------------------------------------------------------
  258. ///
  259. /// Instr::GetSrc1
  260. ///
  261. ///----------------------------------------------------------------------------
  262. inline Opnd *
  263. Instr::GetSrc1() const
  264. {
  265. return this->m_src1;
  266. }
  267. ///----------------------------------------------------------------------------
  268. ///
  269. /// Instr::SetSrc1
  270. ///
  271. /// Makes a copy if opnd is in use...
  272. ///
  273. ///----------------------------------------------------------------------------
  274. inline Opnd *
  275. Instr::SetSrc1(Opnd * newSrc)
  276. {
  277. AssertMsg(this->m_src1 == NULL, "Trying to overwrite existing src.");
  278. newSrc = newSrc->Use(m_func);
  279. this->m_src1 = newSrc;
  280. return newSrc;
  281. }
  282. ///----------------------------------------------------------------------------
  283. ///
  284. /// Instr::GetSrc2
  285. ///
  286. ///----------------------------------------------------------------------------
  287. inline Opnd *
  288. Instr::GetSrc2() const
  289. {
  290. return this->m_src2;
  291. }
  292. ///----------------------------------------------------------------------------
  293. ///
  294. /// Instr::SetSrc2
  295. ///
  296. /// Makes a copy if opnd is in use...
  297. ///
  298. ///----------------------------------------------------------------------------
  299. inline Opnd *
  300. Instr::SetSrc2(Opnd * newSrc)
  301. {
  302. AssertMsg(this->m_src2 == NULL, "Trying to overwrite existing src.");
  303. newSrc = newSrc->Use(m_func);
  304. this->m_src2 = newSrc;
  305. return newSrc;
  306. }
  307. // IsInlined - true if the function that contains the instr has been inlined
  308. inline bool
  309. Instr::IsInlined() const
  310. {
  311. return this->m_func->IsInlined();
  312. }
  313. ///----------------------------------------------------------------------------
  314. ///
  315. /// Instr::ForEachCallDirectArgOutInstrBackward
  316. ///
  317. /// Walks the ArgsOut of CallDirect backwards
  318. ///
  319. ///----------------------------------------------------------------------------
  320. template <typename Fn>
  321. inline bool
  322. Instr::ForEachCallDirectArgOutInstrBackward(Fn fn, uint argsOpndLength) const
  323. {
  324. Assert(this->m_opcode == Js::OpCode::CallDirect); // Right now we call this method only for partial inlining of split, match and exec. Can be modified for other uses also.
  325. // CallDirect src2
  326. IR::Opnd * linkOpnd = this->GetSrc2();
  327. // ArgOut_A_InlineSpecialized
  328. IR::Instr * tmpInstr = linkOpnd->AsSymOpnd()->m_sym->AsStackSym()->m_instrDef;
  329. Assert(tmpInstr->m_opcode == Js::OpCode::ArgOut_A_InlineSpecialized);
  330. // ArgOut_A_InlineSpecialized src2; link to actual argouts.
  331. linkOpnd = tmpInstr->GetSrc2();
  332. uint32 argCount = linkOpnd->AsSymOpnd()->m_sym->AsStackSym()->GetArgSlotNum();
  333. if (argCount != argsOpndLength)
  334. {
  335. return false;
  336. }
  337. while (linkOpnd->IsSymOpnd() && argCount > 0)
  338. {
  339. IR::SymOpnd *src2 = linkOpnd->AsSymOpnd();
  340. StackSym *sym = src2->m_sym->AsStackSym();
  341. Assert(sym->m_isSingleDef);
  342. IR::Instr *argInstr = sym->m_instrDef;
  343. Assert(argInstr->m_opcode == Js::OpCode::ArgOut_A);
  344. if (fn(argInstr, argCount - 1))
  345. {
  346. return true;
  347. }
  348. argCount--;
  349. linkOpnd = argInstr->GetSrc2();
  350. }
  351. return false;
  352. }
  353. ///----------------------------------------------------------------------------
  354. ///
  355. /// BranchInstr::SetTarget
  356. ///
  357. ///----------------------------------------------------------------------------
  358. inline void
  359. BranchInstr::SetTarget(LabelInstr * labelInstr)
  360. {
  361. Assert(!this->m_isMultiBranch);
  362. if (this->m_branchTarget)
  363. {
  364. this->m_branchTarget->RemoveLabelRef(this);
  365. }
  366. if (labelInstr)
  367. {
  368. labelInstr->AddLabelRef(this);
  369. }
  370. this->m_branchTarget = labelInstr;
  371. }
  372. inline void
  373. BranchInstr::ClearTarget()
  374. {
  375. if (this->IsMultiBranch())
  376. {
  377. this->AsMultiBrInstr()->ClearTarget();
  378. }
  379. else
  380. {
  381. this->SetTarget(nullptr);
  382. }
  383. }
  384. ///----------------------------------------------------------------------------
  385. ///
  386. /// BranchInstr::GetTarget
  387. ///
  388. ///----------------------------------------------------------------------------
  389. inline LabelInstr *
  390. BranchInstr::GetTarget() const
  391. {
  392. return this->m_branchTarget;
  393. }
  394. ///----------------------------------------------------------------------------
  395. ///
  396. /// BranchInstr::IsConditional
  397. ///
  398. ///----------------------------------------------------------------------------
  399. inline bool
  400. BranchInstr::IsConditional() const
  401. {
  402. return !this->IsUnconditional();
  403. }
  404. inline bool
  405. BranchInstr::IsMultiBranch() const
  406. {
  407. if (m_branchTarget)
  408. {
  409. Assert(!m_isMultiBranch);
  410. return false;
  411. }
  412. else
  413. {
  414. Assert(m_isMultiBranch);
  415. return true; // it's a multi branch instr
  416. }
  417. }
  418. ///----------------------------------------------------------------------------
  419. ///
  420. /// BranchInstr::IsUnconditional
  421. ///
  422. ///----------------------------------------------------------------------------
  423. inline bool
  424. BranchInstr::IsUnconditional() const
  425. {
  426. if (this->IsLowered())
  427. {
  428. return LowererMD::IsUnconditionalBranch(this);
  429. }
  430. else
  431. {
  432. return (this->m_opcode == Js::OpCode::Br || this->m_opcode == Js::OpCode::MultiBr);
  433. }
  434. }
  435. ///----------------------------------------------------------------------------
  436. ///
  437. /// MultiBranchInstr::AddtoDictionary
  438. /// - Adds the string to the list with the targetoffset
  439. /// In order for the dictionary to have the right value, MapBranchTargetAddress
  440. /// needs to be called to populate the dictionary and then it'll be patched up
  441. /// to the right values
  442. ///
  443. ///----------------------------------------------------------------------------
  444. inline void
  445. MultiBranchInstr::AddtoDictionary(uint32 offset, TBranchKey key)
  446. {
  447. Assert(this->m_kind == StrDictionary);
  448. Assert(key);
  449. this->GetBranchDictionary()->dictionary.AddNew(key, (void*)offset);
  450. }
  451. inline void
  452. MultiBranchInstr::AddtoJumpTable(uint32 offset, uint32 jmpIndex)
  453. {
  454. Assert(this->m_kind == IntJumpTable || this->m_kind == SingleCharStrJumpTable);
  455. Assert(jmpIndex != -1);
  456. this->GetBranchJumpTable()->jmpTable[jmpIndex] = (void*)offset;
  457. }
  458. inline void
  459. MultiBranchInstr::FixMultiBrDefaultTarget(uint32 targetOffset)
  460. {
  461. this->GetBranchJumpTable()->defaultTarget = (void *)targetOffset;
  462. }
  463. inline void
  464. MultiBranchInstr::CreateBranchTargetsAndSetDefaultTarget(int size, Kind kind, uint defaultTargetOffset)
  465. {
  466. AssertMsg(size != 0, "The dictionary/jumpTable size should not be zero");
  467. NativeCodeData::Allocator * allocator = this->m_func->GetNativeCodeDataAllocator();
  468. m_kind = kind;
  469. switch (kind)
  470. {
  471. case IntJumpTable:
  472. case SingleCharStrJumpTable:
  473. {
  474. JitArenaAllocator * jitAllocator = this->m_func->GetTopFunc()->m_alloc;
  475. BranchJumpTableWrapper * branchTargets = BranchJumpTableWrapper::New(jitAllocator, size);
  476. branchTargets->defaultTarget = (void *)defaultTargetOffset;
  477. this->m_branchTargets = branchTargets;
  478. break;
  479. }
  480. case StrDictionary:
  481. {
  482. BranchDictionaryWrapper * branchTargets = BranchDictionaryWrapper::New(allocator, size);
  483. branchTargets->defaultTarget = (void *)defaultTargetOffset;
  484. this->m_branchTargets = branchTargets;
  485. break;
  486. }
  487. default:
  488. Assert(false);
  489. };
  490. }
  491. inline MultiBranchInstr::BranchDictionaryWrapper *
  492. MultiBranchInstr::GetBranchDictionary()
  493. {
  494. return reinterpret_cast<MultiBranchInstr::BranchDictionaryWrapper *>(m_branchTargets);
  495. }
  496. inline MultiBranchInstr::BranchJumpTable *
  497. MultiBranchInstr::GetBranchJumpTable()
  498. {
  499. return reinterpret_cast<MultiBranchInstr::BranchJumpTable *>(m_branchTargets);
  500. }
  501. inline void
  502. MultiBranchInstr::ChangeLabelRef(LabelInstr * oldTarget, LabelInstr * newTarget)
  503. {
  504. if (oldTarget)
  505. {
  506. oldTarget->RemoveLabelRef(this);
  507. }
  508. if (newTarget)
  509. {
  510. newTarget->AddLabelRef(this);
  511. }
  512. }
  513. ///----------------------------------------------------------------------------
  514. ///
  515. /// LabelInstr::SetPC
  516. ///
  517. ///----------------------------------------------------------------------------
  518. inline void
  519. LabelInstr::SetPC(BYTE * pc)
  520. {
  521. this->m_pc.pc = pc;
  522. }
  523. ///----------------------------------------------------------------------------
  524. ///
  525. /// LabelInstr::GetPC
  526. ///
  527. ///----------------------------------------------------------------------------
  528. inline BYTE *
  529. LabelInstr::GetPC(void) const
  530. {
  531. return this->m_pc.pc;
  532. }
  533. ///----------------------------------------------------------------------------
  534. ///
  535. /// LabelInstr::ResetOffset
  536. ///
  537. ///----------------------------------------------------------------------------
  538. inline void
  539. LabelInstr::ResetOffset(uint32 offset)
  540. {
  541. AssertMsg(this->isInlineeEntryInstr, "As of now only InlineeEntryInstr overwrites the offset at encoder stage");
  542. this->m_pc.offset = offset;
  543. }
  544. ///----------------------------------------------------------------------------
  545. ///
  546. /// LabelInstr::SetOffset
  547. ///
  548. ///----------------------------------------------------------------------------
  549. inline void
  550. LabelInstr::SetOffset(uint32 offset)
  551. {
  552. AssertMsg(this->m_pc.offset == 0, "Overwriting existing byte offset");
  553. this->m_pc.offset = offset;
  554. }
  555. ///----------------------------------------------------------------------------
  556. ///
  557. /// LabelInstr::GetOffset
  558. ///
  559. ///----------------------------------------------------------------------------
  560. inline uint32
  561. LabelInstr::GetOffset(void) const
  562. {
  563. return this->m_pc.offset;
  564. }
  565. ///----------------------------------------------------------------------------
  566. ///
  567. /// LabelInstr::SetBasicBlock
  568. ///
  569. ///----------------------------------------------------------------------------
  570. inline void
  571. LabelInstr::SetBasicBlock(BasicBlock * block)
  572. {
  573. AssertMsg(this->m_block == nullptr || block == nullptr, "Overwriting existing block pointer");
  574. this->m_block = block;
  575. }
  576. ///----------------------------------------------------------------------------
  577. ///
  578. /// LabelInstr::GetBasicBlock
  579. ///
  580. ///----------------------------------------------------------------------------
  581. inline BasicBlock *
  582. LabelInstr::GetBasicBlock(void) const
  583. {
  584. return this->m_block;
  585. }
  586. inline void
  587. LabelInstr::SetLoop(Loop* loop)
  588. {
  589. Assert(this->m_isLoopTop);
  590. this->m_loop = loop;
  591. }
  592. inline Loop*
  593. LabelInstr::GetLoop(void) const
  594. {
  595. Assert(this->m_isLoopTop);
  596. return this->m_loop;
  597. }
  598. ///----------------------------------------------------------------------------
  599. ///
  600. /// LabelInstr::UnlinkBasicBlock
  601. ///
  602. ///----------------------------------------------------------------------------
  603. inline void
  604. LabelInstr::UnlinkBasicBlock(void)
  605. {
  606. this->m_block = nullptr;
  607. }
  608. inline BOOL
  609. LabelInstr::IsUnreferenced(void) const
  610. {
  611. return labelRefs.Empty() && !m_hasNonBranchRef;
  612. }
  613. inline void
  614. LabelInstr::SetRegion(Region * region)
  615. {
  616. this->m_region = region;
  617. }
  618. inline Region *
  619. LabelInstr::GetRegion(void) const
  620. {
  621. return this->m_region;
  622. }
  623. } // namespace IR