| /* | 
 |  * Copyright (C) 2011 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef ART_COMPILER_UTILS_LABEL_H_ | 
 | #define ART_COMPILER_UTILS_LABEL_H_ | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/macros.h" | 
 |  | 
 | namespace art { | 
 |  | 
 | class Assembler; | 
 | class AssemblerBuffer; | 
 | class AssemblerFixup; | 
 |  | 
 | namespace arm { | 
 |   class ArmAssembler; | 
 |   class Arm32Assembler; | 
 |   class Thumb2Assembler; | 
 | } | 
 | namespace arm64 { | 
 |   class Arm64Assembler; | 
 | } | 
 | namespace mips { | 
 |   class MipsAssembler; | 
 | } | 
 | namespace mips64 { | 
 |   class Mips64Assembler; | 
 | } | 
 | namespace x86 { | 
 |   class X86Assembler; | 
 |   class NearLabel; | 
 | } | 
 | namespace x86_64 { | 
 |   class X86_64Assembler; | 
 |   class NearLabel; | 
 | } | 
 |  | 
 | class ExternalLabel { | 
 |  public: | 
 |   ExternalLabel(const char* name_in, uintptr_t address_in) | 
 |       : name_(name_in), address_(address_in) { | 
 |     DCHECK(name_in != nullptr); | 
 |   } | 
 |  | 
 |   const char* name() const { return name_; } | 
 |   uintptr_t address() const { | 
 |     return address_; | 
 |   } | 
 |  | 
 |  private: | 
 |   const char* name_; | 
 |   const uintptr_t address_; | 
 | }; | 
 |  | 
 | class Label { | 
 |  public: | 
 |   Label() : position_(0) {} | 
 |  | 
 |   Label(Label&& src) | 
 |       : position_(src.position_) { | 
 |     // We must unlink/unbind the src label when moving; if not, calling the destructor on | 
 |     // the src label would fail. | 
 |     src.position_ = 0; | 
 |   } | 
 |  | 
 |   ~Label() { | 
 |     // Assert if label is being destroyed with unresolved branches pending. | 
 |     CHECK(!IsLinked()); | 
 |   } | 
 |  | 
 |   // Returns the position for bound and linked labels. Cannot be used | 
 |   // for unused labels. | 
 |   int Position() const { | 
 |     CHECK(!IsUnused()); | 
 |     return IsBound() ? -position_ - sizeof(void*) : position_ - sizeof(void*); | 
 |   } | 
 |  | 
 |   int LinkPosition() const { | 
 |     CHECK(IsLinked()); | 
 |     return position_ - sizeof(void*); | 
 |   } | 
 |  | 
 |   bool IsBound() const { return position_ < 0; } | 
 |   bool IsUnused() const { return position_ == 0; } | 
 |   bool IsLinked() const { return position_ > 0; } | 
 |  | 
 |  private: | 
 |   int position_; | 
 |  | 
 |   void Reinitialize() { | 
 |     position_ = 0; | 
 |   } | 
 |  | 
 |   void BindTo(int position) { | 
 |     CHECK(!IsBound()); | 
 |     position_ = -position - sizeof(void*); | 
 |     CHECK(IsBound()); | 
 |   } | 
 |  | 
 |   void LinkTo(int position) { | 
 |     CHECK(!IsBound()); | 
 |     position_ = position + sizeof(void*); | 
 |     CHECK(IsLinked()); | 
 |   } | 
 |  | 
 |   friend class arm::ArmAssembler; | 
 |   friend class arm::Arm32Assembler; | 
 |   friend class arm::Thumb2Assembler; | 
 |   friend class arm64::Arm64Assembler; | 
 |   friend class mips::MipsAssembler; | 
 |   friend class mips64::Mips64Assembler; | 
 |   friend class x86::X86Assembler; | 
 |   friend class x86::NearLabel; | 
 |   friend class x86_64::X86_64Assembler; | 
 |   friend class x86_64::NearLabel; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(Label); | 
 | }; | 
 |  | 
 | }  // namespace art | 
 |  | 
 | #endif  // ART_COMPILER_UTILS_LABEL_H_ |