PIPS
statement.c
Go to the documentation of this file.
1 /*
2 
3  $Id: statement.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 /******************* STATEMENTS *******************/
29 
30 /* Attention, the null statement in C is represented as the continue
31  statement in Fortran (make_continue_statement means make_null_statement)*/
32 
33 // To have strndup(), asprintf()...:
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "genC.h"
40 #include "linear.h"
41 #include "ri.h"
42 #include "ri-util.h"
43 #include "parser_private.h"
44 #include "c_syntax.h"
45 
46 
47 #include "resources.h"
48 #include "database.h"
49 
50 #include "misc.h"
51 #include "text-util.h"
52 #include "prettyprint.h" // for fprint_expression in an error message
53  // and for words_expression() really used
54  // Maybe, the same stuff could be programmed otherwise
55 #include "properties.h"
56 #include "alias_private.h"
57 
58 stack BlockStack; /* BlockStack is used to handle block scope */
59 
60 list LabeledStatements; /* list of labeled statements of the current module*/
61 
64 stack LoopStack = stack_undefined; /* is used for switch statements also, because we do not
65  distinguish a break in a loop or a switch */
66 
68 {
69  /* This must be changed later, the storage is of type return and we
70  have to create a new entity*/
71  entity_storage(e) = make_storage_rom() /* make_storage_return(e) */;
74  make_code(NIL,strdup(""),
76  NIL,
77  make_language_c()));
78  /* code_declaration to be updated : only need formal parameters, because the others are added in
79  block statement declaration ? */
80  pips_debug(4,"Set current module entity %s\n",entity_user_name(e));
81 
82  /* The next two tests are replicated from the Fortran parser,
83  Syntax/procedure.c, MakeCurrentFunction() */
84 
85  /* In case the module is parsed a second time, clean up the symbol
86  table to avoid variable redefinition warnings and errors */
90  if(!code_undefined_p(c) && !ENDP(code_declarations(c))) {
91  /* Clean up existing local entities in case of a recompilation. */
93  }
94  }
95  }
96 
97  /* Let's hope cf is not an intrinsic: name conflict (the problem may
98  have been detected earlier in UpdateEntity() if there are
99  arguments) */
100  if( entity_type(e) != type_undefined
101  && intrinsic_entity_p(e) ) {
102  pips_user_warning("Intrinsic %s redefined.\n"
103  "This is not supported by PIPS. Please rename %s\n",
105  /* Unfortunately, an intrinsics cannot be redefined, just like a user function
106  * or subroutine after editing because intrinsics are not handled like
107  * user functions or subroutines. They are not added to the called_modules
108  * list of other modules, unless the redefining module is parsed FIRST.
109  * There is not mechanism in PIPS to control the parsing order.
110  */
111  CParserError("Name conflict between a "
112  "function and an intrinsic\n");
113  }
114 
115 
117  init_c_areas();
123 }
124 
126 {
128  if (get_bool_property("PARSER_DUMP_SYMBOL_TABLE"))
130  pips_debug(4,"Reset current module entity %s\n",get_current_module_name());
136  /* Reset them to stack_undefined_p instead of STACK_NULL */
141 }
142 
144 {
146 }
147 
148 /* Create a block statement
149 
150  It also gather all the declarations in the statements and declare them
151  in the block sequence.
152 */
154 {
155  /* To please to current RI choices about Fortran, blocks cannot carry
156  line numbers nor comments */
157  /* Anyway, it might be much too late to retrieve the comment
158  associated to the beginning of the block. The lost comment
159  appears after the last statement of the block. To save it, as is
160  done in Fortran, an empty statement should be added at the end of
161  the sequence. */
162  // Gather all the direct declaration entities from the statements:
164 
166  STATEMENT_NUMBER_UNDEFINED /* get_current_C_line_number() */,
168  empty_comments /* get_current_C_comment() */,
171 
173 
174  ifdebug(1) {
175  fprintf(stderr, "Declaration list: ");
177  fprintf(stderr, "NONE\n");
178  else {
180  fprintf(stderr, "\n");
181  }
182  }
183 
184  pips_assert("Block statement is consistent",statement_consistent_p(s));
185  return s;
186 }
187 
188 
190 {
191  MAP(STATEMENT,s,
192  {
193  if (statement_label(s) == l)
194  return s;
196  return statement_undefined;
197 }
198 
199 
200 /* Construct a new statement from \param s by adding a \param label and a
201  \param comment. If it is possible to do it without creating a new
202  statement, retun the old one modified according to.
203 */
205  entity l = MakeCLabel(label);
206  statement labeled_statement;
207  // Get the statement with the l label, if any:
209  if (smt == statement_undefined) {
210  /* There is no other statement already associated with this
211  label... */
212  /* Add a label and deal all the gory details about the PIPS internal
213  representation: */
214  s = add_label_to_statement(l, s, &labeled_statement);
215  // Keep a track of this statement associated to a label:
216  LabeledStatements = CONS(STATEMENT, labeled_statement, LabeledStatements);
217  }
218  else {
219  /* There is already a statement stub smt associated to this label with
220  some gotos pointing to it, so keep it as the labeled target. */
222  && unlabelled_statement_p(s)) {
223  /* The statement does not have a label and can accept one, so
224  patch in place smt: */
227  // Discard the old statement:
230  free_statement(s);
231  // And keep the old one:
232  s = smt;
233  labeled_statement = s;
234  }
235  else {
236  /* The statement can not accept a label or another one, just keep
237  the previous label in front: */
238  list stmts = gen_statement_cons(s, NIL);
239  stmts = gen_statement_cons(smt, stmts);
240  statement seq = make_block_statement(stmts);
241  labeled_statement = smt;
242  s = seq;
243  }
244  }
245  // Associate the current comment to the statement with the label:
246  if (comment != string_undefined) {
247  insert_comments_to_statement(labeled_statement, comment);
248  free(comment);
249  }
250  return s;
251 }
252 
253 
255 {
256  entity l = MakeCLabel(label);
258 
259  /* Find the corresponding statement from its label,
260  if not found, create a pseudo one, which will be replaced lately when
261  we see the statement (label: statement) */
262 
264  if (s == statement_undefined) {
267  }
274 
275  return gts;
276 }
277 
279 {
280  string ename = strdup(concatenate(LABEL_PREFIX,s,NULL));
282  free(ename);
283  if (entity_type(l) == type_undefined)
284  {
285  pips_debug(7,"Label %s\n", s);
290  }
291  else
292  pips_debug(7, "Label %s already exists\n", s);
293  return(l);
294 }
295 
296 
298 {
299  statement smt;
300  int i = basic_int((basic) stack_head(LoopStack));
301  string lab1;
302  asprintf(&lab1,"%s%s%d", get_label_prefix(), "loop_end_", i);
304  free(lab1);
305  string lab2;
306  asprintf(&lab2,"%s%s%d", get_label_prefix(), "break_", i);
308  free(lab2);
309 
311  {
312  /* This loop has a continue statement which has been transformed to goto
313  Add the labeled statement at the end of loop body*/
314  insert_statement(s,s1,false);
315  }
316 
318  s,
320  before);
321  if (!statement_undefined_p(s2))
322  {
323  /* This loop has a break statement which has been transformed to goto
324  Add the labeled statement after the loop */
325  insert_statement(smt,s2,false);
326  }
327 
328  pips_assert("While loop is consistent",statement_consistent_p(smt));
329  /* ifdebug(5) */
330  /* { */
331  /* printf("While loop statement: \n"); */
332  /* print_statement(smt); */
333  /* } */
334  return smt;
335 }
336 
337 
338 /* Create a for-loop statement with some parser-specific characteristics.
339 
340  A more generic implementation would have been in ri-util instead.
341 
342  There are assumptions that 2 comments have been pushed in the parser
343  before.
344 
345  @param[in] e1 is the init part of the for
346 
347  @param[in] e2 is the conditional part of the for
348 
349  @param[in] e3 is the increment part of the for
350 
351  @param[in] body is the loop body statement
352 
353  @return a statement with the for
354 
355  Beware that a block is returned instead of a forloop when a break
356  has been processed. The forloop is somewhere in there...
357 */
359  expression e2,
360  expression e3,
361  statement body) {
362  forloop f;
363  statement smt;
364  // Assume this push have been done in the parser:
365  int sn = pop_current_C_line_number();
366  expression init = e1;
367  expression cond = e2;
368  expression inc = e3;
369 
370  pips_assert("For loop body consistent",statement_consistent_p(body));
371 
374  NIL);
375  else
377 
378  if(expression_undefined_p(cond))
379  /* A bool C constant cannot be used
380  because stdbool.h may not be
381  included */
382  /* cond = make_call_expression(MakeConstant(TRUE_OPERATOR_NAME, */
383  /* is_basic_logical), */
384  /* NIL); */
385  cond = int_to_expression(1);
386  else
387  simplify_C_expression(cond);
388 
389  if(expression_undefined_p(inc))
391  NIL);
392  else
394 
395  int i = basic_int((basic) stack_head(LoopStack));
396  /* Create some land-pad labels to deal with break and continue.
397 
398  Looks like some memory leaks if no break or continue...
399 
400  What happens if this label is already used by the programmer? If
401  I increment i, the label may not be retrieved when
402  needed... unless LoopStack is updated...
403  */
404  string lab1 = string_undefined;
405  //do {
406  //if(!string_undefined_p(lab1)) free(lab1);
407  asprintf(&lab1, "%s%s%d", get_label_prefix(), "loop_end_", i);
408  //i++;
409  //} while(label_string_defined_in_current_module_p(lab1)()
411  free(lab1);
412 
413  string lab2 = string_undefined;
414  //do {
415  //if(!string_undefined_p(lab2)) free(lab2);
416  asprintf(&lab2, "%s%s%d", get_label_prefix(), "break_", i);
417  //i++;
418  //} while(label_string_defined_in_current_module_p(lab1)()
420  free(lab2);
421 
423  /* This loop has a continue statement which has been transformed to goto.
424 
425  Add the labeled statement at the end of loop body*/
426  insert_statement(body, s1, false);
427 
428  /* The for clause may contain declarations*/
429  f = make_forloop(init, cond, inc, body);
437 
438  if (!statement_undefined_p(s2))
439  /* This loop has a break statement which has been transformed to goto
440  Add the labeled statement after the loop */
441  insert_statement(smt, s2, false);
442 
443  // Assume these 2 push have been done in the parser:
444  string comment_after_for_clause = pop_current_C_comment();
445  string comment_before_for_clause = pop_current_C_comment();
446  string sc = strdup(concatenate(comment_before_for_clause,
447  comment_after_for_clause,
448  NULL));
449  free(comment_after_for_clause);
450  free(comment_before_for_clause);
451  smt = add_comment_and_line_number(smt, sc, sn);
453  pips_assert("For loop consistent", statement_consistent_p(smt));
454 
455  pips_assert("For loop is consistent", forloop_consistent_p(f));
456  /* ifdebug(5) { */
457  /* printf("For loop statement: \n"); */
458  /* print_statement(smt); */
459  /* } */
460  return smt;
461 }
462 
463 /* Because a break in the forloop requires the generation of an extra
464  label statement after the forloop. See MakeForLoop(). */
466 {
468  if(statement_forloop_p(s))
469  fl = statement_forloop(s);
470  else if(statement_block_p(s)) {
471  list sl = statement_block(s);
472  statement fs = STATEMENT(CAR(CDR(sl)));
473  if(statement_forloop_p(fs))
474  fl = statement_forloop(fs);
475  }
476  if(forloop_undefined_p(fl))
477  pips_internal_error("Unexpected forloop encoding\n");
478  return fl;
479 }
480 
481 /* Create a C99 for-loop statement with a declaration as first parameter
482  in the for clause, with some parser-specific characteristics.
483 
484  To represent for(int i = a;...;...) we generate instead:
485  {
486  int i;
487  for(int i = a;...;...)
488  }
489 
490  The for could be generated back into the original form by the
491  prettyprinter. To differentiate between such a C99 for loop or a
492  for-loop that was really written with the i declaration just before,
493  west may mark the for loop with an extension here so that the
494  prettyprinter could use this hint to know if it has to do some
495  resugaring or not.
496 
497  @param[in,out] decls is the init part of the for. It is a declaration
498  statement list
499 
500  @param[in] e2 is the conditional part of the for
501 
502  @param[in] e3 is the increment part of the for
503 
504  @param[in] body is the loop body statement
505 
506  @return a statement that contains the declaration and the for
507 */
509  expression e2,
510  expression e3,
511  statement body) {
512  /* ifdebug(6) { */
513  /* printf("For loop statement declarations: \n"); */
514  /* print_statements(decls); */
515  /* } */
516  // FI: modified because insert_statement() should not be used with
517  // declaration statements although it would be OK in this special case
518  // statement decl = make_statement_from_statement_list_or_empty_block(decls);
519  statement decl = make_block_statement(decls);
520  /* First generate naive but more robust version in the RI, such as:
521 
522  {
523  int i = a;
524  for(;...;...)
525  }
526  */
527  statement for_s = MakeForloop(expression_undefined, e2, e3, body);
528  /* We inject the for in its declaration statement to have the naive
529  representation: */
530  // insert_statement(decl, for_s, false);
532  // Gather all the direct declarations from the statements in the block
534  // to put them on the block statement:
535  statement_declarations(decl) = dl;
536 
537  if (!get_bool_property("C_PARSER_GENERATE_NAIVE_C99_FOR_LOOP_DECLARATION")) {
538  /* We try to refine to inject back an initialization in the for-clause.
539 
540  Note split_initializations_in_statemen() works only on a block */
542  list l = statement_block(decl);
543  size_t len = gen_length(l);
544  ifdebug(6)
545  printf("Number of statements in the block: %zd\n", len);
546  if (len == 3) {
547  /* We are interested in solving the simple case when there are 3
548  statements because we should be in the form of:
549  int i;
550  i = a;
551  for(;...;...)
552  */
553  // So we pick the initialization part which is the second statement:
554  statement init = STATEMENT(gen_nth(1, l));
555  // Remove it from the enclosing declaration statement:
556  gen_remove(&l, init);
557  // Get the assignment:
558  call c = statement_call(init);
559  // Housekeeping: first protect what we want to keep somewhere else...
561  // ... and free the now useless container:
563  // Make from it an expression that can appear inside the for clause:
565  // Get the for-loop:
567  // Remove the default-generated initialization expression:
569  // Put the new one instead:
571  if (get_bool_property("C_PARSER_GENERATE_COMPACT_C99_FOR_LOOP_DECLARATION")) {
572  /* We need to remove the decl block statement and move the index
573  declaration directly in the for statement. */
574 
575  /* Not yet implemented because it needs to extend
576  declaration_statement_p for any kind of loops, the loop
577  restructurers... */
578  ;
579  }
580  }
581  }
582  return decl;
583 }
584 
585 
587 {
588  /* Transform a switch statement to if - else - goto. Example:
589 
590  switch (c) {
591  case 1:
592  s1;
593  case 2:
594  s2;
595  default:
596  sd;
597  }
598 
599  if (c==1) goto switch_xxx_case_1;
600  if (c==2) goto switch_xxx_case_2;
601  goto switch_xxx_default;
602  switch_xxx_case_1: ;
603  s1;
604  switch_xxx_case_2: ;
605  s2;
606  switch_xxx_default: ;
607  sd;
608 
609  In si, we can have goto break_xxx; (which was a break)
610 
611  and break_xxx: ; is inserted at the end of the switch statement
612 
613  The statement s corresponds to the body
614 
615  switch_xxx_case_1: ;
616  s1;
617  switch_xxx_case_2: ;
618  s2;
619  switch_xxx_default: ;
620  sd;
621 
622  we have to insert
623 
624  if (c==1) goto switch_xxx_case_1;
625  if (c==2) goto switch_xxx_case_2;
626  goto switch_xxx_default;
627 
628 
629  before s and return the inserted statement. */
630  int i = basic_int((basic) stack_head(LoopStack));
631  string lab ;
632  asprintf(&lab, "%sbreak_%d", get_label_prefix(), i);
636  list tl = sequence_statements(oseq);
637  list ct = list_undefined;
638  list ntl = NIL;
640 
641  ifdebug(8) {
642  pips_debug(8, "tl=%p\n", tl);
643  }
644 
645  /* For the time being, the switch comment is lost. It should already
646  be included in the argument,s */
647  /* pop_current_C_comment(); */
648 
649  /* Make sure the default case is the last one in the test sequence */
650  for(ct=tl;!ENDP(ct); POP(ct)) {
651  statement s = STATEMENT(CAR(ct));
652 
654  ds = s;
655  }
656  else {
657  /* Keep the cases in the user order. Tobe checked at the
658  pARSED_PRINTED_FILE level. */
659  ntl = gen_nconc(ntl, CONS(STATEMENT,s,NIL));
660  //ntl = CONS(STATEMENT,s,ntl);
661  }
662  }
663  if(statement_undefined_p(ds)) {
664  /* no default case, jump out of the switch control structure */
665  ds = MakeBreakStatement(string_undefined /*strdup("")*/);
666  }
667  ntl = gen_nconc(ntl, CONS(STATEMENT,ds,NIL));
668  gen_free_list(tl);
669  sequence_statements(oseq)=NIL;
670  free_sequence(oseq);
672  //seq = instruction_to_statement(make_instruction_sequence(make_sequence(tl)));
673 
674  insert_statement(s,seq,true);
675 
677  free(lab);
678  if (!statement_undefined_p(smt))
679  {
680  /* This switch has a break statement which has been transformed to goto
681  Add the labeled statement after the switch */
682  insert_statement(s,smt,false);
683  }
684  pips_assert("Switch is consistent",statement_consistent_p(s));
685  /* ifdebug(5) */
686  /* { */
687  /* printf("Switch statement: \n"); */
688  /* print_statement(s); */
689  /* } */
690  return s;
691 }
692 
693 /* Transform
694  *
695  * case e:
696  *
697  * to
698  *
699  * switch_xxx_case_e: ;
700  *
701  * and generate
702  *
703  * if (c == e) goto switch_xxx_case_e
704  *
705  * where c is retrieved from SwitchControllerStack
706  * xxx is unique from LoopStack
707  *
708  * Before the code can be generated, expression e must be statically
709  * evaluated, transformer into a character string, and this character
710  * string must be made compatible with C constraints for labels.
711  */
713 {
714  int i = basic_int((basic) stack_head(LoopStack));
715  string lab = NULL;
716  /* It might be easier to evaluate e since e must be evaluable at
717  compile time... And it is necessary if e contains operators whose
718  name cannot be part of a label: see switch04 */
719  string estr = string_undefined;
720  expression ne = e;
721 
722  /* We chose to ignore the impact of casts */
723  if(expression_cast_p(e)) {
724  cast c = expression_cast(e);
725  ne = cast_expression(c);
726  }
727 
728  if(expression_constant_p(ne)) {
729  estr = expression_to_string(ne);
730  }
731  else {
732  /* You must evaluate the constant expression. Hopefully it is an
733  integer expression... */
734  intptr_t val;
735  if(expression_integer_value(ne, &val)) {
736  asprintf(&estr, "%lld", (long long int) val);
737  }
738  else {
740  c_parser_user_warning("Expression \"%s\" not supported as case expression.\n",
742  CParserError("Unsupported case expression\n");
743  }
744  }
745 
746  string restr = estr;
747 
748  /* The expression may be a character */
749  if(*estr=='\'') {
750  /* remove the quotes */
751  restr++;
752  *(estr+strlen(estr)-1) = '\000';
753  }
754 
755  /* Make sure "restr" only contains C characters valid for a label if
756  a character constant is used: is_letter || is_digit || '_'. */
757  if(strspn(restr,
758  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_abcdefghijklmnopqrstuvwxyz")!=strlen(restr) && *estr=='\'') {
759  /* illegal characters such as '?' or ',' or '.' must be converted
760  as well as octal constant such as '\001' and special
761  characters such as '\n' */
762  if(strlen(restr)==1) {
763  /* Must be an illegal character for a label */
764  /* FI: not too safe to make it octal among decimal because it
765  can generate a label conflict. */
766  asprintf(&lab,"%sswitch_%d_case_%hhd",get_label_prefix(),i,*restr);
767  }
768  else if(*restr=='\\') {
769  if(*(restr+1)=='0'||*(restr+1)=='1'||*(restr+1)=='2'||*(restr+1)=='3')
770  /* octal character */
771  asprintf(&lab,"%sswitch_%d_case_o%s",get_label_prefix(),i,restr+1);
772  else if(*(restr+1)=='x'||*(restr+1)=='u'||*(restr+1)=='U')
773  /* hexadecimal character, unicode character */
774  asprintf(&lab,"%sswitch_%d_case_%s",get_label_prefix(),i,restr+1);
775  else {
776  /* FI: let's deal with special cases such as \n, \r, \t,...
777  * The initialization to zero is meaningless but avoids a warning.
778  */
779  char labc = 0; // A string would carry more ASCII information
780  if(*(restr+1)=='a') // bell
781  labc = '\a'; // "BEL"
782  else if(*(restr+1)=='b') // backspace
783  labc = '\b'; // "BS"
784  else if(*(restr+1)=='f') // form feed
785  labc = '\f'; // "FF"
786  else if(*(restr+1)=='n') // new line
787  labc = '\n'; // "LF"
788  else if(*(restr+1)=='t') // horizontal tab
789  labc = '\t'; // "HT"
790  else if(*(restr+1)=='r') // carriage return
791  labc = '\r'; // "CR"
792  else if(*(restr+1)=='v') // vertical tab
793  labc = '\v'; // "VT"
794  else if(*(restr+1)=='\'') // quote
795  labc = '\''; //
796  else if(*(restr+1)=='\"') // double quote
797  labc = '\"'; //
798  else if(*(restr+1)=='\\') // backslash
799  labc = '\\'; //
800  else if(*(restr+1)=='\?') // question mark
801  labc = '\?'; //
802  else
803  pips_internal_error("Unexpected case. %s\n", (restr));
804  asprintf(&lab,"%sswitch_%d_case_%hhd",get_label_prefix(),i,labc);
805  }
806  }
807  }
808  else
809  asprintf(&lab,"%sswitch_%d_case_%s",get_label_prefix(),i,restr);
810 
811  free(estr);
812 
818  CONS(EXPRESSION, e, NIL))));
820  sequence CurrentSwitchGotoStack = stack_head(SwitchGotoStack);
821  sequence_statements(CurrentSwitchGotoStack) = gen_nconc(sequence_statements(CurrentSwitchGotoStack),
822  CONS(STATEMENT,test_to_statement(t),NULL));
823 
824  return s;
825 }
826 
828 {
829  /* Return the labeled statement
830  switch_xxx_default: ;
831  and add
832  goto switch_xxx_default;
833  to the switch header */
834  int i = basic_int((basic) stack_head(LoopStack));
835  string lab;
836  asprintf(&lab,"%sswitch_%d_default", get_label_prefix(), i);
840  sequence CurrentSwitchGoto = stack_head(SwitchGotoStack);
841  /* If the default case is not last, it must be moved later in the
842  sequence_statements(CurrentSwitchGoto) */
843  sequence_statements(CurrentSwitchGoto) = gen_nconc(sequence_statements(CurrentSwitchGoto),
844  CONS(STATEMENT,MakeGotoStatement(lab),NULL));
845  free(lab);
846  return s;
847 }
848 
850 {
851  /* NN : I did not add a bool variable to distinguish between loop
852  and switch statements :-( FI: Also, there is no protection in case
853  the same label has been used by the programmer... */
854  int i = basic_int((basic) stack_head(LoopStack));
855  string lab;
856  asprintf(&lab,"%sbreak_%d", get_label_prefix(), i);
857  statement bs = MakeGotoStatement(lab);
858  free(lab);
859 
860  statement_comments(bs) = cmt;
861 
862  return bs;
863 }
864 
866 {
867  /* Unique label with the LoopStack */
868  int i = basic_int((basic) stack_head(LoopStack));
869  string lab;
870  asprintf(&lab, "%sloop_end_%d", get_label_prefix(), i);
871  statement cs = MakeGotoStatement(lab);
872  free(lab);
873 
874  statement_comments(cs) = cmt;
875 
876  return cs;
877 }
878 
879 /* e is now owned by returned statement */
881 {
882  syntax s = expression_syntax(e);
884  string c = get_current_C_comment();
885 
886  if (syntax_call_p(s)) {
889  free_expression(e);
890  }
891  else
893 
895  if(!string_undefined_p(c)) {
896  statement_comments(st) = c;
897  }
898 
899  return st;
900 }
901 
902 /* The control list is hidden as arguments to the call to CONTROL in
903  * the declaration statement s.
904  *
905  * It is made of 0 and 1 constant expressions.
906  *
907  * The first element tells the prettyprinter if the "extern" keyword
908  * must be printed out.
909  *
910  * The next expressions tells the prettyprinter which variables should
911  * be initialized by this statement.
912  *
913  * The control list for the initializations is built by the C parser, cyacc.y.
914  *
915  * This is only useful for global variables which can be declared
916  * multiple times in multiple files and in multiple ways. See
917  * Prettyprint/double_declaration01-14.c.
918  */
921 {
922  list dl = statement_declarations(s); // declaration list
923 
924  if(ENDP(dl)) {
926  // FI: Well, the parser has declared fields for instance...
927  return NIL;
928  }
929  else {
930  pips_internal_error("Not expected\n");
932  }
933  }
934  else {
935  /* The parser generated the initialization control list backwards */
937 
938  int dn = (int) gen_length(dl); // declaration number
939  int in = (int) gen_length(iel); // initialization number
940  entity first = ENTITY(CAR(dl));
941 
942  list niel = NIL;
943 
944  /* Try to patch the initialization list for derived entities
945  * assuming that derived entities are located anywhere in the
946  * declaration list. See decl64-65 and struct14-15.c
947  */
948 
949  if(dn<in) {
950  /* Place holder variables have been removed. Even if a
951  * compilation unit is being parsed, initialization_expressions
952  * should have no impact.
953  */
954  list ciel = iel;
955  int i;
956  for(i=0;i<dn-1;i++) {
957  ciel = CDR(ciel);
958  }
959  list liel = CDR(ciel);
960  CDR(ciel) = NIL;
961  gen_full_free_list(liel);
962  niel = iel;
963  pips_assert("Same number of elements in both lists",
964  (int) gen_length(niel)==dn);
965  }
966  else if(dn>in) {
967  list ciel = iel;
968  FOREACH(ENTITY, e, dl) {
969  // FI: we could instead check variable_entity_p()?
970  if(derived_entity_p(e) || typedef_entity_p(e)) {
971  niel = CONS(EXPRESSION, int_to_expression(0), niel);
972  in++;
973  }
974  else {
975  niel = CONS(EXPRESSION, EXPRESSION(CAR(ciel)), niel);
976  POP(ciel);
977  }
978  }
979  niel = gen_nreverse(niel);
980  gen_free_list(iel); // initialization_expressions is dead
981  }
982  else {
983  /* The initialization list is OK */
984  niel = iel;
985  }
986 
987 
988  /* We could assert here than in = dn, but this is asserted below
989  * with more explanations. However, only in debug mode 8. */
990 
991  /* Preserve the "extern" information right away before the C parser
992  updates it each time it encounters a global declaration. */
993 
994  /* An extern declaration? */
995 
996  bool is_extern_statement_p = extern_prettyprint_control_list_p();
997  bool is_dummy_statement_p = dummy_prettyprint_control_list_p();
999  int_to_expression((is_extern_statement_p? 1 : 0) +
1000  (is_dummy_statement_p? 2 : 0));
1001 
1002  /* Provide debugging information */
1003 
1004  ifdebug(8) {
1005  fprintf(stderr, "Variable \"%s\" is %sdeclared EXTERN.\n", entity_user_name(first), is_extern_statement_p? "" : "not ");
1006  fprintf(stderr, "Number of declared variables: %d\n", dn);
1007  print_entities(dl);
1008  fprintf(stderr, "Number of initialization expressions: %d\n", in);
1009 
1010  // For debugging
1011  extern void print_expressions(list);
1012  print_expressions(niel);
1013  //printf("\nis_external = %s\n", bool_to_string(is_external));
1014  }
1015 
1016  /* Build the prettyprint control list: extern first and the initializations */
1017  list cel = CONS(EXPRESSION, extern_declaration_p, niel); // control expression list
1018 
1019  ifdebug(8) {
1020  fprintf(stderr, "Number of control expressions: %d\n", (int) gen_length(cel));
1021  print_expressions(cel);
1022  if(gen_length(dl)!=gen_length(niel)) {
1023  print_entities(dl);
1024  pips_assert("The number of variables declared is equal to the number of expressions", gen_length(dl)==gen_length(niel));
1025  }
1026  fprintf(stderr, "**************************\n");
1027  }
1028 
1029  /* Update the declaration statement */
1030 
1032 
1033  // reset the initialization_expressions list in the caller
1034  // initialization_expressions = NIL;
1035  return NIL;
1036  }
1037 }
1038 
1039 /* Force declaration statement s to be an extern declaration */
1040 static bool extern_declaration_p = false;
1041 
1043 {
1044  extern_declaration_p = true;
1045 }
1046 
1047 /* void reset_prettyprint_control_list_to_extern(void) */
1048 /* { */
1049 /* extern_declaration_p = false; */
1050 /* } */
1051 
1052 /* Provide the information only once */
1054 {
1055  bool b = extern_declaration_p;
1056  extern_declaration_p = false;
1057  return b;
1058 }
1059 
1060 /* void set_prettyprint_control_list_to_extern(statement s) */
1061 /* { */
1062 /* // pips_assert("s is a declaration statement", declaration_statement_p(s)); */
1063 /* call c = statement_call(s); */
1064 /* list cel = call_arguments(c); */
1065 /* if(ENDP(cel)) { */
1066 /* cel = CONS(EXPRESSION, int_to_expression(1), NIL); */
1067 /* } */
1068 /* else { */
1069 /* expression ce = EXPRESSION(CAR(cel)); */
1070 /* int extern_p = integer_constant_expression_value(ce); */
1071 /* if(!extern_p) { */
1072 /* EXPRESSION_(CAR(cel)) = int_to_expression(1); */
1073 /* free_expression(ce); */
1074 /* } */
1075 /* } */
1076 /* call_arguments(c) = cel; */
1077 /* } */
1078 ␌
1079 /* Force declaration statement s to be a dummy derived entity
1080  * declaration such as struct s;
1081  */
1082 static bool dummy_declaration_p = false;
1083 
1085 {
1086  dummy_declaration_p = true;
1087 }
1088 
1089 /* Provide the information only once */
1091 {
1092  bool b = dummy_declaration_p;
1093  dummy_declaration_p = false;
1094  return b;
1095 }
call make_call(entity a1, list a2)
Definition: ri.c:269
instruction make_instruction_forloop(forloop _field_)
Definition: ri.c:1193
storage make_storage_rom(void)
Definition: ri.c:2285
instruction make_instruction_expression(expression _field_)
Definition: ri.c:1196
value make_value(enum value_utype tag, void *val)
Definition: ri.c:2832
bool statement_consistent_p(statement p)
Definition: ri.c:2195
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
bool forloop_consistent_p(forloop p)
Definition: ri.c:998
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
code make_code(list a1, string a2, sequence a3, list a4, language a5)
Definition: ri.c:353
void free_expression(expression p)
Definition: ri.c:853
language make_language_c(void)
Definition: ri.c:1253
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
constant make_constant_litteral(void)
Definition: ri.c:418
list gen_statement_cons(statement p, list l)
Definition: ri.c:2202
synchronization make_synchronization_none(void)
Definition: ri.c:2424
sequence make_sequence(list a)
Definition: ri.c:2125
void free_statement(statement p)
Definition: ri.c:2189
forloop make_forloop(expression a1, expression a2, expression a3, statement a4)
Definition: ri.c:1025
void free_sequence(sequence p)
Definition: ri.c:2092
void const char const char const int
static list lexp
string get_current_C_comment(void)
Return the current comment as a string to be freed by the caller and reset the current comment.
Definition: clexer.c:1282
#define c_parser_user_warning(...)
void discard_C_comment(void)
Discard a C comment because we don't know how to deal with it.
Definition: clexer.c:1426
#define get_label_prefix()
The labels in C have function scope...
int get_current_C_line_number(void)
Definition: clexer.c:1146
string pop_current_C_comment(void)
Pop the current comment.
Definition: clexer.c:1352
int pop_current_C_line_number(void)
Definition: clexer.c:1202
entity MakeCLabel(string s)
Definition: statement.c:278
static bool dummy_declaration_p
void set_prettyprint_control_list_to_extern(statement s)
Definition: statement.c:1082
statement ExpressionToStatement(expression e)
e is now owned by returned statement
Definition: statement.c:880
statement MakeForloopWithIndexDeclaration(list decls, expression e2, expression e3, statement body)
Create a C99 for-loop statement with a declaration as first parameter in the for clause,...
Definition: statement.c:508
statement MakeBreakStatement(string cmt)
Definition: statement.c:849
static forloop find_forloop_in_statement(statement s)
Because a break in the forloop requires the generation of an extra label statement after the forloop.
Definition: statement.c:465
statement MakeContinueStatement(string cmt)
Definition: statement.c:865
stack SwitchControllerStack
Definition: statement.c:63
statement FindStatementFromLabel(entity l)
Definition: statement.c:189
statement MakeWhileLoop(list lexp, statement s, bool before)
Definition: statement.c:297
void set_prettyprint_control_list_to_dummy(void)
Definition: statement.c:1084
stack LoopStack
Definition: statement.c:64
list LabeledStatements
BlockStack is used to handle block scope.
Definition: statement.c:60
void MakeCurrentModule(entity e)
is used for switch statements also, because we do not distinguish a break in a loop or a switch
Definition: statement.c:67
statement MakeDefaultStatement()
Definition: statement.c:827
void ResetCurrentModule()
Definition: statement.c:125
stack SwitchGotoStack
list of labeled statements of the current module
Definition: statement.c:62
stack BlockStack
Attention, the null statement in C is represented as the continue statement in Fortran (make_continue...
Definition: statement.c:58
statement MakeForloop(expression e1, expression e2, expression e3, statement body)
Create a for-loop statement with some parser-specific characteristics.
Definition: statement.c:358
statement MakeLabeledStatement(string label, statement s, string comment)
Construct a new statement from.
Definition: statement.c:204
bool extern_prettyprint_control_list_p(void)
void reset_prettyprint_control_list_to_extern(void)
Definition: statement.c:1053
bool dummy_prettyprint_control_list_p(void)
Provide the information only once.
Definition: statement.c:1090
statement MakeCaseStatement(expression e)
Transform.
Definition: statement.c:712
statement MakeSwitchStatement(statement s)
Definition: statement.c:586
list add_prettyprint_control_list_to_declaration_statement(statement s, list initialization_expressions)
The control list is hidden as arguments to the call to CONTROL in the declaration statement s.
Definition: statement.c:920
static bool extern_declaration_p
Force declaration statement s to be an extern declaration.
Definition: statement.c:1040
statement MakeGotoStatement(string label)
Definition: statement.c:254
void set_prettyprint_control_list_to_extern(void)
Definition: statement.c:1042
void InitializeBlock()
Definition: statement.c:143
statement MakeBlock(list stmts)
Create a block statement.
Definition: statement.c:153
void init_c_areas(void)
In C we have 4 areas.
Definition: util.c:186
void CModuleMemoryAllocation(entity)
This function is for MemoryAllocation for Module of C programs.
Definition: util.c:1979
void init_c_implicit_variables(entity)
Definition: util.c:277
void CCleanLocalEntities(entity function)
C language version.
Definition: clean.c:146
static list initialization_expressions
to preserve information about the declarations for the prettyprinter, especially for the global varia...
Definition: cyacc.tab.c:120
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
static void comment(string_buffer code, spoc_hardware_type hw, dagvtx v, int stage, int side, bool flip)
Definition: freia_spoc.c:52
void gen_full_free_list(list l)
Definition: genClib.c:1023
void free(void *)
void CParserError(char *msg)
statement make_block_statement(list body)
Make a block statement from a list of statement.
Definition: statement.c:616
statement instruction_to_statement(instruction instr)
Build a statement from a give instruction.
Definition: statement.c:597
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
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 ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
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 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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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
#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 CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#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
list statement_block(statement s)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
call statement_call(statement s)
Get the call of a statement.
Definition: statement.c:1406
forloop statement_forloop(statement s)
Get the forloop of a statement.
Definition: statement.c:1426
bool unlabelled_statement_p(statement st)
Definition: statement.c:402
bool statement_forloop_p(statement s)
Definition: statement.c:374
statement add_initialization_information_to_declaration_statement(statement s, list iel)
The initialization expression list is integrated into the internal representation as an argument list...
Definition: statement.c:1119
void append_statement_to_block_statement(statement b, statement s)
Definition: statement.c:2586
void insert_comments_to_statement(statement s, const char *the_comments)
Insert a comment string (if non empty) at the beginning of the comments of a statement.
Definition: statement.c:1916
statement make_whileloop_statement(expression condition, statement body, int line_number, bool before)
Build a while loop statement.
Definition: statement.c:1150
statement add_comment_and_line_number(statement s, string sc, int sn)
Since block cannot carry comments nor line numbers, they must be moved to an internal continue statem...
Definition: statement.c:1980
void insert_statement(statement s, statement s1, bool before)
This is the normal entry point.
Definition: statement.c:2570
statement make_continue_statement(entity l)
Definition: statement.c:953
list statements_to_direct_declarations(list sl)
Returns the declarations contained directly in the declaration statements of a list of statements.
Definition: statement.c:3334
statement add_label_to_statement(entity label, statement s, statement *labeled_statement)
Add a label to a statement.
Definition: statement.c:2158
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
void set_prettyprint_language_tag(enum language_utype lang)
set the prettyprint language from a language_utype argument
Definition: language.c:143
#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 LABEL_PREFIX
Definition: naming-local.h:31
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define stack_undefined
Definition: newgen_stack.h:55
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
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
Definition: newgen_types.h:40
#define string_undefined_p(s)
Definition: newgen_types.h:41
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
void print_expressions(list le)
Definition: expression.c:98
string expression_to_string(expression e)
Definition: expression.c:77
#define statement_block_p(stat)
#define test_to_statement(t)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define call_to_statement(c)
#define CONTINUE_FUNCTION_NAME
#define empty_comments
Empty comments (i.e.
void split_initializations_in_statement(statement s)
Transform a declaration with an initialization statement into 2 parts, a declaration statement and an...
Definition: declarations.c:437
void fprint_C_environment(FILE *fd, entity m)
Definition: declarations.c:292
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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 FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
bool intrinsic_entity_p(entity e)
Definition: entity.c:1272
bool typedef_entity_p(entity e)
Definition: entity.c:1902
entity entity_empty_label(void)
Definition: entity.c:1105
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
void print_entities(list l)
Definition: entity.c:167
bool derived_entity_p(entity e)
Definition: entity.c:1048
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression MakeCommaExpression(list l)
Definition: expression.c:3918
bool expression_cast_p(expression e)
Definition: expression.c:450
expression make_call_expression(entity e, list l)
Build an expression that call an function entity with an argument list.
Definition: expression.c:321
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
cast expression_cast(expression e)
Definition: expression.c:455
bool simplify_C_expression(expression e)
Replace C operators "+C" and "-C" which can handle pointers by arithmetic operators "+" and "-" when ...
Definition: expression.c:2814
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
type MakeTypeStatement(void)
Definition: type.c:92
#define value_undefined_p(x)
Definition: ri.h:3017
#define value_code_p(x)
Definition: ri.h:3065
struct _newgen_struct_sequence_ * sequence
Definition: ri.h:351
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define code_undefined_p(x)
Definition: ri.h:758
#define forloop_initialization(x)
Definition: ri.h:1366
#define basic_int(x)
Definition: ri.h:616
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define forloop_undefined_p(x)
Definition: ri.h:1341
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
#define code_declarations(x)
Definition: ri.h:784
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define basic_domain
newgen_area_domain_defined
Definition: ri.h:42
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_goto
Definition: ri.h:1473
#define sequence_statements(x)
Definition: ri.h:2360
#define value_code(x)
Definition: ri.h:3067
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define type_undefined
Definition: ri.h:2883
#define instruction_call(x)
Definition: ri.h:1529
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define call_undefined
Definition: ri.h:685
#define statement_number(x)
Definition: ri.h:2452
#define instruction_goto_p(x)
Definition: ri.h:1524
#define expression_syntax(x)
Definition: ri.h:1247
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
@ is_language_c
Definition: ri.h:1567
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
#define forloop_undefined
Definition: ri.h:1340
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
int printf()
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
#define intptr_t
Definition: stdint.in.h:294
the stack head
Definition: stack.c:62
The structure used to build lists in NewGen.
Definition: newgen_list.h:41