PIPS
statement.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "genC.h"
#include "parser_private.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "misc.h"
#include "properties.h"
#include "syntax.h"
#include "syn_yacc.h"
+ Include dependency graph for statement.c:

Go to the source code of this file.

Data Structures

struct  stmt
 
struct  block
 

Macros

#define INITIAL_STMTHEAP_BUFFER_SIZE   10
 the purpose of the following data structure is to associate labels to instructions. More...
 
#define MAXBLOCK   200
 The purpose of the following data structure is to build the control structure of the procedure being analyzed. More...
 
#define UNDEF   (-2)
 Well, some constant defined in reader.c and not deserving a promotion in syntax-local.h. More...
 

Typedefs

typedef struct block block
 

Functions

static void init_StmtHeap_buffer (void)
 
static void resize_StmtHeap_buffer (void)
 
void parser_reset_StmtHeap_buffer (void)
 statement.c More...
 
statement LabelToStmt (string l)
 this functions looks up in table StmtHeap for the statement s whose label is l. More...
 
void CheckAndInitializeStmt (void)
 this function looks for undefined labels. More...
 
void NewStmt (entity e, statement s)
 this function stores a new association in table StmtHeap: the label of statement s is e. More...
 
void ResetBlockStack ()
 
bool IsBlockStackEmpty ()
 
bool IsBlockStackFull ()
 
void PushBlock (instruction i, string l)
 
instruction PopBlock ()
 
entity MakeLabel (char *s) const
 This functions creates a label. More...
 
statement MakeNewLabelledStatement (entity l, instruction i)
 
statement ReuseLabelledStatement (statement s, instruction i)
 
statement MakeStatement (entity l, instruction i)
 This function makes a statement. More...
 
void LinkInstToCurrentBlock (instruction i, bool number_it)
 this function links the instruction i to the current block of statements. More...
 
instruction MakeEmptyInstructionBlock ()
 this function creates an empty block More...
 
instruction MakeZeroOrOneArgCallInst (char *s, expression e)
 this function creates a simple Fortran statement such as RETURN, CONTINUE, ... More...
 
instruction MakeGotoInst (string n)
 this function creates a goto instruction. More...
 
instruction make_goto_instruction (entity l)
 In a "go to" instruction, the label does not appear explictly. More...
 
instruction MakeComputedGotoInst (list ll, expression e)
 
instruction MakeAssignedGotoInst (list ll, entity i)
 
instruction MakeAssignedOrComputedGotoInst (list ll, expression ce, bool assigned)
 
instruction MakeAssignInst (syntax l, expression e)
 this function creates an affectation statement. More...
 
void update_functional_type_result (entity f, type nt)
 Update of the type returned by function f. More...
 
void update_functional_type_with_actual_arguments (entity e, list l)
 
instruction MakeCallInst (entity e, cons *l)
 this function creates a call statement. More...
 
void MakeDoInst (syntax s, range r, string l)
 this function creates a do loop statement. More...
 
void MakeWhileDoInst (expression c, string l)
 This function creates a while do loop statement. More...
 
expression fix_if_condition (expression e)
 
instruction MakeLogicalIfInst (expression e, instruction i)
 this function creates a logical if statement. More...
 
instruction MakeArithmIfInst (expression e, string l1, string l2, string l3)
 this function transforms an arithmetic if statement into a set of regular tests. More...
 
void MakeBlockIfInst (expression e, int elsif)
 this function and the two next ones create a block if statement. More...
 
int MakeElseInst (bool is_else_p)
 This function is used to handle either an ELSE or an ELSEIF construct. More...
 
void MakeEndifInst ()
 
void MakeEnddoInst ()
 
string NameOfToken (int token)
 
statement make_check_io_statement (string n, expression u, entity l)
 Generate a test to jump to l if flag f is TRUE Used to implement control effects of IO's due to ERR= and END=. More...
 
instruction MakeIoInstA (int keyword, list lci, list lio)
 this function creates an IO statement. More...
 
instruction MakeIoInstB (int keyword, expression e1, expression e2, expression e3, expression e4)
 this function creates a BUFFER IN or BUFFER OUT io statement. More...
 
instruction MakeSimpleIoInst1 (int keyword, expression unit)
 
instruction MakeSimpleIoInst2 (int keyword, expression f, list io_list)
 
void reset_first_statement ()
 
void set_first_format_statement ()
 
bool first_executable_statement_seen ()
 
bool first_format_statement_seen ()
 
void check_in_declarations ()
 
void check_first_statement ()
 This function is called each time an executable statement is encountered but is effective the first time only. More...
 

Variables

static stmtStmtHeap_buffer
 
static int StmtHeap_buffer_size
 
static int CurrentStmt = 0
 
LOCAL block BlockStack [MAXBLOCK]
 statement.c More...
 
LOCAL int CurrentBlock = 0
 
static int seen = false
 Are we in the declaration or in the executable part? Have we seen a FORMAT statement before an executable statement? For more explanation, see check_first_statement() below. More...
 
static int format_seen = false
 
static int declaration_lines = -1
 

Macro Definition Documentation

◆ INITIAL_STMTHEAP_BUFFER_SIZE

#define INITIAL_STMTHEAP_BUFFER_SIZE   10

the purpose of the following data structure is to associate labels to instructions.

The data structure contains a string (the label's name) and a statement (the statement which the label is attached to).

Definition at line 52 of file statement.c.

◆ MAXBLOCK

#define MAXBLOCK   200

The purpose of the following data structure is to build the control structure of the procedure being analyzed.

each time a control statement (do loop, block if, ...) is analyzed, a new block is created and pushed on the block stack. regular statement (assign, goto, return, ...) are linked to the block that is on the top of the stack. blocks are removed from the stack when the corresponding end statement is encountered (endif, end of loop, ...).

The block ending statements are ELSE, ENDIF,...

There does not seem to be any limit on the nesting level in Fortran standard. MAXBLOCK is set to "large" value for our users. The IF/THEN/ELSEIF construct is replaced by nested IF/ELSE statements which increases the nesting level observed by the source reader.

Fabien Coelho suggests to refactor this part of the code with a Newgen stack automatically reallocated on overflow:

stack s = stack_make(statement_domain, 0, 0); stack_push(e, s); e = stack_pop(s); while (!stack_empty_p(s)) { ... } stack_free(s);

Definition at line 189 of file statement.c.

◆ UNDEF

#define UNDEF   (-2)

Well, some constant defined in reader.c and not deserving a promotion in syntax-local.h.

Definition at line 1941 of file statement.c.

Typedef Documentation

◆ block

typedef struct block block

Function Documentation

◆ check_first_statement()

void check_first_statement ( void  )

This function is called each time an executable statement is encountered but is effective the first time only.

It mainly copies the declaration text in the symbol table because it is impossible (very difficult) to reproduce it in a user-friendly manner.

The declaration text stops at the first executable statement or at the first FORMAT statement.

dynamic local buffer

we must read the input file from the begining and up to the line_b_I-1 th line, and the texte read must be stored in buffer

declaration_lines = line_b_I-1;

buffer[ibuffer++] = in_comment? c : toupper(c);

Constant strings must be taken care of

Standard version

For Cathare-2, get rid of 100 to 200 MB of declaration text:

strdup(buffer);

free(buffer), buffer=NULL;

kill the first statement's comment because it's already included in the declaration text

FI: I'd rather keep them together!

clean up the declarations

Common sizes are not yet known because ComputeAddresses() has not been called yet

update_common_sizes();

It might seem logical to perform these calls from EndOfProcedure() here. But at least ComputeAddresses() is useful for implictly declared variables. These calls are better located in EndOfProcedure().

Definition at line 2004 of file statement.c.

2005 {
2006  int line_start = true;
2007  int in_comment = false;
2008  int out_of_constant_string = true;
2009  int in_constant_string = false;
2010  int end_of_constant_string = false;
2011  char string_sep = '\000';
2012 
2013  if (! seen)
2014  {
2015  FILE *fd;
2016  int cpt = 0, ibuffer = 0, c;
2017 
2018  /* dynamic local buffer
2019  */
2020  int buffer_size = 1000;
2021  char * buffer = (char*) malloc(buffer_size);
2022  pips_assert("malloc ok", buffer);
2023 
2024  seen = true;
2025 
2026  /* we must read the input file from the begining and up to the
2027  line_b_I-1 th line, and the texte read must be stored in buffer */
2028 
2029  if(!format_seen) {
2030  /* declaration_lines = line_b_I-1; */
2031  debug(8, "check_first_statement", "line_b_C=%d, line_b_I=%d\n",
2032  line_b_C, line_b_I);
2034  }
2035 
2036  fd = safe_fopen(CurrentFN, "r");
2037  while ((c = getc(fd)) != EOF) {
2038  if(line_start == true)
2039  in_comment = strchr(START_COMMENT_LINE,c) != NULL;
2040  /* buffer[ibuffer++] = in_comment? c : toupper(c); */
2041  if(in_comment) {
2042  buffer[ibuffer++] = c;
2043  }
2044  else {
2045  /* Constant strings must be taken care of */
2046  if(out_of_constant_string) {
2047  if(c=='\'' || c == '"') {
2048  string_sep = c;
2049  out_of_constant_string = false;
2050  in_constant_string = true;
2051  buffer[ibuffer++] = c;
2052  }
2053  else {
2054  buffer[ibuffer++] = toupper(c);
2055  }
2056  }
2057  else
2058  if(in_constant_string) {
2059  if(c==string_sep) {
2060  in_constant_string = false;
2061  end_of_constant_string = true;
2062  }
2063  buffer[ibuffer++] = c;
2064  }
2065  else
2066  if(end_of_constant_string) {
2067  if(c==string_sep) {
2068  in_constant_string = true;
2069  end_of_constant_string = false;
2070  buffer[ibuffer++] = c;
2071  }
2072  else {
2073  out_of_constant_string = true;
2074  end_of_constant_string = false;
2075  buffer[ibuffer++] = toupper(c);
2076  }
2077  }
2078  }
2079 
2080  if (ibuffer >= buffer_size-10)
2081  {
2082  pips_assert("buffer initialized", buffer_size>0);
2083  buffer_size*=2;
2084  buffer = (char*) realloc(buffer, buffer_size);
2085  pips_assert("realloc ok", buffer);
2086  }
2087 
2088  if (c == '\n') {
2089  cpt++;
2090  line_start = true;
2091  in_comment = false;
2092  }
2093  else {
2094  line_start = false;
2095  }
2096 
2097  if (cpt == declaration_lines)
2098  break;
2099  }
2100  safe_fclose(fd, CurrentFN);
2101  buffer[ibuffer++] = '\0';
2102  /* Standard version */
2104  buffer = NULL;
2105  /* For Cathare-2, get rid of 100 to 200 MB of declaration text: */
2106  /*
2107  code_decls_text(EntityCode(get_current_module_entity())) = strdup("");
2108  free(buffer);
2109  */
2110  /* strdup(buffer); */
2111  /* free(buffer), buffer=NULL; */
2112 
2113  /* kill the first statement's comment because it's already
2114  included in the declaration text */
2115  /* FI: I'd rather keep them together! */
2116  /*
2117  PrevComm[0] = '\0';
2118  iPrevComm = 0;
2119  */
2120  /*
2121  Comm[0] = '\0';
2122  iComm = 0;
2123  */
2124 
2125  /* clean up the declarations */
2126  /* Common sizes are not yet known because ComputeAddresses() has not been called yet */
2127  /* update_common_sizes(); */
2128 
2129  /* It might seem logical to perform these calls from EndOfProcedure()
2130  * here. But at least ComputeAddresses() is useful for implictly
2131  * declared variables.
2132  * These calls are better located in EndOfProcedure().
2133  */
2134  /*
2135  * UpdateFunctionalType(FormalParameters);
2136  *
2137  * ComputeEquivalences();
2138  * ComputeAddresses();
2139  *
2140  * check_common_layouts(get_current_module_entity());
2141  *
2142  * SaveChains();
2143  */
2144  }
2145 }
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
void * malloc(YYSIZE_T)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
code EntityCode(entity e)
this function checks that e has an initial value code.
Definition: entity.c:301
#define code_decls_text(x)
Definition: ri.h:786
static int cpt
Definition: stats.c:41
static size_t buffer_size
Definition: string.c:114
static string buffer
Definition: string.c:113
#define START_COMMENT_LINE
Legal characters to start a comment line.
Definition: syntax-local.h:30
char * CurrentFN
Pre-parser for Fortran syntax idiosyncrasy.
Definition: parser.c:49
int line_b_C
Definition: parser.c:68
int line_b_I
Indicates where the current instruction (in fact statement) starts and ends in the input file and giv...
Definition: parser.c:68
static int format_seen
Definition: statement.c:1935
static int seen
Are we in the declaration or in the executable part? Have we seen a FORMAT statement before an execut...
Definition: statement.c:1934
#define UNDEF
Well, some constant defined in reader.c and not deserving a promotion in syntax-local....
Definition: statement.c:1941
static int declaration_lines
Definition: statement.c:1936

References buffer, buffer_size, code_decls_text, cpt, CurrentFN, debug(), declaration_lines, EntityCode(), format_seen, get_current_module_entity(), line_b_C, line_b_I, malloc(), pips_assert, safe_fclose(), safe_fopen(), seen, START_COMMENT_LINE, and UNDEF.

+ Here is the call graph for this function:

◆ check_in_declarations()

void check_in_declarations ( void  )

A FORMAT statement has been found in the middle of the declarations

Definition at line 1976 of file statement.c.

1977 {
1978  if(seen) {
1979  ParserError("Syntax",
1980  "Declaration appears after executable statement");
1981  }
1982  else if(format_seen && !seen) {
1983  /* A FORMAT statement has been found in the middle of the declarations */
1984  if(!get_bool_property("PRETTYPRINT_ALL_DECLARATIONS")) {
1985  pips_user_warning("FORMAT statement within declarations. In order to "
1986  "analyze this code, "
1987  "please set property PRETTYPRINT_ALL_DECLARATIONS "
1988  "or move this FORMAT down in executable code.\n");
1989  ParserError("Syntax", "Source cannot be parsed with current properties");
1990  }
1991  }
1992 }
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define pips_user_warning
Definition: misc-local.h:146
bool ParserError(const char *f, const char *m)
Definition: parser.c:116

References format_seen, get_bool_property(), ParserError(), pips_user_warning, and seen.

+ Here is the call graph for this function:

◆ CheckAndInitializeStmt()

void CheckAndInitializeStmt ( void  )

this function looks for undefined labels.

a label is undefined if a goto to that label has been encountered and if no statement with this label has been parsed.

Definition at line 113 of file statement.c.

114 {
115  int i;
116  int MustStop = false;
117 
118  for (i = 0; i < CurrentStmt; i++) {
119  statement s = StmtHeap_buffer[i].s;
121  MustStop = true;
122  user_warning("CheckAndInitializeStmt", "Undefined label \"%s\"\n",
124  }
125  }
126 
127  if (MustStop) {
128  ParserError("CheckAndInitializeStmt", "Undefined label(s)\n");
129  }
130  else {
131  CurrentStmt = 0;
132  }
133 }
#define user_warning(fn,...)
Definition: misc-local.h:262
const char * label_local_name(entity e)
END_EOLE.
Definition: entity.c:604
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define statement_instruction(x)
Definition: ri.h:2458
statement s
the name of the label
Definition: statement.c:56
static stmt * StmtHeap_buffer
Definition: statement.c:59
static int CurrentStmt
Definition: statement.c:61

References CurrentStmt, instruction_undefined, label_local_name(), ParserError(), stmt::s, statement_instruction, statement_label, StmtHeap_buffer, and user_warning.

Referenced by EndOfProcedure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ first_executable_statement_seen()

bool first_executable_statement_seen ( void  )

Definition at line 1964 of file statement.c.

1965 {
1966  return seen;
1967 }

References seen.

◆ first_format_statement_seen()

bool first_format_statement_seen ( void  )

Definition at line 1970 of file statement.c.

1971 {
1972  return format_seen;
1973 }

References format_seen.

◆ fix_if_condition()

expression fix_if_condition ( expression  e)

with the f77 compiler, this is equivalent to e.NE.0 if e is an integer expression.

Definition at line 1293 of file statement.c.

1294 {
1296 
1297  if(!logical_expression_p(e)) {
1298  /* with the f77 compiler, this is equivalent to e.NE.0 if e is an
1299  integer expression. */
1300  if(integer_expression_p(e)) {
1302  e, int_to_expression(0));
1303  pips_user_warning("IF condition between lines %d and %d is not a logical expression.\n",
1304  line_b_I,line_e_I);
1305  }
1306  else {
1307  ParserError("MakeBlockIfInst", "IF condition is neither logical nor integer.\n");
1308  }
1309  }
1310  else {
1311  cond = e;
1312  }
1313  return cond;
1314 }
#define NON_EQUAL_OPERATOR_NAME
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
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
bool logical_expression_p(expression e)
Definition: expression.c:610
bool integer_expression_p(expression e)
Definition: expression.c:601
#define expression_undefined
Definition: ri.h:1223
int line_e_I
Definition: parser.c:68

