v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
asm-parser.h
Go to the documentation of this file.
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 <memory>
9
11#include "src/asmjs/asm-types.h"
12#include "src/base/enum-set.h"
13#include "src/base/vector.h"
16
17namespace v8 {
18namespace internal {
19
20class Utf16CharacterStream;
21
22namespace wasm {
23
24// A custom parser + validator + wasm converter for asm.js:
25// http://asmjs.org/spec/latest/
26// This parser intentionally avoids the portion of JavaScript parsing
27// that are not required to determine if code is valid asm.js code.
28// * It is mostly one pass.
29// * It bails out on unexpected input.
30// * It assumes strict ordering insofar as permitted by asm.js validation rules.
31// * It relies on a custom scanner that provides de-duped identifiers in two
32// scopes (local + module wide).
34 public:
35 // clang-format off
39#define V(_unused1, name, _unused2, _unused3) kMath##name,
41#undef V
42#define V(name, _unused1) kMath##name,
44#undef V
45#define V(name, _unused1, _unused2, _unused3) k##name,
47#undef V
48 };
49 // clang-format on
50
52
53 explicit AsmJsParser(Zone* zone, uintptr_t stack_limit,
54 Utf16CharacterStream* stream);
55 bool Run();
56 const char* failure_message() const { return failure_message_; }
57 int failure_location() const { return failure_location_; }
59 const StdlibSet* stdlib_uses() const { return &stdlib_uses_; }
60
61 private:
62 // clang-format off
63 enum class VarKind {
64 kUnused,
65 kLocal,
66 kGlobal,
69 kTable,
71#define V(_unused0, Name, _unused1, _unused2) kMath##Name,
73#undef V
74#define V(Name, _unused1) kMath##Name,
76#undef V
77 };
78 // clang-format on
79
80 // A single import in asm.js can require multiple imports in wasm, if the
81 // function is used with different signatures. {cache} keeps the wasm
82 // imports for the single asm.js import of name {function_name}.
91
92 struct VarInfo {
93 AsmType* type = AsmType::None();
95 FunctionImportInfo* import = nullptr;
96 uint32_t mask = 0;
97 uint32_t index = 0;
99 bool mutable_variable = true;
100 bool function_defined = false;
101 };
102
108
109 // Distinguish different kinds of blocks participating in {block_stack}. Each
110 // entry on that stack represents one block in the wasm code, and determines
111 // which block 'break' and 'continue' target in the current context:
112 // - kRegular: The target of a 'break' (with & without identifier).
113 // Pushed by an IterationStatement and a SwitchStatement.
114 // - kLoop : The target of a 'continue' (with & without identifier).
115 // Pushed by an IterationStatement.
116 // - kNamed : The target of a 'break' with a specific identifier.
117 // Pushed by a BlockStatement.
118 // - kOther : Only used for internal blocks, can never be targeted.
120
121 // One entry in the {block_stack}, see {BlockKind} above for details. Blocks
122 // without a label have {kTokenNone} set as their label.
127
128 // Helper class to make {TempVariable} safe for nesting.
130
131 template <typename T>
133 public:
135
136 Zone* zone() const { return reusable_vectors_.zone(); }
137
138 inline void fill(ZoneVector<T>* vec) {
139 if (reusable_vectors_.empty()) return;
140 reusable_vectors_.back().swap(*vec);
141 reusable_vectors_.pop_back();
142 vec->clear();
143 }
144
145 inline void reuse(ZoneVector<T>* vec) {
146 reusable_vectors_.emplace_back(std::move(*vec));
147 }
148
149 private:
151 };
152
153 template <typename T>
154 class CachedVector final : public ZoneVector<T> {
155 public:
157 : ZoneVector<T>(cache->zone()), cache_(cache) {
158 cache->fill(this);
159 }
160 ~CachedVector() { cache_->reuse(this); }
161
162 private:
164 };
165
171 uintptr_t stack_limit_;
175 size_t num_globals_ = 0;
176
181
185
186 // Error Handling related
187 bool failed_ = false;
188 const char* failure_message_;
190
191 // Module Related.
195
197
198 // Track if parsing a heap assignment.
201
203
204 // Types used for stdlib function and their set up.
213
214 // When making calls, the return type is needed to lookup signatures.
215 // For `+callsite(..)` or `fround(callsite(..))` use this value to pass
216 // along the coercion.
218
219 // The source position associated with the above {call_coercion}.
221
222 // When making calls, the coercion can also appear in the source stream
223 // syntactically "behind" the call site. For `callsite(..)|0` use this
224 // value to flag that such a coercion must happen.
226
227 // The source position at which requesting a deferred coercion via the
228 // aforementioned {call_coercion_deferred} is allowed.
230
231 // The code position of the last heap access shift by an immediate value.
232 // For `heap[expr >> value:NumericLiteral]` this indicates from where to
233 // delete code when the expression is used as part of a valid heap access.
234 // Will be set to {kNoHeapAccessShift} if heap access shift wasn't matched.
237 static const size_t kNoHeapAccessShift = -1;
238
239 // Used to track the last label we've seen so it can be matched to later
240 // statements it's attached to.
242
243 // Global imports. The list of imported variables that are copied during
244 // module instantiation into a corresponding global variable.
246
247 Zone* zone() { return zone_; }
248
249 inline bool Peek(AsmJsScanner::token_t token) {
250 return scanner_.Token() == token;
251 }
252
253 inline bool PeekForZero() {
254 return (scanner_.IsUnsigned() && scanner_.AsUnsigned() == 0);
255 }
256
257 inline bool Check(AsmJsScanner::token_t token) {
258 if (scanner_.Token() == token) {
259 scanner_.Next();
260 return true;
261 } else {
262 return false;
263 }
264 }
265
266 inline bool CheckForZero() {
267 if (scanner_.IsUnsigned() && scanner_.AsUnsigned() == 0) {
268 scanner_.Next();
269 return true;
270 } else {
271 return false;
272 }
273 }
274
275 inline bool CheckForDouble(double* value) {
276 if (scanner_.IsDouble()) {
277 *value = scanner_.AsDouble();
278 scanner_.Next();
279 return true;
280 } else {
281 return false;
282 }
283 }
284
285 inline bool CheckForUnsigned(uint32_t* value) {
286 if (scanner_.IsUnsigned()) {
287 *value = scanner_.AsUnsigned();
288 scanner_.Next();
289 return true;
290 } else {
291 return false;
292 }
293 }
294
295 inline bool CheckForUnsignedBelow(uint32_t limit, uint32_t* value) {
296 if (scanner_.IsUnsigned() && scanner_.AsUnsigned() < limit) {
297 *value = scanner_.AsUnsigned();
298 scanner_.Next();
299 return true;
300 } else {
301 return false;
302 }
303 }
304
307 scanner_.Next();
308 return ret;
309 }
310
311 void SkipSemicolon();
312
313 VarInfo* GetVarInfo(AsmJsScanner::token_t token);
314 uint32_t VarIndex(VarInfo* info);
315 void DeclareGlobal(VarInfo* info, bool mutable_variable, AsmType* type,
316 ValueType vtype, WasmInitExpr init);
317 void DeclareStdlibFunc(VarInfo* info, VarKind kind, AsmType* type);
319 ValueType vtype, bool mutable_variable, VarInfo* info);
320
321 // Allocates a temporary local variable. The given {index} is absolute within
322 // the function body, consider using {TemporaryVariableScope} when nesting.
323 uint32_t TempVariable(int index);
324
325 // Preserves a copy of the scanner's current identifier string in the zone.
327
328 // Use to set up block stack layers (including synthetic ones for if-else).
329 // Begin/Loop/End below are implemented with these plus code generation.
331 void BareEnd();
334
335 // Use to set up actual wasm blocks/loops.
338 void End();
339
341
343 const ZoneVector<AsmType*>& params);
344
345 void ValidateModule(); // 6.1 ValidateModule
346 void ValidateModuleParameters(); // 6.1 ValidateModule - parameters
347 void ValidateModuleVars(); // 6.1 ValidateModule - variables
348 void ValidateModuleVar(bool mutable_variable);
349 void ValidateModuleVarImport(VarInfo* info, bool mutable_variable);
350 void ValidateModuleVarStdlib(VarInfo* info);
351 void ValidateModuleVarNewStdlib(VarInfo* info);
352 void ValidateModuleVarFromGlobal(VarInfo* info, bool mutable_variable);
353
354 void ValidateExport(); // 6.2 ValidateExport
355 void ValidateFunctionTable(); // 6.3 ValidateFunctionTable
356 void ValidateFunction(); // 6.4 ValidateFunction
358 void ValidateFunctionLocals(size_t param_count,
359 ZoneVector<ValueType>* locals);
360 void ValidateStatement(); // 6.5 ValidateStatement
361 void Block(); // 6.5.1 Block
362 void ExpressionStatement(); // 6.5.2 ExpressionStatement
363 void EmptyStatement(); // 6.5.3 EmptyStatement
364 void IfStatement(); // 6.5.4 IfStatement
365 void ReturnStatement(); // 6.5.5 ReturnStatement
366 bool IterationStatement(); // 6.5.6 IterationStatement
367 void WhileStatement(); // 6.5.6 IterationStatement - while
368 void DoStatement(); // 6.5.6 IterationStatement - do
369 void ForStatement(); // 6.5.6 IterationStatement - for
370 void BreakStatement(); // 6.5.7 BreakStatement
371 void ContinueStatement(); // 6.5.8 ContinueStatement
372 void LabelledStatement(); // 6.5.9 LabelledStatement
373 void SwitchStatement(); // 6.5.10 SwitchStatement
374 void ValidateCase(); // 6.6. ValidateCase
375 void ValidateDefault(); // 6.7 ValidateDefault
376 AsmType* ValidateExpression(); // 6.8 ValidateExpression
377 AsmType* Expression(AsmType* expect); // 6.8.1 Expression
378 AsmType* NumericLiteral(); // 6.8.2 NumericLiteral
379 AsmType* Identifier(); // 6.8.3 Identifier
380 AsmType* CallExpression(); // 6.8.4 CallExpression
381 AsmType* MemberExpression(); // 6.8.5 MemberExpression
382 AsmType* AssignmentExpression(); // 6.8.6 AssignmentExpression
383 AsmType* UnaryExpression(); // 6.8.7 UnaryExpression
384 AsmType* MultiplicativeExpression(); // 6.8.8 MultiplicativeExpression
385 AsmType* AdditiveExpression(); // 6.8.9 AdditiveExpression
386 AsmType* ShiftExpression(); // 6.8.10 ShiftExpression
387 AsmType* RelationalExpression(); // 6.8.11 RelationalExpression
388 AsmType* EqualityExpression(); // 6.8.12 EqualityExpression
389 AsmType* BitwiseANDExpression(); // 6.8.13 BitwiseANDExpression
390 AsmType* BitwiseXORExpression(); // 6.8.14 BitwiseXORExpression
391 AsmType* BitwiseORExpression(); // 6.8.15 BitwiseORExpression
392 AsmType* ConditionalExpression(); // 6.8.16 ConditionalExpression
393 AsmType* ParenthesizedExpression(); // 6.8.17 ParenthesiedExpression
394 AsmType* ValidateCall(); // 6.9 ValidateCall
395 bool PeekCall(); // 6.9 ValidateCall - helper
396 void ValidateHeapAccess(); // 6.10 ValidateHeapAccess
397 void ValidateFloatCoercion(); // 6.11 ValidateFloatCoercion
398
399 // Used as part of {ForStatement}. Scans forward to the next `)` in order to
400 // skip over the third expression in a for-statement. This is one piece that
401 // makes this parser not be a pure single-pass.
403
404 // Used as part of {SwitchStatement}. Collects all case labels in the current
405 // switch-statement, then resets the scanner position. This is one piece that
406 // makes this parser not be a pure single-pass.
407 void GatherCases(ZoneVector<int32_t>* cases);
408};
409
410} // namespace wasm
411} // namespace internal
412} // namespace v8
413
414#endif // V8_ASMJS_ASM_PARSER_H_
#define STDLIB_ARRAY_TYPE_LIST(V)
Definition asm-names.h:50
#define STDLIB_MATH_VALUE_LIST(V)
Definition asm-names.h:9
#define STDLIB_MATH_FUNCTION_LIST(V)
Definition asm-names.h:41
Builtins::Kind kind
Definition builtins.cc:40
uint32_t AsUnsigned() const
Definition asm-scanner.h:97
CachedVector(CachedVectors< T > *cache)
Definition asm-parser.h:156
ZoneVector< ZoneVector< T > > reusable_vectors_
Definition asm-parser.h:150
ZoneVector< BlockInfo > block_stack_
Definition asm-parser.h:202
bool CheckForUnsigned(uint32_t *value)
Definition asm-parser.h:285
AsmJsScanner::token_t Consume()
Definition asm-parser.h:305
CachedVectors< AsmJsScanner::token_t > cached_token_t_vectors_
Definition asm-parser.h:179
bool Peek(AsmJsScanner::token_t token)
Definition asm-parser.h:249
void ValidateModuleVar(bool mutable_variable)
void ValidateFunctionLocals(size_t param_count, ZoneVector< ValueType > *locals)
void ValidateModuleVarNewStdlib(VarInfo *info)
void Begin(AsmJsScanner::token_t label=0)
void GatherCases(ZoneVector< int32_t > *cases)
void ValidateModuleVarImport(VarInfo *info, bool mutable_variable)
base::Vector< VarInfo > local_var_info_
Definition asm-parser.h:174
AsmJsScanner::token_t foreign_name_
Definition asm-parser.h:193
WasmModuleBuilder * module_builder_
Definition asm-parser.h:168
int FindBreakLabelDepth(AsmJsScanner::token_t label)
AsmJsScanner::token_t stdlib_name_
Definition asm-parser.h:192
void ValidateModuleVarStdlib(VarInfo *info)
CachedVectors< int32_t > cached_int_vectors_
Definition asm-parser.h:180
AsmJsScanner::token_t pending_label_
Definition asm-parser.h:241
const StdlibSet * stdlib_uses() const
Definition asm-parser.h:59
bool CheckForUnsignedBelow(uint32_t limit, uint32_t *value)
Definition asm-parser.h:295
void DeclareStdlibFunc(VarInfo *info, VarKind kind, AsmType *type)
static const AsmJsScanner::token_t kTokenNone
Definition asm-parser.h:196
void ValidateModuleVarFromGlobal(VarInfo *info, bool mutable_variable)
const char * failure_message() const
Definition asm-parser.h:56
AsmType * Expression(AsmType *expect)
AsmJsScanner::token_t heap_name_
Definition asm-parser.h:194
base::Vector< VarInfo > global_var_info_
Definition asm-parser.h:173
bool Check(AsmJsScanner::token_t token)
Definition asm-parser.h:257
bool CheckForDouble(double *value)
Definition asm-parser.h:275
WasmFunctionBuilder * current_function_builder_
Definition asm-parser.h:169
uint32_t VarIndex(VarInfo *info)
void BareBegin(BlockKind kind, AsmJsScanner::token_t label=0)
CachedVectors< AsmType * > cached_asm_type_p_vectors_
Definition asm-parser.h:178
AsmJsParser(Zone *zone, uintptr_t stack_limit, Utf16CharacterStream *stream)
Definition asm-parser.cc:73
ZoneLinkedList< GlobalImport > global_imports_
Definition asm-parser.h:245
V(_unused0, Name, _unused1, _unused2)
void ValidateFunctionParams(ZoneVector< AsmType * > *params)
CachedVectors< ValueType > cached_valuetype_vectors_
Definition asm-parser.h:177
int FindContinueLabelDepth(AsmJsScanner::token_t label)
base::Vector< const char > CopyCurrentIdentifierString()
void AddGlobalImport(base::Vector< const char > name, AsmType *type, ValueType vtype, bool mutable_variable, VarInfo *info)
static const size_t kNoHeapAccessShift
Definition asm-parser.h:237
WasmModuleBuilder * module_builder()
Definition asm-parser.h:58
void DeclareGlobal(VarInfo *info, bool mutable_variable, AsmType *type, ValueType vtype, WasmInitExpr init)
void Loop(AsmJsScanner::token_t label=0)
FunctionSig * ConvertSignature(AsmType *return_type, const ZoneVector< AsmType * > &params)
VarInfo * GetVarInfo(AsmJsScanner::token_t token)
uint32_t TempVariable(int index)
Label label
constexpr int kNoSourcePosition
Definition globals.h:850
Definition c-api.cc:87
ZoneUnorderedMap< FunctionSig, uint32_t > cache
Definition asm-parser.h:85
FunctionImportInfo(base::Vector< const char > name, Zone *zone)
Definition asm-parser.h:88
WasmFunctionBuilder * function_builder
Definition asm-parser.h:94
FunctionImportInfo *uint32_t mask
Definition asm-parser.h:96