1 #ifndef PET_SCAN_H 2 #define PET_SCAN_H 3 4 #include <set> 5 #include <map> 6 7 #include <clang/Basic/SourceManager.h> 8 #include <clang/AST/Decl.h> 9 #include <clang/AST/Stmt.h> 10 #include <clang/Lex/Preprocessor.h> 11 12 #include <isl/ctx.h> 13 #include <isl/map.h> 14 #include <isl/val.h> 15 16 #include "context.h" 17 #include "inliner.h" 18 #include "isl_id_to_pet_expr.h" 19 #include "loc.h" 20 #include "scop.h" 21 #include "summary.h" 22 #include "tree.h" 23 24 #include "config.h" 25 26 namespace clang { 27 28 #ifndef HAVE_STMTRANGE 29 /* StmtRange was replaced by iterator_range in more recent versions of clang. 30 * Implement a StmtRange in terms of this iterator_range if StmtRange 31 * is not available. 32 */ 33 struct StmtRange : std::pair<StmtIterator,StmtIterator> { StmtRangeStmtRange34 StmtRange(const StmtIterator &begin, const StmtIterator &end) : 35 std::pair<StmtIterator,StmtIterator>(begin, end) {} StmtRangeStmtRange36 StmtRange(Stmt::child_range range) : 37 std::pair<StmtIterator,StmtIterator>(range.begin(), 38 range.end()) {} 39 }; 40 #endif 41 42 } 43 44 /* The location of the scop, as delimited by scop and endscop 45 * pragmas by the user. 46 * "scop" and "endscop" are the source locations of the scop and 47 * endscop pragmas. 48 * "start_line" is the line number of the start position. 49 */ 50 struct ScopLoc { ScopLocScopLoc51 ScopLoc() : end(0) {} 52 53 clang::SourceLocation scop; 54 clang::SourceLocation endscop; 55 unsigned start_line; 56 unsigned start; 57 unsigned end; 58 }; 59 60 /* The information extracted from a pragma pencil independent. 61 * We currently only keep track of the line number where 62 * the pragma appears. 63 */ 64 struct Independent { IndependentIndependent65 Independent(unsigned line) : line(line) {} 66 67 unsigned line; 68 }; 69 70 /* Compare two TypeDecl pointers based on their names. 71 */ 72 struct less_name { operatorless_name73 bool operator()(const clang::TypeDecl *x, 74 const clang::TypeDecl *y) { 75 return x->getNameAsString().compare(y->getNameAsString()) < 0; 76 } 77 }; 78 79 /* The PetTypes structure collects a set of RecordDecl and 80 * TypedefNameDecl pointers. 81 * The pointers are sorted using a fixed order. The actual order 82 * is not important, only that it is consistent across platforms. 83 */ 84 struct PetTypes { 85 std::set<clang::RecordDecl *, less_name> records; 86 std::set<clang::TypedefNameDecl *, less_name> typedefs; 87 insertPetTypes88 void insert(clang::RecordDecl *decl) { 89 records.insert(decl); 90 } insertPetTypes91 void insert(clang::TypedefNameDecl *decl) { 92 typedefs.insert(decl); 93 } 94 }; 95 96 struct PetScan { 97 clang::Preprocessor &PP; 98 clang::ASTContext &ast_context; 99 /* The DeclContext of the function containing the scop. 100 */ 101 clang::DeclContext *decl_context; 102 /* If autodetect is false, then loc contains the location 103 * of the scop to be extracted. 104 */ 105 ScopLoc &loc; 106 isl_ctx *ctx; 107 pet_options *options; 108 /* If not NULL, then return_root represents the compound statement 109 * in which a return statement is allowed as the final child. 110 * If return_root is NULL, then no return statements are allowed. 111 */ 112 clang::Stmt *return_root; 113 /* Set if the pet_scop returned by an extract method only 114 * represents part of the input tree. 115 */ 116 bool partial; 117 118 /* A cache of size expressions for array identifiers as computed 119 * by PetScan::get_array_size, or set by PetScan::set_array_size. 120 */ 121 isl_id_to_pet_expr *id_size; 122 /* A cache of size expressions for array types as computed 123 * by PetScan::get_array_size. 124 */ 125 std::map<const clang::Type *, pet_expr *> type_size; 126 127 /* A cache of funtion summaries for function declarations 128 * as extracted by PetScan::get_summary. 129 */ 130 std::map<clang::FunctionDecl *, pet_function_summary *> summary_cache; 131 132 /* A union of mappings of the form 133 * { identifier[] -> [i] : lower_bound <= i <= upper_bound } 134 */ 135 isl_union_map *value_bounds; 136 137 /* The line number of the previously considered Stmt. */ 138 unsigned last_line; 139 /* The line number of the Stmt currently being considered. */ 140 unsigned current_line; 141 /* Information about the independent pragmas in the source code. */ 142 std::vector<Independent> &independent; 143 144 /* All variables that have already been declared 145 * in the current compound statement. 146 */ 147 std::vector<clang::VarDecl *> declarations; 148 /* Sequence number of the next rename. */ 149 int n_rename; 150 /* Have the declared names been collected? */ 151 bool declared_names_collected; 152 /* The names of the variables declared in decl_context, 153 * if declared_names_collected is set. 154 */ 155 std::set<std::string> declared_names; 156 /* A set of names known to be in use. */ 157 std::set<std::string> used_names; 158 159 /* If not NULL, then "call2id" maps inlined call expressions 160 * that return a value to the corresponding variables. 161 */ 162 std::map<clang::Stmt *, isl_id *> *call2id; 163 164 /* Sequence number of the next temporary inlined argument variable. */ 165 int n_arg; 166 /* Sequence number of the next temporary inlined return variable. */ 167 int n_ret; 168 PetScanPetScan169 PetScan(clang::Preprocessor &PP, clang::ASTContext &ast_context, 170 clang::DeclContext *decl_context, ScopLoc &loc, 171 pet_options *options, __isl_take isl_union_map *value_bounds, 172 std::vector<Independent> &independent) : 173 PP(PP), 174 ast_context(ast_context), decl_context(decl_context), loc(loc), 175 ctx(isl_union_map_get_ctx(value_bounds)), 176 options(options), return_root(NULL), partial(false), 177 value_bounds(value_bounds), last_line(0), current_line(0), 178 independent(independent), n_rename(0), 179 declared_names_collected(false), call2id(NULL), 180 n_arg(0), n_ret(0) { 181 id_size = isl_id_to_pet_expr_alloc(ctx, 0); 182 } 183 184 ~PetScan(); 185 186 struct pet_scop *scan(clang::FunctionDecl *fd); 187 188 static __isl_give isl_val *extract_int(isl_ctx *ctx, 189 clang::IntegerLiteral *expr); 190 __isl_give pet_expr *get_array_size(__isl_keep isl_id *id); 191 void set_array_size(__isl_take isl_id *id, __isl_take pet_expr *size); 192 struct pet_array *extract_array(__isl_keep isl_id *id, 193 PetTypes *types, __isl_keep pet_context *pc); 194 __isl_give pet_tree *extract_inlined_call(clang::CallExpr *call, 195 clang::FunctionDecl *fd, __isl_keep isl_id *return_id); 196 private: 197 void set_current_stmt(clang::Stmt *stmt); 198 bool is_current_stmt_marked_independent(); 199 200 void collect_declared_names(); 201 void add_new_used_names(const std::set<std::string> &used_names); 202 bool name_in_use(const std::string &name, clang::Decl *decl); 203 std::string generate_new_name(const std::string &name); 204 205 __isl_give pet_tree *add_kills(__isl_take pet_tree *tree, 206 std::set<clang::ValueDecl *> locals); 207 208 struct pet_scop *scan(clang::Stmt *stmt); 209 210 struct pet_scop *scan_arrays(struct pet_scop *scop, 211 __isl_keep pet_context *pc); 212 struct pet_array *extract_array(clang::ValueDecl *decl, 213 PetTypes *types, __isl_keep pet_context *pc); 214 struct pet_array *extract_array(__isl_keep isl_id_list *decls, 215 PetTypes *types, __isl_keep pet_context *pc); 216 __isl_give pet_expr *set_upper_bounds(__isl_take pet_expr *expr, 217 clang::QualType qt, int pos); 218 struct pet_array *set_upper_bounds(struct pet_array *array, 219 __isl_keep pet_context *pc); 220 int substitute_array_sizes(__isl_keep pet_tree *tree, 221 pet_substituter *substituter); 222 223 __isl_give pet_tree *insert_initial_declarations( 224 __isl_take pet_tree *tree, int n_decl, 225 clang::StmtRange stmt_range); 226 __isl_give pet_tree *extract(clang::Stmt *stmt, 227 bool skip_declarations = false); 228 __isl_give pet_tree *extract(clang::StmtRange stmt_range, bool block, 229 bool skip_declarations, clang::Stmt *parent); 230 __isl_give pet_tree *extract(clang::IfStmt *stmt); 231 __isl_give pet_tree *extract(clang::WhileStmt *stmt); 232 __isl_give pet_tree *extract(clang::CompoundStmt *stmt, 233 bool skip_declarations = false); 234 __isl_give pet_tree *extract(clang::LabelStmt *stmt); 235 __isl_give pet_tree *extract(clang::Decl *decl); 236 __isl_give pet_tree *extract(clang::DeclStmt *expr); 237 __isl_give pet_tree *extract(clang::ReturnStmt *stmt); 238 239 __isl_give pet_loc *construct_pet_loc(clang::SourceRange range, 240 bool skip_semi); 241 __isl_give pet_tree *extract(__isl_take pet_expr *expr, 242 clang::SourceRange range, bool skip_semi); 243 __isl_give pet_tree *update_loc(__isl_take pet_tree *tree, 244 clang::Stmt *stmt); 245 246 struct pet_scop *extract_scop(__isl_take pet_tree *tree); 247 248 clang::BinaryOperator *initialization_assignment(clang::Stmt *init); 249 clang::Decl *initialization_declaration(clang::Stmt *init); 250 clang::ValueDecl *extract_induction_variable(clang::BinaryOperator *stmt); 251 clang::VarDecl *extract_induction_variable(clang::Stmt *init, 252 clang::Decl *stmt); 253 __isl_give pet_expr *extract_unary_increment(clang::UnaryOperator *op, 254 clang::ValueDecl *iv); 255 __isl_give pet_expr *extract_binary_increment( 256 clang::BinaryOperator *op, 257 clang::ValueDecl *iv); 258 __isl_give pet_expr *extract_compound_increment( 259 clang::CompoundAssignOperator *op, 260 clang::ValueDecl *iv); 261 __isl_give pet_expr *extract_increment(clang::ForStmt *stmt, 262 clang::ValueDecl *iv); 263 __isl_give pet_tree *extract_for(clang::ForStmt *stmt); 264 __isl_give pet_tree *extract_expr_stmt(clang::Stmt *stmt); 265 int set_inliner_arguments(pet_inliner &inliner, clang::CallExpr *call, 266 clang::FunctionDecl *fd); 267 268 __isl_give pet_expr *extract_assume(clang::Expr *expr); 269 __isl_give pet_function_summary *get_summary(clang::FunctionDecl *fd); 270 __isl_give pet_expr *set_summary(__isl_take pet_expr *expr, 271 clang::FunctionDecl *fd); 272 __isl_give pet_expr *extract_argument(clang::FunctionDecl *fd, int pos, 273 clang::Expr *expr, bool detect_writes); 274 __isl_give pet_expr *extract_expr(const llvm::APInt &val); 275 __isl_give pet_expr *extract_expr(clang::Expr *expr); 276 __isl_give pet_expr *extract_expr(clang::UnaryOperator *expr); 277 __isl_give pet_expr *extract_expr(clang::BinaryOperator *expr); 278 __isl_give pet_expr *extract_expr(clang::ImplicitCastExpr *expr); 279 __isl_give pet_expr *extract_expr(clang::IntegerLiteral *expr); 280 __isl_give pet_expr *extract_expr(clang::EnumConstantDecl *expr); 281 __isl_give pet_expr *extract_expr(clang::FloatingLiteral *expr); 282 __isl_give pet_expr *extract_expr(clang::ParenExpr *expr); 283 __isl_give pet_expr *extract_expr(clang::ConditionalOperator *expr); 284 __isl_give pet_expr *extract_expr(clang::CallExpr *expr); 285 __isl_give pet_expr *extract_expr(clang::CStyleCastExpr *expr); 286 287 __isl_give pet_expr *extract_access_expr(clang::Expr *expr); 288 __isl_give pet_expr *extract_access_expr(clang::ValueDecl *decl); 289 290 __isl_give pet_expr *extract_index_expr( 291 clang::ArraySubscriptExpr *expr); 292 __isl_give pet_expr *extract_index_expr(clang::Expr *expr); 293 __isl_give pet_expr *extract_index_expr(clang::ImplicitCastExpr *expr); 294 __isl_give pet_expr *extract_index_expr(clang::DeclRefExpr *expr); 295 __isl_give pet_expr *extract_index_expr(clang::ValueDecl *decl); 296 __isl_give pet_expr *extract_index_expr(clang::MemberExpr *expr); 297 298 __isl_give isl_val *extract_int(clang::Expr *expr); 299 __isl_give isl_val *extract_int(clang::ParenExpr *expr); 300 301 clang::FunctionDecl *find_decl_from_name(clang::CallExpr *call, 302 std::string name); 303 clang::FunctionDecl *get_summary_function(clang::CallExpr *call); 304 305 void report(clang::SourceRange range, unsigned id); 306 void report(clang::Stmt *stmt, unsigned id); 307 void report(clang::Decl *decl, unsigned id); 308 void unsupported(clang::Stmt *stmt); 309 void report_unsupported_unary_operator(clang::Stmt *stmt); 310 void report_unsupported_binary_operator(clang::Stmt *stmt); 311 void report_unsupported_statement_type(clang::Stmt *stmt); 312 void report_prototype_required(clang::Stmt *stmt); 313 void report_missing_increment(clang::Stmt *stmt); 314 void report_missing_summary_function(clang::Stmt *stmt); 315 void report_missing_summary_function_body(clang::Stmt *stmt); 316 void report_unsupported_inline_function_argument(clang::Stmt *stmt); 317 void report_unsupported_declaration(clang::Decl *decl); 318 void report_unbalanced_pragmas(clang::SourceLocation scop, 319 clang::SourceLocation endscop); 320 void report_unsupported_return(clang::Stmt *stmt); 321 void report_return_not_at_end_of_function(clang::Stmt *stmt); 322 }; 323 324 #endif 325