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