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