PIPS
type_checker.c
Go to the documentation of this file.
1 /*
2 
3  $Id: type_checker.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 /*
29  * Typecheck Fortran code.
30  * by Son PhamDinh 03-05/2000
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 
36 #include "genC.h"
37 #include "linear.h"
38 
39 #include "ri.h"
40 #include "ri-util.h"
41 #include "misc.h"
42 #include "pipsdbm.h"
43 #include "resources.h"
44 #include "properties.h"
45 
46 #include "bootstrap.h" /* type of intrinsics stuff... */
47 
48 /* Working with hash_table of basic
49  */
50 #define GET_TYPE(h, e) ((basic)hash_get(h, (char*)(e)))
51 #define PUT_TYPE(h, e, b) hash_put(h, (char*)(e), (char*)(b))
52 
53 /* ENTITY
54  * It should be added in file "ri-util.h"
55  */
56 #define CONCAT_OPERATOR_NAME "//"
57 #define ENTITY_CONCAT_P(e) (entity_an_operator_p(e, CONCAT))
58 #define ENTITY_EXTERNAL_P(e) (value_code_p(entity_initial(e)))
59 #define ENTITY_INTRINSIC_P(e) (value_intrinsic_p(entity_initial(e)))
60 
61 #define ENTITY_CONVERSION_P(e,name) \
62  (strcmp(entity_local_name(e), name##_GENERIC_CONVERSION_NAME)==0)
63 #define ENTITY_CONVERSION_CMPLX_P(e) ENTITY_CONVERSION_P(e, CMPLX)
64 #define ENTITY_CONVERSION_DCMPLX_P(e) ENTITY_CONVERSION_P(e, DCMPLX)
65 
67 
68 /**************************************************************************
69  * Typing all the arguments of user-defined function C to its parameters
70  * correspondent.
71  *
72  * Note: The call C must be an user-defined function
73  */
74 static basic
76 {
77  list args = call_arguments(c);
78  type the_tp = entity_type(call_function(c));
79  functional ft = type_functional(the_tp);
81  type result = functional_result(ft);
82  int na = gen_length(args);
83  int nt = gen_length(params);
85  basic b, b1;
86  int argnumber = 0;
87 
88  if (na == nt ||
89  (nt<=na &&
91  {
92  while (args != NIL)
93  {
94  argnumber++;
95  /* Here, parameter is always a variable */
98  b1 = GET_TYPE(context->types, EXPRESSION(CAR(args)));
99  if (!basic_equal_p(b, b1))
100  {
102  "invalid arg #%d to '%s', %s instead of %s!",
103  argnumber,
106  basic_to_string(b));
107  context->number_of_error++;
108  }
109  args = CDR(args);
110  params = CDR(params);
111  }
112  }
113  else if (na < nt)
114  {
116  "Too few argument(s) to '%s' (%d<%d)!",
117  entity_local_name(call_function(c)), na, nt);
118  context->number_of_error++;
119  }
120  else
121  {
123  "Too many argument(s) to '%s' (%d>%d)!",
124  entity_local_name(call_function(c)), na, nt);
125  context->number_of_error++;
126  }
127 
128  /* Subroutine */
129  if (type_void_p(result))
130  {
131  pips_debug(7, "type of %s is overloaded\n", entity_name(call_function(c)));
132  b = make_basic_overloaded();
133  }
134  /* Function */
135  else
136  {
137  pips_debug(7, "type of %s is a function\n", entity_name(call_function(c)));
139  }
140  return b;
141 }
142 
143 /*****************************************************************************
144  * Make typing an expression of type CALL
145  * WARNING: The interpretation of COMPLEX !!!
146  */
147 static basic
149 {
150  typing_function_t dotype;
151  switch_name_function simplifier;
153  entity function_called = call_function(c);
154  basic b;
155  b = basic_undefined;
156 
157  pips_debug(2, "Call to %s; Its type is %s \n", entity_name(function_called),
158  type_to_string(entity_type(function_called)));
159 
160  /* Labels */
161  if (entity_label_p(function_called))
162  {
163  b = make_basic_overloaded();
164  }
165 
166  /* Constants */
167  else if (entity_constant_p(function_called))
168  {
169  b = basic_of_call(c, true, true);
170  }
171 
172  /* User-defined functions */
173  else if (ENTITY_EXTERNAL_P(function_called))
174  {
176  }
177 
178  /* All intrinsics */
179  else if (ENTITY_INTRINSIC_P(function_called))
180  {
181  /* Typing intrinsics */
183  entity_local_name(function_called));
184  if (dotype != 0)
185  {
186  b = dotype(c, context);
187  }
188 
189  /* Simplification */
191  entity_local_name(function_called));
192  if (simplifier != 0)
193  {
194  simplifier(exp, context);
195  }
196  }
197  else if (value_symbolic_p(entity_initial(function_called)))
198  {
199  /* lazy type entity contents... */
200  type_this_entity_if_needed(function_called, context);
201  b = GET_TYPE(context->types,
203  b = copy_basic(b);
204  }
205 
206  pips_debug(7, "Call to %s typed as %s\n", entity_name(function_called),
207  basic_to_string(b));
208 
209  return b;
210 }
211 
212 /*****************************************************************************
213  * Make typing an instruction
214  * (Assignment statement (=) is the only instruction that is typed here)
215  */
216 static void
218 {
219  basic b1;
220  call c;
221  typing_function_t dotype;
222 
223  if (instruction_call_p(i))
224  {
225  c = instruction_call(i);
226  pips_debug(1, "Call to %s; Its type is %s \n",
229 
230  /* type check a SUBROUTINE call. */
232  {
234 
235  if (!basic_overloaded_p(b1))
236  {
238  "Ignored %s value returned by '%s'",
241  /* Count the number of errors */
242  context->number_of_error++;
243  }
244  free_basic(b1);
245 
246  return;
247  }
248 
249  /* Typing intrinsics:
250  * Assignment, control statement, IO statement
251  */
254  if (dotype != 0)
255  {
256  b1 = dotype(c, context);
257  }
258  }
259 }
260 
261 static void
263 {
264  basic b = GET_TYPE(context->types, test_condition(t));
265  if (!basic_logical_p(b))
266  {
268  "Test condition must be a logical expression!");
269  context->number_of_error++;
270  }
271 }
272 
273 static void
275 {
276  basic b = GET_TYPE(context->types, whileloop_condition(w));
277  if (!basic_logical_p(b))
278  {
280  "While condition must be a logical expression!");
281  context->number_of_error++;
282  }
283 }
284 
285 /*****************************************************************************
286  * Range of loop (lower, upper, increment), all must be Integer, Real or Double
287  * (According to ANSI X3.9-1978, FORTRAN 77; Page 11-5)
288  *
289  * Return true if type of range is correct, otherwise FALSE
290  */
291 bool
293 {
294  basic lower, upper, incr;
295  lower = GET_TYPE(types, range_lower(r));
296  upper = GET_TYPE(types, range_upper(r));
297  incr = GET_TYPE(types, range_increment(r));
298  if( (basic_int_p(lower) || basic_float_p(lower)) &&
299  (basic_int_p(upper) || basic_float_p(upper)) &&
300  (basic_int_p(incr) || basic_float_p(incr)))
301  {
302  return true;
303  }
304  return false;
305 }
306 /*****************************************************************************
307  * Typing the loop if necessary
308  */
309 static void
311 {
312  basic ind = entity_basic(loop_index(l));
313 
314  /* ok for F77, but not in F90? */
315  if (!basic_int_p(ind))
316  {
318  "Obsolescent non integer loop index '%s'"
319  " (R822 ISO/IEC 1539:1991 (E))",
321  context->number_of_error++;
322  }
323 
324  if( !(basic_int_p(ind) || basic_float_p(ind)) )
325  {
327  "Index '%s' must be Integer, Real or Double!",
329  context->number_of_error++;
330  }
331  else if (!check_loop_range(loop_range(l), context->types))
332  {
334  "Range of index '%s' must be Integer, Real or Double!",
336  context->number_of_error++;
337  }
338  else
339  {
341  }
342 }
343 
344 /*****************************************************************************
345  * This function will be called in the function
346  * gen_context_recurse(...) of Newgen as its parameter
347  */
348 static void
350 {
351  syntax s = expression_syntax(e);
353 
354  /* Specify the basic of the expression e */
355  switch (syntax_tag(s))
356  {
357  case is_syntax_call:
358  b = type_this_call(e, context);
359  break;
360 
361  case is_syntax_reference:
363  pips_debug(2,"Reference: %s; Type: %s\n",
365  basic_to_string(b));
366  break;
367 
368  case is_syntax_range:
369  /* PDSon: For the range alone (not in loop),
370  * I only check lower, upper and step, they must be all INT, REAL or DBLE
371  */
372  if (!check_loop_range(syntax_range(s), context->types))
373  {
375  "Range must be INT, REAL or DBLE!");
376  context->number_of_error++;
377  }
378  break;
379 
380  default:
381  pips_internal_error("unexpected syntax tag (%d)", syntax_tag(s));
382  }
383 
384  /* Push the basic in hash table "types" */
385  if (!basic_undefined_p(b))
386  {
387  PUT_TYPE(context->types, e, b);
388  }
389 }
390 
392 {
393  MAP(EXPRESSION, ind,
394  {
395  /* cast expressions to INT if not already an int... ? */
396  /* ??? maybe should update context->types ??? */
397 
398  basic b = GET_TYPE(context->types, ind);
399  if (!basic_int_p(b))
400  {
401  basic bint = make_basic_int(4);
402  insert_cast(bint, b, ind, context); /* and simplifies! */
403  free_basic(bint);
404  }
405  },
406  reference_indices(r));
407 }
408 
409 static bool
411 {
412  stack_push(s, context->stats);
413  return true;
414 }
415 
416 static void
418 {
419  pips_assert("pop same push", stack_head(context->stats)==s);
421 }
422 
423 static void type_this_chunk(void * c, type_context_p context)
424 {
426  (c, context,
434  NULL);
435 }
436 
438 {
439  value v = entity_initial(e);
440 
441  /* ??? TODO: type->variable->dimensions->dimension->expression */
442 
443  if (value_symbolic_p(v))
444  {
445  symbolic sy = value_symbolic(v);
447  basic b1, b2;
448 
449  if (hash_defined_p(context->types, s))
450  return;
451 
452  type_this_chunk((void *) s, context);
453 
454  /* type as "e = s" */
455  b1 = entity_basic(e);
456  b2 = GET_TYPE(context->types, s);
457 
458  if (!basic_compatible_p(b1, b2))
459  {
461  "%s parameter '%s' definition from incompatible type %s",
465  context->number_of_error++;
466  return;
467  }
468 
469  if (!basic_equal_p(b1, b2))
470  {
473  }
474 }
475 }
476 
477 static void put_summary(string name, type_context_p context)
478 {
479  user_log("Type Checker Summary\n"
480  "\t%d errors found\n"
481  "\t%d conversions inserted\n"
482  "\t%d simplifications performed\n",
483  context->number_of_error,
484  context->number_of_conversion,
485  context->number_of_simplication);
486 
487  pips_user_warning("summary of '%s': "
488  "%d errors, %d convertions., %d simplifications\n",
489  name,
490  context->number_of_error,
491  context->number_of_conversion,
492  context->number_of_simplication);
493 
494  if (name && get_bool_property("TYPE_CHECKER_ADD_SUMMARY"))
495  {
497  code c;
498  char *buf;
499 
500  pips_assert("entity is a module", entity_module_p(module));
501 
503 
504  asprintf( &buf,
505  "!PIPS TYPER: %d errors, %d conversions, %d simplifications\n",
506  context->number_of_error,
507  context->number_of_conversion,
508  context->number_of_simplication);
509 
511  code_decls_text(c) = buf;
512  else
513  {
514  string tmp = code_decls_text(c);
515  code_decls_text(c) = strdup(concatenate(buf, tmp, NULL));
516  free(buf);
517  free(tmp);
518  }
519  }
520 }
521 
522 /**************************************************************************
523  * Type check all expressions in statements.
524  * Returns false if type errors are detected.
525  */
526 void typing_of_expressions(string name, statement s)
527 {
529 
532  context.number_of_error = 0;
533  context.number_of_conversion = 0;
534  context.number_of_simplication = 0;
535 
536  /* Bottom-up typing */
537  type_this_chunk((void *) s, &context);
538 
539  /* Summary */
540  put_summary(name, &context);
541 
542  /* Type checking ... */
543  HASH_MAP(st, ba, free_basic(ba), context.types);
544  hash_table_free(context.types);
546 }
547 
548 bool type_checker(const string name)
549 {
550  statement stat;
551  debug_on("TYPE_CHECKER_DEBUG_LEVEL");
552  pips_debug(1, "considering module %s\n", name);
553 
554  /* Used to check the language */
556  stat = (statement) db_get_memory_resource(DBR_CODE, name, true);
558 
559  typing_of_expressions(name, stat);
560 
561  DB_PUT_MEMORY_RESOURCE(DBR_CODE, name, stat);
564 
565  pips_debug(1, "done");
566  debug_off();
567  return true;
568 }
void user_log(const char *format,...)
Definition: message.c:234
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
basic make_basic_overloaded(void)
Definition: ri.c:167
basic make_basic_int(intptr_t _field_)
Definition: ri.c:158
void free_basic(basic p)
Definition: ri.c:107
struct paramStruct params
basic(* typing_function_t)(call, type_context_p)
void(* switch_name_function)(expression, type_context_p)
switch_name_function get_switch_name_function_for_intrinsic(const char *name)
Definition: bootstrap.c:4338
typing_function_t get_typing_function_for_intrinsic(const char *name)
Definition: bootstrap.c:4330
expression insert_cast(basic cast, basic from, expression exp, type_context_p)
Function in type_checker.c.
Definition: bootstrap.c:1567
void type_loop_range(basic, range, type_context_p)
Definition: bootstrap.c:1038
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void free(void *)
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
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#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 CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
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_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
void add_one_line_of_comment(statement, string,...)
Definition: statement.c:1940
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
#define debug_on(env)
Definition: misc-local.h:157
#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 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 debug_off()
Definition: misc-local.h:160
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
@ hash_pointer
Definition: newgen_hash.h:32
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
void stack_push(void *, stack)
stack use
Definition: stack.c:373
void stack_free(stack *)
type, bucket_size, policy
Definition: stack.c:292
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399
#define string_undefined_p(s)
Definition: newgen_types.h:41
static char * module
Definition: pips.c:74
string basic_to_string(basic)
Definition: type.c:87
#define basic_compatible_p(b1, b2)
#define entity_constant_p(e)
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 entity_label_p(entity e)
Definition: entity.c:678
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
basic entity_basic(entity e)
return the basic associated to entity e if it's a function/variable/constant basic_undefined otherwis...
Definition: entity.c:1380
bool entity_module_p(entity e)
Definition: entity.c:683
bool basic_equal_p(basic, basic)
Definition: type.c:927
basic basic_of_call(call, bool, bool)
basic basic_of_call(call c): returns the basic of the result given by the call "c".
Definition: type.c:1469
string type_to_string(const type)
type.c
Definition: type.c:51
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define functional_result(x)
Definition: ri.h:1444
#define parameter_type(x)
Definition: ri.h:1819
#define basic_int_p(x)
Definition: ri.h:614
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define range_upper(x)
Definition: ri.h:2290
#define type_functional(x)
Definition: ri.h:2952
#define type_variable(x)
Definition: ri.h:2949
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define syntax_range(x)
Definition: ri.h:2733
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#define range_increment(x)
Definition: ri.h:2292
#define instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202
#define basic_overloaded_p(x)
Definition: ri.h:623
#define value_symbolic(x)
Definition: ri.h:3070
#define basic_undefined_p(x)
Definition: ri.h:557
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define basic_undefined
Definition: ri.h:556
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define value_symbolic_p(x)
Definition: ri.h:3068
#define type_void_p(x)
Definition: ri.h:2959
#define entity_name(x)
Definition: ri.h:2790
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define reference_indices(x)
Definition: ri.h:2328
#define value_code(x)
Definition: ri.h:3067
#define syntax_call(x)
Definition: ri.h:2736
#define instruction_call_p(x)
Definition: ri.h:1527
#define type_varargs_p(x)
Definition: ri.h:2953
#define test_condition(x)
Definition: ri.h:2833
#define range_lower(x)
Definition: ri.h:2288
#define code_decls_text(x)
Definition: ri.h:786
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
#define call_arguments(x)
Definition: ri.h:711
#define whileloop_condition(x)
Definition: ri.h:3160
#define entity_type(x)
Definition: ri.h:2792
#define expression_syntax(x)
Definition: ri.h:1247
#define symbolic_expression(x)
Definition: ri.h:2597
#define loop_index(x)
Definition: ri.h:1640
#define variable_basic(x)
Definition: ri.h:3120
#define basic_logical_p(x)
Definition: ri.h:620
#define basic_float_p(x)
Definition: ri.h:617
#define entity_initial(x)
Definition: ri.h:2796
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
char * strdup()
static char buf[BSZ]
Definition: split_file.c:157
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
list stats
Definition: delay.c:255
Definition: replace.c:135
context for type checking.
static void check_this_reference(reference r, type_context_p context)
Definition: type_checker.c:391
#define ENTITY_EXTERNAL_P(e)
Definition: type_checker.c:58
static void put_summary(string name, type_context_p context)
Definition: type_checker.c:477
static void check_this_loop(loop l, type_context_p context)
Definition: type_checker.c:310
static void type_this_entity_if_needed(entity, type_context_p)
Definition: type_checker.c:437
static void type_this_expression(expression e, type_context_p context)
Definition: type_checker.c:349
static void type_this_instruction(instruction i, type_context_p context)
Definition: type_checker.c:217
bool type_checker(const string name)
Definition: type_checker.c:548
#define GET_TYPE(h, e)
type of intrinsics stuff...
Definition: type_checker.c:50
#define PUT_TYPE(h, e, b)
Definition: type_checker.c:51
static basic type_this_call(expression exp, type_context_p context)
Definition: type_checker.c:148
static void type_this_chunk(void *c, type_context_p context)
Definition: type_checker.c:423
static void stmt_rwt(statement s, type_context_p context)
Definition: type_checker.c:417
bool check_loop_range(range r, hash_table types)
type_checker.c
Definition: type_checker.c:292
static void check_this_test(test t, type_context_p context)
Definition: type_checker.c:262
static bool stmt_flt(statement s, type_context_p context)
Definition: type_checker.c:410
static basic typing_arguments_of_user_function(call c, type_context_p context)
Definition: type_checker.c:75
#define ENTITY_INTRINSIC_P(e)
Definition: type_checker.c:59
static void check_this_whileloop(whileloop w, type_context_p context)
Definition: type_checker.c:274
void typing_of_expressions(string name, statement s)
Definition: type_checker.c:526
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207