// 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/graph-assembler.h"

#include "src/codegen/code-factory.h"
#include "src/compiler/linkage.h"

namespace v8 {
namespace internal {
namespace compiler {

GraphAssembler::GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control,
                               Zone* zone)
    : temp_zone_(zone),
      jsgraph_(jsgraph),
      current_effect_(effect),
      current_control_(control) {}

Node* GraphAssembler::IntPtrConstant(intptr_t value) {
  return jsgraph()->IntPtrConstant(value);
}

Node* GraphAssembler::Int32Constant(int32_t value) {
  return jsgraph()->Int32Constant(value);
}

Node* GraphAssembler::Int64Constant(int64_t value) {
  return jsgraph()->Int64Constant(value);
}

Node* GraphAssembler::UniqueIntPtrConstant(intptr_t value) {
  return graph()->NewNode(
      machine()->Is64() ? common()->Int64Constant(value)
                        : common()->Int32Constant(static_cast<int32_t>(value)));
}

Node* GraphAssembler::SmiConstant(int32_t value) {
  return jsgraph()->SmiConstant(value);
}

Node* GraphAssembler::Uint32Constant(int32_t value) {
  return jsgraph()->Uint32Constant(value);
}

Node* GraphAssembler::Float64Constant(double value) {
  return jsgraph()->Float64Constant(value);
}

Node* GraphAssembler::HeapConstant(Handle<HeapObject> object) {
  return jsgraph()->HeapConstant(object);
}

Node* GraphAssembler::NumberConstant(double value) {
  return jsgraph()->Constant(value);
}

Node* GraphAssembler::ExternalConstant(ExternalReference ref) {
  return jsgraph()->ExternalConstant(ref);
}

Node* GraphAssembler::CEntryStubConstant(int result_size) {
  return jsgraph()->CEntryStubConstant(result_size);
}

Node* GraphAssembler::LoadFramePointer() {
  return graph()->NewNode(machine()->LoadFramePointer());
}

#define SINGLETON_CONST_DEF(Name) \
  Node* GraphAssembler::Name() { return jsgraph()->Name(); }
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DEF)
#undef SINGLETON_CONST_DEF

#define PURE_UNOP_DEF(Name)                            \
  Node* GraphAssembler::Name(Node* input) {            \
    return graph()->NewNode(machine()->Name(), input); \
  }
PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DEF)
#undef PURE_UNOP_DEF

#define PURE_BINOP_DEF(Name)                                 \
  Node* GraphAssembler::Name(Node* left, Node* right) {      \
    return graph()->NewNode(machine()->Name(), left, right); \
  }
PURE_ASSEMBLER_MACH_BINOP_LIST(PURE_BINOP_DEF)
#undef PURE_BINOP_DEF

#define CHECKED_BINOP_DEF(Name)                                                \
  Node* GraphAssembler::Name(Node* left, Node* right) {                        \
    return graph()->NewNode(machine()->Name(), left, right, current_control_); \
  }
CHECKED_ASSEMBLER_MACH_BINOP_LIST(CHECKED_BINOP_DEF)
#undef CHECKED_BINOP_DEF

Node* GraphAssembler::Float64RoundDown(Node* value) {
  CHECK(machine()->Float64RoundDown().IsSupported());
  return graph()->NewNode(machine()->Float64RoundDown().op(), value);
}

Node* GraphAssembler::Float64RoundTruncate(Node* value) {
  CHECK(machine()->Float64RoundTruncate().IsSupported());
  return graph()->NewNode(machine()->Float64RoundTruncate().op(), value);
}

Node* GraphAssembler::Projection(int index, Node* value) {
  return graph()->NewNode(common()->Projection(index), value, current_control_);
}

Node* GraphAssembler::Allocate(AllocationType allocation, Node* size) {
  return current_control_ = current_effect_ = graph()->NewNode(
             simplified()->AllocateRaw(Type::Any(), allocation), size,
             current_effect_, current_control_);
}

Node* GraphAssembler::LoadField(FieldAccess const& access, Node* object) {
  Node* value = current_effect_ =
      graph()->NewNode(simplified()->LoadField(access), object, current_effect_,
                       current_control_);
  return InsertDecompressionIfNeeded(access.machine_type.representation(),
                                     value);
}

