PIPS
sesam_tasks_processing.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sesam_tasks_processing.c 23495 2018-10-24 09:19:47Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "genC.h"
32 
33 #include "linear.h"
34 #include "ri.h"
35 #include "effects.h"
36 #include "database.h"
37 
38 #include "misc.h"
39 #include "ri-util.h"
40 #include "effects-util.h"
41 #include "constants.h"
42 #include "misc.h"
43 #include "text-util.h"
44 #include "text.h"
45 #include "control.h"
46 
47 #include "properties.h"
48 
49 #include "pipsdbm.h"
50 #include "resources.h"
51 
52 #include "effects-generic.h"
53 #include "effects-simple.h"
54 
55 #include "scalopes_private.h"
56 
57 /**
58  @brief returns true if the input label entity name is
59  prefixed by SCALOPES_KERNEL_TASK_PREFIX
60  */
61 static bool sesam_task_label_p(entity e)
62 {
63  const char * prefix = get_string_property ("SCALOPES_KERNEL_TASK_PREFIX");
64  const char * e_name = entity_user_name(e);
65  char * found_s = strstr(e_name, prefix);
66  return found_s != NULL;
67 }
68 
69 /**
70  @brief initalizes the object describing how the targeted sesam application uses buffers
71  all sets and hash tables are emtpy at the beginning.
72  */
74 {
75  *sbp_context =
81 }
82 
83 /**
84  @brief retrieves the original entity from an entity generated by isolate_statement
85  */
87 {
88  const char* prefix = get_string_property ("ISOLATE_STATEMENT_VAR_PREFIX");
89  size_t prefix_size = strlen(prefix);
90  const char* suffix = get_string_property ("ISOLATE_STATEMENT_VAR_SUFFIX");
91 
92 
93  const char * buffer_name = entity_user_name(buffer);
94 
95  pips_debug(5, "looking for %s server variable name\n", buffer_name);
96 
97  ifdebug(5){
98  pips_assert("the input entity is a sesam_buffer var",
99  strstr(buffer_name, prefix)!=NULL);
100  }
101 
102  const char * name_without_prefix = &buffer_name[prefix_size];
103  pips_debug(5, "name_without_prefix is %s\n", name_without_prefix);
104  size_t s_without_prefix = strlen(name_without_prefix);
105 
106  string found_suffix = strstr(name_without_prefix, suffix);
107  pips_debug(5, "found_suffix is %s\n", found_suffix);
108 
109  size_t s_name_end = strlen(found_suffix);
110 
111  size_t size_var_name = s_without_prefix - s_name_end;
112  pips_debug(5, "s_without_prefix = %zd\n", s_without_prefix);
113  pips_debug(5, "s_name_end = %zd\n", s_name_end);
114  pips_debug(5, "size_var_name = %zd\n", size_var_name);
115 
116  char *res_name = strndup(name_without_prefix, size_var_name);
117 
118  pips_debug(5, "found server variable name: %s\n", res_name);
119  entity res = FindEntityFromUserName(get_current_module_name(), res_name); /* try to find it in the current module*/
120  if (entity_undefined_p(res))
121  res = FindEntity(TOP_LEVEL_MODULE_NAME, res_name); /* try to find a global variable */
122  free(res_name);
123  pips_assert("Original entity found in current module or in global variables", !entity_undefined_p(res));
124  return res;
125 }
126 
127 /**
128  @brief returns true if the entity name is prefixed by ISOLATE_STATEMENT_VAR_PREFIX.
129  */
131 {
132  const char* prefix = get_string_property("ISOLATE_STATEMENT_VAR_PREFIX");
133  pips_debug(8, "prefix = %s \n", prefix);
134 
135  const char * e_name = entity_user_name(e);
136  pips_debug(5, "checking entity %s\n", e_name);
137 
138  char * found_s = strstr(e_name, prefix);
139 
140  return (found_s != NULL);
141 }
142 
143 /**
144  @brief updates sbp_context knowing that buffer will be a buffer
145  (input if in_p is true, output otherwise) of kernel task k_task
146 
147  @param sbp_context is the object describing how the targeted sesam application uses buffers
148  @param k_task is the kernel task label, used here as an identifier
149  @param buffer is the pointer to the buffer, used here as an identifier
150  @param in_p is a bool true if the buffer is an input buffer of the task
151 
152  This function:
153  - adds the buffer to sbp_context set of buffers
154  - adds the original variable server task to sbp_context set of server tasks
155  - adds the task to sbp_context set of kernel tasks
156  - adds the buffer to the input (resp. ouput) set of buffers of kernel task k_task.
157  - adds the buffer to the output (resp. input) set of buffers of the server task.
158 
159  This is an unoptimized version: servers are systematically used for original variables.
160 
161  */
163  entity k_task,
164  entity buffer,
165  bool in_p)
166 {
167  /* first add the buffer to the set of buffers */
171  buffer);
172 
173  /* Then add it in the task input (resp. ouput) buffers
174  if in_p is true (resp. false) */
175  /* if the task has not yet been encountered,
176  then add an entry in the kernel task set and buffers first */
180  k_task);
182  if (!bound_entity_task_buffers_p(k_buf, k_task))
183  extend_entity_task_buffers(k_buf, k_task,
186 
187  task_buffers t_buf = apply_entity_task_buffers(k_buf, k_task);
188 
189  if (in_p)
191  task_buffers_input(t_buf),
192  buffer);
193  else
195  task_buffers_output(t_buf),
196  buffer);
197 
198  /* Finally, retrieve the original variable corresponding to the buffer
199  and add it in the server task ouput (resp. input) buffers
200  if in_p is true (resp. false).*/
201  /* if the server task has not yet been encountered,
202  then add an entry in the server task sets and buffers first */
203 
208  s_task);
209  entity_task_buffers s_buf
211 
212  if (!bound_entity_task_buffers_p(s_buf, s_task))
213  extend_entity_task_buffers(s_buf, s_task,
216 
217  t_buf = apply_entity_task_buffers(s_buf, s_task);
218 
219  if (!in_p)
221  task_buffers_input(t_buf),
222  buffer);
223  else
225  task_buffers_output(t_buf),
226  buffer);
227 }
228 
229 /**
230  @brief update the object describing how the targeted sesam application uses buffers
231  with the current statement characteristics
232  */
234  sesam_buffers_processing_context * sbp_context)
235 {
236  bool res = true; // by default, stmt is not a sesam task
237  entity stmt_label = statement_label(stmt);
238 
239  if (sesam_task_label_p(stmt_label)) // stmt is a sesam task statement
240  {
241  pips_debug(1, "considering task with label %s\n", entity_user_name(stmt_label));
242 
244 
245  FOREACH(EFFECT, eff, l_eff)
246  {
248  entity e = effect_entity(eff);
249  pips_debug(5, "considering entity %s\n", entity_name(e));
250  pips_debug_effect(5, "and effect:", eff);
251 
252  /* isolate_statement generates pointers to the actual buffers.
253  do not consider effects on them, but only on the buffers
254  themselves */
256  {
257  pips_debug(5, "adding entity to buffers\n");
259  stmt_label,
260  e,
261  effect_read_p(eff));
262  }
263  }
264  res = false; // do not go further, nested tasks are not yet allowed
265  }
266  return(res);
267 }
268 
269 /**
270  @brief prettyprints in input file how each task uses the buffers
271 
272  @param fp is the File pointer
273  @param tasks_to_buffers is the hash table giving the input and output buffers of each task
274  @param l_buffers is an ordered list of buffers
275  @param task_prefix is a string appended before the task names
276 
277  Then for each task: (sorted before)
278  print #ifdef "task_prefix""task_name"
279  for each buffer in l_buffers
280  if buffer belongs to task input buffers
281  print #define buffer_cons_p 1
282  else
283  print #define buffer_cons_p 0
284  if buffer belongs to task output buffers
285  print #define buffer_prod_p 1
286  else
287  print #define buffer_prod_p 0
288  print #endif
289  */
290 static void print_entity_task_buffers(FILE *fp, set tasks,
291  entity_task_buffers tasks_to_buffers,
292  list l_buffers,
293  const char * task_prefix)
294 {
296 
297  FOREACH(ENTITY, task, l_tasks)
298  {
299  const char * task_name = entity_user_name(task);
300  fprintf(fp, "\n%s%s%s\n", "#ifdef ", task_prefix, task_name);
301  fprintf(fp, "#define %s%s_p 1\n", task_prefix, task_name);
302  task_buffers bufs = apply_entity_task_buffers(tasks_to_buffers, task);
303  set input_bufs = task_buffers_input(bufs);
304  set output_bufs = task_buffers_output(bufs);
305 
306  FOREACH(ENTITY, buf, l_buffers)
307  {
308  if (set_belong_p(input_bufs, buf))
309  fprintf(fp, "%s %s%s\n", "#define", entity_user_name(buf), "_cons_p 1");
310  else
311  fprintf(fp, "%s %s%s\n", "#define", entity_user_name(buf), "_cons_p 0");
312  if (set_belong_p(output_bufs, buf))
313  fprintf(fp, "%s %s%s\n", "#define", entity_user_name(buf), "_prod_p 1");
314  else
315  fprintf(fp, "%s %s%s\n", "#define", entity_user_name(buf), "_prod_p 0");
316 
317  }
318  fprintf(fp, "#else\n");
319  fprintf(fp, "#define %s%s_p 0\n", task_prefix, task_name);
320  fprintf(fp, "%s\n", "#endif");
321  }
322  gen_free_list(l_tasks);
323 }
324 
325 /**
326  @brief prints a header file describing how the targeted sesam application uses buffers
327  @param module_name is the current module name
328  @param sbp_context is the object describing how the targeted sesam application uses buffers
329  */
332 {
333  string buffers_header_name = NULL;
334  string local_buffers_header_name = NULL;
335  FILE *fp;
336  local_buffers_header_name =
337  db_build_file_resource_name(DBR_SESAM_BUFFERS_FILE,
338  module_name, "_buffers.h");
339  buffers_header_name =
341  "/", local_buffers_header_name, NULL));
342  fp = safe_fopen(buffers_header_name, "w");
343 
344 
345  /* first sort buffers list so that buffers are always
346  printed in the same order */
347  set buffers = sesam_buffers_processing_context_buffers(sbp_context);
348  list l_buffers = set_to_sorted_list(buffers,
350 
351  fprintf(fp, "%s%d\n", "#define NB_BUFFERS ",
352  (int) gen_length(l_buffers));
353  /* Then generate buffer identifiers values: */
354  /* for each buffer in buffer list
355  print #define buffer value
356  value ++
357  */
358  int buf_id = 0;
359  FOREACH(ENTITY, buf, l_buffers)
360  {
361  fprintf(fp, "%s%s%s%s\n","#define ", entity_user_name(buf),
362  "_id ", int2a(buf_id));
363  buf_id++;
364  }
365 
366  /* Then for each kernel task: (sorted before)
367  print #ifdef task_name
368  for each buffer in buffer list
369  if buffer belongs to task input buffers
370  print #define buffer_cons_p 1
371  else
372  print #define buffer_cons_p 0
373  if buffer belongs to task output buffers
374  print #define buffer_prod_p 1
375  else
376  print #define buffer_prod_p 0
377  print #endif
378  */
379  set kernel_tasks = sesam_buffers_processing_context_kernel_tasks(sbp_context);
380  entity_task_buffers kernel_buffers
382  print_entity_task_buffers(fp, kernel_tasks, kernel_buffers, l_buffers, "");
383 
384  /* Then do the same for server tasks */
385  set server_tasks = sesam_buffers_processing_context_server_tasks(sbp_context);
386  entity_task_buffers server_buffers
388  print_entity_task_buffers(fp, server_tasks, server_buffers, l_buffers,
389  get_string_property ("SCALOPES_SERVER_TASK_PREFIX"));
390 
391  safe_fclose(fp, buffers_header_name);
392  free(buffers_header_name);
393  gen_free_list(l_buffers);
394 
395  char * server_file_name =
397  "/", module_name, "/", module_name, ".servers", NULL));
398  fp = safe_fopen(server_file_name, "w");
399 
400  list l_server_tasks = set_to_sorted_list(server_tasks, (gen_cmp_func_t) compare_entities);
401  const char* prefix = get_string_property ("SCALOPES_SERVER_TASK_PREFIX");
402  FOREACH(ENTITY, server_task, l_server_tasks)
403  {
404  fprintf(fp, "%s%s\n", prefix, entity_user_name(server_task));
405  }
406  gen_free_list(l_server_tasks);
407  safe_fclose(fp, server_file_name);
408  free(server_file_name);
409 
410  DB_PUT_FILE_RESOURCE(DBR_SESAM_BUFFERS_FILE, strdup(module_name),
411  local_buffers_header_name);
412 }
413 
414 /**
415  @brief PIPS phase that takes a module transformed by isolated statements
416  and produces a header file describing buffer usage for targeted sesam application.
417 
418  @param module_name is the current module name
419  */
421 {
422  // Use this module name and this environment variable to set
424  "SCALOPES_DEBUG_LEVEL");
427 
428  sbp_context_init(&sbp_context);
429 
430  // use cumulated effects for the moment, regions can be used later if need be
432  db_get_memory_resource(DBR_CUMULATED_EFFECTS, module_name, true));
433 
439 
441 
443  // Put back the new statement module
445 
446  return (true);
447 }
448 
450 {
451  // Use this module name and this environment variable to set
453  "SCALOPES_DEBUG_LEVEL");
454 
455  // Put back the new statement module
457 
458  return (true);
459 }
void extend_entity_task_buffers(entity_task_buffers f, entity k, task_buffers v)
bool bound_entity_task_buffers_p(entity_task_buffers f, entity k)
sesam_buffers_processing_context make_sesam_buffers_processing_context(set a1, set a2, entity_task_buffers a3, entity_task_buffers a4, set a5)
task_buffers make_task_buffers(set a1, set a2)
entity_task_buffers make_entity_task_buffers(void)
task_buffers apply_entity_task_buffers(entity_task_buffers f, entity k)
void free_sesam_buffers_processing_context(sesam_buffers_processing_context p)
static statement module_statement
Definition: alias_check.c:125
#define pips_debug_effect(level, message, eff)
for debug
void set_cumulated_rw_effects(statement_effects)
list load_cumulated_rw_effects_list(statement)
void reset_cumulated_rw_effects(void)
void reset_methods_for_effects_prettyprint(const char *)
void set_methods_for_rw_effects_prettyprint(const char *)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
entity effect_entity(effect)
cproto-generated files
Definition: effects.c:52
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
char * get_string_property(const char *)
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
void free(void *)
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
size_t gen_length(const list l)
Definition: list.c:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define PIPS_PHASE_POSTLUDE(new_module_statement)
End a transformation phase by putting back into PIPS the (possibly) modified statement.
#define PIPS_PHASE_PRELUDE(module_name, debug_env_var)
Start a phase that use a module CODE.
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_FILE_RESOURCE
Put a file resource into the current workspace database.
Definition: pipsdbm-local.h:85
string db_build_file_resource_name(const char *rname, const char *oname, const char *suffix)
returns an allocated file name for a file resource.
Definition: lowlevel.c:169
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
static const char * prefix
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
int compare_entities(const entity *pe1, const entity *pe2)
Comparison function for qsort.
Definition: entity.c:1328
entity FindEntityFromUserName(const char *package, const char *name)
Definition: entity.c:1520
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define statement_label(x)
Definition: ri.h:2450
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_name(x)
Definition: ri.h:2790
#define reference_indices(x)
Definition: ri.h:2328
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define sesam_buffers_processing_context_undefined
#define sesam_buffers_processing_context_buffers(x)
#define sesam_buffers_processing_context_server_buffers(x)
#define sesam_buffers_processing_context_kernel_buffers(x)
#define sesam_buffers_processing_context_server_tasks(x)
#define task_buffers_output(x)
#define task_buffers_input(x)
#define sesam_buffers_processing_context_kernel_tasks(x)
static bool sesam_task_label_p(entity e)
returns true if the input label entity name is prefixed by SCALOPES_KERNEL_TASK_PREFIX
static void print_sesam_tasks_buffers_header(const char *module_name, sesam_buffers_processing_context sbp_context)
prints a header file describing how the targeted sesam application uses buffers
static bool entity_sesam_buffer_p(entity e)
returns true if the entity name is prefixed by ISOLATE_STATEMENT_VAR_PREFIX.
static entity sesam_buffer_to_server_entity(entity buffer)
retrieves the original entity from an entity generated by isolate_statement
static void sbp_context_init(sesam_buffers_processing_context *sbp_context)
initalizes the object describing how the targeted sesam application uses buffers all sets and hash ta...
bool sesam_buffers_processing(const char *module_name)
PIPS phase that takes a module transformed by isolated statements and produces a header file describi...
static void print_entity_task_buffers(FILE *fp, set tasks, entity_task_buffers tasks_to_buffers, list l_buffers, const char *task_prefix)
prettyprints in input file how each task uses the buffers
static bool update_sesam_tasks_buffers(statement stmt, sesam_buffers_processing_context *sbp_context)
update the object describing how the targeted sesam application uses buffers with the current stateme...
bool sesam_servers_processing(const char *module_name)
static void sbp_context_add_kernel_task_buffer(sesam_buffers_processing_context *sbp_context, entity k_task, entity buffer, bool in_p)
updates sbp_context knowing that buffer will be a buffer (input if in_p is true, output otherwise) of...
#define ifdebug(n)
Definition: sg.c:47
static char buf[BSZ]
Definition: split_file.c:157
static string buffer
Definition: string.c:113
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
char * int2a(int)
util.c
Definition: util.c:42