IRBuilderAsmJs.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. 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. #ifdef ASMJS_PLAT
  7. namespace AsmJsRegSlots
  8. {
  9. enum ConstSlots
  10. {
  11. ReturnReg = 0,
  12. ModuleMemReg,
  13. ArrayReg,
  14. WasmMemoryReg,
  15. BufferReg,
  16. LengthReg,
  17. RegCount
  18. };
  19. };
  20. class IRBuilderAsmJs
  21. {
  22. friend struct IRBuilderAsmJsSwitchAdapter;
  23. public:
  24. IRBuilderAsmJs(Func * func)
  25. : m_func(func)
  26. , m_IsTJLoopBody(false)
  27. , m_switchAdapter(this)
  28. , m_switchBuilder(&m_switchAdapter)
  29. {
  30. func->m_workItem->InitializeReader(&m_jnReader, &m_statementReader, func->m_alloc);
  31. m_asmFuncInfo = m_func->GetJITFunctionBody()->GetAsmJsInfo();
  32. #if 0
  33. // templatized JIT loop body
  34. if (func->IsLoopBody())
  35. {
  36. Js::LoopEntryPointInfo* loopEntryPointInfo = (Js::LoopEntryPointInfo*)(func->m_workItem->GetEntryPoint());
  37. if (loopEntryPointInfo->GetIsTJMode())
  38. {
  39. m_IsTJLoopBody = true;
  40. func->isTJLoopBody = true;
  41. }
  42. }
  43. #endif
  44. }
  45. void Build();
  46. private:
  47. struct MemAccessTypeInfo
  48. {
  49. WAsmJs::Types valueRegType;
  50. IRType type;
  51. ValueType arrayType;
  52. };
  53. void LoadNativeCodeData();
  54. void AddInstr(IR::Instr * instr, uint32 offset);
  55. bool IsLoopBody()const;
  56. uint GetLoopBodyExitInstrOffset() const;
  57. IR::SymOpnd * BuildLoopBodySlotOpnd(SymID symId);
  58. IR::SymOpnd * BuildAsmJsLoopBodySlotOpnd(SymID symId, IRType opndType);
  59. void EnsureLoopBodyLoadSlot(SymID symId);
  60. void EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type);
  61. bool IsLoopBodyOuterOffset(uint offset) const;
  62. bool IsLoopBodyReturnIPInstr(IR::Instr * instr) const;
  63. IR::Opnd * InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset);
  64. IR::Instr * CreateLoopBodyReturnIPInstr(uint targetOffset, uint offset);
  65. IR::RegOpnd * BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type);
  66. IR::RegOpnd * BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type);
  67. IR::RegOpnd * BuildIntConstOpnd(Js::RegSlot regSlot);
  68. SymID BuildSrcStackSymID(Js::RegSlot regSlot, IRType type = IRType::TyVar);
  69. IR::SymOpnd * BuildFieldOpnd(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind, IRType type, bool scale = true);
  70. PropertySym * BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind);
  71. uint AddStatementBoundary(uint statementIndex, uint offset);
  72. BranchReloc * AddBranchInstr(IR::BranchInstr *instr, uint32 offset, uint32 targetOffset);
  73. BranchReloc * CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset);
  74. void BuildHeapBufferReload(uint32 offset);
  75. template<typename T, typename ConstOpnd, typename F>
  76. void CreateLoadConstInstrForType(byte* table, Js::RegSlot& regAllocated, uint32 constCount, uint32 offset, IRType irType, ValueType valueType, Js::OpCode opcode, F extraProcess);
  77. void BuildConstantLoads();
  78. void BuildImplicitArgIns();
  79. void InsertLabels();
  80. IR::LabelInstr * CreateLabel(IR::BranchInstr * branchInstr, uint& offset);
  81. #if DBG
  82. BVFixed * m_usedAsTemp;
  83. #endif
  84. Js::RegSlot GetTypedRegFromRegSlot(Js::RegSlot reg, WAsmJs::Types type);
  85. Js::RegSlot GetRegSlotFromTypedReg(Js::RegSlot srcReg, WAsmJs::Types type);
  86. Js::RegSlot GetRegSlotFromIntReg(Js::RegSlot srcIntReg) {return GetRegSlotFromTypedReg(srcIntReg, WAsmJs::INT32);}
  87. Js::RegSlot GetRegSlotFromInt64Reg(Js::RegSlot srcIntReg) {return GetRegSlotFromTypedReg(srcIntReg, WAsmJs::INT64);}
  88. Js::RegSlot GetRegSlotFromFloatReg(Js::RegSlot srcFloatReg) {return GetRegSlotFromTypedReg(srcFloatReg, WAsmJs::FLOAT32);}
  89. Js::RegSlot GetRegSlotFromDoubleReg(Js::RegSlot srcDoubleReg) {return GetRegSlotFromTypedReg(srcDoubleReg, WAsmJs::FLOAT64);}
  90. Js::RegSlot GetRegSlotFromSimd128Reg(Js::RegSlot srcSimd128Reg) {return GetRegSlotFromTypedReg(srcSimd128Reg, WAsmJs::SIMD);}
  91. Js::RegSlot GetRegSlotFromVarReg(Js::RegSlot srcVarReg);
  92. Js::OpCode GetSimdOpcode(Js::OpCodeAsmJs asmjsOpcode);
  93. void GetSimdTypesFromAsmType(Js::AsmJsType::Which asmType, IRType *pIRType, ValueType *pValueType = nullptr);
  94. IR::Instr * AddExtendedArg(IR::RegOpnd *src1, IR::RegOpnd *src2, uint32 offset);
  95. bool RegIsSimd128ReturnVar(Js::RegSlot reg);
  96. SymID GetMappedTemp(Js::RegSlot reg);
  97. void SetMappedTemp(Js::RegSlot reg, SymID tempId);
  98. BOOL GetTempUsed(Js::RegSlot reg);
  99. void SetTempUsed(Js::RegSlot reg, BOOL used);
  100. BOOL RegIsTemp(Js::RegSlot reg);
  101. BOOL RegIsConstant(Js::RegSlot reg);
  102. BOOL RegIsVar(Js::RegSlot reg);
  103. BOOL RegIsTypedVar(Js::RegSlot reg, WAsmJs::Types type);
  104. BOOL RegIsIntVar(Js::RegSlot reg) {return RegIsTypedVar(reg, WAsmJs::INT32);}
  105. BOOL RegIsInt64Var(Js::RegSlot reg) {return RegIsTypedVar(reg, WAsmJs::INT64);}
  106. BOOL RegIsFloatVar(Js::RegSlot reg) {return RegIsTypedVar(reg, WAsmJs::FLOAT32);}
  107. BOOL RegIsDoubleVar(Js::RegSlot reg) {return RegIsTypedVar(reg, WAsmJs::FLOAT64);}
  108. BOOL RegIsSimd128Var(Js::RegSlot reg) {return RegIsTypedVar(reg, WAsmJs::SIMD);}
  109. void BuildArgOut(IR::Opnd* srcOpnd, uint32 dstRegSlot, uint32 offset, IRType type, ValueType valueType = ValueType::Uninitialized);
  110. void BuildFromVar(uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, IRType irType, ValueType valueType);
  111. #define LAYOUT_TYPE(layout) \
  112. void Build##layout(Js::OpCodeAsmJs newOpcode, uint32 offset);
  113. #define LAYOUT_TYPE_WMS(layout) \
  114. template <typename SizePolicy> void Build##layout(Js::OpCodeAsmJs newOpcode, uint32 offset);
  115. #define EXCLUDE_FRONTEND_LAYOUT
  116. #include "ByteCode/LayoutTypesAsmJs.h"
  117. void BuildSimd_1Ints(Js::OpCodeAsmJs newOpcode, uint32 offset, IRType dstSimdType, Js::RegSlot* srcRegSlots, Js::RegSlot dstRegSlot, uint LANES);
  118. void BuildSimd_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType);
  119. void BuildSimd_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, Js::RegSlot src3RegSlot, IRType simdType);
  120. void BuildSimd_2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType);
  121. void BuildSimd_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType simdType);
  122. void BuildSimd_3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType simdType);
  123. void BuildSimd_3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType dstSimdType, IRType srcSimdType);
  124. void BuildSimdConversion(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, IRType dstSimdType, IRType srcSimdType);
  125. ValueType GetSimdValueTypeFromIRType(IRType type);
  126. void BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 slotIndex, Js::RegSlot value, Js::RegSlot instance);
  127. void BuildAsmUnsigned1(Js::OpCodeAsmJs newOpcode, uint value);
  128. void BuildWasmMemAccess(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, uint32 constOffset, Js::ArrayBufferView::ViewType viewType);
  129. void BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, Js::ArrayBufferView::ViewType viewType);
  130. void BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, Js::ArrayBufferView::ViewType viewType, uint8 DataWidth);
  131. void BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSlot argCount, Js::RegSlot ret, Js::RegSlot function, int8 returnType);
  132. void BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg);
  133. void BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src);
  134. void BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, Js::RegSlot src2);
  135. void BuildBrInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, int32 src2);
  136. void BuildBrCmp(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, IR::RegOpnd* src1Opnd, IR::Opnd* src2Opnd);
  137. void GenerateLoopBodySlotAccesses(uint offset);
  138. void GenerateLoopBodyStSlots(SymID loopParamSymId, uint offset);
  139. static void InitializeMemAccessTypeInfo(Js::ArrayBufferView::ViewType viewType, _Out_ MemAccessTypeInfo * typeInfo);
  140. Js::PropertyId CalculatePropertyOffset(SymID id, IRType type, bool isVar = true);
  141. IR::Instr* GenerateStSlotForReturn(IR::RegOpnd* srcOpnd, IRType type);
  142. IR::RegOpnd* BuildTrapIfZero(IR::RegOpnd* srcOpnd, uint32 offset);
  143. IR::RegOpnd* BuildTrapIfMinIntOverNegOne(IR::RegOpnd* src1Opnd, IR::RegOpnd* src2Opnd, uint32 offset);
  144. JitArenaAllocator * m_tempAlloc;
  145. JitArenaAllocator * m_funcAlloc;
  146. Func * m_func;
  147. IR::Instr * m_lastInstr;
  148. IR::Instr ** m_offsetToInstruction;
  149. Js::ByteCodeReader m_jnReader;
  150. Js::StatementReader<Js::FunctionBody::ArenaStatementMapList> m_statementReader;
  151. SList<IR::Instr *> * m_argStack;
  152. SList<IR::Instr *> * m_tempList;
  153. SList<int32> * m_argOffsetStack;
  154. SList<BranchReloc *> * m_branchRelocList;
  155. // 1 for const, 1 for var, 1 for temps for each type and 1 for last
  156. static const uint32 m_firstsTypeCount = WAsmJs::LIMIT * 3 + 1;
  157. Js::RegSlot m_firstsType[m_firstsTypeCount];
  158. Js::RegSlot m_firstVarConst;
  159. Js::RegSlot m_firstIRTemp;
  160. Js::RegSlot m_tempCount;
  161. Js::OpCode * m_simdOpcodesMap;
  162. Js::RegSlot GetFirstConst(WAsmJs::Types type) { return m_firstsType[type]; }
  163. Js::RegSlot GetFirstVar(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT]; }
  164. Js::RegSlot GetFirstTmp(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT * 2]; }
  165. Js::RegSlot GetLastConst(WAsmJs::Types type) { return m_firstsType[type + 1]; }
  166. Js::RegSlot GetLastVar(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT + 1]; }
  167. Js::RegSlot GetLastTmp(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT * 2 + 1]; }
  168. SymID * m_tempMap;
  169. BVFixed * m_fbvTempUsed;
  170. uint32 m_functionStartOffset;
  171. const AsmJsJITInfo * m_asmFuncInfo;
  172. StackSym * m_loopBodyRetIPSym;
  173. BVFixed * m_ldSlots;
  174. BVFixed * m_stSlots;
  175. BOOL m_IsTJLoopBody;
  176. IRBuilderAsmJsSwitchAdapter m_switchAdapter;
  177. SwitchIRBuilder m_switchBuilder;
  178. IR::RegOpnd * m_funcOpnd;
  179. #if DBG
  180. uint32 m_offsetToInstructionCount;
  181. #endif
  182. #define BUILD_LAYOUT_DEF(layout, ...) void Build##layout (Js::OpCodeAsmJs, uint32, __VA_ARGS__);
  183. #define Reg_Type Js::RegSlot
  184. #define Int_Type Js::RegSlot
  185. #define Long_Type Js::RegSlot
  186. #define Float_Type Js::RegSlot
  187. #define Double_Type Js::RegSlot
  188. #define IntConst_Type int
  189. #define LongConst_Type int64
  190. #define FloatConst_Type float
  191. #define DoubleConst_Type double
  192. #define Float32x4_Type Js::RegSlot
  193. #define Bool32x4_Type Js::RegSlot
  194. #define Int32x4_Type Js::RegSlot
  195. #define Float64x2_Type Js::RegSlot
  196. #define Int16x8_Type Js::RegSlot
  197. #define Bool16x8_Type Js::RegSlot
  198. #define Int8x16_Type Js::RegSlot
  199. #define Bool8x16_Type Js::RegSlot
  200. #define Uint32x4_Type Js::RegSlot
  201. #define Uint16x8_Type Js::RegSlot
  202. #define Uint8x16_Type Js::RegSlot
  203. #define LAYOUT_TYPE_WMS_REG2(layout, t0, t1) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type)
  204. #define LAYOUT_TYPE_WMS_REG3(layout, t0, t1, t2) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type)
  205. #define LAYOUT_TYPE_WMS_REG4(layout, t0, t1, t2, t3) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type)
  206. #define LAYOUT_TYPE_WMS_REG5(layout, t0, t1, t2, t3, t4) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type)
  207. #define LAYOUT_TYPE_WMS_REG6(layout, t0, t1, t2, t3, t4, t5) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type)
  208. #define LAYOUT_TYPE_WMS_REG7(layout, t0, t1, t2, t3, t4, t5, t6) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type)
  209. #define LAYOUT_TYPE_WMS_REG9(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type)
  210. #define LAYOUT_TYPE_WMS_REG10(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type)
  211. #define LAYOUT_TYPE_WMS_REG11(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type)
  212. #define LAYOUT_TYPE_WMS_REG17(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type, t11##_Type, t12##_Type, t13##_Type, t14##_Type, t15##_Type, t16##_Type)
  213. #define LAYOUT_TYPE_WMS_REG18(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type, t11##_Type, t12##_Type, t13##_Type, t14##_Type, t15##_Type, t16##_Type, t17##_Type)
  214. #define LAYOUT_TYPE_WMS_REG19(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type, t11##_Type, t12##_Type, t13##_Type, t14##_Type, t15##_Type, t16##_Type, t17##_Type, t18##_Type)
  215. #define EXCLUDE_FRONTEND_LAYOUT
  216. #include "LayoutTypesAsmJs.h"
  217. #undef BUILD_LAYOUT_DEF
  218. #undef RegType
  219. #undef IntType
  220. #undef LongType
  221. #undef FloatType
  222. #undef DoubleType
  223. #undef IntConstType
  224. #undef LongConstType
  225. #undef FloatConstType
  226. #undef DoubleConstType
  227. #undef Float32x4Type
  228. #undef Bool32x4Type
  229. #undef Int32x4Type
  230. #undef Float64x2Type
  231. #undef Int16x8Type
  232. #undef Bool16x8Type
  233. #undef Int8x16Type
  234. #undef Bool8x16Type
  235. #undef Uint32x4Type
  236. #undef Uint16x8Type
  237. #undef Uint8x16Type
  238. };
  239. #endif