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