References entity_intrinsic(), expression_undefined, int_to_expression(), integer_expression_p(), line_b_I, line_e_I, logical_expression_p(), MakeBinaryCall(), NON_EQUAL_OPERATOR_NAME, ParserError(), and pips_user_warning.

Referenced by MakeBlockIfInst(), and MakeLogicalIfInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_StmtHeap_buffer()

static void init_StmtHeap_buffer ( void  )
static

if needed

Definition at line 64 of file statement.c.

65 {
66  if (StmtHeap_buffer_size!=0) return; /* if needed */
67  pips_debug(9, "allocating StmtHeap buffer\n");
70  pips_assert("malloc ok", StmtHeap_buffer);
71 }
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
Definition: statement.c:54
#define INITIAL_STMTHEAP_BUFFER_SIZE
the purpose of the following data structure is to associate labels to instructions.
Definition: statement.c:52
static int StmtHeap_buffer_size
Definition: statement.c:60

References INITIAL_STMTHEAP_BUFFER_SIZE, malloc(), pips_assert, pips_debug, StmtHeap_buffer, and StmtHeap_buffer_size.

Referenced by NewStmt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsBlockStackEmpty()

bool IsBlockStackEmpty ( void  )

Definition at line 209 of file statement.c.

210 {
211  return(CurrentBlock == 0);
212 }
LOCAL int CurrentBlock
Definition: statement.c:200

References CurrentBlock.

Referenced by EndOfProcedure(), LinkInstToCurrentBlock(), and PopBlock().

+ Here is the caller graph for this function:

◆ IsBlockStackFull()

bool IsBlockStackFull ( void  )

Definition at line 215 of file statement.c.

216 {
217  return(CurrentBlock == MAXBLOCK);
218 }
#define MAXBLOCK
The purpose of the following data structure is to build the control structure of the procedure being ...
Definition: statement.c:189

References CurrentBlock, and MAXBLOCK.

Referenced by PushBlock().

+ Here is the caller graph for this function:

◆ LabelToStmt()

statement LabelToStmt ( string  l)

this functions looks up in table StmtHeap for the statement s whose label is l.

Definition at line 94 of file statement.c.

96 {
97  int i;
98 
99  for (i = 0; i < CurrentStmt; i++)
100  if (strcmp(l, StmtHeap_buffer[i].l) == 0)
101  return(StmtHeap_buffer[i].s);
102 
103  return(statement_undefined);
104 }
#define statement_undefined
Definition: ri.h:2419

References CurrentStmt, statement_undefined, and StmtHeap_buffer.

Referenced by make_goto_instruction(), MakeStatement(), and NewStmt().

+ Here is the caller graph for this function:

◆ LinkInstToCurrentBlock()

void LinkInstToCurrentBlock ( instruction  i,
bool  number_it 
)

this function links the instruction i to the current block of statements.

if i is the last instruction of the block (i and the block have the same label), the current block is popped from the stack. in fortran, one instruction migth end more than one block.

A label cannot be used twice

a CONTINUE instruction must be added to carry the label, because blocks cannot be labelled

The above continue is not a user statement an should not be numbered

OK, an argument could be added to MakeStatement()...

decrement_statement_number();

instruction_block(i) = CONS (STATEMENT, c, ls);

pips_assert("Why do you want to number a block?!?", false);

OK, let's be cool and ignore this request to save the caller a test

s = MakeStatement(entity_empty_label(), i);

s = instruction_to_statement(i);

s = instruction_to_statement(i);

Because of labelled loop desugaring, new_i may be different from i

Only desugared constructs such as labelled loop, computed go to or IO with error handling should produce blocks. Such blocks should be non-empty and not commented.

Sometimes, we generate blocks with only one statement in it. E.g. alternate returns pips_assert("The block has at least two statements", !ENDP(CDR(instruction_block(new_i))));

For keeping pragma attached to a loop attached to it, we have to find the loop instruction within the block

while i is the last instruction of the current block ...

Parameters
number_itumber_it

Definition at line 529 of file statement.c.

