// 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/compiler/bytecode-graph-builder.h"

#include "src/compiler/linkage.h"
#include "src/compiler/operator-properties.h"
#include "src/interpreter/bytecode-array-iterator.h"

namespace v8 {
namespace internal {
namespace compiler {

// Issues:
// - Need to deal with FrameState / FrameStateBeforeAndAfter / StateValue.
// - Scopes - intimately tied to AST. Need to eval what is needed.
// - Need to resolve closure parameter treatment.
BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
                                               int register_count,
                                               int parameter_count,
                                               Node* control_dependency,
                                               Node* context)
    : builder_(builder),
      register_count_(register_count),
      parameter_count_(parameter_count),
      context_(context),
      control_dependency_(control_dependency),
      effect_dependency_(control_dependency),
      values_(builder->local_zone()) {
  // The layout of values_ is:
  //
  // [receiver] [parameters] [registers]
  //
  // parameter[0] is the receiver (this), parameters 1..N are the
  // parameters supplied to the method (arg0..argN-1). The accumulator
  // is stored separately.

  // Parameters including the receiver
  for (int i = 0; i < parameter_count; i++) {
    const char* debug_name = (i == 0) ? "%this" : nullptr;
    const Operator* op = common()->Parameter(i, debug_name);
    Node* parameter = builder->graph()->NewNode(op, graph()->start());
    values()->push_back(parameter);
  }

  // Registers
  register_base_ = static_cast<int>(values()->size());
  Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
  values()->insert(values()->end(), register_count, undefined_constant);

  // Accumulator
  accumulator_ = undefined_constant;
}


int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
    interpreter::Register the_register) const {
  if (the_register.is_parameter()) {
    return the_register.ToParameterIndex(parameter_count());
  } else {
    return the_register.index() + register_base();
  }
}


void BytecodeGraphBuilder::Environment::BindRegister(
    interpreter::Register the_register, Node* node) {
  int values_index = RegisterToValuesIndex(the_register);
  values()->at(values_index) = node;
}


Node* BytecodeGraphBuilder::Environment::LookupRegister(
    interpreter::Register the_register) const {
  int values_index = RegisterToValuesIndex(the_register);
  return values()->at(values_index);
}


void BytecodeGraphBuilder::Environment::BindAccumulator(Node* node) {
  accumulator_ = node;
}


Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
  return accumulator_;
}


bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const {
  return GetControlDependency()->opcode() == IrOpcode::kDead;
}


void BytecodeGraphBuilder::Environment::MarkAsUnreachable() {
  UpdateControlDependency(builder()->jsgraph()->Dead());
}


BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
                                           CompilationInfo* compilation_info,
                                           JSGraph* jsgraph)
    : local_zone_(local_zone),
      info_(compilation_info),
      jsgraph_(jsgraph),
      input_buffer_size_(0),
      input_buffer_(nullptr),
      exit_controls_(local_zone) {
  bytecode_array_ = handle(info()->shared_info()->bytecode_array());
}


Node* BytecodeGraphBuilder::GetFunctionContext() {
  if (!function_context_.is_set()) {
    // Parameter (arity + 1) is special for the outer context of the function
    const Operator* op =
        common()->Parameter(bytecode_array()->parameter_count(), "%context");
    Node* node = NewNode(op, graph()->start());
    function_context_.set(node);
  }
  return function_context_.get();
}


bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
  // Set up the basic structure of the graph. Outputs for {Start} are
  // the formal parameters (including the receiver) plus context and
  // closure.

  // The additional count items are for the context and closure.
  int actual_parameter_count = bytecode_array()->parameter_count() + 2;
  graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));

  Environment env(this, bytecode_array()->register_count(),
                  bytecode_array()->parameter_count(), graph()->start(),
                  GetFunctionContext());
  set_environment(&env);

  // Build function context only if there are context allocated variables.
  if (info()->num_heap_slots() > 0) {
    UNIMPLEMENTED();  // TODO(oth): Write ast-graph-builder equivalent.
  } else {
    // Simply use the outer function context in building the graph.
    CreateGraphBody(stack_check);
  }

  // Finish the basic structure of the graph.
  DCHECK_NE(0u, exit_controls_.size());
  int const input_count = static_cast<int>(exit_controls_.size());
  Node** const inputs = &exit_controls_.front();
  Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
  graph()->SetEnd(end);

  return true;
}


void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) {
  // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments
  // object setup, this function variable if used, tracing hooks.
  VisitBytecodes();
}


void BytecodeGraphBuilder::VisitBytecodes() {
  interpreter::BytecodeArrayIterator iterator(bytecode_array());
  while (!iterator.done()) {
    switch (iterator.current_bytecode()) {
#define BYTECODE_CASE(name, ...)       \
  case interpreter::Bytecode::k##name: \
    Visit##name(iterator);             \
    break;
      BYTECODE_LIST(BYTECODE_CASE)
#undef BYTECODE_CODE
    }
    iterator.Advance();
  }
}


