// 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_SIMPLIFIED_LOWERING_H_
#define V8_COMPILER_SIMPLIFIED_LOWERING_H_

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

namespace v8 {
namespace internal {
namespace compiler {

// Forward declarations.
class RepresentationChanger;
class RepresentationSelector;
class SourcePositionTable;
class TypeCache;

class SimplifiedLowering final {
 public:
  SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
                     SourcePositionTable* source_positions);
  ~SimplifiedLowering() {}

  void LowerAllNodes();

  void DoMax(Node* node, Operator const* op, MachineRepresentation rep);
  void DoMin(Node* node, Operator const* op, MachineRepresentation rep);
  void DoJSToNumberTruncatesToFloat64(Node* node,
                                      RepresentationSelector* selector);
  void DoJSToNumberTruncatesToWord32(Node* node,
                                     RepresentationSelector* selector);
  void DoShift(Node* node, Operator const* op, Type* rhs_type);
  void DoStringToNumber(Node* node);
  void DoIntegral32ToBit(Node* node);
  void DoOrderedNumberToBit(Node* node);
  void DoNumberToBit(Node* node);
  void DoIntegerToUint8Clamped(Node* node);
  void DoNumberToUint8Clamped(Node* node);
  void DoSigned32ToUint8Clamped(Node* node);
  void DoUnsigned32ToUint8Clamped(Node* node);

 private:
  JSGraph* const jsgraph_;
  Zone* const zone_;
  TypeCache const& type_cache_;
  SetOncePointer<Node> to_number_code_;
  SetOncePointer<Operator const> to_number_operator_;

  // TODO(danno): SimplifiedLowering shouldn't know anything about the source
  // positions table, but must for now since there currently is no other way to
  // pass down source position information to nodes created during
  // lowering. Once this phase becomes a vanilla reducer, it should get source
  // position information via the SourcePositionWrapper like all other reducers.
  SourcePositionTable* source_positions_;

  Node* Float64Round(Node* const node);
  Node* Float64Sign(Node* const node);
  Node* Int32Abs(Node* const node);
  Node* Int32Div(Node* const node);
  Node* Int32Mod(Node* const node);
  Node* Int32Sign(Node* const node);
  Node* Uint32Div(Node* const node);
  Node* Uint32Mod(Node* const node);

  Node* ToNumberCode();
  Operator const* ToNumberOperator();

  friend class RepresentationSelector;

  Isolate* isolate() { return jsgraph_->isolate(); }
  Zone* zone() { return jsgraph_->zone(); }
  JSGraph* jsgraph() { return jsgraph_; }
  Graph* graph() { return jsgraph()->graph(); }
  CommonOperatorBuilder* common() { return jsgraph()->common(); }
  MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
  SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
};

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

#endif  // V8_COMPILER_SIMPLIFIED_LOWERING_H_
