1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved. 2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file. 4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-typer.h" 6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <algorithm> 8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <limits> 9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory> 10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <string> 11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "include/v8.h" 13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/v8.h" 14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/asmjs/asm-types.h" 16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/ast/ast.h" 17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/ast/scopes.h" 18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/base/bits.h" 19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/codegen.h" 20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/globals.h" 2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/messages.h" 2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/utils.h" 2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/vector.h" 2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define FAIL_LOCATION_RAW(location, msg) \ 2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch do { \ 2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<String> message( \ 2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate_->factory()->InternalizeOneByteString(msg)); \ 3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch error_message_ = MessageHandler::MakeMessageObject( \ 3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate_, MessageTemplate::kAsmJsInvalid, (location), message, \ 3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<JSArray>::null()); \ 3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch error_message_->set_error_level(v8::Isolate::kMessageWarning); \ 3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch message_location_ = *(location); \ 3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AsmType::None(); \ 3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } while (false) 37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define FAIL_RAW(node, msg) \ 3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch do { \ 4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MessageLocation location(script_, node->position(), node->position()); \ 4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL_LOCATION_RAW(&location, msg); \ 42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (false) 43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define FAIL_LOCATION(location, msg) \ 4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL_LOCATION_RAW(location, STATIC_CHAR_VECTOR(msg)) 4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define FAIL(node, msg) FAIL_RAW(node, STATIC_CHAR_VECTOR(msg)) 4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define RECURSE(call) \ 50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (GetCurrentStackPosition() < stack_limit_) { \ 52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stack_overflow_ = true; \ 53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(root_, "Stack overflow while parsing asm.js module."); \ 54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch \ 56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* result = (call); \ 57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (stack_overflow_) { \ 58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::None(); \ 59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch \ 61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (result == AsmType::None()) { \ 62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::None(); \ 63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (false) 65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace v8 { 67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace internal { 68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace wasm { 69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochstatic const uint32_t LargestFixNum = std::numeric_limits<int32_t>::max(); 71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochusing v8::internal::AstNode; 74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochusing v8::internal::GetCurrentStackPosition; 75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ---------------------------------------------------------------------------- 77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Implementation of AsmTyper::FlattenedStatements 78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmTyper::FlattenedStatements::FlattenedStatements(Zone* zone, 80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneList<Statement*>* s) 81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch : context_stack_(zone) { 82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch context_stack_.emplace_back(Context(s)); 83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochStatement* AsmTyper::FlattenedStatements::Next() { 86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (;;) { 87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (context_stack_.empty()) { 88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Context* current = &context_stack_.back(); 92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (current->statements_->length() <= current->next_index_) { 94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch context_stack_.pop_back(); 95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Statement* current_statement = 99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch current->statements_->at(current->next_index_++); 100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (current_statement->IsBlock()) { 101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch context_stack_.emplace_back( 102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Context(current_statement->AsBlock()->statements())); 103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return current_statement; 107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ---------------------------------------------------------------------------- 11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Implementation of AsmTyper::SourceLayoutTracker 11262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool AsmTyper::SourceLayoutTracker::IsValid() const { 11462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const Section* kAllSections[] = {&use_asm_, &globals_, &functions_, &tables_, 11562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &exports_}; 11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t ii = 0; ii < arraysize(kAllSections); ++ii) { 11762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const auto& curr_section = *kAllSections[ii]; 11862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t jj = ii + 1; jj < arraysize(kAllSections); ++jj) { 11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (curr_section.IsPrecededBy(*kAllSections[jj])) { 12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return true; 12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid AsmTyper::SourceLayoutTracker::Section::AddNewElement( 12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const AstNode& node) { 12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const int node_pos = node.position(); 13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (start_ == kNoSourcePosition) { 13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch start_ = node_pos; 13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch start_ = std::min(start_, node_pos); 13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (end_ == kNoSourcePosition) { 13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch end_ = node_pos; 13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch end_ = std::max(end_, node_pos); 13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 14062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 14162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool AsmTyper::SourceLayoutTracker::Section::IsPrecededBy( 14362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const Section& other) const { 14462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (start_ == kNoSourcePosition) { 14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(end_, kNoSourcePosition); 14662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 14762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 14862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (other.start_ == kNoSourcePosition) { 14962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(other.end_, kNoSourcePosition); 15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_LE(start_, end_); 15362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_LE(other.start_, other.end_); 15462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return other.start_ <= end_; 15562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// ---------------------------------------------------------------------------- 158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Implementation of AsmTyper::VariableInfo 159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmTyper::VariableInfo* AsmTyper::VariableInfo::ForSpecialSymbol( 161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Zone* zone, StandardMember standard_member) { 162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(standard_member == kStdlib || standard_member == kFFI || 163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch standard_member == kHeap || standard_member == kModule); 164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* new_var_info = new (zone) VariableInfo(AsmType::None()); 165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch new_var_info->standard_member_ = standard_member; 166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch new_var_info->mutability_ = kImmutableGlobal; 167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return new_var_info; 168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmTyper::VariableInfo* AsmTyper::VariableInfo::Clone(Zone* zone) const { 171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CHECK(standard_member_ != kNone); 172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CHECK(!type_->IsA(AsmType::None())); 173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* new_var_info = new (zone) VariableInfo(type_); 174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch new_var_info->standard_member_ = standard_member_; 175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch new_var_info->mutability_ = mutability_; 176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return new_var_info; 177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 17962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid AsmTyper::VariableInfo::SetFirstForwardUse( 18062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch const MessageLocation& source_location) { 181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch missing_definition_ = true; 18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_location_ = source_location; 183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ---------------------------------------------------------------------------- 186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Implementation of AsmTyper 187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Handle<Script> script, 189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FunctionLiteral* root) 190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch : isolate_(isolate), 191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch zone_(zone), 192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch script_(script), 193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch root_(root), 194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch forward_definitions_(zone), 195f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ffi_use_signatures_(zone), 196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_types_(zone), 197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_math_types_(zone), 198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch module_info_(VariableInfo::ForSpecialSymbol(zone_, kModule)), 199f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch global_scope_(ZoneHashMap::kDefaultHashMapCapacity, 200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneAllocationPolicy(zone)), 201f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch local_scope_(ZoneHashMap::kDefaultHashMapCapacity, 202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneAllocationPolicy(zone)), 203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stack_limit_(isolate->stack_guard()->real_climit()), 204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fround_type_(AsmType::FroundType(zone_)), 20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ffi_type_(AsmType::FFIType(zone_)), 20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function_pointer_tables_(zone_) { 207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch InitializeStdlib(); 208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool ValidAsmIdentifier(Handle<String> name) { 212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static const char* kInvalidAsmNames[] = {"eval", "arguments"}; 213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) { 215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) { 216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return true; 220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid AsmTyper::InitializeStdlib() { 224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* d = AsmType::Double(); 225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* dq = AsmType::DoubleQ(); 226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* dq2d = AsmType::Function(zone_, d); 227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch dq2d->AsFunctionType()->AddArgument(dq); 228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* dqdq2d = AsmType::Function(zone_, d); 230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch dqdq2d->AsFunctionType()->AddArgument(dq); 231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch dqdq2d->AsFunctionType()->AddArgument(dq); 232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* f = AsmType::Float(); 234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fq = AsmType::FloatQ(); 235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fq2f = AsmType::Function(zone_, f); 236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fq2f->AsFunctionType()->AddArgument(fq); 237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* s = AsmType::Signed(); 239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* s2s = AsmType::Function(zone_, s); 240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch s2s->AsFunctionType()->AddArgument(s); 241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* i = AsmType::Int(); 243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* i2s = AsmType::Function(zone_, s); 244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch i2s->AsFunctionType()->AddArgument(i); 245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* ii2s = AsmType::Function(zone_, s); 247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ii2s->AsFunctionType()->AddArgument(i); 248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ii2s->AsFunctionType()->AddArgument(i); 249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* minmax_d = AsmType::MinMaxType(zone_, d, d); 251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* The float variant is not part of the spec, but firefox accepts 252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // it. 253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* minmax_f = AsmType::MinMaxType(zone_, f, f); 254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* minmax_i = AsmType::MinMaxType(zone_, s, i); 255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* minmax = AsmType::OverloadedFunction(zone_); 256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch minmax->AsOverloadedFunctionType()->AddOverload(minmax_i); 257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch minmax->AsOverloadedFunctionType()->AddOverload(minmax_f); 258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch minmax->AsOverloadedFunctionType()->AddOverload(minmax_d); 259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fround = fround_type_; 261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* abs = AsmType::OverloadedFunction(zone_); 263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch abs->AsOverloadedFunctionType()->AddOverload(s2s); 264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch abs->AsOverloadedFunctionType()->AddOverload(dq2d); 265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch abs->AsOverloadedFunctionType()->AddOverload(fq2f); 266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* ceil = AsmType::OverloadedFunction(zone_); 268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ceil->AsOverloadedFunctionType()->AddOverload(dq2d); 269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ceil->AsOverloadedFunctionType()->AddOverload(fq2f); 270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* floor = ceil; 272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* sqrt = ceil; 273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch struct StandardMemberInitializer { 275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const char* name; 276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StandardMember standard_member; 277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type; 278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch }; 279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const StandardMemberInitializer stdlib[] = {{"Infinity", kInfinity, d}, 281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"NaN", kNaN, d}, 282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define ASM_TYPED_ARRAYS(V) \ 283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Uint8) \ 284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Int8) \ 285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Uint16) \ 286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Int16) \ 287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Uint32) \ 288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Int32) \ 289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Float32) \ 290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch V(Float64) 291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define ASM_TYPED_ARRAY(TypeName) \ 293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {#TypeName "Array", kNone, AsmType::TypeName##Array()}, 294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ASM_TYPED_ARRAYS(ASM_TYPED_ARRAY) 295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef ASM_TYPED_ARRAY 296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch }; 297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (size_t ii = 0; ii < arraysize(stdlib); ++ii) { 298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_types_[stdlib[ii].name] = new (zone_) VariableInfo(stdlib[ii].type); 299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_types_[stdlib[ii].name]->set_standard_member( 300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib[ii].standard_member); 301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_types_[stdlib[ii].name]->set_mutability( 302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch VariableInfo::kImmutableGlobal); 303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const StandardMemberInitializer math[] = { 306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"PI", kMathPI, d}, 307f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"E", kMathE, d}, 308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"LN2", kMathLN2, d}, 309f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"LN10", kMathLN10, d}, 310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"LOG2E", kMathLOG2E, d}, 311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"LOG10E", kMathLOG10E, d}, 312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"SQRT2", kMathSQRT2, d}, 313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"SQRT1_2", kMathSQRT1_2, d}, 314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"imul", kMathImul, ii2s}, 315f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"abs", kMathAbs, abs}, 316f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // NOTE: clz32 should return fixnum. The current typer can only return 317f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Signed, Float, or Double, so it returns Signed in our version of 318f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // asm.js. 319f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"clz32", kMathClz32, i2s}, 320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"ceil", kMathCeil, ceil}, 321f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"floor", kMathFloor, floor}, 322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"fround", kMathFround, fround}, 323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"pow", kMathPow, dqdq2d}, 324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"exp", kMathExp, dq2d}, 325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"log", kMathLog, dq2d}, 326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"min", kMathMin, minmax}, 327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"max", kMathMax, minmax}, 328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"sqrt", kMathSqrt, sqrt}, 329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"cos", kMathCos, dq2d}, 330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"sin", kMathSin, dq2d}, 331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"tan", kMathTan, dq2d}, 332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"acos", kMathAcos, dq2d}, 333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"asin", kMathAsin, dq2d}, 334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"atan", kMathAtan, dq2d}, 335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {"atan2", kMathAtan2, dqdq2d}, 336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch }; 337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (size_t ii = 0; ii < arraysize(math); ++ii) { 338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_math_types_[math[ii].name] = new (zone_) VariableInfo(math[ii].type); 339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_math_types_[math[ii].name]->set_standard_member( 340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch math[ii].standard_member); 341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_math_types_[math[ii].name]->set_mutability( 342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch VariableInfo::kImmutableGlobal); 343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Used for 5.5 GlobalVariableTypeAnnotations 347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmTyper::VariableInfo* AsmTyper::ImportLookup(Property* import) { 348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* obj = import->obj(); 349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* key = import->key()->AsLiteral(); 35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (key == nullptr) { 35162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return nullptr; 35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ObjectTypeMap* stdlib = &stdlib_types_; 355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* obj_as_property = obj->AsProperty()) { 356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // This can only be stdlib.Math 357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* math_name = obj_as_property->key()->AsLiteral(); 358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (math_name == nullptr || !math_name->IsPropertyName()) { 359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!math_name->AsPropertyName()->IsUtf8EqualTo(CStrVector("Math"))) { 363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* stdlib_var_proxy = obj_as_property->obj()->AsVariableProxy(); 367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (stdlib_var_proxy == nullptr) { 368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch obj = stdlib_var_proxy; 371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib = &stdlib_math_types_; 372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* obj_as_var_proxy = obj->AsVariableProxy(); 375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj_as_var_proxy == nullptr) { 376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* obj_info = Lookup(obj_as_var_proxy->var()); 380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj_info == nullptr) { 381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj_info->IsFFI()) { 385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // For FFI we can't validate import->key, so assume this is OK. 386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_info; 387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!key->IsPropertyName()) { 39062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return nullptr; 39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 39262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch std::unique_ptr<char[]> aname = key->AsPropertyName()->ToCString(); 394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ObjectTypeMap::iterator i = stdlib->find(std::string(aname.get())); 395f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (i == stdlib->end()) { 396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdlib_uses_.insert(i->second->standard_member()); 399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return i->second; 400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 402f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochAsmTyper::VariableInfo* AsmTyper::Lookup(Variable* variable) const { 403f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const ZoneHashMap* scope = in_function_ ? &local_scope_ : &global_scope_; 404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneHashMap::Entry* entry = 405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch scope->Lookup(variable, ComputePointerHash(variable)); 406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (entry == nullptr && in_function_) { 407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch entry = global_scope_.Lookup(variable, ComputePointerHash(variable)); 408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 410f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (entry == nullptr && !module_name_.is_null() && 411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch module_name_->Equals(*variable->name())) { 412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return module_info_; 413f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 415f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr; 416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 417f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid AsmTyper::AddForwardReference(VariableProxy* proxy, VariableInfo* info) { 41962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MessageLocation location(script_, proxy->position(), proxy->position()); 42062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch info->SetFirstForwardUse(location); 421f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch forward_definitions_.push_back(info); 422f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool AsmTyper::AddGlobal(Variable* variable, VariableInfo* info) { 425f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We can't DCHECK(!in_function_) because function may actually install global 426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // names (forward defined functions and function tables.) 427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(info->mutability() != VariableInfo::kInvalidMutability); 428f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(info->IsGlobal()); 429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(ValidAsmIdentifier(variable->name())); 430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 431f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!module_name_.is_null() && module_name_->Equals(*variable->name())) { 432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneHashMap::Entry* entry = global_scope_.LookupOrInsert( 436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone_)); 437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (entry->value != nullptr) { 439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch entry->value = info; 443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return true; 444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool AsmTyper::AddLocal(Variable* variable, VariableInfo* info) { 447f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(in_function_); 448f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(info->mutability() != VariableInfo::kInvalidMutability); 449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!info->IsGlobal()); 450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(ValidAsmIdentifier(variable->name())); 451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneHashMap::Entry* entry = local_scope_.LookupOrInsert( 453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone_)); 454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 455f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (entry->value != nullptr) { 456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch entry->value = info; 460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return true; 461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid AsmTyper::SetTypeOf(AstNode* node, AsmType* type) { 464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_NE(type, AsmType::None()); 46562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (in_function_) { 46662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(function_node_types_.find(node) == function_node_types_.end()); 46762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function_node_types_.insert(std::make_pair(node, type)); 46862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 46962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(module_node_types_.find(node) == module_node_types_.end()); 47062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch module_node_types_.insert(std::make_pair(node, type)); 47162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 47262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 47362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 47462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace { 47562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsLiteralDouble(Literal* literal) { 47662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return literal->raw_value()->IsNumber() && 47762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch literal->raw_value()->ContainsDot(); 47862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 47962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 48062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsLiteralInt(Literal* literal) { 48162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return literal->raw_value()->IsNumber() && 48262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch !literal->raw_value()->ContainsDot(); 48362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 48462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsLiteralMinus1(Literal* literal) { 48662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteralInt(literal) && literal->raw_value()->AsNumber() == -1.0; 487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 48962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsLiteral1Dot0(Literal* literal) { 49062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteralDouble(literal) && literal->raw_value()->AsNumber() == 1.0; 49162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 49362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool IsLiteral0(Literal* literal) { 49462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteralInt(literal) && literal->raw_value()->AsNumber() == 0.0; 49562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 49662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace 49762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::TypeOf(AstNode* node) const { 49962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch auto node_type_iter = function_node_types_.find(node); 50062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (node_type_iter != function_node_types_.end()) { 50162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return node_type_iter->second; 50262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 50362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch node_type_iter = module_node_types_.find(node); 50462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (node_type_iter != module_node_types_.end()) { 505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return node_type_iter->second; 506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Sometimes literal nodes are not added to the node_type_ map simply because 509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // their are not visited with ValidateExpression(). 510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* literal = node->AsLiteral()) { 51162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsLiteralDouble(literal)) { 512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 51462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(literal)) { 51562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AsmType::None(); 51662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t u; 518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (literal->value()->ToUint32(&u)) { 519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (u > LargestFixNum) { 520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Unsigned(); 521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::FixNum(); 523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t i; 525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (literal->value()->ToInt32(&i)) { 526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Signed(); 527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::None(); 531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochAsmType* AsmTyper::TypeOf(Variable* v) const { return Lookup(v)->type(); } 534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmTyper::StandardMember AsmTyper::VariableAsStandardMember(Variable* var) { 536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_info = Lookup(var); 537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_info == nullptr) { 538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return kNone; 539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StandardMember member = var_info->standard_member(); 541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return member; 542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 54462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::FailWithMessage(const char* text) { 54562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL_RAW(root_, OneByteVector(text)); 54662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 54762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool AsmTyper::Validate() { 54962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return ValidateBeforeFunctionsPhase() && 55062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch !AsmType::None()->IsExactly(ValidateModuleFunctions(root_)) && 55162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ValidateAfterFunctionsPhase(); 55262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 55362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 55462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool AsmTyper::ValidateBeforeFunctionsPhase() { 55562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!AsmType::None()->IsExactly(ValidateModuleBeforeFunctionsPhase(root_))) { 556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return true; 557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 56162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool AsmTyper::ValidateInnerFunction(FunctionDeclaration* fun_decl) { 56262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!AsmType::None()->IsExactly(ValidateModuleFunction(fun_decl))) { 56362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return true; 56462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 56662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 56762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 56862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool AsmTyper::ValidateAfterFunctionsPhase() { 56962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!AsmType::None()->IsExactly(ValidateModuleAfterFunctionsPhase(root_))) { 57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return true; 57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 57262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return false; 57362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 57462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 57562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid AsmTyper::ClearFunctionNodeTypes() { function_node_types_.clear(); } 57662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 57762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::TriggerParsingError() { FAIL(root_, "Parsing error"); } 57862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool IsUseAsmDirective(Statement* first_statement) { 581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExpressionStatement* use_asm = first_statement->AsExpressionStatement(); 582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (use_asm == nullptr) { 583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Literal* use_asm_literal = use_asm->expression()->AsLiteral(); 587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (use_asm_literal == nullptr) { 589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm"); 593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAssignment* ExtractInitializerExpression(Statement* statement) { 596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* expr_stmt = statement->AsExpressionStatement(); 597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (expr_stmt == nullptr) { 598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with initializers. 599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* assign = expr_stmt->expression()->AsAssignment(); 602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assign == nullptr) { 603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with initializers. 604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assign->op() != Token::INIT) { 607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with initializers. 608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return assign; 611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.1 ValidateModule 61662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::ValidateModuleBeforeFunctionsPhase(FunctionLiteral* fun) { 617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DeclarationScope* scope = fun->scope(); 618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!scope->is_function_scope()) FAIL(fun, "Not at function scope."); 61962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (scope->inner_scope_calls_eval()) { 62062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(fun, "Invalid asm.js module using eval."); 62162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(fun->name())) 623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Invalid asm.js identifier in module name."); 624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch module_name_ = fun->name(); 625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Allowed parameters: Stdlib, FFI, Mem 627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch static const int MaxModuleParameters = 3; 628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (scope->num_parameters() > MaxModuleParameters) { 629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "asm.js modules may not have more than three parameters."); 630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch struct { 633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch StandardMember standard_member; 634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } kModuleParamInfo[3] = { 635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch {kStdlib}, {kFFI}, {kHeap}, 636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch }; 637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int ii = 0; ii < scope->num_parameters(); ++ii) { 639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* param = scope->parameter(ii); 640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(param); 641f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(param->name())) { 643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Invalid asm.js identifier in module parameter."); 644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* param_info = VariableInfo::ForSpecialSymbol( 647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch zone_, kModuleParamInfo[ii].standard_member); 648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddGlobal(param, param_info)) { 650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Redeclared identifier in module parameter."); 651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FlattenedStatements iter(zone_, fun->body()); 655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* use_asm_directive = iter.Next(); 656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (use_asm_directive == nullptr) { 657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Missing \"use asm\"."); 658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check for extra assignment inserted by the parser when in this form: 660f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // (function Module(a, b, c) {... }) 661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExpressionStatement* estatement = use_asm_directive->AsExpressionStatement(); 662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (estatement != nullptr) { 663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Assignment* assignment = estatement->expression()->AsAssignment(); 664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assignment != nullptr && assignment->target()->IsVariableProxy() && 665f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch assignment->target() 666f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ->AsVariableProxy() 667f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ->var() 668f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ->is_sloppy_function_name()) { 669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch use_asm_directive = iter.Next(); 670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IsUseAsmDirective(use_asm_directive)) { 673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Missing \"use asm\"."); 674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 67562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_layout_.AddUseAsm(*use_asm_directive); 67662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch module_return_ = nullptr; 677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* The spec states that globals should be followed by function 679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // declarations, which should be followed by function pointer tables, followed 680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // by the module export (return) statement. Our AST might be rearraged by the 681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // parser, so we can't rely on it being in source code order. 682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch while (Statement* current = iter.Next()) { 683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* assign = ExtractInitializerExpression(current)) { 684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assign->value()->IsArrayLiteral()) { 685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Save function tables for later validation. 68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch function_pointer_tables_.push_back(assign); 687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateGlobalDeclaration(assign)); 68962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_layout_.AddGlobal(*assign); 690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 693f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* current_as_return = current->AsReturnStatement()) { 69562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (module_return_ != nullptr) { 696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Multiple export statements."); 697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 69862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch module_return_ = current_as_return; 69962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_layout_.AddExport(*module_return_); 700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(current, "Invalid top-level statement in asm.js module."); 704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 70662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AsmType::Int(); // Any type that is not AsmType::None(); 70762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 70862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 70962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::ValidateModuleFunction(FunctionDeclaration* fun_decl) { 71062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(ValidateFunction(fun_decl)); 71162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_layout_.AddFunction(*fun_decl); 71262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 71362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AsmType::Int(); // Any type that is not AsmType::None(); 71462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 71562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 71662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::ValidateModuleFunctions(FunctionLiteral* fun) { 71762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DeclarationScope* scope = fun->scope(); 718c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Declaration::List* decls = scope->declarations(); 719c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (Declaration* decl : *decls) { 720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration()) { 72162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(ValidateModuleFunction(fun_decl)); 722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 72662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AsmType::Int(); // Any type that is not AsmType::None(); 72762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 72862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 72962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::ValidateModuleAfterFunctionsPhase(FunctionLiteral* fun) { 73062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (auto* function_table : function_pointer_tables_) { 731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateFunctionTable(function_table)); 73262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch source_layout_.AddTable(*function_table); 733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 73562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DeclarationScope* scope = fun->scope(); 73662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Declaration::List* decls = scope->declarations(); 737c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (Declaration* decl : *decls) { 738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (decl->IsFunctionDeclaration()) { 739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch VariableDeclaration* var_decl = decl->AsVariableDeclaration(); 743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_decl == nullptr) { 744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(decl, "Invalid asm.js declaration."); 745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_proxy = var_decl->proxy(); 748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_proxy == nullptr) { 749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(decl, "Invalid asm.js declaration."); 750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (Lookup(var_proxy->var()) == nullptr) { 753f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(decl, "Global variable missing initializer in asm.js module."); 754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 6.2 ValidateExport 75862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (module_return_ == nullptr) { 759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Missing asm.js module export."); 760f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* forward_def : forward_definitions_) { 763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (forward_def->missing_definition()) { 76462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL_LOCATION(forward_def->source_location(), 76562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "Missing definition for forward declared identifier."); 766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 76962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(ValidateExport(module_return_)); 770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!source_layout_.IsValid()) { 772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun, "Invalid asm.js source code layout."); 773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 775f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Int(); // Any type that is not AsmType::None(); 776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 778f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool IsDoubleAnnotation(BinaryOperation* binop) { 780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* The parser replaces uses of +x with x*1.0. 781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::MUL) { 782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right_as_literal = binop->right()->AsLiteral(); 786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (right_as_literal == nullptr) { 787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 789f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 79062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteral1Dot0(right_as_literal); 791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool IsIntAnnotation(BinaryOperation* binop) { 794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::BIT_OR) { 795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 797f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right_as_literal = binop->right()->AsLiteral(); 799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (right_as_literal == nullptr) { 800f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteral0(right_as_literal); 804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 806f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 807f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) { 808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!assign->is_compound()); 809f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assign->is_compound()) { 810f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, 811f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Compound assignment not supported when declaring global variables."); 812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target = assign->target(); 815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target->IsVariableProxy()) { 816f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target, "Module assignments may only assign to globals."); 817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target_variable = target->AsVariableProxy()->var(); 819f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target_info = Lookup(target_variable); 820f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info != nullptr) { 822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target, "Redefined global variable."); 823f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 825f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* value = assign->value(); 826f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Not all types of assignment are allowed by asm.js. See 827f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 5.5 Global Variable Type Annotations. 828f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool global_variable = false; 829f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (value->IsLiteral() || value->IsCall()) { 830f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type = nullptr; 831c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableInfo::Mutability mutability; 832c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (target_variable->mode() == CONST) { 833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mutability = VariableInfo::kConstGlobal; 834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mutability = VariableInfo::kMutableGlobal; 836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RECURSE(type = VariableTypeAnnotations(value, mutability)); 838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = new (zone_) VariableInfo(type); 839c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch target_info->set_mutability(mutability); 840f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch global_variable = true; 841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (value->IsProperty()) { 842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = ImportLookup(value->AsProperty()); 843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info == nullptr) { 844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Invalid import."); 845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); 847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info->IsFFI()) { 848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // create a new target info that represents a foreign variable. 849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = new (zone_) VariableInfo(ffi_type_); 850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info->set_mutability(VariableInfo::kImmutableGlobal); 851f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (target_info->type()->IsA(AsmType::Heap())) { 852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Heap view types can not be aliased."); 853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = target_info->Clone(zone_); 855f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 856f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (value->IsBinaryOperation()) { 857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // This should either be: 858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // var <> = ffi.<>|0 860f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 861f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // or 862f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 863f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // var <> = +ffi.<> 864f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* value_binop = value->AsBinaryOperation(); 865f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = value_binop->left(); 866f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* import_type = nullptr; 867f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 868f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsDoubleAnnotation(value_binop)) { 869f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch import_type = AsmType::Double(); 870f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (IsIntAnnotation(value_binop)) { 871f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch import_type = AsmType::Int(); 872f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 873f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(value, 874f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid initializer for foreign import - unrecognized annotation."); 875f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 876f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 877f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!left->IsProperty()) { 878f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(value, 879f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid initializer for foreign import - must import member."); 880f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = ImportLookup(left->AsProperty()); 882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info == nullptr) { 883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jpp): this error message is innacurate: this may fail if the 884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // object lookup fails, or if the property lookup fails, or even if the 885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // import is bogus like a().c. 886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(value, 887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid initializer for foreign import - object lookup failed."); 888f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); 890f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target_info->IsFFI()) { 891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(value, 892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid initializer for foreign import - object is not the ffi."); 893f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Create a new target info that represents the foreign import. 896f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = new (zone_) VariableInfo(import_type); 897f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info->set_mutability(VariableInfo::kMutableGlobal); 898f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (value->IsCallNew()) { 899f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type = nullptr; 900f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(type = NewHeapView(value->AsCallNew())); 901f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = new (zone_) VariableInfo(type); 902f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info->set_mutability(VariableInfo::kImmutableGlobal); 903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else if (auto* proxy = value->AsVariableProxy()) { 904c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto* var_info = Lookup(proxy->var()); 905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 906c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (var_info == nullptr) { 907c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FAIL(value, "Undeclared identifier in global initializer"); 908c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 909c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (var_info->mutability() != VariableInfo::kConstGlobal) { 911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FAIL(value, "Identifier used to initialize a global must be a const"); 912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 913c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 914c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch target_info = new (zone_) VariableInfo(var_info->type()); 915c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (target_variable->mode() == CONST) { 916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch target_info->set_mutability(VariableInfo::kConstGlobal); 917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } else { 918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch target_info->set_mutability(VariableInfo::kMutableGlobal); 919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 920f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 921f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info == nullptr) { 923f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Invalid global variable initializer."); 924f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 925f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(target_variable->name())) { 927f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target, "Invalid asm.js identifier in global variable."); 928f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 929f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 930f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddGlobal(target_variable, target_info)) { 931f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Redeclared global identifier."); 932f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 934f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(target_info->type() != AsmType::None()); 935f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!global_variable) { 936f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Global variables have their types set in VariableTypeAnnotations. 937f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(value, target_info->type()); 938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 939f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(assign, target_info->type()); 940f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(target, target_info->type()); 941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return target_info->type(); 942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.2 ValidateExport 945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ExportType(VariableProxy* fun_export) { 946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_info = Lookup(fun_export->var()); 947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (fun_info == nullptr) { 948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_export, "Undefined identifier in asm.js module export."); 949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 951f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (fun_info->standard_member() != kNone) { 952f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_export, "Module cannot export standard library functions."); 953f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 954f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* type = fun_info->type(); 956f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (type->AsFFIType() != nullptr) { 957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_export, "Module cannot export foreign functions."); 958f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 959f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 960f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (type->AsFunctionTableType() != nullptr) { 961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_export, "Module cannot export function tables."); 962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 964f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (fun_info->type()->AsFunctionType() == nullptr) { 965f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_export, "Module export is not an asm.js function."); 966f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 967f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 96862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!fun_export->var()->is_function()) { 96962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(fun_export, "Module exports must be function declarations."); 97062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 97162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 972f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return type; 973f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 974f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 975f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateExport(ReturnStatement* exports) { 976f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // asm.js modules can export single functions, or multiple functions in an 977f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // object literal. 978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* fun_export = exports->expression()->AsVariableProxy()) { 979f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Exporting single function. 980f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* export_type; 981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(export_type = ExportType(fun_export)); 982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return export_type; 983f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 984f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 985f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* obj_export = exports->expression()->AsObjectLiteral()) { 986f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Exporting object literal. 987f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* prop : *obj_export->properties()) { 988f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!prop->key()->IsLiteral()) { 989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(prop->key(), 990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Only normal object properties may be used in the export object " 991f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "literal."); 992f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 99362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!prop->key()->AsLiteral()->IsPropertyName()) { 99462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(prop->key(), 99562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "Exported functions must have valid identifier names."); 99662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 997f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 998f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* export_obj = prop->value()->AsVariableProxy(); 999f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (export_obj == nullptr) { 1000f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(prop->value(), "Exported value must be an asm.js function name."); 1001f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1002f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1003f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ExportType(export_obj)); 1004f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1005f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1006f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Int(); 1007f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1008f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1009f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(exports, "Unrecognized expression in asm.js module export expression."); 1010f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1012f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.3 ValidateFunctionTable 1013f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateFunctionTable(Assignment* assign) { 1014f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assign->is_compound()) { 1015f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, 1016f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Compound assignment not supported when declaring global variables."); 1017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target = assign->target(); 1020f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target->IsVariableProxy()) { 1021f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target, "Module assignments may only assign to globals."); 1022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1023f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target_variable = target->AsVariableProxy()->var(); 1024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1025f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* value = assign->value()->AsArrayLiteral(); 1026f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CHECK(value != nullptr); 1027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneList<Expression*>* pointers = value->values(); 1028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The function table size must be n = 2 ** m, for m >= 0; 1030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jpp): should this be capped? 1031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!base::bits::IsPowerOfTwo32(pointers->length())) { 1032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Invalid length for function pointer table."); 1033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* table_element_type = nullptr; 1036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* initializer : *pointers) { 1037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_proxy = initializer->AsVariableProxy(); 1038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_proxy == nullptr) { 1039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, 1040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Function pointer table initializer must be a function name."); 1041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_info = Lookup(var_proxy->var()); 1044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_info == nullptr) { 1045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(var_proxy, 1046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Undefined identifier in function pointer table initializer."); 1047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_info->standard_member() != kNone) { 1050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, 1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Function pointer table must not be a member of the standard " 1052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "library."); 1053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* initializer_type = var_info->type(); 1056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (initializer_type->AsFunctionType() == nullptr) { 1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, 1058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Function pointer table initializer must be an asm.js function."); 1059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(var_info->type()->AsFFIType() == nullptr); 1062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(var_info->type()->AsFunctionTableType() == nullptr); 1063f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (table_element_type == nullptr) { 1065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch table_element_type = initializer_type; 1066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (!initializer_type->IsA(table_element_type)) { 1067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, "Type mismatch in function pointer table initializer."); 1068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target_info = Lookup(target_variable); 1072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info == nullptr) { 1073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Function pointer tables are the last entities to be validates, so this is 1074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // unlikely to happen: only unreferenced function tables will not already 1075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // have an entry in the global scope. 1076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info = new (zone_) VariableInfo(AsmType::FunctionTableType( 1077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch zone_, pointers->length(), table_element_type)); 1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info->set_mutability(VariableInfo::kImmutableGlobal); 1079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(target_variable->name())) { 1080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target, "Invalid asm.js identifier in function table name."); 1081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddGlobal(target_variable, target_info)) { 1083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 1084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Redeclared global identifier in function table name."); 1085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(value, target_info->type()); 1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return target_info->type(); 1088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target_info_table = target_info->type()->AsFunctionTableType(); 1091f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info_table == nullptr) { 1092f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Identifier redefined as function pointer table."); 1093f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1094f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target_info->missing_definition()) { 1096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Identifier redefined (function table name)."); 1097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1099c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (static_cast<int>(target_info_table->length()) != pointers->length()) { 1100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Function table size mismatch."); 1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(target_info_table->signature()->AsFunctionType()); 1104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!table_element_type->IsA(target_info_table->signature())) { 1105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assign, "Function table initializer does not match previous type."); 1106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch target_info->MarkDefined(); 1109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(target_info->type() != AsmType::None()); 1110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(value, target_info->type()); 1111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return target_info->type(); 1113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.4 ValidateFunction 1116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) { 1117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FunctionScope _(this); 1118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Extract parameter types. 1120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun = fun_decl->fun(); 1121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_decl_proxy = fun_decl->proxy(); 1123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (fun_decl_proxy == nullptr) { 1124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl, "Anonymous functions are not support in asm.js."); 1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Statement* current; 1128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FlattenedStatements iter(zone_, fun->body()); 1129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch size_t annotated_parameters = 0; 1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 5.3 Function type annotations 1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // * parameters 1134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneVector<AsmType*> parameter_types(zone_); 1135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (; (current = iter.Next()) != nullptr; ++annotated_parameters) { 1136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* stmt = current->AsExpressionStatement(); 1137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (stmt == nullptr) { 1138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with parameters. 1139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* expr = stmt->expression()->AsAssignment(); 1142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (expr == nullptr || expr->is_compound()) { 1143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with parameters. 1144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* proxy = expr->target()->AsVariableProxy(); 1147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (proxy == nullptr) { 1148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with parameters. 1149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* param = proxy->var(); 1152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (param->location() != VariableLocation::PARAMETER || 1153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch param->index() != static_cast<int>(annotated_parameters)) { 1154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with parameters. 1155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type; 1159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(type = ParameterTypeAnnotations(param, expr->value())); 1160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(type->IsParameterType()); 1161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* param_info = new (zone_) VariableInfo(type); 1162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch param_info->set_mutability(VariableInfo::kLocal); 1163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(proxy->name())) { 1164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(proxy, "Invalid asm.js identifier in parameter name."); 1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddLocal(param, param_info)) { 1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(proxy, "Redeclared parameter."); 1169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch parameter_types.push_back(type); 1171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(proxy, type); 1172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(expr, type); 117362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SetTypeOf(expr->value(), type); 1174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (static_cast<int>(annotated_parameters) != fun->parameter_count()) { 1177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl, "Incorrect parameter type annotations."); 1178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 5.3 Function type annotations 1181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // * locals 1182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (; current; current = iter.Next()) { 1183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* initializer = ExtractInitializerExpression(current); 1184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (initializer == nullptr) { 1185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with locals. 1186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* local = initializer->target()->AsVariableProxy(); 1190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (local == nullptr) { 1191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Done with locals. It should never happen. Even if it does, the asm.js 1192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // code should not declare any other locals after this point, so we assume 1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // this is OK. If any other variable declaration is found we report a 1194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // validation error. 1195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 1196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type; 1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(type = VariableTypeAnnotations(initializer->value())); 1201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* local_info = new (zone_) VariableInfo(type); 1202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch local_info->set_mutability(VariableInfo::kLocal); 1203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(local->name())) { 1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(local, "Invalid asm.js identifier in local variable."); 1205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddLocal(local->var(), local_info)) { 1208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, "Redeclared local."); 1209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(local, type); 1212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(initializer, type); 1213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 5.2 Return Type Annotations 1216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* we peel blocks to find the last statement in the asm module 1217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // because the parser may introduce synthetic blocks. 1218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneList<Statement*>* statements = fun->body(); 1219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { 1221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (statements->length() == 0) { 1222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return_type_ = AsmType::Void(); 1223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* last_statement = statements->last(); 1225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* as_block = last_statement->AsBlock(); 1226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (as_block != nullptr) { 1227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch statements = as_block->statements(); 1228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 122962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (auto* ret_statement = last_statement->AsReturnStatement()) { 123062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(return_type_ = 123162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ReturnTypeAnnotations(ret_statement->expression())); 123262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 123362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return_type_ = AsmType::Void(); 123462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 1235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (return_type_ == AsmType::None()); 1238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(return_type_->IsReturnType()); 1240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch for (Declaration* decl : *fun->scope()->declarations()) { 1242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_decl = decl->AsVariableDeclaration(); 1243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_decl == nullptr) { 1244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(decl, "Functions may only define inner variables."); 1245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_proxy = var_decl->proxy(); 1248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_proxy == nullptr) { 1249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(decl, "Invalid local declaration declaration."); 1250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_info = Lookup(var_proxy->var()); 1253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var_info == nullptr || var_info->IsGlobal()) { 1254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(decl, "Local variable missing initializer in asm.js module."); 1255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (; current; current = iter.Next()) { 1259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* current_type; 1260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(current_type = ValidateStatement(current)); 1261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_type = AsmType::Function(zone_, return_type_); 1264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_type_as_function = fun_type->AsFunctionType(); 1265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* param_type : parameter_types) { 1266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fun_type_as_function->AddArgument(param_type); 1267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_var = fun_decl_proxy->var(); 1270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_info = new (zone_) VariableInfo(fun_type); 1271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fun_info->set_mutability(VariableInfo::kImmutableGlobal); 1272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* old_fun_info = Lookup(fun_var); 1273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (old_fun_info == nullptr) { 1274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(fun_var->name())) { 1275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl_proxy, "Invalid asm.js identifier in function name."); 1276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddGlobal(fun_var, fun_info)) { 1278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 1279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl, "Redeclared global identifier."); 1280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(fun, fun_type); 1283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return fun_type; 1284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Not necessarily an error -- fun_decl might have been used before being 1287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // defined. If that's the case, then the type in the global environment must 1288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // be the same as the type inferred by the parameter/return type annotations. 1289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* old_fun_type = old_fun_info->type(); 1290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (old_fun_type->AsFunctionType() == nullptr) { 1291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl, "Identifier redefined as function."); 1292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!old_fun_info->missing_definition()) { 1295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl, "Identifier redefined (function name)."); 1296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!fun_type->IsA(old_fun_type)) { 1299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(fun_decl, "Signature mismatch when defining function."); 1300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch old_fun_info->MarkDefined(); 1303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(fun, fun_type); 1304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return fun_type; 1306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1307f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5 ValidateStatement 1309f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateStatement(Statement* statement) { 1310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (statement->node_type()) { 1311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(statement, "Statement type invalid for asm.js."); 1313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kBlock: 1314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateBlockStatement(statement->AsBlock()); 1315f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kExpressionStatement: 1316f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateExpressionStatement(statement->AsExpressionStatement()); 1317f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kEmptyStatement: 1318f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateEmptyStatement(statement->AsEmptyStatement()); 1319f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kIfStatement: 1320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateIfStatement(statement->AsIfStatement()); 1321f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kReturnStatement: 1322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateReturnStatement(statement->AsReturnStatement()); 1323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kWhileStatement: 1324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateWhileStatement(statement->AsWhileStatement()); 1325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kDoWhileStatement: 1326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateDoWhileStatement(statement->AsDoWhileStatement()); 1327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kForStatement: 1328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateForStatement(statement->AsForStatement()); 1329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kBreakStatement: 1330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateBreakStatement(statement->AsBreakStatement()); 1331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kContinueStatement: 1332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateContinueStatement(statement->AsContinueStatement()); 1333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kSwitchStatement: 1334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateSwitchStatement(statement->AsSwitchStatement()); 1335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.1 BlockStatement 1341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateBlockStatement(Block* block) { 1342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FlattenedStatements iter(zone_, block->statements()); 1343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch while (auto* current = iter.Next()) { 1345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(current)); 1346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1351f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.2 ExpressionStatement 1352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateExpressionStatement(ExpressionStatement* expr) { 1353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* expression = expr->expression(); 1354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* call = expression->AsCall()) { 1355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateCall(AsmType::Void(), call)); 1356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateExpression(expression)); 1358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.3 EmptyStatement 1364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateEmptyStatement(EmptyStatement* empty) { 1365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.4 IfStatement 1369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateIfStatement(IfStatement* if_stmt) { 1370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* cond_type; 1371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(cond_type = ValidateExpression(if_stmt->condition())); 1372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond_type->IsA(AsmType::Int())) { 1373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(if_stmt->condition(), "If condition must be type int."); 1374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(if_stmt->then_statement())); 1376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(if_stmt->else_statement())); 1377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.5 ReturnStatement 1381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateReturnStatement(ReturnStatement* ret_stmt) { 1382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* ret_expr_type = AsmType::Void(); 1383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* ret_expr = ret_stmt->expression()) { 1384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ret_expr_type = ValidateExpression(ret_expr)); 1385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (ret_expr_type == AsmType::Void()) { 1386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* The parser modifies the source code so that expressionless 1387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // returns will return undefined, so we need to allow that. 1388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ret_expr->IsUndefinedLiteral()) { 1389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(ret_stmt, "Return statement expression can't be void."); 1390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1391f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ret_expr_type->IsA(return_type_)) { 1395f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(ret_stmt, "Type mismatch in return statement."); 1396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ret_expr_type; 1399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.6 IterationStatement 1402f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.6.a WhileStatement 1403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateWhileStatement(WhileStatement* while_stmt) { 1404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* cond_type; 1405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(cond_type = ValidateExpression(while_stmt->cond())); 1406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond_type->IsA(AsmType::Int())) { 1407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(while_stmt->cond(), "While condition must be type int."); 1408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1410f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* body = while_stmt->body()) { 1411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(body)); 1412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1413f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1415f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.6.b DoWhileStatement 1417f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateDoWhileStatement(DoWhileStatement* do_while) { 1418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* cond_type; 1419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(cond_type = ValidateExpression(do_while->cond())); 1420f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond_type->IsA(AsmType::Int())) { 1421f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(do_while->cond(), "Do {} While condition must be type int."); 1422f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* body = do_while->body()) { 1425f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(body)); 1426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1428f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.6.c ForStatement 1431f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateForStatement(ForStatement* for_stmt) { 1432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* init = for_stmt->init()) { 1433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(init)); 1434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* cond = for_stmt->cond()) { 1437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* cond_type; 1438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(cond_type = ValidateExpression(cond)); 1439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond_type->IsA(AsmType::Int())) { 1440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cond, "For condition must be type int."); 1441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* next = for_stmt->next()) { 1445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(next)); 1446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1447f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1448f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* body = for_stmt->body()) { 1449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(body)); 1450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1455f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.7 BreakStatement 1456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateBreakStatement(BreakStatement* brk_stmt) { 1457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.8 ContinueStatement 1461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateContinueStatement(ContinueStatement* cont_stmt) { 1462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.9 LabelledStatement 1466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// No need to handle these here -- see the AsmTyper's definition. 1467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.5.10 SwitchStatement 1469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateSwitchStatement(SwitchStatement* stmt) { 1470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* cond_type; 1471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(cond_type = ValidateExpression(stmt->tag())); 1472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond_type->IsA(AsmType::Signed())) { 1473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(stmt, "Switch tag must be signed."); 1474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int default_pos = kNoSourcePosition; 1477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int last_case_pos = kNoSourcePosition; 1478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneSet<int32_t> cases_seen(zone_); 1479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* a_case : *stmt->cases()) { 1480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (a_case->is_default()) { 1481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CHECK(default_pos == kNoSourcePosition); 1482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateDefault(a_case)); 1483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default_pos = a_case->position(); 1484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue; 1485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (last_case_pos == kNoSourcePosition) { 1488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch last_case_pos = a_case->position(); 1489f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch last_case_pos = std::max(last_case_pos, a_case->position()); 1491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1492f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t case_lbl; 1494f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateCase(a_case, &case_lbl)); 1495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto case_lbl_pos = cases_seen.find(case_lbl); 1496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (case_lbl_pos != cases_seen.end() && *case_lbl_pos == case_lbl) { 1497f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(a_case, "Duplicated case label."); 1498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch cases_seen.insert(case_lbl); 1500f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cases_seen.empty()) { 1503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const int64_t max_lbl = *cases_seen.rbegin(); 1504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const int64_t min_lbl = *cases_seen.begin(); 1505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (max_lbl - min_lbl > std::numeric_limits<int32_t>::max()) { 1506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(stmt, "Out-of-bounds case label range."); 1507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (last_case_pos != kNoSourcePosition && default_pos != kNoSourcePosition && 1511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default_pos < last_case_pos) { 1512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(stmt, "Switch default must appear last."); 1513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.6 ValidateCase 1519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 1520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool ExtractInt32CaseLabel(CaseClause* clause, int32_t* lbl) { 1521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* lbl_expr = clause->label()->AsLiteral(); 1522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (lbl_expr == nullptr) { 1524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 152762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(lbl_expr)) { 1528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return lbl_expr->value()->ToInt32(lbl); 1532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 1534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateCase(CaseClause* label, int32_t* case_lbl) { 1536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ExtractInt32CaseLabel(label, case_lbl)) { 1537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(label, "Case label must be a 32-bit signed integer."); 1538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FlattenedStatements iter(zone_, label->statements()); 1541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch while (auto* current = iter.Next()) { 1542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(current)); 1543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.7 ValidateDefault 1548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateDefault(CaseClause* label) { 1549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FlattenedStatements iter(zone_, label->statements()); 1550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch while (auto* current = iter.Next()) { 1551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateStatement(current)); 1552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8 ValidateExpression 1557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateExpression(Expression* expr) { 1558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* expr_ty = AsmType::None(); 1559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (expr->node_type()) { 1561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(expr, "Invalid asm.js expression."); 1563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kLiteral: 1564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateNumericLiteral(expr->AsLiteral())); 1565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kVariableProxy: 1567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateIdentifier(expr->AsVariableProxy())); 1568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kCall: 1570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateCallExpression(expr->AsCall())); 1571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kProperty: 1573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateMemberExpression(expr->AsProperty())); 1574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kAssignment: 1576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateAssignmentExpression(expr->AsAssignment())); 1577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kUnaryOperation: 1579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateUnaryExpression(expr->AsUnaryOperation())); 1580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kConditional: 1582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateConditionalExpression(expr->AsConditional())); 1583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kCompareOperation: 1585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateCompareOperation(expr->AsCompareOperation())); 1586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case AstNode::kBinaryOperation: 1588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(expr_ty = ValidateBinaryOperation(expr->AsBinaryOperation())); 1589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(expr, expr_ty); 1593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return expr_ty; 1594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateCompareOperation(CompareOperation* cmp) { 1597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (cmp->op()) { 1598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmp, "Invalid asm.js comparison operator."); 1600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::LT: 1601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::LTE: 1602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::GT: 1603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::GTE: 1604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateRelationalExpression(cmp); 1605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::EQ: 1606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::NE: 1607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateEqualityExpression(cmp); 1608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 1611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 1614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochbool IsInvert(BinaryOperation* binop) { 1615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::BIT_XOR) { 1616f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right_as_literal = binop->right()->AsLiteral(); 1620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (right_as_literal == nullptr) { 1621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 162462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteralMinus1(right_as_literal); 1625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool IsUnaryMinus(BinaryOperation* binop) { 1628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // *VIOLATION* The parser replaces uses of -x with x*-1. 1629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::MUL) { 1630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right_as_literal = binop->right()->AsLiteral(); 1634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (right_as_literal == nullptr) { 1635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 163862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return IsLiteralMinus1(right_as_literal); 1639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 1641f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) { 1643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define UNOP_OVERLOAD(Src, Dest) \ 1644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 1645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src())) { \ 1646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 1647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 1648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 1649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (expr->op()) { 1651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(expr, "Invalid asm.js binary expression."); 1653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::COMMA: 1654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateCommaExpression(expr); 1655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::MUL: 1656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsDoubleAnnotation(expr)) { 1657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* We can't be 100% sure this really IS a unary + in the asm 1658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // source so we have to be lenient, and treat this as a unary +. 1659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* Call = expr->left()->AsCall()) { 1660f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateCall(AsmType::Double(), Call); 1661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 1663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(expr->left())); 1664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(expr->right(), AsmType::Double()); 1665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Signed, Double); 1666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Unsigned, Double); 1667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(DoubleQ, Double); 1668f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(FloatQ, Double); 1669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(expr, "Invalid type for conversion to double."); 1670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsUnaryMinus(expr)) { 1673f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // *VIOLATION* the parser converts -x to x * -1. 1674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 1675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(expr->left())); 1676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(expr->right(), left_type); 1677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Int, Intish); 1678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(DoubleQ, Double); 1679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(FloatQ, Floatish); 1680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(expr, "Invalid type for unary -."); 1681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // FALTHROUGH 1683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::DIV: 1684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::MOD: 1685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateMultiplicativeExpression(expr); 1686f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::ADD: 1687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SUB: { 1688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static const uint32_t kInitialIntishCount = 0; 1689f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateAdditiveExpression(expr, kInitialIntishCount); 1690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SAR: 1692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SHL: 1693f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SHR: 1694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateShiftExpression(expr); 1695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::BIT_AND: 1696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateBitwiseANDExpression(expr); 1697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::BIT_XOR: 1698f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (IsInvert(expr)) { 1699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = expr->left(); 1700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left_as_binop = left->AsBinaryOperation(); 1701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1702f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (left_as_binop != nullptr && IsInvert(left_as_binop)) { 1703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // This is the special ~~ operator. 1704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 1705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left_as_binop->left())); 1706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(left_as_binop->right(), AsmType::FixNum()); 1707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(left_as_binop, AsmType::Signed()); 1708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(expr->right(), AsmType::FixNum()); 1709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Double, Signed); 1710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(FloatQ, Signed); 1711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(left_as_binop, "Invalid type for conversion to signed."); 1712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1714f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 1715f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 1716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Intish, Signed); 1717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(left, "Invalid type for ~."); 1718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateBitwiseXORExpression(expr); 1721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::BIT_OR: 1722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return ValidateBitwiseORExpression(expr); 1723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef UNOP_OVERLOAD 1725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 1726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.1 Expression 1729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateCommaExpression(BinaryOperation* comma) { 1730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The AST looks like: 1731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // (expr COMMA (expr COMMA (expr COMMA (... )))) 1732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = comma->left(); 1734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* left_as_call = left->AsCall()) { 1735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateCall(AsmType::Void(), left_as_call)); 1736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateExpression(left)); 1738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = comma->right(); 1741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type = nullptr; 1742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* right_as_call = right->AsCall()) { 1743c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RECURSE(right_type = ValidateFloatCoercion(right_as_call)); 1744c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (right_type != AsmType::Float()) { 1745c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // right_type == nullptr <-> right_as_call is not a call to fround. 1746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK(right_type == nullptr); 1747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RECURSE(right_type = ValidateCall(AsmType::Void(), right_as_call)); 1748c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Unnanotated function call to something that's not fround must be a call 1749c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // to a void function. 1750c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_EQ(right_type, AsmType::Void()); 1751c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 1753f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 1754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return right_type; 1757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.2 NumericLiteral 1760f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateNumericLiteral(Literal* literal) { 1761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* asm.js does not allow the use of undefined, but our parser 1762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // inserts them, so we have to handle them. 1763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (literal->IsUndefinedLiteral()) { 1764f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 1765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 176762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsLiteralDouble(literal)) { 1768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 1769f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The parser collapses expressions like !0 and !123 to true/false. 1772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We therefore need to permit these as alternate versions of 0 / 1. 1773f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (literal->raw_value()->IsTrue() || literal->raw_value()->IsFalse()) { 1774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return AsmType::Int(); 1775f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 1776f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t value; 1778f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!literal->value()->ToUint32(&value)) { 1779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t value; 1780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!literal->value()->ToInt32(&value)) { 1781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(literal, "Integer literal is out of range."); 1782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // *VIOLATION* Not really a violation, but rather a difference in 1784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // validation. The spec handles -NumericLiteral in ValidateUnaryExpression, 1785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // but V8's AST represents the negative literals as Literals. 1786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Signed(); 1787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1789f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (value <= LargestFixNum) { 1790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::FixNum(); 1791f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1792f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Unsigned(); 1794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.3 Identifier 1797f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateIdentifier(VariableProxy* proxy) { 1798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* proxy_info = Lookup(proxy->var()); 1799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (proxy_info == nullptr) { 1800f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(proxy, "Undeclared identifier."); 1801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* type = proxy_info->type(); 1803f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (type->IsA(AsmType::None()) || type->AsCallableType() != nullptr) { 1804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(proxy, "Identifier may not be accessed by ordinary expressions."); 1805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1806f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return type; 1807f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1809f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.4 CallExpression 1810f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateCallExpression(Call* call) { 1811f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* return_type; 1812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(return_type = ValidateFloatCoercion(call)); 1813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (return_type == nullptr) { 1814f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Unanotated call to a function must be a call to fround."); 1815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1816f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 1817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1819f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.5 MemberExpression 1820f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateMemberExpression(Property* prop) { 1821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* return_type; 1822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(return_type = ValidateHeapAccess(prop, LoadFromHeap)); 1823f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 1824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1825f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1826f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.6 AssignmentExpression 1827f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateAssignmentExpression(Assignment* assignment) { 1828f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* value_type; 1829f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(value_type = ValidateExpression(assignment->value())); 1830f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1831f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (assignment->op() == Token::INIT) { 1832f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assignment, 1833f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Local variable declaration must be at the top of the function."); 1834f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1835f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1836f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* target_as_proxy = assignment->target()->AsVariableProxy()) { 1837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var = target_as_proxy->var(); 1838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* target_info = Lookup(var); 1839f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1840f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (target_info == nullptr) { 1841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (var->mode() != TEMPORARY) { 1842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target_as_proxy, "Undeclared identifier."); 1843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Temporary variables are special: we add them to the local symbol table 1845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // as we see them, with the exact type of the variable's initializer. This 1846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // means that temporary variables might have nonsensical types (i.e., 1847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // intish, float?, fixnum, and not just the "canonical" types.) 1848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* var_info = new (zone_) VariableInfo(value_type); 1849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch var_info->set_mutability(VariableInfo::kLocal); 1850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(target_as_proxy->name())) { 1851f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(target_as_proxy, 1852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid asm.js identifier in temporary variable."); 1853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1855f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddLocal(var, var_info)) { 1856f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assignment, "Failed to add temporary variable to symbol table."); 1857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return value_type; 1859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1860f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1861f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!target_info->IsMutable()) { 1862f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assignment, "Can't assign to immutable symbol."); 1863f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1864f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1865f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_NE(AsmType::None(), target_info->type()); 1866f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!value_type->IsA(target_info->type())) { 1867f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assignment, "Type mismatch in assignment."); 1868f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1869f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1870f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return value_type; 1871f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1872f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1873f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* target_as_property = assignment->target()->AsProperty()) { 1874f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* allowed_store_types; 1875f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(allowed_store_types = 1876f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ValidateHeapAccess(target_as_property, StoreToHeap)); 1877f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1878f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!value_type->IsA(allowed_store_types)) { 1879f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assignment, "Type mismatch in heap assignment."); 1880f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return value_type; 1883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(assignment, "Invalid asm.js assignment."); 1886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1888f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.7 UnaryExpression 1889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateUnaryExpression(UnaryOperation* unop) { 1890f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* -NumericLiteral is validated in ValidateLiteral. 1891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* +UnaryExpression is validated in ValidateBinaryOperation. 1892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* ~UnaryOperation is validated in ValidateBinaryOperation. 1893f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* ~~UnaryOperation is validated in ValidateBinaryOperation. 1894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(unop->op() != Token::BIT_NOT); 1895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(unop->op() != Token::ADD); 1896f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* exp_type; 1897f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(exp_type = ValidateExpression(unop->expression())); 1898f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define UNOP_OVERLOAD(Src, Dest) \ 1899f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 1900f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (exp_type->IsA(AsmType::Src())) { \ 1901f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 1902f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 1903f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 1904f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1905f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 8.1 Unary Operators 1906f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (unop->op()) { 1907f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1908f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(unop, "Invalid unary operator."); 1909f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::ADD: 1910f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We can't test this because of the +x -> x * 1.0 transformation. 1911f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 1912f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Signed, Double); 1913f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Unsigned, Double); 1914f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(DoubleQ, Double); 1915f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(FloatQ, Double); 1916f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(unop, "Invalid type for unary +."); 1917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SUB: 1918f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We can't test this because of the -x -> x * -1.0 transformation. 1919f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 1920f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Int, Intish); 1921f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(DoubleQ, Double); 1922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(FloatQ, Floatish); 1923f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(unop, "Invalid type for unary -."); 1924f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::BIT_NOT: 1925f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We can't test this because of the ~x -> x ^ -1 transformation. 1926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 1927f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Intish, Signed); 1928f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(unop, "Invalid type for ~."); 1929f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::NOT: 1930f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNOP_OVERLOAD(Int, Int); 1931f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(unop, "Invalid type for !."); 1932f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1934f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef UNOP_OVERLOAD 1935f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1936f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 1937f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1939f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.8 MultiplicativeExpression 1940f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 1941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool IsIntishLiteralFactor(Expression* expr, int32_t* factor) { 1942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* literal = expr->AsLiteral(); 1943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (literal == nullptr) { 1944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 194762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(literal)) { 1948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1951f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!literal->value()->ToInt32(factor)) { 1952f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1953f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1954f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static const int32_t kIntishBound = 1 << 20; 1955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return -kIntishBound < *factor && *factor < kIntishBound; 1956f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 1958f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1959f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateMultiplicativeExpression(BinaryOperation* binop) { 1960f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!IsDoubleAnnotation(binop)); 1961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left(); 1963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = binop->right(); 1964f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1965f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool intish_mul_failed = false; 1966f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() == Token::MUL) { 1967f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t factor; 1968f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsIntishLiteralFactor(left, &factor)) { 1969f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 1970f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 1971f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (right_type->IsA(AsmType::Int())) { 1972f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Intish(); 1973f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1974f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Can't fail here, because the rhs might contain a valid intish factor. 1975f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1976f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The solution is to flag that there was an error, and later on -- when 1977f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // both lhs and rhs are evaluated -- complain. 1978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch intish_mul_failed = true; 1979f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1980f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsIntishLiteralFactor(right, &factor)) { 1982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 1983f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 1984f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Int())) { 1985f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* This will also (and correctly) handle -X, when X is an 1986f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // integer. Therefore, we don't need to handle this case within the if 1987f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // block below. 1988f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Intish(); 1989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch intish_mul_failed = true; 1991f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1992f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (factor == -1) { 1993f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* The frontend transforms -x into x * -1 (not -1.0, because 1994f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // consistency is overrated.) 1995f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::DoubleQ())) { 1996f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 1997f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (left_type->IsA(AsmType::FloatQ())) { 1998f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Floatish(); 1999f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2000f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2001f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2002f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2003f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2004f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (intish_mul_failed) { 2005f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid types for intish * (or unary -)."); 2006f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2007f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2008f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2009f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2010f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2012f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2013f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define BINOP_OVERLOAD(Src0, Src1, Dest) \ 2014f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2015f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2016f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (binop->op()) { 2020f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 2021f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid multiplicative expression."); 2022f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::MUL: 2023f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(DoubleQ, DoubleQ, Double); 2024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(FloatQ, FloatQ, Floatish); 2025f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for *."); 2026f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::DIV: 2027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Signed, Signed, Intish); 2028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Unsigned, Unsigned, Intish); 2029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(DoubleQ, DoubleQ, Double); 2030f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(FloatQ, FloatQ, Floatish); 2031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for /."); 2032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::MOD: 2033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Signed, Signed, Intish); 2034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Unsigned, Unsigned, Intish); 2035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(DoubleQ, DoubleQ, Double); 2036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for %."); 2037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef BINOP_OVERLOAD 2039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.9 AdditiveExpression 2044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateAdditiveExpression(BinaryOperation* binop, 2045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t intish_count) { 2046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch static const uint32_t kMaxIntish = 1 << 20; 2047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left(); 2049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left_as_binop = left->AsBinaryOperation(); 2050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jpp): maybe use an iterative approach instead of the recursion to 2053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ValidateAdditiveExpression. 2054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_as_binop != nullptr && (left_as_binop->op() == Token::ADD || 2055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch left_as_binop->op() == Token::SUB)) { 2056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = 2057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ValidateAdditiveExpression(left_as_binop, intish_count + 1)); 2058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(left_as_binop, left_type); 2059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 2060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2063f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = binop->right(); 2064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right_as_binop = right->AsBinaryOperation(); 2065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (right_as_binop != nullptr && (right_as_binop->op() == Token::ADD || 2068f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch right_as_binop->op() == Token::SUB)) { 2069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = 2070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ValidateAdditiveExpression(right_as_binop, intish_count + 1)); 2071f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(right_as_binop, right_type); 2072f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 2073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2074f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::FloatQ()) && right_type->IsA(AsmType::FloatQ())) { 2077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Floatish(); 2078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Int()) && right_type->IsA(AsmType::Int())) { 2081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (intish_count == 0) { 2082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Intish(); 2083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (intish_count < kMaxIntish) { 2085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Int(); 2086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Too many uncoerced integer additive expressions."); 2088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Double()) && right_type->IsA(AsmType::Double())) { 2091f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 2092f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2093f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2094f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() == Token::SUB) { 2095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::DoubleQ()) && 2096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch right_type->IsA(AsmType::DoubleQ())) { 2097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 2098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2099f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for additive expression."); 2102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.10 ShiftExpression 2105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateShiftExpression(BinaryOperation* binop) { 2106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left(); 2107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = binop->right(); 2108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define BINOP_OVERLOAD(Src0, Src1, Dest) \ 2115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (binop->op()) { 2121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 2122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid shift expression."); 2123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SHL: 2124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Intish, Intish, Signed); 2125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for <<."); 2126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SAR: 2127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Intish, Intish, Signed); 2128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for >>."); 2129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::SHR: 2130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Intish, Intish, Unsigned); 2131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for >>>."); 2132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef BINOP_OVERLOAD 2134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.11 RelationalExpression 2139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateRelationalExpression(CompareOperation* cmpop) { 2140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = cmpop->left(); 2141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = cmpop->right(); 2142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define CMPOP_OVERLOAD(Src0, Src1, Dest) \ 2149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (cmpop->op()) { 2155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 2156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid relational expression."); 2157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::LT: 2158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Signed, Signed, Int); 2159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Unsigned, Unsigned, Int); 2160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Float, Float, Int); 2161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Double, Double, Int); 2162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid operands for <."); 2163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::GT: 2164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Signed, Signed, Int); 2165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Unsigned, Unsigned, Int); 2166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Float, Float, Int); 2167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Double, Double, Int); 2168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid operands for >."); 2169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::LTE: 2170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Signed, Signed, Int); 2171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Unsigned, Unsigned, Int); 2172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Float, Float, Int); 2173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Double, Double, Int); 2174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid operands for <=."); 2175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::GTE: 2176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Signed, Signed, Int); 2177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Unsigned, Unsigned, Int); 2178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Float, Float, Int); 2179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Double, Double, Int); 2180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid operands for >=."); 2181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef CMPOP_OVERLOAD 2183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.12 EqualityExpression 2188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateEqualityExpression(CompareOperation* cmpop) { 2189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = cmpop->left(); 2190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = cmpop->right(); 2191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define CMPOP_OVERLOAD(Src0, Src1, Dest) \ 2198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (cmpop->op()) { 2204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 2205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid equality expression."); 2206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::EQ: 2207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Signed, Signed, Int); 2208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Unsigned, Unsigned, Int); 2209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Float, Float, Int); 2210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Double, Double, Int); 2211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid operands for ==."); 2212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case Token::NE: 2213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Signed, Signed, Int); 2214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Unsigned, Unsigned, Int); 2215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Float, Float, Int); 2216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CMPOP_OVERLOAD(Double, Double, Int); 2217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cmpop, "Invalid operands for !=."); 2218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef CMPOP_OVERLOAD 2220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.13 BitwiseANDExpression 2225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateBitwiseANDExpression(BinaryOperation* binop) { 2226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left(); 2227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = binop->right(); 2228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::BIT_AND) { 2235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid & expression."); 2236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define BINOP_OVERLOAD(Src0, Src1, Dest) \ 2239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Intish, Intish, Signed); 2245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for &."); 2246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef BINOP_OVERLOAD 2247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.14 BitwiseXORExpression 2252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateBitwiseXORExpression(BinaryOperation* binop) { 2253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left(); 2254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = binop->right(); 2255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::BIT_XOR) { 2262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid ^ expression."); 2263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define BINOP_OVERLOAD(Src0, Src1, Dest) \ 2266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Intish, Intish, Signed); 2272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for ^."); 2273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef BINOP_OVERLOAD 2274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.15 BitwiseORExpression 2279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateBitwiseORExpression(BinaryOperation* binop) { 2280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left(); 2281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsIntAnnotation(binop)) { 2282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* left_as_call = left->AsCall()) { 2283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type; 2284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(type = ValidateCall(AsmType::Signed(), left_as_call)); 2285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return type; 2286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 228762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AsmType* left_type; 228862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(left_type = ValidateExpression(left)); 228962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!left_type->IsA(AsmType::Intish())) { 229062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(left, "Left side of |0 annotation must be intish."); 229162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 229262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return AsmType::Signed(); 2293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = binop->right(); 2296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* right_type; 2298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(right_type = ValidateExpression(right)); 2300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (binop->op() != Token::BIT_OR) { 2302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid | expression."); 2303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define BINOP_OVERLOAD(Src0, Src1, Dest) \ 2306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2307f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left_type->IsA(AsmType::Src0()) && right_type->IsA(AsmType::Src1())) { \ 2308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Dest(); \ 2309f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch BINOP_OVERLOAD(Intish, Intish, Signed); 2312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid operands for |."); 2313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef BINOP_OVERLOAD 2314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2315f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2316f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2317f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2318f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.8.16 ConditionalExpression 2319f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateConditionalExpression(Conditional* cond) { 2320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* cond_type; 2321f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(cond_type = ValidateExpression(cond->condition())); 2322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!cond_type->IsA(AsmType::Int())) { 2323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cond, "Ternary operation condition should be int."); 2324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* then_type; 2327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(then_type = ValidateExpression(cond->then_expression())); 2328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* else_type; 2329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(else_type = ValidateExpression(cond->else_expression())); 2330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define SUCCEED_IF_BOTH_ARE(type) \ 2332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch do { \ 2333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (then_type->IsA(AsmType::type())) { \ 2334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!else_type->IsA(AsmType::type())) { \ 2335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cond, "Type mismatch for ternary operation result type."); \ 2336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::type(); \ 2338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 2339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } while (0) 2340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SUCCEED_IF_BOTH_ARE(Int); 2341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SUCCEED_IF_BOTH_ARE(Float); 2342f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SUCCEED_IF_BOTH_ARE(Double); 2343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#undef SUCCEED_IF_BOTH_ARE 2344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(cond, "Ternary operator must return int, float, or double."); 2346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.9 ValidateCall 2349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 2350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool ExtractIndirectCallMask(Expression* expr, uint32_t* value) { 2351f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* as_literal = expr->AsLiteral(); 2352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (as_literal == nullptr) { 2353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 235662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(as_literal)) { 2357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!as_literal->value()->ToUint32(value)) { 2361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return base::bits::IsPowerOfTwo32(1 + *value); 2365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 2367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) { 2369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* float_coercion_type; 2370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(float_coercion_type = ValidateFloatCoercion(call)); 2371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (float_coercion_type == AsmType::Float()) { 2372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call, AsmType::Float()); 2373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 2374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jpp): we should be able to reuse the args vector's storage space. 2377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ZoneVector<AsmType*> args(zone_); 2378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch args.reserve(call->arguments()->length()); 2379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* arg : *call->arguments()) { 2381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* arg_type; 2382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(arg_type = ValidateExpression(arg)); 2383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch args.emplace_back(arg_type); 2384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call_expr = call->expression(); 2387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // identifier(Expression...) 2389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* call_var_proxy = call_expr->AsVariableProxy()) { 2390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call_var_info = Lookup(call_var_proxy->var()); 2391f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (call_var_info == nullptr) { 2393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We can't fail here: the validator performs a single pass over the AST, 2394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // so it is possible for some calls to be currently unresolved. We eagerly 2395f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // add the function to the table of globals. 2396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call_type = AsmType::Function(zone_, return_type)->AsFunctionType(); 2397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* arg : args) { 2398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch call_type->AddArgument(arg->ToParameterType()); 2399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_info = 2401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch new (zone_) VariableInfo(reinterpret_cast<AsmType*>(call_type)); 2402f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fun_info->set_mutability(VariableInfo::kImmutableGlobal); 2403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AddForwardReference(call_var_proxy, fun_info); 2404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(call_var_proxy->name())) { 2405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call_var_proxy, 2406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid asm.js identifier in (forward) function name."); 2407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddGlobal(call_var_proxy->var(), fun_info)) { 2409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 2410f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Redeclared global identifier."); 2411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 241262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (call->GetCallType() != Call::OTHER_CALL) { 241362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(call, "Invalid call of existing global function."); 241462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2415f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call_var_proxy, reinterpret_cast<AsmType*>(call_type)); 2416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call, return_type); 2417f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 2418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2420f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* callee_type = call_var_info->type()->AsCallableType(); 2421f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (callee_type == nullptr) { 2422f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Calling something that's not a function."); 2423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2425f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (callee_type->AsFFIType() != nullptr) { 2426f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (return_type == AsmType::Float()) { 2427f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FAIL(call, "Foreign functions can't return float."); 2428f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2429f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Record FFI use signature, since the asm->wasm translator must know 2430f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // all uses up-front. 2431f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ffi_use_signatures_.emplace_back( 2432f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FFIUseSignature(call_var_proxy->var(), zone_)); 2433f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch FFIUseSignature* sig = &ffi_use_signatures_.back(); 2434f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch sig->return_type_ = return_type; 2435f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch sig->arg_types_.reserve(args.size()); 2436f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (size_t i = 0; i < args.size(); ++i) { 2437f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch sig->arg_types_.emplace_back(args[i]); 2438f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 2439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!callee_type->CanBeInvokedWith(return_type, args)) { 2442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Function invocation does not match function type."); 2443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 244562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (call->GetCallType() != Call::OTHER_CALL) { 244662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(call, "Invalid forward call of global function."); 244762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 244862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call_var_proxy, call_var_info->type()); 2450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call, return_type); 2451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 2452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // identifier[expr & n](Expression...) 2455f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* call_property = call_expr->AsProperty()) { 2456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* index = call_property->key()->AsBinaryOperation(); 2457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (index == nullptr || index->op() != Token::BIT_AND) { 2458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call_property->key(), 2459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Indirect call index must be in the expr & mask form."); 2460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = index->left(); 2463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* right = index->right(); 2464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t mask; 2465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ExtractIndirectCallMask(right, &mask)) { 2466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ExtractIndirectCallMask(left, &mask)) { 2467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(right, "Invalid indirect call mask."); 2468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 2469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch left = right; 2470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const uint32_t table_length = mask + 1; 2473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* left_type; 2475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(left_type = ValidateExpression(left)); 2476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!left_type->IsA(AsmType::Intish())) { 2477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(left, "Indirect call index should be an intish."); 2478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* name_var = call_property->obj()->AsVariableProxy(); 2481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (name_var == nullptr) { 2483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call_property, "Invalid call."); 2484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* name_info = Lookup(name_var->var()); 2487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (name_info == nullptr) { 2488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // We can't fail here -- just like above. 2489f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call_type = AsmType::Function(zone_, return_type)->AsFunctionType(); 2490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (auto* arg : args) { 2491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch call_type->AddArgument(arg->ToParameterType()); 2492f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* table_type = AsmType::FunctionTableType( 2494f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch zone_, table_length, reinterpret_cast<AsmType*>(call_type)); 2495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* fun_info = 2496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch new (zone_) VariableInfo(reinterpret_cast<AsmType*>(table_type)); 2497f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fun_info->set_mutability(VariableInfo::kImmutableGlobal); 2498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AddForwardReference(name_var, fun_info); 2499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!ValidAsmIdentifier(name_var->name())) { 2500f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(name_var, 2501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid asm.js identifier in (forward) function table name."); 2502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!AddGlobal(name_var->var(), fun_info)) { 2504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(false); 2505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Redeclared global identifier."); 2506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 250762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (call->GetCallType() != Call::KEYED_PROPERTY_CALL) { 250862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(call, "Invalid call of existing function table."); 250962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call_property, reinterpret_cast<AsmType*>(call_type)); 2511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call, return_type); 2512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 2513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* previous_type = name_info->type()->AsFunctionTableType(); 2516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (previous_type == nullptr) { 2517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Identifier does not name a function table."); 2518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (table_length != previous_type->length()) { 2521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Function table size does not match expected size."); 2522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* previous_type_signature = 2525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch previous_type->signature()->AsFunctionType(); 2526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(previous_type_signature != nullptr); 2527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!previous_type_signature->CanBeInvokedWith(return_type, args)) { 2528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(jpp): better error messages. 2529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, 2530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Function pointer table signature does not match previous " 2531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "signature."); 2532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 253462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (call->GetCallType() != Call::KEYED_PROPERTY_CALL) { 253562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(call, "Invalid forward call of function table."); 253662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call_property, previous_type->signature()); 2538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call, return_type); 2539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return return_type; 2540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Invalid call."); 2543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.10 ValidateHeapAccess 2546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace { 2547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool ExtractHeapAccessShift(Expression* expr, uint32_t* value) { 2548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* as_literal = expr->AsLiteral(); 2549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (as_literal == nullptr) { 2550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 255362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(as_literal)) { 2554f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return as_literal->value()->ToUint32(value); 2558f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2559f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Returns whether index is too large to access a heap with the given type. 2561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool LiteralIndexOutOfBounds(AsmType* obj_type, uint32_t index) { 2562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (obj_type->ElementSizeInBytes()) { 2563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 1: 2564f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2565f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 2: 2566f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return (index & 0x80000000u) != 0; 2567f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 4: 2568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return (index & 0xC0000000u) != 0; 2569f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case 8: 2570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return (index & 0xE0000000u) != 0; 2571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2572f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 2573f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return true; 2574f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace 2577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateHeapAccess(Property* heap, 2579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch HeapAccessType access_type) { 2580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* obj = heap->obj()->AsVariableProxy(); 2581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj == nullptr) { 2582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, "Invalid heap access."); 2583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2584f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* obj_info = Lookup(obj->var()); 2586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj_info == nullptr) { 2587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, "Undeclared identifier in heap access."); 2588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* obj_type = obj_info->type(); 2591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!obj_type->IsA(AsmType::Heap())) { 2592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, "Identifier does not represent a heap view."); 2593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2594f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(obj, obj_type); 2595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2596f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* key_as_literal = heap->key()->AsLiteral()) { 259762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(key_as_literal)) { 2598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(key_as_literal, "Heap access index must be int."); 2599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t index; 2602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!key_as_literal->value()->ToUint32(&index)) { 2603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(key_as_literal, 2604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Heap access index must be a 32-bit unsigned integer."); 2605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2606f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (LiteralIndexOutOfBounds(obj_type, index)) { 2608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(key_as_literal, "Heap access index is out of bounds"); 2609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2610f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (access_type == LoadFromHeap) { 2612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_type->LoadType(); 2613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_type->StoreType(); 2615f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2616f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* key_as_binop = heap->key()->AsBinaryOperation()) { 2618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t shift; 2619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (key_as_binop->op() == Token::SAR && 2620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExtractHeapAccessShift(key_as_binop->right(), &shift) && 2621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (1 << shift) == obj_type->ElementSizeInBytes()) { 2622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* type; 2623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(type = ValidateExpression(key_as_binop->left())); 2624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (type->IsA(AsmType::Intish())) { 2625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (access_type == LoadFromHeap) { 2626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_type->LoadType(); 2627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_type->StoreType(); 2629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(key_as_binop, "Invalid heap access index."); 2631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2632f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2633f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj_type->ElementSizeInBytes() == 1) { 2635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Leniency: if this is a byte array, we don't require the shift operation 2636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // to be present. 2637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* index_type; 2638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(index_type = ValidateExpression(heap->key())); 2639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!index_type->IsA(AsmType::Int())) { 2640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, "Invalid heap access index for byte array."); 2641f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (access_type == LoadFromHeap) { 2643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_type->LoadType(); 2644f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return obj_type->StoreType(); 2646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, "Invalid heap access index."); 2649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 6.11 ValidateFloatCoercion 2652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool AsmTyper::IsCallToFround(Call* call) { 2653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (call->arguments()->length() != 1) { 2654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call_var_proxy = call->expression()->AsVariableProxy(); 2658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (call_var_proxy == nullptr) { 2659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2660f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2662f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call_var_info = Lookup(call_var_proxy->var()); 2663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (call_var_info == nullptr) { 2664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 2665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return call_var_info->standard_member() == kMathFround; 2668f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ValidateFloatCoercion(Call* call) { 2671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IsCallToFround(call)) { 2672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return nullptr; 2673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* arg = call->arguments()->at(0); 2676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // call is a fround() node. From now, there can be two possible outcomes: 2677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1. fround is used as a return type annotation. 2678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* arg_as_call = arg->AsCall()) { 2679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(ValidateCall(AsmType::Float(), arg_as_call)); 2680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Float(); 2681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2. fround is used for converting to float. 2684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch AsmType* arg_type; 2685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RECURSE(arg_type = ValidateExpression(arg)); 2686f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (arg_type->IsA(AsmType::Floatish()) || arg_type->IsA(AsmType::DoubleQ()) || 2687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch arg_type->IsA(AsmType::Signed()) || arg_type->IsA(AsmType::Unsigned())) { 2688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(call->expression(), fround_type_); 2689f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Float(); 2690f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(call, "Invalid argument type to fround."); 2693f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 5.1 ParameterTypeAnnotations 2696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::ParameterTypeAnnotations(Variable* parameter, 2697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Expression* annotation) { 2698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* binop = annotation->AsBinaryOperation()) { 2699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Must be: 2700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // * x|0 2701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // * x*1 (*VIOLATION* i.e.,, +x) 2702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* left = binop->left()->AsVariableProxy(); 2703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left == nullptr) { 2704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL( 2705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch binop->left(), 2706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid parameter type annotation - should annotate an identifier."); 2707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (left->var() != parameter) { 2709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop->left(), 2710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid parameter type annotation - should annotate a parameter."); 2711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsDoubleAnnotation(binop)) { 2713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(left, AsmType::Double()); 2714f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 2715f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsIntAnnotation(binop)) { 2717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(left, AsmType::Int()); 2718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Int(); 2719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(binop, "Invalid parameter type annotation."); 2721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call = annotation->AsCall(); 2724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (call == nullptr) { 2725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL( 2726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch annotation, 2727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid float parameter type annotation - must be fround(parameter)."); 2728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2729f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IsCallToFround(call)) { 2731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(annotation, 2732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid float parameter type annotation - must be call to fround."); 2733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* src_expr = call->arguments()->at(0)->AsVariableProxy(); 2736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (src_expr == nullptr) { 2737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(annotation, 2738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid float parameter type annotation - argument to fround is not " 2739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "an identifier."); 2740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (src_expr->var() != parameter) { 2743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(annotation, 2744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid float parameter type annotation - argument to fround is not " 2745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "a parameter."); 2746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(src_expr, AsmType::Float()); 2749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Float(); 2750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 5.2 ReturnTypeAnnotations 275362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochAsmType* AsmTyper::ReturnTypeAnnotations(Expression* ret_expr) { 275462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NOT_NULL(ret_expr); 2755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2756f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* binop = ret_expr->AsBinaryOperation()) { 2757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsDoubleAnnotation(binop)) { 2758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 2759f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (IsIntAnnotation(binop)) { 2760f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Signed(); 2761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 276262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Invalid return type annotation."); 2763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2764f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* call = ret_expr->AsCall()) { 2766f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (IsCallToFround(call)) { 2767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Float(); 2768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 276962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Invalid function call in return statement."); 2770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2771f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* literal = ret_expr->AsLiteral()) { 2773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t _; 277462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsLiteralDouble(literal)) { 2775f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 277662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (IsLiteralInt(literal) && literal->value()->ToInt32(&_)) { 2777f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Signed(); 2778f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (literal->IsUndefinedLiteral()) { 2779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // *VIOLATION* The parser changes 2780f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // return; 2782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // into 2784f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // return undefined 2786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Void(); 2787f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 278862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Invalid literal in return statement."); 2789f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2790f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (auto* proxy = ret_expr->AsVariableProxy()) { 2792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto* var_info = Lookup(proxy->var()); 2793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (var_info == nullptr) { 279562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Undeclared identifier in return statement."); 2796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2797c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (var_info->mutability() != VariableInfo::kConstGlobal) { 279962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Identifier in return statement is not const."); 2800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (!var_info->type()->IsReturnType()) { 280362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Constant in return must be signed, float, or double."); 2804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_info->type(); 2807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 280962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // NOTE: This is not strictly valid asm.js, but is emitted by some versions of 281062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Emscripten. 281162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (auto* cond = ret_expr->AsConditional()) { 281262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AsmType* a = AsmType::None(); 281362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch AsmType* b = AsmType::None(); 281462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(a = ReturnTypeAnnotations(cond->then_expression())); 281562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (a->IsA(AsmType::None())) { 281662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return a; 281762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 281862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RECURSE(b = ReturnTypeAnnotations(cond->else_expression())); 281962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (b->IsA(AsmType::None())) { 282062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return b; 282162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 282262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (a->IsExactly(b)) { 282362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return a; 282462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 282562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 282662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 282762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(ret_expr, "Invalid return type expression."); 2828f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2829f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2830f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 5.4 VariableTypeAnnotations 2831f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Also used for 5.5 GlobalVariableTypeAnnotations 2832c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochAsmType* AsmTyper::VariableTypeAnnotations( 2833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Expression* initializer, VariableInfo::Mutability mutability_type) { 2834f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (auto* literal = initializer->AsLiteral()) { 283562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (IsLiteralDouble(literal)) { 2836f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetTypeOf(initializer, AsmType::Double()); 2837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Double(); 2838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 283962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!IsLiteralInt(literal)) { 284062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(initializer, "Invalid type annotation - forbidden literal."); 284162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 2842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int32_t i32; 2843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch uint32_t u32; 2844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch AsmType* initializer_type = nullptr; 2845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (literal->value()->ToUint32(&u32)) { 2846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (u32 > LargestFixNum) { 2847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch initializer_type = AsmType::Unsigned(); 2848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SetTypeOf(initializer, initializer_type); 2849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 2850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch initializer_type = AsmType::FixNum(); 2851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SetTypeOf(initializer, initializer_type); 2852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch initializer_type = AsmType::Signed(); 2853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (literal->value()->ToInt32(&i32)) { 2855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch initializer_type = AsmType::Signed(); 2856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SetTypeOf(initializer, initializer_type); 2857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 2858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, "Invalid type annotation - forbidden literal."); 2859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2860c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (mutability_type != VariableInfo::kConstGlobal) { 2861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return AsmType::Int(); 2862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return initializer_type; 2864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2866c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (auto* proxy = initializer->AsVariableProxy()) { 2867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch auto* var_info = Lookup(proxy->var()); 2868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (var_info == nullptr) { 2870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FAIL(initializer, 2871c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch "Undeclared identifier in variable declaration initializer."); 2872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (var_info->mutability() != VariableInfo::kConstGlobal) { 2875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FAIL(initializer, 2876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch "Identifier in variable declaration initializer must be const."); 2877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 2879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch SetTypeOf(initializer, var_info->type()); 2880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch return var_info->type(); 2881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* call = initializer->AsCall(); 2884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (call == nullptr) { 2885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, 2886c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch "Invalid variable initialization - it should be a literal, const, or " 2887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "fround(literal)."); 2888f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2890f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!IsCallToFround(call)) { 2891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, 2892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid float coercion - expected call fround(literal)."); 2893f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* src_expr = call->arguments()->at(0)->AsLiteral(); 2896f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (src_expr == nullptr) { 2897f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(initializer, 2898f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Invalid float type annotation - expected literal argument for call " 2899f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "to fround."); 2900f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2901f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 290262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // ERRATA: 5.4 290362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // According to the spec: float constants must contain dots in local, 290462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // but not in globals. 290562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // However, the errata doc (and actual programs), use integer values 290662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // with fround(..). 290762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Skipping the check that would go here to enforce this. 290862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Checking instead the literal expression is at least a number. 290962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (!src_expr->raw_value()->IsNumber()) { 291062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FAIL(initializer, 291162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "Invalid float type annotation - expected numeric literal for call " 291262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "to fround."); 2913f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2914f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2915f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return AsmType::Float(); 2916f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2918f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// 5.5 GlobalVariableTypeAnnotations 2919f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochAsmType* AsmTyper::NewHeapView(CallNew* new_heap_view) { 2920f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* heap_type = new_heap_view->expression()->AsProperty(); 2921f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (heap_type == nullptr) { 2922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(new_heap_view, "Invalid type after new."); 2923f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2924f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* heap_view_info = ImportLookup(heap_type); 2925f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (heap_view_info == nullptr) { 2927f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(new_heap_view, "Unknown stdlib member in heap view declaration."); 2928f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2929f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2930f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!heap_view_info->type()->IsA(AsmType::Heap())) { 2931f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(new_heap_view, "Type is not a heap view type."); 2932f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2934f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (new_heap_view->arguments()->length() != 1) { 2935f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(new_heap_view, "Invalid number of arguments when creating heap view."); 2936f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2937f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* heap = new_heap_view->arguments()->at(0); 2939f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* heap_var_proxy = heap->AsVariableProxy(); 2940f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (heap_var_proxy == nullptr) { 2942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, 2943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Heap view creation parameter should be the module's heap parameter."); 2944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto* heap_var_info = Lookup(heap_var_proxy->var()); 2947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (heap_var_info == nullptr) { 2949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, "Undeclared identifier instead of heap parameter."); 2950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2951f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2952f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (!heap_var_info->IsHeap()) { 2953f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FAIL(heap, 2954f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "Heap view creation parameter should be the module's heap parameter."); 2955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2956f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(heap_view_info->type()->IsA(AsmType::Heap())); 2958f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return heap_view_info->type(); 2959f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2960f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace wasm 2962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace internal 2963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} // namespace v8 2964