xml_AST.cc: directly include required headers
[ppn.git] / pdg2c.cc
blobb2dbcee59396cec68b8dfba81ae9b1197fc4dd02
1 /* Convert a PDG extracted using c2pdg and possibly transformed back to C code.
2 */
3 #include <stdio.h>
4 #include <stdlib.h>
6 #include <isl/ctx.h>
7 #include <isl/aff.h>
8 #include <isl/ast_build.h>
9 #include <pet.h>
11 #include <isa/pdg.h>
12 #include "pdg2c_options.h"
14 using pdg::PDG;
16 /* Find the element in scop->stmts that has the given "name".
18 static struct pet_stmt *find_stmt(struct pet_scop *scop, const char *name)
20 int i;
22 for (i = 0; i < scop->n_stmt; ++i) {
23 struct pet_stmt *stmt = scop->stmts[i];
24 const char *name_i;
26 name_i = isl_set_get_tuple_name(stmt->domain);
27 if (!strcmp(name, name_i))
28 return stmt;
31 return NULL;
34 extern "C" {
35 static __isl_give void free_isl_id_to_ast_expr(void *user);
36 static __isl_give isl_multi_pw_aff *pullback_index(
37 __isl_take isl_multi_pw_aff *mpa, __isl_keep isl_id *id, void *user);
38 static __isl_give isl_ast_node *at_each_domain(__isl_take isl_ast_node *node,
39 __isl_keep isl_ast_build *build, void *user);
40 static __isl_give isl_printer *transform(__isl_take isl_printer *p,
41 struct pet_scop *scop, void *user);
42 static __isl_give isl_printer *print_user(__isl_take isl_printer *p,
43 __isl_take isl_ast_print_options *print_options,
44 __isl_keep isl_ast_node *node, void *user);
47 static __isl_give void free_isl_id_to_ast_expr(void *user)
49 isl_id_to_ast_expr_free((isl_id_to_ast_expr *) user);
52 /* Find the element in scop->stmts that the same name
53 * as the function call by the given user node.
54 * These names are determined by the names of the domains
55 * of the schedule constructed in transform().
57 static pet_stmt *extract_pet_stmt(__isl_keep isl_ast_node *node,
58 struct pet_scop *scop)
60 isl_ast_expr *expr, *arg;
61 isl_id *id;
62 pet_stmt *stmt;
64 expr = isl_ast_node_user_get_expr(node);
65 arg = isl_ast_expr_get_op_arg(expr, 0);
66 isl_ast_expr_free(expr);
67 id = isl_ast_expr_get_id(arg);
68 isl_ast_expr_free(arg);
69 stmt = find_stmt(scop, isl_id_get_name(id));
70 isl_id_free(id);
72 return stmt;
75 /* Index transformation callback for pet_stmt_build_ast_exprs.
77 * "index" expresses the array indices in terms of statement iterators
78 * "iterator_map" expresses the statement iterators in terms of
79 * AST loop iterators.
81 * The result expresses the array indices in terms of
82 * AST loop iterators.
84 static __isl_give isl_multi_pw_aff *pullback_index(
85 __isl_take isl_multi_pw_aff *index, __isl_keep isl_id *id, void *user)
87 isl_pw_multi_aff *iterator_map = (isl_pw_multi_aff *) user;
89 iterator_map = isl_pw_multi_aff_copy(iterator_map);
90 return isl_multi_pw_aff_pullback_pw_multi_aff(index, iterator_map);
93 /* Transform the accesses in the statement associated to the domain
94 * called by "node" to refer to the AST loop iterators, construct
95 * corresponding AST expressions using "build" and attach them
96 * to the node.
98 static __isl_give isl_ast_node *at_each_domain(__isl_take isl_ast_node *node,
99 __isl_keep isl_ast_build *build, void *user)
101 const char *name;
102 pet_stmt *stmt;
103 isl_ctx *ctx;
104 isl_id *id;
105 isl_map *map;
106 isl_pw_multi_aff *iterator_map;
107 isl_id_to_ast_expr *ref2expr;
108 struct pet_scop *scop = (struct pet_scop *) user;
110 ctx = isl_ast_node_get_ctx(node);
112 stmt = extract_pet_stmt(node, scop);
113 if (!stmt)
114 isl_die(ctx, isl_error_internal, "cannot find statement",
115 isl_ast_node_free(node); node = NULL);
117 map = isl_map_from_union_map(isl_ast_build_get_schedule(build));
118 map = isl_map_reverse(map);
119 iterator_map = isl_pw_multi_aff_from_map(map);
120 ref2expr = pet_stmt_build_ast_exprs(stmt, build,
121 &pullback_index, iterator_map, NULL, NULL);
122 isl_pw_multi_aff_free(iterator_map);
124 id = isl_id_alloc(ctx, NULL, ref2expr);
125 id = isl_id_set_free_user(id, &free_isl_id_to_ast_expr);
127 return isl_ast_node_set_annotation(node, id);
130 /* Print the statement corresponding to "node" to "p".
131 * We look for the statement in the pet_scop passed through "user".
132 * The AST expressions for all references in the statement
133 * have been attached to the node by at_each_domain().
135 static __isl_give isl_printer *print_user(__isl_take isl_printer *p,
136 __isl_take isl_ast_print_options *print_options,
137 __isl_keep isl_ast_node *node, void *user)
139 isl_id_to_ast_expr *ref2expr;
140 isl_id *id;
141 struct pet_stmt *stmt;
142 struct pet_scop *scop = (struct pet_scop *) user;
144 stmt = extract_pet_stmt(node, scop);
146 id = isl_ast_node_get_annotation(node);
147 ref2expr = (isl_id_to_ast_expr *) isl_id_get_user(id);
148 isl_id_free(id);
150 p = pet_stmt_print_body(stmt, p, ref2expr);
152 isl_ast_print_options_free(print_options);
154 return p;
157 /* Transform "scop" based on the schedule stored in "pdg" and
158 * print the result to "p".
160 static __isl_give isl_printer *transform(__isl_take isl_printer *p,
161 struct pet_scop *scop, void *user)
163 PDG *pdg = (PDG *) user;
164 isl_ctx *ctx;
165 isl_ast_build *build;
166 isl_ast_node *tree;
167 isl_ast_print_options *print_options;
168 isl_union_map *sched;
170 ctx = isl_printer_get_ctx(p);
171 build = isl_ast_build_from_context(pdg->get_context_isl_set());
172 build = isl_ast_build_set_at_each_domain(build, &at_each_domain, scop);
173 sched = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
175 for (int i = 0; i < pdg->nodes.size(); ++i) {
176 const char *name;
177 isl_id *id;
178 isl_set *source;
179 isl_map *map;
181 if (!pdg->nodes[i]->schedule)
182 isl_die(ctx, isl_error_internal, "Missing schedule",
183 isl_union_map_free(sched); sched = NULL);
184 if (!pdg->nodes[i]->name)
185 isl_die(ctx, isl_error_internal, "Missing node name",
186 isl_union_map_free(sched); sched = NULL);
187 if (!sched)
188 break;
190 name = pdg->nodes[i]->name->s.c_str();
192 source = pdg->nodes[i]->source->get_isl_set(ctx);
194 map = pdg->nodes[i]->schedule->get_isl_map(ctx);
195 map = isl_map_intersect_domain(map, source);
196 id = isl_id_alloc(ctx, name, NULL);
197 map = isl_map_set_tuple_id(map, isl_dim_in, id);
199 sched = isl_union_map_add_map(sched, map);
202 tree = isl_ast_build_ast_from_schedule(build, sched);
203 isl_ast_build_free(build);
205 p = isl_ast_node_print_macros(tree, p);
207 print_options = isl_ast_print_options_alloc(ctx);
208 print_options = isl_ast_print_options_set_print_user(print_options,
209 &print_user, scop);
210 p = isl_ast_node_print(tree, p, print_options);
212 isl_ast_node_free(tree);
214 pet_scop_free(scop);
215 return p;
218 /* Given a C source code file and a PDG that is assumed to correspond
219 * to the first and only scop in this source code, print out the transformed
220 * C code based on the schedule of the PDG.
221 * The original PDG is assumed to have been extracted using c2pdg from
222 * the same source file.
224 int main(int argc, char **argv)
226 isl_ctx *ctx;
227 PDG *pdg;
228 FILE *input = stdin;
229 FILE *output = stdout;
230 struct options *options = options_new_with_defaults();
232 ctx = isl_ctx_alloc_with_options(&options_args, options);
233 if (!ctx) {
234 fprintf(stderr, "Unable to allocate ctx\n");
235 return EXIT_FAILURE;
238 pet_options_set_autodetect(ctx, 1);
239 argc = options_parse(options, argc, argv, ISL_ARG_ALL);
241 if (options->input_pdg && strcmp(options->input_pdg, "-")) {
242 input = fopen(options->input_pdg, "r");
243 assert(input);
245 if (options->output && strcmp(options->output, "-")) {
246 output = fopen(options->output, "w");
247 assert(output);
249 pdg = PDG::Load(input, ctx);
250 assert(pdg);
252 if (pet_transform_C_source(ctx, options->input_C, output,
253 &transform, pdg) < 0)
254 return EXIT_FAILURE;
256 pdg->free();
257 delete pdg;
259 if (output != stdout)
260 fclose(output);
262 isl_ctx_free(ctx);
263 return EXIT_SUCCESS;