532 {
533  statement s;
534  cons * pc;
535  entity l = MakeLabel(lab_I);
536 
537  pips_debug(8, "Begin for instruction %s with label \"%s\"\n",
539 
540  /* A label cannot be used twice */
542 
543  if (IsBlockStackEmpty())
544  ParserError("LinkInstToCurrentBlock", "no current block\n");
545 
547  /* a CONTINUE instruction must be added to carry the label,
548  because blocks cannot be labelled */
549  /*
550  list ls = instruction_block(i);
551  statement c = MakeStatement(l, make_continue_instruction());
552  */
553  /* The above continue is not a user statement an should not be numbered */
554  /* OK, an argument could be added to MakeStatement()... */
555  /* decrement_statement_number(); */
556 
557  /* instruction_block(i) = CONS (STATEMENT, c, ls); */
558  if(number_it) {
559  /* pips_assert("Why do you want to number a block?!?", false); */
560  /* OK, let's be cool and ignore this request to save the caller a test */
561  /* s = MakeStatement(entity_empty_label(), i); */
562  /* s = instruction_to_statement(i); */
563  ;
564  }
565  else{
566  /* s = instruction_to_statement(i); */
567  ;
568  }
569  s = MakeStatement(l, i);
570  }
571  else {
572  s = MakeStatement(l, i);
573  }
574 
575  if (iPrevComm != 0) {
576  /* Because of labelled loop desugaring, new_i may be different from i */
578  if(instruction_block_p(new_i)) {
579  statement fs = statement_undefined; // first statement of the block
580  statement ss = statement_undefined; // second statement, if it exist
581  statement cs = statement_undefined; // commented statement
582 
583  /* Only desugared constructs such as labelled loop, computed go to or IO with
584  * error handling should produce blocks. Such blocks should be
585  * non-empty and not commented.
586  */
587  pips_assert("The block is non empty", !ENDP(instruction_block(new_i)));
588  /* Sometimes, we generate blocks with only one statement in it. E.g. alternate returns
589  pips_assert("The block has at least two statements", !ENDP(CDR(instruction_block(new_i))));
590  */
591 
592  fs = STATEMENT(CAR(instruction_block(new_i)));
593  /* For keeping pragma attached to a loop attached to it,
594  we have to find the loop instruction within the
595  block */
596  if(!ENDP(CDR(instruction_block(new_i)))) {
597  ss = STATEMENT(CAR(CDR(instruction_block(new_i))));
598 
600  cs = ss;
601  else
602  cs = fs;
603  }
604  else {
605  cs = fs;
606  }
607  /*
608  pips_assert("The first statement has no comments",
609  statement_comments(cs) == empty_comments);
610  */
612  user_log("Current comment of chosen statement: \"%s\"\n",
613  statement_comments(cs));
614  user_log("Block comment to be carried by first statement: \"%s\"\n",
615  PrevComm);
616  pips_internal_error("The first statement of the block should have no comments");
617  }
618 
619  pips_assert("The chosen statement is not a block",
621 
623  }
624  else {
626  }
627  PrevComm[0] = '\0';
628  iPrevComm = 0;
629  }
630 
631  pc = CONS(STATEMENT, s, NULL);
632 
633  if (BlockStack[CurrentBlock-1].c == NULL) {
635  }
636  else {
637  CDR(BlockStack[CurrentBlock-1].c) = pc;
638  }
639  BlockStack[CurrentBlock-1].c = pc;
640 
641  /* while i is the last instruction of the current block ... */
642  while (BlockStack[CurrentBlock-1].l != NULL &&
643  strcmp(label_local_name(l), BlockStack[CurrentBlock-1].l) == 0)
644  PopBlock();
645 
646  pips_debug(8, "End for instruction %s with label \"%s\"\n",
648 }
void user_log(const char *format,...)
Definition: message.c:234
stack BlockStack
Attention, the null statement in C is represented as the continue statement in Fortran (make_continue...
Definition: statement.c:58
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
bool statement_loop_p(statement s)
Definition: statement.c:349
bool continue_statement_p(statement s)
Test if a statement is a CONTINUE, that is the FORTRAN nop, the ";" in C or the "pass" in Python....
Definition: statement.c:203
string instruction_identification(instruction i)
Return a constant string representing symbolically the instruction type.
Definition: instruction.c:284
#define pips_internal_error
Definition: misc-local.h:149
char * PrevComm
Definition: reader.c:152
int iPrevComm
Definition: reader.c:153
#define instruction_block_p(i)
#define instruction_block(i)
#define empty_comments
Empty comments (i.e.
bool entity_empty_label_p(entity e)
Definition: entity.c:666
#define statement_comments(x)
Definition: ri.h:2456
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
char * strdup()
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
char lab_I[6]
Definition: parser.c:69
void reset_current_label_string()
Definition: parser.c:71
statement MakeStatement(entity l, instruction i)
This function makes a statement.
Definition: statement.c:431
bool IsBlockStackEmpty()
Definition: statement.c:209
entity MakeLabel(char *s) const
This functions creates a label.
Definition: statement.c:257
instruction PopBlock()
Definition: statement.c:238

References BlockStack, CAR, CDR, CONS, continue_statement_p(), CurrentBlock, empty_comments, ENDP, entity_empty_label_p(), instruction_block, instruction_block_p, instruction_identification(), iPrevComm, IsBlockStackEmpty(), lab_I, label_local_name(), MakeLabel(), MakeStatement(), ParserError(), pips_assert, pips_debug, pips_internal_error, PopBlock(), PrevComm, reset_current_label_string(), STATEMENT, statement_comments, statement_instruction, statement_loop_p(), statement_undefined, strdup(), and user_log().

Referenced by EndOfProcedure(), GenerateReturn(), MakeBlockIfInst(), MakeDoInst(), MakeElseInst(), MakeEnddoInst(), MakeEndifInst(), and MakeWhileDoInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_check_io_statement()

statement make_check_io_statement ( string  n,
expression  u,
entity  l 
)

Generate a test to jump to l if flag f is TRUE Used to implement control effects of IO's due to ERR= and END=.

Should not use MakeStatement() directly or indirectly to avoid counting these pseudo-instructions

Definition at line 1691 of file statement.c.

1692 {
1700 
1701  statement_consistent_p(check);
1702 
1703  return check;
1704 }
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
bool statement_consistent_p(statement p)
Definition: ri.c:2195
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
statement instruction_to_statement(instruction instr)
Build a statement from a give instruction.
Definition: statement.c:597
statement make_empty_block_statement()
Build an empty statement (block/sequence)
Definition: statement.c:625
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define IO_EFFECTS_PACKAGE_NAME
Implicit variables to handle IO effetcs.
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
expression reference_to_expression(reference r)
Definition: expression.c:196
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
@ is_instruction_test
Definition: ri.h:1470
instruction make_goto_instruction(entity l)
In a "go to" instruction, the label does not appear explictly.
Definition: statement.c:706

References CONS, EXPRESSION, FindEntity(), instruction_to_statement(), IO_EFFECTS_PACKAGE_NAME, is_instruction_test, make_empty_block_statement(), make_goto_instruction(), make_instruction(), make_reference(), make_test(), NIL, reference_to_expression(), and statement_consistent_p().

Referenced by MakeIoInstA().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_goto_instruction()

instruction make_goto_instruction ( entity  l)

In a "go to" instruction, the label does not appear explictly.

It is replaced by the statement to be jumped at. If the statement carrying the label has been encountered before, everything is fine. Else the target statement has to be synthesized blindly ahead of time.

Definition at line 706 of file statement.c.

707 {
710 
711  if (s == statement_undefined) {
712  s = make_statement(l,
716  instruction_undefined, NIL, NULL,
718  NewStmt(l, s);
719  }
720 
722 
723  return g;
724 }
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
synchronization make_synchronization_none(void)
Definition: ri.c:2424
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
#define STATEMENT_NUMBER_UNDEFINED
default values
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
@ is_instruction_goto
Definition: ri.h:1473
#define entity_name(x)
Definition: ri.h:2790
statement LabelToStmt(string l)
this functions looks up in table StmtHeap for the statement s whose label is l.
Definition: statement.c:94
void NewStmt(entity e, statement s)
this function stores a new association in table StmtHeap: the label of statement s is e.
Definition: statement.c:141

References empty_comments, empty_extensions(), entity_name, instruction_undefined, is_instruction_goto, LabelToStmt(), make_instruction(), make_statement(), make_synchronization_none(), NewStmt(), NIL, STATEMENT_NUMBER_UNDEFINED, STATEMENT_ORDERING_UNDEFINED, and statement_undefined.

Referenced by make_check_io_statement(), and MakeGotoInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeArithmIfInst()

instruction MakeArithmIfInst ( expression  e,
string  l1,
string  l2,
string  l3 
)

this function transforms an arithmetic if statement into a set of regular tests.

long but easy to understand without comments.

e is the test expression. e is inserted in the instruction returned (beware of sharing)

l1, l2, l3 are the three labels of the original if statement.

  IF (E) 10, 20, 30

becomes

  IF (E .LT. 0) THEN
     GOTO 10
  ELSE
     IF (E .EQ. 0) THEN
        GOTO 20
     ELSE
        GOTO 30
     ENDIF
  ENDIF

FI: Should be improved by testing equality between l1, l2 and l3 Cases observed: l1 == l2 l2 == l3 l1 == l3 Plus, just in case, l1==l2==l3

This must be quite unusual, but the variables in e have to be dereferenced to respect the use-def chains, e may have side effects,...

If the optimizer is very good, the absolute value of e should be checked positive?

General case

Parameters
l11
l22
l33

Definition at line 1399 of file statement.c.

1402 {
1403  expression e1, e2;
1404  statement s1, s2, s3, s;
1406 
1407  /* FI: Should be improved by testing equality between l1, l2 and l3
1408  * Cases observed:
1409  * l1 == l2
1410  * l2 == l3
1411  * l1 == l3
1412  * Plus, just in case, l1==l2==l3
1413  */
1414 
1415  if(strcmp(l1,l2)==0) {
1416  if(strcmp(l2,l3)==0) {
1417  /* This must be quite unusual, but the variables in e have to be dereferenced
1418  * to respect the use-def chains, e may have side effects,...
1419  *
1420  * If the optimizer is very good, the absolute value of e
1421  * should be checked positive?
1422  */
1423  e1 = MakeUnaryCall(CreateIntrinsic("ABS"), e);
1424  e2 = MakeBinaryCall(CreateIntrinsic(".GE."),
1425  e1, int_to_expression(0));
1426 
1429 
1431  make_test(e2,s1,s2));
1432  }
1433  else {
1434  e1 = MakeBinaryCall(CreateIntrinsic(".LE."),
1435  e, int_to_expression(0));
1436 
1439 
1441  make_test(e1,s1,s3));
1442  }
1443  }
1444  else if(strcmp(l1,l3)==0) {
1445  e1 = MakeBinaryCall(CreateIntrinsic(".EQ."),
1446  e, int_to_expression(0));
1447 
1450 
1452  make_test(e1,s2,s1));
1453  }
1454  else if(strcmp(l2,l3)==0) {
1455  e1 = MakeBinaryCall(CreateIntrinsic(".LT."),
1456  e, int_to_expression(0));
1457 
1460 
1462  make_test(e1,s1,s2));
1463  }
1464  else {
1465  /* General case */
1466  e1 = MakeBinaryCall(CreateIntrinsic(".LT."),
1467  e, int_to_expression(0));
1468  e2 = MakeBinaryCall(CreateIntrinsic(".EQ."),
1470 
1474 
1476  make_test(e2,s2,s3)));
1478 
1480  }
1481 
1482  return ifarith;
1483 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
int get_statement_number()
eturn the line number of the statement being parsed
Definition: reader.c:1392
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
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
#define statement_number(x)
Definition: ri.h:2452
s1
Definition: set.c:247
instruction MakeGotoInst(string n)
this function creates a goto instruction.
Definition: statement.c:686

References copy_expression(), CreateIntrinsic(), get_statement_number(), instruction_to_statement(), instruction_undefined, int_to_expression(), is_instruction_test, make_empty_block_statement(), make_instruction(), make_test(), MakeBinaryCall(), MakeGotoInst(), MakeUnaryCall(), s1, and statement_number.

+ Here is the call graph for this function:

◆ MakeAssignedGotoInst()

instruction MakeAssignedGotoInst ( list  ll,
entity  i 
)
Parameters
lll

Definition at line 734 of file statement.c.

735 {
736  instruction inst;
738 
740 
741  inst = MakeAssignedOrComputedGotoInst(ll, expr, true);
742 
743  return inst;
744 }
void DeclareVariable(entity e, type t, list d, storage s, value v)
void DeclareVariable(e, t, d, s, v): update entity e description as declaration statements are encoun...
Definition: declaration.c:670
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
#define value_undefined
Definition: ri.h:3016
#define type_undefined
Definition: ri.h:2883
#define storage_undefined
Definition: ri.h:2476
instruction MakeAssignedOrComputedGotoInst(list ll, expression ce, bool assigned)
Definition: statement.c:747

References DeclareVariable(), entity_to_expression(), MakeAssignedOrComputedGotoInst(), NIL, storage_undefined, type_undefined, and value_undefined.

+ Here is the call graph for this function:

◆ MakeAssignedOrComputedGotoInst()

instruction MakeAssignedOrComputedGotoInst ( list  ll,
expression  ce,
bool  assigned 
)

ce might have side effects

ce can be used several times without side effects

We cannot know yet if ce has side effects

expression_intrinsic_operation_p(ce): a user call may be hidden at a lower level and some intrinsics may have side effects and it might be more efficient not to recompute a complex expression several times

Prefix starts with I to avoid an explicit declaration and a regeneration of declarations by the prettyprinter.

Assigned GO TO: if the current label is not in the list, this is an error in Fortran 90. ISO/IEC 1539 Section 8.2.4 page 108. Same in Fortran 77 standard, Section 11-2.

Update the statement numbers of all possibly allocated statements

MakeStatement won't increment the current statement number because this is a block... so it has to be done here

FatalError("parser", "computed goto statement prohibited\n");

Parameters
lll
cee
assignedssigned

Definition at line 747 of file statement.c.

748 {
750  list cs = NIL;
751  int l = 0;
752  list cl = list_undefined;
754  syntax sce = expression_syntax(ce);
756 
757  /* ce might have side effects */
758  if(syntax_reference_p(sce)) {
759  /* ce can be used several times without side effects */
760  e = ce;
761  }
762  else if(syntax_call_p(sce)) {
763  if(call_constant_p(syntax_call(sce))) {
764  e = ce;
765  }
766  else {
767  /* We cannot know yet if ce has side effects */
768  /* expression_intrinsic_operation_p(ce): a user call may be hidden
769  at a lower level and some intrinsics may have side effects and
770  it might be more efficient not to recompute a complex
771  expression several times */
772  /* Prefix starts with I to avoid an explicit declaration and a
773  regeneration of declarations by the prettyprinter. */
776  make_basic(is_basic_int, (void*) 4));
778 
779  e = entity_to_expression(tmp);
780  }
781  }
782  else {
783  pips_internal_error("No range expected", false);
784  }
785 
786 
787  for(l = gen_length(ll), cl = ll; !ENDP(cl); l--, POP(cl)) {
788  string ln = STRING(CAR(cl));
789  instruction g = MakeGotoInst(ln);
790  expression cond =
795  entity_domain),
796  copy_expression(e),
797  int_to_expression(assigned? atoi(ln):l));
798  /* Assigned GO TO: if the current label is not in the list, this is an error
799  * in Fortran 90. ISO/IEC 1539 Section 8.2.4 page 108. Same in Fortran 77
800  * standard, Section 11-2.
801  */
802  statement may_stop = (assigned && (cl==ll)) ?
805  :
807  instruction iif =
809  make_test(cond,
811  may_stop));
813 
814  s = instruction_to_statement(iif);
815 
816  /* Update the statement numbers of all possibly allocated statements */
818  if(stop_statement_p(may_stop))
820 
821  cs = CONS(STATEMENT, s, cs);
822  }
823 
825  cs = CONS(STATEMENT, s_init, cs);
826 
827  /* MakeStatement won't increment the current statement number
828  * because this is a block... so it has to be done here
829  */
830  // (void) get_next_statement_number();
831  ins = make_instruction_block(cs);
832 
833  (void) instruction_consistent_p(ins);
834 
835  /* FatalError("parser", "computed goto statement prohibited\n"); */
836 
837  return ins;
838 }
bool instruction_consistent_p(instruction p)
Definition: ri.c:1124
basic make_basic(enum basic_utype tag, void *val)
Definition: ri.c:155
string make_entity_fullname(const char *module_name, const char *local_name)
END_EOLE.
Definition: entity_names.c:230
#define call_constant_p(C)
Definition: flint_check.c:51
#define STRING(x)
Definition: genC.h:87
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
size_t gen_length(const list l)
Definition: list.c:150
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
statement make_assign_statement(expression l, expression r)
Definition: statement.c:583
bool stop_statement_p(statement s)
Test if a statement is a Fortran STOP.
Definition: statement.c:263
static expression s_init
must take care not to substitute in an inserted expression
Definition: macros.c:177
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
#define EQUAL_OPERATOR_NAME
#define STOP_FUNCTION_NAME
#define make_empty_statement
An alias for make_empty_block_statement.
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
@ is_basic_int
Definition: ri.h:571
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_call_p(x)
Definition: ri.h:2734
#define syntax_call(x)
Definition: ri.h:2736
#define statement_undefined_p(x)
Definition: ri.h:2420
#define expression_syntax(x)
Definition: ri.h:1247
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
instruction MakeZeroOrOneArgCallInst(char *s, expression e)
this function creates a simple Fortran statement such as RETURN, CONTINUE, ...
Definition: statement.c:669

References call_constant_p, CAR, CONS, copy_expression(), ENDP, entity_domain, entity_to_expression(), EQUAL_OPERATOR_NAME, expression_syntax, expression_undefined, gen_find_tabulated(), gen_length(), get_current_module_entity(), get_statement_number(), instruction_consistent_p(), instruction_to_statement(), instruction_undefined, int_to_expression(), is_basic_int, is_instruction_test, list_undefined, make_assign_statement(), make_basic(), make_empty_statement, make_entity_fullname(), make_instruction(), make_instruction_block(), make_new_scalar_variable_with_prefix(), make_test(), MakeBinaryCall(), MakeGotoInst(), MakeZeroOrOneArgCallInst(), NIL, pips_internal_error, POP, s_init, STATEMENT, statement_number, statement_undefined, statement_undefined_p, STOP_FUNCTION_NAME, stop_statement_p(), STRING, syntax_call, syntax_call_p, syntax_reference_p, and TOP_LEVEL_MODULE_NAME.

