00001 //===-- codegen/DependencySet.cpp ----------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009-2010, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "CodeGenRoutine.h" 00010 #include "DependencySet.h" 00011 #include "comma/ast/AggExpr.h" 00012 #include "comma/ast/Decl.h" 00013 #include "comma/ast/DSTDefinition.h" 00014 #include "comma/ast/ExprVisitor.h" 00015 #include "comma/ast/RangeAttrib.h" 00016 #include "comma/ast/Stmt.h" 00017 #include "comma/ast/StmtVisitor.h" 00018 00019 #include <algorithm> 00020 00021 using namespace comma; 00022 00023 using llvm::dyn_cast; 00024 using llvm::dyn_cast_or_null; 00025 using llvm::cast; 00026 using llvm::isa; 00027 00028 namespace { 00029 00033 class DependencyScanner : private StmtVisitor, private ExprVisitor { 00034 00035 llvm::UniqueVector<const DomainInstanceDecl*> &dependents; 00036 00037 public: 00038 DependencyScanner(llvm::UniqueVector<const DomainInstanceDecl*> &dependents) 00039 : dependents(dependents) { } 00040 00041 void scan(Stmt *stmt) { visitStmt(stmt); } 00042 00043 private: 00045 00046 void visitStmtSequence(StmtSequence *node); 00047 void visitBlockStmt(BlockStmt *node); 00048 void visitProcedureCallStmt(ProcedureCallStmt *node); 00049 void visitReturnStmt(ReturnStmt *node); 00050 void visitAssignmentStmt(AssignmentStmt *node); 00051 void visitIfStmt(IfStmt *node); 00052 void visitWhileStmt(WhileStmt *node); 00053 void visitLoopStmt(LoopStmt *node); 00054 void visitRaiseStmt(RaiseStmt *node); 00055 void visitForStmt(ForStmt *node); 00057 00059 00060 void visitFunctionCallExpr(FunctionCallExpr *node); 00061 void visitInjExpr(InjExpr *node); 00062 void visitPrjExpr(PrjExpr *node); 00063 void visitAggregateExpr(AggregateExpr *node); 00064 void visitQualifiedExpr(QualifiedExpr *node); 00065 void visitDereferenceExpr(DereferenceExpr *node); 00066 void visitAllocatorExpr(AllocatorExpr *node); 00068 00069 void addDependents(const DomainInstanceDecl *instance); 00070 }; 00071 00072 } // end anonymous namespace. 00073 00074 00075 //===----------------------------------------------------------------------===// 00076 // DependecyScanner methods. 00077 00078 void DependencyScanner::addDependents(const DomainInstanceDecl *instance) 00079 { 00080 // If the given instance is parameterized, insert each argument as a 00081 // dependency, ignoring abstract domains and % (the formal parameters of a 00082 // functor, nor the domain itself, need recording). 00083 if (instance->isParameterized()) { 00084 typedef DomainInstanceDecl::arg_iterator iterator; 00085 iterator E = instance->endArguments(); 00086 for (iterator I = instance->beginArguments(); I != E; ++I) { 00087 DomainType *argTy = (*I)->getType(); 00088 if (!(argTy->isAbstract() || argTy->denotesPercent())) { 00089 DomainInstanceDecl *argInstance = argTy->getInstanceDecl(); 00090 assert(argInstance && "Bad domain type!"); 00091 dependents.insert(argInstance); 00092 } 00093 } 00094 } 00095 dependents.insert(instance); 00096 } 00097 00098 void DependencyScanner::visitStmtSequence(StmtSequence *node) 00099 { 00100 for (StmtSequence::stmt_iter I = node->stmt_begin(); 00101 I != node->stmt_end(); ++I) 00102 visitStmt(*I); 00103 00104 if (node->isHandled()) { 00105 for (StmtSequence::handler_iter I = node->handler_begin(); 00106 I != node->handler_end(); ++I) 00107 visitStmtSequence(*I); 00108 } 00109 } 00110 00111 void DependencyScanner::visitBlockStmt(BlockStmt *node) 00112 { 00113 // Scan the block statement for object declarations with initializers. 00114 typedef BlockStmt::DeclIter iterator; 00115 iterator E = node->endDecls(); 00116 for (iterator I = node->beginDecls(); I != E; ++I) { 00117 if (ObjectDecl *decl = dyn_cast<ObjectDecl>(*I)) { 00118 if (decl->hasInitializer()) 00119 visitExpr(decl->getInitializer()); 00120 } 00121 } 00122 00123 // Scan the associated sequence of statements. 00124 visitStmtSequence(node); 00125 } 00126 00127 void DependencyScanner::visitProcedureCallStmt(ProcedureCallStmt *node) 00128 { 00130 if (node->isDirectCall()) { 00131 ProcedureDecl *proc = node->getConnective(); 00132 DomainInstanceDecl *instance = 00133 cast<DomainInstanceDecl>(proc->getDeclRegion()); 00134 addDependents(instance); 00135 } 00136 00137 typedef ProcedureCallStmt::arg_iterator iterator; 00138 iterator I = node->begin_arguments(); 00139 iterator E = node->end_arguments(); 00140 for ( ; I != E; ++I) 00141 visitExpr(*I); 00142 } 00143 00144 void DependencyScanner::visitReturnStmt(ReturnStmt *node) 00145 { 00146 if (node->hasReturnExpr()) 00147 visitExpr(node->getReturnExpr()); 00148 } 00149 00150 void DependencyScanner::visitAssignmentStmt(AssignmentStmt *node) 00151 { 00152 // The target of an assignment is always local to the current capsule, so 00153 // there are never any dependents. Scan that rhs. 00154 visitExpr(node->getAssignedExpr()); 00155 } 00156 00157 void DependencyScanner::visitIfStmt(IfStmt *node) 00158 { 00159 visitExpr(node->getCondition()); 00160 visitStmtSequence(node->getConsequent()); 00161 00162 IfStmt::iterator E = node->endElsif(); 00163 for (IfStmt::iterator I = node->beginElsif(); I != E; ++I) { 00164 visitExpr(I->getCondition()); 00165 visitStmtSequence(I->getConsequent()); 00166 } 00167 00168 if (node->hasAlternate()) 00169 visitStmtSequence(node->getAlternate()); 00170 } 00171 00172 void DependencyScanner::visitWhileStmt(WhileStmt *node) 00173 { 00174 visitExpr(node->getCondition()); 00175 visitStmtSequence(node->getBody()); 00176 } 00177 00178 void DependencyScanner::visitLoopStmt(LoopStmt *node) 00179 { 00180 visitStmtSequence(node->getBody()); 00181 } 00182 00183 void DependencyScanner::visitRaiseStmt(RaiseStmt *node) 00184 { 00185 if (node->hasMessage()) 00186 visitExpr(node->getMessage()); 00187 00188 ExceptionDecl *exception; 00189 DeclRegion *region; 00190 DomainInstanceDecl *instance; 00191 exception = node->getExceptionDecl(); 00192 region = exception->getDeclRegion(); 00193 if (region && (instance = dyn_cast<DomainInstanceDecl>(region))) 00194 addDependents(instance); 00195 } 00196 00197 void DependencyScanner::visitForStmt(ForStmt *node) 00198 { 00199 DSTDefinition *control = node->getControl(); 00200 00201 if (control->definedUsingRange()) { 00202 Range *range = control->getRange(); 00203 visitExpr(range->getLowerBound()); 00204 visitExpr(range->getUpperBound()); 00205 } 00206 else if (control->definedUsingAttrib()) { 00207 RangeAttrib *attrib = control->getAttrib(); 00208 if (ArrayRangeAttrib *ARA = dyn_cast<ArrayRangeAttrib>(attrib)) 00209 visitExpr(ARA->getPrefix()); 00210 } 00211 else if (control->definedUsingConstraint()) { 00212 Range *range = control->getType()->getConstraint(); 00213 visitExpr(range->getLowerBound()); 00214 visitExpr(range->getUpperBound()); 00215 } 00216 00217 visitStmtSequence(node->getBody()); 00218 } 00219 00220 void DependencyScanner::visitFunctionCallExpr(FunctionCallExpr *node) 00221 { 00223 if (node->isDirectCall()) { 00224 FunctionDecl *fn = node->getConnective(0); 00225 DomainInstanceDecl *instance = 00226 cast<DomainInstanceDecl>(fn->getDeclRegion()); 00227 addDependents(instance); 00228 } 00229 00230 typedef FunctionCallExpr::arg_iterator iterator; 00231 iterator I = node->begin_arguments(); 00232 iterator E = node->end_arguments(); 00233 for ( ; I != E; ++I) 00234 visitExpr(*I); 00235 } 00236 00237 void DependencyScanner::visitInjExpr(InjExpr *node) 00238 { 00239 visitExpr(node->getOperand()); 00240 } 00241 00242 void DependencyScanner::visitPrjExpr(PrjExpr *node) 00243 { 00244 visitExpr(node->getOperand()); 00245 } 00246 00247 void DependencyScanner::visitAggregateExpr(AggregateExpr *node) 00248 { 00249 typedef AggregateExpr::pos_iterator pos_iterator; 00250 for (pos_iterator I = node->pos_begin(), E = node->pos_end(); I != E; ++I) 00251 visitExpr(*I); 00252 00253 typedef AggregateExpr::kl_iterator kl_iterator; 00254 for (kl_iterator I = node->kl_begin(), E = node->kl_end(); I != E; ++I) 00255 visitExpr((*I)->getExpr()); 00256 00257 if (Expr *others = node->getOthersExpr()) 00258 visitExpr(others); 00259 } 00260 00261 void DependencyScanner::visitQualifiedExpr(QualifiedExpr *node) 00262 { 00263 visitExpr(node->getOperand()); 00264 } 00265 00266 void DependencyScanner::visitDereferenceExpr(DereferenceExpr *node) 00267 { 00268 visitExpr(node->getPrefix()); 00269 } 00270 00271 void DependencyScanner::visitAllocatorExpr(AllocatorExpr *node) 00272 { 00273 if (node->isInitialized()) 00274 visitExpr(node->getInitializer()); 00275 } 00276 00277 //===----------------------------------------------------------------------===// 00278 // DependencySet methods. 00279 00280 void DependencySet::scan() 00281 { 00282 typedef DeclRegion::ConstDeclIter decl_iterator; 00283 00284 DependencyScanner DS(dependents); 00285 const AddDecl *add = capsule->getImplementation(); 00286 00287 // If there is no body, there is nothing to do. 00288 if (!add) 00289 return; 00290 00291 // Iterate over each subroutine declaration present in the capsules body an 00292 // analyze each in turn. 00293 decl_iterator E = add->endDecls(); 00294 for (decl_iterator I = add->beginDecls(); I != E; ++I) { 00295 if (SubroutineDecl *srDecl = dyn_cast<SubroutineDecl>(*I)) { 00296 if (srDecl->hasBody()) 00297 DS.scan(srDecl->getBody()); 00298 } 00299 } 00300 } 00301 00302 DependencySet::iterator 00303 DependencySet::find(const DomainInstanceDecl *instance) const 00304 { 00305 return std::find(begin(), end(), instance); 00306 }