// 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.

#ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
#define V8_COMPILER_REPRESENTATION_CHANGE_H_

#include "src/compiler/js-graph.h"
#include "src/compiler/simplified-operator.h"

namespace v8 {
namespace internal {
namespace compiler {

enum IdentifyZeros { kIdentifyZeros, kDistinguishZeros };

class Truncation final {
 public:
  // Constructors.
  static Truncation None() {
    return Truncation(TruncationKind::kNone, kIdentifyZeros);
  }
  static Truncation Bool() {
    return Truncation(TruncationKind::kBool, kIdentifyZeros);
  }
  static Truncation Word32() {
    return Truncation(TruncationKind::kWord32, kIdentifyZeros);
  }
  static Truncation Word64() {
    return Truncation(TruncationKind::kWord64, kIdentifyZeros);
  }
  static Truncation Float64(IdentifyZeros identify_zeros = kDistinguishZeros) {
    return Truncation(TruncationKind::kFloat64, identify_zeros);
  }
  static Truncation Any(IdentifyZeros identify_zeros = kDistinguishZeros) {
    return Truncation(TruncationKind::kAny, identify_zeros);
  }

  static Truncation Generalize(Truncation t1, Truncation t2) {
    return Truncation(
        Generalize(t1.kind(), t2.kind()),
        GeneralizeIdentifyZeros(t1.identify_zeros(), t2.identify_zeros()));
  }

  // Queries.
  bool IsUnused() const { return kind_ == TruncationKind::kNone; }
  bool IsUsedAsBool() const {
    return LessGeneral(kind_, TruncationKind::kBool);
  }
  bool IsUsedAsWord32() const {
    return LessGeneral(kind_, TruncationKind::kWord32);
  }
  bool IsUsedAsFloat64() const {
    return LessGeneral(kind_, TruncationKind::kFloat64);
  }
  bool IdentifiesUndefinedAndZero() {
    return LessGeneral(kind_, TruncationKind::kWord32) ||
           LessGeneral(kind_, TruncationKind::kBool);
  }
  bool IdentifiesUndefinedAndNaN() {
    return LessGeneral(kind_, TruncationKind::kFloat64) ||
           LessGeneral(kind_, TruncationKind::kWord64);
  }
  bool IdentifiesZeroAndMinusZero() const {
    return identify_zeros() == kIdentifyZeros;
  }

  // Operators.
  bool operator==(Truncation other) const {
    return kind() == other.kind() && identify_zeros() == other.identify_zeros();
  }
  bool operator!=(Truncation other) const { return !(*this == other); }

  // Debug utilities.
  const char* description() const;
  bool IsLessGeneralThan(Truncation other) {
    return LessGeneral(kind(), other.kind()) &&
           LessGeneralIdentifyZeros(identify_zeros(), other.identify_zeros());
  }

  IdentifyZeros identify_zeros() const { return identify_zeros_; }

 private:
  enum class TruncationKind : uint8_t {
    kNone,
    kBool,
    kWord32,
    kWord64,
    kFloat64,
    kAny
  };

  explicit Truncation(TruncationKind kind, IdentifyZeros identify_zeros)
      : kind_(kind), identify_zeros_(identify_zeros) {
    DCHECK(kind == TruncationKind::kAny || kind == TruncationKind::kFloat64 ||
           identify_zeros == kIdentifyZeros);
  }
  TruncationKind kind() const { return kind_; }

  TruncationKind kind_;
  IdentifyZeros identify_zeros_;