Referenced by MakeAssignedGotoInst(), and MakeComputedGotoInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeAssignInst()

instruction MakeAssignInst ( syntax  l,
expression  e 
)

this function creates an affectation statement.

l is a reference (the left hand side).

e is an expression (the right hand side).

Let us keep the statement function definition somewhere.

Preserve the current comments as well as the information about the macro substitution

FI: we stumble here when a Fortran macro is used.

FI: we stumble here when a Fortran PARAMETER is used as lhs.

Definition at line 848 of file statement.c.

849 {
852 
853  if(syntax_reference_p(l)) {
855  i = make_assign_instruction(lhs, e);
856  }
857  else
858  {
859  if(syntax_call_p(l) &&
862  {
863  list lexpr = CONS(EXPRESSION, e, NIL);
864  list asub = call_arguments(syntax_call(l));
865 
867  free_syntax(l);
868 
871  gen_append(asub, lexpr)));
872  }
873  else
874  {
875  if (syntax_call_p(l) &&
877  {
878  if (get_bool_property("PARSER_EXPAND_STATEMENT_FUNCTIONS"))
879  {
880  /* Let us keep the statement function definition somewhere.
881  */
882  /* Preserve the current comments as well as the information
883  about the macro substitution */
886 
887  pips_debug(5, "considering %s as a macro\n",
889 
891  statement_comments(stmt2) =
892  strdup(concatenate("C$PIPS STATEMENT FUNCTION ",
894  " SUBSTITUTED\n", 0));
896  CONS(STATEMENT, stmt2, NIL)));
897  }
898  else
899  {
900  /* FI: we stumble here when a Fortran macro is used. */
901  user_warning("MakeAssignInst", "%s() appears as lhs\n",
903  ParserError("MakeAssignInst",
904  "bad lhs (function call or undeclared array)"
905  " or PIPS unsupported Fortran macro\n"
906  "you might consider switching the "
907  "PARSER_EXPAND_STATEMENT_FUNCTIONS property,\n"
908  "in the latter, at your own risk...\n");
909  }
910  }
911  else {
912  if(syntax_call_p(l)) {
913  /* FI: we stumble here when a Fortran PARAMETER is used as lhs. */
914  user_warning("MakeAssignInst", "PARAMETER %s appears as lhs\n",
916  ParserError("MakeAssignInst",
917  "Illegal lhs\n");
918  }
919  else {
920  FatalError("MakeAssignInst", "Unexpected syntax tag\n");
921  }
922  }
923  }
924  }
925 
926  return i;
927 }
call make_call(entity a1, list a2)
Definition: ri.c:269
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
void free_syntax(syntax p)
Definition: ri.c:2445
instruction make_assign_instruction(expression l, expression r)
Definition: instruction.c:87
list gen_append(list l1, const list l2)
Definition: list.c:471
statement make_continue_statement(entity l)
Definition: statement.c:953
void parser_add_a_macro(call c, expression e)
Definition: macros.c:113
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define SUBSTRING_FUNCTION_NAME
#define ASSIGN_SUBSTRING_FUNCTION_NAME
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 entity_empty_label(void)
Definition: entity.c:1105
#define normalized_undefined
Definition: ri.h:1745
#define call_function(x)
Definition: ri.h:709
@ is_instruction_call
Definition: ri.h:1474
#define value_symbolic_p(x)
Definition: ri.h:3068
#define call_arguments(x)
Definition: ri.h:711
#define entity_initial(x)
Definition: ri.h:2796
#define FatalError(f, m)
Definition: syntax-local.h:56

References ASSIGN_SUBSTRING_FUNCTION_NAME, call_arguments, call_function, concatenate(), CONS, entity_empty_label(), entity_initial, entity_intrinsic(), entity_local_name(), entity_name, EXPRESSION, expression_undefined, FatalError, free_syntax(), gen_append(), get_bool_property(), instruction_undefined, is_instruction_call, make_assign_instruction(), make_call(), make_continue_statement(), make_expression(), make_instruction(), make_instruction_block(), NIL, normalized_undefined, parser_add_a_macro(), ParserError(), pips_debug, STATEMENT, statement_comments, strdup(), SUBSTRING_FUNCTION_NAME, syntax_call, syntax_call_p, syntax_reference_p, user_warning, and value_symbolic_p.

+ Here is the call graph for this function:

◆ MakeBlockIfInst()

void MakeBlockIfInst ( expression  e,
int  elsif 
)

this function and the two next ones create a block if statement.

the true and the else part of the test are two empty blocks. e is the test expression.

the true block is pushed on the stack. it will contain the next statements, and will end with a else statement or an endif statement.

if a else statement is reached, the true block is popped and the false block is pushed to gather the false part statements. if no else statement is found, the true block will be popped with the endif statement and the false block will remain empty.

Parameters
elsiflsif

Definition at line 1498 of file statement.c.

1501 {
1502  instruction bt, bf, i;
1503  expression cond = fix_if_condition(e);
1504 
1507 
1509  make_test(cond,
1510  MakeStatement(MakeLabel(""), bt),
1511  MakeStatement(MakeLabel(""), bf)));
1512 
1513  LinkInstToCurrentBlock(i, true);
1514 
1515  PushBlock(bt, "ELSE");
1516  BlockStack[CurrentBlock-1].elsifs = elsif ;
1517 }
void PushBlock(instruction i, string l)
Definition: statement.c:221
instruction MakeEmptyInstructionBlock()
this function creates an empty block
Definition: statement.c:654
expression fix_if_condition(expression e)
Definition: statement.c:1293
void LinkInstToCurrentBlock(instruction i, bool number_it)
this function links the instruction i to the current block of statements.
Definition: statement.c:529

References BlockStack, CurrentBlock, fix_if_condition(), is_instruction_test, LinkInstToCurrentBlock(), make_instruction(), make_test(), MakeEmptyInstructionBlock(), MakeLabel(), MakeStatement(), and PushBlock().

+ Here is the call graph for this function:

◆ MakeCallInst()

instruction MakeCallInst ( entity  e,
cons l 
)

this function creates a call statement.

e is the called function. l is the argument list, a list of expressions.

ParserError("MakeCallInst", "Formal functional parameters are not supported " "by PIPS.\n");

FI: Before you can proceed to update_functional_type_result(), you may have to fix the type of e. Basically, if its type is not functional, it should be made functional with result void. I do not fix the problem in the parser because tons of other problems are going to appear, at least one for each PIPS analysis, starting with effects, proper, cumulated, regions, transformers, preconditions,... No quick fix, but a special effort made after an explicit decision.

The following assertion is no longer true when fucntions are passed as actual arguments.

pips_assert("e itself is returned", MakeExternalFunction(e, MakeTypeVoid()) == e);

Parameters
lcallee list of actual parameters

Definition at line 1091 of file statement.c.

1095 {
1097  list ar = get_alternate_returns();
1098  list ap = add_actual_return_code(l);
1099  storage s = entity_storage(e);
1100  bool ffp_p = false;
1101  entity fe = e;
1102 
1103  if(!storage_undefined_p(s)) {
1104  if(storage_formal_p(s)) {
1105  ffp_p = true;
1106  pips_user_warning("entity %s is a formal functional parameter\n",
1107  entity_name(e));
1108  /* ParserError("MakeCallInst",
1109  "Formal functional parameters are not supported "
1110  "by PIPS.\n"); */
1111  /* FI: Before you can proceed to
1112  update_functional_type_result(), you may have to fix
1113  the type of e. Basically, if its type is not
1114  functional, it should be made functional with result
1115  void. I do not fix the problem in the parser because
1116  tons of other problems are going to appear, at least
1117  one for each PIPS analysis, starting with effects,
1118  proper, cumulated, regions, transformers,
1119  preconditions,... No quick fix, but a special effort
1120  made after an explicit decision. */
1121  }
1122  }
1123 
1124  if(!ffp_p) {
1126 
1127  /* The following assertion is no longer true when fucntions are
1128  passed as actual arguments. */
1129  /* pips_assert("e itself is returned",
1130  MakeExternalFunction(e, MakeTypeVoid()) == e); */
1132  }
1133 
1136 
1137  if(!ENDP(ar)) {
1140 
1142  pips_assert("Alternate return substitution required\n", SubstituteAlternateReturnsP());
1144  pips_assert("Must be a sequence", instruction_block_p(i));
1146  s,
1147  instruction_block(i));
1148  }
1149  else {
1151  }
1152 
1153  return i;
1154 }
type make_type(enum type_utype tag, void *val)
Definition: ri.c:2706
#define UU
Definition: newgen_types.h:98
entity MakeExternalFunction(entity e, type r)
Definition: procedure.c:2372
void update_called_modules(entity e)
Definition: procedure.c:308
type MakeTypeVoid(void)
Definition: type.c:102
#define storage_formal_p(x)
Definition: ri.h:2522
#define entity_storage(x)
Definition: ri.h:2794
@ is_type_void
Definition: ri.h:2904
#define storage_undefined_p(x)
Definition: ri.h:2477
bool SubstituteAlternateReturnsP()
Definition: return.c:81
list add_actual_return_code(list apl)
Definition: return.c:222
instruction generate_return_code_checks(list labels)
Definition: return.c:337
list get_alternate_returns()
Definition: return.c:258
void update_functional_type_with_actual_arguments(entity e, list l)
Definition: statement.c:971
void update_functional_type_result(entity f, type nt)
Update of the type returned by function f.
Definition: statement.c:932

References add_actual_return_code(), CONS, ENDP, entity_name, entity_storage, generate_return_code_checks(), get_alternate_returns(), get_statement_number(), instruction_block, instruction_block_p, instruction_to_statement(), instruction_undefined, is_instruction_call, is_type_void, make_call(), make_instruction(), make_type(), MakeExternalFunction(), MakeTypeVoid(), pips_assert, pips_user_warning, STATEMENT, statement_number, storage_formal_p, storage_undefined_p, SubstituteAlternateReturnsP(), update_called_modules(), update_functional_type_result(), update_functional_type_with_actual_arguments(), and UU.

+ Here is the call graph for this function:

◆ MakeComputedGotoInst()

instruction MakeComputedGotoInst ( list  ll,
expression  e 
)
Parameters
lll

Definition at line 727 of file statement.c.

728 {
729  instruction inst = MakeAssignedOrComputedGotoInst(ll, e, false);
730 
731  return inst;
732 }

References MakeAssignedOrComputedGotoInst().

Referenced by generate_return_code_checks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeDoInst()

void MakeDoInst ( syntax  s,
range  r,
string  l 
)

this function creates a do loop statement.

s is a reference to the do variable.

r is the range of the do loop.

l is the label of the last statement of the loop.

This free is not nice for the caller! Nor for the debugger.

Let's build a sequence with loop range assignments

Definition at line 1167 of file statement.c.

1171 {
1172  instruction ido, instblock_do;
1173  statement stmt_do;
1174  entity dovar, dolab;
1175 
1176  if (!syntax_reference_p(s))
1177  FatalError("MakeDoInst", "function call as DO variable\n");
1178 
1179  if (reference_indices(syntax_reference(s)) != NULL)
1180  FatalError("MakeDoInst", "variable reference as DO variable\n");
1181 
1184  /* This free is not nice for the caller! Nor for the debugger. */
1185  free_syntax(s);
1186 
1187  dolab = MakeLabel((strcmp(l, "BLOCKDO") == 0) ? "" : l);
1188 
1189  instblock_do = MakeEmptyInstructionBlock();
1190  stmt_do = instruction_to_statement(instblock_do);
1191 
1192  if(get_bool_property("PARSER_LINEARIZE_LOOP_BOUNDS")) {
1196 
1199  make_loop(dovar, r, stmt_do, dolab,
1201  UU),
1202  NIL));
1203  }
1204  else {
1205  /* Let's build a sequence with loop range assignments */
1207  make_loop(dovar, r, stmt_do, dolab,
1209  UU),
1210  NIL));
1212 
1213  if(!normalized_linear_p(ni)) {
1216  make_basic(is_basic_int, (void*) 4));
1220  }
1221 
1222  if(!normalized_linear_p(nu)) {
1225  make_basic(is_basic_int, (void*) 4));
1229  }
1230 
1231  if(!normalized_linear_p(nl)) {
1234  make_basic(is_basic_int, (void*) 4));
1238  }
1239  ido = make_instruction_block(a);
1240  }
1241  }
1242  else {
1244  make_loop(dovar, r, stmt_do, dolab,
1246  UU),
1247  NIL));
1248  }
1249 
1250  LinkInstToCurrentBlock(ido, true);
1251 
1252  PushBlock(instblock_do, l);
1253 }
execution make_execution(enum execution_utype tag, void *val)
Definition: ri.c:838
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
#define NORMALIZE_EXPRESSION(e)
#define syntax_reference(x)
Definition: ri.h:2730
#define normalized_linear_p(x)
Definition: ri.h:1779
#define reference_variable(x)
Definition: ri.h:2326
#define range_upper(x)
Definition: ri.h:2290
#define range_increment(x)
Definition: ri.h:2292
#define entity_undefined
Definition: ri.h:2761
@ is_instruction_loop
Definition: ri.h:1471
#define reference_indices(x)
Definition: ri.h:2328
#define range_lower(x)
Definition: ri.h:2288
@ is_execution_sequential
Definition: ri.h:1189

