// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

// Required to get M_E etc. in MSVC.
#if defined(_WIN32)
#define _USE_MATH_DEFINES
#endif
#include <math.h>

#include "src/asmjs/asm-types.h"
#include "src/asmjs/asm-wasm-builder.h"
#include "src/asmjs/switch-logic.h"

#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-opcodes.h"

#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/codegen.h"

namespace v8 {
namespace internal {
namespace wasm {

#define RECURSE(call)               \
  do {                              \
    DCHECK(!HasStackOverflow());    \
    call;                           \
    if (HasStackOverflow()) return; \
  } while (false)

enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope };
enum ValueFate { kDrop, kLeaveOnStack };

struct ForeignVariable {
  Handle<Name> name;
  Variable* var;
  LocalType type;
};

class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
 public:
  AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
                     AsmTyper* typer)
      : local_variables_(ZoneHashMap::kDefaultHashMapCapacity,
                         ZoneAllocationPolicy(zone)),
        functions_(ZoneHashMap::kDefaultHashMapCapacity,
                   ZoneAllocationPolicy(zone)),
        global_variables_(ZoneHashMap::kDefaultHashMapCapacity,
                          ZoneAllocationPolicy(zone)),
        scope_(kModuleScope),
        builder_(new (zone) WasmModuleBuilder(zone)),
        current_function_builder_(nullptr),
        literal_(literal),
        isolate_(isolate),
        zone_(zone),
        typer_(typer),
        breakable_blocks_(zone),
        foreign_variables_(zone),
        init_function_(nullptr),
        foreign_init_function_(nullptr),
        next_table_index_(0),
        function_tables_(ZoneHashMap::kDefaultHashMapCapacity,
                         ZoneAllocationPolicy(zone)),
        imported_function_table_(this) {
    InitializeAstVisitor(isolate);
  }

  void InitializeInitFunction() {
    FunctionSig::Builder b(zone(), 0, 0);
    init_function_ = builder_->AddFunction(b.Build());
    builder_->MarkStartFunction(init_function_);
  }

