PIPS
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "parser_private.h"
#include "c_syntax.h"
#include "resources.h"
#include "database.h"
#include "misc.h"
#include "text-util.h"
#include "prettyprint.h"
#include "properties.h"
#include "alias_private.h"
Go to the source code of this file.
Functions | |
void | MakeCurrentModule (entity e) |
is used for switch statements also, because we do not distinguish a break in a loop or a switch More... | |
void | ResetCurrentModule () |
void | InitializeBlock () |
statement | MakeBlock (list stmts) |
Create a block statement. More... | |
statement | FindStatementFromLabel (entity l) |
statement | MakeLabeledStatement (string label, statement s, string comment) |
Construct a new statement from. More... | |
statement | MakeGotoStatement (string label) |
entity | MakeCLabel (string s) |
statement | MakeWhileLoop (list lexp, statement s, bool before) |
statement | MakeForloop (expression e1, expression e2, expression e3, statement body) |
Create a for-loop statement with some parser-specific characteristics. More... | |
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. More... | |
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, with some parser-specific characteristics. More... | |
statement | MakeSwitchStatement (statement s) |
statement | MakeCaseStatement (expression e) |
Transform. More... | |
statement | MakeDefaultStatement () |
statement | MakeBreakStatement (string cmt) |
statement | MakeContinueStatement (string cmt) |
statement | ExpressionToStatement (expression e) |
e is now owned by returned statement More... | |
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. More... | |
void | set_prettyprint_control_list_to_extern (void) |
bool | extern_prettyprint_control_list_p (void) |
void reset_prettyprint_control_list_to_extern(void) More... | |
void | set_prettyprint_control_list_to_dummy (void) |
bool | dummy_prettyprint_control_list_p (void) |
Provide the information only once. More... | |
Variables | |
stack | BlockStack |
Attention, the null statement in C is represented as the continue statement in Fortran (make_continue_statement means make_null_statement) More... | |
list | LabeledStatements |
BlockStack is used to handle block scope. More... | |
stack | SwitchGotoStack = stack_undefined |
list of labeled statements of the current module More... | |
stack | SwitchControllerStack = stack_undefined |
stack | LoopStack = stack_undefined |
static bool | extern_declaration_p = false |
Force declaration statement s to be an extern declaration. More... | |
static bool | dummy_declaration_p = false |
void set_prettyprint_control_list_to_extern(statement s) More... | |
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.
It is made of 0 and 1 constant expressions.
The first element tells the prettyprinter if the "extern" keyword must be printed out.
The next expressions tells the prettyprinter which variables should be initialized by this statement.
The control list for the initializations is built by the C parser, cyacc.y.
This is only useful for global variables which can be declared multiple times in multiple files and in multiple ways. See Prettyprint/double_declaration01-14.c.
The parser generated the initialization control list backwards
Try to patch the initialization list for derived entities assuming that derived entities are located anywhere in the declaration list. See decl64-65 and struct14-15.c
Place holder variables have been removed. Even if a compilation unit is being parsed, initialization_expressions should have no impact.
The initialization list is OK
We could assert here than in = dn, but this is asserted below with more explanations. However, only in debug mode 8.
Preserve the "extern" information right away before the C parser updates it each time it encounters a global declaration.
An extern declaration?
Provide debugging information
Build the prettyprint control list: extern first and the initializations
Update the declaration statement
initialization_expressions | nitialization_expressions |
Definition at line 919 of file statement.c.
References add_initialization_information_to_declaration_statement(), CAR, CDR, CONS, derived_entity_p(), dummy_prettyprint_control_list_p(), ENDP, ENTITY, entity_user_name(), EXPRESSION, extern_declaration_p, extern_prettyprint_control_list_p(), FOREACH, fprintf(), gen_free_list(), gen_full_free_list(), gen_length(), gen_nreverse(), ifdebug, initialization_expressions, int, int_to_expression(), NIL, pips_assert, pips_internal_error, POP, print_entities(), print_expressions(), statement_declarations, and typedef_entity_p().
bool dummy_prettyprint_control_list_p | ( | void | ) |
Provide the information only once.
Definition at line 1090 of file statement.c.
References dummy_declaration_p.
Referenced by add_prettyprint_control_list_to_declaration_statement().
statement ExpressionToStatement | ( | expression | e | ) |
e is now owned by returned statement
Definition at line 880 of file statement.c.
References call_to_statement, call_undefined, expression_syntax, free_expression(), get_current_C_comment(), get_current_C_line_number(), instruction_to_statement(), make_instruction_expression(), statement_comments, statement_number, statement_undefined, string_undefined_p, syntax_call, and syntax_call_p.
bool extern_prettyprint_control_list_p | ( | void | ) |
void reset_prettyprint_control_list_to_extern(void)
{ extern_declaration_p = false; } Provide the information only once
Definition at line 1053 of file statement.c.
References extern_declaration_p.
Referenced by add_prettyprint_control_list_to_declaration_statement().
Because a break in the forloop requires the generation of an extra label statement after the forloop.
See MakeForLoop().
Definition at line 465 of file statement.c.
References CAR, CDR, forloop_undefined, forloop_undefined_p, pips_internal_error, STATEMENT, statement_block(), statement_block_p, statement_forloop(), and statement_forloop_p().
Referenced by MakeForloopWithIndexDeclaration().
Definition at line 189 of file statement.c.
References LabeledStatements, MAP, STATEMENT, statement_label, and statement_undefined.
Referenced by MakeForloop(), MakeGotoStatement(), MakeLabeledStatement(), MakeSwitchStatement(), and MakeWhileLoop().
void InitializeBlock | ( | void | ) |
Definition at line 143 of file statement.c.
References BlockStack, stack_make(), and statement_domain.
Create a block statement.
It also gather all the declarations in the statements and declare them in the block sequence.
To please to current RI choices about Fortran, blocks cannot carry line numbers nor comments
Anyway, it might be much too late to retrieve the comment associated to the beginning of the block. The lost comment appears after the last statement of the block. To save it, as is done in Fortran, an empty statement should be added at the end of the sequence.
stmts | tmts |
Definition at line 153 of file statement.c.
References discard_C_comment(), empty_comments, empty_extensions(), ENDP, entity_empty_label(), fprintf(), ifdebug, make_instruction_sequence(), make_sequence(), make_statement(), make_synchronization_none(), pips_assert, print_entities(), statement_consistent_p(), statement_declarations, STATEMENT_NUMBER_UNDEFINED, STATEMENT_ORDERING_UNDEFINED, statements_to_direct_declarations(), and string_undefined.
NN : I did not add a bool variable to distinguish between loop and switch statements :-( FI: Also, there is no protection in case the same label has been used by the programmer...
cmt | mt |
Definition at line 849 of file statement.c.
References asprintf, basic_int, free(), get_label_prefix, LoopStack, MakeGotoStatement(), stack_head(), and statement_comments.
Referenced by MakeSwitchStatement().
statement MakeCaseStatement | ( | expression | e | ) |
Transform.
case e:
to
switch_xxx_case_e: ;
and generate
if (c == e) goto switch_xxx_case_e
where c is retrieved from SwitchControllerStack xxx is unique from LoopStack
Before the code can be generated, expression e must be statically evaluated, transformer into a character string, and this character string must be made compatible with C constraints for labels.
It might be easier to evaluate e since e must be evaluable at compile time... And it is necessary if e contains operators whose name cannot be part of a label: see switch04
We chose to ignore the impact of casts
You must evaluate the constant expression. Hopefully it is an integer expression...
The expression may be a character
remove the quotes
Make sure "restr" only contains C characters valid for a label if a character constant is used: is_letter || is_digit || '_'.
illegal characters such as '?' or ',' or '.' must be converted as well as octal constant such as '\001' and special characters such as '
'
Must be an illegal character for a label
FI: not too safe to make it octal among decimal because it can generate a label conflict.
octal character
hexadecimal character, unicode character
FI: let's deal with special cases such as
, \r, \t,... The initialization to zero is meaningless but avoids a warning.
Definition at line 712 of file statement.c.
References asprintf, basic_int, c_parser_user_warning, call_to_expression(), cast_expression, CONS, CParserError(), entity_empty_label(), entity_intrinsic(), entity_undefined, EXPRESSION, expression_cast(), expression_cast_p(), expression_constant_p(), expression_integer_value(), expression_to_string(), free(), gen_nconc(), get_current_C_comment(), get_label_prefix, intptr_t, is_language_c, LoopStack, make_call(), make_continue_statement(), make_test(), MakeGotoStatement(), MakeLabeledStatement(), NIL, pips_internal_error, sequence_statements, set_prettyprint_language_tag(), stack_head(), STATEMENT, string_undefined, SwitchControllerStack, SwitchGotoStack, and test_to_statement.
Definition at line 278 of file statement.c.
References concatenate(), entity_initial, entity_storage, entity_type, FindOrCreateEntity(), free(), get_current_module_name(), is_value_constant, LABEL_PREFIX, make_constant_litteral(), make_storage_rom(), make_value(), MakeTypeStatement(), pips_debug, strdup(), and type_undefined.
Referenced by MakeForloop(), MakeGotoStatement(), MakeLabeledStatement(), MakeSwitchStatement(), and MakeWhileLoop().
Unique label with the LoopStack
cmt | mt |
Definition at line 865 of file statement.c.
References asprintf, basic_int, free(), get_label_prefix, LoopStack, MakeGotoStatement(), stack_head(), and statement_comments.
void MakeCurrentModule | ( | entity | e | ) |
is used for switch statements also, because we do not distinguish a break in a loop or a switch
This must be changed later, the storage is of type return and we have to create a new entity
make_storage_return(e)
code_declaration to be updated : only need formal parameters, because the others are added in block statement declaration ?
The next two tests are replicated from the Fortran parser, Syntax/procedure.c, MakeCurrentFunction()
In case the module is parsed a second time, clean up the symbol table to avoid variable redefinition warnings and errors
Clean up existing local entities in case of a recompilation.
Let's hope cf is not an intrinsic: name conflict (the problem may have been detected earlier in UpdateEntity() if there are arguments)
Unfortunately, an intrinsics cannot be redefined, just like a user function or subroutine after editing because intrinsics are not handled like user functions or subroutines. They are not added to the called_modules list of other modules, unless the redefining module is parsed FIRST. There is not mechanism in PIPS to control the parsing order.
Definition at line 67 of file statement.c.
References basic_domain, CCleanLocalEntities(), code_declarations, code_undefined_p, CParserError(), ENDP, entity_initial, entity_local_name(), entity_storage, entity_type, entity_user_name(), expression_domain, init_c_areas(), init_c_implicit_variables(), intrinsic_entity_p(), is_value_code, LabeledStatements, LoopStack, make_code(), make_language_c(), make_sequence(), make_storage_rom(), make_value(), NIL, pips_debug, pips_user_warning, sequence_domain, set_current_module_entity(), stack_make(), strdup(), SwitchControllerStack, SwitchGotoStack, type_undefined, value_code, value_code_p, and value_undefined_p.
statement MakeDefaultStatement | ( | void | ) |
Return the labeled statement switch_xxx_default: ; and add goto switch_xxx_default; to the switch header
If the default case is not last, it must be moved later in the sequence_statements(CurrentSwitchGoto)
Definition at line 827 of file statement.c.
References asprintf, basic_int, CONS, entity_empty_label(), free(), gen_nconc(), get_current_C_comment(), get_label_prefix, LoopStack, make_continue_statement(), MakeGotoStatement(), MakeLabeledStatement(), sequence_statements, stack_head(), STATEMENT, and SwitchGotoStack.
statement MakeForloop | ( | expression | e1, |
expression | e2, | ||
expression | e3, | ||
statement | body | ||
) |
Create a for-loop statement with some parser-specific characteristics.
A more generic implementation would have been in ri-util instead.
There are assumptions that 2 comments have been pushed in the parser before.
[in] | e1 | is the init part of the for |
[in] | e2 | is the conditional part of the for |
[in] | e3 | is the increment part of the for |
[in] | body | is the loop body statement |
Beware that a block is returned instead of a forloop when a break has been processed. The forloop is somewhere in there...
A bool C constant cannot be used because stdbool.h may not be included
cond = make_call_expression(MakeConstant(TRUE_OPERATOR_NAME,
is_basic_logical),
NIL);
Create some land-pad labels to deal with break and continue.
Looks like some memory leaks if no break or continue...
What happens if this label is already used by the programmer? If I increment i, the label may not be retrieved when needed... unless LoopStack is updated...
This loop has a continue statement which has been transformed to goto.
Add the labeled statement at the end of loop body
The for clause may contain declarations
This loop has a break statement which has been transformed to goto Add the labeled statement after the loop
printf("For loop statement: \n");
print_statement(smt);
}
e1 | 1 |
e2 | 2 |
e3 | 3 |
body | ody |
Definition at line 358 of file statement.c.
References add_comment_and_line_number(), asprintf, basic_int, concatenate(), CONTINUE_FUNCTION_NAME, empty_extensions(), entity_empty_label(), entity_intrinsic(), expression_undefined_p, f(), FindStatementFromLabel(), forloop_consistent_p(), free(), get_current_C_line_number(), get_label_prefix, init, insert_statement(), int_to_expression(), LoopStack, make_call_expression(), make_forloop(), make_instruction_forloop(), make_statement(), make_synchronization_none(), MakeCLabel(), NIL, pips_assert, pop_current_C_comment(), pop_current_C_line_number(), s1, simplify_C_expression(), stack_head(), stack_pop(), statement_consistent_p(), STATEMENT_ORDERING_UNDEFINED, statement_undefined_p, strdup(), and string_undefined.
Referenced by MakeForloopWithIndexDeclaration().
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, with some parser-specific characteristics.
To represent for(int i = a;...;...) we generate instead: { int i; for(int i = a;...;...) }
The for could be generated back into the original form by the prettyprinter. To differentiate between such a C99 for loop or a for-loop that was really written with the i declaration just before, west may mark the for loop with an extension here so that the prettyprinter could use this hint to know if it has to do some resugaring or not.
[in,out] | decls | is the init part of the for. It is a declaration statement list |
[in] | e2 | is the conditional part of the for |
[in] | e3 | is the increment part of the for |
[in] | body | is the loop body statement |
printf("For loop statement declarations: \n");
print_statements(decls);
}
First generate naive but more robust version in the RI, such as:
{ int i = a; for(;...;...) }
We inject the for in its declaration statement to have the naive representation:
We try to refine to inject back an initialization in the for-clause.
Note split_initializations_in_statemen() works only on a block
We are interested in solving the simple case when there are 3 statements because we should be in the form of: int i; i = a; for(;...;...)
We need to remove the decl block statement and move the index declaration directly in the for statement.
Not yet implemented because it needs to extend declaration_statement_p for any kind of loops, the loop restructurers...
decls | ecls |
e2 | 2 |
e3 | 3 |
body | ody |
Definition at line 508 of file statement.c.
References append_statement_to_block_statement(), call_to_expression(), call_undefined, expression_undefined, f(), find_forloop_in_statement(), forloop_initialization, free_expression(), free_statement(), gen_length(), gen_nth(), gen_remove(), get_bool_property(), ifdebug, init, instruction_call, make_block_statement(), MakeForloop(), printf(), split_initializations_in_statement(), STATEMENT, statement_block(), statement_call(), statement_declarations, statement_instruction, and statements_to_direct_declarations().
Find the corresponding statement from its label, if not found, create a pseudo one, which will be replaced lately when we see the statement (label: statement)
label | abel |
Definition at line 254 of file statement.c.
References CONS, empty_extensions(), entity_empty_label(), FindStatementFromLabel(), get_current_C_comment(), get_current_C_line_number(), is_instruction_goto, LabeledStatements, make_continue_statement(), make_instruction(), make_statement(), make_synchronization_none(), MakeCLabel(), NIL, STATEMENT, STATEMENT_ORDERING_UNDEFINED, and statement_undefined.
Referenced by MakeBreakStatement(), MakeCaseStatement(), MakeContinueStatement(), and MakeDefaultStatement().
Construct a new statement from.
s | by adding a |
label | and a |
comment. | If it is possible to do it without creating a new statement, retun the old one modified according to. |
There is no other statement already associated with this label...
Add a label and deal all the gory details about the PIPS internal representation:
There is already a statement stub smt associated to this label with some gotos pointing to it, so keep it as the labeled target.
The statement does not have a label and can accept one, so patch in place smt:
The statement can not accept a label or another one, just keep the previous label in front:
label | abel |
comment | omment |
Definition at line 204 of file statement.c.
References add_label_to_statement(), comment(), CONS, FindStatementFromLabel(), free(), free_statement(), gen_statement_cons(), insert_comments_to_statement(), instruction_sequence_p, instruction_undefined, LabeledStatements, make_block_statement(), MakeCLabel(), NIL, STATEMENT, statement_comments, statement_instruction, statement_undefined, string_undefined, and unlabelled_statement_p().
Referenced by MakeCaseStatement(), and MakeDefaultStatement().
Transform a switch statement to if - else - goto. Example:
switch (c) { case 1: s1; case 2: s2; default: sd; }
if (c==1) goto switch_xxx_case_1; if (c==2) goto switch_xxx_case_2; goto switch_xxx_default; switch_xxx_case_1: ; s1; switch_xxx_case_2: ; s2; switch_xxx_default: ; sd;
In si, we can have goto break_xxx; (which was a break)
and break_xxx: ; is inserted at the end of the switch statement
The statement s corresponds to the body
switch_xxx_case_1: ; s1; switch_xxx_case_2: ; s2; switch_xxx_default: ; sd;
we have to insert
if (c==1) goto switch_xxx_case_1; if (c==2) goto switch_xxx_case_2; goto switch_xxx_default;
before s and return the inserted statement.
For the time being, the switch comment is lost. It should already be included in the argument,s
Make sure the default case is the last one in the test sequence
Keep the cases in the user order. Tobe checked at the pARSED_PRINTED_FILE level.
no default case, jump out of the switch control structure
trdup("")
This switch has a break statement which has been transformed to goto Add the labeled statement after the switch
{
printf("Switch statement: \n");
print_statement(s);
}
Definition at line 586 of file statement.c.
References asprintf, basic_int, CAR, CONS, ENDP, FindStatementFromLabel(), free(), free_sequence(), gen_free_list(), gen_nconc(), get_label_prefix, ifdebug, insert_statement(), instruction_goto_p, instruction_to_statement(), list_undefined, LoopStack, make_instruction_sequence(), make_sequence(), MakeBreakStatement(), MakeCLabel(), NIL, pips_assert, pips_debug, POP, sequence_statements, stack_head(), STATEMENT, statement_consistent_p(), statement_instruction, statement_undefined, statement_undefined_p, string_undefined, and SwitchGotoStack.
This loop has a continue statement which has been transformed to goto Add the labeled statement at the end of loop body
This loop has a break statement which has been transformed to goto Add the labeled statement after the loop
{
printf("While loop statement: \n");
print_statement(smt);
}
lexp | exp |
before | efore |
Definition at line 297 of file statement.c.
References asprintf, basic_int, FindStatementFromLabel(), free(), get_current_C_line_number(), get_label_prefix, insert_statement(), lexp, LoopStack, make_whileloop_statement(), MakeCLabel(), MakeCommaExpression(), pips_assert, s1, stack_head(), statement_consistent_p(), and statement_undefined_p.
void ResetCurrentModule | ( | void | ) |
Reset them to stack_undefined_p instead of STACK_NULL
Definition at line 125 of file statement.c.
References BlockStack, CModuleMemoryAllocation(), fprint_C_environment(), get_bool_property(), get_current_module_entity(), get_current_module_name(), LoopStack, pips_debug, reset_current_module_entity(), stack_free(), stack_undefined, SwitchControllerStack, and SwitchGotoStack.
void set_prettyprint_control_list_to_dummy | ( | void | ) |
Definition at line 1084 of file statement.c.
References dummy_declaration_p.
void set_prettyprint_control_list_to_extern | ( | void | ) |
Definition at line 1042 of file statement.c.
References extern_declaration_p.
stack BlockStack |
Attention, the null statement in C is represented as the continue statement in Fortran (make_continue_statement means make_null_statement)
statement.c
Definition at line 58 of file statement.c.
Referenced by InitializeBlock(), LinkInstToCurrentBlock(), MakeBlockIfInst(), MakeElseInst(), MakeEnddoInst(), MakeEndifInst(), PopBlock(), PushBlock(), and ResetCurrentModule().
void set_prettyprint_control_list_to_extern(statement s)
{ // pips_assert("s is a declaration statement", declaration_statement_p(s)); call c = statement_call(s); list cel = call_arguments(c); if(ENDP(cel)) { cel = CONS(EXPRESSION, int_to_expression(1), NIL); } else { expression ce = EXPRESSION(CAR(cel)); int extern_p = integer_constant_expression_value(ce); if(!extern_p) { EXPRESSION_(CAR(cel)) = int_to_expression(1); free_expression(ce); } } call_arguments(c) = cel; } Force declaration statement s to be a dummy derived entity declaration such as struct s;
Definition at line 1082 of file statement.c.
Referenced by dummy_prettyprint_control_list_p(), and set_prettyprint_control_list_to_dummy().
Force declaration statement s to be an extern declaration.
Definition at line 1040 of file statement.c.
Referenced by add_prettyprint_control_list_to_declaration_statement(), extern_prettyprint_control_list_p(), and set_prettyprint_control_list_to_extern().
list LabeledStatements |
BlockStack is used to handle block scope.
Definition at line 60 of file statement.c.
Referenced by FindStatementFromLabel(), MakeCurrentModule(), MakeGotoStatement(), and MakeLabeledStatement().
stack LoopStack = stack_undefined |
Definition at line 64 of file statement.c.
Referenced by c_parser_error(), MakeBreakStatement(), MakeCaseStatement(), MakeContinueStatement(), MakeCurrentModule(), MakeDefaultStatement(), MakeForloop(), MakeSwitchStatement(), MakeWhileLoop(), and ResetCurrentModule().
stack SwitchControllerStack = stack_undefined |
Definition at line 63 of file statement.c.
Referenced by c_parser_error(), MakeCaseStatement(), MakeCurrentModule(), and ResetCurrentModule().
stack SwitchGotoStack = stack_undefined |
list of labeled statements of the current module
Definition at line 62 of file statement.c.
Referenced by c_parser_error(), MakeCaseStatement(), MakeCurrentModule(), MakeDefaultStatement(), MakeSwitchStatement(), and ResetCurrentModule().