#define LLVM_OPERATOR_H
#include "llvm/Constants.h"
+#include "llvm/DataLayout.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Instruction.h"
+#include "llvm/Type.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
namespace llvm {
private:
// Do not implement any of these. The Operator class is intended to be used
// as a utility, and is never itself instantiated.
- void *operator new(size_t, unsigned);
- void *operator new(size_t s);
- Operator();
+ void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t s) LLVM_DELETED_FUNCTION;
+ Operator() LLVM_DELETED_FUNCTION;
+
+protected:
+ // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete
+ // an overridden method that's not deleted in the base class. Cannot leave
+ // this unimplemented because that leads to an ODR-violation.
~Operator();
public:
return Instruction::UserOp1;
}
- static inline bool classof(const Operator *) { return true; }
static inline bool classof(const Instruction *) { return true; }
static inline bool classof(const ConstantExpr *) { return true; }
static inline bool classof(const Value *V) {
};
private:
- ~OverflowingBinaryOperator(); // do not implement
-
friend class BinaryOperator;
friend class ConstantExpr;
void setHasNoUnsignedWrap(bool B) {
return (SubclassOptionalData & NoSignedWrap) != 0;
}
- static inline bool classof(const OverflowingBinaryOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Add ||
I->getOpcode() == Instruction::Sub ||
enum {
IsExact = (1 << 0)
};
-
+
+private:
friend class BinaryOperator;
friend class ConstantExpr;
void setIsExact(bool B) {
SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
}
-
-private:
- ~PossiblyExactOperator(); // do not implement
+
public:
/// isExact - Test whether this division is known to be exact, with
/// zero remainder.
bool isExact() const {
return SubclassOptionalData & IsExact;
}
-
+
static bool isPossiblyExactOpcode(unsigned OpC) {
return OpC == Instruction::SDiv ||
OpC == Instruction::UDiv ||
(isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
}
};
-
-
+/// Convenience struct for specifying and reasoning about fast-math flags.
+class FastMathFlags {
+private:
+ friend class FPMathOperator;
+ unsigned Flags;
+ FastMathFlags(unsigned F) : Flags(F) { }
+
+public:
+ enum {
+ UnsafeAlgebra = (1 << 0),
+ NoNaNs = (1 << 1),
+ NoInfs = (1 << 2),
+ NoSignedZeros = (1 << 3),
+ AllowReciprocal = (1 << 4)
+ };
+
+ FastMathFlags() : Flags(0)
+ { }
+
+ /// Whether any flag is set
+ bool any() { return Flags != 0; }
+
+ /// Set all the flags to false
+ void clear() { Flags = 0; }
+
+ /// Flag queries
+ bool noNaNs() { return 0 != (Flags & NoNaNs); }
+ bool noInfs() { return 0 != (Flags & NoInfs); }
+ bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); }
+ bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); }
+ bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); }
+
+ /// Flag setters
+ void setNoNaNs() { Flags |= NoNaNs; }
+ void setNoInfs() { Flags |= NoInfs; }
+ void setNoSignedZeros() { Flags |= NoSignedZeros; }
+ void setAllowReciprocal() { Flags |= AllowReciprocal; }
+ void setUnsafeAlgebra() {
+ Flags |= UnsafeAlgebra;
+ setNoNaNs();
+ setNoInfs();
+ setNoSignedZeros();
+ setAllowReciprocal();
+ }
+};
+
+
+/// FPMathOperator - Utility class for floating point operations which can have
+/// information about relaxed accuracy requirements attached to them.
+class FPMathOperator : public Operator {
+private:
+ friend class Instruction;
+
+ void setHasUnsafeAlgebra(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::UnsafeAlgebra) |
+ (B * FastMathFlags::UnsafeAlgebra);
+
+ // Unsafe algebra implies all the others
+ if (B) {
+ setHasNoNaNs(true);
+ setHasNoInfs(true);
+ setHasNoSignedZeros(true);
+ setHasAllowReciprocal(true);
+ }
+ }
+ void setHasNoNaNs(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::NoNaNs) |
+ (B * FastMathFlags::NoNaNs);
+ }
+ void setHasNoInfs(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::NoInfs) |
+ (B * FastMathFlags::NoInfs);
+ }
+ void setHasNoSignedZeros(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) |
+ (B * FastMathFlags::NoSignedZeros);
+ }
+ void setHasAllowReciprocal(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) |
+ (B * FastMathFlags::AllowReciprocal);
+ }
+
+ /// Convenience function for setting all the fast-math flags
+ void setFastMathFlags(FastMathFlags FMF) {
+ SubclassOptionalData |= FMF.Flags;
+ }
+
+public:
+ /// Test whether this operation is permitted to be
+ /// algebraically transformed, aka the 'A' fast-math property.
+ bool hasUnsafeAlgebra() const {
+ return (SubclassOptionalData & FastMathFlags::UnsafeAlgebra) != 0;
+ }
+
+ /// Test whether this operation's arguments and results are to be
+ /// treated as non-NaN, aka the 'N' fast-math property.
+ bool hasNoNaNs() const {
+ return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0;
+ }
+
+ /// Test whether this operation's arguments and results are to be
+ /// treated as NoN-Inf, aka the 'I' fast-math property.
+ bool hasNoInfs() const {
+ return (SubclassOptionalData & FastMathFlags::NoInfs) != 0;
+ }
+
+ /// Test whether this operation can treat the sign of zero
+ /// as insignificant, aka the 'S' fast-math property.
+ bool hasNoSignedZeros() const {
+ return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0;
+ }
+
+ /// Test whether this operation is permitted to use
+ /// reciprocal instead of division, aka the 'R' fast-math property.
+ bool hasAllowReciprocal() const {
+ return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
+ }
+
+ /// Convenience function for getting all the fast-math flags
+ FastMathFlags getFastMathFlags() const {
+ return FastMathFlags(SubclassOptionalData);
+ }
+
+ /// \brief Get the maximum error permitted by this operation in ULPs. An
+ /// accuracy of 0.0 means that the operation should be performed with the
+ /// default precision.
+ float getFPAccuracy() const;
+
+ static inline bool classof(const Instruction *I) {
+ return I->getType()->isFPOrFPVectorTy();
+ }
+ static inline bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
+
/// ConcreteOperator - A helper template for defining operators for individual
/// opcodes.
template<typename SuperClass, unsigned Opc>
class ConcreteOperator : public SuperClass {
- ~ConcreteOperator(); // DO NOT IMPLEMENT
public:
- static inline bool classof(const ConcreteOperator<SuperClass, Opc> *) {
- return true;
- }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Opc;
}
}
};
-class FAddOperator : public ConcreteOperator<Operator, Instruction::FAdd> {
- ~FAddOperator(); // DO NOT IMPLEMENT
-};
-class FSubOperator : public ConcreteOperator<Operator, Instruction::FSub> {
- ~FSubOperator(); // DO NOT IMPLEMENT
-};
-class FMulOperator : public ConcreteOperator<Operator, Instruction::FMul> {
- ~FMulOperator(); // DO NOT IMPLEMENT
-};
-class FDivOperator : public ConcreteOperator<Operator, Instruction::FDiv> {
- ~FDivOperator(); // DO NOT IMPLEMENT
-};
-class URemOperator : public ConcreteOperator<Operator, Instruction::URem> {
- ~URemOperator(); // DO NOT IMPLEMENT
-};
-class SRemOperator : public ConcreteOperator<Operator, Instruction::SRem> {
- ~SRemOperator(); // DO NOT IMPLEMENT
-};
-class FRemOperator : public ConcreteOperator<Operator, Instruction::FRem> {
- ~FRemOperator(); // DO NOT IMPLEMENT
-};
-class AndOperator : public ConcreteOperator<Operator, Instruction::And> {
- ~AndOperator(); // DO NOT IMPLEMENT
-};
-class OrOperator : public ConcreteOperator<Operator, Instruction::Or> {
- ~OrOperator(); // DO NOT IMPLEMENT
-};
-class XorOperator : public ConcreteOperator<Operator, Instruction::Xor> {
- ~XorOperator(); // DO NOT IMPLEMENT
-};
-class TruncOperator : public ConcreteOperator<Operator, Instruction::Trunc> {
- ~TruncOperator(); // DO NOT IMPLEMENT
-};
-class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {
- ~ZExtOperator(); // DO NOT IMPLEMENT
-};
-class SExtOperator : public ConcreteOperator<Operator, Instruction::SExt> {
- ~SExtOperator(); // DO NOT IMPLEMENT
-};
-class FPToUIOperator : public ConcreteOperator<Operator, Instruction::FPToUI> {
- ~FPToUIOperator(); // DO NOT IMPLEMENT
-};
-class FPToSIOperator : public ConcreteOperator<Operator, Instruction::FPToSI> {
- ~FPToSIOperator(); // DO NOT IMPLEMENT
-};
-class UIToFPOperator : public ConcreteOperator<Operator, Instruction::UIToFP> {
- ~UIToFPOperator(); // DO NOT IMPLEMENT
-};
-class SIToFPOperator : public ConcreteOperator<Operator, Instruction::SIToFP> {
- ~SIToFPOperator(); // DO NOT IMPLEMENT
-};
-class FPTruncOperator
- : public ConcreteOperator<Operator, Instruction::FPTrunc> {
- ~FPTruncOperator(); // DO NOT IMPLEMENT
-};
-class FPExtOperator : public ConcreteOperator<Operator, Instruction::FPExt> {
- ~FPExtOperator(); // DO NOT IMPLEMENT
-};
-class PtrToIntOperator
- : public ConcreteOperator<Operator, Instruction::PtrToInt> {
- ~PtrToIntOperator(); // DO NOT IMPLEMENT
-};
-class IntToPtrOperator
- : public ConcreteOperator<Operator, Instruction::IntToPtr> {
- ~IntToPtrOperator(); // DO NOT IMPLEMENT
-};
-class BitCastOperator
- : public ConcreteOperator<Operator, Instruction::BitCast> {
- ~BitCastOperator(); // DO NOT IMPLEMENT
-};
-class ICmpOperator : public ConcreteOperator<Operator, Instruction::ICmp> {
- ~ICmpOperator(); // DO NOT IMPLEMENT
-};
-class FCmpOperator : public ConcreteOperator<Operator, Instruction::FCmp> {
- ~FCmpOperator(); // DO NOT IMPLEMENT
-};
-class SelectOperator : public ConcreteOperator<Operator, Instruction::Select> {
- ~SelectOperator(); // DO NOT IMPLEMENT
-};
-class ExtractElementOperator
- : public ConcreteOperator<Operator, Instruction::ExtractElement> {
- ~ExtractElementOperator(); // DO NOT IMPLEMENT
-};
-class InsertElementOperator
- : public ConcreteOperator<Operator, Instruction::InsertElement> {
- ~InsertElementOperator(); // DO NOT IMPLEMENT
-};
-class ShuffleVectorOperator
- : public ConcreteOperator<Operator, Instruction::ShuffleVector> {
- ~ShuffleVectorOperator(); // DO NOT IMPLEMENT
-};
-class ExtractValueOperator
- : public ConcreteOperator<Operator, Instruction::ExtractValue> {
- ~ExtractValueOperator(); // DO NOT IMPLEMENT
-};
-class InsertValueOperator
- : public ConcreteOperator<Operator, Instruction::InsertValue> {
- ~InsertValueOperator(); // DO NOT IMPLEMENT
-};
-
class AddOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {
- ~AddOperator(); // DO NOT IMPLEMENT
};
class SubOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {
- ~SubOperator(); // DO NOT IMPLEMENT
};
class MulOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {
- ~MulOperator(); // DO NOT IMPLEMENT
};
class ShlOperator
: public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {
- ~ShlOperator(); // DO NOT IMPLEMENT
};
-
+
class SDivOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {
- ~SDivOperator(); // DO NOT IMPLEMENT
};
class UDivOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {
- ~UDivOperator(); // DO NOT IMPLEMENT
};
class AShrOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {
- ~AShrOperator(); // DO NOT IMPLEMENT
};
class LShrOperator
: public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {
- ~LShrOperator(); // DO NOT IMPLEMENT
};
-
-
-
+
+
+
class GEPOperator
: public ConcreteOperator<Operator, Instruction::GetElementPtr> {
- ~GEPOperator(); // DO NOT IMPLEMENT
-
enum {
IsInBounds = (1 << 0)
};
/// getPointerOperandType - Method to return the pointer operand as a
/// PointerType.
- const PointerType *getPointerOperandType() const {
- return reinterpret_cast<const PointerType*>(getPointerOperand()->getType());
+ Type *getPointerOperandType() const {
+ return getPointerOperand()->getType();
+ }
+
+ /// getPointerAddressSpace - Method to return the address space of the
+ /// pointer operand.
+ unsigned getPointerAddressSpace() const {
+ return cast<PointerType>(getPointerOperandType())->getAddressSpace();
}
unsigned getNumIndices() const { // Note: always non-negative
}
return true;
}
+
+ /// \brief Accumulate the constant address offset of this GEP if possible.
+ ///
+ /// This routine accepts an APInt into which it will accumulate the constant
+ /// offset of this GEP if the GEP is in fact constant. If the GEP is not
+ /// all-constant, it returns false and the value of the offset APInt is
+ /// undefined (it is *not* preserved!). The APInt passed into this routine
+ /// must be at least as wide as the IntPtr type for the address space of
+ /// the base GEP pointer.
+ bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const {
+ assert(Offset.getBitWidth() ==
+ DL.getPointerSizeInBits(getPointerAddressSpace()) &&
+ "The offset must have exactly as many bits as our pointer.");
+
+ for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
+ GTI != GTE; ++GTI) {
+ ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
+ if (!OpC)
+ return false;
+ if (OpC->isZero())
+ continue;
+
+ // Handle a struct index, which adds its field offset to the pointer.
+ if (StructType *STy = dyn_cast<StructType>(*GTI)) {
+ unsigned ElementIdx = OpC->getZExtValue();
+ const StructLayout *SL = DL.getStructLayout(STy);
+ Offset += APInt(Offset.getBitWidth(),
+ SL->getElementOffset(ElementIdx));
+ continue;
+ }
+
+ // For array or vector indices, scale the index by the size of the type.
+ APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth());
+ Offset += Index * APInt(Offset.getBitWidth(),
+ DL.getTypeAllocSize(GTI.getIndexedType()));
+ }
+ return true;
+ }
+
};
} // End llvm namespace