1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_LABEL_H_
6#define V8_LABEL_H_
7
8#include "src/base/macros.h"
9
10namespace v8 {
11namespace internal {
12
13// -----------------------------------------------------------------------------
14// Labels represent pc locations; they are typically jump or call targets.
15// After declaration, a label can be freely used to denote known or (yet)
16// unknown pc location. Assembler::bind() is used to bind a label to the
17// current pc. A label can be bound only once.
18
19class Label {
20 public:
21  enum Distance { kNear, kFar };
22
23  INLINE(Label()) {
24    Unuse();
25    UnuseNear();
26  }
27
28  INLINE(~Label()) {
29    DCHECK(!is_linked());
30    DCHECK(!is_near_linked());
31  }
32
33  INLINE(void Unuse()) { pos_ = 0; }
34  INLINE(void UnuseNear()) { near_link_pos_ = 0; }
35
36  INLINE(bool is_bound() const) { return pos_ < 0; }
37  INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; }
38  INLINE(bool is_linked() const) { return pos_ > 0; }
39  INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; }
40
41  // Returns the position of bound or linked labels. Cannot be used
42  // for unused labels.
43  int pos() const {
44    if (pos_ < 0) return -pos_ - 1;
45    if (pos_ > 0) return pos_ - 1;
46    UNREACHABLE();
47    return 0;
48  }
49
50  int near_link_pos() const { return near_link_pos_ - 1; }
51
52 private:
53  // pos_ encodes both the binding state (via its sign)
54  // and the binding position (via its value) of a label.
55  //
56  // pos_ <  0  bound label, pos() returns the jump target position
57  // pos_ == 0  unused label
58  // pos_ >  0  linked label, pos() returns the last reference position
59  int pos_;
60
61  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
62  int near_link_pos_;
63
64  void bind_to(int pos) {
65    pos_ = -pos - 1;
66    DCHECK(is_bound());
67  }
68  void link_to(int pos, Distance distance = kFar) {
69    if (distance == kNear) {
70      near_link_pos_ = pos + 1;
71      DCHECK(is_near_linked());
72    } else {
73      pos_ = pos + 1;
74      DCHECK(is_linked());
75    }
76  }
77
78  friend class Assembler;
79  friend class Displacement;
80  friend class RegExpMacroAssemblerIrregexp;
81
82#if V8_TARGET_ARCH_ARM64
83  // On ARM64, the Assembler keeps track of pointers to Labels to resolve
84  // branches to distant targets. Copying labels would confuse the Assembler.
85  DISALLOW_COPY_AND_ASSIGN(Label);  // NOLINT
86#endif
87};
88
89}  // namespace internal
90}  // namespace v8
91
92#endif  // V8_LABEL_H_
93