// Copyright 2017 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_LABEL_H_
#define V8_LABEL_H_

#include "src/base/macros.h"

namespace v8 {
namespace internal {

// -----------------------------------------------------------------------------
// Labels represent pc locations; they are typically jump or call targets.
// After declaration, a label can be freely used to denote known or (yet)
// unknown pc location. Assembler::bind() is used to bind a label to the
// current pc. A label can be bound only once.

class Label {
 public:
  enum Distance {
    kNear,  // near jump: 8 bit displacement (signed)
    kFar    // far jump: 32 bit displacement (signed)
  };

  Label() = default;

// On ARM64, the Assembler keeps track of pointers to Labels to resolve
// branches to distant targets. Copying labels would confuse the Assembler.
// On other platforms, allow move construction.
#if !V8_TARGET_ARCH_ARM64
// In debug builds, the old Label has to be cleared in order to avoid a DCHECK
// failure in it's destructor.
#ifdef DEBUG
  Label(Label&& other) V8_NOEXCEPT { *this = std::move(other); }
  Label& operator=(Label&& other) V8_NOEXCEPT {
    pos_ = other.pos_;
    near_link_pos_ = other.near_link_pos_;
    other.Unuse();
    other.UnuseNear();
    return *this;
  }
#else
  Label(Label&&) V8_NOEXCEPT = default;
  Label& operator=(Label&&) V8_NOEXCEPT = default;
#endif
#endif

#ifdef DEBUG
  V8_INLINE ~Label() {
    DCHECK(!is_linked());
    DCHECK(!is_near_linked());
  }
#endif

  V8_INLINE void Unuse() { pos_ = 0; }
  V8_INLINE void UnuseNear() { near_link_pos_ = 0; }

  V8_INLINE bool is_bound() const { return pos_ < 0; }
  V8_INLINE bool is_unused() const { return pos_ == 0 && near_link_pos_ == 0; }
  V8_INLINE bool is_linked() const { return pos_ > 0; }
  V8_INLINE bool is_near_linked() const { return near_link_pos_ > 0; }

  // Returns the position of bound or linked labels. Cannot be used
  // for unused labels.
  int pos() const {
    if (pos_ < 0) return -pos_ - 1;
    if (pos_ > 0) return pos_ - 1;
    UNREACHABLE();
  }

  int near_link_pos() const { return near_link_pos_ - 1; }

 private:
  // pos_ encodes both the binding state (via its sign)
  // and the binding position (via its value) of a label.
  //
  // pos_ <  0  bound label, pos() returns the jump target position
  // pos_ == 0  unused label
  // pos_ >  0  linked label, pos() returns the last reference position
  int pos_ = 0;

  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
  int near_link_pos_ = 0;

  void bind_to(int pos) {
    pos_ = -pos - 1;
    DCHECK(is_bound());
  }
  void link_to(int pos, Distance distance = kFar) {
    if (distance == kNear) {
      near_link_pos_ = pos + 1;
      DCHECK(is_near_linked());
    } else {
      pos_ = pos + 1;
      DCHECK(is_linked());
    }
  }

  friend class Assembler;
  friend class Displacement;
  friend class RegExpMacroAssemblerIrregexp;

  // Disallow copy construction and assignment, but allow move construction and
  // move assignment on selected platforms (see above).
  DISALLOW_COPY_AND_ASSIGN(Label);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_LABEL_H_
