// Copyright 2014 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/raw-machine-assembler.h"

#include "src/code-factory.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/scheduler.h"

namespace v8 {
namespace internal {
namespace compiler {

RawMachineAssembler::RawMachineAssembler(Isolate* isolate, Graph* graph,
                                         CallDescriptor* call_descriptor,
                                         MachineRepresentation word,
                                         MachineOperatorBuilder::Flags flags)
    : isolate_(isolate),
      graph_(graph),
      schedule_(new (zone()) Schedule(zone())),
      machine_(zone(), word, flags),
      common_(zone()),
      call_descriptor_(call_descriptor),
      parameters_(parameter_count(), zone()),
      current_block_(schedule()->start()) {
  int param_count = static_cast<int>(parameter_count());
  // Add an extra input for the JSFunction parameter to the start node.
  graph->SetStart(graph->NewNode(common_.Start(param_count + 1)));
  for (size_t i = 0; i < parameter_count(); ++i) {
    parameters_[i] =
        AddNode(common()->Parameter(static_cast<int>(i)), graph->start());
  }
  graph->SetEnd(graph->NewNode(common_.End(0)));
}

Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value,
                                                     RelocInfo::Mode rmode) {
  return kPointerSize == 8
             ? RelocatableInt64Constant(value, rmode)
             : RelocatableInt32Constant(static_cast<int>(value), rmode);
}

Schedule* RawMachineAssembler::Export() {
  // Compute the correct codegen order.
  DCHECK(schedule_->rpo_order()->empty());
  OFStream os(stdout);
  if (FLAG_trace_turbo_scheduler) {
    PrintF("--- RAW SCHEDULE -------------------------------------------\n");
    os << *schedule_;
  }
  schedule_->EnsureCFGWellFormedness();
  schedule_->PropagateDeferredMark();
  if (FLAG_trace_turbo_scheduler) {
    PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n");
    os << *schedule_;
  }
  Scheduler::ComputeSpecialRPO(zone(), schedule_);
  // Invalidate RawMachineAssembler.
  Schedule* schedule = schedule_;
  schedule_ = nullptr;
  return schedule;
}


Node* RawMachineAssembler::Parameter(size_t index) {
  DCHECK(index < parameter_count());
  return parameters_[index];
}


void RawMachineAssembler::Goto(RawMachineLabel* label) {
  DCHECK(current_block_ != schedule()->end());
  schedule()->AddGoto(CurrentBlock(), Use(label));
  current_block_ = nullptr;
}


void RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val,
                                 RawMachineLabel* false_val) {
  DCHECK(current_block_ != schedule()->end());
  Node* branch = MakeNode(common()->Branch(), 1, &condition);
  schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
  current_block_ = nullptr;
}


void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
                                 int32_t* case_values,
                                 RawMachineLabel** case_labels,
                                 size_t case_count) {
  DCHECK_NE(schedule()->end(), current_block_);
  size_t succ_count = case_count + 1;
  Node* switch_node = AddNode(common()->Switch(succ_count), index);
  BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count);
  for (size_t index = 0; index < case_count; ++index) {
    int32_t case_value = case_values[index];
    BasicBlock* case_block = schedule()->NewBasicBlock();
    Node* case_node =
        graph()->NewNode(common()->IfValue(case_value), switch_node);
    schedule()->AddNode(case_block, case_node);
    schedule()->AddGoto(case_block, Use(case_labels[index]));
    succ_blocks[index] = case_block;
  }
  BasicBlock* default_block = schedule()->NewBasicBlock();
  Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node);
  schedule()->AddNode(default_block, default_node);
  schedule()->AddGoto(default_block, Use(default_label));
  succ_blocks[case_count] = default_block;
  schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count);
  current_block_ = nullptr;
}


void RawMachineAssembler::Return(Node* value) {
  Node* ret = MakeNode(common()->Return(), 1, &value);
  schedule()->AddReturn(CurrentBlock(), ret);
  current_block_ = nullptr;
}


