Line data Source code
1 : // Copyright 2016 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 SRC_ASMJS_ASM_TYPER_H_
6 : #define SRC_ASMJS_ASM_TYPER_H_
7 :
8 : #include <cstdint>
9 : #include <string>
10 : #include <unordered_map>
11 : #include <unordered_set>
12 :
13 : #include "src/allocation.h"
14 : #include "src/asmjs/asm-names.h"
15 : #include "src/asmjs/asm-types.h"
16 : #include "src/ast/ast-type-bounds.h"
17 : #include "src/ast/ast-types.h"
18 : #include "src/ast/ast.h"
19 : #include "src/effects.h"
20 : #include "src/messages.h"
21 : #include "src/type-info.h"
22 : #include "src/zone/zone-containers.h"
23 : #include "src/zone/zone.h"
24 :
25 : namespace v8 {
26 : namespace internal {
27 : namespace wasm {
28 :
29 : class AsmType;
30 : class AsmTyperHarnessBuilder;
31 : class SourceLayoutTracker;
32 :
33 : class AsmTyper final {
34 : public:
35 : enum StandardMember {
36 : kHeap = -4,
37 : kFFI = -3,
38 : kStdlib = -2,
39 : kModule = -1,
40 : kNone = 0,
41 : kInfinity,
42 : kNaN,
43 : #define V(_unused1, name, _unused2, _unused3) kMath##name,
44 : STDLIB_MATH_FUNCTION_LIST(V)
45 : #undef V
46 : #define V(name, _unused1) kMath##name,
47 : STDLIB_MATH_VALUE_LIST(V)
48 : #undef V
49 : #define V(name, _unused1, _unused2, _unused3) k##name,
50 : STDLIB_ARRAY_TYPE_LIST(V)
51 : #undef V
52 : };
53 :
54 709392 : ~AsmTyper() = default;
55 : AsmTyper(Isolate* isolate, Zone* zone, Handle<Script> script,
56 : FunctionLiteral* root);
57 :
58 : bool Validate();
59 : // Do asm.js validation in phases (to interleave with conversion to wasm).
60 : bool ValidateBeforeFunctionsPhase();
61 : bool ValidateInnerFunction(FunctionDeclaration* decl);
62 : bool ValidateAfterFunctionsPhase();
63 : void ClearFunctionNodeTypes();
64 :
65 : Handle<JSMessageObject> error_message() const { return error_message_; }
66 : const MessageLocation* message_location() const { return &message_location_; }
67 :
68 : AsmType* TriggerParsingError();
69 :
70 : AsmType* TypeOf(AstNode* node) const;
71 : AsmType* TypeOf(Variable* v) const;
72 : StandardMember VariableAsStandardMember(Variable* var);
73 :
74 : // Allow the asm-wasm-builder to trigger failures (for interleaved
75 : // validating).
76 : AsmType* FailWithMessage(const char* text);
77 :
78 : typedef std::unordered_set<StandardMember, std::hash<int> > StdlibSet;
79 :
80 : StdlibSet StdlibUses() const { return stdlib_uses_; }
81 :
82 : // Each FFI import has a usage-site signature associated with it.
83 32482 : struct FFIUseSignature {
84 : Variable* var;
85 : ZoneVector<AsmType*> arg_types_;
86 : AsmType* return_type_;
87 : FFIUseSignature(Variable* v, Zone* zone)
88 13962 : : var(v), arg_types_(zone), return_type_(nullptr) {}
89 : };
90 :
91 : const ZoneVector<FFIUseSignature>& FFIUseSignatures() {
92 : return ffi_use_signatures_;
93 : }
94 :
95 : private:
96 : friend class v8::internal::wasm::AsmTyperHarnessBuilder;
97 :
98 : class VariableInfo : public ZoneObject {
99 : public:
100 : enum Mutability {
101 : kInvalidMutability,
102 : kLocal,
103 : kMutableGlobal,
104 : // *VIOLATION* We support const variables in asm.js, as per the
105 : //
106 : // https://discourse.wicg.io/t/allow-const-global-variables/684
107 : //
108 : // Global const variables are treated as if they were numeric literals,
109 : // and can be used anywhere a literal can be used.
110 : kConstGlobal,
111 : kImmutableGlobal,
112 : };
113 :
114 13722775 : explicit VariableInfo(AsmType* t) : type_(t) {}
115 :
116 : VariableInfo* Clone(Zone* zone) const;
117 :
118 : bool IsMutable() const {
119 143987 : return mutability_ == kLocal || mutability_ == kMutableGlobal;
120 : }
121 :
122 : bool IsGlobal() const {
123 30628 : return mutability_ == kImmutableGlobal || mutability_ == kConstGlobal ||
124 : mutability_ == kMutableGlobal;
125 : }
126 :
127 : bool IsStdlib() const { return standard_member_ == kStdlib; }
128 : bool IsFFI() const { return standard_member_ == kFFI; }
129 : bool IsHeap() const { return standard_member_ == kHeap; }
130 :
131 2671 : void MarkDefined() { missing_definition_ = false; }
132 : void SetFirstForwardUse(const MessageLocation& source_location);
133 :
134 : StandardMember standard_member() const { return standard_member_; }
135 : void set_standard_member(StandardMember standard_member) {
136 13276257 : standard_member_ = standard_member;
137 : }
138 :
139 : AsmType* type() const { return type_; }
140 : void set_type(AsmType* type) { type_ = type; }
141 :
142 : Mutability mutability() const { return mutability_; }
143 13345377 : void set_mutability(Mutability mutability) { mutability_ = mutability; }
144 :
145 : bool missing_definition() const { return missing_definition_; }
146 :
147 : const MessageLocation* source_location() { return &source_location_; }
148 :
149 : static VariableInfo* ForSpecialSymbol(Zone* zone,
150 : StandardMember standard_member);
151 :
152 : private:
153 : AsmType* type_;
154 : StandardMember standard_member_ = kNone;
155 : Mutability mutability_ = kInvalidMutability;
156 : // missing_definition_ is set to true for forward definition - i.e., use
157 : // before definition.
158 : bool missing_definition_ = false;
159 : // Used for error messages.
160 : MessageLocation source_location_;
161 : };
162 :
163 : // RAII-style manager for the in_function_ member variable.
164 : struct FunctionScope {
165 : explicit FunctionScope(AsmTyper* typer) : typer_(typer) {
166 : DCHECK(!typer_->in_function_);
167 11690 : typer_->in_function_ = true;
168 : typer_->local_scope_.Clear();
169 11690 : typer_->return_type_ = AsmType::None();
170 : }
171 :
172 : ~FunctionScope() {
173 : DCHECK(typer_->in_function_);
174 11690 : typer_->in_function_ = false;
175 : }
176 :
177 : AsmTyper* typer_;
178 : };
179 :
180 : // FlattenedStatements is an iterator class for ZoneList<Statement*> that
181 : // flattens the Block construct in the AST. This is here because we need it in
182 : // the tests.
183 : class FlattenedStatements {
184 : public:
185 : explicit FlattenedStatements(Zone* zone, ZoneList<Statement*>* s);
186 : Statement* Next();
187 :
188 : private:
189 : struct Context {
190 134855 : explicit Context(ZoneList<Statement*>* s) : statements_(s) {}
191 : ZoneList<Statement*>* statements_;
192 : int next_index_ = 0;
193 : };
194 :
195 : ZoneVector<Context> context_stack_;
196 :
197 : DISALLOW_IMPLICIT_CONSTRUCTORS(FlattenedStatements);
198 : };
199 :
200 : class SourceLayoutTracker {
201 : public:
202 : SourceLayoutTracker() = default;
203 : bool IsValid() const;
204 4542 : void AddUseAsm(const AstNode& node) { use_asm_.AddNewElement(node); }
205 13738 : void AddGlobal(const AstNode& node) { globals_.AddNewElement(node); }
206 11089 : void AddFunction(const AstNode& node) { functions_.AddNewElement(node); }
207 264 : void AddTable(const AstNode& node) { tables_.AddNewElement(node); }
208 3677 : void AddExport(const AstNode& node) { exports_.AddNewElement(node); }
209 :
210 : private:
211 : class Section {
212 : public:
213 : Section() = default;
214 : Section(const Section&) = default;
215 : Section& operator=(const Section&) = default;
216 :
217 : void AddNewElement(const AstNode& node);
218 : bool IsPrecededBy(const Section& other) const;
219 :
220 : private:
221 : int start_ = kNoSourcePosition;
222 : int end_ = kNoSourcePosition;
223 : };
224 :
225 : Section use_asm_;
226 : Section globals_;
227 : Section functions_;
228 : Section tables_;
229 : Section exports_;
230 :
231 : DISALLOW_COPY_AND_ASSIGN(SourceLayoutTracker);
232 : };
233 :
234 : using ObjectTypeMap = ZoneMap<std::string, VariableInfo*>;
235 : void InitializeStdlib();
236 : void SetTypeOf(AstNode* node, AsmType* type);
237 :
238 : void AddForwardReference(VariableProxy* proxy, VariableInfo* info);
239 : bool AddGlobal(Variable* global, VariableInfo* info);
240 : bool AddLocal(Variable* global, VariableInfo* info);
241 : // Used for 5.5 GlobalVariableTypeAnnotations
242 : VariableInfo* ImportLookup(Property* expr);
243 : // 3.3 Environment Lookup
244 : // NOTE: In the spec, the lookup function's prototype is
245 : //
246 : // Lookup(Delta, Gamma, x)
247 : //
248 : // Delta is the global_scope_ member, and Gamma, local_scope_.
249 : VariableInfo* Lookup(Variable* variable) const;
250 :
251 : // All of the ValidateXXX methods below return AsmType::None() in case of
252 : // validation failure.
253 :
254 : // 6.1 ValidateModule
255 : AsmType* ValidateModuleBeforeFunctionsPhase(FunctionLiteral* fun);
256 : AsmType* ValidateModuleFunction(FunctionDeclaration* fun_decl);
257 : AsmType* ValidateModuleFunctions(FunctionLiteral* fun);
258 : AsmType* ValidateModuleAfterFunctionsPhase(FunctionLiteral* fun);
259 : AsmType* ValidateGlobalDeclaration(Assignment* assign);
260 : // 6.2 ValidateExport
261 : AsmType* ExportType(VariableProxy* fun_export);
262 : AsmType* ValidateExport(ReturnStatement* exports);
263 : // 6.3 ValidateFunctionTable
264 : AsmType* ValidateFunctionTable(Assignment* assign);
265 : // 6.4 ValidateFunction
266 : AsmType* ValidateFunction(FunctionDeclaration* fun_decl);
267 : // 6.5 ValidateStatement
268 : AsmType* ValidateStatement(Statement* statement);
269 : // 6.5.1 BlockStatement
270 : AsmType* ValidateBlockStatement(Block* block);
271 : // 6.5.2 ExpressionStatement
272 : AsmType* ValidateExpressionStatement(ExpressionStatement* expr);
273 : // 6.5.3 EmptyStatement
274 : AsmType* ValidateEmptyStatement(EmptyStatement* empty);
275 : // 6.5.4 IfStatement
276 : AsmType* ValidateIfStatement(IfStatement* if_stmt);
277 : // 6.5.5 ReturnStatement
278 : AsmType* ValidateReturnStatement(ReturnStatement* ret_stmt);
279 : // 6.5.6 IterationStatement
280 : // 6.5.6.a WhileStatement
281 : AsmType* ValidateWhileStatement(WhileStatement* while_stmt);
282 : // 6.5.6.b DoWhileStatement
283 : AsmType* ValidateDoWhileStatement(DoWhileStatement* do_while);
284 : // 6.5.6.c ForStatement
285 : AsmType* ValidateForStatement(ForStatement* for_stmt);
286 : // 6.5.7 BreakStatement
287 : AsmType* ValidateBreakStatement(BreakStatement* brk_stmt);
288 : // 6.5.8 ContinueStatement
289 : AsmType* ValidateContinueStatement(ContinueStatement* cont_stmt);
290 : // 6.5.9 LabelledStatement
291 : // NOTE: we don't need to handle these: Labelled statements are
292 : // BreakableStatements in our AST, but BreakableStatement is not a concrete
293 : // class -- and we're handling all of BreakableStatement's subclasses.
294 : // 6.5.10 SwitchStatement
295 : AsmType* ValidateSwitchStatement(SwitchStatement* stmt);
296 : // 6.6 ValidateCase
297 : AsmType* ValidateCase(CaseClause* label, int32_t* case_lbl);
298 : // 6.7 ValidateDefault
299 : AsmType* ValidateDefault(CaseClause* label);
300 : // 6.8 ValidateExpression
301 : AsmType* ValidateExpression(Expression* expr);
302 : AsmType* ValidateCompareOperation(CompareOperation* cmp);
303 : AsmType* ValidateBinaryOperation(BinaryOperation* binop);
304 : // 6.8.1 Expression
305 : AsmType* ValidateCommaExpression(BinaryOperation* comma);
306 : // 6.8.2 NumericLiteral
307 : AsmType* ValidateNumericLiteral(Literal* literal);
308 : // 6.8.3 Identifier
309 : AsmType* ValidateIdentifier(VariableProxy* proxy);
310 : // 6.8.4 CallExpression
311 : AsmType* ValidateCallExpression(Call* call);
312 : // 6.8.5 MemberExpression
313 : AsmType* ValidateMemberExpression(Property* prop);
314 : // 6.8.6 AssignmentExpression
315 : AsmType* ValidateAssignmentExpression(Assignment* assignment);
316 : // 6.8.7 UnaryExpression
317 : AsmType* ValidateUnaryExpression(UnaryOperation* unop);
318 : // 6.8.8 MultiplicativeExpression
319 : AsmType* ValidateMultiplicativeExpression(BinaryOperation* binop);
320 : // 6.8.9 AdditiveExpression
321 : AsmType* ValidateAdditiveExpression(BinaryOperation* binop,
322 : uint32_t intish_count);
323 : // 6.8.10 ShiftExpression
324 : AsmType* ValidateShiftExpression(BinaryOperation* binop);
325 : // 6.8.11 RelationalExpression
326 : AsmType* ValidateRelationalExpression(CompareOperation* cmpop);
327 : // 6.8.12 EqualityExpression
328 : AsmType* ValidateEqualityExpression(CompareOperation* cmpop);
329 : // 6.8.13 BitwiseANDExpression
330 : AsmType* ValidateBitwiseANDExpression(BinaryOperation* binop);
331 : // 6.8.14 BitwiseXORExpression
332 : AsmType* ValidateBitwiseXORExpression(BinaryOperation* binop);
333 : // 6.8.15 BitwiseORExpression
334 : AsmType* ValidateBitwiseORExpression(BinaryOperation* binop);
335 : // 6.8.16 ConditionalExpression
336 : AsmType* ValidateConditionalExpression(Conditional* cond);
337 : // 6.9 ValidateCall
338 : AsmType* ValidateCall(AsmType* return_type, Call* call);
339 : // 6.10 ValidateHeapAccess
340 : enum HeapAccessType { LoadFromHeap, StoreToHeap };
341 : AsmType* ValidateHeapAccess(Property* heap, HeapAccessType access_type);
342 : // 6.11 ValidateFloatCoercion
343 : bool IsCallToFround(Call* call);
344 : AsmType* ValidateFloatCoercion(Call* call);
345 :
346 : // 5.1 ParameterTypeAnnotations
347 : AsmType* ParameterTypeAnnotations(Variable* parameter,
348 : Expression* annotation);
349 : // 5.2 ReturnTypeAnnotations
350 : AsmType* ReturnTypeAnnotations(Expression* ret_expr);
351 : // 5.4 VariableTypeAnnotations
352 : // 5.5 GlobalVariableTypeAnnotations
353 : AsmType* VariableTypeAnnotations(
354 : Expression* initializer,
355 : VariableInfo::Mutability global = VariableInfo::kLocal);
356 : AsmType* ImportExpression(Property* import);
357 : AsmType* NewHeapView(CallNew* new_heap_view);
358 :
359 : Isolate* isolate_;
360 : Zone* zone_;
361 : Handle<Script> script_;
362 : FunctionLiteral* root_;
363 : bool in_function_ = false;
364 :
365 : AsmType* return_type_ = nullptr;
366 :
367 : ZoneVector<VariableInfo*> forward_definitions_;
368 : ZoneVector<FFIUseSignature> ffi_use_signatures_;
369 : ObjectTypeMap stdlib_types_;
370 : ObjectTypeMap stdlib_math_types_;
371 :
372 : // The ASM module name. This member is used to prevent globals from redefining
373 : // the module name.
374 : VariableInfo* module_info_;
375 : Handle<String> module_name_;
376 :
377 : // 3 Environments
378 : ZoneHashMap global_scope_; // 3.1 Global environment
379 : ZoneHashMap local_scope_; // 3.2 Variable environment
380 :
381 : std::uintptr_t stack_limit_;
382 : bool stack_overflow_ = false;
383 : std::unordered_map<AstNode*, AsmType*> module_node_types_;
384 : std::unordered_map<AstNode*, AsmType*> function_node_types_;
385 : static const int kErrorMessageLimit = 128;
386 : AsmType* fround_type_;
387 : AsmType* ffi_type_;
388 : Handle<JSMessageObject> error_message_;
389 : MessageLocation message_location_;
390 : StdlibSet stdlib_uses_;
391 :
392 : SourceLayoutTracker source_layout_;
393 : ReturnStatement* module_return_;
394 : ZoneVector<Assignment*> function_pointer_tables_;
395 :
396 : DISALLOW_IMPLICIT_CONSTRUCTORS(AsmTyper);
397 : };
398 :
399 : } // namespace wasm
400 : } // namespace internal
401 : } // namespace v8
402 :
403 : #endif // SRC_ASMJS_ASM_TYPER_H_
|