AsmJsByteCodeGenerator.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. #ifndef TEMP_DISABLE_ASMJS
  7. namespace Js
  8. {
  9. enum EBinaryMathOpCodes: int;
  10. enum EBinaryComparatorOpCodes: int;
  11. // Information about the expression that has been emitted
  12. struct EmitExpressionInfo
  13. {
  14. EmitExpressionInfo( RegSlot location_, const AsmJsType& type_ ) :
  15. location( location_ ), type( type_ )
  16. {
  17. }
  18. EmitExpressionInfo( const AsmJsType& type_ ) :
  19. location( Constants::NoRegister ), type( type_ )
  20. {
  21. }
  22. EmitExpressionInfo():
  23. location( Constants::NoRegister ), type( AsmJsType::Void )
  24. {
  25. }
  26. RegSlot location;
  27. AsmJsType type;
  28. };
  29. /// AutoPtr cleanup for asmjs bytecode compilation
  30. class AsmJsFunctionCompilation
  31. {
  32. AsmJSByteCodeGenerator* mGenerator;
  33. public:
  34. AsmJsFunctionCompilation( AsmJSByteCodeGenerator* gen ) :
  35. mGenerator( gen )
  36. {
  37. }
  38. ~AsmJsFunctionCompilation()
  39. {
  40. CleanUp();
  41. }
  42. void CleanUp();
  43. void FinishCompilation()
  44. {
  45. mGenerator = nullptr;
  46. }
  47. };
  48. class AsmJSByteCodeGenerator
  49. {
  50. friend AsmJsFunctionCompilation;
  51. AsmJsFunc* mFunction;
  52. FuncInfo* mInfo;
  53. AsmJsModuleCompiler* mCompiler;
  54. // Reference to non-asmjs bytecode gen. Needed to bind fields for SIMD.js code
  55. ByteCodeGenerator* mByteCodeGenerator;
  56. AsmJsByteCodeWriter mWriter;
  57. int mNestedCallCount;
  58. bool mIsCallLegal;
  59. public:
  60. AsmJSByteCodeGenerator(AsmJsFunc* func, AsmJsModuleCompiler* compiler);
  61. static void EmitEmptyByteCode(FuncInfo* funcInfo, ByteCodeGenerator* byteCodeGen, ParseNode* funcNode);
  62. bool EmitOneFunction();
  63. private:
  64. ArenaAllocator mAllocator;
  65. bool BlockHasOwnScope( ParseNode* pnodeBlock );
  66. void PrintAsmJsCompilationError(__out_ecount(256) char16* msg);
  67. void DefineLabels();
  68. void EmitAsmJsFunctionBody();
  69. void EmitTopLevelStatement( ParseNode *stmt );
  70. EmitExpressionInfo Emit( ParseNode *pnode );
  71. EmitExpressionInfo EmitIdentifier( ParseNode * pnode );
  72. EmitExpressionInfo EmitLdArrayBuffer( ParseNode * pnode );
  73. enum TypedArrayEmitType{
  74. LoadTypedArray,
  75. StoreTypedArray,
  76. };
  77. EmitExpressionInfo EmitTypedArrayIndex(ParseNode* indexNode, OpCodeAsmJs &op, uint32 &indexSlot, ArrayBufferView::ViewType viewType, TypedArrayEmitType emitType);
  78. EmitExpressionInfo EmitAssignment( ParseNode * pnode );
  79. EmitExpressionInfo EmitReturn( ParseNode * pnode );
  80. EmitExpressionInfo EmitCall( ParseNode * pnode, AsmJsRetType expectedType = AsmJsRetType::Void );
  81. EmitExpressionInfo EmitMathBuiltin( ParseNode* pnode, AsmJsMathFunction* mathFunction, AsmJsRetType expectedType );
  82. EmitExpressionInfo EmitMinMax(ParseNode* pnode, AsmJsMathFunction* mathFunction, AsmJsRetType expectedType);
  83. EmitExpressionInfo EmitUnaryPos( ParseNode * pnode );
  84. EmitExpressionInfo EmitUnaryNeg( ParseNode * pnode );
  85. EmitExpressionInfo EmitUnaryNot( ParseNode * pnode );
  86. EmitExpressionInfo EmitUnaryLogNot( ParseNode * pnode );
  87. EmitExpressionInfo EmitBinaryMultiType( ParseNode * pnode, EBinaryMathOpCodes op );
  88. EmitExpressionInfo EmitBinaryInt( ParseNode * pnode, OpCodeAsmJs op );
  89. EmitExpressionInfo EmitQMark( ParseNode * pnode );
  90. EmitExpressionInfo EmitSwitch( ParseNode * pnode );
  91. EmitExpressionInfo EmitBinaryComparator( ParseNode * pnode, EBinaryComparatorOpCodes op);
  92. EmitExpressionInfo EmitLoop( ParseNode *loopNode, ParseNode *cond, ParseNode *body, ParseNode *incr, BOOL doWhile = false );
  93. EmitExpressionInfo EmitIf( ParseNode * pnode );
  94. EmitExpressionInfo EmitBooleanExpression( ParseNode* pnodeCond, Js::ByteCodeLabel trueLabel, Js::ByteCodeLabel falseLabel );
  95. EmitExpressionInfo* EmitSimdBuiltinArguments(ParseNode* pnode, AsmJsFunctionDeclaration* func, __out_ecount(pnode->sxCall.argCount) AsmJsType *argsTypes, EmitExpressionInfo *argsInfo);
  96. bool ValidateSimdFieldAccess(PropertyName field, const AsmJsType& receiverType, OpCodeAsmJs &op);
  97. EmitExpressionInfo EmitDotExpr(ParseNode* pnode);
  98. EmitExpressionInfo EmitSimdBuiltin(ParseNode* pnode, AsmJsSIMDFunction* simdFunction, AsmJsRetType expectedType);
  99. EmitExpressionInfo EmitSimdLoadStoreBuiltin(ParseNode* pnode, AsmJsSIMDFunction* simdFunction, AsmJsRetType expectedType);
  100. void FinalizeRegisters( FunctionBody* byteCodeFunction );
  101. void LoadAllConstants();
  102. void StartStatement(ParseNode* pnode);
  103. void EndStatement(ParseNode* pnode);
  104. // Emits the bytecode to load from the module
  105. // dst is the location of the variable in the function
  106. // index is the location of the target in the module's table
  107. void LoadModuleInt(RegSlot dst, RegSlot index); // dst points to the IntRegisterSpace
  108. void LoadModuleFloat(RegSlot dst, RegSlot index); // dst points to the FloatRegisterSpace
  109. void LoadModuleDouble( RegSlot dst, RegSlot index ); // dst points to the DoubleRegisterSpace
  110. void LoadModuleFFI( RegSlot dst, RegSlot index ); // dst points to a Var
  111. void LoadModuleFunction( RegSlot dst, RegSlot index ); // dst points to a Var
  112. void LoadModuleFunctionTable( RegSlot dst, RegSlot FuncTableIndex, RegSlot FuncIndexLocation ); // dst points to a Var
  113. // Emits the bytecode to set a variable int the module
  114. // dst is the location of the variable in the module's table
  115. // src is the location of the variable in the function
  116. void SetModuleInt(Js::RegSlot dst, RegSlot src);
  117. void SetModuleFloat(Js::RegSlot dst, RegSlot src);
  118. void SetModuleDouble( Js::RegSlot dst, RegSlot src );
  119. void LoadModuleSimd(RegSlot dst, RegSlot index, AsmJsVarType type);
  120. void SetModuleSimd(RegSlot dst, RegSlot src, AsmJsVarType type);
  121. void LoadSimd(RegSlot dst, RegSlot src, AsmJsVarType type);
  122. bool IsFRound(AsmJsMathFunction* sym);
  123. bool IsValidSimdFcnRetType(AsmJsSIMDFunction& simdFunction, const AsmJsRetType& expectedType, const AsmJsRetType& retType);
  124. /// TODO:: Finish removing references to old bytecode generator
  125. ByteCodeGenerator* GetOldByteCodeGenerator() const
  126. {
  127. return mByteCodeGenerator;
  128. }
  129. bool IsSimdjsEnabled()
  130. {
  131. return mFunction->GetFuncBody()->GetScriptContext()->GetConfig()->IsSimdjsEnabled();
  132. }
  133. // try to reuse a tmp register or acquire a new one
  134. // also takes care of releasing tmp register
  135. template<typename T>
  136. RegSlot GetAndReleaseBinaryLocations( const EmitExpressionInfo* lhs, const EmitExpressionInfo* rhs )
  137. {
  138. RegSlot tmpRegToUse;
  139. if( mFunction->IsTmpLocation<T>( lhs ) )
  140. {
  141. tmpRegToUse = lhs->location;
  142. mFunction->ReleaseLocation<T>( rhs );
  143. }
  144. else if( mFunction->IsTmpLocation<T>( rhs ) )
  145. {
  146. tmpRegToUse = rhs->location;
  147. mFunction->ReleaseLocation<T>( lhs );
  148. }
  149. else
  150. {
  151. tmpRegToUse = mFunction->AcquireTmpRegister<T>();
  152. mFunction->ReleaseLocation<T>( rhs );
  153. mFunction->ReleaseLocation<T>( lhs );
  154. }
  155. return tmpRegToUse;
  156. }
  157. template<typename T>
  158. RegSlot GetAndReleaseUnaryLocations( const EmitExpressionInfo* rhs )
  159. {
  160. RegSlot tmpRegToUse;
  161. if( mFunction->IsTmpLocation<T>( rhs ) )
  162. {
  163. tmpRegToUse = rhs->location;
  164. }
  165. else
  166. {
  167. tmpRegToUse = mFunction->AcquireTmpRegister<T>();
  168. mFunction->ReleaseLocation<T>( rhs );
  169. }
  170. return tmpRegToUse;
  171. }
  172. };
  173. }
  174. #endif