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 }