  static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
  static IdentifyZeros GeneralizeIdentifyZeros(IdentifyZeros i1,
                                               IdentifyZeros i2);
  static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
  static bool LessGeneralIdentifyZeros(IdentifyZeros u1, IdentifyZeros u2);
};

enum class TypeCheckKind : uint8_t {
  kNone,
  kSignedSmall,
  kSigned32,
  kNumber,
  kNumberOrOddball,
  kHeapObject
};

inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
  switch (type_check) {
    case TypeCheckKind::kNone:
      return os << "None";
    case TypeCheckKind::kSignedSmall:
      return os << "SignedSmall";
    case TypeCheckKind::kSigned32:
      return os << "Signed32";
    case TypeCheckKind::kNumber:
      return os << "Number";
    case TypeCheckKind::kNumberOrOddball:
      return os << "NumberOrOddball";
    case TypeCheckKind::kHeapObject:
      return os << "HeapObject";
  }
  UNREACHABLE();
}

// The {UseInfo} class is used to describe a use of an input of a node.
//
// This information is used in two different ways, based on the phase:
//
// 1. During propagation, the use info is used to inform the input node
//    about what part of the input is used (we call this truncation) and what
//    is the preferred representation. For conversions that will require
//    checks, we also keep track of whether a minus zero check is needed.
//
// 2. During lowering, the use info is used to properly convert the input
//    to the preferred representation. The preferred representation might be
//    insufficient to do the conversion (e.g. word32->float64 conv), so we also
//    need the signedness information to produce the correct value.
class UseInfo {
 public:
  UseInfo(MachineRepresentation representation, Truncation truncation,
          TypeCheckKind type_check = TypeCheckKind::kNone)
      : representation_(representation),
        truncation_(truncation),
        type_check_(type_check) {}
  static UseInfo TruncatingWord32() {
    return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
  }
  static UseInfo TruncatingWord64() {
    return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
  }
  static UseInfo Bool() {
    return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
  }
  static UseInfo Float32() {
    return UseInfo(MachineRepresentation::kFloat32, Truncation::Any());
  }
  static UseInfo TruncatingFloat64() {
    return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
  }
  static UseInfo PointerInt() {
    return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
  }
  static UseInfo AnyTagged() {
    return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
  }
  static UseInfo TaggedSigned() {
    return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any());
  }
  static UseInfo TaggedPointer() {
    return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any());
  }

  // Possibly deoptimizing conversions.
  static UseInfo CheckedHeapObjectAsTaggedPointer() {
    return UseInfo(MachineRepresentation::kTaggedPointer, Truncation::Any(),
                   TypeCheckKind::kHeapObject);
  }
  static UseInfo CheckedSignedSmallAsTaggedSigned() {
    return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any(),
                   TypeCheckKind::kSignedSmall);
  }
  static UseInfo CheckedSignedSmallAsWord32(IdentifyZeros identify_zeros) {
    return UseInfo(MachineRepresentation::kWord32,
                   Truncation::Any(identify_zeros),
                   TypeCheckKind::kSignedSmall);
  }
  static UseInfo CheckedSigned32AsWord32(IdentifyZeros identify_zeros) {
    return UseInfo(MachineRepresentation::kWord32,
                   Truncation::Any(identify_zeros), TypeCheckKind::kSigned32);
  }
  static UseInfo CheckedNumberAsFloat64() {
    return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
                   TypeCheckKind::kNumber);
  }
  static UseInfo CheckedNumberAsWord32() {
    return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
                   TypeCheckKind::kNumber);
  }
  static UseInfo CheckedNumberOrOddballAsFloat64() {
    return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
                   TypeCheckKind::kNumberOrOddball);
  }
  static UseInfo CheckedNumberOrOddballAsWord32() {
    return UseInfo(MachineRepresentation::kWord32, Truncation::Word32(),
                   TypeCheckKind::kNumberOrOddball);
  }

  // Undetermined representation.
  static UseInfo Any() {
    return UseInfo(MachineRepresentation::kNone, Truncation::Any());
  }
  static UseInfo AnyTruncatingToBool() {
    return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
  }

  // Value not used.
  static UseInfo None() {
    return UseInfo(MachineRepresentation::kNone, Truncation::None());
  }

  MachineRepresentation representation() const { return representation_; }
  Truncation truncation() const { return truncation_; }
  TypeCheckKind type_check() const { return type_check_; }
  CheckForMinusZeroMode minus_zero_check() const {
    return truncation().IdentifiesZeroAndMinusZero()
               ? CheckForMinusZeroMode::kDontCheckForMinusZero
               : CheckForMinusZeroMode::kCheckForMinusZero;
  }

 private:
  MachineRepresentation representation_;
  Truncation truncation_;
  TypeCheckKind type_check_;
};