References CONS, entity_to_expression(), entity_undefined, FatalError, free_syntax(), get_bool_property(), get_current_module_entity(), instruction_to_statement(), is_basic_int, is_execution_sequential, is_instruction_loop, LinkInstToCurrentBlock(), make_assign_instruction(), make_basic(), make_execution(), make_instruction(), make_instruction_block(), make_loop(), make_new_scalar_variable_with_prefix(), MakeEmptyInstructionBlock(), MakeLabel(), NIL, NORMALIZE_EXPRESSION, normalized_linear_p, PushBlock(), range_increment, range_lower, range_upper, reference_indices, reference_variable, STATEMENT, syntax_reference, syntax_reference_p, and UU.

+ Here is the call graph for this function:

◆ MakeElseInst()

int MakeElseInst ( bool  is_else_p)

This function is used to handle either an ELSE or an ELSEIF construct.

No open block can be closed by this ELSE

Generate a CONTINUE to carry the comments but not the label because the ELSE is not represented in the IR and cannot carry comments. The ELSEIF is transformed into an IF which can carry comments and label but the prettyprint of structured code is nicer if the comments are carried by a CONTINUE in the previous block. Of course, this is not good for unstructured code since comments end up far from their intended target or attached to a dead CONTINUE if the previous block ends up with a GO TO.

The current label is temporarily hidden.

generate a CONTINUE to carry the label because the ELSE is not represented in the IR

Parameters
is_else_ps_else_p

Definition at line 1522 of file statement.c.

1523 {
1524  statement if_stmt;
1525  test if_test;
1526  int elsifs;
1527  bool has_comments_p = (iPrevComm != 0);
1528 
1529  if(CurrentBlock==0) {
1530  /* No open block can be closed by this ELSE */
1531  ParserError("MakeElseInst", "unexpected ELSE statement\n");
1532  }
1533 
1534  elsifs = BlockStack[CurrentBlock-1].elsifs ;
1535 
1536  if (strcmp("ELSE", BlockStack[CurrentBlock-1].l))
1537  ParserError("MakeElseInst", "block if statement badly nested\n");
1538 
1539  if (has_comments_p) {
1540  /* Generate a CONTINUE to carry the comments but not the label
1541  because the ELSE is not represented in the IR and cannot carry
1542  comments. The ELSEIF is transformed into an IF which can carry
1543  comments and label but the prettyprint of structured code is
1544  nicer if the comments are carried by a CONTINUE in the previous
1545  block. Of course, this is not good for unstructured code since
1546  comments end up far from their intended target or attached to
1547  a dead CONTINUE if the previous block ends up with a GO TO.
1548 
1549  The current label is temporarily hidden. */
1550  string ln = strdup(get_current_label_string());
1554  free(ln);
1555  }
1556 
1557  (void) PopBlock();
1558 
1559  if_stmt = STATEMENT(CAR(BlockStack[CurrentBlock-1].c));
1560 
1561  if (! instruction_test_p(statement_instruction(if_stmt)))
1562  FatalError("MakeElseInst", "no block if statement\n");
1563 
1564  if_test = instruction_test(statement_instruction(if_stmt));
1565 
1566  PushBlock(statement_instruction(test_false(if_test)), "ENDIF");
1567 
1568  if (is_else_p && !empty_current_label_string_p()) {
1569  /* generate a CONTINUE to carry the label because the ELSE is not
1570  represented in the IR */
1572  }
1573 
1574  return( BlockStack[CurrentBlock-1].elsifs = elsifs ) ;
1575 }
void free(void *)
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
#define test_false(x)
Definition: ri.h:2837
#define instruction_test_p(x)
Definition: ri.h:1515
#define instruction_test(x)
Definition: ri.h:1517
void set_current_label_string(string ln)
Definition: parser.c:81
string get_current_label_string()
Definition: parser.c:76
bool empty_current_label_string_p()
Definition: parser.c:87

References BlockStack, CAR, CurrentBlock, empty_current_label_string_p(), FatalError, free(), get_current_label_string(), instruction_test, instruction_test_p, iPrevComm, LinkInstToCurrentBlock(), make_continue_instruction(), ParserError(), PopBlock(), PushBlock(), reset_current_label_string(), set_current_label_string(), STATEMENT, statement_instruction, strdup(), and test_false.

Referenced by MakeEndifInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeEmptyInstructionBlock()

instruction MakeEmptyInstructionBlock ( void  )

this function creates an empty block

Definition at line 654 of file statement.c.

655 {
656  return(make_instruction_block(NIL));
657 }

References make_instruction_block(), and NIL.

Referenced by MakeBlockIfInst(), MakeCurrentFunction(), MakeDoInst(), and MakeWhileDoInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeEnddoInst()

void MakeEnddoInst ( void  )

inkInstToCurrentBlock(MakeZeroOrOneArgCallInst("ENDDO", expression_undefined));

Although it is not really an instruction, the ENDDO statement may carry comments and be labelled when closing a DO label structure.

An unlabelled ENDDO can only close one loop. This cannot be performed by LinkInstToCurrentBlock().

Definition at line 1611 of file statement.c.

1612 {
1613  if(CurrentBlock<=1) {
1614  ParserError("MakeEnddoInst", "Unexpected ENDDO statement\n");
1615  }
1616 
1617  if (strcmp("BLOCKDO", BlockStack[CurrentBlock-1].l)
1618  &&strcmp(lab_I, BlockStack[CurrentBlock-1].l))
1619  ParserError("MakeEnddoInst", "block do statement badly nested\n");
1620 
1621  /*LinkInstToCurrentBlock(MakeZeroOrOneArgCallInst("ENDDO",
1622  expression_undefined));*/
1623  /* Although it is not really an instruction, the ENDDO statement may
1624  * carry comments and be labelled when closing a DO label structure.
1625  */
1627 
1628  /* An unlabelled ENDDO can only close one loop. This cannot be
1629  * performed by LinkInstToCurrentBlock().
1630  */
1631  if (strcmp("BLOCKDO", BlockStack[CurrentBlock-1].l)==0)
1632  (void) PopBlock();
1633 }

References BlockStack, CurrentBlock, lab_I, LinkInstToCurrentBlock(), make_continue_instruction(), ParserError(), and PopBlock().

+ Here is the call graph for this function:

◆ MakeEndifInst()

void MakeEndifInst ( void  )

generate a CONTINUE to carry the comments

Definition at line 1578 of file statement.c.

1579 {
1580  int elsifs = -1;
1581 
1582  if(CurrentBlock==0) {
1583  ParserError("MakeEndifInst", "unexpected ENDIF statement\n");
1584  }
1585 
1586  if (iPrevComm != 0) {
1587  /* generate a CONTINUE to carry the comments */
1589  }
1590 
1591  if (BlockStack[CurrentBlock-1].l != NULL &&
1592  strcmp("ELSE", BlockStack[CurrentBlock-1].l) == 0) {
1593  elsifs = MakeElseInst(true);
1595  }
1596  if (BlockStack[CurrentBlock-1].l == NULL ||
1597  strcmp("ENDIF", BlockStack[CurrentBlock-1].l)) {
1598  ParserError("MakeEndifInst", "block if statement badly nested\n");
1599  }
1600  else {
1601  elsifs = BlockStack[CurrentBlock-1].elsifs ;
1602  }
1603  pips_assert( "MakeEndifInst", elsifs >= 0 ) ;
1604 
1605  do {
1606  (void) PopBlock();
1607  } while( elsifs-- != 0 ) ;
1608 }
int MakeElseInst(bool is_else_p)
This function is used to handle either an ELSE or an ELSEIF construct.
Definition: statement.c:1522

References BlockStack, CurrentBlock, iPrevComm, LinkInstToCurrentBlock(), make_continue_instruction(), MakeElseInst(), ParserError(), pips_assert, and PopBlock().

+ Here is the call graph for this function:

◆ MakeGotoInst()

instruction MakeGotoInst ( string  n)

this function creates a goto instruction.

n is the target label.

Definition at line 686 of file statement.c.

688 {
691 
692  l = MakeLabel(n);
693 
694  i = make_goto_instruction(l);
695 
696  return i;
697 }

References entity_undefined, instruction_undefined, make_goto_instruction(), and MakeLabel().

Referenced by MakeArithmIfInst(), MakeAssignedOrComputedGotoInst(), and MakeReturn().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeIoInstA()

instruction MakeIoInstA ( int  keyword,
list  lci,
list  lio 
)

this function creates an IO statement.

keyword indicates which io statement is to be built (READ, WRITE, ...).

lci is a list of 'control specifications'. its has the following format:

    ("UNIT=", 6, "FMT=", "*", "RECL=", 80, "ERR=", 20)

lio is the list of expressions to write or references to read.

The composite IO with potential branches for ERR and END

The pure io itself

virtual tests to implement ERR= and END= clauses

we scan the list of specifications to detect labels (such as in ERR=20, END=30, FMT=50, etc.), that were stored as integer constants (20, 30, 50) and that must be replaced by labels (_20, _30, _50).

here is a label

UNIT is not defined for INQUIRE (et least) Let's use LUN 0 by default for END et ERR.

Parameters
keywordeyword
lcici
lioio

Definition at line 1715 of file statement.c.

1716 {
1717  cons *l;
1718  /* The composite IO with potential branches for ERR and END */
1720  /* The pure io itself */
1722  /* virtual tests to implement ERR= and END= clauses */
1723  statement io_err = statement_undefined;
1724  statement io_end = statement_undefined;
1726 
1727  for (l = lci; l != NULL; l = CDR(CDR(l))) {
1728  syntax s1;
1729  entity e1;
1730 
1732 
1733  e1 = call_function(syntax_call(s1));
1734 
1735  if (strcmp(entity_local_name(e1), "UNIT=") == 0) {
1736  if( ! expression_undefined_p(unit) )
1738  unit = EXPRESSION(CAR(CDR(l)));
1739  }
1740  }
1741 
1742  /* we scan the list of specifications to detect labels (such as in
1743  ERR=20, END=30, FMT=50, etc.), that were stored as integer constants
1744  (20, 30, 50) and that must be replaced by labels (_20, _30, _50). */
1745  for (l = lci; l != NULL; l = CDR(CDR(l))) {
1746  syntax s1, s2;
1747  entity e1, e2;
1748 
1750  s2 = expression_syntax(EXPRESSION(CAR(CDR(l))));
1751 
1752  pips_assert("syntax is a call", syntax_call_p(s1));
1753  e1 = call_function(syntax_call(s1));
1754  pips_assert("value is constant", value_constant_p(entity_initial(e1)));
1755  pips_assert("constant is not int (thus litteral or call)",
1757 
1758  if (strcmp(entity_local_name(e1), "ERR=") == 0 ||
1759  strcmp(entity_local_name(e1), "END=") == 0 ||
1760  strcmp(entity_local_name(e1), "FMT=") == 0) {
1761  if (syntax_call_p(s2)) {
1762  e2 = call_function(syntax_call(s2));
1763  if (value_constant_p(entity_initial(e2))) {
1765  /* here is a label */
1766  call_function(syntax_call(s2)) =
1768  }
1769  }
1770  e2 = call_function(syntax_call(s2));
1771  if (strcmp(entity_local_name(e1), "FMT=") != 0
1773  /* UNIT is not defined for INQUIRE (et least)
1774  * Let's use LUN 0 by default for END et ERR.
1775  */
1776  unit = int_to_expression(0);
1777  }
1778  if (strcmp(entity_local_name(e1), "ERR=") == 0) {
1780  }
1781  else if (strcmp(entity_local_name(e1), "END=") == 0) {
1783  }
1784  else {
1785  //free_expression(unit);
1786  ;
1787  }
1788  }
1789  }
1790  }
1791 
1792  /*
1793  for (l = lci; CDR(l) != NULL; l = CDR(l)) ;
1794 
1795  CDR(l) = lio;
1796  l = lci;
1797  */
1798 
1799  lci = gen_nconc(lci, lio);
1800 
1803  lci));
1804 
1805  if(statement_undefined_p(io_err) && statement_undefined_p(io_end)) {
1806  io = io_call;
1807  }
1808  else {
1809  list ls = NIL;
1810  if(!statement_undefined_p(io_err)) {
1811  ls = CONS(STATEMENT, io_err, ls);
1812  }
1813  if(!statement_undefined_p(io_end)) {
1814  ls = CONS(STATEMENT, io_end, ls);
1815  }
1816  ls = CONS(STATEMENT, MakeStatement(entity_empty_label(), io_call), ls);
1819  }
1820 
1821  return io;
1822 }
void free_expression(expression p)
Definition: ri.c:853
sequence make_sequence(list a)
Definition: ri.c:2125
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
int unit
UNIT.
Definition: newgen_types.h:97
#define IO_EOF_ARRAY_NAME
array of end of file codes
#define IO_ERROR_ARRAY_NAME
array of error codes for LUNs
#define value_constant(x)
Definition: ri.h:3073
#define value_constant_p(x)
Definition: ri.h:3071
#define constant_int_p(x)
Definition: ri.h:848
@ is_instruction_sequence
Definition: ri.h:1469
#define expression_undefined_p(x)
Definition: ri.h:1224
statement make_check_io_statement(string n, expression u, entity l)
Generate a test to jump to l if flag f is TRUE Used to implement control effects of IO's due to ERR= ...
Definition: statement.c:1691
string NameOfToken(int token)
Definition: statement.c:1636