  void BuildForeignInitFunction() {
    foreign_init_function_ = builder_->AddFunction();
    FunctionSig::Builder b(zone(), 0, foreign_variables_.size());
    for (auto i = foreign_variables_.begin(); i != foreign_variables_.end();
         ++i) {
      b.AddParam(i->type);
    }
    foreign_init_function_->ExportAs(
        CStrVector(AsmWasmBuilder::foreign_init_name));
    foreign_init_function_->SetSignature(b.Build());
    for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) {
      foreign_init_function_->EmitGetLocal(static_cast<uint32_t>(pos));
      ForeignVariable* fv = &foreign_variables_[pos];
      uint32_t index = LookupOrInsertGlobal(fv->var, fv->type);
      foreign_init_function_->EmitWithVarInt(kExprSetGlobal, index);
    }
  }

  i::Handle<i::FixedArray> GetForeignArgs() {
    i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray(
        static_cast<int>(foreign_variables_.size()));
    for (size_t i = 0; i < foreign_variables_.size(); ++i) {
      ForeignVariable* fv = &foreign_variables_[i];
      ret->set(static_cast<int>(i), *fv->name);
    }
    return ret;
  }

  void Build() {
    InitializeInitFunction();
    RECURSE(VisitFunctionLiteral(literal_));
    BuildForeignInitFunction();
  }

  void VisitVariableDeclaration(VariableDeclaration* decl) {}

  void VisitFunctionDeclaration(FunctionDeclaration* decl) {
    DCHECK_EQ(kModuleScope, scope_);
    DCHECK_NULL(current_function_builder_);
    current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var());
    scope_ = kFuncScope;
    RECURSE(Visit(decl->fun()));
    scope_ = kModuleScope;
    current_function_builder_ = nullptr;
    local_variables_.Clear();
  }

  void VisitStatements(ZoneList<Statement*>* stmts) {
    for (int i = 0; i < stmts->length(); ++i) {
      Statement* stmt = stmts->at(i);
      ExpressionStatement* e = stmt->AsExpressionStatement();
      if (e != nullptr && e->expression()->IsUndefinedLiteral()) {
        continue;
      }
      RECURSE(Visit(stmt));
      if (stmt->IsJump()) break;
    }
  }

  void VisitBlock(Block* stmt) {
    if (stmt->statements()->length() == 1) {
      ExpressionStatement* expr =
          stmt->statements()->at(0)->AsExpressionStatement();
      if (expr != nullptr) {
        if (expr->expression()->IsAssignment()) {
          RECURSE(VisitExpressionStatement(expr));
          return;
        }
      }
    }
    if (scope_ == kFuncScope) {
      BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock);
      RECURSE(VisitStatements(stmt->statements()));
    } else {
      RECURSE(VisitStatements(stmt->statements()));
    }
  }

  class BlockVisitor {
   private:
    AsmWasmBuilderImpl* builder_;

   public:
    BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt,
                 WasmOpcode opcode)
        : builder_(builder) {
      builder_->breakable_blocks_.push_back(
          std::make_pair(stmt, opcode == kExprLoop));
      // block and loops have a type immediate.
      builder_->current_function_builder_->EmitWithU8(opcode, kLocalVoid);
    }
    ~BlockVisitor() {
      builder_->current_function_builder_->Emit(kExprEnd);
      builder_->breakable_blocks_.pop_back();
    }
  };

  void VisitExpressionStatement(ExpressionStatement* stmt) {
    VisitForEffect(stmt->expression());
  }

  void VisitForEffect(Expression* expr) {
    if (expr->IsAssignment()) {
      // Don't emit drops for assignments. Instead use SetLocal/GetLocal.
      VisitAssignment(expr->AsAssignment(), kDrop);
      return;
    }
    if (expr->IsCall()) {
      // Only emit a drop if the call has a non-void return value.
      if (VisitCallExpression(expr->AsCall()) && scope_ == kFuncScope) {
        current_function_builder_->Emit(kExprDrop);
      }
      return;
    }
    if (expr->IsBinaryOperation()) {
      BinaryOperation* binop = expr->AsBinaryOperation();
      if (binop->op() == Token::COMMA) {
        VisitForEffect(binop->left());
        VisitForEffect(binop->right());
        return;
      }
    }
    RECURSE(Visit(expr));
    if (scope_ == kFuncScope) current_function_builder_->Emit(kExprDrop);
  }

  void VisitEmptyStatement(EmptyStatement* stmt) {}

  void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); }

  void VisitIfStatement(IfStatement* stmt) {
    DCHECK_EQ(kFuncScope, scope_);
    RECURSE(Visit(stmt->condition()));
    current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
    // WASM ifs come with implement blocks for both arms.
    breakable_blocks_.push_back(std::make_pair(nullptr, false));
    if (stmt->HasThenStatement()) {
      RECURSE(Visit(stmt->then_statement()));
    }
    if (stmt->HasElseStatement()) {
      current_function_builder_->Emit(kExprElse);
      RECURSE(Visit(stmt->else_statement()));
    }
    current_function_builder_->Emit(kExprEnd);
    breakable_blocks_.pop_back();
  }

  void DoBreakOrContinue(BreakableStatement* target, bool is_continue) {
    DCHECK_EQ(kFuncScope, scope_);
    for (int i = static_cast<int>(breakable_blocks_.size()) - 1; i >= 0; --i) {
      auto elem = breakable_blocks_.at(i);
      if (elem.first == target && elem.second == is_continue) {
        int block_distance = static_cast<int>(breakable_blocks_.size() - i - 1);
        current_function_builder_->Emit(kExprBr);
        current_function_builder_->EmitVarInt(block_distance);
        return;
      }
    }
    UNREACHABLE();  // statement not found
  }

  void VisitContinueStatement(ContinueStatement* stmt) {
    DoBreakOrContinue(stmt->target(), true);
  }

  void VisitBreakStatement(BreakStatement* stmt) {
    DoBreakOrContinue(stmt->target(), false);
  }

  void VisitReturnStatement(ReturnStatement* stmt) {
    if (scope_ == kModuleScope) {
      scope_ = kExportScope;
      RECURSE(Visit(stmt->expression()));
      scope_ = kModuleScope;
    } else if (scope_ == kFuncScope) {
      RECURSE(Visit(stmt->expression()));
      current_function_builder_->Emit(kExprReturn);
    } else {
      UNREACHABLE();
    }
  }

  void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); }

  void HandleCase(CaseNode* node,
                  ZoneMap<int, unsigned int>& case_to_block,
                  VariableProxy* tag, int default_block, int if_depth) {
    int prev_if_depth = if_depth;
    if (node->left != nullptr) {
      VisitVariableProxy(tag);
      current_function_builder_->EmitI32Const(node->begin);
      current_function_builder_->Emit(kExprI32LtS);
      current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
      if_depth++;
      breakable_blocks_.push_back(std::make_pair(nullptr, false));
      HandleCase(node->left, case_to_block, tag, default_block, if_depth);
      current_function_builder_->Emit(kExprElse);
    }
    if (node->right != nullptr) {
      VisitVariableProxy(tag);
      current_function_builder_->EmitI32Const(node->end);
      current_function_builder_->Emit(kExprI32GtS);
      current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
      if_depth++;
      breakable_blocks_.push_back(std::make_pair(nullptr, false));
      HandleCase(node->right, case_to_block, tag, default_block, if_depth);
      current_function_builder_->Emit(kExprElse);
    }
    if (node->begin == node->end) {
      VisitVariableProxy(tag);
      current_function_builder_->EmitI32Const(node->begin);
      current_function_builder_->Emit(kExprI32Eq);
      current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
      DCHECK(case_to_block.find(node->begin) != case_to_block.end());
      current_function_builder_->Emit(kExprBr);
      current_function_builder_->EmitVarInt(1 + if_depth +
                                            case_to_block[node->begin]);
      current_function_builder_->Emit(kExprEnd);
    } else {
      if (node->begin != 0) {
        VisitVariableProxy(tag);
        current_function_builder_->EmitI32Const(node->begin);
        current_function_builder_->Emit(kExprI32Sub);
      } else {
        VisitVariableProxy(tag);
      }
      current_function_builder_->Emit(kExprBrTable);
      current_function_builder_->EmitVarInt(node->end - node->begin + 1);
      for (int v = node->begin; v <= node->end; ++v) {
        if (case_to_block.find(v) != case_to_block.end()) {
          uint32_t target = if_depth + case_to_block[v];
          current_function_builder_->EmitVarInt(target);
        } else {
          uint32_t target = if_depth + default_block;
          current_function_builder_->EmitVarInt(target);
        }
        if (v == kMaxInt) {
          break;
        }
      }
      uint32_t target = if_depth + default_block;
      current_function_builder_->EmitVarInt(target);
    }

    while (if_depth-- != prev_if_depth) {
      breakable_blocks_.pop_back();
      current_function_builder_->Emit(kExprEnd);
    }
  }

  void VisitSwitchStatement(SwitchStatement* stmt) {
    VariableProxy* tag = stmt->tag()->AsVariableProxy();
    DCHECK_NOT_NULL(tag);
    ZoneList<CaseClause*>* clauses = stmt->cases();
    int case_count = clauses->length();
    if (case_count == 0) {
      return;
    }
    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock);
    ZoneVector<BlockVisitor*> blocks(zone_);
    ZoneVector<int32_t> cases(zone_);
    ZoneMap<int, unsigned int> case_to_block(zone_);
    bool has_default = false;
    for (int i = case_count - 1; i >= 0; --i) {
      CaseClause* clause = clauses->at(i);
      blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock));
      if (!clause->is_default()) {
        Literal* label = clause->label()->AsLiteral();
        Handle<Object> value = label->value();
        int32_t label_value;
        bool label_is_i32 = value->ToInt32(&label_value);
        DCHECK(value->IsNumber() && label_is_i32);
        (void)label_is_i32;
        case_to_block[label_value] = i;
        cases.push_back(label_value);
      } else {
        DCHECK_EQ(i, case_count - 1);
        has_default = true;
      }
    }
    if (!has_default || case_count > 1) {
      int default_block = has_default ? case_count - 1 : case_count;
      BlockVisitor switch_logic_block(this, nullptr, kExprBlock);
      CaseNode* root = OrderCases(&cases, zone_);
      HandleCase(root, case_to_block, tag, default_block, 0);
      if (root->left != nullptr || root->right != nullptr ||
          root->begin == root->end) {
        current_function_builder_->Emit(kExprBr);
        current_function_builder_->EmitVarInt(default_block);
      }
    }
    for (int i = 0; i < case_count; ++i) {
      CaseClause* clause = clauses->at(i);
      RECURSE(VisitStatements(clause->statements()));
      BlockVisitor* v = blocks.at(case_count - i - 1);
      blocks.pop_back();
      delete v;
    }
  }

  void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }

  void VisitDoWhileStatement(DoWhileStatement* stmt) {
    DCHECK_EQ(kFuncScope, scope_);
    BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock);
    BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop);
    RECURSE(Visit(stmt->body()));
    RECURSE(Visit(stmt->cond()));
    current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
    current_function_builder_->EmitWithU8(kExprBr, 1);
    current_function_builder_->Emit(kExprEnd);
  }

  void VisitWhileStatement(WhileStatement* stmt) {
    DCHECK_EQ(kFuncScope, scope_);
    BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock);
    BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop);
    RECURSE(Visit(stmt->cond()));
    breakable_blocks_.push_back(std::make_pair(nullptr, false));
    current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
    RECURSE(Visit(stmt->body()));
    current_function_builder_->EmitWithU8(kExprBr, 1);
    current_function_builder_->Emit(kExprEnd);
    breakable_blocks_.pop_back();
  }

  void VisitForStatement(ForStatement* stmt) {
    DCHECK_EQ(kFuncScope, scope_);
    if (stmt->init() != nullptr) {
      RECURSE(Visit(stmt->init()));
    }
    BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock);
    BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop);
    if (stmt->cond() != nullptr) {
      RECURSE(Visit(stmt->cond()));
      current_function_builder_->Emit(kExprI32Eqz);
      current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
      current_function_builder_->EmitWithU8(kExprBr, 2);
      current_function_builder_->Emit(kExprEnd);
    }
    if (stmt->body() != nullptr) {
      RECURSE(Visit(stmt->body()));
    }
    if (stmt->next() != nullptr) {
      RECURSE(Visit(stmt->next()));
    }
    current_function_builder_->EmitWithU8(kExprBr, 0);
  }

  void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); }

  void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); }

  void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); }

  void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); }

  void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); }

  void VisitFunctionLiteral(FunctionLiteral* expr) {
    DeclarationScope* scope = expr->scope();
    if (scope_ == kFuncScope) {
      if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) {
        // Add the parameters for the function.
        const auto& arguments = func_type->Arguments();
        for (int i = 0; i < expr->parameter_count(); ++i) {
          LocalType type = TypeFrom(arguments[i]);
          DCHECK_NE(kAstStmt, type);
          InsertParameter(scope->parameter(i), type, i);
        }
      } else {
        UNREACHABLE();
      }
    }
    RECURSE(VisitStatements(expr->body()));
    RECURSE(VisitDeclarations(scope->declarations()));
  }

  void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
    UNREACHABLE();
  }

  void VisitConditional(Conditional* expr) {
    DCHECK_EQ(kFuncScope, scope_);
    RECURSE(Visit(expr->condition()));
    // WASM ifs come with implicit blocks for both arms.
    breakable_blocks_.push_back(std::make_pair(nullptr, false));
    LocalTypeCode type;
    switch (TypeOf(expr)) {
      case kAstI32:
        type = kLocalI32;
        break;
      case kAstI64:
        type = kLocalI64;
        break;
      case kAstF32:
        type = kLocalF32;
        break;
      case kAstF64:
        type = kLocalF64;
        break;
      default:
        UNREACHABLE();
    }
    current_function_builder_->EmitWithU8(kExprIf, type);
    RECURSE(Visit(expr->then_expression()));
    current_function_builder_->Emit(kExprElse);
    RECURSE(Visit(expr->else_expression()));
    current_function_builder_->Emit(kExprEnd);
    breakable_blocks_.pop_back();
  }

  bool VisitStdlibConstant(Variable* var) {
    AsmTyper::StandardMember standard_object =
        typer_->VariableAsStandardMember(var);
    double value;
    switch (standard_object) {
      case AsmTyper::kInfinity: {
        value = std::numeric_limits<double>::infinity();
        break;
      }
      case AsmTyper::kNaN: {
        value = std::numeric_limits<double>::quiet_NaN();
        break;
      }
      case AsmTyper::kMathE: {
        value = M_E;
        break;
      }
      case AsmTyper::kMathLN10: {
        value = M_LN10;
        break;
      }
      case AsmTyper::kMathLN2: {
        value = M_LN2;
        break;
      }
      case AsmTyper::kMathLOG10E: {
        value = M_LOG10E;
        break;
      }
      case AsmTyper::kMathLOG2E: {
        value = M_LOG2E;
        break;
      }
      case AsmTyper::kMathPI: {
        value = M_PI;
        break;
      }
      case AsmTyper::kMathSQRT1_2: {
        value = M_SQRT1_2;
        break;
      }
      case AsmTyper::kMathSQRT2: {
        value = M_SQRT2;
        break;
      }
      default: { return false; }
    }
    byte code[] = {WASM_F64(value)};
    current_function_builder_->EmitCode(code, sizeof(code));
    return true;
  }

  void VisitVariableProxy(VariableProxy* expr) {
    if (scope_ == kFuncScope || scope_ == kInitScope) {
      Variable* var = expr->var();
      if (VisitStdlibConstant(var)) {
        return;
      }
      LocalType var_type = TypeOf(expr);
      DCHECK_NE(kAstStmt, var_type);
      if (var->IsContextSlot()) {
        current_function_builder_->EmitWithVarInt(
            kExprGetGlobal, LookupOrInsertGlobal(var, var_type));
      } else {
        current_function_builder_->EmitGetLocal(
            LookupOrInsertLocal(var, var_type));
      }
    } else if (scope_ == kExportScope) {
      Variable* var = expr->var();
      DCHECK(var->is_function());
      WasmFunctionBuilder* function = LookupOrInsertFunction(var);
      function->ExportAs(CStrVector(AsmWasmBuilder::single_function_name));
    }
  }

  void VisitLiteral(Literal* expr) {
    Handle<Object> value = expr->value();
    if (!(value->IsNumber() || expr->raw_value()->IsTrue() ||
          expr->raw_value()->IsFalse()) ||
        (scope_ != kFuncScope && scope_ != kInitScope)) {
      return;
    }
    AsmType* type = typer_->TypeOf(expr);
    DCHECK_NE(type, AsmType::None());

    if (type->IsA(AsmType::Signed())) {
      int32_t i = 0;
      if (!value->ToInt32(&i)) {
        UNREACHABLE();
      }
      byte code[] = {WASM_I32V(i)};
      current_function_builder_->EmitCode(code, sizeof(code));
    } else if (type->IsA(AsmType::Unsigned()) || type->IsA(AsmType::FixNum())) {
      uint32_t u = 0;
      if (!value->ToUint32(&u)) {
        UNREACHABLE();
      }
      int32_t i = static_cast<int32_t>(u);
      byte code[] = {WASM_I32V(i)};
      current_function_builder_->EmitCode(code, sizeof(code));
    } else if (type->IsA(AsmType::Int())) {
      // The parser can collapse !0, !1 etc to true / false.
      // Allow these as int literals.
      if (expr->raw_value()->IsTrue()) {
        byte code[] = {WASM_I32V(1)};
        current_function_builder_->EmitCode(code, sizeof(code));
      } else if (expr->raw_value()->IsFalse()) {
        byte code[] = {WASM_I32V(0)};
        current_function_builder_->EmitCode(code, sizeof(code));
      } else if (expr->raw_value()->IsNumber()) {
        // This can happen when -x becomes x * -1 (due to the parser).
        int32_t i = 0;
        if (!value->ToInt32(&i) || i != -1) {
          UNREACHABLE();
        }
        byte code[] = {WASM_I32V(i)};
        current_function_builder_->EmitCode(code, sizeof(code));
      } else {
        UNREACHABLE();
      }
    } else if (type->IsA(AsmType::Double())) {
      // TODO(bradnelson): Pattern match the case where negation occurs and
      // emit f64.neg instead.
      double val = expr->raw_value()->AsNumber();
      byte code[] = {WASM_F64(val)};
      current_function_builder_->EmitCode(code, sizeof(code));
    } else if (type->IsA(AsmType::Float())) {
      // This can happen when -fround(x) becomes fround(x) * 1.0[float]
      // (due to the parser).
      // TODO(bradnelson): Pattern match this and emit f32.neg instead.
      double val = expr->raw_value()->AsNumber();
      DCHECK_EQ(-1.0, val);
      byte code[] = {WASM_F32(val)};
      current_function_builder_->EmitCode(code, sizeof(code));
    } else {
      UNREACHABLE();
    }
  }

  void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); }

  void VisitObjectLiteral(ObjectLiteral* expr) {
    ZoneList<ObjectLiteralProperty*>* props = expr->properties();
    for (int i = 0; i < props->length(); ++i) {
      ObjectLiteralProperty* prop = props->at(i);
      DCHECK_EQ(kExportScope, scope_);
      VariableProxy* expr = prop->value()->AsVariableProxy();
      DCHECK_NOT_NULL(expr);
      Variable* var = expr->var();
      Literal* name = prop->key()->AsLiteral();
      DCHECK_NOT_NULL(name);
      DCHECK(name->IsPropertyName());
      const AstRawString* raw_name = name->AsRawPropertyName();
      if (var->is_function()) {
        WasmFunctionBuilder* function = LookupOrInsertFunction(var);
        function->Export();
        function->SetName({reinterpret_cast<const char*>(raw_name->raw_data()),
                           raw_name->length()});
      }
    }
  }

  void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); }

  void LoadInitFunction() {
    current_function_builder_ = init_function_;
    scope_ = kInitScope;
  }

  void UnLoadInitFunction() {
    scope_ = kModuleScope;
    current_function_builder_ = nullptr;
  }

  void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) {
    auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType();
    DCHECK_NOT_NULL(func_tbl_type);
    auto* func_type = func_tbl_type->signature()->AsFunctionType();
    const auto& arguments = func_type->Arguments();
    LocalType return_type = TypeFrom(func_type->ReturnType());
    FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
                             arguments.size());
    if (return_type != kAstStmt) {
      sig.AddReturn(return_type);
    }
    for (auto* arg : arguments) {
      sig.AddParam(TypeFrom(arg));
    }
    uint32_t signature_index = builder_->AddSignature(sig.Build());
    InsertFunctionTable(table->var(), next_table_index_, signature_index);
    next_table_index_ += funcs->values()->length();
    for (int i = 0; i < funcs->values()->length(); ++i) {
      VariableProxy* func = funcs->values()->at(i)->AsVariableProxy();
      DCHECK_NOT_NULL(func);
      builder_->AddIndirectFunction(
          LookupOrInsertFunction(func->var())->func_index());
    }
  }

  struct FunctionTableIndices : public ZoneObject {
    uint32_t start_index;
    uint32_t signature_index;
  };

  void InsertFunctionTable(Variable* v, uint32_t start_index,
                           uint32_t signature_index) {
    FunctionTableIndices* container = new (zone()) FunctionTableIndices();
    container->start_index = start_index;
    container->signature_index = signature_index;
    ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert(
        v, ComputePointerHash(v), ZoneAllocationPolicy(zone()));
    entry->value = container;
  }

  FunctionTableIndices* LookupFunctionTable(Variable* v) {
    ZoneHashMap::Entry* entry =
        function_tables_.Lookup(v, ComputePointerHash(v));
    DCHECK_NOT_NULL(entry);
    return reinterpret_cast<FunctionTableIndices*>(entry->value);
  }

  class ImportedFunctionTable {
   private:
    class ImportedFunctionIndices : public ZoneObject {
     public:
      const char* name_;
      int name_length_;
      WasmModuleBuilder::SignatureMap signature_to_index_;

      ImportedFunctionIndices(const char* name, int name_length, Zone* zone)
          : name_(name), name_length_(name_length), signature_to_index_(zone) {}
    };
    ZoneHashMap table_;
    AsmWasmBuilderImpl* builder_;

   public:
    explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder)
        : table_(ZoneHashMap::kDefaultHashMapCapacity,
                 ZoneAllocationPolicy(builder->zone())),
          builder_(builder) {}

    void AddImport(Variable* v, const char* name, int name_length) {
      ImportedFunctionIndices* indices = new (builder_->zone())
          ImportedFunctionIndices(name, name_length, builder_->zone());
      auto* entry = table_.LookupOrInsert(
          v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone()));
      entry->value = indices;
    }

    // Get a function's index (or allocate if new).
    uint32_t LookupOrInsertImport(Variable* v, FunctionSig* sig) {
      ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v));
      DCHECK_NOT_NULL(entry);
      ImportedFunctionIndices* indices =
          reinterpret_cast<ImportedFunctionIndices*>(entry->value);
      WasmModuleBuilder::SignatureMap::iterator pos =
          indices->signature_to_index_.find(sig);
      if (pos != indices->signature_to_index_.end()) {
        return pos->second;
      } else {
        uint32_t index = builder_->builder_->AddImport(
            indices->name_, indices->name_length_, sig);
        indices->signature_to_index_[sig] = index;
        return index;
      }
    }
  };

  void EmitAssignmentLhs(Expression* target, MachineType* mtype) {
    // Match the left hand side of the assignment.
    VariableProxy* target_var = target->AsVariableProxy();
    if (target_var != nullptr) {
      // Left hand side is a local or a global variable, no code on LHS.
      return;
    }

    Property* target_prop = target->AsProperty();
    if (target_prop != nullptr) {
      // Left hand side is a property access, i.e. the asm.js heap.
      VisitPropertyAndEmitIndex(target_prop, mtype);
      return;
    }

    if (target_var == nullptr && target_prop == nullptr) {
      UNREACHABLE();  // invalid assignment.
    }
  }

  void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) {
    BinaryOperation* binop = value->AsBinaryOperation();
    if (binop != nullptr) {
      if (scope_ == kInitScope) {
        // Handle foreign variables in the initialization scope.
        Property* prop = binop->left()->AsProperty();
        if (binop->op() == Token::MUL) {
          DCHECK(binop->right()->IsLiteral());
          DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
          DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot());
          DCHECK(target->IsVariableProxy());
          VisitForeignVariable(true, target->AsVariableProxy()->var(), prop);
          *is_nop = true;
          return;
        } else if (binop->op() == Token::BIT_OR) {
          DCHECK(binop->right()->IsLiteral());
          DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
          DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot());
          DCHECK(target->IsVariableProxy());
          VisitForeignVariable(false, target->AsVariableProxy()->var(), prop);
          *is_nop = true;
          return;
        } else {
          UNREACHABLE();
        }
      }
      if (MatchBinaryOperation(binop) == kAsIs) {
        VariableProxy* target_var = target->AsVariableProxy();
        VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy();
        if (target_var != nullptr && effective_value_var != nullptr &&
            target_var->var() == effective_value_var->var()) {
          *is_nop = true;
          return;
        }
      }
    }
    RECURSE(Visit(value));
  }

  void EmitAssignment(Assignment* expr, MachineType type, ValueFate fate) {
    // Match the left hand side of the assignment.
    VariableProxy* target_var = expr->target()->AsVariableProxy();
    if (target_var != nullptr) {
      // Left hand side is a local or a global variable.
      Variable* var = target_var->var();
      LocalType var_type = TypeOf(expr);
      DCHECK_NE(kAstStmt, var_type);
      if (var->IsContextSlot()) {
        uint32_t index = LookupOrInsertGlobal(var, var_type);
        current_function_builder_->EmitWithVarInt(kExprSetGlobal, index);
        if (fate == kLeaveOnStack) {
          current_function_builder_->EmitWithVarInt(kExprGetGlobal, index);
        }
      } else {
        if (fate == kDrop) {
          current_function_builder_->EmitSetLocal(
              LookupOrInsertLocal(var, var_type));
        } else {
          current_function_builder_->EmitTeeLocal(
              LookupOrInsertLocal(var, var_type));
        }
      }
    }

    Property* target_prop = expr->target()->AsProperty();
    if (target_prop != nullptr) {
      // Left hand side is a property access, i.e. the asm.js heap.
      if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() &&
          typer_->TypeOf(expr->target()->AsProperty()->obj())
              ->IsA(AsmType::Float32Array())) {
        current_function_builder_->Emit(kExprF32ConvertF64);
      }
      // Note that unlike StoreMem, AsmjsStoreMem ignores out-of-bounds writes.
      WasmOpcode opcode;
      if (type == MachineType::Int8()) {
        opcode = kExprI32AsmjsStoreMem8;
      } else if (type == MachineType::Uint8()) {
        opcode = kExprI32AsmjsStoreMem8;
      } else if (type == MachineType::Int16()) {
        opcode = kExprI32AsmjsStoreMem16;
      } else if (type == MachineType::Uint16()) {
        opcode = kExprI32AsmjsStoreMem16;
      } else if (type == MachineType::Int32()) {
        opcode = kExprI32AsmjsStoreMem;
      } else if (type == MachineType::Uint32()) {
        opcode = kExprI32AsmjsStoreMem;
      } else if (type == MachineType::Float32()) {
        opcode = kExprF32AsmjsStoreMem;
      } else if (type == MachineType::Float64()) {
        opcode = kExprF64AsmjsStoreMem;
      } else {
        UNREACHABLE();
      }
      current_function_builder_->Emit(opcode);
      if (fate == kDrop) {
        // Asm.js stores to memory leave their result on the stack.
        current_function_builder_->Emit(kExprDrop);
      }
    }

    if (target_var == nullptr && target_prop == nullptr) {
      UNREACHABLE();  // invalid assignment.
    }
  }

  void VisitAssignment(Assignment* expr) {
    VisitAssignment(expr, kLeaveOnStack);
  }

  void VisitAssignment(Assignment* expr, ValueFate fate) {
    bool as_init = false;
    if (scope_ == kModuleScope) {
      // Skip extra assignment inserted by the parser when in this form:
      // (function Module(a, b, c) {... })
      if (expr->target()->IsVariableProxy() &&
          expr->target()->AsVariableProxy()->var()->is_sloppy_function_name()) {
        return;
      }
      Property* prop = expr->value()->AsProperty();
      if (prop != nullptr) {
        VariableProxy* vp = prop->obj()->AsVariableProxy();
        if (vp != nullptr && vp->var()->IsParameter() &&
            vp->var()->index() == 1) {
          VariableProxy* target = expr->target()->AsVariableProxy();
          if (typer_->TypeOf(target)->AsFFIType() != nullptr) {
            const AstRawString* name =
                prop->key()->AsLiteral()->AsRawPropertyName();
            imported_function_table_.AddImport(
                target->var(), reinterpret_cast<const char*>(name->raw_data()),
                name->length());
          }
        }
        // Property values in module scope don't emit code, so return.
        return;
      }
      ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
      if (funcs != nullptr &&
          typer_->TypeOf(funcs)
              ->AsFunctionTableType()
              ->signature()
              ->AsFunctionType()) {
        VariableProxy* target = expr->target()->AsVariableProxy();
        DCHECK_NOT_NULL(target);
        AddFunctionTable(target, funcs);
        // Only add to the function table. No init needed.
        return;
      }
      if (expr->value()->IsCallNew()) {
        // No init code to emit for CallNew nodes.
        return;
      }
      as_init = true;
    }

    if (as_init) LoadInitFunction();
    MachineType mtype = MachineType::None();
    bool is_nop = false;
    EmitAssignmentLhs(expr->target(), &mtype);
    EmitAssignmentRhs(expr->target(), expr->value(), &is_nop);
    if (!is_nop) {
      EmitAssignment(expr, mtype, fate);
    }
    if (as_init) UnLoadInitFunction();
  }

  void VisitYield(Yield* expr) { UNREACHABLE(); }

  void VisitThrow(Throw* expr) { UNREACHABLE(); }

  void VisitForeignVariable(bool is_float, Variable* var, Property* expr) {
    DCHECK(expr->obj()->AsVariableProxy());
    DCHECK(VariableLocation::PARAMETER ==
           expr->obj()->AsVariableProxy()->var()->location());
    DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index());
    Literal* key_literal = expr->key()->AsLiteral();
    DCHECK_NOT_NULL(key_literal);
    if (!key_literal->value().is_null()) {
      Handle<Name> name =
          i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
      LocalType type = is_float ? kAstF64 : kAstI32;
      foreign_variables_.push_back({name, var, type});
    }
  }

  void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) {
    Expression* obj = expr->obj();
    AsmType* type = typer_->TypeOf(obj);
    int size;
    if (type->IsA(AsmType::Uint8Array())) {
      *mtype = MachineType::Uint8();
      size = 1;
    } else if (type->IsA(AsmType::Int8Array())) {
      *mtype = MachineType::Int8();
      size = 1;
    } else if (type->IsA(AsmType::Uint16Array())) {
      *mtype = MachineType::Uint16();
      size = 2;
    } else if (type->IsA(AsmType::Int16Array())) {
      *mtype = MachineType::Int16();
      size = 2;
    } else if (type->IsA(AsmType::Uint32Array())) {
      *mtype = MachineType::Uint32();
      size = 4;
    } else if (type->IsA(AsmType::Int32Array())) {
      *mtype = MachineType::Int32();
      size = 4;
    } else if (type->IsA(AsmType::Uint32Array())) {
      *mtype = MachineType::Uint32();
      size = 4;
    } else if (type->IsA(AsmType::Float32Array())) {
      *mtype = MachineType::Float32();
      size = 4;
    } else if (type->IsA(AsmType::Float64Array())) {
      *mtype = MachineType::Float64();
      size = 8;
    } else {
      UNREACHABLE();
    }
    if (size == 1) {
      // Allow more general expression in byte arrays than the spec
      // strictly permits.
      // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in
      // places that strictly should be HEAP8[HEAP32[..]>>0].
      RECURSE(Visit(expr->key()));
      return;
    }

    Literal* value = expr->key()->AsLiteral();
    if (value) {
      DCHECK(value->raw_value()->IsNumber());
      DCHECK_EQ(kAstI32, TypeOf(value));
      int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber());
      // TODO(titzer): handle overflow here.
      current_function_builder_->EmitI32Const(val * size);
      return;
    }
    BinaryOperation* binop = expr->key()->AsBinaryOperation();
    if (binop) {
      DCHECK_EQ(Token::SAR, binop->op());
      DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber());
      DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral()));
      DCHECK_EQ(size,
                1 << static_cast<int>(
                    binop->right()->AsLiteral()->raw_value()->AsNumber()));
      // Mask bottom bits to match asm.js behavior.
      byte mask = static_cast<byte>(~(size - 1));
      RECURSE(Visit(binop->left()));
      current_function_builder_->EmitWithU8(kExprI8Const, mask);
      current_function_builder_->Emit(kExprI32And);
      return;
    }
    UNREACHABLE();
  }

  void VisitProperty(Property* expr) {
    MachineType type;
    VisitPropertyAndEmitIndex(expr, &type);
    WasmOpcode opcode;
    if (type == MachineType::Int8()) {
      opcode = kExprI32AsmjsLoadMem8S;
    } else if (type == MachineType::Uint8()) {
      opcode = kExprI32AsmjsLoadMem8U;
    } else if (type == MachineType::Int16()) {
      opcode = kExprI32AsmjsLoadMem16S;
    } else if (type == MachineType::Uint16()) {
      opcode = kExprI32AsmjsLoadMem16U;
    } else if (type == MachineType::Int32()) {
      opcode = kExprI32AsmjsLoadMem;
    } else if (type == MachineType::Uint32()) {
      opcode = kExprI32AsmjsLoadMem;
    } else if (type == MachineType::Float32()) {
      opcode = kExprF32AsmjsLoadMem;
    } else if (type == MachineType::Float64()) {
      opcode = kExprF64AsmjsLoadMem;
    } else {
      UNREACHABLE();
    }

    current_function_builder_->Emit(opcode);
  }

  bool VisitStdlibFunction(Call* call, VariableProxy* expr) {
    Variable* var = expr->var();
    AsmTyper::StandardMember standard_object =
        typer_->VariableAsStandardMember(var);
    ZoneList<Expression*>* args = call->arguments();
    LocalType call_type = TypeOf(call);

    switch (standard_object) {
      case AsmTyper::kNone: {
        return false;
      }
      case AsmTyper::kMathAcos: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Acos);
        break;
      }
      case AsmTyper::kMathAsin: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Asin);
        break;
      }
      case AsmTyper::kMathAtan: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Atan);
        break;
      }
      case AsmTyper::kMathCos: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Cos);
        break;
      }
      case AsmTyper::kMathSin: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Sin);
        break;
      }
      case AsmTyper::kMathTan: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Tan);
        break;
      }
      case AsmTyper::kMathExp: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Exp);
        break;
      }
      case AsmTyper::kMathLog: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Log);
        break;
      }
      case AsmTyper::kMathCeil: {
        VisitCallArgs(call);
        if (call_type == kAstF32) {
          current_function_builder_->Emit(kExprF32Ceil);
        } else if (call_type == kAstF64) {
          current_function_builder_->Emit(kExprF64Ceil);
        } else {
          UNREACHABLE();
        }
        break;
      }
      case AsmTyper::kMathFloor: {
        VisitCallArgs(call);
        if (call_type == kAstF32) {
          current_function_builder_->Emit(kExprF32Floor);
        } else if (call_type == kAstF64) {
          current_function_builder_->Emit(kExprF64Floor);
        } else {
          UNREACHABLE();
        }
        break;
      }
      case AsmTyper::kMathSqrt: {
        VisitCallArgs(call);
        if (call_type == kAstF32) {
          current_function_builder_->Emit(kExprF32Sqrt);
        } else if (call_type == kAstF64) {
          current_function_builder_->Emit(kExprF64Sqrt);
        } else {
          UNREACHABLE();
        }
        break;
      }
      case AsmTyper::kMathClz32: {
        VisitCallArgs(call);
        DCHECK(call_type == kAstI32);
        current_function_builder_->Emit(kExprI32Clz);
        break;
      }
      case AsmTyper::kMathAbs: {
        if (call_type == kAstI32) {
          WasmTemporary tmp(current_function_builder_, kAstI32);

          // if set_local(tmp, x) < 0
          Visit(call->arguments()->at(0));
          current_function_builder_->EmitTeeLocal(tmp.index());
          byte code[] = {WASM_I8(0)};
          current_function_builder_->EmitCode(code, sizeof(code));
          current_function_builder_->Emit(kExprI32LtS);
          current_function_builder_->EmitWithU8(kExprIf, kLocalI32);

          // then (0 - tmp)
          current_function_builder_->EmitCode(code, sizeof(code));
          current_function_builder_->EmitGetLocal(tmp.index());
          current_function_builder_->Emit(kExprI32Sub);

          // else tmp
          current_function_builder_->Emit(kExprElse);
          current_function_builder_->EmitGetLocal(tmp.index());
          // end
          current_function_builder_->Emit(kExprEnd);

        } else if (call_type == kAstF32) {
          VisitCallArgs(call);
          current_function_builder_->Emit(kExprF32Abs);
        } else if (call_type == kAstF64) {
          VisitCallArgs(call);
          current_function_builder_->Emit(kExprF64Abs);
        } else {
          UNREACHABLE();
        }
        break;
      }
      case AsmTyper::kMathMin: {
        // TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
        if (call_type == kAstI32) {
          WasmTemporary tmp_x(current_function_builder_, kAstI32);
          WasmTemporary tmp_y(current_function_builder_, kAstI32);

          // if set_local(tmp_x, x) < set_local(tmp_y, y)
          Visit(call->arguments()->at(0));
          current_function_builder_->EmitTeeLocal(tmp_x.index());

          Visit(call->arguments()->at(1));
          current_function_builder_->EmitTeeLocal(tmp_y.index());

          current_function_builder_->Emit(kExprI32LeS);
          current_function_builder_->EmitWithU8(kExprIf, kLocalI32);

          // then tmp_x
          current_function_builder_->EmitGetLocal(tmp_x.index());

          // else tmp_y
          current_function_builder_->Emit(kExprElse);
          current_function_builder_->EmitGetLocal(tmp_y.index());
          current_function_builder_->Emit(kExprEnd);

        } else if (call_type == kAstF32) {
          VisitCallArgs(call);
          current_function_builder_->Emit(kExprF32Min);
        } else if (call_type == kAstF64) {
          VisitCallArgs(call);
          current_function_builder_->Emit(kExprF64Min);
        } else {
          UNREACHABLE();
        }
        break;
      }
      case AsmTyper::kMathMax: {
        // TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
        if (call_type == kAstI32) {
          WasmTemporary tmp_x(current_function_builder_, kAstI32);
          WasmTemporary tmp_y(current_function_builder_, kAstI32);

          // if set_local(tmp_x, x) < set_local(tmp_y, y)
          Visit(call->arguments()->at(0));

          current_function_builder_->EmitTeeLocal(tmp_x.index());

          Visit(call->arguments()->at(1));
          current_function_builder_->EmitTeeLocal(tmp_y.index());

          current_function_builder_->Emit(kExprI32LeS);
          current_function_builder_->EmitWithU8(kExprIf, kLocalI32);

          // then tmp_y
          current_function_builder_->EmitGetLocal(tmp_y.index());

          // else tmp_x
          current_function_builder_->Emit(kExprElse);
          current_function_builder_->EmitGetLocal(tmp_x.index());
          current_function_builder_->Emit(kExprEnd);

        } else if (call_type == kAstF32) {
          VisitCallArgs(call);
          current_function_builder_->Emit(kExprF32Max);
        } else if (call_type == kAstF64) {
          VisitCallArgs(call);
          current_function_builder_->Emit(kExprF64Max);
        } else {
          UNREACHABLE();
        }
        break;
      }
      case AsmTyper::kMathAtan2: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Atan2);
        break;
      }
      case AsmTyper::kMathPow: {
        VisitCallArgs(call);
        DCHECK_EQ(kAstF64, call_type);
        current_function_builder_->Emit(kExprF64Pow);
        break;
      }
      case AsmTyper::kMathImul: {
        VisitCallArgs(call);
        current_function_builder_->Emit(kExprI32Mul);
        break;
      }
      case AsmTyper::kMathFround: {
        DCHECK(args->length() == 1);
        Literal* literal = args->at(0)->AsLiteral();
        if (literal != nullptr) {
          // constant fold Math.fround(#const);
          if (literal->raw_value()->IsNumber()) {
            float val = static_cast<float>(literal->raw_value()->AsNumber());
            byte code[] = {WASM_F32(val)};
            current_function_builder_->EmitCode(code, sizeof(code));
            return true;
          }
        }
        VisitCallArgs(call);
        static const bool kDontIgnoreSign = false;
        switch (TypeIndexOf(args->at(0), kDontIgnoreSign)) {
          case kInt32:
          case kFixnum:
            current_function_builder_->Emit(kExprF32SConvertI32);
            break;
          case kUint32:
            current_function_builder_->Emit(kExprF32UConvertI32);
            break;
          case kFloat32:
            break;
          case kFloat64:
            current_function_builder_->Emit(kExprF32ConvertF64);
            break;
          default:
            UNREACHABLE();
        }
        break;
      }
      default: {
        UNREACHABLE();
        break;
      }
    }
    return true;
  }

  void VisitCallArgs(Call* expr) {
    ZoneList<Expression*>* args = expr->arguments();
    for (int i = 0; i < args->length(); ++i) {
      Expression* arg = args->at(i);
      RECURSE(Visit(arg));
    }
  }

  void VisitCall(Call* expr) { VisitCallExpression(expr); }

  bool VisitCallExpression(Call* expr) {
    Call::CallType call_type = expr->GetCallType();
    bool returns_value = true;
    switch (call_type) {
      case Call::OTHER_CALL: {
        VariableProxy* proxy = expr->expression()->AsVariableProxy();
        if (proxy != nullptr) {
          DCHECK(kFuncScope == scope_ ||
                 typer_->VariableAsStandardMember(proxy->var()) ==
                     AsmTyper::kMathFround);
          if (VisitStdlibFunction(expr, proxy)) {
            return true;
          }
        }
        DCHECK(kFuncScope == scope_);
        VariableProxy* vp = expr->expression()->AsVariableProxy();
        DCHECK_NOT_NULL(vp);
        if (typer_->TypeOf(vp)->AsFFIType() != nullptr) {
          LocalType return_type = TypeOf(expr);
          ZoneList<Expression*>* args = expr->arguments();
          FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
                                   args->length());
          if (return_type != kAstStmt) {
            sig.AddReturn(return_type);
          } else {
            returns_value = false;
          }
          for (int i = 0; i < args->length(); ++i) {
            sig.AddParam(TypeOf(args->at(i)));
          }
          uint32_t index = imported_function_table_.LookupOrInsertImport(
              vp->var(), sig.Build());
          VisitCallArgs(expr);
          current_function_builder_->Emit(kExprCallFunction);
          current_function_builder_->EmitVarInt(index);
        } else {
          WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var());
          VisitCallArgs(expr);
          current_function_builder_->Emit(kExprCallFunction);
          current_function_builder_->EmitDirectCallIndex(
              function->func_index());
          returns_value = function->signature()->return_count() > 0;
        }
        break;
      }
      case Call::KEYED_PROPERTY_CALL: {
        DCHECK_EQ(kFuncScope, scope_);
        Property* p = expr->expression()->AsProperty();
        DCHECK_NOT_NULL(p);
        VariableProxy* var = p->obj()->AsVariableProxy();
        DCHECK_NOT_NULL(var);
        FunctionTableIndices* indices = LookupFunctionTable(var->var());
        Visit(p->key());  // TODO(titzer): should use RECURSE()

        // We have to use a temporary for the correct order of evaluation.
        current_function_builder_->EmitI32Const(indices->start_index);
        current_function_builder_->Emit(kExprI32Add);
        WasmTemporary tmp(current_function_builder_, kAstI32);
        current_function_builder_->EmitSetLocal(tmp.index());

        VisitCallArgs(expr);

        current_function_builder_->EmitGetLocal(tmp.index());
        current_function_builder_->Emit(kExprCallIndirect);
        current_function_builder_->EmitVarInt(indices->signature_index);
        returns_value =
            builder_->GetSignature(indices->signature_index)->return_count() >
            0;
        break;
      }
      default:
        UNREACHABLE();
    }
    return returns_value;
  }

  void VisitCallNew(CallNew* expr) { UNREACHABLE(); }

  void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); }

  void VisitUnaryOperation(UnaryOperation* expr) {
    RECURSE(Visit(expr->expression()));
    switch (expr->op()) {
      case Token::NOT: {
        DCHECK_EQ(kAstI32, TypeOf(expr->expression()));
        current_function_builder_->Emit(kExprI32Eqz);
        break;
      }
      default:
        UNREACHABLE();
    }
  }

  void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); }

  bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op,
                               int32_t val) {
    DCHECK_NOT_NULL(expr->right());
    if (expr->op() == op && expr->right()->IsLiteral() &&
        TypeOf(expr) == kAstI32) {
      Literal* right = expr->right()->AsLiteral();
      DCHECK(right->raw_value()->IsNumber());
      if (static_cast<int32_t>(right->raw_value()->AsNumber()) == val) {
        return true;
      }
    }
    return false;
  }

  bool MatchDoubleBinaryOperation(BinaryOperation* expr, Token::Value op,
                                  double val) {
    DCHECK_NOT_NULL(expr->right());
    if (expr->op() == op && expr->right()->IsLiteral() &&
        TypeOf(expr) == kAstF64) {
      Literal* right = expr->right()->AsLiteral();
      DCHECK(right->raw_value()->IsNumber());
      if (right->raw_value()->AsNumber() == val) {
        return true;
      }
    }
    return false;
  }

  enum ConvertOperation { kNone, kAsIs, kToInt, kToDouble };

  ConvertOperation MatchOr(BinaryOperation* expr) {
    if (MatchIntBinaryOperation(expr, Token::BIT_OR, 0) &&
        (TypeOf(expr->left()) == kAstI32)) {
      return kAsIs;
    } else {
      return kNone;
    }
  }

  ConvertOperation MatchShr(BinaryOperation* expr) {
    if (MatchIntBinaryOperation(expr, Token::SHR, 0)) {
      // TODO(titzer): this probably needs to be kToUint
      return (TypeOf(expr->left()) == kAstI32) ? kAsIs : kToInt;
    } else {
      return kNone;
    }
  }

  ConvertOperation MatchXor(BinaryOperation* expr) {
    if (MatchIntBinaryOperation(expr, Token::BIT_XOR, 0xffffffff)) {
      DCHECK_EQ(kAstI32, TypeOf(expr->left()));
      DCHECK_EQ(kAstI32, TypeOf(expr->right()));
      BinaryOperation* op = expr->left()->AsBinaryOperation();
      if (op != nullptr) {
        if (MatchIntBinaryOperation(op, Token::BIT_XOR, 0xffffffff)) {
          DCHECK_EQ(kAstI32, TypeOf(op->right()));
          if (TypeOf(op->left()) != kAstI32) {
            return kToInt;
          } else {
            return kAsIs;
          }
        }
      }
    }
    return kNone;
  }

  ConvertOperation MatchMul(BinaryOperation* expr) {
    if (MatchDoubleBinaryOperation(expr, Token::MUL, 1.0)) {
      DCHECK_EQ(kAstF64, TypeOf(expr->right()));
      if (TypeOf(expr->left()) != kAstF64) {
        return kToDouble;
      } else {
        return kAsIs;
      }
    } else {
      return kNone;
    }
  }

  ConvertOperation MatchBinaryOperation(BinaryOperation* expr) {
    switch (expr->op()) {
      case Token::BIT_OR:
        return MatchOr(expr);
      case Token::SHR:
        return MatchShr(expr);
      case Token::BIT_XOR:
        return MatchXor(expr);
      case Token::MUL:
        return MatchMul(expr);
      default:
        return kNone;
    }
  }

