00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "comma/ast/Expr.h"
00010 #include "comma/ast/Range.h"
00011
00012 #include "llvm/ADT/APInt.h"
00013
00014 using namespace comma;
00015 using llvm::dyn_cast;
00016 using llvm::cast;
00017 using llvm::isa;
00018
00019
00020 Range::Range(Expr *lower, Expr *upper, DiscreteType *type)
00021 : Ast(AST_Range),
00022 lowerBound(lower, 0),
00023 upperBound(upper, 0),
00024 rangeTy(type)
00025 {
00026 initializeStaticBounds();
00027 }
00028
00029 Location Range::getLowerLocation() const
00030 {
00031 return getLowerBound()->getLocation();
00032 }
00033
00034 Location Range::getUpperLocation() const
00035 {
00036 return getUpperBound()->getLocation();
00037 }
00038
00039 void Range::initializeStaticBounds()
00040 {
00041 Expr *lower = getLowerBound();
00042 Expr *upper = getUpperBound();
00043
00044
00045
00046 if (lower->staticDiscreteValue(lowerValue))
00047 markLowerAsStatic();
00048 if (upper->staticDiscreteValue(upperValue))
00049 markUpperAsStatic();
00050
00051
00052
00053 if (hasType())
00054 checkAndAdjustLimits();
00055 }
00056
00057 void Range::checkAndAdjustLimits()
00058 {
00059 assert(rangeTy && "Range type not set!");
00060
00061 unsigned width = rangeTy->getSize();
00062 if (hasStaticLowerBound()) {
00063 assert(lowerValue.getMinSignedBits() <= width && "Bounds too wide!");
00064 lowerValue.sextOrTrunc(width);
00065 }
00066 if (hasStaticUpperBound()) {
00067 assert(upperValue.getMinSignedBits() <= width && "Bounds too wide!");
00068 upperValue.sextOrTrunc(width);
00069 }
00070 }
00071
00072 void Range::setLowerBound(Expr *expr)
00073 {
00074 lowerBound.setPointer(expr);
00075 if (expr->staticDiscreteValue(lowerValue)) {
00076 markLowerAsStatic();
00077 if (hasType())
00078 checkAndAdjustLimits();
00079 }
00080 else
00081 markLowerAsDynamic();
00082 }
00083
00084 void Range::setUpperBound(Expr *expr)
00085 {
00086 upperBound.setPointer(expr);
00087 if (expr->staticDiscreteValue(upperValue)) {
00088 markUpperAsStatic();
00089 if (hasType())
00090 checkAndAdjustLimits();
00091 }
00092 else
00093 markUpperAsDynamic();
00094 }
00095
00096 bool Range::isNull() const
00097 {
00098 if (!isStatic())
00099 return false;
00100
00101 const llvm::APInt &lower = getStaticLowerBound();
00102 const llvm::APInt &upper = getStaticUpperBound();
00103
00104 if (getType()->isSigned())
00105 return upper.slt(lower);
00106 else
00107 return upper.ult(lower);
00108 }
00109
00110 bool Range::contains(const llvm::APInt &value) const
00111 {
00112
00113
00114 assert(isStatic() && "Cannot determin containment for non-static ranges!");
00115
00116 if (isNull())
00117 return false;
00118
00119 llvm::APInt candidate(value);
00120
00121 unsigned rangeWidth = getType()->getSize();
00122
00123 if (candidate.getMinSignedBits() > rangeWidth)
00124 return false;
00125 else if (candidate.getBitWidth() > rangeWidth)
00126 candidate.trunc(rangeWidth);
00127 else if (candidate.getBitWidth() < rangeWidth)
00128 candidate.sext(rangeWidth);
00129
00130 const llvm::APInt &lower = getStaticLowerBound();
00131 const llvm::APInt &upper = getStaticUpperBound();
00132 return lower.sle(candidate) && candidate.sle(upper);
00133 }
00134
00135 uint64_t Range::length() const
00136 {
00137 assert(isStatic() && "Cannot compute length of non-static range!");
00138
00139 if (isNull())
00140 return 0;
00141
00142 int64_t lower;
00143 int64_t upper;
00144
00145
00146 if (getType()->isSigned()) {
00147 lower = getStaticLowerBound().getSExtValue();
00148 upper = getStaticUpperBound().getSExtValue();
00149 }
00150 else {
00151 lower = getStaticLowerBound().getZExtValue();
00152 upper = getStaticUpperBound().getZExtValue();
00153 }
00154
00155 if (lower < 0) {
00156 uint64_t lowElems = -lower;
00157 if (upper >= 0)
00158 return uint64_t(upper) + lowElems + 1;
00159 else {
00160 uint64_t upElems = -upper;
00161 return lowElems - upElems + 1;
00162 }
00163 }
00164
00165
00166 return uint64_t(upper - lower) + 1;
00167 }