References call_function, CAR, CDR, CONS, constant_int_p, CreateIntrinsic(), entity_empty_label(), entity_initial, entity_local_name(), EXPRESSION, expression_syntax, expression_undefined, expression_undefined_p, free_expression(), gen_nconc(), instruction_consistent_p(), instruction_undefined, int_to_expression(), IO_EOF_ARRAY_NAME, IO_ERROR_ARRAY_NAME, is_instruction_call, is_instruction_sequence, make_call(), make_check_io_statement(), make_instruction(), make_sequence(), MakeLabel(), MakeStatement(), NameOfToken(), NIL, pips_assert, s1, STATEMENT, statement_undefined, statement_undefined_p, syntax_call, syntax_call_p, value_constant, and value_constant_p.

Referenced by MakeSimpleIoInst1().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeIoInstB()

instruction MakeIoInstB ( int  keyword,
expression  e1,
expression  e2,
expression  e3,
expression  e4 
)

this function creates a BUFFER IN or BUFFER OUT io statement.

this is not ansi fortran.

e1 is the logical unit.

nobody known the exact meaning of e2

e3 et e4 are references that indicate which variable elements are to be buffered in or out.

Parameters
keywordeyword
e11
e22
e33
e44

Definition at line 1837 of file statement.c.

1840 {
1841  cons * l;
1842 
1843  l = CONS(EXPRESSION, e1,
1844  CONS(EXPRESSION, e2,
1845  CONS(EXPRESSION, e3,
1846  CONS(EXPRESSION, e4, NULL))));
1847 
1850  l)));
1851 }

References CONS, CreateIntrinsic(), EXPRESSION, is_instruction_call, make_call(), make_instruction(), and NameOfToken().

+ Here is the call graph for this function:

◆ MakeLabel()

entity MakeLabel ( char*  s) const

This functions creates a label.

LABEL_PREFIX is added to its name, for integer constants and labels not to have the same name space.

If an empty string is passed, the empty label seems to be returned since EMPTY_LABEL_NAME is defined as LABEL_PREFIX in ri-util-local.h (FI, 5 March 1998)

Definition at line 257 of file statement.c.

259 {
260  entity l;
261  static char *name = NULL ;
262 
263  if( name == NULL ) {
264  name = (char *)malloc( LABEL_SIZE+sizeof(LABEL_PREFIX) ) ;
265  }
266  debug(5, "MakeLabel", "\"%s\"\n", s);
267 
268  strcpy(name, LABEL_PREFIX);
269  strcat(name, s);
270 
271  l = FindOrCreateEntity( (strcmp( name, LABEL_PREFIX )==0) ?
273  CurrentPackage, name);
274 
275  if (entity_type(l) == type_undefined) {
276  debug(5, "MakeLabel", "%s\n", name);
281  }
282  else {
283  debug(5, "MakeLabel", "%s already exists\n", name);
284  }
285  return(l);
286 }
storage make_storage_rom(void)
Definition: ri.c:2285
value make_value(enum value_utype tag, void *val)
Definition: ri.c:2832
constant make_constant_litteral(void)
Definition: ri.c:418
#define LABEL_PREFIX
Definition: naming-local.h:31
#define LABEL_SIZE
constant sizes
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
type MakeTypeStatement(void)
Definition: type.c:92
@ is_value_constant
Definition: ri.h:3033
#define entity_type(x)
Definition: ri.h:2792
const char * CurrentPackage
the name of the current package, i.e.
Definition: parser.c:58

References CurrentPackage, debug(), entity_initial, entity_storage, entity_type, FindOrCreateEntity(), is_value_constant, LABEL_PREFIX, LABEL_SIZE, make_constant_litteral(), make_storage_rom(), make_value(), MakeTypeStatement(), malloc(), TOP_LEVEL_MODULE_NAME, and type_undefined.

Referenced by add_alternate_return(), GenerateReturn(), LinkInstToCurrentBlock(), MakeBlockIfInst(), MakeDoInst(), MakeGotoInst(), MakeIoInstA(), MakeReturn(), and MakeWhileDoInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeLogicalIfInst()

instruction MakeLogicalIfInst ( expression  e,
instruction  i 
)

this function creates a logical if statement.

the true part of the test is a block with only one instruction (i), and the false part is an empty block.

Modifications:

  • there is no need for a block in the true branch, any statement can do
  • there is no need for a CONTINUE statement in the false branch, an empty block is plenty
  • MakeStatement() cannot be used for the true and false branches because it disturbs the statement numering

It is not easy to number bt because Yacc reduction order does not help...

Instruction i should not be a block, unless:

  • an alternate return
  • a computed GO TO
  • an assigned GO TO has been desugared.

If the logical IF is labelled, the label has been stolen by the first statement in the block. This shows that label should only be affected by MakeStatement and not by desugaring routines.

statement first = STATEMENT(CAR(l));

Only the alternate return case assert: pips_assert("Block of two instructions or call with return code checks", (gen_length(l)==2 && assignment_statement_p(first)) || (statement_call_p(first)) );

Definition at line 1329 of file statement.c.

1332 {
1333  /* It is not easy to number bt because Yacc reduction order does not help... */
1336  expression cond = fix_if_condition(e);
1338  make_test(cond, bt, bf));
1339 
1340  if (i == instruction_undefined)
1341  FatalError("MakeLogicalIfInst", "bad instruction\n");
1342 
1343  /* Instruction i should not be a block, unless:
1344  * - an alternate return
1345  * - a computed GO TO
1346  * - an assigned GO TO
1347  * has been desugared.
1348  *
1349  * If the logical IF is labelled, the label has been stolen by the
1350  * first statement in the block. This shows that label should only
1351  * be affected by MakeStatement and not by desugaring routines.
1352  */
1353  if(instruction_block_p(i)) {
1354  list l = instruction_block(i);
1355  /* statement first = STATEMENT(CAR(l)); */
1356  /* Only the alternate return case assert:
1357  pips_assert("Block of two instructions or call with return code checks",
1358  (gen_length(l)==2 && assignment_statement_p(first))
1359  ||
1360  (statement_call_p(first))
1361  );
1362  */
1363  MAP(STATEMENT, s, {
1365  }, l);
1366  }
1367  else {
1369  }
1370 
1371  return ti;
1372 }
#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

References FatalError, fix_if_condition(), get_statement_number(), instruction_block, instruction_block_p, instruction_to_statement(), instruction_undefined, is_instruction_test, make_empty_block_statement(), make_instruction(), make_test(), MAP, STATEMENT, and statement_number.

+ Here is the call graph for this function:

◆ MakeNewLabelledStatement()

statement MakeNewLabelledStatement ( entity  l,
instruction  i 
)

Associate label to the first statement in the block because block cannot be labelled.

Definition at line 289 of file statement.c.

292 {
293  statement s;
294 
295  debug(9, "MakeNewLabelledStatement", "begin for label \"%s\" and instruction %s\n",
297 
298  if(instruction_loop_p(i) && get_bool_property("PARSER_SIMPLIFY_LABELLED_LOOPS")) {
301 
302  statement_number(ls) = get_statement_number();//get_next_statement_number();
303  NewStmt(l, c);
305  CONS(STATEMENT, ls, NIL)));
306  }
307  else if(instruction_block_p(i)) {
308  /* Associate label to the first statement in the block because
309  * block cannot be labelled.
310  */
312 
313  statement_label(s1) = l;
314  NewStmt(l, s1);
320  }
321  else {
322  s = make_statement(l,
323  (instruction_goto_p(i))?
324  STATEMENT_NUMBER_UNDEFINED : get_statement_number(),//get_next_statement_number(),
328  NewStmt(l, s);
329  }
330 
331  debug(9, "MakeNewLabelledStatement", "end for label \"%s\"\n",
332  label_local_name(l));
333 
334  return s;
335 }
statement make_block_statement(list body)
Make a block statement from a list of statement.
Definition: statement.c:616
#define instruction_loop_p(x)
Definition: ri.h:1518
#define instruction_goto_p(x)
Definition: ri.h:1524

References CAR, CONS, debug(), empty_comments, empty_extensions(), entity_empty_label(), get_bool_property(), get_statement_number(), instruction_block, instruction_block_p, instruction_goto_p, instruction_identification(), instruction_loop_p, instruction_to_statement(), label_local_name(), make_block_statement(), make_continue_statement(), make_statement(), make_synchronization_none(), NewStmt(), NIL, s1, STATEMENT, statement_label, statement_number, STATEMENT_NUMBER_UNDEFINED, and STATEMENT_ORDERING_UNDEFINED.

Referenced by MakeStatement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeSimpleIoInst1()

instruction MakeSimpleIoInst1 ( int  keyword,
expression  unit 
)

Functionally PRINT is a special case of WRITE

Parameters
keywordeyword

Definition at line 1854 of file statement.c.

1855 {
1857  expression std, format, unite;
1858  cons * lci;
1859 
1860  switch(keyword) {
1861  case TK_READ:
1862  case TK_PRINT:
1865  unite = MakeCharacterConstantExpression("UNIT=");
1866  format = MakeCharacterConstantExpression("FMT=");
1867 
1868  lci = CONS(EXPRESSION, unite,
1869  CONS(EXPRESSION, std,
1870  CONS(EXPRESSION, format,
1871  CONS(EXPRESSION, unit, NULL))));
1872  /* Functionally PRINT is a special case of WRITE */
1873  inst = MakeIoInstA((keyword==TK_PRINT)?TK_WRITE:TK_READ,
1874  lci, NIL);
1875  break;
1876  case TK_WRITE:
1877  case TK_OPEN:
1878  case TK_CLOSE:
1879  case TK_INQUIRE:
1880  ParserError("Syntax",
1881  "Illegal syntax in IO statement, "
1882  "Parentheses and arguments required");
1883  break;
1884  case TK_BACKSPACE:
1885  case TK_REWIND:
1886  case TK_ENDFILE:
1887  unite = MakeCharacterConstantExpression("UNIT=");
1888  lci = CONS(EXPRESSION, unite,
1889  CONS(EXPRESSION, unit, NULL));
1890  inst = MakeIoInstA(keyword, lci, NIL);
1891  break;
1892  default:
1893  ParserError("Syntax","Unexpected token in IO statement");
1894  }
1895  return inst;
1896 }
expression MakeCharacterConstantExpression(string s)
END_EOLE.
Definition: constant.c:573
#define LIST_DIRECTED_FORMAT_NAME
Definition: naming-local.h:97
expression MakeNullaryCall(entity f)
Creates a call expression to a function with zero arguments.
Definition: expression.c:331
#define TK_CLOSE
Definition: syn_yacc.c:289
#define TK_ENDFILE
Definition: syn_yacc.c:301
#define TK_BACKSPACE
Definition: syn_yacc.c:282
#define TK_WRITE
Definition: syn_yacc.c:337
#define TK_REWIND
Definition: syn_yacc.c:329
#define TK_OPEN
Definition: syn_yacc.c:320
#define TK_PRINT
Definition: syn_yacc.c:324
#define TK_READ
Definition: syn_yacc.c:326
#define TK_INQUIRE
Definition: syn_yacc.c:315
instruction MakeIoInstA(int keyword, list lci, list lio)
this function creates an IO statement.
Definition: statement.c:1715

References CONS, CreateIntrinsic(), EXPRESSION, instruction_undefined, LIST_DIRECTED_FORMAT_NAME, MakeCharacterConstantExpression(), MakeIoInstA(), MakeNullaryCall(), NIL, ParserError(), TK_BACKSPACE, TK_CLOSE, TK_ENDFILE, TK_INQUIRE, TK_OPEN, TK_PRINT, TK_READ, TK_REWIND, and TK_WRITE.

+ Here is the call graph for this function:

◆ MakeSimpleIoInst2()

instruction MakeSimpleIoInst2 ( int  keyword,
expression  f,
list  io_list 
)
Parameters
keywordeyword
io_listo_list

Definition at line 1899 of file statement.c.

1900 {
1902  //expression std, format, unite;
1903  //list cil;
1904 
1905  switch(keyword) {
1906  case TK_READ:
1907  inst = make_simple_Fortran_io_instruction(true, f, io_list);
1908  break;
1909  case TK_PRINT:
1910  inst = make_simple_Fortran_io_instruction(false, f, io_list);
1911  break;
1912  case TK_WRITE:
1913  case TK_OPEN:
1914  case TK_CLOSE:
1915  case TK_INQUIRE:
1916  case TK_BACKSPACE:
1917  case TK_REWIND:
1918  case TK_ENDFILE:
1919  ParserError("Syntax",
1920  "Illegal syntax in IO statement, Parentheses are required");
1921  break;
1922  default:
1923  ParserError("Syntax","Unexpected token in IO statement");
1924  }
1925  return inst;
1926 }
instruction make_simple_Fortran_io_instruction(bool is_read_p, expression f, list io_list)
Derived from the Fortran parser code.
Definition: statement.c:807
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15

References f(), instruction_undefined, make_simple_Fortran_io_instruction(), ParserError(), TK_BACKSPACE, TK_CLOSE, TK_ENDFILE, TK_INQUIRE, TK_OPEN, TK_PRINT, TK_READ, TK_REWIND, and TK_WRITE.

Referenced by make_print_statement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeStatement()

statement MakeStatement ( entity  l,
instruction  i 
)

