PIPS
module.c
Go to the documentation of this file.
1 /*
2 
3  $Id: module.c 22599 2015-07-13 07:12:41Z irigoin $
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 // strndup are GNU extensions...
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include "genC.h"
33 #include "text.h"
34 #include "constants.h"
35 
36 #include "text-util.h"
37 #include "misc.h"
38 #include "linear.h"
39 #include "ri.h"
40 #include "ri-util.h"
41 #include "pipsdbm.h"
42 #include "workspace-util.h"
43 
44 /* High-level functions about modules, using pipsdbm and ri-util and
45  some global variables assumed properly set
46  */
47 
48 /* Retrieve all declarations linked to a module, but the local
49  variables private to loops. Allocate and build a new list which
50  will have to be freed by the caller.
51 
52  This function has been implemented twice.
53 
54  It may be useless because code_declarations() is supposed to
55  contain all module declarations, regardless of where the
56  declarations happens.
57  */
59 {
61  if (list_undefined_p(dl))
62  {
65  }
66 
67  /* FI: maybe we should also look up the declarations in the compilation unit... */
68 
69  ifdebug(9) {
70  pips_debug(8, "Current module declarations:\n");
71  print_entities(dl);
72  fprintf(stderr, "\n");
73  }
74 
75  return gen_copy_seq(dl);
76 }
77 
79 {
81  return module_declarations(m);
82 }
83 
84 /* Return a list of all variables and functions accessible somewhere in a module. */
86 {
89  list mdl = module_declarations(m);
90 
91  pips_assert("compilation unit is an entity list.",
93  pips_assert("initial cudl is an entity list.", entity_list_p(cudl));
94  pips_assert("mdl is an entity list.", entity_list_p(mdl));
95 
96  cudl = gen_nconc(cudl, mdl);
97 
98  /* Make sure you only have entities in list cudl */
99  pips_assert("Final cudl is an entity list.", entity_list_p(cudl));
100 
101  return cudl;
102 }
103 
104 /* Retrieve the compilation unit containing a module definition.
105  *
106  * The implementation is clumsy.
107  *
108  * It would be nice to memoize the information as with
109  * get_current_module_entity().
110  *
111  * It would be much nicer to keep a resource like INPUT_FILE_NAME, say
112  * COMPILATION_UNIT_NAME.
113  *
114  * The entity returned may be undefined.
115  */
117 {
119 
121  cu = m;
122  else if(!db_resource_p(DBR_USER_FILE, module_local_name(m))) {
123  /* The resource does not always exist.
124  *
125  * For Fortran code to start with.
126  *
127  * For synthesized code too: initializer, outliner... (although
128  * pass outline might build a compilation unit...
129  *
130  * Let's assume that synthesized module "foo" has "foo!" a
131  * compilation unit name and it never is a static function.
132  */
133  string name = strdup(concatenate(entity_name(m), FILE_SEP_STRING, NULL));
134  cu = gen_find_tabulated(name, entity_domain);
135  }
136  else {
137  // string aufn = db_get_memory_resource(DBR_USER_FILE, entity_user_name(m), true);
138  string aufn = db_get_memory_resource(DBR_USER_FILE, module_local_name(m), true);
139  string lufn = strrchr(aufn, '/')+1;
140 
141  if(lufn!=NULL) {
142  string n = strstr(lufn, PP_C_ED);
143  int l = n-lufn;
144  string cun = strndup(lufn, l);
145 
146  if(static_module_name_p(cun)) {
147  string end = strrchr(cun, FILE_SEP_CHAR);
148  *(end+1) = '\0';
150  }
151  else {
152  string ncun = strdup(concatenate(cun, FILE_SEP_STRING, NULL));
154  free(ncun);
155  }
156  free(cun);
157  }
158  else
159  pips_internal_error("Not implemented yet");
160  }
161  pips_assert("If defined, cu is a compilation unit",
163  return cu;
164 }
165 
166 bool language_module_p(entity m, string lid)
167 {
168  bool c_p = false;
169 
170  if(entity_module_p(m)) {
171  /* FI: does not work with static functions */
172  //string aufn = db_get_memory_resource(DBR_USER_FILE, entity_user_name(m), true);
173  /* SG: must check if the ressource exist (not always the case) */
174  const char* lname= module_local_name(m);
175  if( db_resource_p(DBR_USER_FILE,lname) )
176  {
177  string aufn = db_get_memory_resource(DBR_USER_FILE, module_local_name(m), true);
178  string n = strstr(aufn, lid);
179 
180  c_p = (n!=NULL);
181  }
182  else
183  c_p = true; /* SG: be positive ! (needed for Hpfc)*/
184  }
185  return c_p;
186 }
187 
188 /** Add an entity to the current's module compilation unit declarations
189  * we have to generate its statement if none created before
190  * due to limitation of pipsmake, it is not always possible to make sure from pipsmake
191  * that this ressource is created.
192  * For example in INLINING (!) we would like to tell pipsmake
193  * we need the CODE resource from all module callers.
194  *
195  * @param[in] e is the entity to add
196  * @param[in] cu is the compilation unit
197  */
200  const char* cum = module_local_name(cu);
201  if( c_module_p(cu) ) {
202  if(!db_resource_required_or_available_p(DBR_PARSED_CODE,cum))
203  {
204  bool compilation_unit_parser(const char*);
210  if(!entity_undefined_p(tmp))
214  }
215  if(!db_resource_required_or_available_p(DBR_CODE,cum))
216  {
217  bool controlizer(const char*);
222  controlizer(cum);
223  if(!entity_undefined_p(tmp))
227  }
228  s=(statement)db_get_memory_resource(DBR_CODE,cum,true);
229  }
230  /* SG: when adding a new entity to compilation unit,
231  * one should check the entity is not already present
232  * but an entity with the same name may already be defined there
233  * so check this with a very costly test*/
234  list cu_entities = entity_declarations(cu);
235  FOREACH(ENTITY,cue,cu_entities)
237  return;
239  if( c_module_p(cu) ) {
240  module_reorder(s);
241  db_put_or_update_memory_resource(DBR_CODE,cum,s,true);
242  db_touch_resource(DBR_CODE,cum);
243  if( typedef_entity_p(e) ) {
244  //keyword_typedef_table = (hash_table)db_get_memory_resource(DBR_DECLARATIONS, cum, true);
245  //put_new_typedef(entity_user_name(e));
246  // FI: I do not see why the global variable of the parsers should be reused here
247  // hash_table keyword_typedef_table = (hash_table)db_get_memory_resource(DBR_DECLARATIONS, cum, true);
248  set_keyword_typedef_table((hash_table) db_get_memory_resource(DBR_DECLARATIONS, cum, true));
249  //hash_put(keyword_typedef_table,strdup(cum),(void *) TK_NAMED_TYPE);
250  // FI; temporary
251  //hash_put(keyword_typedef_table,strdup(cum),(void *) 262);
253  //SG: we have to do this behind the back of pipsmake. Not Good for serialization, but otherwise it forces the recompilation of the parsed_code of the associated modules, not good :(
254  //DB_PUT_MEMORY_RESOURCE(DBR_DECLARATIONS, cum, keyword_typedef_table);
255  }
256 
257  }
258 }
259 
260 /** Remove an entity from the current's module compilation unit declarations
261  *
262  * @param[in] e is the entity to remove
263  * @param[in] cu is the compilation unit
264  */
267  const char* cum = module_local_name(cu);
268  if( c_module_p(cu) ) {
269  if(!db_resource_required_or_available_p(DBR_CODE,cum))
270  {
271  bool controlizer(const char*);
276  controlizer(cum);
277  if(!entity_undefined_p(tmp))
281  }
282  s=(statement)db_get_memory_resource(DBR_CODE,cum,true);
283  }
284 
285  // Remove entity from global declaration lists
287  // FIXME : s is only defined for c_module !!
289 
291  if( c_module_p(cu) ) {
292  module_reorder(s);
293  db_put_or_update_memory_resource(DBR_CODE,cum,s,true);
294  db_touch_resource(DBR_CODE,cum);
295  }
296 }
297 
298 
299 
300 void
302 {
305  FOREACH(ENTITY,se,tse) {
306  const char * eln = entity_local_name(se);
307  if(strstr(eln, DUMMY_STRUCT_PREFIX) || strstr(eln, DUMMY_UNION_PREFIX) ) {
308  continue;
309  }
311  }
312  gen_free_list(tse);
314 }
315 
316 /*
317  For C, the declaration in the module statements are added.
318 
319  Because this function relies on pipsdbm, it should be relocated
320  into another library. Prime candidate is preprocessor : - (
321  */
322 
324 {
326  bool c_module_p(entity);
327 
328  if(c_module_p(m)) {
329  //const char* module_name = entity_user_name(m);
330  const char* module_name = entity_local_name(m);
331  statement s = (statement) db_get_memory_resource(DBR_PARSED_CODE, module_name, true);
333 
334  FOREACH(ENTITY, e, sdl) {
335  if(!entity_is_argument_p(e, dl))
336  dl = gen_nconc(dl, CONS(ENTITY, e, NIL));
337  }
338  gen_free_list(sdl);
339  }
340 
341  return dl;
342 }
343 
344 /* The output is undefined if the module is referenced but not defined in
345  * the workspace, for instance because its code should be synthesized.
346  *
347  * Fabien Coelho suggests to build a default compilation unit where all
348  * synthesized module codes would be located.
349  */
351 {
353  pips_assert("only for C modules\n", entity_undefined_p(e) || c_module_p(e));
354 
355  // Should only be called for C modules.
357 
358  // The guard may not be sufficient...
359  // and this may crash in db_get_memory_resource()
360  if(db_resource_p(DBR_USER_FILE, module_name)) {
361  string source_file_name =
362  db_get_memory_resource(DBR_USER_FILE, module_name, true);
363  string simpler_file_name = pips_basename(source_file_name, PP_C_ED);
364 
365  // It is not clear how robust it is going to be
366  // when file name conflicts occur.
368  simpler_file_name);
369  free(simpler_file_name);
370  }
371 
372  return compilation_unit_name;
373 }
374 
375 /* To be checked for static functions... */
377 {
379  pips_assert("only for C modules\n", entity_undefined_p(e) || c_module_p(e));
380 
381  // Should only be called for C modules.
382  string input_file_name = string_undefined;
383 
384  // The guard may not be sufficient...
385  // and this may crash in db_get_memory_resource()
386  if(db_resource_p(DBR_USER_FILE, module_name)) {
387  string source_file_name =
388  db_get_memory_resource(DBR_USER_FILE, module_name, true);
389  string simpler_file_name = pips_basename(source_file_name, PP_C_ED);
390 
391  // It is not clear how robust it is going to be
392  // when file name conflicts occur.
393  (void) asprintf(&input_file_name, "%s/" WORKSPACE_SRC_SPACE "/%s.c",
394  db_get_current_workspace_directory(), simpler_file_name);
395  free(simpler_file_name);
396  }
397 
398  return input_file_name;
399 }
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
bool db_resource_required_or_available_p(const char *rname, const char *oname)
from now on we must not know about the database internals?
Definition: database.c:505
bool db_touch_resource(const char *rname, const char *oname)
touch logical time for resource[owner], possibly behind the back of pipsdbm.
Definition: database.c:538
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
string compilation_unit_name
cproto-generated files
Definition: c_parser.c:49
bool compilation_unit_parser(const char *module_name)
Definition: c_parser.c:746
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
bool controlizer(const char *module_name)
The old controlizer user interface.
Definition: module.c:224
bool static_module_name_p(const char *name)
Check if the given name is a static module name.
Definition: entity_names.c:122
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * pips_basename(char *fullpath, char *suffix)
Definition: file.c:822
void free(void *)
void set_current_module_declarations(list)
Definition: static.c:131
list get_current_module_declarations(void)
Definition: static.c:141
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define list_undefined_p(c)
Return if a list is undefined.
Definition: newgen_list.h:75
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
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
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
void db_put_or_update_memory_resource(const char *rname, const char *oname, void *p, bool update_is_ok)
Put a resource into the current workspace database.
Definition: database.c:854
statement remove_declaration_statement(statement, entity)
Declarations are not only lists of entities, but also statement to carry the line number,...
Definition: statement.c:2966
list statement_to_declarations(void *)
Get a list of all variables declared recursively within a statement.
Definition: statement.c:3253
char end
Definition: gtk_status.c:82
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define asprintf
Definition: misc-local.h:225
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define DUMMY_STRUCT_PREFIX
Definition: naming-local.h:87
#define FILE_SEP_STRING
Definition: naming-local.h:41
#define FILE_SEP_CHAR
Definition: naming-local.h:38
#define DUMMY_UNION_PREFIX
Definition: naming-local.h:88
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define same_string_p(s1, s2)
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
#define string_undefined
Definition: newgen_types.h:40
static char * module
Definition: pips.c:74
#define WORKSPACE_SRC_SPACE
Definition: pipsdbm-local.h:32
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define entity_declarations(e)
MISC: newgen shorthands.
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool entity_list_p(list el)
Checks that el only contains entity.
Definition: entity.c:1411
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool typedef_entity_p(entity e)
Definition: entity.c:1902
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
void print_entities(list l)
Definition: entity.c:167
bool entity_module_p(entity e)
Definition: entity.c:683
bool compilation_unit_entity_p(entity e)
Check if the given module entity is a compilation unit.
Definition: module.c:87
void set_keyword_typedef_table(hash_table)
Definition: static.c:263
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
void declare_new_typedef(const string)
Definition: static.c:283
list type_supporting_entities(list, type)
Definition: type.c:4347
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define code_declarations(x)
Definition: ri.h:784
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
#define value_code(x)
Definition: ri.h:3067
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define statement_undefined
Definition: ri.h:2419
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
static int lname(char *s, int look_for_entry)
check for keywords for subprograms return 0 if comment card, 1 if found name and put in arg string.
Definition: split_file.c:283
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
list module_declarations(entity m)
High-level functions about modules, using pipsdbm and ri-util and some global variables assumed prope...
Definition: module.c:58
list module_to_all_declarations(entity m)
Definition: module.c:323
bool language_module_p(entity m, string lid)
Definition: module.c:166
string module_name_to_input_file_name(const char *module_name)
To be checked for static functions...
Definition: module.c:376
string compilation_unit_of_module(const char *module_name)
The output is undefined if the module is referenced but not defined in the workspace,...
Definition: module.c:350
list current_module_declarations()
Definition: module.c:78
void AddEntityToCompilationUnit(entity e, entity cu)
Add an entity to the current's module compilation unit declarations we have to generate its statement...
Definition: module.c:198
list module_entities(entity m)
Return a list of all variables and functions accessible somewhere in a module.
Definition: module.c:85
void RemoveEntityFromCompilationUnit(entity e, entity cu)
Remove an entity from the current's module compilation unit declarations.
Definition: module.c:265
void AddEntityToModuleCompilationUnit(entity e, entity module)
Definition: module.c:301
entity module_entity_to_compilation_unit_entity(entity m)
Retrieve the compilation unit containing a module definition.
Definition: module.c:116