void BytecodeGraphBuilder::VisitLdaZero(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->ZeroConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaSmi8(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->Constant(iterator.GetImmediateOperand(0));
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaUndefined(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->UndefinedConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaNull(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->NullConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaTheHole(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->TheHoleConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaTrue(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->TrueConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaFalse(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->FalseConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdar(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  environment()->BindAccumulator(value);
}


void BytecodeGraphBuilder::VisitStar(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* value = environment()->LookupAccumulator();
  environment()->BindRegister(iterator.GetRegisterOperand(0), value);
}


void BytecodeGraphBuilder::VisitLdaGlobal(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitStaGlobal(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitLdaContextSlot(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitLoadICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitLoadICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitKeyedLoadICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitKeyedLoadICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitStoreICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitStoreICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitKeyedStoreICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitKeyedStoreICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitCall(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitCallRuntime(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::BuildBinaryOp(
    const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
  Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* right = environment()->LookupAccumulator();
  Node* node = NewNode(js_op, left, right);

  // TODO(oth): Real frame state and environment check pointing.
  int frame_state_count =
      OperatorProperties::GetFrameStateInputCount(node->op());
  for (int i = 0; i < frame_state_count; i++) {
    NodeProperties::ReplaceFrameStateInput(node, i,
                                           jsgraph()->EmptyFrameState());
  }
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitAdd(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->Add(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitSub(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->Subtract(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitMul(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->Multiply(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitDiv(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->Divide(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitMod(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->Modulus(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitShiftLeft(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->ShiftLeft(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitShiftRight(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->ShiftRight(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitShiftRightLogical(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildBinaryOp(javascript()->ShiftRightLogical(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitLogicalNot(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTypeOf(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestNotEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestEqualStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestNotEqualStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestLessThan(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestGreaterThan(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestLessThanOrEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestIn(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitTestInstanceOf(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitToBoolean(
    const interpreter::BytecodeArrayIterator& ToBoolean) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitJump(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitJumpConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitJumpIfTrue(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitJumpIfTrueConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitJumpIfFalse(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitJumpIfFalseConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitReturn(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* control =
      NewNode(common()->Return(), environment()->LookupAccumulator());
  UpdateControlDependencyToLeaveFunction(control);
}


Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
  if (size > input_buffer_size_) {
    size = size + kInputBufferSizeIncrement + input_buffer_size_;
    input_buffer_ = local_zone()->NewArray<Node*>(size);
    input_buffer_size_ = size;
  }
  return input_buffer_;
}


Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
                                     Node** value_inputs, bool incomplete) {
  DCHECK_EQ(op->ValueInputCount(), value_input_count);

  bool has_context = OperatorProperties::HasContextInput(op);
  int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
  bool has_control = op->ControlInputCount() == 1;
  bool has_effect = op->EffectInputCount() == 1;

  DCHECK_LT(op->ControlInputCount(), 2);
  DCHECK_LT(op->EffectInputCount(), 2);

  Node* result = NULL;
  if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
    result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
  } else {
    int input_count_with_deps = value_input_count;
    if (has_context) ++input_count_with_deps;
    input_count_with_deps += frame_state_count;
    if (has_control) ++input_count_with_deps;
    if (has_effect) ++input_count_with_deps;
    Node** buffer = EnsureInputBufferSize(input_count_with_deps);
    memcpy(buffer, value_inputs, kPointerSize * value_input_count);
    Node** current_input = buffer + value_input_count;
    if (has_context) {
      *current_input++ = environment()->Context();
    }
    for (int i = 0; i < frame_state_count; i++) {
      // The frame state will be inserted later. Here we misuse
      // the {Dead} node as a sentinel to be later overwritten
      // with the real frame state.
      *current_input++ = jsgraph()->Dead();
    }
    if (has_effect) {
      *current_input++ = environment()->GetEffectDependency();
    }
    if (has_control) {
      *current_input++ = environment()->GetControlDependency();
    }
    result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
    if (!environment()->IsMarkedAsUnreachable()) {
      // Update the current control dependency for control-producing nodes.
      if (NodeProperties::IsControl(result)) {
        environment()->UpdateControlDependency(result);
      }
      // Update the current effect dependency for effect-producing nodes.
      if (result->op()->EffectOutputCount() > 0) {
        environment()->UpdateEffectDependency(result);
      }
      // Add implicit success continuation for throwing nodes.
      if (!result->op()->HasProperty(Operator::kNoThrow)) {
        const Operator* if_success = common()->IfSuccess();
        Node* on_success = graph()->NewNode(if_success, result);
        environment_->UpdateControlDependency(on_success);
      }
    }
  }

  return result;
}


Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
  int inputs = control->op()->ControlInputCount() + 1;
  if (control->opcode() == IrOpcode::kLoop) {
    // Control node for loop exists, add input.
    const Operator* op = common()->Loop(inputs);
    control->AppendInput(graph_zone(), other);
    NodeProperties::ChangeOp(control, op);
  } else if (control->opcode() == IrOpcode::kMerge) {
    // Control node for merge exists, add input.
    const Operator* op = common()->Merge(inputs);
    control->AppendInput(graph_zone(), other);
    NodeProperties::ChangeOp(control, op);
  } else {
    // Control node is a singleton, introduce a merge.
    const Operator* op = common()->Merge(inputs);
    Node* merge_inputs[] = {control, other};
    control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
  }
  return control;
}


void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
  if (environment()->IsMarkedAsUnreachable()) return;
  environment()->MarkAsUnreachable();
  exit_controls_.push_back(exit);
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
