This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- ast/Range.cpp ----------------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009, Stephen Wilson 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 // Try to evaluate the upper and lower bounds as static discrete 00045 // expressions and mark each bound as appropriate. 00046 if (lower->staticDiscreteValue(lowerValue)) 00047 markLowerAsStatic(); 00048 if (upper->staticDiscreteValue(upperValue)) 00049 markUpperAsStatic(); 00050 00051 // If a type is associated with this range, resolve the width of the static 00052 // bounds (if available). 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 // FIXME: Perhaps this method should return a ternary value instead of a 00113 // bool. 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 // Extract the bounds of this range according to the type. 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 // The range is non-null, so upper > 0 and lower >= 0. 00166 return uint64_t(upper - lower) + 1; 00167 }