00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "CGContext.h"
00010 #include "CodeGenRoutine.h"
00011 #include "BoundsEmitter.h"
00012 #include "comma/ast/AggExpr.h"
00013
00014 using namespace comma;
00015 using llvm::dyn_cast;
00016 using llvm::cast;
00017 using llvm::isa;
00018
00019 namespace {
00020
00023 llvm::Value *synthBounds(llvm::IRBuilder<> &Builder,
00024 const llvm::StructType *boundTy,
00025 llvm::Value *lower, llvm::Value *upper)
00026 {
00027
00028 if (isa<llvm::Constant>(lower) && isa<llvm::Constant>(upper)) {
00029 std::vector<llvm::Constant*> elts;
00030 elts.push_back(cast<llvm::Constant>(lower));
00031 elts.push_back(cast<llvm::Constant>(upper));
00032 return llvm::ConstantStruct::get(boundTy, elts);
00033 }
00034
00035
00036 llvm::Value *bounds = llvm::UndefValue::get(boundTy);
00037 bounds = Builder.CreateInsertValue(bounds, lower, 0);
00038 bounds = Builder.CreateInsertValue(bounds, upper, 1);
00039 return bounds;
00040 }
00041
00042 }
00043
00044
00045 BoundsEmitter::BoundsEmitter(CodeGenRoutine &CGR)
00046 : CGR(CGR),
00047 CG(CGR.getCodeGen()),
00048 CGT(CGR.getCGC().getCGT()) { }
00049
00050 const llvm::StructType *BoundsEmitter::getType(const ArrayType *arrTy)
00051 {
00052 return CGT.lowerArrayBounds(arrTy);
00053 }
00054
00055 llvm::Value *BoundsEmitter::synthScalarBounds(llvm::IRBuilder<> &Builder,
00056 const DiscreteType *type)
00057 {
00058 LUPair LU = getScalarBounds(Builder, type);
00059 llvm::Value *lower = LU.first;
00060 llvm::Value *upper = LU.second;
00061 const llvm::StructType *boundTy = CGT.lowerScalarBounds(type);
00062 return synthBounds(Builder, boundTy, lower, upper);
00063 }
00064
00065 BoundsEmitter::LUPair
00066 BoundsEmitter::getScalarBounds(llvm::IRBuilder<> &Builder,
00067 const DiscreteType *type)
00068 {
00069 LUPair LU;
00070
00071 if (const Range *range = type->getConstraint()) {
00072 if (range->isStatic())
00073 LU = getRange(Builder, range);
00074 else {
00075
00076
00077
00078 SRFrame *frame = CGR.getSRFrame();
00079 llvm::Value *bounds = frame->lookup(type, activation::Bounds);
00080
00081 if (!bounds) {
00082 bounds = synthRange(Builder, range);
00083 frame->associate(type, activation::Bounds, bounds);
00084 }
00085 LU.first = getLowerBound(Builder, bounds, 0);
00086 LU.second = getUpperBound(Builder, bounds, 0);
00087 }
00088 }
00089 else {
00090 const llvm::Type *loweredTy = CGT.lowerType(type);
00091 llvm::APInt bound;
00092
00093 type->getLowerLimit(bound);
00094 LU.first = llvm::ConstantInt::get(loweredTy, bound);
00095
00096 type->getUpperLimit(bound);
00097 LU.second = llvm::ConstantInt::get(loweredTy, bound);
00098 }
00099
00100 return LU;
00101 }
00102
00103 llvm::Value *BoundsEmitter::getLowerBound(llvm::IRBuilder<> &Builder,
00104 const DiscreteType *type)
00105 {
00106 if (type->isConstrained())
00107 return getLowerBound(Builder, type->getConstraint());
00108
00109 const llvm::Type *loweredTy = CGT.lowerType(type);
00110 llvm::APInt bound;
00111
00112 type->getLowerLimit(bound);
00113 return llvm::ConstantInt::get(loweredTy, bound);
00114 }
00115
00116 llvm::Value *BoundsEmitter::getUpperBound(llvm::IRBuilder<> &Builder,
00117 const DiscreteType *type)
00118 {
00119 if (type->isConstrained())
00120 return getUpperBound(Builder, type->getConstraint());
00121
00122 const llvm::Type *loweredTy = CGT.lowerType(type);
00123 llvm::APInt bound;
00124
00125 type->getUpperLimit(bound);
00126 return llvm::ConstantInt::get(loweredTy, bound);
00127 }
00128
00129 llvm::Value *BoundsEmitter::getLowerBound(llvm::IRBuilder<> &Builder,
00130 const Range *range)
00131 {
00132 const llvm::Type *elemTy = CGT.lowerType(range->getType());
00133
00134 if (range->hasStaticLowerBound()) {
00135 const llvm::APInt &bound = range->getStaticLowerBound();
00136 return llvm::ConstantInt::get(elemTy, bound);
00137 }
00138 else {
00139 Expr *expr = const_cast<Expr*>(range->getLowerBound());
00140 return CGR.emitValue(expr).first();
00141 }
00142 }
00143
00144 llvm::Value *BoundsEmitter::getUpperBound(llvm::IRBuilder<> &Builder,
00145 const Range *range)
00146 {
00147 const llvm::Type *elemTy = CGT.lowerType(range->getType());
00148
00149 if (range->hasStaticUpperBound()) {
00150 const llvm::APInt &bound = range->getStaticUpperBound();
00151 return llvm::ConstantInt::get(elemTy, bound);
00152 }
00153 else {
00154 Expr *expr = const_cast<Expr*>(range->getUpperBound());
00155 return CGR.emitValue(expr).first();
00156 }
00157 }
00158
00159 llvm::Value *BoundsEmitter::synthRange(llvm::IRBuilder<> &Builder,
00160 const Range *range)
00161 {
00162 llvm::Value *lower = getLowerBound(Builder, range);
00163 llvm::Value *upper = getUpperBound(Builder, range);
00164 const llvm::StructType *boundTy = CGT.lowerRange(range);
00165 return synthBounds(Builder, boundTy, lower, upper);
00166 }
00167
00168 llvm::Value *BoundsEmitter::synthRange(llvm::IRBuilder<> &Builder,
00169 llvm::Value *lower, llvm::Value *upper)
00170 {
00171 std::vector<const llvm::Type*> elts;
00172 const llvm::IntegerType *limitTy;
00173 limitTy = cast<llvm::IntegerType>(lower->getType());
00174 assert(limitTy == upper->getType() && "Inconsitent types for range!");
00175
00176
00177 elts.push_back(limitTy);
00178 elts.push_back(limitTy);
00179 return synthBounds(Builder, CG.getStructTy(elts), lower, upper);
00180 }
00181
00182 BoundsEmitter::LUPair BoundsEmitter::getRange(llvm::IRBuilder<> &Builder,
00183 const Range *range)
00184 {
00185 llvm::Value *lower = getLowerBound(Builder, range);
00186 llvm::Value *upper = getUpperBound(Builder, range);
00187 return LUPair(lower, upper);
00188 }
00189
00190 llvm::Value *BoundsEmitter::computeBoundLength(llvm::IRBuilder<> &Builder,
00191 llvm::Value *bounds,
00192 unsigned index)
00193 {
00194 llvm::Value *lower = getLowerBound(Builder, bounds, index);
00195 llvm::Value *upper = getUpperBound(Builder, bounds, index);
00196
00197
00198
00199
00200
00201
00202 const llvm::IntegerType *boundTy;
00203 const llvm::IntegerType *i32Ty;
00204
00205 boundTy = cast<llvm::IntegerType>(lower->getType());
00206 i32Ty = CG.getInt32Ty();
00207
00208 if (boundTy->getBitWidth() < 32) {
00209 lower = Builder.CreateSExt(lower, i32Ty);
00210 upper = Builder.CreateSExt(upper, i32Ty);
00211 }
00212 else if (boundTy->getBitWidth() > 32) {
00213 lower = Builder.CreateTrunc(lower, i32Ty);
00214 upper = Builder.CreateTrunc(upper, i32Ty);
00215 }
00216
00217 llvm::Value *size = Builder.CreateSub(upper, lower);
00218 llvm::Value *one = llvm::ConstantInt::get(size->getType(), 1);
00219 return Builder.CreateAdd(size, one);
00220 }
00221
00222 llvm::Value *BoundsEmitter::computeTotalBoundLength(llvm::IRBuilder<> &Builder,
00223 llvm::Value *bounds)
00224 {
00225 const llvm::StructType *strTy;
00226 const llvm::IntegerType *sumTy;
00227 llvm::Value *length;
00228 unsigned numElts;
00229
00230
00231 if (!bounds->getType()->isAggregateType())
00232 bounds = Builder.CreateLoad(bounds);
00233
00234 strTy = cast<llvm::StructType>(bounds->getType());
00235 sumTy = CG.getInt32Ty();
00236
00237 length = llvm::ConstantInt::get(sumTy, int64_t(0));
00238 numElts = strTy->getNumElements() / 2;
00239
00240 for (unsigned idx = 0; idx < numElts; ++idx) {
00241 llvm::Value *partial = computeBoundLength(Builder, bounds, idx);
00242 length = Builder.CreateAdd(length, partial);
00243 }
00244 return length;
00245 }
00246
00247 llvm::Value *BoundsEmitter::computeIsNull(llvm::IRBuilder<> &Builder,
00248 llvm::Value *bounds, unsigned index)
00249 {
00250 llvm::Value *lower = getLowerBound(Builder, bounds, index);
00251 llvm::Value *upper = getUpperBound(Builder, bounds, index);
00252 return Builder.CreateICmpSLT(upper, lower);
00253 }
00254
00255 llvm::Value *BoundsEmitter::synthArrayBounds(llvm::IRBuilder<> &Builder,
00256 ArrayType *arrTy)
00257 {
00258 if (arrTy->isStaticallyConstrained())
00259 return synthStaticArrayBounds(Builder, arrTy);
00260
00261
00262 const llvm::StructType *boundsTy = getType(arrTy);
00263 llvm::Value *bounds = llvm::UndefValue::get(boundsTy);
00264
00265 for (unsigned i = 0; i < arrTy->getRank(); ++i) {
00266 DiscreteType *idxTy = arrTy->getIndexType(i);
00267 LUPair LU = getScalarBounds(Builder, idxTy);
00268
00269 bounds = Builder.CreateInsertValue(bounds, LU.first, 2*i);
00270 bounds = Builder.CreateInsertValue(bounds, LU.second, 2*i + 1);
00271 }
00272 return bounds;
00273 }
00274
00275 llvm::Constant *
00276 BoundsEmitter::synthStaticArrayBounds(llvm::IRBuilder<> &Builder,
00277 ArrayType *arrTy)
00278 {
00279 const llvm::StructType *boundsTy = getType(arrTy);
00280 std::vector<llvm::Constant*> bounds;
00281
00282 for (unsigned i = 0; i < arrTy->getRank(); ++i) {
00283 DiscreteType *idxTy = arrTy->getIndexType(i);
00284 Range *range = idxTy->getConstraint();
00285
00286 assert(idxTy->isStaticallyConstrained());
00287 const llvm::APInt &lower = range->getStaticLowerBound();
00288 const llvm::APInt &upper = range->getStaticUpperBound();
00289 const llvm::Type *eltTy = boundsTy->getElementType(i);
00290 bounds.push_back(llvm::ConstantInt::get(eltTy, lower));
00291 bounds.push_back(llvm::ConstantInt::get(eltTy, upper));
00292 }
00293 llvm::Constant *data = llvm::ConstantStruct::get(boundsTy, bounds);
00294 return data;
00295 }
00296
00297 llvm::Value *BoundsEmitter::synthAggregateBounds(llvm::IRBuilder<> &Builder,
00298 AggregateExpr *agg,
00299 llvm::Value *dst)
00300 {
00301 assert(agg->isPurelyPositional() &&
00302 "Cannot codegen bounds for this type of aggregate!");
00303
00304 llvm::Value *bounds = 0;
00305 ArrayType *arrTy = cast<ArrayType>(agg->getType());
00306
00307 if (arrTy->isStaticallyConstrained())
00308 bounds = synthStaticArrayBounds(Builder, arrTy);
00309 else {
00310
00311 llvm::APInt bound;
00312 std::vector<llvm::Constant*> boundValues;
00313 DiscreteType *idxTy = arrTy->getIndexType(0);
00314 llvm::LLVMContext &context = CG.getLLVMContext();
00315
00316 assert(!agg->hasOthers() &&
00317 "Cannot codegen bounds for dynamic aggregates with others!");
00318
00319
00320 if (Range *range = idxTy->getConstraint()) {
00321 assert(range->isStatic() && "Cannot codegen dynamic ranges.");
00322 bound = range->getStaticLowerBound();
00323 boundValues.push_back(llvm::ConstantInt::get(context, bound));
00324 }
00325 else {
00326 idxTy->getLowerLimit(bound);
00327 boundValues.push_back(llvm::ConstantInt::get(context, bound));
00328 }
00329
00330
00331
00332 llvm::APInt length(bound.getBitWidth(), agg->numPositionalComponents());
00333 bound += --length;
00334 boundValues.push_back(llvm::ConstantInt::get(context, bound));
00335
00336
00337
00338 const llvm::StructType *boundsTy = getType(arrTy);
00339 bounds = llvm::ConstantStruct::get(boundsTy, boundValues);
00340 }
00341
00342 if (dst)
00343 Builder.CreateStore(bounds, dst);
00344 return bounds;
00345 }