LCOV - code coverage report
Current view: top level - src/asmjs - asm-parser.h (source / functions) Hit Total Coverage
Test: app.info Lines: 16 16 100.0 %
Date: 2017-04-26 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_ASMJS_ASM_PARSER_H_
       6             : #define V8_ASMJS_ASM_PARSER_H_
       7             : 
       8             : #include <string>
       9             : #include <vector>
      10             : 
      11             : #include "src/asmjs/asm-scanner.h"
      12             : #include "src/asmjs/asm-typer.h"
      13             : #include "src/asmjs/asm-types.h"
      14             : #include "src/wasm/wasm-module-builder.h"
      15             : #include "src/zone/zone-containers.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace wasm {
      20             : 
      21             : // A custom parser + validator + wasm converter for asm.js:
      22             : // http://asmjs.org/spec/latest/
      23             : // This parser intentionally avoids the portion of JavaScript parsing
      24             : // that are not required to determine if code is valid asm.js code.
      25             : // * It is mostly one pass.
      26             : // * It bails out on unexpected input.
      27             : // * It assumes strict ordering insofar as permitted by asm.js validation rules.
      28             : // * It relies on a custom scanner that provides de-duped identifiers in two
      29             : //   scopes (local + module wide).
      30      702326 : class AsmJsParser {
      31             :  public:
      32             :   explicit AsmJsParser(Isolate* isolate, Zone* zone, Handle<Script> script,
      33             :                        int start, int end);
      34             :   bool Run();
      35             :   const char* failure_message() const { return failure_message_; }
      36             :   int failure_location() const { return failure_location_; }
      37             :   WasmModuleBuilder* module_builder() { return module_builder_; }
      38             :   const AsmTyper::StdlibSet* stdlib_uses() const { return &stdlib_uses_; }
      39             : 
      40             :  private:
      41             :   // clang-format off
      42             :   enum class VarKind {
      43             :     kUnused,
      44             :     kLocal,
      45             :     kGlobal,
      46             :     kSpecial,
      47             :     kFunction,
      48             :     kTable,
      49             :     kImportedFunction,
      50             : #define V(_unused0, Name, _unused1, _unused2) kMath##Name,
      51             :     STDLIB_MATH_FUNCTION_LIST(V)
      52             : #undef V
      53             : #define V(Name, _unused1) kMath##Name,
      54             :     STDLIB_MATH_VALUE_LIST(V)
      55             : #undef V
      56             :   };
      57             :   // clang-format on
      58             : 
      59             :   struct FunctionImportInfo {
      60             :     Vector<const char> function_name;
      61             :     WasmModuleBuilder::SignatureMap cache;
      62             :   };
      63             : 
      64             :   struct VarInfo {
      65             :     AsmType* type;
      66             :     WasmFunctionBuilder* function_builder;
      67             :     FunctionImportInfo* import;
      68             :     int32_t mask;
      69             :     uint32_t index;
      70             :     VarKind kind;
      71             :     bool mutable_variable;
      72             :     bool function_defined;
      73             : 
      74             :     VarInfo();
      75             :   };
      76             : 
      77             :   struct GlobalImport {
      78             :     Vector<const char> import_name;
      79             :     ValueType value_type;
      80             :     VarInfo* var_info;
      81             :   };
      82             : 
      83             :   enum class BlockKind { kRegular, kLoop, kOther };
      84             : 
      85             :   struct BlockInfo {
      86             :     BlockKind kind;
      87             :     AsmJsScanner::token_t label;
      88             :   };
      89             : 
      90             :   // Helper class to make {TempVariable} safe for nesting.
      91             :   class TemporaryVariableScope;
      92             : 
      93             :   Zone* zone_;
      94             :   AsmJsScanner scanner_;
      95             :   WasmModuleBuilder* module_builder_;
      96             :   WasmFunctionBuilder* current_function_builder_;
      97             :   AsmType* return_type_;
      98             :   uintptr_t stack_limit_;
      99             :   AsmTyper::StdlibSet stdlib_uses_;
     100             :   ZoneVector<VarInfo> global_var_info_;
     101             :   ZoneVector<VarInfo> local_var_info_;
     102             : 
     103             :   int function_temp_locals_offset_;
     104             :   int function_temp_locals_used_;
     105             :   int function_temp_locals_depth_;
     106             : 
     107             :   // Error Handling related
     108             :   bool failed_;
     109             :   const char* failure_message_;
     110             :   int failure_location_;
     111             : 
     112             :   // Module Related.
     113             :   AsmJsScanner::token_t stdlib_name_;
     114             :   AsmJsScanner::token_t foreign_name_;
     115             :   AsmJsScanner::token_t heap_name_;
     116             : 
     117             :   static const AsmJsScanner::token_t kTokenNone = 0;
     118             : 
     119             :   // Track if parsing a heap assignment.
     120             :   bool inside_heap_assignment_;
     121             :   AsmType* heap_access_type_;
     122             : 
     123             :   ZoneVector<BlockInfo> block_stack_;
     124             : 
     125             :   // Types used for stdlib function and their set up.
     126             :   AsmType* stdlib_dq2d_;
     127             :   AsmType* stdlib_dqdq2d_;
     128             :   AsmType* stdlib_fq2f_;
     129             :   AsmType* stdlib_i2s_;
     130             :   AsmType* stdlib_ii2s_;
     131             :   AsmType* stdlib_minmax_;
     132             :   AsmType* stdlib_abs_;
     133             :   AsmType* stdlib_ceil_like_;
     134             :   AsmType* stdlib_fround_;
     135             : 
     136             :   // When making calls, the return type is needed to lookup signatures.
     137             :   // For `+callsite(..)` or `fround(callsite(..))` use this value to pass
     138             :   // along the coercion.
     139             :   AsmType* call_coercion_;
     140             : 
     141             :   // The source position associated with the above {call_coercion}.
     142             :   size_t call_coercion_position_;
     143             : 
     144             :   // When making calls, the coercion can also appear in the source stream
     145             :   // syntactically "behind" the call site. For `callsite(..)|0` use this
     146             :   // value to flag that such a coercion must happen.
     147             :   AsmType* call_coercion_deferred_;
     148             : 
     149             :   // The source position at which requesting a deferred coercion via the
     150             :   // aforementioned {call_coercion_deferred} is allowed.
     151             :   size_t call_coercion_deferred_position_;
     152             : 
     153             :   // Used to track the last label we've seen so it can be matched to later
     154             :   // statements it's attached to.
     155             :   AsmJsScanner::token_t pending_label_;
     156             : 
     157             :   // Global imports. The list of imported variables that are copied during
     158             :   // module instantiation into a corresponding global variable.
     159             :   ZoneLinkedList<GlobalImport> global_imports_;
     160             : 
     161             :   Zone* zone() { return zone_; }
     162             : 
     163             :   inline bool Peek(AsmJsScanner::token_t token) {
     164     1267765 :     return scanner_.Token() == token;
     165             :   }
     166             : 
     167             :   inline bool Check(AsmJsScanner::token_t token) {
     168     2205445 :     if (scanner_.Token() == token) {
     169      153485 :       scanner_.Next();
     170             :       return true;
     171             :     } else {
     172             :       return false;
     173             :     }
     174             :   }
     175             : 
     176       33116 :   inline bool CheckForZero() {
     177       33116 :     if (scanner_.IsUnsigned() && scanner_.AsUnsigned() == 0) {
     178       31998 :       scanner_.Next();
     179       31998 :       return true;
     180             :     } else {
     181             :       return false;
     182             :     }
     183             :   }
     184             : 
     185             :   inline bool CheckForDouble(double* value) {
     186       78619 :     if (scanner_.IsDouble()) {
     187             :       *value = scanner_.AsDouble();
     188        1464 :       scanner_.Next();
     189             :       return true;
     190             :     } else {
     191             :       return false;
     192             :     }
     193             :   }
     194             : 
     195             :   inline bool CheckForUnsigned(uint32_t* value) {
     196      127128 :     if (scanner_.IsUnsigned()) {
     197             :       *value = scanner_.AsUnsigned();
     198      104364 :       scanner_.Next();
     199             :       return true;
     200             :     } else {
     201             :       return false;
     202             :     }
     203             :   }
     204             : 
     205             :   inline bool CheckForUnsignedBelow(uint32_t limit, uint32_t* value) {
     206      181871 :     if (scanner_.IsUnsigned() && scanner_.AsUnsigned() < limit) {
     207             :       *value = scanner_.AsUnsigned();
     208       71524 :       scanner_.Next();
     209             :       return true;
     210             :     } else {
     211             :       return false;
     212             :     }
     213             :   }
     214             : 
     215             :   inline AsmJsScanner::token_t Consume() {
     216       30289 :     AsmJsScanner::token_t ret = scanner_.Token();
     217      320605 :     scanner_.Next();
     218             :     return ret;
     219             :   }
     220             : 
     221             :   void SkipSemicolon();
     222             : 
     223             :   VarInfo* GetVarInfo(AsmJsScanner::token_t token);
     224             :   uint32_t VarIndex(VarInfo* info);
     225             :   void DeclareGlobal(VarInfo* info, bool mutable_variable, AsmType* type,
     226             :                      ValueType vtype,
     227             :                      const WasmInitExpr& init = WasmInitExpr());
     228             :   void DeclareStdlibFunc(VarInfo* info, VarKind kind, AsmType* type);
     229             :   void AddGlobalImport(Vector<const char> name, AsmType* type, ValueType vtype,
     230             :                        bool mutable_variable, VarInfo* info);
     231             : 
     232             :   // Allocates a temporary local variable. The given {index} is absolute within
     233             :   // the function body, consider using {TemporaryVariableScope} when nesting.
     234             :   uint32_t TempVariable(int index);
     235             : 
     236             :   // Preserves a copy of the scanner's current identifier string in the zone.
     237             :   Vector<const char> CopyCurrentIdentifierString();
     238             : 
     239             :   // Use to set up block stack layers (including synthetic ones for if-else).
     240             :   // Begin/Loop/End below are implemented with these plus code generation.
     241             :   void BareBegin(BlockKind kind = BlockKind::kOther,
     242             :                  AsmJsScanner::token_t label = 0);
     243             :   void BareEnd();
     244             :   int FindContinueLabelDepth(AsmJsScanner::token_t label);
     245             :   int FindBreakLabelDepth(AsmJsScanner::token_t label);
     246             : 
     247             :   // Use to set up actual wasm blocks/loops.
     248             :   void Begin(AsmJsScanner::token_t label = 0);
     249             :   void Loop(AsmJsScanner::token_t label = 0);
     250             :   void End();
     251             : 
     252             :   void InitializeStdlibTypes();
     253             : 
     254             :   FunctionSig* ConvertSignature(AsmType* return_type,
     255             :                                 const std::vector<AsmType*>& params);
     256             : 
     257             :   // 6.1 ValidateModule
     258             :   void ValidateModule();
     259             :   void ValidateModuleParameters();
     260             :   void ValidateModuleVars();
     261             :   void ValidateModuleVar(bool mutable_variable);
     262             :   bool ValidateModuleVarImport(VarInfo* info, bool mutable_variable);
     263             :   void ValidateModuleVarStdlib(VarInfo* info);
     264             :   void ValidateModuleVarNewStdlib(VarInfo* info);
     265             :   void ValidateModuleVarFromGlobal(VarInfo* info, bool mutable_variable);
     266             : 
     267             :   void ValidateExport();         // 6.2 ValidateExport
     268             :   void ValidateFunctionTable();  // 6.3 ValidateFunctionTable
     269             :   void ValidateFunction();       // 6.4 ValidateFunction
     270             :   void ValidateFunctionParams(std::vector<AsmType*>* params);
     271             :   void ValidateFunctionLocals(size_t param_count,
     272             :                               std::vector<ValueType>* locals);
     273             :   void ValidateStatement();              // ValidateStatement
     274             :   void Block();                          // 6.5.1 Block
     275             :   void ExpressionStatement();            // 6.5.2 ExpressionStatement
     276             :   void EmptyStatement();                 // 6.5.3 EmptyStatement
     277             :   void IfStatement();                    // 6.5.4 IfStatement
     278             :   void ReturnStatement();                // 6.5.5 ReturnStatement
     279             :   bool IterationStatement();             // 6.5.6 IterationStatement
     280             :   void WhileStatement();                 // 6.5.6 IterationStatement - while
     281             :   void DoStatement();                    // 6.5.6 IterationStatement - do
     282             :   void ForStatement();                   // 6.5.6 IterationStatement - for
     283             :   void BreakStatement();                 // 6.5.7 BreakStatement
     284             :   void ContinueStatement();              // 6.5.8 ContinueStatement
     285             :   void LabelledStatement();              // 6.5.9 LabelledStatement
     286             :   void SwitchStatement();                // 6.5.10 SwitchStatement
     287             :   void ValidateCase();                   // 6.6. ValidateCase
     288             :   void ValidateDefault();                // 6.7 ValidateDefault
     289             :   AsmType* ValidateExpression();         // 6.8 ValidateExpression
     290             :   AsmType* Expression(AsmType* expect);  // 6.8.1 Expression
     291             :   AsmType* NumericLiteral();             // 6.8.2 NumericLiteral
     292             :   AsmType* Identifier();                 // 6.8.3 Identifier
     293             :   AsmType* CallExpression();             // 6.8.4 CallExpression
     294             :   AsmType* MemberExpression();           // 6.8.5 MemberExpression
     295             :   AsmType* AssignmentExpression();       // 6.8.6 AssignmentExpression
     296             :   AsmType* UnaryExpression();            // 6.8.7 UnaryExpression
     297             :   AsmType* MultiplicativeExpression();   // 6.8.8 MultiplicativeExpression
     298             :   AsmType* AdditiveExpression();         // 6.8.9 AdditiveExpression
     299             :   AsmType* ShiftExpression();            // 6.8.10 ShiftExpression
     300             :   AsmType* RelationalExpression();       // 6.8.11 RelationalExpression
     301             :   AsmType* EqualityExpression();         // 6.8.12 EqualityExpression
     302             :   AsmType* BitwiseANDExpression();       // 6.8.13 BitwiseANDExpression
     303             :   AsmType* BitwiseXORExpression();       // 6.8.14 BitwiseXORExpression
     304             :   AsmType* BitwiseORExpression();        // 6.8.15 BitwiseORExpression
     305             :   AsmType* ConditionalExpression();      // 6.8.16 ConditionalExpression
     306             :   AsmType* ParenthesizedExpression();    // 6.8.17 ParenthesiedExpression
     307             :   AsmType* ValidateCall();               // 6.9 ValidateCall
     308             :   bool PeekCall();                       // 6.9 ValidateCall - helper
     309             :   void ValidateHeapAccess();             // 6.10 ValidateHeapAccess
     310             :   void ValidateFloatCoercion();          // 6.11 ValidateFloatCoercion
     311             : 
     312             :   // Used as part of {ForStatement}. Scans forward to the next `)` in order to
     313             :   // skip over the third expression in a for-statement. This is one piece that
     314             :   // makes this parser not be a pure single-pass.
     315             :   void ScanToClosingParenthesis();
     316             : 
     317             :   // Used as part of {SwitchStatement}. Collects all case labels in the current
     318             :   // switch-statement, then resets the scanner position. This is one piece that
     319             :   // makes this parser not be a pure single-pass.
     320             :   void GatherCases(std::vector<int32_t>* cases);
     321             : };
     322             : 
     323             : }  // namespace wasm
     324             : }  // namespace internal
     325             : }  // namespace v8
     326             : 
     327             : #endif  // V8_ASMJS_ASM_PARSER_H_

Generated by: LCOV version 1.10