Home | History | Annotate | Download | only in asmjs
      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 
     22 namespace v8 {
     23 namespace internal {
     24 namespace wasm {
     25 
     26 class AsmType;
     27 class AsmTyperHarnessBuilder;
     28 
     29 class 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