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

Side by Side Diff: src/IceOperand.h

Issue 1386593004: Subzero: Fix nondeterministic behavior in constant pool creation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Update comment Created 5 years, 2 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/IceGlobalContext.cpp ('k') | src/IceTargetLoweringARM32.h » ('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 /// 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
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
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
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
OLDNEW
« no previous file with comments | « src/IceGlobalContext.cpp ('k') | src/IceTargetLoweringARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698