Node* GraphAssembler::LoadElement(ElementAccess const& access, Node* object,
                                  Node* index) {
  Node* value = current_effect_ =
      graph()->NewNode(simplified()->LoadElement(access), object, index,
                       current_effect_, current_control_);
  return InsertDecompressionIfNeeded(access.machine_type.representation(),
                                     value);
}

Node* GraphAssembler::StoreField(FieldAccess const& access, Node* object,
                                 Node* value) {
  value =
      InsertCompressionIfNeeded(access.machine_type.representation(), value);
  return current_effect_ =
             graph()->NewNode(simplified()->StoreField(access), object, value,
                              current_effect_, current_control_);
}

Node* GraphAssembler::StoreElement(ElementAccess const& access, Node* object,
                                   Node* index, Node* value) {
  value =
      InsertCompressionIfNeeded(access.machine_type.representation(), value);
  return current_effect_ =
             graph()->NewNode(simplified()->StoreElement(access), object, index,
                              value, current_effect_, current_control_);
}

Node* GraphAssembler::DebugBreak() {
  return current_effect_ = graph()->NewNode(machine()->DebugBreak(),
                                            current_effect_, current_control_);
}

Node* GraphAssembler::Unreachable() {
  return current_effect_ = graph()->NewNode(common()->Unreachable(),
                                            current_effect_, current_control_);
}

Node* GraphAssembler::Store(StoreRepresentation rep, Node* object, Node* offset,
                            Node* value) {
  value = InsertCompressionIfNeeded(rep.representation(), value);
  return current_effect_ =
             graph()->NewNode(machine()->Store(rep), object, offset, value,
                              current_effect_, current_control_);
}

Node* GraphAssembler::Load(MachineType type, Node* object, Node* offset) {
  Node* value = current_effect_ = graph()->NewNode(
      machine()->Load(type), object, offset, current_effect_, current_control_);
  return InsertDecompressionIfNeeded(type.representation(), value);
}

Node* GraphAssembler::StoreUnaligned(MachineRepresentation rep, Node* object,
                                     Node* offset, Node* value) {
  Operator const* const op =
      (rep == MachineRepresentation::kWord8 ||
       machine()->UnalignedStoreSupported(rep))
          ? machine()->Store(StoreRepresentation(rep, kNoWriteBarrier))
          : machine()->UnalignedStore(rep);
  return current_effect_ = graph()->NewNode(op, object, offset, value,
                                            current_effect_, current_control_);
}

Node* GraphAssembler::LoadUnaligned(MachineType type, Node* object,
                                    Node* offset) {
  Operator const* const op =
      (type.representation() == MachineRepresentation::kWord8 ||
       machine()->UnalignedLoadSupported(type.representation()))
          ? machine()->Load(type)
          : machine()->UnalignedLoad(type);
  return current_effect_ = graph()->NewNode(op, object, offset, current_effect_,
                                            current_control_);
}

Node* GraphAssembler::Retain(Node* buffer) {
  return current_effect_ =
             graph()->NewNode(common()->Retain(), buffer, current_effect_);
}

Node* GraphAssembler::UnsafePointerAdd(Node* base, Node* external) {
  return current_effect_ =
             graph()->NewNode(machine()->UnsafePointerAdd(), base, external,
                              current_effect_, current_control_);
}

Node* GraphAssembler::ToNumber(Node* value) {
  return current_effect_ =
             graph()->NewNode(ToNumberOperator(), ToNumberBuiltinConstant(),
                              value, NoContextConstant(), current_effect_);
}

Node* GraphAssembler::BitcastWordToTagged(Node* value) {
  return current_effect_ =
             graph()->NewNode(machine()->BitcastWordToTagged(), value,
                              current_effect_, current_control_);
}

Node* GraphAssembler::BitcastTaggedToWord(Node* value) {
  return current_effect_ =
             graph()->NewNode(machine()->BitcastTaggedToWord(), value,
                              current_effect_, current_control_);
}

Node* GraphAssembler::BitcastTaggedSignedToWord(Node* value) {
  return current_effect_ =
             graph()->NewNode(machine()->BitcastTaggedSignedToWord(), value,
                              current_effect_, current_control_);
}

