OLD | NEW |
1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// | 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
11 /// This file declares the Operand class and its target-independent subclasses. | 11 /// This file declares the Operand class and its target-independent subclasses. |
12 /// The main classes are Variable, which represents an LLVM variable that is | 12 /// The main classes are Variable, which represents an LLVM variable that is |
13 /// either register- or stack-allocated, and the Constant hierarchy, which | 13 /// either register- or stack-allocated, and the Constant hierarchy, which |
14 /// represents integer, floating-point, and/or symbolic constants. | 14 /// represents integer, floating-point, and/or symbolic constants. |
15 /// | 15 /// |
16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
17 | 17 |
18 #ifndef SUBZERO_SRC_ICEOPERAND_H | 18 #ifndef SUBZERO_SRC_ICEOPERAND_H |
19 #define SUBZERO_SRC_ICEOPERAND_H | 19 #define SUBZERO_SRC_ICEOPERAND_H |
20 | 20 |
21 #include "IceCfg.h" | 21 #include "IceCfg.h" |
22 #include "IceDefs.h" | 22 #include "IceDefs.h" |
23 #include "IceGlobalContext.h" | 23 #include "IceGlobalContext.h" |
24 #include "IceTypes.h" | 24 #include "IceTypes.h" |
25 | 25 |
| 26 #include "llvm/Support/Format.h" |
| 27 |
26 namespace Ice { | 28 namespace Ice { |
27 | 29 |
28 class Operand { | 30 class Operand { |
29 Operand() = delete; | 31 Operand() = delete; |
30 Operand(const Operand &) = delete; | 32 Operand(const Operand &) = delete; |
31 Operand &operator=(const Operand &) = delete; | 33 Operand &operator=(const Operand &) = delete; |
32 | 34 |
33 public: | 35 public: |
34 static constexpr size_t MaxTargetKinds = 10; | 36 static constexpr size_t MaxTargetKinds = 10; |
35 enum OperandKind { | 37 enum OperandKind { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } | 110 } |
109 | 111 |
110 /// Constant is the abstract base class for constants. All constants are | 112 /// Constant is the abstract base class for constants. All constants are |
111 /// allocated from a global arena and are pooled. | 113 /// allocated from a global arena and are pooled. |
112 class Constant : public Operand { | 114 class Constant : public Operand { |
113 Constant() = delete; | 115 Constant() = delete; |
114 Constant(const Constant &) = delete; | 116 Constant(const Constant &) = delete; |
115 Constant &operator=(const Constant &) = delete; | 117 Constant &operator=(const Constant &) = delete; |
116 | 118 |
117 public: | 119 public: |
118 void emitPoolLabel(Ostream &Str) const { | 120 virtual void emitPoolLabel(Ostream &Str, const GlobalContext *Ctx) const { |
119 Str << ".L$" << getType() << "$" << PoolEntryID; | 121 (void)Str; |
120 } | 122 (void)Ctx; |
| 123 llvm::report_fatal_error("emitPoolLabel not defined for type"); |
| 124 }; |
121 void emit(const Cfg *Func) const override { emit(Func->getTarget()); } | 125 void emit(const Cfg *Func) const override { emit(Func->getTarget()); } |
122 virtual void emit(TargetLowering *Target) const = 0; | 126 virtual void emit(TargetLowering *Target) const = 0; |
123 | 127 |
124 static bool classof(const Operand *Operand) { | 128 static bool classof(const Operand *Operand) { |
125 OperandKind Kind = Operand->getKind(); | 129 OperandKind Kind = Operand->getKind(); |
126 return Kind >= kConst_Base && Kind <= kConst_Max; | 130 return Kind >= kConst_Base && Kind <= kConst_Max; |
127 } | 131 } |
128 | 132 |
129 /// Judge if this given immediate should be randomized or pooled By default | 133 /// Judge if this given immediate should be randomized or pooled By default |
130 /// should return false, only constant integers should truly go through this | 134 /// should return false, only constant integers should truly go through this |
131 /// method. | 135 /// method. |
132 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) { | 136 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) { |
133 (void)Ctx; | 137 (void)Ctx; |
134 return false; | 138 return false; |
135 } | 139 } |
136 | 140 |
137 void setShouldBePooled(bool R) { shouldBePooled = R; } | 141 void setShouldBePooled(bool R) { shouldBePooled = R; } |
138 | 142 |
139 bool getShouldBePooled() const { return shouldBePooled; } | 143 bool getShouldBePooled() const { return shouldBePooled; } |
140 | 144 |
141 protected: | 145 protected: |
142 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) | 146 Constant(OperandKind Kind, Type Ty) |
143 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) { | 147 : Operand(Kind, Ty), shouldBePooled(false) { |
144 Vars = nullptr; | 148 Vars = nullptr; |
145 NumVars = 0; | 149 NumVars = 0; |
146 } | 150 } |
147 /// PoolEntryID is an integer that uniquely identifies the constant within its | |
148 /// constant pool. It is used for building the constant pool in the object | |
149 /// code and for referencing its entries. | |
150 const uint32_t PoolEntryID; | |
151 /// Whether we should pool this constant. Usually Float/Double and pooled | 151 /// Whether we should pool this constant. Usually Float/Double and pooled |
152 /// Integers should be flagged true. | 152 /// Integers should be flagged true. |
153 bool shouldBePooled; | 153 bool shouldBePooled; |
154 }; | 154 }; |
155 | 155 |
156 /// ConstantPrimitive<> wraps a primitive type. | 156 /// ConstantPrimitive<> wraps a primitive type. |
157 template <typename T, Operand::OperandKind K> | 157 template <typename T, Operand::OperandKind K> |
158 class ConstantPrimitive : public Constant { | 158 class ConstantPrimitive : public Constant { |
159 ConstantPrimitive() = delete; | 159 ConstantPrimitive() = delete; |
160 ConstantPrimitive(const ConstantPrimitive &) = delete; | 160 ConstantPrimitive(const ConstantPrimitive &) = delete; |
161 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete; | 161 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete; |
162 | 162 |
163 public: | 163 public: |
164 using PrimType = T; | 164 using PrimType = T; |
165 | 165 |
166 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value, | 166 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, |
167 uint32_t PoolEntryID) { | 167 PrimType Value) { |
168 assert(!Ctx->isIRGenerationDisabled() && | 168 assert(!Ctx->isIRGenerationDisabled() && |
169 "Attempt to build primitive constant when IR generation disabled"); | 169 "Attempt to build primitive constant when IR generation disabled"); |
170 return new (Ctx->allocate<ConstantPrimitive>()) | 170 return new (Ctx->allocate<ConstantPrimitive>()) |
171 ConstantPrimitive(Ty, Value, PoolEntryID); | 171 ConstantPrimitive(Ty, Value); |
172 } | 172 } |
173 PrimType getValue() const { return Value; } | 173 PrimType getValue() const { return Value; } |
| 174 void emitPoolLabel(Ostream &Str, const GlobalContext *Ctx) const final { |
| 175 Str << ".L$" << getType() << "$"; |
| 176 // Print hex characters byte by byte, starting from the most significant |
| 177 // byte. NOTE: This ordering assumes Subzero runs on a little-endian |
| 178 // platform. That means the possibility of different label names depending |
| 179 // on the endian-ness of the platform where Subzero runs. |
| 180 for (unsigned i = 0; i < sizeof(Value); ++i) { |
| 181 constexpr unsigned HexWidthChars = 2; |
| 182 unsigned Offset = sizeof(Value) - 1 - i; |
| 183 Str << llvm::format_hex_no_prefix( |
| 184 *(Offset + (const unsigned char *)&Value), HexWidthChars); |
| 185 } |
| 186 // For a floating-point value in DecorateAsm mode, also append the value in |
| 187 // human-readable sprintf form, changing '+' to 'p' and '-' to 'm' to |
| 188 // maintain valid asm labels. |
| 189 if (std::is_floating_point<PrimType>::value && !BuildDefs::minimal() && |
| 190 Ctx->getFlags().getDecorateAsm()) { |
| 191 char Buf[30]; |
| 192 snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value); |
| 193 for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) { |
| 194 if (Buf[i] == '-') |
| 195 Buf[i] = 'm'; |
| 196 else if (Buf[i] == '+') |
| 197 Buf[i] = 'p'; |
| 198 } |
| 199 Str << Buf; |
| 200 } |
| 201 } |
174 using Constant::emit; | 202 using Constant::emit; |
175 void emit(TargetLowering *Target) const final; | 203 void emit(TargetLowering *Target) const final; |
176 using Constant::dump; | 204 using Constant::dump; |
177 void dump(const Cfg *, Ostream &Str) const override { | 205 void dump(const Cfg *, Ostream &Str) const override { |
178 if (BuildDefs::dump()) | 206 if (BuildDefs::dump()) |
179 Str << getValue(); | 207 Str << getValue(); |
180 } | 208 } |
181 | 209 |
182 static bool classof(const Operand *Operand) { | 210 static bool classof(const Operand *Operand) { |
183 return Operand->getKind() == K; | 211 return Operand->getKind() == K; |
184 } | 212 } |
185 | 213 |
186 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) override { | 214 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) override { |
187 (void)Ctx; | 215 (void)Ctx; |
188 return false; | 216 return false; |
189 } | 217 } |
190 | 218 |
191 private: | 219 private: |
192 ConstantPrimitive(Type Ty, PrimType Value, uint32_t PoolEntryID) | 220 ConstantPrimitive(Type Ty, PrimType Value) : Constant(K, Ty), Value(Value) {} |
193 : Constant(K, Ty, PoolEntryID), Value(Value) {} | |
194 const PrimType Value; | 221 const PrimType Value; |
195 }; | 222 }; |
196 | 223 |
197 using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>; | 224 using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>; |
198 using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>; | 225 using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>; |
199 using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>; | 226 using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>; |
200 using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>; | 227 using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>; |
201 | 228 |
202 template <> | 229 template <> |
203 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const { | 230 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 | 270 |
244 /// ConstantRelocatable represents a symbolic constant combined with a fixed | 271 /// ConstantRelocatable represents a symbolic constant combined with a fixed |
245 /// offset. | 272 /// offset. |
246 class ConstantRelocatable : public Constant { | 273 class ConstantRelocatable : public Constant { |
247 ConstantRelocatable() = delete; | 274 ConstantRelocatable() = delete; |
248 ConstantRelocatable(const ConstantRelocatable &) = delete; | 275 ConstantRelocatable(const ConstantRelocatable &) = delete; |
249 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; | 276 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; |
250 | 277 |
251 public: | 278 public: |
252 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, | 279 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, |
253 const RelocatableTuple &Tuple, | 280 const RelocatableTuple &Tuple) { |
254 uint32_t PoolEntryID) { | |
255 assert(!Ctx->isIRGenerationDisabled() && | 281 assert(!Ctx->isIRGenerationDisabled() && |
256 "Attempt to build relocatable constant when IR generation disabled"); | 282 "Attempt to build relocatable constant when IR generation disabled"); |
257 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( | 283 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( |
258 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); | 284 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling); |
259 } | 285 } |
260 | 286 |
261 RelocOffsetT getOffset() const { return Offset; } | 287 RelocOffsetT getOffset() const { return Offset; } |
262 const IceString &getName() const { return Name; } | 288 const IceString &getName() const { return Name; } |
263 void setSuppressMangling(bool Value) { SuppressMangling = Value; } | 289 void setSuppressMangling(bool Value) { SuppressMangling = Value; } |
264 bool getSuppressMangling() const { return SuppressMangling; } | 290 bool getSuppressMangling() const { return SuppressMangling; } |
265 using Constant::emit; | 291 using Constant::emit; |
266 void emit(TargetLowering *Target) const final; | 292 void emit(TargetLowering *Target) const final; |
267 void emitWithoutPrefix(TargetLowering *Target) const; | 293 void emitWithoutPrefix(TargetLowering *Target) const; |
268 using Constant::dump; | 294 using Constant::dump; |
269 void dump(const Cfg *Func, Ostream &Str) const override; | 295 void dump(const Cfg *Func, Ostream &Str) const override; |
270 | 296 |
271 static bool classof(const Operand *Operand) { | 297 static bool classof(const Operand *Operand) { |
272 OperandKind Kind = Operand->getKind(); | 298 OperandKind Kind = Operand->getKind(); |
273 return Kind == kConstRelocatable; | 299 return Kind == kConstRelocatable; |
274 } | 300 } |
275 | 301 |
276 private: | 302 private: |
277 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name, | 303 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name, |
278 bool SuppressMangling, uint32_t PoolEntryID) | 304 bool SuppressMangling) |
279 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), | 305 : Constant(kConstRelocatable, Ty), Offset(Offset), Name(Name), |
280 Name(Name), SuppressMangling(SuppressMangling) {} | 306 SuppressMangling(SuppressMangling) {} |
281 const RelocOffsetT Offset; /// fixed offset to add | 307 const RelocOffsetT Offset; /// fixed offset to add |
282 const IceString Name; /// optional for debug/dump | 308 const IceString Name; /// optional for debug/dump |
283 bool SuppressMangling; | 309 bool SuppressMangling; |
284 }; | 310 }; |
285 | 311 |
286 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to | 312 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to |
287 /// lower ConstantUndef to any value, backends should try to make code | 313 /// lower ConstantUndef to any value, backends should try to make code |
288 /// generation deterministic by lowering ConstantUndefs to 0. | 314 /// generation deterministic by lowering ConstantUndefs to 0. |
289 class ConstantUndef : public Constant { | 315 class ConstantUndef : public Constant { |
290 ConstantUndef() = delete; | 316 ConstantUndef() = delete; |
291 ConstantUndef(const ConstantUndef &) = delete; | 317 ConstantUndef(const ConstantUndef &) = delete; |
292 ConstantUndef &operator=(const ConstantUndef &) = delete; | 318 ConstantUndef &operator=(const ConstantUndef &) = delete; |
293 | 319 |
294 public: | 320 public: |
295 static ConstantUndef *create(GlobalContext *Ctx, Type Ty, | 321 static ConstantUndef *create(GlobalContext *Ctx, Type Ty) { |
296 uint32_t PoolEntryID) { | |
297 assert(!Ctx->isIRGenerationDisabled() && | 322 assert(!Ctx->isIRGenerationDisabled() && |
298 "Attempt to build undefined constant when IR generation disabled"); | 323 "Attempt to build undefined constant when IR generation disabled"); |
299 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID); | 324 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty); |
300 } | 325 } |
301 | 326 |
302 using Constant::emit; | 327 using Constant::emit; |
303 void emit(TargetLowering *Target) const final; | 328 void emit(TargetLowering *Target) const final; |
304 using Constant::dump; | 329 using Constant::dump; |
305 void dump(const Cfg *, Ostream &Str) const override { | 330 void dump(const Cfg *, Ostream &Str) const override { |
306 if (BuildDefs::dump()) | 331 if (BuildDefs::dump()) |
307 Str << "undef"; | 332 Str << "undef"; |
308 } | 333 } |
309 | 334 |
310 static bool classof(const Operand *Operand) { | 335 static bool classof(const Operand *Operand) { |
311 return Operand->getKind() == kConstUndef; | 336 return Operand->getKind() == kConstUndef; |
312 } | 337 } |
313 | 338 |
314 private: | 339 private: |
315 ConstantUndef(Type Ty, uint32_t PoolEntryID) | 340 ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {} |
316 : Constant(kConstUndef, Ty, PoolEntryID) {} | |
317 }; | 341 }; |
318 | 342 |
319 /// RegWeight is a wrapper for a uint32_t weight value, with a special value | 343 /// RegWeight is a wrapper for a uint32_t weight value, with a special value |
320 /// that represents infinite weight, and an addWeight() method that ensures that | 344 /// that represents infinite weight, and an addWeight() method that ensures that |
321 /// W+infinity=infinity. | 345 /// W+infinity=infinity. |
322 class RegWeight { | 346 class RegWeight { |
323 public: | 347 public: |
324 RegWeight() = default; | 348 RegWeight() = default; |
325 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} | 349 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} |
326 RegWeight(const RegWeight &) = default; | 350 RegWeight(const RegWeight &) = default; |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 private: | 734 private: |
711 const Cfg *Func; | 735 const Cfg *Func; |
712 MetadataKind Kind; | 736 MetadataKind Kind; |
713 CfgVector<VariableTracking> Metadata; | 737 CfgVector<VariableTracking> Metadata; |
714 const static InstDefList NoDefinitions; | 738 const static InstDefList NoDefinitions; |
715 }; | 739 }; |
716 | 740 |
717 } // end of namespace Ice | 741 } // end of namespace Ice |
718 | 742 |
719 #endif // SUBZERO_SRC_ICEOPERAND_H | 743 #endif // SUBZERO_SRC_ICEOPERAND_H |
OLD | NEW |