From 9269dd067f15c2df9c0903c8aaa349dd5d41ed9d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Sat, 8 Jun 2013 16:06:24 +0200 Subject: [PATCH] add pet_transform_C_source The function currently only allows for the transformation of a single scop inside each function body. Signed-off-by: Sven Verdoolaege --- Makefile.am | 1 + include/pet.h | 8 +++++ pet.cc | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ print.c | 31 +++++++++++++++++++ print.h | 14 +++++++++ 5 files changed, 149 insertions(+) create mode 100644 print.h diff --git a/Makefile.am b/Makefile.am index 25bc342..b5e2534 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,6 +37,7 @@ libpet_la_SOURCES = \ options.h \ options.c \ print.c \ + print.h \ scan.h \ scan.cc \ scop.h \ diff --git a/include/pet.h b/include/pet.h index 0b7ae7d..1ae3a49 100644 --- a/include/pet.h +++ b/include/pet.h @@ -267,6 +267,14 @@ int pet_op_is_inc_dec(enum pet_op_type op); struct pet_scop *pet_scop_extract_from_C_source(isl_ctx *ctx, const char *filename, const char *function); +/* Transform the C source file "input" by rewriting each scop + * (at most one per function) through a call to "transform". + * The transformed C code is written to "output". + */ +int pet_transform_C_source(isl_ctx *ctx, const char *input, FILE *output, + __isl_give isl_printer *(*transform)(__isl_take isl_printer *p, + struct pet_scop *scop, void *user), void *user); + /* Update all isl_sets and isl_maps such that they all have the same * parameters in the same order. */ diff --git a/pet.cc b/pet.cc index d150005..6925804 100644 --- a/pet.cc +++ b/pet.cc @@ -82,8 +82,11 @@ #include #include +#include + #include "options.h" #include "scan.h" +#include "print.h" #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array)) @@ -892,3 +895,95 @@ struct pet_scop *pet_scop_extract_from_C_source(isl_ctx *ctx, return scop; } + +/* Internal data structure for pet_transform_C_source + * + * transform is the function that should be called to print a scop + * in is the input source file + * out is the output source file + * end is the offset of the end of the previous scop (zero if we have not + * found any scop yet) + * p is a printer that prints to out. + */ +struct pet_transform_data { + __isl_give isl_printer *(*transform)(__isl_take isl_printer *p, + struct pet_scop *scop, void *user); + void *user; + + FILE *in; + FILE *out; + unsigned end; + isl_printer *p; +}; + +/* This function is called each time a scop is detected. + * + * We first copy the input text code from the end of the previous scop + * until the start of "scop" and then print the scop itself through + * a call to data->transform. + * Finally, we keep track of the end of "scop" so that we can + * continue copying when we find the next scop. + */ +static int pet_transform(struct pet_scop *scop, void *user) +{ + struct pet_transform_data *data = (struct pet_transform_data *) user; + + if (copy(data->in, data->out, data->end, scop->start) < 0) + goto error; + data->end = scop->end; + data->p = data->transform(data->p, scop, data->user); + if (!data->p) + return -1; + return 0; +error: + pet_scop_free(scop); + return -1; +} + +/* Transform the C source file "input" by rewriting each scop + * (at most one per function) through a call to "transform". + * The transformed C code is written to "output". + * + * For each scop we find, we first copy the input text code + * from the end of the previous scop (or the beginning of the file + * in case of the first scop) until the start of the scop + * and then print the scop itself through a call to "transform". + * At the end we copy everything from the end of the final scop + * until the end of the input file to "output". + */ +int pet_transform_C_source(isl_ctx *ctx, const char *input, FILE *out, + __isl_give isl_printer *(*transform)(__isl_take isl_printer *p, + struct pet_scop *scop, void *user), void *user) +{ + struct pet_transform_data data; + int r; + + data.in = stdin; + data.out = out; + if (input && strcmp(input, "-")) { + data.in = fopen(input, "r"); + if (!data.in) + isl_die(ctx, isl_error_unknown, "unable to open file", + return -1); + } + + data.p = isl_printer_to_file(ctx, data.out); + data.p = isl_printer_set_output_format(data.p, ISL_FORMAT_C); + + data.transform = transform; + data.user = user; + data.end = 0; + r = pet_foreach_scop_in_C_source(ctx, input, NULL, + &pet_transform, &data); + + isl_printer_free(data.p); + if (!data.p) + r = -1; + if (r == 0 && copy(data.in, data.out, data.end, -1) < 0) + r = -1; + + if (data.in != stdin) + fclose(data.in); + + return r; +} diff --git a/print.c b/print.c index 3940194..4a9ab27 100644 --- a/print.c +++ b/print.c @@ -36,6 +36,7 @@ #include #include #include +#include "print.h" #include "scop.h" /* Internal data structure for pet_stmt_build_ast_exprs. @@ -388,3 +389,33 @@ __isl_give isl_printer *pet_stmt_print_body(struct pet_stmt *stmt, return p; } + +/* Copy the contents of "input" from offset "start" to "end" to "output". + */ +int copy(FILE *input, FILE *output, long start, long end) +{ + char buffer[1024]; + size_t n, m; + + if (end < 0) { + fseek(input, 0, SEEK_END); + end = ftell(input); + } + + fseek(input, start, SEEK_SET); + + while (start < end) { + n = end - start; + if (n > 1024) + n = 1024; + n = fread(buffer, 1, n, input); + if (n <= 0) + return -1; + m = fwrite(buffer, 1, n, output); + if (n != m) + return -1; + start += n; + } + + return 0; +} diff --git a/print.h b/print.h new file mode 100644 index 0000000..d4ee304 --- /dev/null +++ b/print.h @@ -0,0 +1,14 @@ +#ifndef PET_PRINT_H +#define PET_PRINT_H + +#if defined(__cplusplus) +extern "C" { +#endif + +int copy(FILE *input, FILE *output, long start, long end); + +#if defined(__cplusplus) +} +#endif + +#endif -- 2.11.4.GIT