void RawMachineAssembler::Return(Node* v1, Node* v2) {
  Node* values[] = {v1, v2};
  Node* ret = MakeNode(common()->Return(2), 2, values);
  schedule()->AddReturn(CurrentBlock(), ret);
  current_block_ = nullptr;
}


void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
  Node* values[] = {v1, v2, v3};
  Node* ret = MakeNode(common()->Return(3), 3, values);
  schedule()->AddReturn(CurrentBlock(), ret);
  current_block_ = nullptr;
}

void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }

void RawMachineAssembler::Comment(const char* msg) {
  AddNode(machine()->Comment(msg));
}

Node* RawMachineAssembler::CallN(CallDescriptor* desc, Node* function,
                                 Node** args) {
  int param_count =
      static_cast<int>(desc->GetMachineSignature()->parameter_count());
  int input_count = param_count + 1;
  Node** buffer = zone()->NewArray<Node*>(input_count);
  int index = 0;
  buffer[index++] = function;
  for (int i = 0; i < param_count; i++) {
    buffer[index++] = args[i];
  }
  return AddNode(common()->Call(desc), input_count, buffer);
}


Node* RawMachineAssembler::CallNWithFrameState(CallDescriptor* desc,
                                               Node* function, Node** args,
                                               Node* frame_state) {
  DCHECK(desc->NeedsFrameState());
  int param_count =
      static_cast<int>(desc->GetMachineSignature()->parameter_count());
  int input_count = param_count + 2;
  Node** buffer = zone()->NewArray<Node*>(input_count);
  int index = 0;
  buffer[index++] = function;
  for (int i = 0; i < param_count; i++) {
    buffer[index++] = args[i];
  }
  buffer[index++] = frame_state;
  return AddNode(common()->Call(desc), input_count, buffer);
}

Node* RawMachineAssembler::CallRuntime0(Runtime::FunctionId function,
                                        Node* context) {
  CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
      zone(), function, 0, Operator::kNoProperties, CallDescriptor::kNoFlags);
  int return_count = static_cast<int>(descriptor->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(0);

  return AddNode(common()->Call(descriptor), centry, ref, arity, context);
}

Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
                                        Node* arg1, Node* context) {
  CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
      zone(), function, 1, Operator::kNoProperties, CallDescriptor::kNoFlags);
  int return_count = static_cast<int>(descriptor->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(1);

  return AddNode(common()->Call(descriptor), centry, arg1, ref, arity, context);
}


Node* RawMachineAssembler::CallRuntime2(Runtime::FunctionId function,
                                        Node* arg1, Node* arg2, Node* context) {
  CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
      zone(), function, 2, Operator::kNoProperties, CallDescriptor::kNoFlags);
  int return_count = static_cast<int>(descriptor->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(2);

  return AddNode(common()->Call(descriptor), centry, arg1, arg2, ref, arity,
                 context);
}

Node* RawMachineAssembler::CallRuntime3(Runtime::FunctionId function,
                                        Node* arg1, Node* arg2, Node* arg3,
                                        Node* context) {
  CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
      zone(), function, 3, Operator::kNoProperties, CallDescriptor::kNoFlags);
  int return_count = static_cast<int>(descriptor->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(3);

  return AddNode(common()->Call(descriptor), centry, arg1, arg2, arg3, ref,
                 arity, context);
}

Node* RawMachineAssembler::CallRuntime4(Runtime::FunctionId function,
                                        Node* arg1, Node* arg2, Node* arg3,
                                        Node* arg4, Node* context) {
  CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
      zone(), function, 4, Operator::kNoProperties, CallDescriptor::kNoFlags);
  int return_count = static_cast<int>(descriptor->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(4);

  return AddNode(common()->Call(descriptor), centry, arg1, arg2, arg3, arg4,
                 ref, arity, context);
}


