PIPS
return.c
Go to the documentation of this file.
1 /*
2 
3  $Id: return.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 /* Handling of C return statements. Unlike Fortran return statements,
28  C return statements carry the value returned by functions. In some
29  sense, they have a continuation since they return to the caller,
30  but there is no local continuation. So C return cannot be simply
31  replaced by goto statements. This only preserves the control
32  semantics. An additional variable, the return value, must be
33  declared and used to collect information about the different values
34  that are returned. This translation can be removed when there is
35  only one return at the end of the function body. Note that pass
36  restructure_control may be useful for procedure with several
37  returns because unspaghettify, called by the controlizer, is not
38  strong enough.
39  *
40  * Francois Irigoin
41  */
42 
43 #include <stdio.h>
44 
45 #include "genC.h"
46 #include "linear.h"
47 #include "ri.h"
48 #include "ri-util.h"
49 #include "misc.h"
50 #include "properties.h"
51 #include "prettyprint.h" // for last_statement()
52 
53 #include "c_syntax.h"
54 
55 //static entity C_end_label = entity_undefined;
56 //static char *C_end_label_local_name = RETURN_LABEL_NAME;
57 
59 {
61  return l;
62 }
63 
64 /* Generate a unique call statement to RETURN per module */
65 
66 /* Saved to be reused each time a return must be converted into a
67  goto b ythe parser */
69 /* Saved to optimize the internal representation instead of relying
70  on the parser and/or on control_restructure: is it possible to
71  optimize? what is the last expression list returned? Which
72  statement becomes redundant? */
76 /* It is saved because it is hard to retrieve from within
77  actual_c_parser() once the aprsing is
78  over. get_current_module_entity() seems to return an undefined
79  entity */
81 /* get_current_module_entity() is reset too early by the parser */
83 
85 {
90  type mt = entity_type(m);
93 
94  if(type_void_p(r))
96  else {
102  CONS(EXPRESSION, arg, NIL));
103  }
104 
105  // FI: I'd like to add a return label to this special statement...
107  statement_label(s) = l;
108  return s;
109 }
110 
111 /* The return statement must be reset when it is used by the parser to
112  * add the return statement to the function body or when a parser
113  * error is encountered.
114  */
116 {
123  //c_end_label = entity_undefined;
124 }
125 
126 /* This function is used to generate all goto's towards the unique
127  * return used to C replace return statement and to insert this unique
128  * return at the end of the current function's body.
129  */
131 {
133  pips_assert("No return statement yet\n", number_of_return_statements==-1);
136  }
138  return C_return_statement;
139 }
140 ␌
141 /* This function creates a goto instruction to label end_label. This is
142  * done to eliminate return statements.
143  *
144  * Note: I was afraid the mouse trap would not work to analyze
145  * multiple procedures but there is no problem. I guess that MakeGotoInst()
146  * generates the proper label entity regardless of end_label. FI.
147  */
148 
149 /* Generates the internal representation of a C return statement. If
150  * e is an undefined expression, a goto returnlabel is
151  * generated. Else, e is assigned to the return value of the current
152  * function, a goto is generated and both are returned within a
153  * block.
154  */
155 statement C_MakeReturnStatement(list el, int ln, string c)
156 {
161 
162  last_returned_value = el;
163 
164  if(!ENDP(el)) {
165  /* Assign the expression to the return value of the current
166  function */
169  if(ENDP(CDR(el))) {
170  expression e = EXPRESSION(CAR(el));
172  }
173  else {
174  pips_internal_error("This case is not implemented yet.");
175  }
176  }
177 
179 
180  if(instruction_undefined_p(ainst)) {
181  inst = ginst;
183  ln,
185  c,
186  inst,
187  NIL,
190  }
191  else {
193  ln,
195  c,
196  ainst,
197  NIL,
201  list sl = CONS(STATEMENT, as, CONS(STATEMENT, gs, NIL));
203  inst = make_instruction_block(sl);
204  s = instruction_to_statement(inst);
205  }
206 
207  pips_assert("inst is consistent", instruction_consistent_p(inst));
208  pips_assert("s is consistent", statement_consistent_p(s));
209 
210 
211  return s;
212 }
213 
215 {
217 }
218 
219 /* When return statements have been encountered, each of them has
220  * been replaced by a goto to a unique return statement. This unique
221  * return statement may have to be added to the function body.
222  */
224 {
225  if(get_bool_property("C_PARSER_RETURN_SUBSTITUTION")) {
226  /* How many return statements have been encountered? */
227  int nrs = GetReturnNumber();
228  int replace_p = false;
229  if(nrs==-1 || nrs==0)
230  ; /* nothing to be done */
231  else if(nrs==1) {
232  /* If the return statement is the last statement of the module
233  statement, the goto and the assignment can be replaced by a
234  call to return. Otherwise, a return statement with the
235  proper label must be added at the end of the module statement
236  ms */
237  //statement ls = find_last_statement(ms);
238  statement ls = last_statement(ms);
239  if(!statement_undefined_p(ls)) {
241  if(instruction_goto_p(li)) {
242  statement ts = instruction_goto(li);
243  if(ts==C_return_statement) {
244  //instruction lrvai =
245  // statement_instruction(last_return_value_assignment);
246  /* The goto instruction and, possibly, the return value
247  assignment can be removed: just remove the label? */
254  free_instruction(li);
255  //free_instruction(lrvai); contains the expression resued above!
256  replace_p = false;
257  }
258  else
259  replace_p = true;
260  }
261  else
262  replace_p = true;
263  }
264  else
265  replace_p = true;
266  }
267  else if(nrs>1)
268  replace_p = true;
269  else
270  pips_internal_error("The number of return statements has"
271  " not been initialized");
272 
273  if(replace_p) {
274  /* Do not forget to declare the return variable... */
276  pips_assert("ms is a block", statement_block_p(ms));
280  ms);
282  }
284  }
285  }
287 }
bool instruction_consistent_p(instruction p)
Definition: ri.c:1124
call make_call(entity a1, list a2)
Definition: ri.c:269
bool statement_consistent_p(statement p)
Definition: ri.c:2195
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
void free_instruction(instruction p)
Definition: ri.c:1118
synchronization make_synchronization_none(void)
Definition: ri.c:2424
instruction make_instruction_goto(statement _field_)
Definition: ri.c:1181
void FixCReturnStatements(statement ms)
When return statements have been encountered, each of them has been replaced by a goto to a unique re...
Definition: return.c:223
static entity return_current_module
get_current_module_entity() is reset too early by the parser
Definition: return.c:82
static int number_of_return_statements
Saved to optimize the internal representation instead of relying on the parser and/or on control_rest...
Definition: return.c:73
static statement last_return_value_assignment
Definition: return.c:75
static list last_returned_value
Definition: return.c:74
static entity return_value_entity
It is saved because it is hard to retrieve from within actual_c_parser() once the aprsing is over.
Definition: return.c:80
static statement C_return_statement
Generate a unique call statement to RETURN per module.
Definition: return.c:68
void Reset_C_ReturnStatement()
The return statement must be reset when it is used by the parser to add the return statement to the f...
Definition: return.c:115
statement C_MakeReturnStatement(list el, int ln, string c)
This function creates a goto instruction to label end_label.
Definition: return.c:155
entity Generate_C_ReturnLabel(entity m)
Handling of C return statements.
Definition: return.c:58
int GetReturnNumber()
Definition: return.c:214
statement Generate_C_ReturnStatement()
Definition: return.c:84
statement Get_C_ReturnStatement()
This function is used to generate all goto's towards the unique return used to C replace return state...
Definition: return.c:130
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
statement instruction_to_statement(instruction)
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
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
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
instruction make_assign_instruction(expression l, expression r)
Definition: instruction.c:87
instruction make_call_instruction(entity e, list l)
Build an instruction that call a function entity with an argument list.
Definition: instruction.c:51
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
#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 RETURN_LABEL_NAME
Definition: naming-local.h:106
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
#define string_undefined
Definition: newgen_types.h:40
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
statement last_statement(statement)
A simplified version of find_last_statement() located in prettyprint.c and designed to be used within...
Definition: statement.c:168
#define statement_block_p(stat)
#define C_RETURN_FUNCTION_NAME
#define call_to_instruction
entity entity_empty_label(void)
Definition: entity.c:1105
entity CreateIntrinsic(string name)
this function does not create an intrinsic function because they must all be created beforehand by th...
Definition: entity.c:1311
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
entity make_label(const char *module_name, const char *local_name)
Definition: entity.c:308
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
entity function_to_return_value(entity m)
Returns the entity rv that carries the value returned by module m, when m is not a C void function or...
Definition: module.c:509
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
#define functional_result(x)
Definition: ri.h:1444
#define type_functional(x)
Definition: ri.h:2952
#define instruction_goto(x)
Definition: ri.h:1526
#define instruction_undefined_p(x)
Definition: ri.h:1455
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define type_void_p(x)
Definition: ri.h:2959
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define instruction_goto_p(x)
Definition: ri.h:1524
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
The structure used to build lists in NewGen.
Definition: newgen_list.h:41