11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_LABEL_H_
61cb0ef41Sopenharmony_ci#define V8_CODEGEN_LABEL_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/base/macros.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
141cb0ef41Sopenharmony_ci// Labels represent pc locations; they are typically jump or call targets.
151cb0ef41Sopenharmony_ci// After declaration, a label can be freely used to denote known or (yet)
161cb0ef41Sopenharmony_ci// unknown pc location. Assembler::bind() is used to bind a label to the
171cb0ef41Sopenharmony_ci// current pc. A label can be bound only once.
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciclass Label {
201cb0ef41Sopenharmony_ci public:
211cb0ef41Sopenharmony_ci  enum Distance {
221cb0ef41Sopenharmony_ci    kNear,  // near jump: 8 bit displacement (signed)
231cb0ef41Sopenharmony_ci    kFar    // far jump: 32 bit displacement (signed)
241cb0ef41Sopenharmony_ci  };
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  Label() = default;
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  // Disallow copy construction and assignment, but allow move construction and
291cb0ef41Sopenharmony_ci  // move assignment on selected platforms (see below).
301cb0ef41Sopenharmony_ci  Label(const Label&) = delete;
311cb0ef41Sopenharmony_ci  Label& operator=(const Label&) = delete;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci// On ARM64, the Assembler keeps track of pointers to Labels to resolve
341cb0ef41Sopenharmony_ci// branches to distant targets. Copying labels would confuse the Assembler.
351cb0ef41Sopenharmony_ci// On other platforms, allow move construction.
361cb0ef41Sopenharmony_ci#if !V8_TARGET_ARCH_ARM64
371cb0ef41Sopenharmony_ci// In debug builds, the old Label has to be cleared in order to avoid a DCHECK
381cb0ef41Sopenharmony_ci// failure in it's destructor.
391cb0ef41Sopenharmony_ci#ifdef DEBUG
401cb0ef41Sopenharmony_ci  Label(Label&& other) V8_NOEXCEPT { *this = std::move(other); }
411cb0ef41Sopenharmony_ci  Label& operator=(Label&& other) V8_NOEXCEPT {
421cb0ef41Sopenharmony_ci    pos_ = other.pos_;
431cb0ef41Sopenharmony_ci    near_link_pos_ = other.near_link_pos_;
441cb0ef41Sopenharmony_ci    other.Unuse();
451cb0ef41Sopenharmony_ci    other.UnuseNear();
461cb0ef41Sopenharmony_ci    return *this;
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci#else
491cb0ef41Sopenharmony_ci  Label(Label&&) V8_NOEXCEPT = default;
501cb0ef41Sopenharmony_ci  Label& operator=(Label&&) V8_NOEXCEPT = default;
511cb0ef41Sopenharmony_ci#endif
521cb0ef41Sopenharmony_ci#endif
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci#ifdef DEBUG
551cb0ef41Sopenharmony_ci  V8_INLINE ~Label() {
561cb0ef41Sopenharmony_ci    DCHECK(!is_linked());
571cb0ef41Sopenharmony_ci    DCHECK(!is_near_linked());
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci#endif
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  V8_INLINE void Unuse() { pos_ = 0; }
621cb0ef41Sopenharmony_ci  V8_INLINE void UnuseNear() { near_link_pos_ = 0; }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  V8_INLINE bool is_bound() const { return pos_ < 0; }
651cb0ef41Sopenharmony_ci  V8_INLINE bool is_unused() const { return pos_ == 0 && near_link_pos_ == 0; }
661cb0ef41Sopenharmony_ci  V8_INLINE bool is_linked() const { return pos_ > 0; }
671cb0ef41Sopenharmony_ci  V8_INLINE bool is_near_linked() const { return near_link_pos_ > 0; }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  // Returns the position of bound or linked labels. Cannot be used
701cb0ef41Sopenharmony_ci  // for unused labels.
711cb0ef41Sopenharmony_ci  int pos() const {
721cb0ef41Sopenharmony_ci    if (pos_ < 0) return -pos_ - 1;
731cb0ef41Sopenharmony_ci    if (pos_ > 0) return pos_ - 1;
741cb0ef41Sopenharmony_ci    UNREACHABLE();
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  int near_link_pos() const { return near_link_pos_ - 1; }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci private:
801cb0ef41Sopenharmony_ci  // pos_ encodes both the binding state (via its sign)
811cb0ef41Sopenharmony_ci  // and the binding position (via its value) of a label.
821cb0ef41Sopenharmony_ci  //
831cb0ef41Sopenharmony_ci  // pos_ <  0  bound label, pos() returns the jump target position
841cb0ef41Sopenharmony_ci  // pos_ == 0  unused label
851cb0ef41Sopenharmony_ci  // pos_ >  0  linked label, pos() returns the last reference position
861cb0ef41Sopenharmony_ci  int pos_ = 0;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
891cb0ef41Sopenharmony_ci  int near_link_pos_ = 0;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  void bind_to(int pos) {
921cb0ef41Sopenharmony_ci    pos_ = -pos - 1;
931cb0ef41Sopenharmony_ci    DCHECK(is_bound());
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci  void link_to(int pos, Distance distance = kFar) {
961cb0ef41Sopenharmony_ci    if (distance == kNear) {
971cb0ef41Sopenharmony_ci      near_link_pos_ = pos + 1;
981cb0ef41Sopenharmony_ci      DCHECK(is_near_linked());
991cb0ef41Sopenharmony_ci    } else {
1001cb0ef41Sopenharmony_ci      pos_ = pos + 1;
1011cb0ef41Sopenharmony_ci      DCHECK(is_linked());
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  friend class Assembler;
1061cb0ef41Sopenharmony_ci  friend class Displacement;
1071cb0ef41Sopenharmony_ci  friend class RegExpBytecodeGenerator;
1081cb0ef41Sopenharmony_ci};
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci}  // namespace internal
1111cb0ef41Sopenharmony_ci}  // namespace v8
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_LABEL_H_
114