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 }