|  | /* | 
|  | * 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_ |