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