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