WasmByteCodeGenerator.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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 Wasm
  7. {
  8. struct EmitInfo : WAsmJs::EmitInfoBase
  9. {
  10. EmitInfo(Js::RegSlot location_, const WasmTypes::WasmType& type_) :
  11. WAsmJs::EmitInfoBase(location_), type(type_)
  12. {
  13. }
  14. EmitInfo(const WasmTypes::WasmType& type_) : type(type_) {}
  15. EmitInfo() : type(WasmTypes::Void) {}
  16. WasmTypes::WasmType type;
  17. };
  18. typedef WAsmJs::RegisterSpace WasmRegisterSpace;
  19. struct WasmLocal
  20. {
  21. WasmLocal() :
  22. location(Js::Constants::NoRegister), type(WasmTypes::Limit)
  23. {
  24. }
  25. WasmLocal(Js::RegSlot loc, WasmTypes::WasmType tp) :
  26. location(loc), type(tp)
  27. {
  28. }
  29. Js::RegSlot location;
  30. WasmTypes::WasmType type;
  31. };
  32. class WasmToAsmJs
  33. {
  34. public:
  35. static Js::AsmJsRetType GetAsmJsReturnType(WasmTypes::WasmType wasmType);
  36. static Js::AsmJsVarType GetAsmJsVarType(WasmTypes::WasmType wasmType);
  37. };
  38. class WasmCompilationException
  39. {
  40. void FormatError(const char16* _msg, va_list arglist);
  41. char16* errorMsg;
  42. public:
  43. WasmCompilationException(const char16* _msg, ...);
  44. WasmCompilationException(const char16* _msg, va_list arglist);
  45. char16* ReleaseErrorMessage()
  46. {
  47. Assert(errorMsg);
  48. char16* msg = errorMsg;
  49. errorMsg = nullptr;
  50. return msg;
  51. };
  52. };
  53. struct BlockInfo
  54. {
  55. struct YieldInfo
  56. {
  57. EmitInfo info;
  58. bool didYield = false;
  59. } *yieldInfo = nullptr;
  60. Js::ByteCodeLabel label;
  61. bool DidYield() const { return HasYield() && yieldInfo->didYield; }
  62. bool HasYield() const { return yieldInfo != nullptr; }
  63. };
  64. typedef JsUtil::BaseDictionary<uint, LPCUTF8, ArenaAllocator> WasmExportDictionary;
  65. struct WasmReaderInfo
  66. {
  67. Field(WasmFunctionInfo*) m_funcInfo;
  68. Field(Js::WebAssemblyModule*) m_module;
  69. Field(Js::Var) m_bufferSrc;
  70. };
  71. class WasmModuleGenerator
  72. {
  73. public:
  74. WasmModuleGenerator(Js::ScriptContext* scriptContext, Js::Utf8SourceInfo* sourceInfo, const byte* binaryBuffer, uint binaryBufferLength);
  75. Js::WebAssemblyModule* GenerateModule();
  76. void GenerateFunctionHeader(uint32 index);
  77. private:
  78. WasmBinaryReader* GetReader() const;
  79. Memory::Recycler* m_recycler;
  80. Js::Utf8SourceInfo* m_sourceInfo;
  81. Js::ScriptContext* m_scriptContext;
  82. Js::WebAssemblyModule* m_module;
  83. };
  84. class WasmBytecodeGenerator
  85. {
  86. public:
  87. static const Js::RegSlot ModuleSlotRegister = 0;
  88. static const Js::RegSlot ReturnRegister = 0;
  89. static const Js::RegSlot FunctionRegister = 0;
  90. static const Js::RegSlot CallReturnRegister = 0;
  91. static const Js::RegSlot ModuleEnvRegister = 1;
  92. static const Js::RegSlot ArrayBufferRegister = 2;
  93. static const Js::RegSlot ArraySizeRegister = 3;
  94. static const Js::RegSlot ScriptContextBufferRegister = 4;
  95. static const Js::RegSlot ReservedRegisterCount = 5;
  96. WasmBytecodeGenerator(Js::ScriptContext* scriptContext, WasmReaderInfo* readerinfo);
  97. static void GenerateFunctionBytecode(Js::ScriptContext* scriptContext, WasmReaderInfo* readerinfo);
  98. private:
  99. void GenerateFunction();
  100. void EmitExpr(WasmOp op);
  101. EmitInfo EmitBlock();
  102. void EmitBlockCommon(BlockInfo* blockInfo, bool* endOnElse = nullptr);
  103. EmitInfo EmitLoop();
  104. template<WasmOp wasmOp>
  105. EmitInfo EmitCall();
  106. EmitInfo EmitIfElseExpr();
  107. void EmitBrTable();
  108. EmitInfo EmitDrop();
  109. EmitInfo EmitGrowMemory();
  110. EmitInfo EmitGetLocal();
  111. EmitInfo EmitGetGlobal();
  112. EmitInfo EmitSetGlobal();
  113. EmitInfo EmitSetLocal(bool tee);
  114. void EmitReturnExpr(EmitInfo* explicitRetInfo = nullptr);
  115. EmitInfo EmitSelect();
  116. #if DBG_DUMP
  117. void PrintOpName(WasmOp op) const;
  118. #endif
  119. void EmitBr();
  120. EmitInfo EmitBrIf();
  121. EmitInfo EmitMemAccess(WasmOp wasmOp, const WasmTypes::WasmType* signature, Js::ArrayBufferView::ViewType viewType, bool isStore);
  122. EmitInfo EmitBinExpr(Js::OpCodeAsmJs op, const WasmTypes::WasmType* signature);
  123. EmitInfo EmitUnaryExpr(Js::OpCodeAsmJs op, const WasmTypes::WasmType* signature);
  124. template<WasmTypes::WasmType type>
  125. EmitInfo EmitConst();
  126. void EmitLoadConst(EmitInfo dst, WasmConstLitNode cnst);
  127. void EnregisterLocals();
  128. void ReleaseLocation(EmitInfo* info);
  129. EmitInfo PopLabel(Js::ByteCodeLabel labelValidation);
  130. BlockInfo PushLabel(Js::ByteCodeLabel label, bool addBlockYieldInfo = true);
  131. void YieldToBlock(BlockInfo blockInfo, EmitInfo expr);
  132. void YieldToBlock(uint relativeDepth, EmitInfo expr);
  133. bool ShouldYieldToBlock(uint relativeDepth) const;
  134. BlockInfo GetBlockInfo(uint relativeDepth) const;
  135. Js::ByteCodeLabel GetLabel(uint relativeDepth);
  136. static bool IsBlockOpCode(WasmOp op);
  137. static Js::OpCodeAsmJs GetLoadOp(WasmTypes::WasmType type);
  138. static Js::OpCodeAsmJs GetReturnOp(WasmTypes::WasmType type);
  139. WasmRegisterSpace* GetRegisterSpace(WasmTypes::WasmType type);
  140. EmitInfo PopEvalStack();
  141. void PushEvalStack(EmitInfo);
  142. EmitInfo EnsureYield(BlockInfo);
  143. void EnterEvalStackScope();
  144. // The caller needs to release the location of the returned EmitInfo
  145. void ExitEvalStackScope();
  146. void SetUnreachableState(bool isUnreachable);
  147. bool IsUnreachable() const { return this->isUnreachable; }
  148. Js::FunctionBody* GetFunctionBody() const { return m_funcInfo->GetBody(); }
  149. WasmReaderBase* GetReader() const;
  150. ArenaAllocator m_alloc;
  151. bool isUnreachable;
  152. WasmLocal* m_locals;
  153. WasmFunctionInfo* m_funcInfo;
  154. Js::WebAssemblyModule* m_module;
  155. uint m_maxArgOutDepth;
  156. Js::AsmJsByteCodeWriter m_writer;
  157. Js::ScriptContext* m_scriptContext;
  158. WAsmJs::TypedRegisterAllocator mTypedRegisterAllocator;
  159. JsUtil::Stack<BlockInfo> m_blockInfos;
  160. JsUtil::Stack<EmitInfo> m_evalStack;
  161. };
  162. }