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 /// \brief Declares the Operand class and its target-independent subclasses. | 11 /// \brief Declares the Operand class and its target-independent subclasses. |
12 /// | 12 /// |
13 /// The main classes are Variable, which represents an LLVM variable that is | 13 /// The main classes are Variable, which represents an LLVM variable that is |
14 /// either register- or stack-allocated, and the Constant hierarchy, which | 14 /// either register- or stack-allocated, and the Constant hierarchy, which |
15 /// represents integer, floating-point, and/or symbolic constants. | 15 /// represents integer, floating-point, and/or symbolic constants. |
16 /// | 16 /// |
17 //===----------------------------------------------------------------------===// | 17 //===----------------------------------------------------------------------===// |
18 | 18 |
19 #ifndef SUBZERO_SRC_ICEOPERAND_H | 19 #ifndef SUBZERO_SRC_ICEOPERAND_H |
20 #define SUBZERO_SRC_ICEOPERAND_H | 20 #define SUBZERO_SRC_ICEOPERAND_H |
21 | 21 |
22 #include "IceDefs.h" | 22 #include "IceDefs.h" |
23 #include "IceCfg.h" | 23 #include "IceCfg.h" |
24 #include "IceGlobalContext.h" | 24 #include "IceGlobalContext.h" |
| 25 #include "IceStringPool.h" |
25 #include "IceTypes.h" | 26 #include "IceTypes.h" |
26 | 27 |
27 #include "llvm/Support/Format.h" | 28 #include "llvm/Support/Format.h" |
28 | 29 |
29 #include <limits> | 30 #include <limits> |
30 #include <type_traits> | 31 #include <type_traits> |
31 | 32 |
32 namespace Ice { | 33 namespace Ice { |
33 | 34 |
34 class Operand { | 35 class Operand { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 } | 115 } |
115 | 116 |
116 /// Constant is the abstract base class for constants. All constants are | 117 /// Constant is the abstract base class for constants. All constants are |
117 /// allocated from a global arena and are pooled. | 118 /// allocated from a global arena and are pooled. |
118 class Constant : public Operand { | 119 class Constant : public Operand { |
119 Constant() = delete; | 120 Constant() = delete; |
120 Constant(const Constant &) = delete; | 121 Constant(const Constant &) = delete; |
121 Constant &operator=(const Constant &) = delete; | 122 Constant &operator=(const Constant &) = delete; |
122 | 123 |
123 public: | 124 public: |
124 virtual void emitPoolLabel(Ostream &Str) const { | |
125 (void)Str; | |
126 llvm::report_fatal_error("emitPoolLabel not defined for type"); | |
127 }; | |
128 // Declare the lookup counter to take minimal space in a non-DUMP build. | 125 // Declare the lookup counter to take minimal space in a non-DUMP build. |
129 using CounterType = | 126 using CounterType = |
130 std::conditional<BuildDefs::dump(), uint64_t, uint8_t>::type; | 127 std::conditional<BuildDefs::dump(), uint64_t, uint8_t>::type; |
131 void emit(const Cfg *Func) const override { emit(Func->getTarget()); } | 128 void emit(const Cfg *Func) const override { emit(Func->getTarget()); } |
132 virtual void emit(TargetLowering *Target) const = 0; | 129 virtual void emit(TargetLowering *Target) const = 0; |
133 | 130 |
134 static bool classof(const Operand *Operand) { | 131 static bool classof(const Operand *Operand) { |
135 OperandKind Kind = Operand->getKind(); | 132 OperandKind Kind = Operand->getKind(); |
136 return Kind >= kConst_Base && Kind <= kConst_Max; | 133 return Kind >= kConst_Base && Kind <= kConst_Max; |
137 } | 134 } |
138 | 135 |
| 136 const GlobalString getLabelName() const { return LabelName; } |
| 137 |
139 /// Judge if this given immediate should be randomized or pooled By default | 138 /// Judge if this given immediate should be randomized or pooled By default |
140 /// should return false, only constant integers should truly go through this | 139 /// should return false, only constant integers should truly go through this |
141 /// method. | 140 /// method. |
142 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) { | 141 virtual bool shouldBeRandomizedOrPooled() const { return false; } |
143 (void)Ctx; | |
144 return false; | |
145 } | |
146 | 142 |
147 void setShouldBePooled(bool R) { ShouldBePooled = R; } | |
148 bool getShouldBePooled() const { return ShouldBePooled; } | 143 bool getShouldBePooled() const { return ShouldBePooled; } |
149 | 144 |
150 // This should be thread-safe because the constant pool lock is acquired | 145 // This should be thread-safe because the constant pool lock is acquired |
151 // before the method is invoked. | 146 // before the method is invoked. |
152 void updateLookupCount() { | 147 void updateLookupCount() { |
153 if (!BuildDefs::dump()) | 148 if (!BuildDefs::dump()) |
154 return; | 149 return; |
155 ++LookupCount; | 150 ++LookupCount; |
156 } | 151 } |
157 CounterType getLookupCount() const { return LookupCount; } | 152 CounterType getLookupCount() const { return LookupCount; } |
158 | 153 |
159 protected: | 154 protected: |
160 Constant(OperandKind Kind, Type Ty) : Operand(Kind, Ty) { | 155 Constant(OperandKind Kind, Type Ty) : Operand(Kind, Ty) { |
161 Vars = nullptr; | 156 Vars = nullptr; |
162 NumVars = 0; | 157 NumVars = 0; |
163 } | 158 } |
| 159 /// Set the ShouldBePooled field to the proper value after the object is fully |
| 160 /// initialized. |
| 161 void initShouldBePooled(); |
| 162 GlobalString LabelName; |
164 /// Whether we should pool this constant. Usually Float/Double and pooled | 163 /// Whether we should pool this constant. Usually Float/Double and pooled |
165 /// Integers should be flagged true. | 164 /// Integers should be flagged true. Ideally this field would be const, but |
| 165 /// it needs to be initialized only after the subclass is fully constructed. |
166 bool ShouldBePooled = false; | 166 bool ShouldBePooled = false; |
167 /// Note: If ShouldBePooled is ever removed from the base class, we will want | 167 /// Note: If ShouldBePooled is ever removed from the base class, we will want |
168 /// to completely disable LookupCount in a non-DUMP build to save space. | 168 /// to completely disable LookupCount in a non-DUMP build to save space. |
169 CounterType LookupCount = 0; | 169 CounterType LookupCount = 0; |
170 }; | 170 }; |
171 | 171 |
172 /// ConstantPrimitive<> wraps a primitive type. | 172 /// ConstantPrimitive<> wraps a primitive type. |
173 template <typename T, Operand::OperandKind K> | 173 template <typename T, Operand::OperandKind K> |
174 class ConstantPrimitive : public Constant { | 174 class ConstantPrimitive : public Constant { |
175 ConstantPrimitive() = delete; | 175 ConstantPrimitive() = delete; |
176 ConstantPrimitive(const ConstantPrimitive &) = delete; | 176 ConstantPrimitive(const ConstantPrimitive &) = delete; |
177 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete; | 177 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete; |
178 | 178 |
179 public: | 179 public: |
180 using PrimType = T; | 180 using PrimType = T; |
181 | 181 |
182 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, | 182 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, |
183 PrimType Value) { | 183 PrimType Value) { |
184 return new (Ctx->allocate<ConstantPrimitive>()) | 184 auto *Const = |
185 ConstantPrimitive(Ty, Value); | 185 new (Ctx->allocate<ConstantPrimitive>()) ConstantPrimitive(Ty, Value); |
| 186 Const->initShouldBePooled(); |
| 187 if (Const->getShouldBePooled()) |
| 188 Const->initName(Ctx); |
| 189 return Const; |
186 } | 190 } |
187 PrimType getValue() const { return Value; } | 191 PrimType getValue() const { return Value; } |
188 void emitPoolLabel(Ostream &Str) const final { | 192 using Constant::emit; |
| 193 void emit(TargetLowering *Target) const final; |
| 194 using Constant::dump; |
| 195 void dump(const Cfg *, Ostream &Str) const override { |
| 196 if (BuildDefs::dump()) |
| 197 Str << getValue(); |
| 198 } |
| 199 |
| 200 static bool classof(const Operand *Operand) { |
| 201 return Operand->getKind() == K; |
| 202 } |
| 203 |
| 204 virtual bool shouldBeRandomizedOrPooled() const override { return false; } |
| 205 |
| 206 private: |
| 207 ConstantPrimitive(Type Ty, PrimType Value) : Constant(K, Ty), Value(Value) {} |
| 208 |
| 209 void initName(GlobalContext *Ctx) { |
| 210 std::string Buffer; |
| 211 llvm::raw_string_ostream Str(Buffer); |
189 Str << ".L$" << getType() << "$"; | 212 Str << ".L$" << getType() << "$"; |
190 // Print hex characters byte by byte, starting from the most significant | 213 // Print hex characters byte by byte, starting from the most significant |
191 // byte. NOTE: This ordering assumes Subzero runs on a little-endian | 214 // byte. NOTE: This ordering assumes Subzero runs on a little-endian |
192 // platform. That means the possibility of different label names depending | 215 // platform. That means the possibility of different label names depending |
193 // on the endian-ness of the platform where Subzero runs. | 216 // on the endian-ness of the platform where Subzero runs. |
194 for (unsigned i = 0; i < sizeof(Value); ++i) { | 217 for (unsigned i = 0; i < sizeof(Value); ++i) { |
195 constexpr unsigned HexWidthChars = 2; | 218 constexpr unsigned HexWidthChars = 2; |
196 unsigned Offset = sizeof(Value) - 1 - i; | 219 unsigned Offset = sizeof(Value) - 1 - i; |
197 Str << llvm::format_hex_no_prefix( | 220 Str << llvm::format_hex_no_prefix( |
198 *(Offset + (const unsigned char *)&Value), HexWidthChars); | 221 *(Offset + (const unsigned char *)&Value), HexWidthChars); |
199 } | 222 } |
200 // For a floating-point value in DecorateAsm mode, also append the value in | 223 // For a floating-point value in DecorateAsm mode, also append the value in |
201 // human-readable sprintf form, changing '+' to 'p' and '-' to 'm' to | 224 // human-readable sprintf form, changing '+' to 'p' and '-' to 'm' to |
202 // maintain valid asm labels. | 225 // maintain valid asm labels. |
203 if (std::is_floating_point<PrimType>::value && !BuildDefs::minimal() && | 226 if (std::is_floating_point<PrimType>::value && !BuildDefs::minimal() && |
204 GlobalContext::getFlags().getDecorateAsm()) { | 227 GlobalContext::getFlags().getDecorateAsm()) { |
205 char Buf[30]; | 228 char Buf[30]; |
206 snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value); | 229 snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value); |
207 for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) { | 230 for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) { |
208 if (Buf[i] == '-') | 231 if (Buf[i] == '-') |
209 Buf[i] = 'm'; | 232 Buf[i] = 'm'; |
210 else if (Buf[i] == '+') | 233 else if (Buf[i] == '+') |
211 Buf[i] = 'p'; | 234 Buf[i] = 'p'; |
212 } | 235 } |
213 Str << Buf; | 236 Str << Buf; |
214 } | 237 } |
215 } | 238 LabelName = GlobalString::createWithString(Ctx, Str.str()); |
216 using Constant::emit; | |
217 void emit(TargetLowering *Target) const final; | |
218 using Constant::dump; | |
219 void dump(const Cfg *, Ostream &Str) const override { | |
220 if (BuildDefs::dump()) | |
221 Str << getValue(); | |
222 } | 239 } |
223 | 240 |
224 static bool classof(const Operand *Operand) { | |
225 return Operand->getKind() == K; | |
226 } | |
227 | |
228 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) override { | |
229 (void)Ctx; | |
230 return false; | |
231 } | |
232 | |
233 private: | |
234 ConstantPrimitive(Type Ty, PrimType Value) : Constant(K, Ty), Value(Value) {} | |
235 const PrimType Value; | 241 const PrimType Value; |
236 }; | 242 }; |
237 | 243 |
238 using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>; | 244 using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>; |
239 using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>; | 245 using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>; |
240 using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>; | 246 using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>; |
241 using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>; | 247 using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>; |
242 | 248 |
243 template <> | 249 template <> |
244 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const { | 250 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const { |
245 if (!BuildDefs::dump()) | 251 if (!BuildDefs::dump()) |
246 return; | 252 return; |
247 if (getType() == IceType_i1) | 253 if (getType() == IceType_i1) |
248 Str << (getValue() ? "true" : "false"); | 254 Str << (getValue() ? "true" : "false"); |
249 else | 255 else |
250 Str << static_cast<int32_t>(getValue()); | 256 Str << static_cast<int32_t>(getValue()); |
251 } | 257 } |
252 | 258 |
253 /// Specialization of the template member function for ConstantInteger32 | 259 /// Specialization of the template member function for ConstantInteger32 |
254 template <> | 260 template <> bool ConstantInteger32::shouldBeRandomizedOrPooled() const; |
255 bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx); | |
256 | 261 |
257 template <> | 262 template <> |
258 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const { | 263 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const { |
259 if (!BuildDefs::dump()) | 264 if (!BuildDefs::dump()) |
260 return; | 265 return; |
261 assert(getType() == IceType_i64); | 266 assert(getType() == IceType_i64); |
262 Str << static_cast<int64_t>(getValue()); | 267 Str << static_cast<int64_t>(getValue()); |
263 } | 268 } |
264 | 269 |
265 /// RelocOffset allows symbolic references in ConstantRelocatables' offsets, | 270 /// RelocOffset allows symbolic references in ConstantRelocatables' offsets, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 | 313 |
309 /// RelocatableTuple bundles the parameters that are used to construct an | 314 /// RelocatableTuple bundles the parameters that are used to construct an |
310 /// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit | 315 /// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit |
311 /// into the global constant pool template mechanism. | 316 /// into the global constant pool template mechanism. |
312 class RelocatableTuple { | 317 class RelocatableTuple { |
313 RelocatableTuple() = delete; | 318 RelocatableTuple() = delete; |
314 RelocatableTuple &operator=(const RelocatableTuple &) = delete; | 319 RelocatableTuple &operator=(const RelocatableTuple &) = delete; |
315 | 320 |
316 public: | 321 public: |
317 RelocatableTuple(const RelocOffsetT Offset, | 322 RelocatableTuple(const RelocOffsetT Offset, |
318 const RelocOffsetArray &OffsetExpr, const IceString &Name) | 323 const RelocOffsetArray &OffsetExpr, GlobalString Name) |
319 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name) {} | 324 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name) {} |
320 | 325 |
321 RelocatableTuple(const RelocOffsetT Offset, | 326 RelocatableTuple(const RelocOffsetT Offset, |
322 const RelocOffsetArray &OffsetExpr, const IceString &Name, | 327 const RelocOffsetArray &OffsetExpr, GlobalString Name, |
323 const IceString &EmitString) | 328 const std::string &EmitString) |
324 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name), | 329 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name), |
325 EmitString(EmitString) {} | 330 EmitString(EmitString) {} |
326 | 331 |
327 RelocatableTuple(const RelocatableTuple &) = default; | 332 RelocatableTuple(const RelocatableTuple &) = default; |
328 | 333 |
329 const RelocOffsetT Offset; | 334 const RelocOffsetT Offset; |
330 const RelocOffsetArray OffsetExpr; | 335 const RelocOffsetArray OffsetExpr; |
331 const IceString Name; | 336 const GlobalString Name; |
332 const IceString EmitString; | 337 const std::string EmitString; |
333 }; | 338 }; |
334 | 339 |
335 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B); | 340 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B); |
336 | 341 |
337 /// ConstantRelocatable represents a symbolic constant combined with a fixed | 342 /// ConstantRelocatable represents a symbolic constant combined with a fixed |
338 /// offset. | 343 /// offset. |
339 class ConstantRelocatable : public Constant { | 344 class ConstantRelocatable : public Constant { |
340 ConstantRelocatable() = delete; | 345 ConstantRelocatable() = delete; |
341 ConstantRelocatable(const ConstantRelocatable &) = delete; | 346 ConstantRelocatable(const ConstantRelocatable &) = delete; |
342 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; | 347 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; |
343 | 348 |
344 public: | 349 public: |
345 template <typename T> | 350 template <typename T> |
346 static ConstantRelocatable *create(T *AllocOwner, Type Ty, | 351 static ConstantRelocatable *create(T *AllocOwner, Type Ty, |
347 const RelocatableTuple &Tuple) { | 352 const RelocatableTuple &Tuple) { |
348 return new (AllocOwner->template allocate<ConstantRelocatable>()) | 353 return new (AllocOwner->template allocate<ConstantRelocatable>()) |
349 ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name, | 354 ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name, |
350 Tuple.EmitString); | 355 Tuple.EmitString); |
351 } | 356 } |
352 | 357 |
353 RelocOffsetT getOffset() const { | 358 RelocOffsetT getOffset() const { |
354 RelocOffsetT Ret = Offset; | 359 RelocOffsetT Ret = Offset; |
355 for (const auto *const OffsetReloc : OffsetExpr) { | 360 for (const auto *const OffsetReloc : OffsetExpr) { |
356 Ret += OffsetReloc->getOffset(); | 361 Ret += OffsetReloc->getOffset(); |
357 } | 362 } |
358 return Ret; | 363 return Ret; |
359 } | 364 } |
360 | 365 |
361 const IceString &getEmitString() const { return EmitString; } | 366 const std::string &getEmitString() const { return EmitString; } |
362 | 367 |
363 const IceString &getName() const { return Name; } | 368 GlobalString getName() const { return Name; } |
364 using Constant::emit; | 369 using Constant::emit; |
365 void emit(TargetLowering *Target) const final; | 370 void emit(TargetLowering *Target) const final; |
366 void emitWithoutPrefix(const TargetLowering *Target, | 371 void emitWithoutPrefix(const TargetLowering *Target, |
367 const char *Suffix = "") const; | 372 const char *Suffix = "") const; |
368 using Constant::dump; | 373 using Constant::dump; |
369 void dump(const Cfg *Func, Ostream &Str) const override; | 374 void dump(const Cfg *Func, Ostream &Str) const override; |
370 | 375 |
371 static bool classof(const Operand *Operand) { | 376 static bool classof(const Operand *Operand) { |
372 OperandKind Kind = Operand->getKind(); | 377 OperandKind Kind = Operand->getKind(); |
373 return Kind == kConstRelocatable; | 378 return Kind == kConstRelocatable; |
374 } | 379 } |
375 | 380 |
376 private: | 381 private: |
377 ConstantRelocatable(Type Ty, const RelocOffsetT Offset, | 382 ConstantRelocatable(Type Ty, const RelocOffsetT Offset, |
378 const RelocOffsetArray &OffsetExpr, const IceString &Name, | 383 const RelocOffsetArray &OffsetExpr, GlobalString Name, |
379 const IceString &EmitString) | 384 const std::string &EmitString) |
380 : Constant(kConstRelocatable, Ty), Offset(Offset), OffsetExpr(OffsetExpr), | 385 : Constant(kConstRelocatable, Ty), Offset(Offset), OffsetExpr(OffsetExpr), |
381 Name(Name), EmitString(EmitString) {} | 386 Name(Name), EmitString(EmitString) {} |
382 | 387 |
383 const RelocOffsetT Offset; /// fixed, known offset to add | 388 const RelocOffsetT Offset; /// fixed, known offset to add |
384 const RelocOffsetArray OffsetExpr; /// fixed, unknown offset to add | 389 const RelocOffsetArray OffsetExpr; /// fixed, unknown offset to add |
385 const IceString Name; /// optional for debug/dump | 390 const GlobalString Name; /// optional for debug/dump |
386 const IceString EmitString; /// optional for textual emission | 391 const std::string EmitString; /// optional for textual emission |
387 }; | 392 }; |
388 | 393 |
389 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to | 394 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to |
390 /// lower ConstantUndef to any value, backends should try to make code | 395 /// lower ConstantUndef to any value, backends should try to make code |
391 /// generation deterministic by lowering ConstantUndefs to 0. | 396 /// generation deterministic by lowering ConstantUndefs to 0. |
392 class ConstantUndef : public Constant { | 397 class ConstantUndef : public Constant { |
393 ConstantUndef() = delete; | 398 ConstantUndef() = delete; |
394 ConstantUndef(const ConstantUndef &) = delete; | 399 ConstantUndef(const ConstantUndef &) = delete; |
395 ConstantUndef &operator=(const ConstantUndef &) = delete; | 400 ConstantUndef &operator=(const ConstantUndef &) = delete; |
396 | 401 |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 Variable &operator=(const Variable &) = delete; | 635 Variable &operator=(const Variable &) = delete; |
631 | 636 |
632 enum RegRequirement : uint8_t { | 637 enum RegRequirement : uint8_t { |
633 RR_MayHaveRegister, | 638 RR_MayHaveRegister, |
634 RR_MustHaveRegister, | 639 RR_MustHaveRegister, |
635 RR_MustNotHaveRegister, | 640 RR_MustNotHaveRegister, |
636 }; | 641 }; |
637 | 642 |
638 public: | 643 public: |
639 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { | 644 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { |
640 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); | 645 return new (Func->allocate<Variable>()) |
| 646 Variable(Func, kVariable, Ty, Index); |
641 } | 647 } |
642 | 648 |
643 SizeT getIndex() const { return Number; } | 649 SizeT getIndex() const { return Number; } |
644 IceString getName(const Cfg *Func) const; | 650 std::string getName(const Cfg *Func) const; |
645 virtual void setName(Cfg *Func, const IceString &NewName) { | 651 virtual void setName(const Cfg *Func, const std::string &NewName) { |
646 // Make sure that the name can only be set once. | 652 (void)Func; |
647 assert(NameIndex == Cfg::IdentifierIndexInvalid); | 653 if (NewName.empty()) |
648 if (!NewName.empty()) | 654 return; |
649 NameIndex = Func->addIdentifierName(NewName); | 655 Name = VariableString::createWithString(Func, NewName); |
650 } | 656 } |
651 | 657 |
652 bool getIsArg() const { return IsArgument; } | 658 bool getIsArg() const { return IsArgument; } |
653 virtual void setIsArg(bool Val = true) { IsArgument = Val; } | 659 virtual void setIsArg(bool Val = true) { IsArgument = Val; } |
654 bool getIsImplicitArg() const { return IsImplicitArgument; } | 660 bool getIsImplicitArg() const { return IsImplicitArgument; } |
655 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; } | 661 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; } |
656 | 662 |
657 void setIgnoreLiveness() { IgnoreLiveness = true; } | 663 void setIgnoreLiveness() { IgnoreLiveness = true; } |
658 bool getIgnoreLiveness() const { return IgnoreLiveness; } | 664 bool getIgnoreLiveness() const { return IgnoreLiveness; } |
659 | 665 |
660 int32_t getStackOffset() const { return StackOffset; } | 666 int32_t getStackOffset() const { return StackOffset; } |
661 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 667 void setStackOffset(int32_t Offset) { StackOffset = Offset; } |
662 /// Returns the variable's stack offset in symbolic form, to improve | 668 /// Returns the variable's stack offset in symbolic form, to improve |
663 /// readability in DecorateAsm mode. | 669 /// readability in DecorateAsm mode. |
664 IceString getSymbolicStackOffset(const Cfg *Func) const { | 670 std::string getSymbolicStackOffset(const Cfg *Func) const { |
665 if (!BuildDefs::dump()) | 671 if (!BuildDefs::dump()) |
666 return ""; | 672 return ""; |
667 return "lv$" + getName(Func); | 673 return "lv$" + getName(Func); |
668 } | 674 } |
669 | 675 |
670 bool hasReg() const { return getRegNum().hasValue(); } | 676 bool hasReg() const { return getRegNum().hasValue(); } |
671 RegNumT getRegNum() const { return RegNum; } | 677 RegNumT getRegNum() const { return RegNum; } |
672 void setRegNum(RegNumT NewRegNum) { | 678 void setRegNum(RegNumT NewRegNum) { |
673 // Regnum shouldn't be set more than once. | 679 // Regnum shouldn't be set more than once. |
674 assert(!hasReg() || RegNum == NewRegNum); | 680 assert(!hasReg() || RegNum == NewRegNum); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 constexpr bool UseTrimmed = true; | 724 constexpr bool UseTrimmed = true; |
719 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 725 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); |
720 } | 726 } |
721 | 727 |
722 /// Creates a temporary copy of the variable with a different type. Used | 728 /// Creates a temporary copy of the variable with a different type. Used |
723 /// primarily for syntactic correctness of textual assembly emission. Note | 729 /// primarily for syntactic correctness of textual assembly emission. Note |
724 /// that only basic information is copied, in particular not IsArgument, | 730 /// that only basic information is copied, in particular not IsArgument, |
725 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, | 731 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, |
726 /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made | 732 /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made |
727 /// instead of copying the existing assignment. | 733 /// instead of copying the existing assignment. |
728 const Variable *asType(Type Ty, RegNumT NewRegNum) const; | 734 const Variable *asType(const Cfg *Func, Type Ty, RegNumT NewRegNum) const; |
729 | 735 |
730 void emit(const Cfg *Func) const override; | 736 void emit(const Cfg *Func) const override; |
731 using Operand::dump; | 737 using Operand::dump; |
732 void dump(const Cfg *Func, Ostream &Str) const override; | 738 void dump(const Cfg *Func, Ostream &Str) const override; |
733 | 739 |
734 /// Return reg num of base register, if different from stack/frame register. | 740 /// Return reg num of base register, if different from stack/frame register. |
735 virtual RegNumT getBaseRegNum() const { return RegNumT(); } | 741 virtual RegNumT getBaseRegNum() const { return RegNumT(); } |
736 | 742 |
737 static bool classof(const Operand *Operand) { | 743 static bool classof(const Operand *Operand) { |
738 OperandKind Kind = Operand->getKind(); | 744 OperandKind Kind = Operand->getKind(); |
739 return Kind >= kVariable && Kind <= kVariable_Max; | 745 return Kind >= kVariable && Kind <= kVariable_Max; |
740 } | 746 } |
741 | 747 |
742 protected: | 748 protected: |
743 Variable(OperandKind K, Type Ty, SizeT Index) | 749 Variable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index) |
744 : Operand(K, Ty), Number(Index), | 750 : Operand(K, Ty), Number(Index), |
| 751 Name(VariableString::createWithoutString(Func)), |
745 RegisterClass(static_cast<RegClass>(Ty)) { | 752 RegisterClass(static_cast<RegClass>(Ty)) { |
746 Vars = VarsReal; | 753 Vars = VarsReal; |
747 Vars[0] = this; | 754 Vars[0] = this; |
748 NumVars = 1; | 755 NumVars = 1; |
| 756 if (BuildDefs::dump()) { |
| 757 Name = VariableString::createWithString( |
| 758 Func, "__" + std::to_string(getIndex())); |
| 759 } else { |
| 760 Name = VariableString::createWithoutString(Func); |
| 761 } |
749 } | 762 } |
750 /// Number is unique across all variables, and is used as a (bit)vector index | 763 /// Number is unique across all variables, and is used as a (bit)vector index |
751 /// for liveness analysis. | 764 /// for liveness analysis. |
752 const SizeT Number; | 765 const SizeT Number; |
753 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; | 766 VariableString Name; |
754 bool IsArgument = false; | 767 bool IsArgument = false; |
755 bool IsImplicitArgument = false; | 768 bool IsImplicitArgument = false; |
756 /// IgnoreLiveness means that the variable should be ignored when constructing | 769 /// IgnoreLiveness means that the variable should be ignored when constructing |
757 /// and validating live ranges. This is usually reserved for the stack | 770 /// and validating live ranges. This is usually reserved for the stack |
758 /// pointer and other physical registers specifically referenced by name. | 771 /// pointer and other physical registers specifically referenced by name. |
759 bool IgnoreLiveness = false; | 772 bool IgnoreLiveness = false; |
760 // If IsRematerializable, RegNum keeps track of which register (stack or frame | 773 // If IsRematerializable, RegNum keeps track of which register (stack or frame |
761 // pointer), and StackOffset is the known offset from that register. | 774 // pointer), and StackOffset is the known offset from that register. |
762 bool IsRematerializable = false; | 775 bool IsRematerializable = false; |
763 RegRequirement RegRequirement = RR_MayHaveRegister; | 776 RegRequirement RegRequirement = RR_MayHaveRegister; |
(...skipping 13 matching lines...) Expand all Loading... |
777 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In | 790 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In |
778 // this situation the variable must be split into a low and a high word. | 791 // this situation the variable must be split into a low and a high word. |
779 class Variable64On32 : public Variable { | 792 class Variable64On32 : public Variable { |
780 Variable64On32() = delete; | 793 Variable64On32() = delete; |
781 Variable64On32(const Variable64On32 &) = delete; | 794 Variable64On32(const Variable64On32 &) = delete; |
782 Variable64On32 &operator=(const Variable64On32 &) = delete; | 795 Variable64On32 &operator=(const Variable64On32 &) = delete; |
783 | 796 |
784 public: | 797 public: |
785 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) { | 798 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) { |
786 return new (Func->allocate<Variable64On32>()) | 799 return new (Func->allocate<Variable64On32>()) |
787 Variable64On32(kVariable64On32, Ty, Index); | 800 Variable64On32(Func, kVariable64On32, Ty, Index); |
788 } | 801 } |
789 | 802 |
790 void setName(Cfg *Func, const IceString &NewName) override { | 803 void setName(const Cfg *Func, const std::string &NewName) override { |
791 Variable::setName(Func, NewName); | 804 Variable::setName(Func, NewName); |
792 if (LoVar && HiVar) { | 805 if (LoVar && HiVar) { |
793 LoVar->setName(Func, getName(Func) + "__lo"); | 806 LoVar->setName(Func, getName(Func) + "__lo"); |
794 HiVar->setName(Func, getName(Func) + "__hi"); | 807 HiVar->setName(Func, getName(Func) + "__hi"); |
795 } | 808 } |
796 } | 809 } |
797 | 810 |
798 void setIsArg(bool Val = true) override { | 811 void setIsArg(bool Val = true) override { |
799 Variable::setIsArg(Val); | 812 Variable::setIsArg(Val); |
800 if (LoVar && HiVar) { | 813 if (LoVar && HiVar) { |
(...skipping 11 matching lines...) Expand all Loading... |
812 return HiVar; | 825 return HiVar; |
813 } | 826 } |
814 | 827 |
815 void initHiLo(Cfg *Func) { | 828 void initHiLo(Cfg *Func) { |
816 assert(LoVar == nullptr); | 829 assert(LoVar == nullptr); |
817 assert(HiVar == nullptr); | 830 assert(HiVar == nullptr); |
818 LoVar = Func->makeVariable(IceType_i32); | 831 LoVar = Func->makeVariable(IceType_i32); |
819 HiVar = Func->makeVariable(IceType_i32); | 832 HiVar = Func->makeVariable(IceType_i32); |
820 LoVar->setIsArg(getIsArg()); | 833 LoVar->setIsArg(getIsArg()); |
821 HiVar->setIsArg(getIsArg()); | 834 HiVar->setIsArg(getIsArg()); |
822 LoVar->setName(Func, getName(Func) + "__lo"); | 835 if (BuildDefs::dump()) { |
823 HiVar->setName(Func, getName(Func) + "__hi"); | 836 LoVar->setName(Func, getName(Func) + "__lo"); |
| 837 HiVar->setName(Func, getName(Func) + "__hi"); |
| 838 } |
824 } | 839 } |
825 | 840 |
826 static bool classof(const Operand *Operand) { | 841 static bool classof(const Operand *Operand) { |
827 OperandKind Kind = Operand->getKind(); | 842 OperandKind Kind = Operand->getKind(); |
828 return Kind == kVariable64On32; | 843 return Kind == kVariable64On32; |
829 } | 844 } |
830 | 845 |
831 protected: | 846 protected: |
832 Variable64On32(OperandKind K, Type Ty, SizeT Index) : Variable(K, Ty, Index) { | 847 Variable64On32(const Cfg *Func, OperandKind K, Type Ty, SizeT Index) |
| 848 : Variable(Func, K, Ty, Index) { |
833 assert(typeWidthInBytes(Ty) == 8); | 849 assert(typeWidthInBytes(Ty) == 8); |
834 } | 850 } |
835 | 851 |
836 Variable *LoVar = nullptr; | 852 Variable *LoVar = nullptr; |
837 Variable *HiVar = nullptr; | 853 Variable *HiVar = nullptr; |
838 }; | 854 }; |
839 | 855 |
840 enum MetadataKind { | 856 enum MetadataKind { |
841 VMK_Uses, /// Track only uses, not defs | 857 VMK_Uses, /// Track only uses, not defs |
842 VMK_SingleDefs, /// Track uses+defs, but only record single def | 858 VMK_SingleDefs, /// Track uses+defs, but only record single def |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 private: | 959 private: |
944 const Cfg *Func; | 960 const Cfg *Func; |
945 MetadataKind Kind; | 961 MetadataKind Kind; |
946 CfgVector<VariableTracking> Metadata; | 962 CfgVector<VariableTracking> Metadata; |
947 const static InstDefList NoDefinitions; | 963 const static InstDefList NoDefinitions; |
948 }; | 964 }; |
949 | 965 |
950 } // end of namespace Ice | 966 } // end of namespace Ice |
951 | 967 |
952 #endif // SUBZERO_SRC_ICEOPERAND_H | 968 #endif // SUBZERO_SRC_ICEOPERAND_H |
OLD | NEW |