// Work around Mul + Div being defined in PPC assembler.
#ifdef Mul
#undef Mul
#endif

#define NON_SIGNED_BINOP(op)      \
  static WasmOpcode opcodes[] = { \
    kExprI32##op,                 \
    kExprI32##op,                 \
    kExprF32##op,                 \
    kExprF64##op                  \
  }

#define SIGNED_BINOP(op)          \
  static WasmOpcode opcodes[] = { \
    kExprI32##op##S,              \
    kExprI32##op##U,              \
    kExprF32##op,                 \
    kExprF64##op                  \
  }

#define NON_SIGNED_INT_BINOP(op) \
  static WasmOpcode opcodes[] = { kExprI32##op, kExprI32##op }

#define BINOP_CASE(token, op, V, ignore_sign)                         \
  case token: {                                                       \
    V(op);                                                            \
    int type = TypeIndexOf(expr->left(), expr->right(), ignore_sign); \
    current_function_builder_->Emit(opcodes[type]);                   \
    break;                                                            \
  }

  Expression* GetLeft(BinaryOperation* expr) {
    if (expr->op() == Token::BIT_XOR) {
      return expr->left()->AsBinaryOperation()->left();
    } else {
      return expr->left();
    }
  }

  void VisitBinaryOperation(BinaryOperation* expr) {
    ConvertOperation convertOperation = MatchBinaryOperation(expr);
    static const bool kDontIgnoreSign = false;
    if (convertOperation == kToDouble) {
      RECURSE(Visit(expr->left()));
      TypeIndex type = TypeIndexOf(expr->left(), kDontIgnoreSign);
      if (type == kInt32 || type == kFixnum) {
        current_function_builder_->Emit(kExprF64SConvertI32);
      } else if (type == kUint32) {
        current_function_builder_->Emit(kExprF64UConvertI32);
      } else if (type == kFloat32) {
        current_function_builder_->Emit(kExprF64ConvertF32);
      } else {
        UNREACHABLE();
      }
    } else if (convertOperation == kToInt) {
      RECURSE(Visit(GetLeft(expr)));
      TypeIndex type = TypeIndexOf(GetLeft(expr), kDontIgnoreSign);
      if (type == kFloat32) {
        current_function_builder_->Emit(kExprI32AsmjsSConvertF32);
      } else if (type == kFloat64) {
        current_function_builder_->Emit(kExprI32AsmjsSConvertF64);
      } else {
        UNREACHABLE();
      }
    } else if (convertOperation == kAsIs) {
      RECURSE(Visit(GetLeft(expr)));
    } else {
      if (expr->op() == Token::COMMA) {
        RECURSE(VisitForEffect(expr->left()));
        RECURSE(Visit(expr->right()));
        return;
      }
      RECURSE(Visit(expr->left()));
      RECURSE(Visit(expr->right()));

      switch (expr->op()) {
        BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true);
        BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true);
        BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true);
        BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true);
        BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true);
        BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true);
        BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true);
        BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true);
        BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true);
        case Token::DIV: {
          static WasmOpcode opcodes[] = {kExprI32AsmjsDivS, kExprI32AsmjsDivU,
                                         kExprF32Div, kExprF64Div};
          int type = TypeIndexOf(expr->left(), expr->right(), false);
          current_function_builder_->Emit(opcodes[type]);
          break;
        }
        case Token::MOD: {
          TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false);
          if (type == kInt32) {
            current_function_builder_->Emit(kExprI32AsmjsRemS);
          } else if (type == kUint32) {
            current_function_builder_->Emit(kExprI32AsmjsRemU);
          } else if (type == kFloat64) {
            current_function_builder_->Emit(kExprF64Mod);
            return;
          } else {
            UNREACHABLE();
          }
          break;
        }
        case Token::COMMA: {
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }

  void VisitCompareOperation(CompareOperation* expr) {
    RECURSE(Visit(expr->left()));
    RECURSE(Visit(expr->right()));
    switch (expr->op()) {
      BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false);
      BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false);
      BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false);
      BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false);
      BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false);
      default:
        UNREACHABLE();
    }
  }

