EncoderMD.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. class Encoder;
  6. enum RelocType {
  7. RelocTypeBranch, // cond, uncond branch
  8. RelocTypeCallPcrel, // calls
  9. RelocTypeLabelUse, // direct use of a label
  10. RelocTypeLabel, // points to label instr
  11. RelocTypeAlignedLabel, // points to loop-top label instr that needs alignment
  12. RelocTypeInlineeEntryOffset, // points to offset immediate in buffer
  13. };
  14. ///---------------------------------------------------------------------------
  15. ///
  16. /// class EncoderReloc
  17. ///
  18. ///---------------------------------------------------------------------------
  19. class EncodeRelocAndLabels
  20. {
  21. public:
  22. RelocType m_type;
  23. void * m_ptr; // points to encoded buffer byte or LabelInstr if RelocTypeLabel
  24. void * m_origPtr; // copy of m_ptr to be used to get offset in the source buffer during BR shortening
  25. private:
  26. union
  27. {
  28. IR::LabelInstr* m_labelInstr; // ptr to Br Label
  29. BYTE m_nopCount;
  30. uint64 m_InlineeOffset;
  31. };
  32. bool m_isShortBr;
  33. public:
  34. void init(RelocType type, void* ptr, IR::LabelInstr* labelInstr = nullptr)
  35. {
  36. m_type = type;
  37. m_ptr = ptr;
  38. m_InlineeOffset = 0;
  39. m_isShortBr = false;
  40. if (type == RelocTypeLabel)
  41. {
  42. // preserve original PC for labels
  43. m_origPtr = (void*)((IR::LabelInstr*)ptr)->GetPC();
  44. m_nopCount = 0;
  45. }
  46. else
  47. {
  48. m_origPtr = ptr;
  49. if (type == RelocTypeBranch)
  50. {
  51. Assert(labelInstr);
  52. m_labelInstr = labelInstr;
  53. m_isShortBr = false;
  54. }
  55. else if (type == RelocTypeLabelUse)
  56. {
  57. Assert(labelInstr);
  58. m_labelInstr = labelInstr;
  59. }
  60. }
  61. }
  62. void revert()
  63. {
  64. // recover old label PC
  65. if (isLabel())
  66. {
  67. // recover old label PC and reset alignment nops
  68. // we keep aligned labels type so we align them on the second attempt.
  69. setLabelCurrPC(getLabelOrigPC());
  70. m_nopCount = 0;
  71. return;
  72. }
  73. if (m_type == RelocTypeBranch)
  74. {
  75. m_isShortBr = false;
  76. }
  77. m_ptr = m_origPtr;
  78. }
  79. bool isLabel() const { return isAlignedLabel() || m_type == RelocTypeLabel; }
  80. bool isAlignedLabel() const { return m_type == RelocTypeAlignedLabel; }
  81. bool isLongBr() const { return m_type == RelocTypeBranch && !m_isShortBr; }
  82. bool isShortBr() const { return m_type == RelocTypeBranch && m_isShortBr; }
  83. BYTE* getBrOpCodeByte() const { return (BYTE*)m_origPtr - 1;}
  84. IR::LabelInstr * getBrTargetLabel() const
  85. {
  86. Assert((m_type == RelocTypeBranch || m_type == RelocTypeLabelUse) && m_labelInstr);
  87. return m_labelInstr;
  88. }
  89. IR::LabelInstr * getLabel() const
  90. {
  91. Assert(isLabel());
  92. return (IR::LabelInstr*) m_ptr;
  93. }
  94. // get label original PC without shortening/alignment
  95. BYTE * getLabelOrigPC() const
  96. {
  97. Assert(isLabel());
  98. return ((BYTE*) m_origPtr);
  99. }
  100. // get label PC after shortening/alignment
  101. BYTE * getLabelCurrPC() const
  102. {
  103. Assert(isLabel());
  104. return getLabel()->GetPC();
  105. }
  106. BYTE getLabelNopCount() const
  107. {
  108. Assert(isAlignedLabel());
  109. return m_nopCount;
  110. }
  111. void setLabelCurrPC(BYTE* pc)
  112. {
  113. Assert(isLabel());
  114. getLabel()->SetPC(pc);
  115. }
  116. void setLabelNopCount(BYTE nopCount)
  117. {
  118. Assert(isAlignedLabel());
  119. Assert (nopCount >= 0 && nopCount < 16);
  120. m_nopCount = nopCount;
  121. }
  122. void setAsShortBr()
  123. {
  124. Assert(m_type == RelocTypeBranch);
  125. m_isShortBr = true;
  126. }
  127. // Validates if the branch is short and its target PC fits in one byte
  128. bool validateShortBrTarget() const
  129. {
  130. return isShortBr() &&
  131. getBrTargetLabel()->GetPC() - ((BYTE*)m_ptr + 1) >= -128 &&
  132. getBrTargetLabel()->GetPC() - ((BYTE*)m_ptr + 1) <= 127;
  133. }
  134. uint64 GetInlineOffset()
  135. {
  136. return m_InlineeOffset;
  137. }
  138. void SetInlineOffset(uint64 offset)
  139. {
  140. m_InlineeOffset = offset;
  141. }
  142. };
  143. ///---------------------------------------------------------------------------
  144. ///
  145. /// class EncoderMD
  146. ///
  147. ///---------------------------------------------------------------------------
  148. enum Forms : BYTE;
  149. typedef JsUtil::List<EncodeRelocAndLabels, ArenaAllocator> RelocList;
  150. typedef JsUtil::List<InlineeFrameRecord*, ArenaAllocator> InlineeFrameRecords;
  151. class EncoderMD
  152. {
  153. public:
  154. EncoderMD(Func * func) : m_func(func) {}
  155. ptrdiff_t Encode(IR::Instr * instr, BYTE *pc, BYTE* beginCodeAddress = nullptr);
  156. void Init(Encoder *encoder);
  157. void ApplyRelocs(size_t codeBufferAddress, size_t codeSize, uint* bufferCRC, BOOL isBrShorteningSucceeded, bool isFinalBufferValidation = false);
  158. uint GetRelocDataSize(EncodeRelocAndLabels *reloc);
  159. BYTE * GetRelocBufferAddress(EncodeRelocAndLabels * reloc);
  160. void EncodeInlineeCallInfo(IR::Instr *instr, uint32 offset);
  161. static bool TryConstFold(IR::Instr *instr, IR::RegOpnd *regOpnd);
  162. static bool TryFold(IR::Instr *instr, IR::RegOpnd *regOpnd);
  163. static bool SetsConditionCode(IR::Instr *instr);
  164. static bool UsesConditionCode(IR::Instr *instr);
  165. static bool IsOPEQ(IR::Instr *instr);
  166. static bool IsSHIFT(IR::Instr *instr);
  167. static bool IsMOVEncoding(IR::Instr *instr);
  168. RelocList* GetRelocList() const { return m_relocList; }
  169. int AppendRelocEntry(RelocType type, void *ptr, IR::LabelInstr *label= nullptr);
  170. int FixRelocListEntry(uint32 index, int totalBytesSaved, BYTE *buffStart, BYTE* buffEnd);
  171. void FixMaps(uint32 brOffset, uint32 bytesSaved, uint32 *inlineeFrameRecordsIndex, uint32 *inlineeFrameMapIndex, uint32 *pragmaInstToRecordOffsetIndex, uint32 *offsetBuffIndex);
  172. void UpdateRelocListWithNewBuffer(RelocList * relocList, BYTE * newBuffer, BYTE * oldBufferStart, BYTE * oldBufferEnd);
  173. #ifdef DBG
  174. void VerifyRelocList(BYTE *buffStart, BYTE *buffEnd);
  175. #endif
  176. void AddLabelReloc(BYTE* relocAddress);
  177. private:
  178. const BYTE GetOpcodeByte2(IR::Instr *instr);
  179. static Forms GetInstrForm(IR::Instr *instr);
  180. const BYTE * GetFormTemplate(IR::Instr *instr);
  181. const BYTE * GetOpbyte(IR::Instr *instr);
  182. const BYTE GetRegEncode(IR::RegOpnd *regOpnd);
  183. const BYTE GetRegEncode(RegNum reg);
  184. static const uint32 GetOpdope(IR::Instr *instr);
  185. const uint32 GetLeadIn(IR::Instr * instr);
  186. BYTE EmitModRM(IR::Instr * instr, IR::Opnd *opnd, BYTE reg1);
  187. void EmitConst(size_t val, int size, bool allowImm64 = false);
  188. BYTE EmitImmed(IR::Opnd * opnd, int opSize, int sbit, bool allowImm64 = false);
  189. static bool FitsInByte(size_t value);
  190. bool IsExtendedRegister(RegNum reg);
  191. BYTE GetMod(IR::IndirOpnd * opr, int* pDispSize);
  192. BYTE GetMod(IR::SymOpnd * opr, int* pDispSize, RegNum& rmReg);
  193. BYTE GetMod(size_t offset, bool regIsRbpOrR13, int * pDispSize);
  194. BYTE GetRexByte(BYTE rexCode, IR::Opnd * opnd);
  195. BYTE GetRexByte(BYTE rexCode, RegNum reg);
  196. int GetOpndSize(IR::Opnd * opnd);
  197. void EmitRexByte(BYTE * prexByte, BYTE rexByte, bool skipRexByte, bool reservedRexByte);
  198. enum
  199. {
  200. REXOVERRIDE = 0x40,
  201. REXW = 8,
  202. REXR = 4,
  203. REXX = 2,
  204. REXB = 1,
  205. };
  206. static const BYTE Mod00 = 0x00 << 6;
  207. static const BYTE Mod01 = 0x01 << 6;
  208. static const BYTE Mod10 = 0x02 << 6;
  209. static const BYTE Mod11 = 0x03 << 6;
  210. private:
  211. Func * m_func;
  212. Encoder * m_encoder;
  213. BYTE * m_pc;
  214. RelocList * m_relocList;
  215. int m_lastLoopLabelPosition;
  216. };