185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe/*
285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * Copyright (C) 2011 The Android Open Source Project
385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe *
485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * Licensed under the Apache License, Version 2.0 (the "License");
585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * you may not use this file except in compliance with the License.
685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * You may obtain a copy of the License at
785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe *
885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe *      http://www.apache.org/licenses/LICENSE-2.0
985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe *
1085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * Unless required by applicable law or agreed to in writing, software
1185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * distributed under the License is distributed on an "AS IS" BASIS,
1285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * See the License for the specific language governing permissions and
1485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * limitations under the License.
1585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe */
1685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
1785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#ifndef ART_COMPILER_UTILS_LABEL_H_
1885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#define ART_COMPILER_UTILS_LABEL_H_
1985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
2085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "base/logging.h"
2185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "base/macros.h"
2285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
2385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace art {
2485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
2585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampeclass Assembler;
2685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampeclass AssemblerBuffer;
2785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampeclass AssemblerFixup;
2885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
2985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace arm {
3085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class ArmAssembler;
3185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class Arm32Assembler;
3285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class Thumb2Assembler;
3385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}
3485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace arm64 {
3585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class Arm64Assembler;
3685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}
3785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace mips {
3885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class MipsAssembler;
3985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}
4085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace mips64 {
4185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class Mips64Assembler;
4285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}
4385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace x86 {
4485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class X86Assembler;
4585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class NearLabel;
4685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}
4785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace x86_64 {
4885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class X86_64Assembler;
4985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  class NearLabel;
5085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}
5185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
5285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampeclass ExternalLabel {
5385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe public:
5485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  ExternalLabel(const char* name_in, uintptr_t address_in)
5585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe      : name_(name_in), address_(address_in) {
5685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    DCHECK(name_in != nullptr);
5785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
5885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
5985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  const char* name() const { return name_; }
6085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  uintptr_t address() const {
6185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    return address_;
6285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
6385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
6485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe private:
6585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  const char* name_;
6685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  const uintptr_t address_;
6785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe};
6885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
6985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampeclass Label {
7085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe public:
7185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  Label() : position_(0) {}
7285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
738c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic  Label(Label&& src)
748c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic      : position_(src.position_) {
758c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic    // We must unlink/unbind the src label when moving; if not, calling the destructor on
768c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic    // the src label would fail.
778c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic    src.position_ = 0;
788c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic  }
798c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic
8085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  ~Label() {
8185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    // Assert if label is being destroyed with unresolved branches pending.
8285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(!IsLinked());
8385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
8485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
8585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  // Returns the position for bound and linked labels. Cannot be used
8685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  // for unused labels.
8785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  int Position() const {
8885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(!IsUnused());
8985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    return IsBound() ? -position_ - sizeof(void*) : position_ - sizeof(void*);
9085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
9185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
9285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  int LinkPosition() const {
9385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(IsLinked());
9485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    return position_ - sizeof(void*);
9585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
9685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
9785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  bool IsBound() const { return position_ < 0; }
9885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  bool IsUnused() const { return position_ == 0; }
9985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  bool IsLinked() const { return position_ > 0; }
10085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
10185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe private:
10285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  int position_;
10385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
10485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void Reinitialize() {
10585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    position_ = 0;
10685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
10785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
10885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void BindTo(int position) {
10985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(!IsBound());
11085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    position_ = -position - sizeof(void*);
11185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(IsBound());
11285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
11385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
11485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void LinkTo(int position) {
11585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(!IsBound());
11685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    position_ = position + sizeof(void*);
11785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    CHECK(IsLinked());
11885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
11985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
12085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class arm::ArmAssembler;
12185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class arm::Arm32Assembler;
12285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class arm::Thumb2Assembler;
12385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class arm64::Arm64Assembler;
12485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class mips::MipsAssembler;
12585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class mips64::Mips64Assembler;
12685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class x86::X86Assembler;
12785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class x86::NearLabel;
12885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class x86_64::X86_64Assembler;
12985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  friend class x86_64::NearLabel;
13085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
13185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  DISALLOW_COPY_AND_ASSIGN(Label);
13285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe};
13385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
13485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}  // namespace art
13585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
13685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#endif  // ART_COMPILER_UTILS_LABEL_H_
137