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