Node* GraphAssembler::Word32PoisonOnSpeculation(Node* value) {
  return current_effect_ =
             graph()->NewNode(machine()->Word32PoisonOnSpeculation(), value,
                              current_effect_, current_control_);
}

Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason,
                                   VectorSlotPair const& feedback,
                                   Node* condition, Node* frame_state,
                                   IsSafetyCheck is_safety_check) {
  return current_control_ = current_effect_ = graph()->NewNode(
             common()->DeoptimizeIf(DeoptimizeKind::kEager, reason, feedback,
                                    is_safety_check),
             condition, frame_state, current_effect_, current_control_);
}

Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason,
                                      VectorSlotPair const& feedback,
                                      Node* condition, Node* frame_state,
                                      IsSafetyCheck is_safety_check) {
  return current_control_ = current_effect_ = graph()->NewNode(
             common()->DeoptimizeUnless(DeoptimizeKind::kEager, reason,
                                        feedback, is_safety_check),
             condition, frame_state, current_effect_, current_control_);
}

void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
                            GraphAssemblerLabel<0u>* if_false,
                            IsSafetyCheck is_safety_check) {
  DCHECK_NOT_NULL(current_control_);

  BranchHint hint = BranchHint::kNone;
  if (if_true->IsDeferred() != if_false->IsDeferred()) {
    hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
  }

  Node* branch = graph()->NewNode(common()->Branch(hint, is_safety_check),
                                  condition, current_control_);

  current_control_ = graph()->NewNode(common()->IfTrue(), branch);
  MergeState(if_true);

  current_control_ = graph()->NewNode(common()->IfFalse(), branch);
  MergeState(if_false);

  current_control_ = nullptr;
  current_effect_ = nullptr;
}

// Extractors (should be only used when destructing the assembler.
Node* GraphAssembler::ExtractCurrentControl() {
  Node* result = current_control_;
  current_control_ = nullptr;
  return result;
}

Node* GraphAssembler::ExtractCurrentEffect() {
  Node* result = current_effect_;
  current_effect_ = nullptr;
  return result;
}

Node* GraphAssembler::InsertDecompressionIfNeeded(MachineRepresentation rep,
                                                  Node* value) {
  if (COMPRESS_POINTERS_BOOL) {
    switch (rep) {
      case MachineRepresentation::kCompressedPointer:
        value = graph()->NewNode(
            machine()->ChangeCompressedPointerToTaggedPointer(), value);
        break;
      case MachineRepresentation::kCompressedSigned:
        value = graph()->NewNode(
            machine()->ChangeCompressedSignedToTaggedSigned(), value);
        break;
      case MachineRepresentation::kCompressed:
        value = graph()->NewNode(machine()->ChangeCompressedToTagged(), value);
        break;
      default:
        break;
    }
  }
  return value;
}

Node* GraphAssembler::InsertCompressionIfNeeded(MachineRepresentation rep,
                                                Node* value) {
  if (COMPRESS_POINTERS_BOOL) {
    switch (rep) {
      case MachineRepresentation::kCompressedPointer:
        value = graph()->NewNode(
            machine()->ChangeTaggedPointerToCompressedPointer(), value);
        break;
      case MachineRepresentation::kCompressedSigned:
        value = graph()->NewNode(
            machine()->ChangeTaggedSignedToCompressedSigned(), value);
        break;
      case MachineRepresentation::kCompressed:
        value = graph()->NewNode(machine()->ChangeTaggedToCompressed(), value);
        break;
      default:
        break;
    }
  }
  return value;
}

void GraphAssembler::Reset(Node* effect, Node* control) {
  current_effect_ = effect;
  current_control_ = control;
}

Operator const* GraphAssembler::ToNumberOperator() {
  if (!to_number_operator_.is_set()) {
    Callable callable =
        Builtins::CallableFor(jsgraph()->isolate(), Builtins::kToNumber);
    CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    auto call_descriptor = Linkage::GetStubCallDescriptor(
        graph()->zone(), callable.descriptor(),
        callable.descriptor().GetStackParameterCount(), flags,
        Operator::kEliminatable);
    to_number_operator_.set(common()->Call(call_descriptor));
  }
  return to_number_operator_.get();
}

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