This function makes a statement.

l is the label and i the instruction. We make sure that the label is not declared twice.

Comments are added by LinkInstToCurrentBlock() which calls MakeStatement() because it links the instruction by linking its statement..

GO TO statements are numbered like other statements although they are destroyed by the controlizer. To be changed.

There is an actual label

Well, there is no easy solution to handle labels when Fortran constructs such as alternate returns, computed gotos and assigned gotos are desugared because they may be part of a logical IF, unknowingly.

FI, PJ: the "rice" phase does not handle labels on DO like 100 in: 100 DO 200 I = 1, N

This should be trapped by "rice" when loops are checked to see if Allen/Kennedy's algorithm is applicable

There is not forward reference to the this label. A new statement can be safely allocated.

A forward reference has been encountered and the corresponding statement has been allocated and has been referenced by at least one go to statement.

The CONTINUE slot can be re-used. It is likely to be an artificial CONTINUE added to carry a comment. Maybe it would be better to manage lab_I in a more consistent way by resetting it as soon as it is used. But I did not find the reset!

}

No actual label, no problem

Definition at line 431 of file statement.c.

434 {
435  statement s;
436 
437  debug(5, "MakeStatement", "Begin for label %s and instruction %s\n",
439 
440  pips_assert("MakeStatement", type_statement_p(entity_type(l)));
441  pips_assert("MakeStatement", storage_rom_p(entity_storage(l)));
442  pips_assert("MakeStatement", value_constant_p(entity_initial(l)));
443  pips_assert("MakeStatement",
445 
446  if (!entity_empty_label_p(l)) {
447  /* There is an actual label */
448 
449  /* Well, there is no easy solution to handle labels when Fortran
450  * constructs such as alternate returns, computed gotos and
451  * assigned gotos are desugared because they may be part of a
452  * logical IF, unknowingly.
453  */
454  /*
455  if (instruction_block_p(i))
456  ParserError("makeStatement", "a block must have no label\n");
457  */
458 
459  /* FI, PJ: the "rice" phase does not handle labels on DO like 100 in:
460  * 100 DO 200 I = 1, N
461  *
462  * This should be trapped by "rice" when loops are checked to see
463  * if Allen/Kennedy's algorithm is applicable
464  */
465  if (instruction_loop_p(i)) {
466  if(!get_bool_property("PARSER_SIMPLIFY_LABELLED_LOOPS")) {
467  user_warning("MakeStatement",
468  "DO loop reachable by GO TO via label %s "
469  "cannot be parallelized by PIPS\n",
470  entity_local_name(l));
471  }
472  }
473 
474  if ((s = LabelToStmt(entity_name(l))) == statement_undefined) {
475  /* There is not forward reference to the this label. A new statement
476  * can be safely allocated.
477  */
478  s = MakeNewLabelledStatement(l,i);
479  }
480  else {
481  /* A forward reference has been encountered and the corresponding
482  * statement has been allocated and has been referenced by at least
483  * one go to statement.
484  */
485 
487  /* The CONTINUE slot can be re-used. It is likely to
488  be an artificial CONTINUE added to carry a
489  comment. Maybe it would be better to manage lab_I in a
490  more consistent way by resetting it as soon as it is
491  used. But I did not find the reset! */
492  /*
493  if(statement_continue_p(s)) {
494  free_instruction(statement_instruction(s));
495  statement_instruction(s) = instruction_undefined;
496  statement_number(s) = STATEMENT_NUMBER_UNDEFINED;
497  }
498  else {
499  */
500  user_warning("MakeStatement", "Label %s may be used twice\n",
501  entity_local_name(l));
502  ParserError("MakeStatement", "Same label used twice\n");
503  /* } */
504  }
505  s = ReuseLabelledStatement(s, i);
506  }
507  }
508  else {
509  /* No actual label, no problem */
510  s = make_statement(l,
512  STATEMENT_NUMBER_UNDEFINED : get_statement_number(), //get_next_statement_number(),
516  }
517 
518  return(s);
519 }
#define type_statement_p(x)
Definition: ri.h:2941
#define constant_litteral_p(x)
Definition: ri.h:857
#define storage_rom_p(x)
Definition: ri.h:2525
statement ReuseLabelledStatement(statement s, instruction i)
Definition: statement.c:338
statement MakeNewLabelledStatement(entity l, instruction i)
Definition: statement.c:289

References constant_litteral_p, debug(), empty_comments, empty_extensions(), entity_empty_label_p(), entity_initial, entity_local_name(), entity_name, entity_storage, entity_type, get_bool_property(), get_statement_number(), instruction_block_p, instruction_goto_p, instruction_identification(), instruction_loop_p, instruction_undefined, LabelToStmt(), make_statement(), make_synchronization_none(), MakeNewLabelledStatement(), NIL, ParserError(), pips_assert, ReuseLabelledStatement(), statement_instruction, STATEMENT_NUMBER_UNDEFINED, STATEMENT_ORDERING_UNDEFINED, statement_undefined, storage_rom_p, type_statement_p, user_warning, value_constant, and value_constant_p.

Referenced by GenerateReturn(), LinkInstToCurrentBlock(), MakeBlockIfInst(), and MakeIoInstA().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeWhileDoInst()

void MakeWhileDoInst ( expression  c,
string  l 
)

This function creates a while do loop statement.

c is the loop condition l is the label of the last statement of the loop.

with the f77 compiler, this is equivalent to c.NE.0

Definition at line 1262 of file statement.c.

1263 {
1264  instruction iwdo, instblock_do;
1265  statement stmt_do;
1266  entity dolab;
1268 
1269  if(!logical_expression_p(c)) {
1270  /* with the f77 compiler, this is equivalent to c.NE.0*/
1272  c, int_to_expression(0));
1273  pips_user_warning("WHILE condition between lines %d and %d is not a logical expression.\n",
1274  line_b_I,line_e_I);
1275  }
1276  else {
1277  cond = c;
1278  }
1279 
1280  dolab = MakeLabel((strcmp(l, "BLOCKDO") == 0) ? "" : l);
1281 
1282  instblock_do = MakeEmptyInstructionBlock();
1283  stmt_do = instruction_to_statement(instblock_do);
1284 
1286  make_whileloop(cond, stmt_do, dolab,make_evaluation_before()));
1287 
1288  LinkInstToCurrentBlock(iwdo, true);
1289 
1290  PushBlock(instblock_do, l);
1291 }
evaluation make_evaluation_before(void)
Definition: ri.c:786
whileloop make_whileloop(expression a1, statement a2, entity a3, evaluation a4)
Definition: ri.c:2937
@ is_instruction_whileloop
Definition: ri.h:1472

References entity_intrinsic(), expression_undefined, instruction_to_statement(), int_to_expression(), is_instruction_whileloop, line_b_I, line_e_I, LinkInstToCurrentBlock(), logical_expression_p(), make_evaluation_before(), make_instruction(), make_whileloop(), MakeBinaryCall(), MakeEmptyInstructionBlock(), MakeLabel(), NON_EQUAL_OPERATOR_NAME, pips_user_warning, and PushBlock().

+ Here is the call graph for this function:

◆ MakeZeroOrOneArgCallInst()

instruction MakeZeroOrOneArgCallInst ( char *  s,
expression  e 
)

this function creates a simple Fortran statement such as RETURN, CONTINUE, ...

s is the name of the intrinsic function.

e is one optional argument (might be equal to expression_undefined).

la liste d'arguments

Definition at line 669 of file statement.c.

672 {
673  cons *l; /* la liste d'arguments */
674 
675  l = (e == expression_undefined) ? NIL : CONS(EXPRESSION, e, NIL);
676 
678  make_call(CreateIntrinsic(s), l)));
679 }

References CONS, CreateIntrinsic(), EXPRESSION, expression_undefined, is_instruction_call, make_call(), make_instruction(), and NIL.

Referenced by GenerateReturn(), gfc2pips_code2instruction__TOP(), MakeAssignedOrComputedGotoInst(), and MakeReturn().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ NameOfToken()

string NameOfToken ( int  token)

just to avoid a gcc warning

Parameters
tokenoken

Definition at line 1636 of file statement.c.

1638 {
1639  string name;
1640 
1641  switch (token) {
1642  case TK_BUFFERIN:
1643  name = "BUFFERIN";
1644  break;
1645  case TK_BUFFEROUT:
1646  name = "BUFFEROUT";
1647  break;
1648  case TK_INQUIRE:
1649  name = "INQUIRE";
1650  break;
1651  case TK_OPEN:
1652  name = "OPEN";
1653  break;
1654  case TK_CLOSE:
1655  name = "CLOSE";
1656  break;
1657  case TK_PRINT:
1658  name = "PRINT";
1659  break;
1660  case TK_READ:
1661  name = "READ";
1662  break;
1663  case TK_REWIND:
1664  name = "REWIND";
1665  break;
1666  case TK_WRITE:
1667  name = "WRITE";
1668  break;
1669  case TK_ENDFILE:
1670  name = "ENDFILE";
1671  break;
1672  case TK_BACKSPACE:
1673  name = "BACKSPACE";
1674  break;
1675  default:
1676  FatalError("NameOfToken", "unknown token\n");
1677  name = string_undefined; /* just to avoid a gcc warning */
1678  break;
1679  }
1680 
1681  return(name);
1682 }
#define string_undefined
Definition: newgen_types.h:40
#define TK_BUFFEROUT
Definition: syn_yacc.c:286
#define TK_BUFFERIN
Definition: syn_yacc.c:285

References FatalError, string_undefined, TK_BACKSPACE, TK_BUFFERIN, TK_BUFFEROUT, TK_CLOSE, TK_ENDFILE, TK_INQUIRE, TK_OPEN, TK_PRINT, TK_READ, TK_REWIND, and TK_WRITE.

Referenced by MakeIoInstA(), and MakeIoInstB().

+ Here is the caller graph for this function:

◆ NewStmt()

void NewStmt ( entity  e,
statement  s 
)

this function stores a new association in table StmtHeap: the label of statement s is e.

Definition at line 141 of file statement.c.

144 {
146 
147  pips_assert("The empty label is not associated to a statement",
149 
150  pips_assert("Label e is the label of statement s", e==statement_label(s));
151 
153  user_log("NewStmt: duplicate label: %s\n", entity_name(e));
154  ParserError("NewStmt", "duplicate label\n");
155  }
156 
159 
162  CurrentStmt += 1;
163 }
string l
Definition: statement.c:55
static void init_StmtHeap_buffer(void)
Definition: statement.c:64
static void resize_StmtHeap_buffer(void)
Definition: statement.c:74

References CurrentStmt, entity_empty_label_p(), entity_name, init_StmtHeap_buffer(), stmt::l, LabelToStmt(), ParserError(), pips_assert, resize_StmtHeap_buffer(), stmt::s, statement_label, statement_undefined, StmtHeap_buffer, StmtHeap_buffer_size, and user_log().

Referenced by make_goto_instruction(), and MakeNewLabelledStatement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parser_reset_StmtHeap_buffer()

void parser_reset_StmtHeap_buffer ( void  )

statement.c

Definition at line 85 of file statement.c.

86 {
87  CurrentStmt = 0;
88 }

References CurrentStmt.

Referenced by ParserError().

+ Here is the caller graph for this function:

◆ PopBlock()

instruction PopBlock ( void  )

Definition at line 238 of file statement.c.

239 {
240  if (IsBlockStackEmpty())
241  ParserError("PopBlock", "bottom of stack reached\n");
242 
243  return(BlockStack[--CurrentBlock].i);
244 }

References BlockStack, CurrentBlock, IsBlockStackEmpty(), and ParserError().

Referenced by EndOfProcedure(), LinkInstToCurrentBlock(), MakeElseInst(), MakeEnddoInst(), and MakeEndifInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PushBlock()

void PushBlock ( instruction  i,
string  l 
)

Definition at line 221 of file statement.c.

224 {
225  if (IsBlockStackFull())
226  ParserError("PushBlock", "top of stack reached\n");
227 
228  pips_assert("PushBlock", instruction_block_p(i));
229 
230  BlockStack[CurrentBlock].i = i;
231  BlockStack[CurrentBlock].l = l;
232  BlockStack[CurrentBlock].c = NULL;
233  BlockStack[CurrentBlock].elsifs = 0;
234  CurrentBlock += 1;
235 }
bool IsBlockStackFull()
Definition: statement.c:215

References BlockStack, CurrentBlock, instruction_block_p, IsBlockStackFull(), ParserError(), and pips_assert.

Referenced by MakeBlockIfInst(), MakeCurrentFunction(), MakeDoInst(), MakeElseInst(), and MakeWhileDoInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reset_first_statement()

void reset_first_statement ( void  )

Definition at line 1944 of file statement.c.

1945 {
1946  seen = false;
1947  format_seen = false;
1948  declaration_lines = -1;
1949 }

References declaration_lines, format_seen, and seen.

◆ ResetBlockStack()

void ResetBlockStack ( void  )

Definition at line 203 of file statement.c.

204 {
205  CurrentBlock = 0;
206 }

References CurrentBlock.

Referenced by AbortOfProcedure(), and ParserError().

+ Here is the caller graph for this function:

◆ resize_StmtHeap_buffer()

static void resize_StmtHeap_buffer ( void  )
static

Definition at line 74 of file statement.c.