// Contains logic related to changing the representation of values for constants
// and other nodes, as well as lowering Simplified->Machine operators.
// Eagerly folds any representation changes for constants.
class RepresentationChanger final {
 public:
  RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
      : jsgraph_(jsgraph),
        isolate_(isolate),
        testing_type_errors_(false),
        type_error_(false) {}

  // Changes representation from {output_type} to {use_rep}. The {truncation}
  // parameter is only used for sanity checking - if the changer cannot figure
  // out signedness for the word32->float64 conversion, then we check that the
  // uses truncate to word32 (so they do not care about signedness).
  Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
                             Type* output_type, Node* use_node,
                             UseInfo use_info);
  const Operator* Int32OperatorFor(IrOpcode::Value opcode);
  const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
  const Operator* TaggedSignedOperatorFor(IrOpcode::Value opcode);
  const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
  const Operator* Uint32OverflowOperatorFor(IrOpcode::Value opcode);
  const Operator* Float64OperatorFor(IrOpcode::Value opcode);

  MachineType TypeForBasePointer(const FieldAccess& access) {
    return access.tag() != 0 ? MachineType::AnyTagged()
                             : MachineType::Pointer();
  }

  MachineType TypeForBasePointer(const ElementAccess& access) {
    return access.tag() != 0 ? MachineType::AnyTagged()
                             : MachineType::Pointer();
  }

 private:
  JSGraph* jsgraph_;
  Isolate* isolate_;

  friend class RepresentationChangerTester;  // accesses the below fields.

  bool testing_type_errors_;  // If {true}, don't abort on a type error.
  bool type_error_;           // Set when a type error is detected.

  Node* GetTaggedSignedRepresentationFor(Node* node,
                                         MachineRepresentation output_rep,
                                         Type* output_type, Node* use_node,
                                         UseInfo use_info);
  Node* GetTaggedPointerRepresentationFor(Node* node,
                                          MachineRepresentation output_rep,
                                          Type* output_type, Node* use_node,
                                          UseInfo use_info);
  Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
                                   Type* output_type, Truncation truncation);
  Node* GetFloat32RepresentationFor(Node* node,
                                    MachineRepresentation output_rep,
                                    Type* output_type, Truncation truncation);
  Node* GetFloat64RepresentationFor(Node* node,
                                    MachineRepresentation output_rep,
                                    Type* output_type, Node* use_node,
                                    UseInfo use_info);
  Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
                                   Type* output_type, Node* use_node,
                                   UseInfo use_info);
  Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
                                Type* output_type);
  Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
                                   Type* output_type);
  Node* TypeError(Node* node, MachineRepresentation output_rep,
                  Type* output_type, MachineRepresentation use);
  Node* MakeTruncatedInt32Constant(double value);
  Node* InsertChangeBitToTagged(Node* node);
  Node* InsertChangeFloat32ToFloat64(Node* node);
  Node* InsertChangeFloat64ToInt32(Node* node);
  Node* InsertChangeFloat64ToUint32(Node* node);
  Node* InsertChangeInt32ToFloat64(Node* node);
  Node* InsertChangeTaggedSignedToInt32(Node* node);
  Node* InsertChangeTaggedToFloat64(Node* node);
  Node* InsertChangeUint32ToFloat64(Node* node);

  Node* InsertConversion(Node* node, const Operator* op, Node* use_node);

  JSGraph* jsgraph() const { return jsgraph_; }
  Isolate* isolate() const { return isolate_; }
  Factory* factory() const { return isolate()->factory(); }
  SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
  MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
};

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

#endif  // V8_COMPILER_REPRESENTATION_CHANGE_H_
