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