75 {
76  pips_debug(9, "resizing StmtHeap buffer\n");
77  pips_assert("buffer initialized", StmtHeap_buffer_size>0);
79  StmtHeap_buffer = (stmt*) realloc(StmtHeap_buffer,
80  sizeof(stmt)*StmtHeap_buffer_size);
81  pips_assert("realloc ok", StmtHeap_buffer);
82 }

References pips_assert, pips_debug, StmtHeap_buffer, and StmtHeap_buffer_size.

Referenced by NewStmt().

+ Here is the caller graph for this function:

◆ ReuseLabelledStatement()

statement ReuseLabelledStatement ( statement  s,
instruction  i 
)

Comments probably are lost...

Here, you are in trouble because the label cannot be carried by the block. It should be carried by the first statement of the block... which has already been allocated. This only should occur with desugared constructs because they must bypass the MakeStatement() module to handle statement numbering properly.

Reuse s1, the first statement of the block, to contain the whole block. Reuse s to contain the first instruction of the block.

s only has got a label

statement_number(s) = (instruction_goto_p(i))? STATEMENT_NUMBER_UNDEFINED : get_next_statement_number();

Let's number labelled GOTO because a CONTINUE is derived later from them

Definition at line 338 of file statement.c.

341 {
343 
344  debug(9, "ReuseLabelledStatement", "begin for label \"%s\"\n",
346 
347  pips_assert("Should have no number",
349  pips_assert("The statement instruction should be undefined",
351 
352  if(instruction_loop_p(i) && get_bool_property("PARSER_SIMPLIFY_LABELLED_LOOPS")) {
353  /* Comments probably are lost... */
356 
357  statement_number(ls) = get_statement_number();//get_next_statement_number();
358  statement_instruction(s) = c;
359 
360  new_s = instruction_to_statement(
363  CONS(STATEMENT, ls, NIL)))));
364  }
365  else if(instruction_block_p(i)) {
366  /* Here, you are in trouble because the label cannot be carried
367  * by the block. It should be carried by the first statement of
368  * the block... which has already been allocated.
369  * This only should occur with desugared constructs because they
370  * must bypass the MakeStatement() module to handle statement
371  * numbering properly.
372  *
373  * Reuse s1, the first statement of the block, to contain the
374  * whole block. Reuse s to contain the first instruction of the
375  * block.
376  */
378 
379  pips_assert("The first statement of the block is not a block",
381 
382  /* s only has got a label */
387 
393 
395  CDR(instruction_block(i)));
396 
397  pips_assert("The first statement of block s1 must be s\n",
399  == s);
400 
401  new_s = s1;
402  }
403  else {
404  statement_instruction(s) = i;
405  /*
406  statement_number(s) = (instruction_goto_p(i))?
407  STATEMENT_NUMBER_UNDEFINED : get_next_statement_number();
408  */
409  /* Let's number labelled GOTO because a CONTINUE is derived later from them */
410  statement_number(s) = get_statement_number(); //get_next_statement_number();
411  new_s = s;
412  }
413 
414  debug(9, "ReuseLabelledStatement", "end for label \"%s\"\n",
416 
417  return new_s;
418 }
#define statement_block_p(stat)
#define statement_ordering(x)
Definition: ri.h:2454
#define instruction_undefined_p(x)
Definition: ri.h:1455

References CAR, CDR, CONS, debug(), empty_comments, entity_empty_label(), get_bool_property(), get_statement_number(), instruction_block, instruction_block_p, instruction_loop_p, instruction_to_statement(), instruction_undefined_p, is_instruction_sequence, label_local_name(), make_continue_instruction(), make_instruction(), make_sequence(), NIL, pips_assert, s1, STATEMENT, statement_block_p, statement_comments, statement_instruction, statement_label, statement_number, STATEMENT_NUMBER_UNDEFINED, statement_ordering, STATEMENT_ORDERING_UNDEFINED, and statement_undefined.

Referenced by MakeStatement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_first_format_statement()

void set_first_format_statement ( void  )

declaration_lines = line_b_I-1;

Definition at line 1952 of file statement.c.

1953 {
1954  if(!format_seen && !seen) {
1955  format_seen = true;
1956  /* declaration_lines = line_b_I-1; */
1957  debug(8, "set_first_format_statement", "line_b_C=%d, line_b_I=%d\n",
1958  line_b_C, line_b_I);
1960  }
1961 }

References debug(), declaration_lines, format_seen, line_b_C, line_b_I, seen, and UNDEF.

+ Here is the call graph for this function:

◆ update_functional_type_result()

void update_functional_type_result ( entity  f,
type  nt 
)

Update of the type returned by function f.

nt must be a freshly allocated object. It is included in f's data structure

The function is probably a formal parameter, its type is wrong. The return type is either void if it is called by CALL or its current implicit type.

Parameters
ntt

Definition at line 932 of file statement.c.

933 {
934  type ft = entity_type(f);
935  type rt = type_undefined;
936 
937  //pips_assert("function type is functional", type_functional_p(ft));
938  if(!type_functional_p(ft)) {
939  /* The function is probably a formal parameter, its type is
940  wrong. The return type is either void if it is called by CALL
941  or its current implicit type. */
943  pips_user_warning("Variable \"%s\" is a formal functional parameter\n",
945  ParserError(__FUNCTION__,
946  "Formal functional parameters are not yet supported\n");
947  }
948  else {
949  pips_internal_error("Unexpected case");
950  }
951  }
952  else {
954  }
955 
956  pips_assert("result type is variable or unkown or void or undefined",
957  type_undefined_p(rt)
958  || type_unknown_p(rt)
959  || type_void_p(rt)
960  || type_variable_p(rt));
961 
962  pips_assert("new result type is variable or void",
963  type_void_p(nt)
964  ||type_variable_p(nt));
965 
966  free_type(rt);
968 }
void free_type(type p)
Definition: ri.c:2658
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
#define type_functional_p(x)
Definition: ri.h:2950
#define functional_result(x)
Definition: ri.h:1444
#define type_unknown_p(x)
Definition: ri.h:2956
#define type_functional(x)
Definition: ri.h:2952
#define type_undefined_p(x)
Definition: ri.h:2884
#define type_void_p(x)
Definition: ri.h:2959
#define type_variable_p(x)
Definition: ri.h:2947

References entity_storage, entity_type, entity_user_name(), f(), free_type(), functional_result, ParserError(), pips_assert, pips_internal_error, pips_user_warning, storage_formal_p, type_functional, type_functional_p, type_undefined, type_undefined_p, type_unknown_p, type_variable_p, and type_void_p.

Referenced by MakeCallInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_functional_type_with_actual_arguments()

void update_functional_type_with_actual_arguments ( entity  e,
list  l 
)

OK, it is not safe: may be it's a 0-ary function

The pre-existing typing of e should match the new one

parameter p = parameter_undefined;

OK

the actual parameter list must be exhausted

as well as the type parameter list

unless the last type in the parameter list is a varargs

Definition at line 971 of file statement.c.

972 {
973  list pc = list_undefined;
974  list pc2 = list_undefined;
975  type t = type_undefined;
977 
978  pips_assert("update_functional_type_with_actual_arguments", !type_undefined_p(entity_type(e)));
979  t = entity_type(e);
980  pips_assert("update_functional_type_with_actual_arguments", type_functional_p(t));
981  ft = type_functional(t);
982 
983 
984  if( ENDP(functional_parameters(ft))) {
985  /* OK, it is not safe: may be it's a 0-ary function */
986  for (pc = l; pc != NULL; pc = CDR(pc)) {
987  expression ae = EXPRESSION(CAR(pc));
988  type t = type_undefined;
990 
991  if(expression_reference_p(ae)) {
994 
995  if(type_functional_p(tv)) {
996  pips_user_warning("Functional actual argument %s found.\n"
997  "Functional arguments are not yet suported by PIPS\n",
999  }
1000 
1001  t = copy_type(tv);
1002  }
1003  else {
1004  basic b = basic_of_expression(ae);
1005  variable v = make_variable(b, NIL,NIL);
1006  t = make_type(is_type_variable, v);
1007  }
1008 
1009  p = make_parameter(t,
1011  make_dummy_unknown());
1012  functional_parameters(ft) =
1014  CONS(PARAMETER, p, NIL));
1015  }
1016  }
1017  else if(get_bool_property("PARSER_TYPE_CHECK_CALL_SITES")) {
1018  /* The pre-existing typing of e should match the new one */
1019  int i = 0;
1020  bool warning_p = false;
1021 
1022  for (pc = l, pc2 = functional_parameters(ft), i = 1;
1023  !ENDP(pc) && !ENDP(pc2);
1024  POP(pc), i++) {
1025  expression ae = EXPRESSION(CAR(pc));
1026  type at = type_undefined;
1027  type ft = parameter_type(PARAMETER(CAR(pc2)));
1028  type eft = type_varargs_p(ft)? type_varargs(ft) : ft;
1029  /* parameter p = parameter_undefined; */
1030 
1031  if(expression_reference_p(ae)) {
1034 
1035  if(type_functional_p(tv)) {
1036  pips_user_warning("Functional actual argument %s found.\n"
1037  "Functional arguments are not yet suported by PIPS\n",
1039  }
1040 
1041  at = copy_type(tv);
1042  }
1043  else {
1044  basic b = basic_of_expression(ae);
1045  variable v = make_variable(b, NIL,NIL);
1046 
1047  at = make_type(is_type_variable, v);
1048  }
1049 
1050  if((type_variable_p(eft)
1052  || type_equal_p(at, eft)) {
1053  /* OK */
1054  if(!type_varargs_p(ft))
1055  POP(pc2);
1056  }
1057  else {
1058  user_warning("update_functional_type_with_actual_arguments",
1059  "incompatible %d%s actual argument and type in call to %s "
1060  "between lines %d and %d. Current type is not updated\n",
1061  i, nth_suffix(i),
1063  free_type(at);
1064  warning_p = true;
1065  break;
1066  }
1067  free_type(at);
1068  }
1069 
1070  if(!warning_p) {
1071  if(!(ENDP(pc) /* the actual parameter list must be exhausted */
1072  && (ENDP(pc2) /* as well as the type parameter list */
1073  || (ENDP(CDR(pc2)) /* unless the last type in the parameter list is a varargs */
1074  && type_varargs_p(parameter_type(PARAMETER(CAR(pc2)))))))) {
1075  user_warning("update_functional_type_with_actual_arguments",
1076  "inconsistent arg. list lengths for %s:\n"
1077  " %d args according to type and %d actual arguments\n"
1078  "between lines %d and %d. Current type is not updated\n",
1079  module_local_name(e),
1082  }
1083  }
1084  }
1085 }
parameter make_parameter(type a1, mode a2, dummy a3)
Definition: ri.c:1495
type copy_type(type p)
TYPE.
Definition: ri.c:2655
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
dummy make_dummy_unknown(void)
Definition: ri.c:617
string nth_suffix(int)
Definition: string.c:250
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
mode MakeModeReference(void)
Definition: type.c:82
bool type_equal_p(type, type)
Definition: type.c:547
#define parameter_type(x)
Definition: ri.h:1819
#define parameter_undefined
Definition: ri.h:1794
#define type_variable(x)
Definition: ri.h:2949
#define basic_overloaded_p(x)
Definition: ri.h:623
#define type_varargs(x)
Definition: ri.h:2955
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define type_varargs_p(x)
Definition: ri.h:2953
@ is_type_variable
Definition: ri.h:2900
#define functional_undefined
Definition: ri.h:1418
#define variable_basic(x)
Definition: ri.h:3120

References basic_of_expression(), basic_overloaded_p, CAR, CDR, CONS, copy_type(), ENDP, entity_local_name(), entity_type, EXPRESSION, expression_reference(), expression_reference_p(), free_type(), functional_parameters, functional_undefined, gen_length(), gen_nconc(), get_bool_property(), is_type_variable, line_b_I, line_e_I, list_undefined, make_dummy_unknown(), make_parameter(), make_type(), make_variable(), MakeModeReference(), module_local_name(), NIL, nth_suffix(), PARAMETER, parameter_type, parameter_undefined, pips_assert, pips_user_warning, POP, reference_variable, type_equal_p(), type_functional, type_functional_p, type_undefined, type_undefined_p, type_varargs, type_varargs_p, type_variable, type_variable_p, user_warning, and variable_basic.

Referenced by MakeAtom(), and MakeCallInst().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ BlockStack

LOCAL block BlockStack[MAXBLOCK]

statement.c

statement.c

Definition at line 199 of file statement.c.

Referenced by c_parser_error().

◆ CurrentBlock

◆ CurrentStmt

int CurrentStmt = 0
static

◆ declaration_lines

int declaration_lines = -1
static

◆ format_seen

◆ seen

int seen = false
static

Are we in the declaration or in the executable part? Have we seen a FORMAT statement before an executable statement? For more explanation, see check_first_statement() below.

Definition at line 1934 of file statement.c.

Referenced by check_first_statement(), check_in_declarations(), first_executable_statement_seen(), reset_first_statement(), and set_first_format_statement().

◆ StmtHeap_buffer

stmt* StmtHeap_buffer
static

◆ StmtHeap_buffer_size

int StmtHeap_buffer_size
static

Definition at line 60 of file statement.c.

Referenced by init_StmtHeap_buffer(), NewStmt(), and resize_StmtHeap_buffer().