Node* RawMachineAssembler::TailCallN(CallDescriptor* desc, Node* function,
                                     Node** args) {
  int param_count =
      static_cast<int>(desc->GetMachineSignature()->parameter_count());
  int input_count = param_count + 1;
  Node** buffer = zone()->NewArray<Node*>(input_count);
  int index = 0;
  buffer[index++] = function;
  for (int i = 0; i < param_count; i++) {
    buffer[index++] = args[i];
  }
  Node* tail_call = MakeNode(common()->TailCall(desc), input_count, buffer);
  schedule()->AddTailCall(CurrentBlock(), tail_call);
  current_block_ = nullptr;
  return tail_call;
}

Node* RawMachineAssembler::TailCallRuntime0(Runtime::FunctionId function,
                                            Node* context) {
  const int kArity = 0;
  CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
      zone(), function, kArity, Operator::kNoProperties,
      CallDescriptor::kSupportsTailCalls);
  int return_count = static_cast<int>(desc->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(kArity);

  Node* nodes[] = {centry, ref, arity, context};
  Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);

  schedule()->AddTailCall(CurrentBlock(), tail_call);
  current_block_ = nullptr;
  return tail_call;
}

Node* RawMachineAssembler::TailCallRuntime1(Runtime::FunctionId function,
                                            Node* arg1, Node* context) {
  const int kArity = 1;
  CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
      zone(), function, kArity, Operator::kNoProperties,
      CallDescriptor::kSupportsTailCalls);
  int return_count = static_cast<int>(desc->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(kArity);

  Node* nodes[] = {centry, arg1, ref, arity, context};
  Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);

  schedule()->AddTailCall(CurrentBlock(), tail_call);
  current_block_ = nullptr;
  return tail_call;
}


Node* RawMachineAssembler::TailCallRuntime2(Runtime::FunctionId function,
                                            Node* arg1, Node* arg2,
                                            Node* context) {
  const int kArity = 2;
  CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
      zone(), function, kArity, Operator::kNoProperties,
      CallDescriptor::kSupportsTailCalls);
  int return_count = static_cast<int>(desc->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(kArity);

  Node* nodes[] = {centry, arg1, arg2, ref, arity, context};
  Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);

  schedule()->AddTailCall(CurrentBlock(), tail_call);
  current_block_ = nullptr;
  return tail_call;
}

Node* RawMachineAssembler::TailCallRuntime3(Runtime::FunctionId function,
                                            Node* arg1, Node* arg2, Node* arg3,
                                            Node* context) {
  const int kArity = 3;
  CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
      zone(), function, kArity, Operator::kNoProperties,
      CallDescriptor::kSupportsTailCalls);
  int return_count = static_cast<int>(desc->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(kArity);

  Node* nodes[] = {centry, arg1, arg2, arg3, ref, arity, context};
  Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);

  schedule()->AddTailCall(CurrentBlock(), tail_call);
  current_block_ = nullptr;
  return tail_call;
}

Node* RawMachineAssembler::TailCallRuntime4(Runtime::FunctionId function,
                                            Node* arg1, Node* arg2, Node* arg3,
                                            Node* arg4, Node* context) {
  const int kArity = 4;
  CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
      zone(), function, kArity, Operator::kNoProperties,
      CallDescriptor::kSupportsTailCalls);
  int return_count = static_cast<int>(desc->ReturnCount());

  Node* centry = HeapConstant(CEntryStub(isolate(), return_count).GetCode());
  Node* ref = AddNode(
      common()->ExternalConstant(ExternalReference(function, isolate())));
  Node* arity = Int32Constant(kArity);

  Node* nodes[] = {centry, arg1, arg2, arg3, arg4, ref, arity, context};
  Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);

  schedule()->AddTailCall(CurrentBlock(), tail_call);
  current_block_ = nullptr;
  return tail_call;
}