#undef BINOP_CASE
#undef NON_SIGNED_INT_BINOP
#undef SIGNED_BINOP
#undef NON_SIGNED_BINOP

  enum TypeIndex {
    kInt32 = 0,
    kUint32 = 1,
    kFloat32 = 2,
    kFloat64 = 3,
    kFixnum = 4
  };

  TypeIndex TypeIndexOf(Expression* left, Expression* right, bool ignore_sign) {
    TypeIndex left_index = TypeIndexOf(left, ignore_sign);
    TypeIndex right_index = TypeIndexOf(right, ignore_sign);
    if (left_index == kFixnum) {
      left_index = right_index;
    }
    if (right_index == kFixnum) {
      right_index = left_index;
    }
    if (left_index == kFixnum && right_index == kFixnum) {
      left_index = kInt32;
      right_index = kInt32;
    }
    if (left_index != right_index) {
      DCHECK(ignore_sign && (left_index <= 1) && (right_index <= 1));
    }
    return left_index;
  }

  TypeIndex TypeIndexOf(Expression* expr, bool ignore_sign) {
    AsmType* type = typer_->TypeOf(expr);
    if (type->IsA(AsmType::FixNum())) {
      return kFixnum;
    }

    if (type->IsA(AsmType::Signed())) {
      return kInt32;
    }

    if (type->IsA(AsmType::Unsigned())) {
      return kUint32;
    }

    if (type->IsA(AsmType::Intish())) {
      if (!ignore_sign) {
        // TODO(jpp): log a warning and move on.
      }
      return kInt32;
    }

    if (type->IsA(AsmType::Floatish())) {
      return kFloat32;
    }

    if (type->IsA(AsmType::DoubleQ())) {
      return kFloat64;
    }

    UNREACHABLE();
    return kInt32;
  }

