Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceAssemblerX86Base.h - base x86 assembler -*- C++ -*---===// | 1 //===- subzero/src/IceAssemblerX86Base.h - base x86 assembler -*- C++ -*---===// |
| 2 // | 2 // |
| 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 4 // for details. All rights reserved. Use of this source code is governed by a | 4 // for details. All rights reserved. Use of this source code is governed by a |
| 5 // BSD-style license that can be found in the LICENSE file. | 5 // BSD-style license that can be found in the LICENSE file. |
| 6 // | 6 // |
| 7 // Modified by the Subzero authors. | 7 // Modified by the Subzero authors. |
| 8 // | 8 // |
| 9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
| 10 // | 10 // |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 } | 64 } |
| 65 bool is_uint16() const { | 65 bool is_uint16() const { |
| 66 return fixup_ == nullptr && Utils::IsUint(16, value_); | 66 return fixup_ == nullptr && Utils::IsUint(16, value_); |
| 67 } | 67 } |
| 68 | 68 |
| 69 private: | 69 private: |
| 70 const int32_t value_; | 70 const int32_t value_; |
| 71 AssemblerFixup *fixup_ = nullptr; | 71 AssemblerFixup *fixup_ = nullptr; |
| 72 }; | 72 }; |
| 73 | 73 |
| 74 class Label { | 74 /// X86 allows near and far jumps. |
| 75 class Label final : public Ice::Label { | |
| 75 Label(const Label &) = delete; | 76 Label(const Label &) = delete; |
| 76 Label &operator=(const Label &) = delete; | 77 Label &operator=(const Label &) = delete; |
| 77 | 78 |
| 78 public: | 79 public: |
| 79 Label() { | 80 Label() = default; |
| 80 if (BuildDefs::asserts()) { | 81 ~Label() = default; |
| 81 for (int i = 0; i < kMaxUnresolvedBranches; i++) { | 82 |
| 82 unresolved_near_positions_[i] = -1; | 83 void finalCheck() const override { |
| 83 } | 84 Ice::Label::finalCheck(); |
| 84 } | 85 assert(!hasNear()); |
| 85 } | 86 } |
| 86 | 87 |
| 87 ~Label() = default; | 88 /// Returns the position of an earlier branch instruction which assumes that |
| 88 | 89 /// this label is "near", and bumps iterator to the next near position. |
| 89 void FinalCheck() const { | 90 intptr_t getNearPosition() { |
| 90 // Assert if label is being destroyed with unresolved branches pending. | 91 assert(hasNear()); |
| 91 assert(!IsLinked()); | 92 intptr_t Pos = UnresolvedNearPositions.back(); |
| 92 assert(!HasNear()); | 93 UnresolvedNearPositions.pop_back(); |
| 94 return Pos; | |
| 93 } | 95 } |
| 94 | 96 |
| 95 // TODO(jvoung): why are labels offset by this? | 97 bool hasNear() const { return !UnresolvedNearPositions.empty(); } |
| 96 static const uint32_t kWordSize = sizeof(uint32_t); | 98 bool isUnused() const override { |
| 97 | 99 return Ice::Label::isUnused() && !hasNear(); |
| 98 // Returns the position for bound labels (branches that come after this | |
| 99 // are considered backward branches). Cannot be used for unused or linked | |
| 100 // labels. | |
| 101 intptr_t Position() const { | |
| 102 assert(IsBound()); | |
| 103 return -position_ - kWordSize; | |
| 104 } | 100 } |
| 105 | 101 |
| 106 // Returns the position of an earlier branch instruction that was linked | 102 private: |
| 107 // to this label (branches that use this are considered forward branches). | 103 void nearLinkTo(intptr_t position) { |
| 108 // The linked instructions form a linked list, of sorts, using the | 104 assert(!isBound()); |
| 109 // instruction's displacement field for the location of the next | 105 UnresolvedNearPositions.push_back(position); |
| 110 // instruction that is also linked to this label. | |
| 111 intptr_t LinkPosition() const { | |
| 112 assert(IsLinked()); | |
| 113 return position_ - kWordSize; | |
| 114 } | 106 } |
| 115 | 107 |
| 116 // Returns the position of an earlier branch instruction which | 108 llvm::SmallVector<intptr_t, 20> UnresolvedNearPositions; |
| 117 // assumes that this label is "near", and bumps iterator to the | |
| 118 // next near position. | |
| 119 intptr_t NearPosition() { | |
| 120 assert(HasNear()); | |
| 121 return unresolved_near_positions_[--num_unresolved_]; | |
| 122 } | |
| 123 | |
| 124 bool IsBound() const { return position_ < 0; } | |
| 125 bool IsLinked() const { return position_ > 0; } | |
| 126 bool IsUnused() const { return (position_ == 0) && (num_unresolved_ == 0); } | |
| 127 bool HasNear() const { return num_unresolved_ != 0; } | |
| 128 | |
| 129 private: | |
| 130 void BindTo(intptr_t position) { | |
| 131 assert(!IsBound()); | |
| 132 assert(!HasNear()); | |
| 133 position_ = -position - kWordSize; | |
| 134 assert(IsBound()); | |
| 135 } | |
| 136 | |
| 137 void LinkTo(intptr_t position) { | |
| 138 assert(!IsBound()); | |
| 139 position_ = position + kWordSize; | |
| 140 assert(IsLinked()); | |
| 141 } | |
| 142 | |
| 143 void NearLinkTo(intptr_t position) { | |
| 144 assert(!IsBound()); | |
| 145 assert(num_unresolved_ < kMaxUnresolvedBranches); | |
| 146 unresolved_near_positions_[num_unresolved_++] = position; | |
| 147 } | |
| 148 | |
| 149 static constexpr int kMaxUnresolvedBranches = 20; | |
| 150 | |
| 151 intptr_t position_ = 0; | |
| 152 intptr_t num_unresolved_ = 0; | |
| 153 // TODO(stichnot,jvoung): Can this instead be | |
| 154 // llvm::SmallVector<intptr_t, kMaxUnresolvedBranches> ? | |
| 155 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; | |
| 156 | 109 |
| 157 template <class> friend class AssemblerX86Base; | 110 template <class> friend class AssemblerX86Base; |
| 158 }; | 111 }; |
| 159 | 112 |
| 160 template <class Machine> class AssemblerX86Base : public Assembler { | 113 template <class Machine> class AssemblerX86Base : public Assembler { |
| 161 AssemblerX86Base(const AssemblerX86Base &) = delete; | 114 AssemblerX86Base(const AssemblerX86Base &) = delete; |
| 162 AssemblerX86Base &operator=(const AssemblerX86Base &) = delete; | 115 AssemblerX86Base &operator=(const AssemblerX86Base &) = delete; |
| 163 | 116 |
| 164 protected: | 117 protected: |
| 165 AssemblerX86Base(AssemblerKind Kind, bool use_far_branches) | 118 AssemblerX86Base(AssemblerKind Kind, bool use_far_branches) |
| 166 : Assembler(Kind) { | 119 : Assembler(Kind) { |
| 167 // This mode is only needed and implemented for MIPS and ARM. | 120 // This mode is only needed and implemented for MIPS and ARM. |
| 168 assert(!use_far_branches); | 121 assert(!use_far_branches); |
| 169 (void)use_far_branches; | 122 (void)use_far_branches; |
| 170 } | 123 } |
| 171 | 124 |
| 172 public: | 125 public: |
| 173 using Traits = MachineTraits<Machine>; | 126 using Traits = MachineTraits<Machine>; |
| 174 | 127 |
| 175 ~AssemblerX86Base() override; | 128 ~AssemblerX86Base() override; |
| 176 | 129 |
| 177 static const bool kNearJump = true; | 130 static const bool kNearJump = true; |
| 178 static const bool kFarJump = false; | 131 static const bool kFarJump = false; |
| 179 | 132 |
| 180 void alignFunction() override; | 133 void alignFunction() override; |
| 181 | 134 |
| 182 SizeT getBundleAlignLog2Bytes() const override { return 5; } | 135 SizeT getBundleAlignLog2Bytes() const override { return 5; } |
| 183 | 136 |
| 184 const char *getNonExecPadDirective() const override { return ".p2align"; } | 137 const char *getAlignDirective() const override { return ".p2align"; } |
| 185 | 138 |
| 186 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { | 139 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override { |
| 187 static const uint8_t Padding[] = {0xF4}; | 140 static const uint8_t Padding[] = {0xF4}; |
| 188 return llvm::ArrayRef<uint8_t>(Padding, 1); | 141 return llvm::ArrayRef<uint8_t>(Padding, 1); |
| 189 } | 142 } |
| 190 | 143 |
| 191 void padWithNop(intptr_t Padding) override { | 144 void padWithNop(intptr_t Padding) override { |
| 192 while (Padding > MAX_NOP_SIZE) { | 145 while (Padding > MAX_NOP_SIZE) { |
| 193 nop(MAX_NOP_SIZE); | 146 nop(MAX_NOP_SIZE); |
| 194 Padding -= MAX_NOP_SIZE; | 147 Padding -= MAX_NOP_SIZE; |
| 195 } | 148 } |
| 196 if (Padding) | 149 if (Padding) |
| 197 nop(Padding); | 150 nop(Padding); |
| 198 } | 151 } |
| 199 | 152 |
| 200 Label *GetOrCreateCfgNodeLabel(SizeT NodeNumber); | 153 Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) override; |
| 201 void bindCfgNodeLabel(SizeT NodeNumber) override; | 154 void bindCfgNodeLabel(SizeT NodeNumber) override; |
| 202 Label *GetOrCreateLocalLabel(SizeT Number); | 155 Label *getOrCreateLocalLabel(SizeT Number); |
| 203 void BindLocalLabel(SizeT Number); | 156 void BindLocalLabel(SizeT Number); |
|
Jim Stichnoth
2015/07/30 15:20:23
Change this to lowercase as well?
ascull
2015/07/30 17:29:59
Done.
| |
| 204 | 157 |
| 205 bool fixupIsPCRel(FixupKind Kind) const override { | 158 bool fixupIsPCRel(FixupKind Kind) const override { |
| 206 // Currently assuming this is the only PC-rel relocation type used. | 159 // Currently assuming this is the only PC-rel relocation type used. |
| 207 // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0 | 160 // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0 |
| 208 return Kind == Traits::PcRelFixup; | 161 return Kind == Traits::PcRelFixup; |
| 209 } | 162 } |
| 210 | 163 |
| 211 // Operations to emit GPR instructions (and dispatch on operand type). | 164 // Operations to emit GPR instructions (and dispatch on operand type). |
| 212 typedef void (AssemblerX86Base::*TypedEmitGPR)(Type, | 165 typedef void (AssemblerX86Base::*TypedEmitGPR)(Type, |
| 213 typename Traits::GPRRegister); | 166 typename Traits::GPRRegister); |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 void emitGenericShift(int rm, Type Ty, | 832 void emitGenericShift(int rm, Type Ty, |
| 880 const typename Traits::Operand &operand, | 833 const typename Traits::Operand &operand, |
| 881 typename Traits::GPRRegister shifter); | 834 typename Traits::GPRRegister shifter); |
| 882 | 835 |
| 883 typedef std::vector<Label *> LabelVector; | 836 typedef std::vector<Label *> LabelVector; |
| 884 // A vector of pool-allocated x86 labels for CFG nodes. | 837 // A vector of pool-allocated x86 labels for CFG nodes. |
| 885 LabelVector CfgNodeLabels; | 838 LabelVector CfgNodeLabels; |
| 886 // A vector of pool-allocated x86 labels for Local labels. | 839 // A vector of pool-allocated x86 labels for Local labels. |
| 887 LabelVector LocalLabels; | 840 LabelVector LocalLabels; |
| 888 | 841 |
| 889 Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels); | 842 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); |
| 890 | 843 |
| 891 // The arith_int() methods factor out the commonality between the encodings of | 844 // The arith_int() methods factor out the commonality between the encodings of |
| 892 // add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag | 845 // add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag |
| 893 // parameter is statically asserted to be less than 8. | 846 // parameter is statically asserted to be less than 8. |
| 894 template <uint32_t Tag> | 847 template <uint32_t Tag> |
| 895 void arith_int(Type Ty, typename Traits::GPRRegister reg, | 848 void arith_int(Type Ty, typename Traits::GPRRegister reg, |
| 896 const Immediate &imm); | 849 const Immediate &imm); |
| 897 | 850 |
| 898 template <uint32_t Tag> | 851 template <uint32_t Tag> |
| 899 void arith_int(Type Ty, typename Traits::GPRRegister reg0, | 852 void arith_int(Type Ty, typename Traits::GPRRegister reg0, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 949 emitUint8(0x66); | 902 emitUint8(0x66); |
| 950 } | 903 } |
| 951 | 904 |
| 952 } // end of namespace X86Internal | 905 } // end of namespace X86Internal |
| 953 | 906 |
| 954 } // end of namespace Ice | 907 } // end of namespace Ice |
| 955 | 908 |
| 956 #include "IceAssemblerX86BaseImpl.h" | 909 #include "IceAssemblerX86BaseImpl.h" |
| 957 | 910 |
| 958 #endif // SUBZERO_SRC_ICEASSEMBLERX86BASE_H | 911 #endif // SUBZERO_SRC_ICEASSEMBLERX86BASE_H |
| OLD | NEW |