PIPS
macros.c
Go to the documentation of this file.
1 /*
2 
3  $Id: macros.c 23065 2016-03-02 09:05:50Z 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  * Partial Fortran statement functions support by cold expansion.
29  */
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 
35 #include "genC.h"
36 #include "parser_private.h"
37 #include "linear.h"
38 #include "ri.h"
39 #include "ri-util.h"
40 
41 #include "misc.h"
42 #include "properties.h"
43 
44 #include "syntax.h"
45 
46 /*********************************************************** MACRO HANDLING */
47 
48 typedef struct {
51 } macro_t;
52 
54 static int current_macros_size = 0;
55 static int current_macro_index = 0; /* next available chunk */
56 
58 {
59  pips_debug(5, "initializing macro-expansion support stuff\n");
60 
61  current_macro_index = 0; /* ??? memory leak... */
62 
63  if (current_macros_size==0)
64  {
68  pips_assert("malloc ok", current_macros);
69  }
70 }
71 
73 {
74  pips_debug(5, "closing macro-expansion support stuff\n");
75 
77  {
78  call c;
79  entity macro;
80 
83 
84  macro = call_function(c);
85  free_call(c);
86 
87  /* what about the entity?
88  * It might exist such a real top-level entity...
89  * what if added as a callee...
90  * the entity should be destroyed...
91  * best would be to have it as a local entity,
92  * and have the calles and top-level updates delayed.
93  */
95  }
96 }
97 
99 {
100  int i;
101  for (i=0; i<current_macro_index; i++)
103  return &current_macros[i];
104 
105  return NULL; /* not found */
106 }
107 
109 {
110  return find_entity_macro(e)==NULL;
111 }
112 
114 {
115  entity macro = call_function(c);
116 
117  pips_debug(5, "adding macro %s\n", entity_name(macro));
118  pips_assert("macros support initialized", current_macros_size>0);
119 
120  if (current_macro_index>=current_macros_size) /* resize! */
121  {
123  current_macros = (macro_t*)
124  realloc(current_macros, sizeof(macro_t)*current_macros_size);
125  pips_assert("realloc ok", current_macros);
126  }
127 
128  if (find_entity_macro(macro) != NULL) {
129  pips_user_warning("Macro \"%s\" is not yet defined.\n",
130  entity_name(macro));
131  ParserError("parser_add_a_macro",
132  "It may be an undeclared array.\n");
133  }
134 
135  /* expand macros in the macro! It is ok, because
136  * referenced macros must appear in preceding lines (F77 15-5, line 3-5).
137  */
139 
140  /* store the result.
141  */
145 }
146 
147 
148 /* is there a call to some untrusted function?
149  */
150 static bool some_call;
151 
152 static bool call_flt(call c)
153 {
156  return true;
157  /* else untrusted!
158  */
159  some_call = true;
160  gen_recurse_stop(NULL);
161  return false;
162 }
163 
165 {
166  some_call = false;
168  return some_call;
169 }
170 
171 
172 
173 /****************************************************** MACRO SUBSTITUTION */
174 
175 /* must take care not to substitute in an inserted expression
176  */
178 static list /* of expression */ already_subs = NIL;
179 
180 static bool expr_flt(expression e)
181 {
182  return !gen_in_list_p(e, already_subs);
183 }
184 
185 static void expr_rwt(expression e)
186 {
187  if (expression_equal_p(s_init, e))
188  {
192  }
193 }
194 
195 /* substitutes occurences of initial by replacement in tree
196  */
198  expression tree,
199  expression initial,
200  expression replacement)
201 {
202  /* ifdebug(8) { */
203  /* pips_debug(8, "tree/initial/replacement\n"); */
204  /* print_expression(tree); */
205  /* print_expression(initial); */
206  /* print_expression(replacement); */
207  /* } */
208 
209  s_init = initial;
210  s_repl = replacement;
211 
213 
216 }
217 
219 {
221  already_subs = NIL;
222 }
223 
225 {
226  bool warned = false;
227  macro_t * def;
228  call c, lhs;
229  entity macro;
230  expression rhs;
231  list /* of expression */ lactuals, lformals;
232 
233  if (!expression_call_p(e)) return;
234 
236  macro = call_function(c);
237  lactuals = call_arguments(c);
238 
239  /* get the macro definition. */
240  def = find_entity_macro(macro);
241 
242  if (def==NULL) {
243  pips_debug(5, "no macro definition for %s\n", entity_name(macro));
244  return;
245  }
246 
247  lhs = def->lhs;
248  rhs = copy_expression(def->rhs); /* duplicated, for latter subs. */
249 
250  pips_assert("right macro function", macro == call_function(lhs));
251 
252  lformals = call_arguments(lhs);
253 
254  pips_assert("same #args", gen_length(lactuals)==gen_length(lformals));
255 
257 
258  /* replace each formal by its actual.
259  */
260  for (; !ENDP(lactuals); POP(lactuals), POP(lformals))
261  {
262  expression actu, form;
263 
264  form = EXPRESSION(CAR(lformals)); /* MUST be a simple reference */
265  pips_assert("dummy arg ok",
266  expression_reference_p(form) &&
268 
269  /* if the replacement is a constant, or a reference without
270  * calls to external functions, it should be safe
271  */
272  actu = EXPRESSION(CAR(lactuals));
273 
274  if (!warned && untrusted_call_p(actu)) {
275  pips_user_warning("maybe non safe substitution of macro %s!\n",
276  module_local_name(macro));
277  warned = true;
278  }
279 
280  substitute_expression_in_expression(rhs, form, actu);
281  }
282 
284 
285  /* it is important to keep the same expression, for gen_recurse use.
286  */
290  free(rhs);
291 }
292 
293 
295 {
296  if (current_macro_index>0 &&
297  get_bool_property("PARSER_EXPAND_STATEMENT_FUNCTIONS"))
299 }
300 
301 
303 {
305 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
syntax copy_syntax(syntax p)
SYNTAX.
Definition: ri.c:2442
void free_expression(expression p)
Definition: ri.c:853
void free_syntax(syntax p)
Definition: ri.c:2445
void free_call(call p)
Definition: ri.c:236
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void * malloc(YYSIZE_T)
void free(void *)
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
static expression s_init
must take care not to substitute in an inserted expression
Definition: macros.c:177
static int current_macros_size
Definition: macros.c:54
static list already_subs
of expression
Definition: macros.c:178
void parser_substitute_all_macros(statement s)
Definition: macros.c:294
void parser_close_macros_support(void)
Definition: macros.c:72
bool parser_entity_macro_p(entity e)
Definition: macros.c:108
void parser_substitute_all_macros_in_expression(expression e)
Definition: macros.c:302
void parser_macro_expansion(expression e)
Definition: macros.c:224
static bool call_flt(call c)
Definition: macros.c:152
static void expr_rwt(expression e)
Definition: macros.c:185
static bool some_call
is there a call to some untrusted function?
Definition: macros.c:150
void reset_substitute_expression_in_expression(void)
Definition: macros.c:218
void parser_init_macros_support(void)
next available chunk
Definition: macros.c:57
static int current_macro_index
Definition: macros.c:55
void parser_add_a_macro(call c, expression e)
Definition: macros.c:113
static bool expr_flt(expression e)
Definition: macros.c:180
static bool untrusted_call_p(expression e)
Definition: macros.c:164
static expression s_repl
Definition: macros.c:177
static macro_t * current_macros
Definition: macros.c:53
static macro_t * find_entity_macro(entity e)
Definition: macros.c:98
static void substitute_expression_in_expression(expression tree, expression initial, expression replacement)
substitutes occurences of initial by replacement in tree
Definition: macros.c:197
#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_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
void remove_from_called_modules(entity e)
macros are added, although they should not have been.
Definition: procedure.c:354
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool expression_call_p(expression e)
Definition: expression.c:415
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define syntax_reference(x)
Definition: ri.h:2730
#define call_function(x)
Definition: ri.h:709
#define value_intrinsic_p(x)
Definition: ri.h:3074
#define value_constant_p(x)
Definition: ri.h:3071
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
#define value_symbolic_p(x)
Definition: ri.h:3068
#define entity_name(x)
Definition: ri.h:2790
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define syntax_undefined
Definition: ri.h:2676
#define call_arguments(x)
Definition: ri.h:711
#define expression_syntax(x)
Definition: ri.h:1247
#define entity_initial(x)
Definition: ri.h:2796
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: macros.c:48
call lhs
Definition: macros.c:49
expression rhs
Definition: macros.c:50
bool ParserError(const char *f, const char *m)
Definition: parser.c:116