#undef CASE
#undef NON_SIGNED_INT
#undef SIGNED
#undef NON_SIGNED

  void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); }

  void VisitDeclarations(ZoneList<Declaration*>* decls) {
    for (int i = 0; i < decls->length(); ++i) {
      Declaration* decl = decls->at(i);
      RECURSE(Visit(decl));
    }
  }

  void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); }

  void VisitSpread(Spread* expr) { UNREACHABLE(); }

  void VisitSuperPropertyReference(SuperPropertyReference* expr) {
    UNREACHABLE();
  }

  void VisitSuperCallReference(SuperCallReference* expr) { UNREACHABLE(); }

  void VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement* expr) {
    UNREACHABLE();
  }

  void VisitDoExpression(DoExpression* expr) { UNREACHABLE(); }

  void VisitRewritableExpression(RewritableExpression* expr) { UNREACHABLE(); }

  struct IndexContainer : public ZoneObject {
    uint32_t index;
  };

  uint32_t LookupOrInsertLocal(Variable* v, LocalType type) {
    DCHECK_NOT_NULL(current_function_builder_);
    ZoneHashMap::Entry* entry =
        local_variables_.Lookup(v, ComputePointerHash(v));
    if (entry == nullptr) {
      uint32_t index;
      DCHECK(!v->IsParameter());
      index = current_function_builder_->AddLocal(type);
      IndexContainer* container = new (zone()) IndexContainer();
      container->index = index;
      entry = local_variables_.LookupOrInsert(v, ComputePointerHash(v),
                                              ZoneAllocationPolicy(zone()));
      entry->value = container;
    }
    return (reinterpret_cast<IndexContainer*>(entry->value))->index;
  }

  void InsertParameter(Variable* v, LocalType type, uint32_t index) {
    DCHECK(v->IsParameter());
    DCHECK_NOT_NULL(current_function_builder_);
    ZoneHashMap::Entry* entry =
        local_variables_.Lookup(v, ComputePointerHash(v));
    DCHECK_NULL(entry);
    IndexContainer* container = new (zone()) IndexContainer();
    container->index = index;
    entry = local_variables_.LookupOrInsert(v, ComputePointerHash(v),
                                            ZoneAllocationPolicy(zone()));
    entry->value = container;
  }

  uint32_t LookupOrInsertGlobal(Variable* v, LocalType type) {
    ZoneHashMap::Entry* entry =
        global_variables_.Lookup(v, ComputePointerHash(v));
    if (entry == nullptr) {
      uint32_t index = builder_->AddGlobal(type, 0);
      IndexContainer* container = new (zone()) IndexContainer();
      container->index = index;
      entry = global_variables_.LookupOrInsert(v, ComputePointerHash(v),
                                               ZoneAllocationPolicy(zone()));
      entry->value = container;
    }
    return (reinterpret_cast<IndexContainer*>(entry->value))->index;
  }

  WasmFunctionBuilder* LookupOrInsertFunction(Variable* v) {
    DCHECK_NOT_NULL(builder_);
    ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v));
    if (entry == nullptr) {
      auto* func_type = typer_->TypeOf(v)->AsFunctionType();
      DCHECK_NOT_NULL(func_type);
      // Build the signature for the function.
      LocalType return_type = TypeFrom(func_type->ReturnType());
      const auto& arguments = func_type->Arguments();
      FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
                             arguments.size());
      if (return_type != kAstStmt) b.AddReturn(return_type);
      for (int i = 0; i < static_cast<int>(arguments.size()); ++i) {
        LocalType type = TypeFrom(arguments[i]);
        DCHECK_NE(kAstStmt, type);
        b.AddParam(type);
      }

      WasmFunctionBuilder* function = builder_->AddFunction(b.Build());
      entry = functions_.LookupOrInsert(v, ComputePointerHash(v),
                                        ZoneAllocationPolicy(zone()));
      function->SetName(
          {reinterpret_cast<const char*>(v->raw_name()->raw_data()),
           v->raw_name()->length()});
      entry->value = function;
    }
    return (reinterpret_cast<WasmFunctionBuilder*>(entry->value));
  }

  LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); }

  LocalType TypeFrom(AsmType* type) {
    if (type->IsA(AsmType::Intish())) {
      return kAstI32;
    }

    if (type->IsA(AsmType::Floatish())) {
      return kAstF32;
    }

    if (type->IsA(AsmType::DoubleQ())) {
      return kAstF64;
    }

    return kAstStmt;
  }

  Zone* zone() { return zone_; }

  ZoneHashMap local_variables_;
  ZoneHashMap functions_;
  ZoneHashMap global_variables_;
  AsmScope scope_;
  WasmModuleBuilder* builder_;
  WasmFunctionBuilder* current_function_builder_;
  FunctionLiteral* literal_;
  Isolate* isolate_;
  Zone* zone_;
  AsmTyper* typer_;
  ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
  ZoneVector<ForeignVariable> foreign_variables_;
  WasmFunctionBuilder* init_function_;
  WasmFunctionBuilder* foreign_init_function_;
  uint32_t next_table_index_;
  ZoneHashMap function_tables_;
  ImportedFunctionTable imported_function_table_;

  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();

 private:
  DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl);
};

AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
                               FunctionLiteral* literal, AsmTyper* typer)
    : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {}

// TODO(aseemgarg): probably should take zone (to write wasm to) as input so
// that zone in constructor may be thrown away once wasm module is written.
ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) {
  AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_);
  impl.Build();
  *foreign_args = impl.GetForeignArgs();
  ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_);
  impl.builder_->WriteTo(*buffer);
  return buffer;
}

const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__";
const char* AsmWasmBuilder::single_function_name = "__single_function__";

}  // namespace wasm
}  // namespace internal
}  // namespace v8
