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

#ifndef V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
#define V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_

#include "src/interpreter/bytecode-array-builder.h"

#include "src/interpreter/bytecode-label.h"
#include "src/zone-containers.h"

namespace v8 {
namespace internal {
namespace interpreter {

class ControlFlowBuilder BASE_EMBEDDED {
 public:
  explicit ControlFlowBuilder(BytecodeArrayBuilder* builder)
      : builder_(builder) {}
  virtual ~ControlFlowBuilder() {}

 protected:
  BytecodeArrayBuilder* builder() const { return builder_; }

 private:
  BytecodeArrayBuilder* builder_;

  DISALLOW_COPY_AND_ASSIGN(ControlFlowBuilder);
};

class BreakableControlFlowBuilder : public ControlFlowBuilder {
 public:
  explicit BreakableControlFlowBuilder(BytecodeArrayBuilder* builder)
      : ControlFlowBuilder(builder),
        break_sites_(builder->zone()) {}
  virtual ~BreakableControlFlowBuilder();

  // This method should be called by the control flow owner before
  // destruction to update sites that emit jumps for break.
  void SetBreakTarget(const BytecodeLabel& break_target);

  // This method is called when visiting break statements in the AST.
  // Inserts a jump to a unbound label that is patched when the corresponding
  // SetBreakTarget is called.
  void Break() { EmitJump(&break_sites_); }
  void BreakIfTrue() { EmitJumpIfTrue(&break_sites_); }
  void BreakIfFalse() { EmitJumpIfFalse(&break_sites_); }
  void BreakIfUndefined() { EmitJumpIfUndefined(&break_sites_); }
  void BreakIfNull() { EmitJumpIfNull(&break_sites_); }

 protected:
  void EmitJump(ZoneVector<BytecodeLabel>* labels);
  void EmitJump(ZoneVector<BytecodeLabel>* labels, int index);
  void EmitJumpIfTrue(ZoneVector<BytecodeLabel>* labels);
  void EmitJumpIfTrue(ZoneVector<BytecodeLabel>* labels, int index);
  void EmitJumpIfFalse(ZoneVector<BytecodeLabel>* labels);
  void EmitJumpIfFalse(ZoneVector<BytecodeLabel>* labels, int index);
  void EmitJumpIfUndefined(ZoneVector<BytecodeLabel>* labels);
  void EmitJumpIfNull(ZoneVector<BytecodeLabel>* labels);

  void BindLabels(const BytecodeLabel& target, ZoneVector<BytecodeLabel>* site);

  // Unbound labels that identify jumps for break statements in the code.
  ZoneVector<BytecodeLabel> break_sites_;
};


// Class to track control flow for block statements (which can break in JS).
class BlockBuilder final : public BreakableControlFlowBuilder {
 public:
  explicit BlockBuilder(BytecodeArrayBuilder* builder)
      : BreakableControlFlowBuilder(builder) {}

  void EndBlock();

 private:
  BytecodeLabel block_end_;
};


// A class to help with co-ordinating break and continue statements with
// their loop.
class LoopBuilder final : public BreakableControlFlowBuilder {
 public:
  explicit LoopBuilder(BytecodeArrayBuilder* builder)
      : BreakableControlFlowBuilder(builder),
        continue_sites_(builder->zone()) {}
  ~LoopBuilder();

  void LoopHeader(ZoneVector<BytecodeLabel>* additional_labels);
  void JumpToHeader() { builder()->Jump(&loop_header_); }
  void JumpToHeaderIfTrue() { builder()->JumpIfTrue(&loop_header_); }
  void SetContinueTarget();
  void EndLoop();

  // This method is called when visiting continue statements in the AST.
  // Inserts a jump to an unbound label that is patched when SetContinueTarget
  // is called.
  void Continue() { EmitJump(&continue_sites_); }
  void ContinueIfTrue() { EmitJumpIfTrue(&continue_sites_); }
  void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_sites_); }
  void ContinueIfNull() { EmitJumpIfNull(&continue_sites_); }

 private:
  BytecodeLabel loop_header_;
  BytecodeLabel loop_end_;

  // Unbound labels that identify jumps for continue statements in the code.
  ZoneVector<BytecodeLabel> continue_sites_;
};


// A class to help with co-ordinating break statements with their switch.
class SwitchBuilder final : public BreakableControlFlowBuilder {
 public:
  explicit SwitchBuilder(BytecodeArrayBuilder* builder, int number_of_cases)
      : BreakableControlFlowBuilder(builder),
        case_sites_(builder->zone()) {
    case_sites_.resize(number_of_cases);
  }
  ~SwitchBuilder();

  // This method should be called by the SwitchBuilder owner when the case
  // statement with |index| is emitted to update the case jump site.
  void SetCaseTarget(int index);

  // This method is called when visiting case comparison operation for |index|.
  // Inserts a JumpIfTrue to a unbound label that is patched when the
  // corresponding SetCaseTarget is called.
  void Case(int index) { EmitJumpIfTrue(&case_sites_, index); }

  // This method is called when all cases comparisons have been emitted if there
  // is a default case statement. Inserts a Jump to a unbound label that is
  // patched when the corresponding SetCaseTarget is called.
  void DefaultAt(int index) { EmitJump(&case_sites_, index); }

 private:
  // Unbound labels that identify jumps for case statements in the code.
  ZoneVector<BytecodeLabel> case_sites_;
};


// A class to help with co-ordinating control flow in try-catch statements.
class TryCatchBuilder final : public ControlFlowBuilder {
 public:
  explicit TryCatchBuilder(BytecodeArrayBuilder* builder)
      : ControlFlowBuilder(builder), handler_id_(builder->NewHandlerEntry()) {}

  void BeginTry(Register context);
  void EndTry();
  void EndCatch();

 private:
  int handler_id_;
  BytecodeLabel handler_;
  BytecodeLabel exit_;
};


// A class to help with co-ordinating control flow in try-finally statements.
class TryFinallyBuilder final : public ControlFlowBuilder {
 public:
  explicit TryFinallyBuilder(BytecodeArrayBuilder* builder, bool will_catch)
      : ControlFlowBuilder(builder),
        handler_id_(builder->NewHandlerEntry()),
        finalization_sites_(builder->zone()),
        will_catch_(will_catch) {}

  void BeginTry(Register context);
  void LeaveTry();
  void EndTry();
  void BeginHandler();
  void BeginFinally();
  void EndFinally();

 private:
  int handler_id_;
  BytecodeLabel handler_;

  // Unbound labels that identify jumps to the finally block in the code.
  ZoneVector<BytecodeLabel> finalization_sites_;

  // Conservative prediction of whether exceptions thrown into the handler for
  // this finally block will be caught. Note that such a prediction depends on
  // whether this try-finally is nested inside a surrounding try-catch.
  bool will_catch_;
};

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_CONTROL_FLOW_BUILDERS_H_
