Index: src/asmjs/asm-parser.h |
diff --git a/src/asmjs/asm-parser.h b/src/asmjs/asm-parser.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..86aec71636945215fdd008e2c45ad5281b1b97de |
--- /dev/null |
+++ b/src/asmjs/asm-parser.h |
@@ -0,0 +1,304 @@ |
+// Copyright 2017 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_ASMJS_ASM_PARSER_H_ |
+#define V8_ASMJS_ASM_PARSER_H_ |
+ |
+#include <list> |
+#include <string> |
+#include <vector> |
+ |
+#include "src/asmjs/asm-scanner.h" |
+#include "src/asmjs/asm-typer.h" |
+#include "src/asmjs/asm-types.h" |
+#include "src/wasm/signature-map.h" |
+#include "src/wasm/wasm-module-builder.h" |
+#include "src/zone/zone-containers.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace wasm { |
+ |
+// A custom parser + validator + wasm converter for asm.js: |
+// http://asmjs.org/spec/latest/ |
+// This parser intentionally avoids the portion of JavaScript parsing |
+// that are not required to determine if code is valid asm.js code. |
+// * It is mostly one pass. |
+// * It bails out on unexpected input. |
+// * It assumes strict ordering insofar as permitted by asm.js validation rules. |
+// * It relies on a custom scanner that provides de-duped identifiers in two |
+// scopes (local + module wide). |
+class AsmJsParser { |
+ public: |
+ explicit AsmJsParser(Isolate* isolate, Zone* zone, Handle<Script> script, |
+ int start, int end); |
+ bool Run(); |
+ const char* failure_message() const { return failure_message_.c_str(); } |
+ int failure_location() const { return failure_location_; } |
+ WasmModuleBuilder* module_builder() { return module_builder_; } |
+ const AsmTyper::StdlibSet* stdlib_uses() const { return &stdlib_uses_; } |
+ |
+ private: |
+ // clang-format off |
+ enum class VarKind { |
+ kUnused, |
+ kLocal, |
+ kGlobal, |
+ kSpecial, |
+ kFunction, |
+ kTable, |
+ kImportedFunction, |
+#define V(_unused0, Name, _unused1, _unused2) kMath##Name, |
+ STDLIB_MATH_FUNCTION_LIST(V) |
+#undef V |
+#define V(Name) kMath##Name, |
+ STDLIB_MATH_VALUE_LIST(V) |
+#undef V |
+ }; |
+ // clang-format on |
+ |
+ struct FunctionImportInfo { |
+ std::string name; |
+ SignatureMap cache; |
+ std::vector<uint32_t> cache_index; |
+ }; |
+ |
+ struct VarInfo { |
+ AsmType* type; |
+ WasmFunctionBuilder* function_builder; |
+ FunctionImportInfo* import; |
+ int32_t mask; |
+ uint32_t index; |
+ VarKind kind; |
+ bool mutable_variable; |
+ bool function_defined; |
+ |
+ VarInfo(); |
+ void DeclareGlobalImport(AsmType* type, uint32_t index); |
+ void DeclareStdlibFunc(VarKind kind, AsmType* type); |
+ }; |
+ |
+ struct GlobalImport { |
+ std::string import_name; |
+ uint32_t import_index; |
+ uint32_t global_index; |
+ bool needs_init; |
+ }; |
+ |
+ enum class BlockKind { kRegular, kLoop, kOther }; |
+ |
+ struct BlockInfo { |
+ BlockKind kind; |
+ AsmJsScanner::token_t label; |
+ }; |
+ |
+ Zone* zone_; |
+ AsmJsScanner scanner_; |
+ WasmModuleBuilder* module_builder_; |
+ WasmFunctionBuilder* current_function_builder_; |
+ AsmType* return_type_; |
+ std::uintptr_t stack_limit_; |
+ AsmTyper::StdlibSet stdlib_uses_; |
+ std::list<FunctionImportInfo> function_import_info_; |
+ ZoneVector<VarInfo> global_var_info_; |
+ ZoneVector<VarInfo> local_var_info_; |
+ |
+ int function_temp_locals_offset_; |
+ int function_temp_locals_used_; |
+ |
+ // Error Handling related |
+ bool failed_; |
+ std::string failure_message_; |
+ int failure_location_; |
+ |
+ // Module Related. |
+ AsmJsScanner::token_t stdlib_name_; |
+ AsmJsScanner::token_t foreign_name_; |
+ AsmJsScanner::token_t heap_name_; |
+ |
+ static const AsmJsScanner::token_t kTokenNone = 0; |
+ |
+ // Track if parsing a heap assignment. |
+ bool inside_heap_assignment_; |
+ AsmType* heap_access_type_; |
+ |
+ ZoneVector<BlockInfo> block_stack_; |
+ |
+ // Types used for stdlib function and their set up. |
+ AsmType* stdlib_dq2d_; |
+ AsmType* stdlib_dqdq2d_; |
+ AsmType* stdlib_fq2f_; |
+ AsmType* stdlib_i2s_; |
+ AsmType* stdlib_ii2s_; |
+ AsmType* stdlib_minmax_; |
+ AsmType* stdlib_abs_; |
+ AsmType* stdlib_ceil_like_; |
+ AsmType* stdlib_fround_; |
+ |
+ // When making calls, the return type is needed to lookup signatures. |
+ // For +callsite(..) or fround(callsite(..)) use this value to pass |
+ // along the coercion. |
+ AsmType* call_coercion_; |
+ |
+ // Used to track the last label we've seen so it can be matched to later |
+ // statements it's attached to. |
+ AsmJsScanner::token_t pending_label_; |
+ |
+ // Global imports. |
+ // NOTE: Holds the strings referenced in wasm-module-builder for imports. |
+ ZoneLinkedList<GlobalImport> global_imports_; |
+ |
+ Zone* zone() { return zone_; } |
+ |
+ inline bool Peek(AsmJsScanner::token_t token) { |
+ return scanner_.Token() == token; |
+ } |
+ |
+ inline bool Check(AsmJsScanner::token_t token) { |
+ if (scanner_.Token() == token) { |
+ scanner_.Next(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ inline bool CheckForZero() { |
+ if (scanner_.IsUnsigned() && scanner_.AsUnsigned() == 0) { |
+ scanner_.Next(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ inline bool CheckForDouble(double* value) { |
+ if (scanner_.IsDouble()) { |
+ *value = scanner_.AsDouble(); |
+ scanner_.Next(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ inline bool CheckForUnsigned(uint64_t* value) { |
+ if (scanner_.IsUnsigned()) { |
+ *value = scanner_.AsUnsigned(); |
+ scanner_.Next(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ inline bool CheckForUnsignedBelow(uint64_t limit, uint64_t* value) { |
+ if (scanner_.IsUnsigned() && scanner_.AsUnsigned() < limit) { |
+ *value = scanner_.AsUnsigned(); |
+ scanner_.Next(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ inline AsmJsScanner::token_t Consume() { |
+ AsmJsScanner::token_t ret = scanner_.Token(); |
+ scanner_.Next(); |
+ return ret; |
+ } |
+ |
+ void SkipSemicolon(); |
+ |
+ VarInfo* GetVarInfo(AsmJsScanner::token_t token); |
+ uint32_t VarIndex(VarInfo* info); |
+ void DeclareGlobal(VarInfo* info, bool mutable_variable, AsmType* type, |
+ ValueType vtype, |
+ const WasmInitExpr& init = WasmInitExpr()); |
+ |
+ int32_t TempVariable(int i); |
+ |
+ void AddGlobalImport(std::string name, AsmType* type, ValueType vtype, |
+ bool mutable_variable, VarInfo* info); |
+ |
+ // Use to set up block stack layers (including synthetic ones for if-else). |
+ // Begin/Loop/End below are implemented with these plus code generation. |
+ void BareBegin(BlockKind kind = BlockKind::kOther, |
+ AsmJsScanner::token_t label = 0); |
+ void BareEnd(); |
+ int FindContinueLabelDepth(AsmJsScanner::token_t label); |
+ int FindBreakLabelDepth(AsmJsScanner::token_t label); |
+ |
+ // Use to set up actual wasm blocks/loops. |
+ void Begin(AsmJsScanner::token_t label = 0); |
+ void Loop(AsmJsScanner::token_t label = 0); |
+ void End(); |
+ |
+ void InitializeStdlibTypes(); |
+ |
+ FunctionSig* ConvertSignature(AsmType* return_type, |
+ const std::vector<AsmType*>& params); |
+ |
+ // 6.1 ValidateModule |
+ void ValidateModule(); |
+ void ValidateModuleParameters(); |
+ void ValidateModuleVars(); |
+ void ValidateModuleVar(bool mutable_variable); |
+ bool ValidateModuleVarImport(VarInfo* info, bool mutable_variable); |
+ void ValidateModuleVarStdlib(VarInfo* info); |
+ void ValidateModuleVarNewStdlib(VarInfo* info); |
+ void ValidateModuleVarFloat(VarInfo* info, bool mutable_variable); |
+ |
+ void ValidateExport(); // 6.2 ValidateExport |
+ void ValidateFunctionTable(); // 6.3 ValidateFunctionTable |
+ void ValidateFunction(); // 6.4 ValidateFunction |
+ void ValidateFunctionParams(std::vector<AsmType*>* params); |
+ void ValidateFunctionLocals(size_t param_count, |
+ std::vector<ValueType>* locals); |
+ void ValidateStatement(); // ValidateStatement |
+ void Block(); // 6.5.1 Block |
+ void ExpressionStatement(); // 6.5.2 ExpressionStatement |
+ void EmptyStatement(); // 6.5.3 EmptyStatement |
+ void IfStatement(); // 6.5.4 IfStatement |
+ void ReturnStatement(); // 6.5.5 ReturnStatement |
+ bool IterationStatement(); // 6.5.6 IterationStatement |
+ void WhileStatement(); // 6.5.6 IterationStatement - while |
+ void DoStatement(); // 6.5.6 IterationStatement - do |
+ void ForStatement(); // 6.5.6 IterationStatement - for |
+ void BreakStatement(); // 6.5.7 BreakStatement |
+ void ContinueStatement(); // 6.5.8 ContinueStatement |
+ void LabelledStatement(); // 6.5.9 LabelledStatement |
+ void SwitchStatement(); // 6.5.10 SwitchStatement |
+ void ValidateCase(); // 6.6. ValidateCase |
+ void ValidateDefault(); // 6.7 ValidateDefault |
+ AsmType* ValidateExpression(); // 6.8 ValidateExpression |
+ AsmType* Expression(AsmType* expect); // 6.8.1 Expression |
+ AsmType* NumericLiteral(); // 6.8.2 NumericLiteral |
+ AsmType* Identifier(); // 6.8.3 Identifier |
+ AsmType* CallExpression(); // 6.8.4 CallExpression |
+ AsmType* MemberExpression(); // 6.8.5 MemberExpression |
+ AsmType* AssignmentExpression(); // 6.8.6 AssignmentExpression |
+ AsmType* UnaryExpression(); // 6.8.7 UnaryExpression |
+ AsmType* MultiplicativeExpression(); // 6.8.8 MultaplicativeExpression |
+ AsmType* AdditiveExpression(); // 6.8.9 AdditiveExpression |
+ AsmType* ShiftExpression(); // 6.8.10 ShiftExpression |
+ AsmType* RelationalExpression(); // 6.8.11 RelationalExpression |
+ AsmType* EqualityExpression(); // 6.8.12 EqualityExpression |
+ AsmType* BitwiseANDExpression(); // 6.8.13 BitwiseANDExpression |
+ AsmType* BitwiseXORExpression(); // 6.8.14 BitwiseXORExpression |
+ AsmType* BitwiseORExpression(); // 6.8.15 BitwiseORExpression |
+ AsmType* ConditionalExpression(); // 6.8.16 ConditionalExpression |
+ AsmType* ParenthesizedExpression(); // 6.8.17 ParenthesiedExpression |
+ AsmType* ValidateCall(); // 6.9 ValidateCall |
+ bool PeekCall(); // 6.9 ValidateCall - helper |
+ void ValidateHeapAccess(); // 6.10 ValidateHeapAccess |
+ void ValidateFloatCoercion(); // 6.11 ValidateFloatCoercion |
+ |
+ void GatherCases(std::vector<int32_t>* cases); |
+}; |
+ |
+} // namespace wasm |
+} // namespace internal |
+} // namespace v8 |
+#endif |