| 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
|
|
|