Node* RawMachineAssembler::CallCFunction0(MachineType return_type,
                                          Node* function) {
  MachineSignature::Builder builder(zone(), 1, 0);
  builder.AddReturn(return_type);
  const CallDescriptor* descriptor =
      Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());

  return AddNode(common()->Call(descriptor), function);
}


Node* RawMachineAssembler::CallCFunction1(MachineType return_type,
                                          MachineType arg0_type, Node* function,
                                          Node* arg0) {
  MachineSignature::Builder builder(zone(), 1, 1);
  builder.AddReturn(return_type);
  builder.AddParam(arg0_type);
  const CallDescriptor* descriptor =
      Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());

  return AddNode(common()->Call(descriptor), function, arg0);
}


Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
                                          MachineType arg0_type,
                                          MachineType arg1_type, Node* function,
                                          Node* arg0, Node* arg1) {
  MachineSignature::Builder builder(zone(), 1, 2);
  builder.AddReturn(return_type);
  builder.AddParam(arg0_type);
  builder.AddParam(arg1_type);
  const CallDescriptor* descriptor =
      Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());

  return AddNode(common()->Call(descriptor), function, arg0, arg1);
}


Node* RawMachineAssembler::CallCFunction8(
    MachineType return_type, MachineType arg0_type, MachineType arg1_type,
    MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
    MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
    Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
    Node* arg5, Node* arg6, Node* arg7) {
  MachineSignature::Builder builder(zone(), 1, 8);
  builder.AddReturn(return_type);
  builder.AddParam(arg0_type);
  builder.AddParam(arg1_type);
  builder.AddParam(arg2_type);
  builder.AddParam(arg3_type);
  builder.AddParam(arg4_type);
  builder.AddParam(arg5_type);
  builder.AddParam(arg6_type);
  builder.AddParam(arg7_type);
  Node* args[] = {function, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
  const CallDescriptor* descriptor =
      Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
  return AddNode(common()->Call(descriptor), arraysize(args), args);
}


void RawMachineAssembler::Bind(RawMachineLabel* label) {
  DCHECK(current_block_ == nullptr);
  DCHECK(!label->bound_);
  label->bound_ = true;
  current_block_ = EnsureBlock(label);
  current_block_->set_deferred(label->deferred_);
}


BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
  label->used_ = true;
  return EnsureBlock(label);
}


BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
  if (label->block_ == nullptr) label->block_ = schedule()->NewBasicBlock();
  return label->block_;
}


BasicBlock* RawMachineAssembler::CurrentBlock() {
  DCHECK(current_block_);
  return current_block_;
}

Node* RawMachineAssembler::Phi(MachineRepresentation rep, int input_count,
                               Node* const* inputs) {
  Node** buffer = new (zone()->New(sizeof(Node*) * (input_count + 1)))
      Node*[input_count + 1];
  std::copy(inputs, inputs + input_count, buffer);
  buffer[input_count] = graph()->start();
  return AddNode(common()->Phi(rep, input_count), input_count + 1, buffer);
}

void RawMachineAssembler::AppendPhiInput(Node* phi, Node* new_input) {
  const Operator* op = phi->op();
  const Operator* new_op = common()->ResizeMergeOrPhi(op, phi->InputCount());
  phi->InsertInput(zone(), phi->InputCount() - 1, new_input);
  NodeProperties::ChangeOp(phi, new_op);
}

Node* RawMachineAssembler::AddNode(const Operator* op, int input_count,
                                   Node* const* inputs) {
  DCHECK_NOT_NULL(schedule_);
  DCHECK_NOT_NULL(current_block_);
  Node* node = MakeNode(op, input_count, inputs);
  schedule()->AddNode(CurrentBlock(), node);
  return node;
}

Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
                                    Node* const* inputs) {
  // The raw machine assembler nodes do not have effect and control inputs,
  // so we disable checking input counts here.
  return graph()->NewNodeUnchecked(op, input_count, inputs);
}

RawMachineLabel::~RawMachineLabel() { DCHECK(bound_ || !used_); }

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