Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file defines various classes for working with Instructions and |
||
10 | // ConstantExprs. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_IR_OPERATOR_H |
||
15 | #define LLVM_IR_OPERATOR_H |
||
16 | |||
17 | #include "llvm/ADT/MapVector.h" |
||
18 | #include "llvm/IR/Constants.h" |
||
19 | #include "llvm/IR/FMF.h" |
||
20 | #include "llvm/IR/Instruction.h" |
||
21 | #include "llvm/IR/Type.h" |
||
22 | #include "llvm/IR/Value.h" |
||
23 | #include "llvm/Support/Casting.h" |
||
24 | #include <cstddef> |
||
25 | #include <optional> |
||
26 | |||
27 | namespace llvm { |
||
28 | |||
29 | /// This is a utility class that provides an abstraction for the common |
||
30 | /// functionality between Instructions and ConstantExprs. |
||
31 | class Operator : public User { |
||
32 | public: |
||
33 | // The Operator class is intended to be used as a utility, and is never itself |
||
34 | // instantiated. |
||
35 | Operator() = delete; |
||
36 | ~Operator() = delete; |
||
37 | |||
38 | void *operator new(size_t s) = delete; |
||
39 | |||
40 | /// Return the opcode for this Instruction or ConstantExpr. |
||
41 | unsigned getOpcode() const { |
||
42 | if (const Instruction *I = dyn_cast<Instruction>(this)) |
||
43 | return I->getOpcode(); |
||
44 | return cast<ConstantExpr>(this)->getOpcode(); |
||
45 | } |
||
46 | |||
47 | /// If V is an Instruction or ConstantExpr, return its opcode. |
||
48 | /// Otherwise return UserOp1. |
||
49 | static unsigned getOpcode(const Value *V) { |
||
50 | if (const Instruction *I = dyn_cast<Instruction>(V)) |
||
51 | return I->getOpcode(); |
||
52 | if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) |
||
53 | return CE->getOpcode(); |
||
54 | return Instruction::UserOp1; |
||
55 | } |
||
56 | |||
57 | static bool classof(const Instruction *) { return true; } |
||
58 | static bool classof(const ConstantExpr *) { return true; } |
||
59 | static bool classof(const Value *V) { |
||
60 | return isa<Instruction>(V) || isa<ConstantExpr>(V); |
||
61 | } |
||
62 | |||
63 | /// Return true if this operator has flags which may cause this operator |
||
64 | /// to evaluate to poison despite having non-poison inputs. |
||
65 | bool hasPoisonGeneratingFlags() const; |
||
66 | |||
67 | /// Return true if this operator has poison-generating flags or metadata. |
||
68 | /// The latter is only possible for instructions. |
||
69 | bool hasPoisonGeneratingFlagsOrMetadata() const; |
||
70 | }; |
||
71 | |||
72 | /// Utility class for integer operators which may exhibit overflow - Add, Sub, |
||
73 | /// Mul, and Shl. It does not include SDiv, despite that operator having the |
||
74 | /// potential for overflow. |
||
75 | class OverflowingBinaryOperator : public Operator { |
||
76 | public: |
||
77 | enum { |
||
78 | AnyWrap = 0, |
||
79 | NoUnsignedWrap = (1 << 0), |
||
80 | NoSignedWrap = (1 << 1) |
||
81 | }; |
||
82 | |||
83 | private: |
||
84 | friend class Instruction; |
||
85 | friend class ConstantExpr; |
||
86 | |||
87 | void setHasNoUnsignedWrap(bool B) { |
||
88 | SubclassOptionalData = |
||
89 | (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); |
||
90 | } |
||
91 | void setHasNoSignedWrap(bool B) { |
||
92 | SubclassOptionalData = |
||
93 | (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); |
||
94 | } |
||
95 | |||
96 | public: |
||
97 | /// Test whether this operation is known to never |
||
98 | /// undergo unsigned overflow, aka the nuw property. |
||
99 | bool hasNoUnsignedWrap() const { |
||
100 | return SubclassOptionalData & NoUnsignedWrap; |
||
101 | } |
||
102 | |||
103 | /// Test whether this operation is known to never |
||
104 | /// undergo signed overflow, aka the nsw property. |
||
105 | bool hasNoSignedWrap() const { |
||
106 | return (SubclassOptionalData & NoSignedWrap) != 0; |
||
107 | } |
||
108 | |||
109 | static bool classof(const Instruction *I) { |
||
110 | return I->getOpcode() == Instruction::Add || |
||
111 | I->getOpcode() == Instruction::Sub || |
||
112 | I->getOpcode() == Instruction::Mul || |
||
113 | I->getOpcode() == Instruction::Shl; |
||
114 | } |
||
115 | static bool classof(const ConstantExpr *CE) { |
||
116 | return CE->getOpcode() == Instruction::Add || |
||
117 | CE->getOpcode() == Instruction::Sub || |
||
118 | CE->getOpcode() == Instruction::Mul || |
||
119 | CE->getOpcode() == Instruction::Shl; |
||
120 | } |
||
121 | static bool classof(const Value *V) { |
||
122 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || |
||
123 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); |
||
124 | } |
||
125 | }; |
||
126 | |||
127 | /// A udiv or sdiv instruction, which can be marked as "exact", |
||
128 | /// indicating that no bits are destroyed. |
||
129 | class PossiblyExactOperator : public Operator { |
||
130 | public: |
||
131 | enum { |
||
132 | IsExact = (1 << 0) |
||
133 | }; |
||
134 | |||
135 | private: |
||
136 | friend class Instruction; |
||
137 | friend class ConstantExpr; |
||
138 | |||
139 | void setIsExact(bool B) { |
||
140 | SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); |
||
141 | } |
||
142 | |||
143 | public: |
||
144 | /// Test whether this division is known to be exact, with zero remainder. |
||
145 | bool isExact() const { |
||
146 | return SubclassOptionalData & IsExact; |
||
147 | } |
||
148 | |||
149 | static bool isPossiblyExactOpcode(unsigned OpC) { |
||
150 | return OpC == Instruction::SDiv || |
||
151 | OpC == Instruction::UDiv || |
||
152 | OpC == Instruction::AShr || |
||
153 | OpC == Instruction::LShr; |
||
154 | } |
||
155 | |||
156 | static bool classof(const ConstantExpr *CE) { |
||
157 | return isPossiblyExactOpcode(CE->getOpcode()); |
||
158 | } |
||
159 | static bool classof(const Instruction *I) { |
||
160 | return isPossiblyExactOpcode(I->getOpcode()); |
||
161 | } |
||
162 | static bool classof(const Value *V) { |
||
163 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || |
||
164 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); |
||
165 | } |
||
166 | }; |
||
167 | |||
168 | /// Utility class for floating point operations which can have |
||
169 | /// information about relaxed accuracy requirements attached to them. |
||
170 | class FPMathOperator : public Operator { |
||
171 | private: |
||
172 | friend class Instruction; |
||
173 | |||
174 | /// 'Fast' means all bits are set. |
||
175 | void setFast(bool B) { |
||
176 | setHasAllowReassoc(B); |
||
177 | setHasNoNaNs(B); |
||
178 | setHasNoInfs(B); |
||
179 | setHasNoSignedZeros(B); |
||
180 | setHasAllowReciprocal(B); |
||
181 | setHasAllowContract(B); |
||
182 | setHasApproxFunc(B); |
||
183 | } |
||
184 | |||
185 | void setHasAllowReassoc(bool B) { |
||
186 | SubclassOptionalData = |
||
187 | (SubclassOptionalData & ~FastMathFlags::AllowReassoc) | |
||
188 | (B * FastMathFlags::AllowReassoc); |
||
189 | } |
||
190 | |||
191 | void setHasNoNaNs(bool B) { |
||
192 | SubclassOptionalData = |
||
193 | (SubclassOptionalData & ~FastMathFlags::NoNaNs) | |
||
194 | (B * FastMathFlags::NoNaNs); |
||
195 | } |
||
196 | |||
197 | void setHasNoInfs(bool B) { |
||
198 | SubclassOptionalData = |
||
199 | (SubclassOptionalData & ~FastMathFlags::NoInfs) | |
||
200 | (B * FastMathFlags::NoInfs); |
||
201 | } |
||
202 | |||
203 | void setHasNoSignedZeros(bool B) { |
||
204 | SubclassOptionalData = |
||
205 | (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | |
||
206 | (B * FastMathFlags::NoSignedZeros); |
||
207 | } |
||
208 | |||
209 | void setHasAllowReciprocal(bool B) { |
||
210 | SubclassOptionalData = |
||
211 | (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | |
||
212 | (B * FastMathFlags::AllowReciprocal); |
||
213 | } |
||
214 | |||
215 | void setHasAllowContract(bool B) { |
||
216 | SubclassOptionalData = |
||
217 | (SubclassOptionalData & ~FastMathFlags::AllowContract) | |
||
218 | (B * FastMathFlags::AllowContract); |
||
219 | } |
||
220 | |||
221 | void setHasApproxFunc(bool B) { |
||
222 | SubclassOptionalData = |
||
223 | (SubclassOptionalData & ~FastMathFlags::ApproxFunc) | |
||
224 | (B * FastMathFlags::ApproxFunc); |
||
225 | } |
||
226 | |||
227 | /// Convenience function for setting multiple fast-math flags. |
||
228 | /// FMF is a mask of the bits to set. |
||
229 | void setFastMathFlags(FastMathFlags FMF) { |
||
230 | SubclassOptionalData |= FMF.Flags; |
||
231 | } |
||
232 | |||
233 | /// Convenience function for copying all fast-math flags. |
||
234 | /// All values in FMF are transferred to this operator. |
||
235 | void copyFastMathFlags(FastMathFlags FMF) { |
||
236 | SubclassOptionalData = FMF.Flags; |
||
237 | } |
||
238 | |||
239 | public: |
||
240 | /// Test if this operation allows all non-strict floating-point transforms. |
||
241 | bool isFast() const { |
||
242 | return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 && |
||
243 | (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 && |
||
244 | (SubclassOptionalData & FastMathFlags::NoInfs) != 0 && |
||
245 | (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 && |
||
246 | (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 && |
||
247 | (SubclassOptionalData & FastMathFlags::AllowContract) != 0 && |
||
248 | (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0); |
||
249 | } |
||
250 | |||
251 | /// Test if this operation may be simplified with reassociative transforms. |
||
252 | bool hasAllowReassoc() const { |
||
253 | return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0; |
||
254 | } |
||
255 | |||
256 | /// Test if this operation's arguments and results are assumed not-NaN. |
||
257 | bool hasNoNaNs() const { |
||
258 | return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; |
||
259 | } |
||
260 | |||
261 | /// Test if this operation's arguments and results are assumed not-infinite. |
||
262 | bool hasNoInfs() const { |
||
263 | return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; |
||
264 | } |
||
265 | |||
266 | /// Test if this operation can ignore the sign of zero. |
||
267 | bool hasNoSignedZeros() const { |
||
268 | return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; |
||
269 | } |
||
270 | |||
271 | /// Test if this operation can use reciprocal multiply instead of division. |
||
272 | bool hasAllowReciprocal() const { |
||
273 | return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; |
||
274 | } |
||
275 | |||
276 | /// Test if this operation can be floating-point contracted (FMA). |
||
277 | bool hasAllowContract() const { |
||
278 | return (SubclassOptionalData & FastMathFlags::AllowContract) != 0; |
||
279 | } |
||
280 | |||
281 | /// Test if this operation allows approximations of math library functions or |
||
282 | /// intrinsics. |
||
283 | bool hasApproxFunc() const { |
||
284 | return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0; |
||
285 | } |
||
286 | |||
287 | /// Convenience function for getting all the fast-math flags |
||
288 | FastMathFlags getFastMathFlags() const { |
||
289 | return FastMathFlags(SubclassOptionalData); |
||
290 | } |
||
291 | |||
292 | /// Get the maximum error permitted by this operation in ULPs. An accuracy of |
||
293 | /// 0.0 means that the operation should be performed with the default |
||
294 | /// precision. |
||
295 | float getFPAccuracy() const; |
||
296 | |||
297 | static bool classof(const Value *V) { |
||
298 | unsigned Opcode; |
||
299 | if (auto *I = dyn_cast<Instruction>(V)) |
||
300 | Opcode = I->getOpcode(); |
||
301 | else if (auto *CE = dyn_cast<ConstantExpr>(V)) |
||
302 | Opcode = CE->getOpcode(); |
||
303 | else |
||
304 | return false; |
||
305 | |||
306 | switch (Opcode) { |
||
307 | case Instruction::FNeg: |
||
308 | case Instruction::FAdd: |
||
309 | case Instruction::FSub: |
||
310 | case Instruction::FMul: |
||
311 | case Instruction::FDiv: |
||
312 | case Instruction::FRem: |
||
313 | // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp |
||
314 | // should not be treated as a math op, but the other opcodes should. |
||
315 | // This would make things consistent with Select/PHI (FP value type |
||
316 | // determines whether they are math ops and, therefore, capable of |
||
317 | // having fast-math-flags). |
||
318 | case Instruction::FCmp: |
||
319 | return true; |
||
320 | case Instruction::PHI: |
||
321 | case Instruction::Select: |
||
322 | case Instruction::Call: { |
||
323 | Type *Ty = V->getType(); |
||
324 | while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) |
||
325 | Ty = ArrTy->getElementType(); |
||
326 | return Ty->isFPOrFPVectorTy(); |
||
327 | } |
||
328 | default: |
||
329 | return false; |
||
330 | } |
||
331 | } |
||
332 | }; |
||
333 | |||
334 | /// A helper template for defining operators for individual opcodes. |
||
335 | template<typename SuperClass, unsigned Opc> |
||
336 | class ConcreteOperator : public SuperClass { |
||
337 | public: |
||
338 | static bool classof(const Instruction *I) { |
||
339 | return I->getOpcode() == Opc; |
||
340 | } |
||
341 | static bool classof(const ConstantExpr *CE) { |
||
342 | return CE->getOpcode() == Opc; |
||
343 | } |
||
344 | static bool classof(const Value *V) { |
||
345 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || |
||
346 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); |
||
347 | } |
||
348 | }; |
||
349 | |||
350 | class AddOperator |
||
351 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { |
||
352 | }; |
||
353 | class SubOperator |
||
354 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { |
||
355 | }; |
||
356 | class MulOperator |
||
357 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { |
||
358 | }; |
||
359 | class ShlOperator |
||
360 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { |
||
361 | }; |
||
362 | |||
363 | class SDivOperator |
||
364 | : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { |
||
365 | }; |
||
366 | class UDivOperator |
||
367 | : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { |
||
368 | }; |
||
369 | class AShrOperator |
||
370 | : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { |
||
371 | }; |
||
372 | class LShrOperator |
||
373 | : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { |
||
374 | }; |
||
375 | |||
376 | class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {}; |
||
377 | |||
378 | class GEPOperator |
||
379 | : public ConcreteOperator<Operator, Instruction::GetElementPtr> { |
||
380 | friend class GetElementPtrInst; |
||
381 | friend class ConstantExpr; |
||
382 | |||
383 | enum { |
||
384 | IsInBounds = (1 << 0), |
||
385 | // InRangeIndex: bits 1-6 |
||
386 | }; |
||
387 | |||
388 | void setIsInBounds(bool B) { |
||
389 | SubclassOptionalData = |
||
390 | (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); |
||
391 | } |
||
392 | |||
393 | public: |
||
394 | /// Test whether this is an inbounds GEP, as defined by LangRef.html. |
||
395 | bool isInBounds() const { |
||
396 | return SubclassOptionalData & IsInBounds; |
||
397 | } |
||
398 | |||
399 | /// Returns the offset of the index with an inrange attachment, or |
||
400 | /// std::nullopt if none. |
||
401 | std::optional<unsigned> getInRangeIndex() const { |
||
402 | if (SubclassOptionalData >> 1 == 0) |
||
403 | return std::nullopt; |
||
404 | return (SubclassOptionalData >> 1) - 1; |
||
405 | } |
||
406 | |||
407 | inline op_iterator idx_begin() { return op_begin()+1; } |
||
408 | inline const_op_iterator idx_begin() const { return op_begin()+1; } |
||
409 | inline op_iterator idx_end() { return op_end(); } |
||
410 | inline const_op_iterator idx_end() const { return op_end(); } |
||
411 | |||
412 | inline iterator_range<op_iterator> indices() { |
||
413 | return make_range(idx_begin(), idx_end()); |
||
414 | } |
||
415 | |||
416 | inline iterator_range<const_op_iterator> indices() const { |
||
417 | return make_range(idx_begin(), idx_end()); |
||
418 | } |
||
419 | |||
420 | Value *getPointerOperand() { |
||
421 | return getOperand(0); |
||
422 | } |
||
423 | const Value *getPointerOperand() const { |
||
424 | return getOperand(0); |
||
425 | } |
||
426 | static unsigned getPointerOperandIndex() { |
||
427 | return 0U; // get index for modifying correct operand |
||
428 | } |
||
429 | |||
430 | /// Method to return the pointer operand as a PointerType. |
||
431 | Type *getPointerOperandType() const { |
||
432 | return getPointerOperand()->getType(); |
||
433 | } |
||
434 | |||
435 | Type *getSourceElementType() const; |
||
436 | Type *getResultElementType() const; |
||
437 | |||
438 | /// Method to return the address space of the pointer operand. |
||
439 | unsigned getPointerAddressSpace() const { |
||
440 | return getPointerOperandType()->getPointerAddressSpace(); |
||
441 | } |
||
442 | |||
443 | unsigned getNumIndices() const { // Note: always non-negative |
||
444 | return getNumOperands() - 1; |
||
445 | } |
||
446 | |||
447 | bool hasIndices() const { |
||
448 | return getNumOperands() > 1; |
||
449 | } |
||
450 | |||
451 | /// Return true if all of the indices of this GEP are zeros. |
||
452 | /// If so, the result pointer and the first operand have the same |
||
453 | /// value, just potentially different types. |
||
454 | bool hasAllZeroIndices() const { |
||
455 | for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { |
||
456 | if (ConstantInt *C = dyn_cast<ConstantInt>(I)) |
||
457 | if (C->isZero()) |
||
458 | continue; |
||
459 | return false; |
||
460 | } |
||
461 | return true; |
||
462 | } |
||
463 | |||
464 | /// Return true if all of the indices of this GEP are constant integers. |
||
465 | /// If so, the result pointer and the first operand have |
||
466 | /// a constant offset between them. |
||
467 | bool hasAllConstantIndices() const { |
||
468 | for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { |
||
469 | if (!isa<ConstantInt>(I)) |
||
470 | return false; |
||
471 | } |
||
472 | return true; |
||
473 | } |
||
474 | |||
475 | unsigned countNonConstantIndices() const { |
||
476 | return count_if(indices(), [](const Use& use) { |
||
477 | return !isa<ConstantInt>(*use); |
||
478 | }); |
||
479 | } |
||
480 | |||
481 | /// Compute the maximum alignment that this GEP is garranteed to preserve. |
||
482 | Align getMaxPreservedAlignment(const DataLayout &DL) const; |
||
483 | |||
484 | /// Accumulate the constant address offset of this GEP if possible. |
||
485 | /// |
||
486 | /// This routine accepts an APInt into which it will try to accumulate the |
||
487 | /// constant offset of this GEP. |
||
488 | /// |
||
489 | /// If \p ExternalAnalysis is provided it will be used to calculate a offset |
||
490 | /// when a operand of GEP is not constant. |
||
491 | /// For example, for a value \p ExternalAnalysis might try to calculate a |
||
492 | /// lower bound. If \p ExternalAnalysis is successful, it should return true. |
||
493 | /// |
||
494 | /// If the \p ExternalAnalysis returns false or the value returned by \p |
||
495 | /// ExternalAnalysis results in a overflow/underflow, this routine returns |
||
496 | /// false and the value of the offset APInt is undefined (it is *not* |
||
497 | /// preserved!). |
||
498 | /// |
||
499 | /// The APInt passed into this routine must be at exactly as wide as the |
||
500 | /// IntPtr type for the address space of the base GEP pointer. |
||
501 | bool accumulateConstantOffset( |
||
502 | const DataLayout &DL, APInt &Offset, |
||
503 | function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const; |
||
504 | |||
505 | static bool accumulateConstantOffset( |
||
506 | Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, |
||
507 | APInt &Offset, |
||
508 | function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr); |
||
509 | |||
510 | /// Collect the offset of this GEP as a map of Values to their associated |
||
511 | /// APInt multipliers, as well as a total Constant Offset. |
||
512 | bool collectOffset(const DataLayout &DL, unsigned BitWidth, |
||
513 | MapVector<Value *, APInt> &VariableOffsets, |
||
514 | APInt &ConstantOffset) const; |
||
515 | }; |
||
516 | |||
517 | class PtrToIntOperator |
||
518 | : public ConcreteOperator<Operator, Instruction::PtrToInt> { |
||
519 | friend class PtrToInt; |
||
520 | friend class ConstantExpr; |
||
521 | |||
522 | public: |
||
523 | Value *getPointerOperand() { |
||
524 | return getOperand(0); |
||
525 | } |
||
526 | const Value *getPointerOperand() const { |
||
527 | return getOperand(0); |
||
528 | } |
||
529 | |||
530 | static unsigned getPointerOperandIndex() { |
||
531 | return 0U; // get index for modifying correct operand |
||
532 | } |
||
533 | |||
534 | /// Method to return the pointer operand as a PointerType. |
||
535 | Type *getPointerOperandType() const { |
||
536 | return getPointerOperand()->getType(); |
||
537 | } |
||
538 | |||
539 | /// Method to return the address space of the pointer operand. |
||
540 | unsigned getPointerAddressSpace() const { |
||
541 | return cast<PointerType>(getPointerOperandType())->getAddressSpace(); |
||
542 | } |
||
543 | }; |
||
544 | |||
545 | class BitCastOperator |
||
546 | : public ConcreteOperator<Operator, Instruction::BitCast> { |
||
547 | friend class BitCastInst; |
||
548 | friend class ConstantExpr; |
||
549 | |||
550 | public: |
||
551 | Type *getSrcTy() const { |
||
552 | return getOperand(0)->getType(); |
||
553 | } |
||
554 | |||
555 | Type *getDestTy() const { |
||
556 | return getType(); |
||
557 | } |
||
558 | }; |
||
559 | |||
560 | class AddrSpaceCastOperator |
||
561 | : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> { |
||
562 | friend class AddrSpaceCastInst; |
||
563 | friend class ConstantExpr; |
||
564 | |||
565 | public: |
||
566 | Value *getPointerOperand() { return getOperand(0); } |
||
567 | |||
568 | const Value *getPointerOperand() const { return getOperand(0); } |
||
569 | |||
570 | unsigned getSrcAddressSpace() const { |
||
571 | return getPointerOperand()->getType()->getPointerAddressSpace(); |
||
572 | } |
||
573 | |||
574 | unsigned getDestAddressSpace() const { |
||
575 | return getType()->getPointerAddressSpace(); |
||
576 | } |
||
577 | }; |
||
578 | |||
579 | } // end namespace llvm |
||
580 | |||
581 | #endif // LLVM_IR_OPERATOR_H |