Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: src/IceOperand.h

Issue 1838753002: Subzero: Remove IceString. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: More cleanup Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceMangling.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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; } 143 void initShouldBePooled();
148 bool getShouldBePooled() const { return ShouldBePooled; } 144 bool getShouldBePooled() const { return ShouldBePooled; }
149 145
150 // This should be thread-safe because the constant pool lock is acquired 146 // This should be thread-safe because the constant pool lock is acquired
151 // before the method is invoked. 147 // before the method is invoked.
152 void updateLookupCount() { 148 void updateLookupCount() {
153 if (!BuildDefs::dump()) 149 if (!BuildDefs::dump())
154 return; 150 return;
155 ++LookupCount; 151 ++LookupCount;
156 } 152 }
157 CounterType getLookupCount() const { return LookupCount; } 153 CounterType getLookupCount() const { return LookupCount; }
158 154
159 protected: 155 protected:
160 Constant(OperandKind Kind, Type Ty) : Operand(Kind, Ty) { 156 Constant(GlobalContext *, OperandKind Kind, Type Ty) : Operand(Kind, Ty) {
161 Vars = nullptr; 157 Vars = nullptr;
162 NumVars = 0; 158 NumVars = 0;
163 } 159 }
160 GlobalString LabelName;
164 /// Whether we should pool this constant. Usually Float/Double and pooled 161 /// Whether we should pool this constant. Usually Float/Double and pooled
165 /// Integers should be flagged true. 162 /// Integers should be flagged true. Ideally this field would be const, but
163 /// it needs to be initialized only after the subclass is fully constructed.
166 bool ShouldBePooled = false; 164 bool ShouldBePooled = false;
167 /// Note: If ShouldBePooled is ever removed from the base class, we will want 165 /// 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. 166 /// to completely disable LookupCount in a non-DUMP build to save space.
169 CounterType LookupCount = 0; 167 CounterType LookupCount = 0;
170 }; 168 };
171 169
172 /// ConstantPrimitive<> wraps a primitive type. 170 /// ConstantPrimitive<> wraps a primitive type.
173 template <typename T, Operand::OperandKind K> 171 template <typename T, Operand::OperandKind K>
174 class ConstantPrimitive : public Constant { 172 class ConstantPrimitive : public Constant {
175 ConstantPrimitive() = delete; 173 ConstantPrimitive() = delete;
176 ConstantPrimitive(const ConstantPrimitive &) = delete; 174 ConstantPrimitive(const ConstantPrimitive &) = delete;
177 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete; 175 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
178 176
179 public: 177 public:
180 using PrimType = T; 178 using PrimType = T;
181 179
182 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, 180 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty,
183 PrimType Value) { 181 PrimType Value) {
184 return new (Ctx->allocate<ConstantPrimitive>()) 182 auto *Const = new (Ctx->allocate<ConstantPrimitive>())
185 ConstantPrimitive(Ty, Value); 183 ConstantPrimitive(Ctx, Ty, Value);
184 Const->initShouldBePooled();
185 if (Const->getShouldBePooled())
186 Const->initName(Ctx);
187 return Const;
186 } 188 }
187 PrimType getValue() const { return Value; } 189 PrimType getValue() const { return Value; }
188 void emitPoolLabel(Ostream &Str) const final { 190 using Constant::emit;
191 void emit(TargetLowering *Target) const final;
192 using Constant::dump;
193 void dump(const Cfg *, Ostream &Str) const override {
194 if (BuildDefs::dump())
195 Str << getValue();
196 }
197
198 static bool classof(const Operand *Operand) {
199 return Operand->getKind() == K;
200 }
201
202 virtual bool shouldBeRandomizedOrPooled() const override { return false; }
203
204 private:
205 ConstantPrimitive(GlobalContext *Ctx, Type Ty, PrimType Value)
206 : Constant(Ctx, K, Ty), Value(Value) {}
207
208 void initName(GlobalContext *Ctx) {
209 std::string Buffer;
210 llvm::raw_string_ostream Str(Buffer);
189 Str << ".L$" << getType() << "$"; 211 Str << ".L$" << getType() << "$";
190 // Print hex characters byte by byte, starting from the most significant 212 // Print hex characters byte by byte, starting from the most significant
191 // byte. NOTE: This ordering assumes Subzero runs on a little-endian 213 // byte. NOTE: This ordering assumes Subzero runs on a little-endian
192 // platform. That means the possibility of different label names depending 214 // platform. That means the possibility of different label names depending
193 // on the endian-ness of the platform where Subzero runs. 215 // on the endian-ness of the platform where Subzero runs.
194 for (unsigned i = 0; i < sizeof(Value); ++i) { 216 for (unsigned i = 0; i < sizeof(Value); ++i) {
195 constexpr unsigned HexWidthChars = 2; 217 constexpr unsigned HexWidthChars = 2;
196 unsigned Offset = sizeof(Value) - 1 - i; 218 unsigned Offset = sizeof(Value) - 1 - i;
197 Str << llvm::format_hex_no_prefix( 219 Str << llvm::format_hex_no_prefix(
198 *(Offset + (const unsigned char *)&Value), HexWidthChars); 220 *(Offset + (const unsigned char *)&Value), HexWidthChars);
199 } 221 }
200 // For a floating-point value in DecorateAsm mode, also append the value in 222 // 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 223 // human-readable sprintf form, changing '+' to 'p' and '-' to 'm' to
202 // maintain valid asm labels. 224 // maintain valid asm labels.
203 if (std::is_floating_point<PrimType>::value && !BuildDefs::minimal() && 225 if (std::is_floating_point<PrimType>::value && !BuildDefs::minimal() &&
204 GlobalContext::getFlags().getDecorateAsm()) { 226 GlobalContext::getFlags().getDecorateAsm()) {
205 char Buf[30]; 227 char Buf[30];
206 snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value); 228 snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value);
207 for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) { 229 for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) {
208 if (Buf[i] == '-') 230 if (Buf[i] == '-')
209 Buf[i] = 'm'; 231 Buf[i] = 'm';
210 else if (Buf[i] == '+') 232 else if (Buf[i] == '+')
211 Buf[i] = 'p'; 233 Buf[i] = 'p';
212 } 234 }
213 Str << Buf; 235 Str << Buf;
214 } 236 }
215 } 237 LabelName = GlobalString(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 } 238 }
223 239
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; 240 const PrimType Value;
236 }; 241 };
237 242
238 using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>; 243 using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>;
239 using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>; 244 using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>;
240 using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>; 245 using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>;
241 using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>; 246 using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>;
242 247
243 template <> 248 template <>
244 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const { 249 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
245 if (!BuildDefs::dump()) 250 if (!BuildDefs::dump())
246 return; 251 return;
247 if (getType() == IceType_i1) 252 if (getType() == IceType_i1)
248 Str << (getValue() ? "true" : "false"); 253 Str << (getValue() ? "true" : "false");
249 else 254 else
250 Str << static_cast<int32_t>(getValue()); 255 Str << static_cast<int32_t>(getValue());
251 } 256 }
252 257
253 /// Specialization of the template member function for ConstantInteger32 258 /// Specialization of the template member function for ConstantInteger32
254 template <> 259 template <> bool ConstantInteger32::shouldBeRandomizedOrPooled() const;
255 bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
256 260
257 template <> 261 template <>
258 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const { 262 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
259 if (!BuildDefs::dump()) 263 if (!BuildDefs::dump())
260 return; 264 return;
261 assert(getType() == IceType_i64); 265 assert(getType() == IceType_i64);
262 Str << static_cast<int64_t>(getValue()); 266 Str << static_cast<int64_t>(getValue());
263 } 267 }
264 268
265 /// RelocOffset allows symbolic references in ConstantRelocatables' offsets, 269 /// RelocOffset allows symbolic references in ConstantRelocatables' offsets,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 312
309 /// RelocatableTuple bundles the parameters that are used to construct an 313 /// RelocatableTuple bundles the parameters that are used to construct an
310 /// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit 314 /// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit
311 /// into the global constant pool template mechanism. 315 /// into the global constant pool template mechanism.
312 class RelocatableTuple { 316 class RelocatableTuple {
313 RelocatableTuple() = delete; 317 RelocatableTuple() = delete;
314 RelocatableTuple &operator=(const RelocatableTuple &) = delete; 318 RelocatableTuple &operator=(const RelocatableTuple &) = delete;
315 319
316 public: 320 public:
317 RelocatableTuple(const RelocOffsetT Offset, 321 RelocatableTuple(const RelocOffsetT Offset,
318 const RelocOffsetArray &OffsetExpr, const IceString &Name) 322 const RelocOffsetArray &OffsetExpr, GlobalString Name)
319 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name) {} 323 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name) {}
320 324
321 RelocatableTuple(const RelocOffsetT Offset, 325 RelocatableTuple(const RelocOffsetT Offset,
322 const RelocOffsetArray &OffsetExpr, const IceString &Name, 326 const RelocOffsetArray &OffsetExpr, GlobalString Name,
323 const IceString &EmitString) 327 const std::string &EmitString)
324 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name), 328 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name),
325 EmitString(EmitString) {} 329 EmitString(EmitString) {}
326 330
327 RelocatableTuple(const RelocatableTuple &) = default; 331 RelocatableTuple(const RelocatableTuple &) = default;
328 332
329 const RelocOffsetT Offset; 333 const RelocOffsetT Offset;
330 const RelocOffsetArray OffsetExpr; 334 const RelocOffsetArray OffsetExpr;
331 const IceString Name; 335 const GlobalString Name;
332 const IceString EmitString; 336 const std::string EmitString;
333 }; 337 };
334 338
335 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B); 339 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
336 340
337 /// ConstantRelocatable represents a symbolic constant combined with a fixed 341 /// ConstantRelocatable represents a symbolic constant combined with a fixed
338 /// offset. 342 /// offset.
339 class ConstantRelocatable : public Constant { 343 class ConstantRelocatable : public Constant {
340 ConstantRelocatable() = delete; 344 ConstantRelocatable() = delete;
341 ConstantRelocatable(const ConstantRelocatable &) = delete; 345 ConstantRelocatable(const ConstantRelocatable &) = delete;
342 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; 346 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
343 347
344 public: 348 public:
345 template <typename T> 349 template <typename T>
346 static ConstantRelocatable *create(T *AllocOwner, Type Ty, 350 static ConstantRelocatable *create(T *AllocOwner, GlobalContext *Ctx, Type Ty,
347 const RelocatableTuple &Tuple) { 351 const RelocatableTuple &Tuple) {
348 return new (AllocOwner->template allocate<ConstantRelocatable>()) 352 return new (AllocOwner->template allocate<ConstantRelocatable>())
349 ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name, 353 ConstantRelocatable(Ctx, Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name,
350 Tuple.EmitString); 354 Tuple.EmitString);
351 } 355 }
356 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
357 const RelocatableTuple &Tuple) {
358 return create(Ctx, Ctx, Ty, Tuple);
359 }
352 360
353 RelocOffsetT getOffset() const { 361 RelocOffsetT getOffset() const {
354 RelocOffsetT Ret = Offset; 362 RelocOffsetT Ret = Offset;
355 for (const auto *const OffsetReloc : OffsetExpr) { 363 for (const auto *const OffsetReloc : OffsetExpr) {
356 Ret += OffsetReloc->getOffset(); 364 Ret += OffsetReloc->getOffset();
357 } 365 }
358 return Ret; 366 return Ret;
359 } 367 }
360 368
361 const IceString &getEmitString() const { return EmitString; } 369 const std::string &getEmitString() const { return EmitString; }
362 370
363 const IceString &getName() const { return Name; } 371 GlobalString getName() const { return Name; }
364 using Constant::emit; 372 using Constant::emit;
365 void emit(TargetLowering *Target) const final; 373 void emit(TargetLowering *Target) const final;
366 void emitWithoutPrefix(const TargetLowering *Target, 374 void emitWithoutPrefix(const TargetLowering *Target,
367 const char *Suffix = "") const; 375 const char *Suffix = "") const;
368 using Constant::dump; 376 using Constant::dump;
369 void dump(const Cfg *Func, Ostream &Str) const override; 377 void dump(const Cfg *Func, Ostream &Str) const override;
370 378
371 static bool classof(const Operand *Operand) { 379 static bool classof(const Operand *Operand) {
372 OperandKind Kind = Operand->getKind(); 380 OperandKind Kind = Operand->getKind();
373 return Kind == kConstRelocatable; 381 return Kind == kConstRelocatable;
374 } 382 }
375 383
376 private: 384 private:
377 ConstantRelocatable(Type Ty, const RelocOffsetT Offset, 385 ConstantRelocatable(GlobalContext *Ctx, Type Ty, const RelocOffsetT Offset,
378 const RelocOffsetArray &OffsetExpr, const IceString &Name, 386 const RelocOffsetArray &OffsetExpr, GlobalString Name,
379 const IceString &EmitString) 387 const std::string &EmitString)
380 : Constant(kConstRelocatable, Ty), Offset(Offset), OffsetExpr(OffsetExpr), 388 : Constant(Ctx, kConstRelocatable, Ty), Offset(Offset),
381 Name(Name), EmitString(EmitString) {} 389 OffsetExpr(OffsetExpr), Name(Name), EmitString(EmitString) {}
382 390
383 const RelocOffsetT Offset; /// fixed, known offset to add 391 const RelocOffsetT Offset; /// fixed, known offset to add
384 const RelocOffsetArray OffsetExpr; /// fixed, unknown offset to add 392 const RelocOffsetArray OffsetExpr; /// fixed, unknown offset to add
385 const IceString Name; /// optional for debug/dump 393 const GlobalString Name; /// optional for debug/dump
386 const IceString EmitString; /// optional for textual emission 394 const std::string EmitString; /// optional for textual emission
387 }; 395 };
388 396
389 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to 397 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to
390 /// lower ConstantUndef to any value, backends should try to make code 398 /// lower ConstantUndef to any value, backends should try to make code
391 /// generation deterministic by lowering ConstantUndefs to 0. 399 /// generation deterministic by lowering ConstantUndefs to 0.
392 class ConstantUndef : public Constant { 400 class ConstantUndef : public Constant {
393 ConstantUndef() = delete; 401 ConstantUndef() = delete;
394 ConstantUndef(const ConstantUndef &) = delete; 402 ConstantUndef(const ConstantUndef &) = delete;
395 ConstantUndef &operator=(const ConstantUndef &) = delete; 403 ConstantUndef &operator=(const ConstantUndef &) = delete;
396 404
397 public: 405 public:
398 static ConstantUndef *create(GlobalContext *Ctx, Type Ty) { 406 static ConstantUndef *create(GlobalContext *Ctx, Type Ty) {
399 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty); 407 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ctx, Ty);
400 } 408 }
401 409
402 using Constant::emit; 410 using Constant::emit;
403 void emit(TargetLowering *Target) const final; 411 void emit(TargetLowering *Target) const final;
404 using Constant::dump; 412 using Constant::dump;
405 void dump(const Cfg *, Ostream &Str) const override { 413 void dump(const Cfg *, Ostream &Str) const override {
406 if (BuildDefs::dump()) 414 if (BuildDefs::dump())
407 Str << "undef"; 415 Str << "undef";
408 } 416 }
409 417
410 static bool classof(const Operand *Operand) { 418 static bool classof(const Operand *Operand) {
411 return Operand->getKind() == kConstUndef; 419 return Operand->getKind() == kConstUndef;
412 } 420 }
413 421
414 private: 422 private:
415 ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {} 423 ConstantUndef(GlobalContext *Ctx, Type Ty) : Constant(Ctx, kConstUndef, Ty) {}
416 }; 424 };
417 425
418 /// RegNumT is for holding target-specific register numbers, plus the sentinel 426 /// RegNumT is for holding target-specific register numbers, plus the sentinel
419 /// value if no register is assigned. Its public ctor allows direct use of enum 427 /// value if no register is assigned. Its public ctor allows direct use of enum
420 /// values, such as RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1). 428 /// values, such as RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1).
421 /// This is to try to prevent inappropriate assumptions about enum ordering. If 429 /// This is to try to prevent inappropriate assumptions about enum ordering. If
422 /// needed, the fromInt() method can be used, such as when a RegNumT is based 430 /// needed, the fromInt() method can be used, such as when a RegNumT is based
423 /// on a bitvector index. 431 /// on a bitvector index.
424 class RegNumT { 432 class RegNumT {
425 public: 433 public:
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 Variable &operator=(const Variable &) = delete; 638 Variable &operator=(const Variable &) = delete;
631 639
632 enum RegRequirement : uint8_t { 640 enum RegRequirement : uint8_t {
633 RR_MayHaveRegister, 641 RR_MayHaveRegister,
634 RR_MustHaveRegister, 642 RR_MustHaveRegister,
635 RR_MustNotHaveRegister, 643 RR_MustNotHaveRegister,
636 }; 644 };
637 645
638 public: 646 public:
639 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { 647 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
640 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); 648 return new (Func->allocate<Variable>())
649 Variable(Func, kVariable, Ty, Index);
641 } 650 }
642 651
643 SizeT getIndex() const { return Number; } 652 SizeT getIndex() const { return Number; }
644 IceString getName(const Cfg *Func) const; 653 std::string getName(const Cfg *Func) const;
645 virtual void setName(Cfg *Func, const IceString &NewName) { 654 virtual void setName(const Cfg *Func, const std::string &NewName) {
646 // Make sure that the name can only be set once. 655 (void)Func;
647 assert(NameIndex == Cfg::IdentifierIndexInvalid); 656 if (NewName.empty())
648 if (!NewName.empty()) 657 return;
649 NameIndex = Func->addIdentifierName(NewName); 658 Name = VariableString(Func, NewName);
650 } 659 }
651 660
652 bool getIsArg() const { return IsArgument; } 661 bool getIsArg() const { return IsArgument; }
653 virtual void setIsArg(bool Val = true) { IsArgument = Val; } 662 virtual void setIsArg(bool Val = true) { IsArgument = Val; }
654 bool getIsImplicitArg() const { return IsImplicitArgument; } 663 bool getIsImplicitArg() const { return IsImplicitArgument; }
655 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; } 664 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
656 665
657 void setIgnoreLiveness() { IgnoreLiveness = true; } 666 void setIgnoreLiveness() { IgnoreLiveness = true; }
658 bool getIgnoreLiveness() const { return IgnoreLiveness; } 667 bool getIgnoreLiveness() const { return IgnoreLiveness; }
659 668
660 int32_t getStackOffset() const { return StackOffset; } 669 int32_t getStackOffset() const { return StackOffset; }
661 void setStackOffset(int32_t Offset) { StackOffset = Offset; } 670 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
662 /// Returns the variable's stack offset in symbolic form, to improve 671 /// Returns the variable's stack offset in symbolic form, to improve
663 /// readability in DecorateAsm mode. 672 /// readability in DecorateAsm mode.
664 IceString getSymbolicStackOffset(const Cfg *Func) const { 673 std::string getSymbolicStackOffset(const Cfg *Func) const {
665 if (!BuildDefs::dump()) 674 if (!BuildDefs::dump())
666 return ""; 675 return "";
667 return "lv$" + getName(Func); 676 return "lv$" + getName(Func);
668 } 677 }
669 678
670 bool hasReg() const { return getRegNum().hasValue(); } 679 bool hasReg() const { return getRegNum().hasValue(); }
671 RegNumT getRegNum() const { return RegNum; } 680 RegNumT getRegNum() const { return RegNum; }
672 void setRegNum(RegNumT NewRegNum) { 681 void setRegNum(RegNumT NewRegNum) {
673 // Regnum shouldn't be set more than once. 682 // Regnum shouldn't be set more than once.
674 assert(!hasReg() || RegNum == NewRegNum); 683 assert(!hasReg() || RegNum == NewRegNum);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 constexpr bool UseTrimmed = true; 727 constexpr bool UseTrimmed = true;
719 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); 728 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
720 } 729 }
721 730
722 /// Creates a temporary copy of the variable with a different type. Used 731 /// Creates a temporary copy of the variable with a different type. Used
723 /// primarily for syntactic correctness of textual assembly emission. Note 732 /// primarily for syntactic correctness of textual assembly emission. Note
724 /// that only basic information is copied, in particular not IsArgument, 733 /// that only basic information is copied, in particular not IsArgument,
725 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, 734 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
726 /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made 735 /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made
727 /// instead of copying the existing assignment. 736 /// instead of copying the existing assignment.
728 const Variable *asType(Type Ty, RegNumT NewRegNum) const; 737 const Variable *asType(const Cfg *Func, Type Ty, RegNumT NewRegNum) const;
729 738
730 void emit(const Cfg *Func) const override; 739 void emit(const Cfg *Func) const override;
731 using Operand::dump; 740 using Operand::dump;
732 void dump(const Cfg *Func, Ostream &Str) const override; 741 void dump(const Cfg *Func, Ostream &Str) const override;
733 742
734 /// Return reg num of base register, if different from stack/frame register. 743 /// Return reg num of base register, if different from stack/frame register.
735 virtual RegNumT getBaseRegNum() const { return RegNumT(); } 744 virtual RegNumT getBaseRegNum() const { return RegNumT(); }
736 745
737 static bool classof(const Operand *Operand) { 746 static bool classof(const Operand *Operand) {
738 OperandKind Kind = Operand->getKind(); 747 OperandKind Kind = Operand->getKind();
739 return Kind >= kVariable && Kind <= kVariable_Max; 748 return Kind >= kVariable && Kind <= kVariable_Max;
740 } 749 }
741 750
742 protected: 751 protected:
743 Variable(OperandKind K, Type Ty, SizeT Index) 752 Variable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
744 : Operand(K, Ty), Number(Index), 753 : Operand(K, Ty), Number(Index), Name(Func),
745 RegisterClass(static_cast<RegClass>(Ty)) { 754 RegisterClass(static_cast<RegClass>(Ty)) {
746 Vars = VarsReal; 755 Vars = VarsReal;
747 Vars[0] = this; 756 Vars[0] = this;
748 NumVars = 1; 757 NumVars = 1;
758 if (BuildDefs::dump()) {
759 Name = VariableString(Func, "__" + std::to_string(getIndex()));
760 } else {
761 Name = VariableString(Func);
762 }
749 } 763 }
750 /// Number is unique across all variables, and is used as a (bit)vector index 764 /// Number is unique across all variables, and is used as a (bit)vector index
751 /// for liveness analysis. 765 /// for liveness analysis.
752 const SizeT Number; 766 const SizeT Number;
753 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; 767 VariableString Name;
754 bool IsArgument = false; 768 bool IsArgument = false;
755 bool IsImplicitArgument = false; 769 bool IsImplicitArgument = false;
756 /// IgnoreLiveness means that the variable should be ignored when constructing 770 /// IgnoreLiveness means that the variable should be ignored when constructing
757 /// and validating live ranges. This is usually reserved for the stack 771 /// and validating live ranges. This is usually reserved for the stack
758 /// pointer and other physical registers specifically referenced by name. 772 /// pointer and other physical registers specifically referenced by name.
759 bool IgnoreLiveness = false; 773 bool IgnoreLiveness = false;
760 // If IsRematerializable, RegNum keeps track of which register (stack or frame 774 // If IsRematerializable, RegNum keeps track of which register (stack or frame
761 // pointer), and StackOffset is the known offset from that register. 775 // pointer), and StackOffset is the known offset from that register.
762 bool IsRematerializable = false; 776 bool IsRematerializable = false;
763 RegRequirement RegRequirement = RR_MayHaveRegister; 777 RegRequirement RegRequirement = RR_MayHaveRegister;
(...skipping 13 matching lines...) Expand all
777 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In 791 // 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. 792 // this situation the variable must be split into a low and a high word.
779 class Variable64On32 : public Variable { 793 class Variable64On32 : public Variable {
780 Variable64On32() = delete; 794 Variable64On32() = delete;
781 Variable64On32(const Variable64On32 &) = delete; 795 Variable64On32(const Variable64On32 &) = delete;
782 Variable64On32 &operator=(const Variable64On32 &) = delete; 796 Variable64On32 &operator=(const Variable64On32 &) = delete;
783 797
784 public: 798 public:
785 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) { 799 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
786 return new (Func->allocate<Variable64On32>()) 800 return new (Func->allocate<Variable64On32>())
787 Variable64On32(kVariable64On32, Ty, Index); 801 Variable64On32(Func, kVariable64On32, Ty, Index);
788 } 802 }
789 803
790 void setName(Cfg *Func, const IceString &NewName) override { 804 void setName(const Cfg *Func, const std::string &NewName) override {
791 Variable::setName(Func, NewName); 805 Variable::setName(Func, NewName);
792 if (LoVar && HiVar) { 806 if (LoVar && HiVar) {
793 LoVar->setName(Func, getName(Func) + "__lo"); 807 LoVar->setName(Func, getName(Func) + "__lo");
794 HiVar->setName(Func, getName(Func) + "__hi"); 808 HiVar->setName(Func, getName(Func) + "__hi");
795 } 809 }
796 } 810 }
797 811
798 void setIsArg(bool Val = true) override { 812 void setIsArg(bool Val = true) override {
799 Variable::setIsArg(Val); 813 Variable::setIsArg(Val);
800 if (LoVar && HiVar) { 814 if (LoVar && HiVar) {
(...skipping 11 matching lines...) Expand all
812 return HiVar; 826 return HiVar;
813 } 827 }
814 828
815 void initHiLo(Cfg *Func) { 829 void initHiLo(Cfg *Func) {
816 assert(LoVar == nullptr); 830 assert(LoVar == nullptr);
817 assert(HiVar == nullptr); 831 assert(HiVar == nullptr);
818 LoVar = Func->makeVariable(IceType_i32); 832 LoVar = Func->makeVariable(IceType_i32);
819 HiVar = Func->makeVariable(IceType_i32); 833 HiVar = Func->makeVariable(IceType_i32);
820 LoVar->setIsArg(getIsArg()); 834 LoVar->setIsArg(getIsArg());
821 HiVar->setIsArg(getIsArg()); 835 HiVar->setIsArg(getIsArg());
822 LoVar->setName(Func, getName(Func) + "__lo"); 836 if (BuildDefs::dump()) {
823 HiVar->setName(Func, getName(Func) + "__hi"); 837 LoVar->setName(Func, getName(Func) + "__lo");
838 HiVar->setName(Func, getName(Func) + "__hi");
839 }
824 } 840 }
825 841
826 static bool classof(const Operand *Operand) { 842 static bool classof(const Operand *Operand) {
827 OperandKind Kind = Operand->getKind(); 843 OperandKind Kind = Operand->getKind();
828 return Kind == kVariable64On32; 844 return Kind == kVariable64On32;
829 } 845 }
830 846
831 protected: 847 protected:
832 Variable64On32(OperandKind K, Type Ty, SizeT Index) : Variable(K, Ty, Index) { 848 Variable64On32(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
849 : Variable(Func, K, Ty, Index) {
833 assert(typeWidthInBytes(Ty) == 8); 850 assert(typeWidthInBytes(Ty) == 8);
834 } 851 }
835 852
836 Variable *LoVar = nullptr; 853 Variable *LoVar = nullptr;
837 Variable *HiVar = nullptr; 854 Variable *HiVar = nullptr;
838 }; 855 };
839 856
840 enum MetadataKind { 857 enum MetadataKind {
841 VMK_Uses, /// Track only uses, not defs 858 VMK_Uses, /// Track only uses, not defs
842 VMK_SingleDefs, /// Track uses+defs, but only record single def 859 VMK_SingleDefs, /// Track uses+defs, but only record single def
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 private: 960 private:
944 const Cfg *Func; 961 const Cfg *Func;
945 MetadataKind Kind; 962 MetadataKind Kind;
946 CfgVector<VariableTracking> Metadata; 963 CfgVector<VariableTracking> Metadata;
947 const static InstDefList NoDefinitions; 964 const static InstDefList NoDefinitions;
948 }; 965 };
949 966
950 } // end of namespace Ice 967 } // end of namespace Ice
951 968
952 #endif // SUBZERO_SRC_ICEOPERAND_H 969 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW
« no previous file with comments | « src/IceMangling.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698