PIPS
util.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "workspace-util.h"
#include "c_parser_private.h"
#include "c_syntax.h"
#include "text-util.h"
#include "prettyprint.h"
#include "cyacc.h"
#include "resources.h"
#include "database.h"
#include "misc.h"
#include "properties.h"
+ Include dependency graph for util.c:

Go to the source code of this file.

Macros

#define FILE_LOCAL_USER_DEFINED_TYPES_P   (true)
 

Functions

void c_parser_user_warning_alist (const char *pips_func, const char *pips_file, const int pips_line, const char *format, va_list *args)
 Compared to pips_user_warning(), the name of the calling function is lost, which does not help maintenance but generates more user-friendly messages. More...
 
void c_parser_user_warning_func (const char *pips_func, const char *pips_file, const int pips_line, const char *format,...)
 
static void set_current_dummy_parameter_number (int n)
 
void reset_current_dummy_parameter_number ()
 
static int get_current_dummy_parameter_number (void)
 
entity get_top_level_entity ()
 
void MakeTopLevelEntity ()
 
void init_c_areas ()
 In C we have 4 areas. More...
 
entity make_C_constant_entity (string name, tag bt, size_t size)
 
void init_c_implicit_variables (entity m)
 
entity get_current_compilation_unit_entity ()
 
void MakeCurrentCompilationUnitEntity (const char *name)
 A compilation unit is also considered as a module. More...
 
void ResetCurrentCompilationUnitEntity (bool is_compilation_unit_parser)
 
expression MakeFunctionExpression (expression e, list le)
 e is now owned by returned expression and must not be used any longer More...
 
expression MemberDerivedIdentifierToExpression (type t, string m)
 
expression MemberIdentifierToExpression (expression e, string m)
 
expression IdentifierToExpression (string s)
 
expression MakeArrayExpression (expression exp, list lexp)
 FI: this function is called for a bracketed comma expression. More...
 
entity FindEntityFromLocalName (string name)
 
entity FindOrCreateEntityFromLocalNameAndPrefix (string name, string prefix, bool is_external)
 
entity FindOrCreateEntityFromLocalNameAndPrefixAndScope (string name, string prefix, string scope, bool is_external)
 
entity FindEntityFromLocalNameAndPrefixAndScope (string name, string prefix, string scope)
 The parameter "scope" is potentially destroyed. More...
 
entity FindEntityFromLocalNameAndPrefix (string name, string prefix)
 
entity CreateEntityFromLocalNameAndPrefix (string name, string prefix, bool is_external)
 
bool CheckExternList ()
 
void c_parser_put_new_typedef (const char *name)
 Store named type for the lexical analyzer, which has to decide if a character string is the name of a type or the name of a variable. More...
 
void put_new_typedef (const char *name)
 This function is used by libraries "step"* and "task_parallelization". More...
 
entity FindOrCreateCurrentEntity (string name, stack ContextStack __attribute__((__unused__)), stack FormalStack, stack FunctionStack, bool is_external)
 This function finds or creates the current entity. More...
 
void UpdateParenEntity (entity e, list lq)
 
dimension MakeDimension (list le, list ql)
 
type UpdateFinalPointer (type pt, type t)
 
void UpdatePointerEntity (entity e, type pt, list lq)
 
void UpdateArrayEntity (entity e, list lq, list le)
 
entity RenameFunctionEntity (entity oe)
 Rename function oe if necessary. More...
 
void UpdateFunctionEntity (entity oe, list la)
 The parser has found out that an entity is a function and partially sets its type. More...
 
type UpdateType (type t1, type t2)
 This function replaces the undefined field in t1 by t2. More...
 
static bool referencenodeclfilter (reference r)
 
static bool callnodeclfilter (call c)
 
static void nodecl_p (entity __attribute__((unused)) module, statement stat)
 
void CCompilationUnitMemoryAllocations (entity module, bool first_p)
 This function allocates the memory to the Current Compilation Unit. More...
 
void CCompilationUnitMemoryAllocation (entity module)
 
void CCompilationUnitMemoryReallocation (entity module)
 
void CModuleMemoryAllocation (entity module)
 This function is for MemoryAllocation for Module of C programs. More...
 
void UseDummyArguments (entity f)
 If f has regular formal parameters, destroy them. More...
 
void UseFormalArguments (entity f)
 If f has dummy formal parameters, replace them by standard formal parameters. More...
 
void RemoveDummyArguments (entity f, list refs)
 To chase formals in type declarations. More...
 
void SubstituteDummyParameters (entity f, list el)
 
void CreateReturnEntity (entity f)
 If necessary, create the return entity, which is a hidden variable used in PIPS internal representation to carry the value returned by a function. More...
 
void UpdateEntity2 (entity f, stack FormalStack __attribute__((__unused__)), stack OffsetStack __attribute__((__unused__)))
 A subset of UpdateEntity, used when the function entity is already more defined because the return type is implicit. More...
 
void UpdateEntity (entity e, stack ContextStack, stack FormalStack, stack FunctionStack, stack OffsetStack, bool is_external, bool is_declaration)
 Update the entity with final type, storage and initial value; and also (sometimes?) declare it at the module level. More...
 
void UpdateEntities (list le, stack ContextStack, stack FormalStack, stack FunctionStack, stack OffsetStack, bool is_external, bool is_declaration)
 
static entity CleanUpEntity (entity e)
 if returned entity != original entity, e must be freed, otherwise an invalid entity is still tabulated More...
 
void CleanUpEntities (list le)
 
void UpdateAbstractEntity (entity e, stack ContextStack)
 
void RemoveFromExterns (entity e)
 
void AddToExterns (entity e, entity mod)
 
void AddToDeclarations (entity e, entity mod)
 FI: check the difference with AddEntityToDeclarations() More...
 
void UpdateDerivedEntity (list ld, entity e, stack ContextStack)
 
list TakeDerivedEntities (list le)
 
void UpdateDerivedEntities (list ld, list le, stack ContextStack)
 
void InitializeEnumMemberValues (list lem)
 
entity MakeDerivedEntity (string name, list members, bool is_external, int i)
 
storage MakeStorageRam (entity v, bool is_external, bool is_static)
 The storage part should not be called twice when reparsing compilation unit. More...
 
string CreateMemberScope (string derived, bool is_external)
 
value MakeEnumeratorInitialValue (list enum_list, int counter)
 
int ComputeAreaOffset (entity a, entity v)
 
list MakeParameterList (list l1, list l2, stack FunctionStack)
 
parameter FindParameterEntity (string s, int offset, list l)
 
void AddToCalledModules (entity e)
 
void NStackPop (stack s, int n)
 Pop n times the stack s. More...
 
void StackPop (stack OffsetStack)
 The OffsetStack is poped n times, where n is the number of formal arguments of the actual function. More...
 
void StackPush (stack OffsetStack)
 The OffsetStack is pushed incrementally. More...
 
void set_entity_initial (entity v, expression nie)
 Be careful if the initial value has already been set. More...
 
bool check_declaration_uniqueness_p (statement s)
 This is designed for standard C functions, not for compilation units. More...
 
list insert_qualifier (list ql, qualifier nq)
 if qualifier "nq" does not already belong to qualifier list "ql", add it in front of the list. More...
 
void reset_preprocessor_line_analysis (void)
 
int analyze_preprocessor_line (string line, int C_line_number)
 Analyze information about user line number provided by the C preprocessor and by PIPS file splitter and return the C line number in the source file. More...
 

Variables

static int current_dummy_parameter_number =0
 The data structure to tackle the memory allocation problem due to reparsing of compilation unit. More...
 
static bool declarationerror_p
 
static bool buffer_initialized_p = false
 

Macro Definition Documentation

◆ FILE_LOCAL_USER_DEFINED_TYPES_P

#define FILE_LOCAL_USER_DEFINED_TYPES_P   (true)

Function Documentation

◆ AddToCalledModules()

void AddToCalledModules ( entity  e)

Definition at line 3413 of file util.c.

3414 {
3415  if (!intrinsic_entity_p(e))
3416  {
3417  bool already_here = false;
3418  //string n = top_level_entity_p(e)?entity_local_name(e):entity_name(e);
3419  const char* n = entity_local_name(e);
3420  MAP(STRING,s,
3421  {
3422  if (strcmp(n, s) == 0)
3423  {
3424  already_here = true;
3425  break;
3426  }
3427  }, CalledModules);
3428 
3429  if (! already_here)
3430  {
3431  pips_debug(2, "Adding %s to list of called modules\n", n);
3433  }
3434  }
3435 }
list CalledModules
Definition: c_parser.c:51
#define STRING(x)
Definition: genC.h:87
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#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
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
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
bool intrinsic_entity_p(entity e)
Definition: entity.c:1272
char * strdup()

References CalledModules, CONS, entity_local_name(), intrinsic_entity_p(), MAP, pips_debug, strdup(), and STRING.

Referenced by MakeFunctionExpression().

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

◆ AddToDeclarations()

void AddToDeclarations ( entity  e,
entity  mod 
)

FI: check the difference with AddEntityToDeclarations()

Here, the declared entity is added to the module declarations only.

Parameters
modod

Definition at line 2924 of file util.c.

2925 {
2927 
2928  if (!gen_in_list_p(e,dl))
2929  {
2930  pips_debug(5,"Add entity \"%s\" (\"%s\") to module %s\n",
2931  entity_user_name(e),
2932  entity_name(e),
2933  entity_user_name(mod));
2936  CONS(ENTITY,e,NIL));
2937  }
2938 }
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
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 ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define code_declarations(x)
Definition: ri.h:784
#define entity_name(x)
Definition: ri.h:2790
#define value_code(x)
Definition: ri.h:3067
#define entity_initial(x)
Definition: ri.h:2796
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References code_declarations, CONS, ENTITY, entity_initial, entity_name, entity_user_name(), gen_in_list_p(), gen_nconc(), NIL, pips_debug, and value_code.

Referenced by CreateReturnEntity(), MakeFunctionExpression(), MakeParameterList(), and UpdateEntity().

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

◆ AddToExterns()

void AddToExterns ( entity  e,
entity  mod 
)
Parameters
modod

Definition at line 2898 of file util.c.

2899 {
2900  // the entity e can be extern variable and extern functions
2902 
2903  pips_assert("le is an entity list", entity_list_p(le));
2904 
2905  if(!gen_in_list_p(e, le))
2906  {
2907  pips_debug(5,"Add entity %s to extern declaration %s \n",
2909  pips_assert("e is an entity", entity_domain_number(e)==entity_domain);
2910  pips_assert("mod is an entity", entity_domain_number(mod)==entity_domain);
2913  CONS(ENTITY,e,NIL));
2914 
2916  pips_assert("le is an entity list", entity_list_p(le));
2917  }
2918 }
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
bool entity_list_p(list el)
Checks that el only contains entity.
Definition: entity.c:1411
#define code_externs(x)
Definition: ri.h:790
#define entity_domain_number(x)
Definition: ri.h:2788
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410

References code_externs, CONS, ENTITY, entity_domain, entity_domain_number, entity_initial, entity_list_p(), entity_user_name(), gen_in_list_p(), gen_nconc(), NIL, pips_assert, pips_debug, and value_code.

Referenced by FindOrCreateCurrentEntity(), and UpdateEntity().

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

◆ analyze_preprocessor_line()

int analyze_preprocessor_line ( string  line,
int  C_line_number 
)

Analyze information about user line number provided by the C preprocessor and by PIPS file splitter and return the C line number in the source file.

We do not have specs and must evolve with C preprocessors such as cpp.

We assume that information about the lines in the included files is only provided for compilation unit.

We assume that information about user line in a module is always related to the user source file, and that the first line has been generated by PIPS file splitter with syntax "x nnn", with no information about the user source file name.

See examples line00.c, line01.c, line02.c and line03.c. And do not forget cominc02 for the compilation unit case. And missing01.c for synthesized code.

More examples needed for include lines placed within a function body, with C code or preprocessor definitions: line04 and line05.

the C preprocessors, such as cpp, and PIPS file splitter provide line information in pragmas which are not line pragmas.

Not too sure about C source code generated by PIPS by passes initializer, clone, outlining, inlinging...

strstr(line, "#line")==line &&

Not to sure about this case

The next lines have been imported from an included file. Ignore information about include files, preserve the current C_line_number.

Not to sure about this case: internal error?

Parameters
lineine
C_line_number_line_number

Definition at line 3617 of file util.c.

3618 {
3619  // In compilation units, ignore information about include files
3620  // Could be used so size "buffer", but not "init_buffer"
3621  // int s = strlen(line);
3622  char buffer[1024];
3623  static char init_buffer[1024];
3624 
3625  pips_debug(9,"Pragma-like comment %s\n",line);
3626 
3627  /* the C preprocessors, such as cpp, and PIPS file splitter provide
3628  * line information in pragmas which are not #line pragmas.
3629  *
3630  * Not too sure about C source code generated by PIPS by passes
3631  * initializer, clone, outlining, inlinging...
3632  */
3633 
3634  if(/* strstr(line, "#line")==line && */ strlen(line)>=4) {
3635  int initial_C_line_number = -1;
3636  int items = sscanf(line+1, "%d %s", &initial_C_line_number, buffer);
3637  if(items==2) {
3638  // if(C_line_number==UNDEFINED_C_LINE_NUMBER) {
3639  //if(C_line_number==FIRST_C_LINE_NUMBER) {
3640  // Local files are named either "./foo.c" or "foo.c"
3641  int skip = 0;
3642  if(buffer[1]=='.' && buffer[2]=='/') {
3643  skip = 2;
3644  buffer[2] = '"';
3645  }
3646  if(!buffer_initialized_p) {
3647  //if(strstr(buffer, ".h"))
3648  //fprintf(stderr, "Abnormal file name %s\n", buffer);
3649  buffer_initialized_p = true;
3650  C_line_number = initial_C_line_number;
3651  C_line_increment = 1;
3652  (void) strcpy(init_buffer, buffer+skip);
3653  }
3654  else if(same_string_p((string) (buffer+skip), (string) init_buffer)) {
3655  C_line_increment = 1;
3657  && C_line_number>initial_C_line_number) {
3658  int d = C_line_number-initial_C_line_number;
3660  C_line_number = initial_C_line_number;
3661  }
3662  else {
3663  /* Not to sure about this case */
3664  C_line_number = initial_C_line_number;
3665  }
3666  }
3667  else {
3668  /* The next lines have been imported from an included file.
3669  * Ignore information about include files, preserve the
3670  * current C_line_number.
3671  */
3672  C_line_increment = 0;
3673  }
3674  }
3675  else if(items==1) {
3676  /* Not to sure about this case: internal error? */
3677  C_line_number = initial_C_line_number;
3678  }
3679  else {
3680  // items==0
3681  pips_user_warning("No line number after a #: \"%s\".\n", line);
3682  CParserError("Ill. formated # pragma.\n");
3683  }
3684  }
3685  return C_line_number;
3686 }
bool compilation_unit_parser_is_running_p
To pass down the information to functions used by the syntactical analyzer.
Definition: c_parser.c:541
void remove_LFs_from_C_comment(int)
Remove "extra_LF" trailing LF from C_current_comment if they can be found at the end of the comment s...
Definition: clexer.c:1398
int C_line_increment
from "clex.l"
Definition: c_syntax.h:296
static bool buffer_initialized_p
Definition: util.c:3590
static int C_line_number
To track the user line number, that is the one in the original user file.
Definition: clexer.c:1102
void CParserError(char *msg)
#define pips_user_warning
Definition: misc-local.h:146
#define same_string_p(s1, s2)
static int line
FLEX_SCANNER.
Definition: scanner.c:852
static string buffer
Definition: string.c:113

References buffer, buffer_initialized_p, C_line_increment, C_line_number, compilation_unit_parser_is_running_p, CParserError(), line, pips_debug, pips_user_warning, remove_LFs_from_C_comment(), and same_string_p.

+ Here is the call graph for this function:

◆ c_parser_put_new_typedef()

void c_parser_put_new_typedef ( const char *  name)

Store named type for the lexical analyzer, which has to decide if a character string is the name of a type or the name of a variable.

See is_c_parser_keyword_typedef() in clex.l

Parameters
nameame

Definition at line 1060 of file util.c.

1061 {
1062  string s = get_c_parser_current_scope();
1063  string sname = string_undefined;
1064  if(same_string_p(s, ""))
1065  sname = strdup(name);
1066  else
1067  sname = strdup(concatenate(name,"%", s, NULL));
1068  hash_put(keyword_typedef_table, sname,(void *) TK_NAMED_TYPE);
1069  pips_debug(5, "Add typedef name %s to hash table\n",sname);
1070 }
string get_c_parser_current_scope(void)
Definition: cyacc.tab.c:569
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define string_undefined
Definition: newgen_types.h:40
hash_table keyword_typedef_table
Because of typedefs, the C lexers need help to decide if a character string such as toto is a type na...
Definition: static.c:253
#define TK_NAMED_TYPE
Definition: splitc.c:760

References concatenate(), get_c_parser_current_scope(), hash_put(), keyword_typedef_table, pips_debug, same_string_p, strdup(), string_undefined, and TK_NAMED_TYPE.

Referenced by FindOrCreateCurrentEntity().

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

◆ c_parser_user_warning_alist()

void c_parser_user_warning_alist ( const char *  pips_func,
const char *  pips_file,
const int  pips_line,
const char *  format,
va_list *  args 
)

Compared to pips_user_warning(), the name of the calling function is lost, which does not help maintenance but generates more user-friendly messages.

util.c

Parser warning on C code synthesized by PIPS

Parameters
pips_funcips_func
pips_fileips_file
pips_lineips_line
formatormat
argsrgs

Definition at line 60 of file util.c.

66 {
67  if (get_bool_property("NO_USER_WARNING"))
68  return;
69 
70  // First and current line number in PIPS preprocessed file (ifn)
72  int fln = get_previous_c_lineno();
73  int uln = c_lineno;
74  string ifn_src = safe_get_line_interval(ifn, fln, uln);
75 
76  // Previous and current line numbers, in user input file (uifn)
77  // ??? string_undefined for pips generated code?
79  int pln = get_previous_C_line_number();
80  int cln = get_current_C_line_number();
81 
82  // Do not print more than 10 lines: the beginning of the user
83  // input C file may be full of includes and comments all
84  // considered related to the first declaration.
85  pips_assert("consistent line numbers", 1 <= pln && pln <= cln);
86  if (pln < cln-9)
87  pln = cln-9;
88 
89  string uifn_src = safe_get_line_interval(uifn, pln, cln);
90 
91  string more;
92 
93  asprintf(&more,
94  "Source code after preprocessing:\n%s"
95  "Input source code, before preprocessing:\n%s",
96  ifn_src, uifn_src);
97 
100  (const string) pips_func, (const string) pips_file, pips_line,
101  NULL, uifn, pln, cln,
102  NULL, more, (const string) format, args);
103 
104  free(more);
105 
106  // else???
107  /* Parser warning on C code synthesized by PIPS */
108  // pips_internal_error("Some synthesized code raises a "
109  // "C parser warning.\n");
110 }
void pips_log_alist(const pips_log_t tag, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string format, va_list *args)
log entry with unprocessed format/alist arguments
Definition: message.c:1200
string get_pips_current_pass_name(void)
Export this piece of information to customize warning functions in passes.
Definition: message.c:77
string get_pips_current_module(void)
Definition: message.c:82
string get_c_parser_current_user_input_file_name()
Definition: c_parser.c:89
string get_c_parser_current_input_file_name()
Definition: c_parser.c:58
int get_previous_c_lineno(void)
Definition: clexer.c:1115
int get_current_C_line_number(void)
Definition: clexer.c:1146
int get_previous_C_line_number(void)
Should be called just before get_current_C_line_number.
Definition: clexer.c:1161
int c_lineno
the file read in by the c_lexer
Definition: c_syntax.h:293
string safe_get_line_interval(const string fn, int f, int l)
return lines f-l from file fn as a string
Definition: file.c:539
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void free(void *)
#define asprintf
Definition: misc-local.h:225
@ warning_log
Definition: misc-local.h:34

References asprintf, c_lineno, free(), get_bool_property(), get_c_parser_current_input_file_name(), get_c_parser_current_user_input_file_name(), get_current_C_line_number(), get_pips_current_module(), get_pips_current_pass_name(), get_previous_C_line_number(), get_previous_c_lineno(), pips_assert, pips_log_alist(), safe_get_line_interval(), and warning_log.

Referenced by c_parser_user_warning_func().

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

◆ c_parser_user_warning_func()

void c_parser_user_warning_func ( const char *  pips_func,
const char *  pips_file,
const int  pips_line,
const char *  format,
  ... 
)
Parameters
pips_funcips_func
pips_fileips_file
pips_lineips_line
formatormat

Definition at line 112 of file util.c.

118 {
119  va_list args;
120  va_start(args, format);
121  c_parser_user_warning_alist(pips_func, pips_file, pips_line, format, &args);
122  va_end(args);
123 }
void c_parser_user_warning_alist(const char *pips_func, const char *pips_file, const int pips_line, const char *format, va_list *args)
Compared to pips_user_warning(), the name of the calling function is lost, which does not help mainte...
Definition: util.c:60

References c_parser_user_warning_alist().

+ Here is the call graph for this function:

◆ callnodeclfilter()

static bool callnodeclfilter ( call  c)
static

Here, there is no known dummy parameter entity... unless we build a default dummy parameter, using unique names such as v1, v2, v3,..

Definition at line 1822 of file util.c.

1823 {
1824  entity e = call_function(c);
1825  if(value_code_p(entity_initial(e))) {
1828  {
1829  // Implicit declaration of an external function: returns an int
1830  // Compute arguments type from call c
1831  type ot = entity_type(e);
1832  // Too bad we assume the old type is no good
1835  NIL,
1836  NIL));
1837  list ptl = NIL;
1838  list args = call_arguments(c);
1839  list carg = list_undefined;
1840  type ft = type_undefined;
1841 
1842  for(carg=args; !ENDP(carg); POP (carg)) {
1843  expression ce = EXPRESSION(CAR(carg));
1844  type ct = expression_to_user_type(ce);
1845  /* Here, there is no known dummy parameter entity... unless
1846  we build a default dummy parameter, using unique names such as v1, v2, v3,.. */
1848 
1849  ptl = gen_nconc(ptl, CONS(PARAMETER, cp, NIL));
1850  }
1852 
1853  free_type(ot);
1854  entity_type(e) = ft;
1855 
1858  c_parser_user_warning("\n\nNo declaration of function %s in module %s\n"
1859  "Implicit declaration added\n",
1861  }
1862  }
1863 
1864  return true;
1865 }
functional make_functional(list a1, type a2)
Definition: ri.c:1109
parameter make_parameter(type a1, mode a2, dummy a3)
Definition: ri.c:1495
basic make_basic(enum basic_utype tag, void *val)
Definition: ri.c:155
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
void free_type(type p)
Definition: ri.c:2658
dummy make_dummy_unknown(void)
Definition: ri.c:617
mode make_mode_value(void)
Definition: ri.c:1353
type make_type(enum type_utype tag, void *val)
Definition: ri.c:2706
#define c_parser_user_warning(...)
entity get_current_compilation_unit_entity()
Definition: util.c:320
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define DEFAULT_INTEGER_TYPE_SIZE
#define entity_declarations(e)
MISC: newgen shorthands.
type expression_to_user_type(expression)
Preserve typedef'ed types when possible.
Definition: type.c:2645
@ is_basic_int
Definition: ri.h:571
#define value_code_p(x)
Definition: ri.h:3065
#define call_function(x)
Definition: ri.h:709
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define type_undefined
Definition: ri.h:2883
#define call_arguments(x)
Definition: ri.h:711
@ is_type_functional
Definition: ri.h:2901
@ is_type_variable
Definition: ri.h:2900
#define entity_type(x)
Definition: ri.h:2792
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87

References c_parser_user_warning, call_arguments, call_function, CAR, CONS, cp, DEFAULT_INTEGER_TYPE_SIZE, ENDP, ENTITY, entity_declarations, entity_initial, entity_type, entity_user_name(), EXPRESSION, expression_to_user_type(), free_type(), gen_in_list_p(), gen_nconc(), get_current_compilation_unit_entity(), get_current_module_entity(), get_current_module_name(), is_basic_int, is_type_functional, is_type_variable, list_undefined, make_basic(), make_dummy_unknown(), make_functional(), make_mode_value(), make_parameter(), make_type(), make_variable(), NIL, PARAMETER, POP, type_undefined, and value_code_p.

Referenced by nodecl_p().

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

◆ CCompilationUnitMemoryAllocation()

void CCompilationUnitMemoryAllocation ( entity  module)
Parameters
moduleodule

Definition at line 1967 of file util.c.

1968 {
1970 }
void CCompilationUnitMemoryAllocations(entity module, bool first_p)
This function allocates the memory to the Current Compilation Unit.
Definition: util.c:1881
static char * module
Definition: pips.c:74

References CCompilationUnitMemoryAllocations(), and module.

Referenced by ResetCurrentCompilationUnitEntity().

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

◆ CCompilationUnitMemoryAllocations()

void CCompilationUnitMemoryAllocations ( entity  module,
bool  first_p 
)

This function allocates the memory to the Current Compilation Unit.

Check that all variables used or defined are declared

Allocate variables

We are in trouble

check the type of variable here to avoid conflicting declarations

The C parser is no longer active when this warning is emitted. It is not possible to rely on its line numbers.

No way to know if a pointer is initialized or not

This may happen with variables such as "__morecore" which is a functional pointer to a malloc like function and which is declared in a header file.

It may or not be an error, depending on conflicting initializations or not. It seems better to leave this for gcc or clang to decide before running PIPS.

Do not modify the initial allocation

Do not allocate the memory for external variables: Set the offset of ram -2 which signifies UNKNOWN offset

Parameters
moduleodule
first_pirst_p

Definition at line 1881 of file util.c.

1882 {
1884  entity var = entity_undefined;
1885 
1886  pips_debug(8,"MEMORY ALLOCATION BEGINS\n");
1887 
1888  /* Check that all variables used or defined are declared */
1890 
1891  /* Allocate variables */
1892  for(; !ENDP(ld); ld = CDR(ld)) {
1893  var = ENTITY(CAR(ld));
1895  storage s = entity_storage(var);
1896  type t = entity_type(var);
1897  type ut = ultimate_type(t);
1898 
1899  // Make sure that the ultimate type is variable */
1900  if(!type_variable_p(ut) && storage_ram_p(s)) {
1901  /* We are in trouble */
1902  pips_internal_error("Variable %s has not a variable type",
1903  entity_user_name(var));
1904  }
1905 
1906  // Add some preconditions here
1907  if(storage_ram_p(s)) {
1908  ram r = storage_ram(s);
1909  entity a = ram_section(r);
1910  /* check the type of variable here to avoid conflicting declarations */
1911  // External variable list: evl
1913  if(!gen_in_list_p(var, evl)) {
1916  && ram_offset(r) != DYNAMIC_RAM_OFFSET ) {
1917  if(first_p) {
1918  /* The C parser is no longer active when this warning is emitted.
1919  * It is not possible to rely on its line numbers.
1920  */
1921  // c_parser_user_warning
1923  ("Multiple declarations of variable \"%s\" in different files\n",
1924  entity_local_name(var));
1925  if(top_level_entity_p(a)
1927  /* No way to know if a pointer is initialized or
1928  not */
1929  ||value_code_p(entity_initial(var)))) {
1930  /* This may happen with variables such as
1931  "__morecore" which is a functional pointer to a
1932  malloc like function and which is declared in a
1933  header file. */
1934  ;
1935  }
1936  else {
1937  // CParserError("Fix your source code!\n");
1938  /* It may or not be an error, depending on conflicting
1939  * initializations or not. It seems better to leave
1940  * this for gcc or clang to decide before running
1941  * PIPS.
1942  */
1943  }
1944  /* Do not modify the initial allocation */
1945  ;
1946  }
1947  }
1948  else {
1950  add_C_variable_to_area(a,var);
1951  }
1952  }
1953  else {
1954  /* Do not allocate the memory for external variables:
1955  Set the offset of ram -2 which signifies UNKNOWN offset
1956  */
1957 
1958  // Check type here to avoid conflict declarations
1959  if(ram_offset(r) == UNKNOWN_RAM_OFFSET)
1961  }
1962  }
1963  }
1964  }
1965 }
statement ModuleStatement
Definition: c_parser.c:53
static void nodecl_p(entity __attribute__((unused)) module, statement stat)
Definition: util.c:1868
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define pips_internal_error
Definition: misc-local.h:149
#define DYNAMIC_RAM_OFFSET
FI: I would have assumed that it is used for the stack area, but I must be wrong.....
#define UNKNOWN_RAM_OFFSET
#define UNDEFINED_RAM_OFFSET
bool top_level_entity_p(entity e)
Check if the scope of entity e is global.
Definition: entity.c:1130
type ultimate_type(type)
Definition: type.c:3466
bool place_holder_variable_p(entity)
Definition: variable.c:2069
int add_C_variable_to_area(entity, entity)
Definition: variable.c:1381
#define area_size(x)
Definition: ri.h:544
#define value_unknown_p(x)
Definition: ri.h:3077
#define entity_storage(x)
Definition: ri.h:2794
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define entity_undefined
Definition: ri.h:2761
#define type_area(x)
Definition: ri.h:2946
#define storage_ram(x)
Definition: ri.h:2521
#define type_variable_p(x)
Definition: ri.h:2947
#define ram_offset(x)
Definition: ri.h:2251

References add_C_variable_to_area(), area_size, CAR, CDR, code_externs, DYNAMIC_RAM_OFFSET, ENDP, ENTITY, entity_declarations, entity_initial, entity_local_name(), entity_storage, entity_type, entity_undefined, entity_user_name(), gen_in_list_p(), module, ModuleStatement, nodecl_p(), pips_debug, pips_internal_error, pips_user_warning, place_holder_variable_p(), ram_offset, ram_section, storage_ram, storage_ram_p, top_level_entity_p(), type_area, type_variable_p, ultimate_type(), UNDEFINED_RAM_OFFSET, UNKNOWN_RAM_OFFSET, value_code, value_code_p, and value_unknown_p.

Referenced by CCompilationUnitMemoryAllocation(), and CCompilationUnitMemoryReallocation().

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

◆ CCompilationUnitMemoryReallocation()

void CCompilationUnitMemoryReallocation ( entity  module)
Parameters
moduleodule

Definition at line 1972 of file util.c.

1973 {
1975 }

References CCompilationUnitMemoryAllocations(), and module.

Referenced by ResetCurrentCompilationUnitEntity().

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

◆ check_declaration_uniqueness_p()

bool check_declaration_uniqueness_p ( statement  s)

This is designed for standard C functions, not for compilation units.

e must be a function: they can be declared several times

Definition at line 3540 of file util.c.

3541 {
3542  list dl = statement_declarations(s);
3543  bool failure_p = false;
3544 
3545  FOREACH(ENTITY, e, dl) {
3546  int n = gen_occurences(e, dl);
3547  if(n>1) {
3548  /* e must be a function: they can be declared several times */
3549  type t = ultimate_type(entity_type(e));
3550 
3551  if(!type_functional_p(t)) {
3552  pips_debug(0, "Entity \"%s\" declared %d times.\n", entity_name(e), n);
3553  failure_p = true;
3554  }
3555  }
3556  }
3557  if(failure_p)
3558  pips_internal_error("Module declarations are not unique");
3559 
3560  return !failure_p;
3561 }
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
int gen_occurences(const void *vo, const list l)
count occurences of vo in l
Definition: list.c:746
#define type_functional_p(x)
Definition: ri.h:2950
#define statement_declarations(x)
Definition: ri.h:2460

References ENTITY, entity_name, entity_type, FOREACH, gen_occurences(), pips_debug, pips_internal_error, statement_declarations, type_functional_p, and ultimate_type().

Referenced by actual_c_parser().

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

◆ CheckExternList()

bool CheckExternList ( void  )

Definition at line 1025 of file util.c.

1026 {
1028  if(entity_undefined_p(f))
1029  pips_debug(5,"Current module is undefined\n");
1030  else {
1031  value fv = entity_initial(f);
1032  pips_debug(5,"Current module is function \"%s\"\n", entity_name(f));
1033  if(!value_undefined_p(fv)) {
1034  code fc = value_code(fv);
1035  if(!code_undefined_p(fc)) {
1036  list el = code_externs(fc);
1037  list le = gen_last(el);
1038  pips_debug(8, "Number of extern variables and functions: %zd\n",
1039  gen_length(el));
1040  if(gen_length(el)>0) {
1041  pips_debug(8, "Last entity %s in cons %p with car=%p and cdr=%p\n",
1042  entity_name(ENTITY(CAR(le))),
1043  le,
1044  &(le->car),
1045  (void *) (le->cdr));
1046  }
1047  pips_assert("externs is an entity list", entity_list_p(el));
1048  }
1049  }
1050  }
1051  return true;
1052 }
size_t gen_length(const list l)
Definition: list.c:150
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define value_undefined_p(x)
Definition: ri.h:3017
#define code_undefined_p(x)
Definition: ri.h:758
#define entity_undefined_p(x)
Definition: ri.h:2762
struct cons * cdr
The pointer to the next element.
Definition: newgen_list.h:43
gen_chunk car
The data payload of a list element.
Definition: newgen_list.h:42

References cons::car, CAR, cons::cdr, code_externs, code_undefined_p, ENTITY, entity_initial, entity_list_p(), entity_name, entity_undefined_p, f(), gen_last(), gen_length(), get_current_module_entity(), pips_assert, pips_debug, value_code, and value_undefined_p.

+ Here is the call graph for this function:

◆ CleanUpEntities()

void CleanUpEntities ( list  le)

update entity in module declarations

Update storage area

Update entity in current entity list

Remove entity from potentially removable externs and add it the new entity

Apparently, formal parameters may have been declared for such an entity and PIPS code dumps when the symbol table is written.

See decl62.c and decl63.c

Parameters
lee

Definition at line 2772 of file util.c.

2773 {
2774  list ce = list_undefined;
2775  bool found = false;
2776 
2777  for(ce=le; !ENDP(ce); POP(ce)) {
2778  entity e = ENTITY(CAR(ce));
2779  entity ne = CleanUpEntity(e);
2780  if(ne!=e) {
2783  list de = list_undefined;
2784  storage s = entity_storage(e);
2785 
2786  /* update entity in module declarations */
2787  found = false;
2788  for(de=d; !ENDP(de); POP(de)) {
2789  entity ed = ENTITY(CAR(de));
2790  if(ed==e) {
2791  CAR(de).p = (gen_chunk *) ne;
2792  found = true;
2793  }
2794  }
2795  if(!found)
2796  pips_internal_error("Entity to be replaced not declared");
2797 
2798  /* Update storage area */
2799  found = false;
2800  if(storage_ram_p(s)) {
2801  ram r = storage_ram(s);
2802  entity a = ram_section(r);
2804  list lde = list_undefined;
2805 
2806  for(lde=ld; !ENDP(lde); POP(lde)) {
2807  entity ed = ENTITY(CAR(lde));
2808  if(ed==e) {
2809  found = true;
2810  CAR(lde).p = (gen_chunk *) ne;
2811  }
2812  }
2813  if(!found)
2814  pips_internal_error("Entity to be replaced not allocated in its ram area");
2815  }
2816  else {
2817  pips_internal_error("Unexpected storage kind");
2818  }
2819 
2820  /* Update entity in current entity list */
2821  CAR(ce).p = (gen_chunk *) ne;
2822 
2823  /* Remove entity from potentially removable externs and add it
2824  the new entity */
2825  gen_remove(&removable_extern_entities, (void *) e);
2827 
2828  /* Apparently, formal parameters may have been declared for such
2829  * an entity and PIPS code dumps when the symbol table is
2830  * written.
2831  *
2832  * See decl62.c and decl63.c
2833  */
2834  //free_entity(e);
2835  }
2836  }
2837 }
list removable_extern_entities
Definition: c_parser.c:542
static entity CleanUpEntity(entity e)
if returned entity != original entity, e must be freed, otherwise an invalid entity is still tabulate...
Definition: util.c:2745
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#define area_layout(x)
Definition: ri.h:546
A gen_chunk is used to store every object.
Definition: genC.h:58

References area_layout, CAR, CleanUpEntity(), code_declarations, CONS, ENDP, ENTITY, entity_initial, entity_storage, entity_type, gen_remove(), get_current_module_entity(), list_undefined, pips_internal_error, POP, ram_section, removable_extern_entities, storage_ram, storage_ram_p, type_area, and value_code.

+ Here is the call graph for this function:

◆ CleanUpEntity()

static entity CleanUpEntity ( entity  e)
static

if returned entity != original entity, e must be freed, otherwise an invalid entity is still tabulated

The variable name is wrong

Entity e should be removed... but it's pretty dangerous.

let the caller do it

Definition at line 2745 of file util.c.

2746 {
2747  entity ne = e;
2748  type et = entity_type(e);
2749  const char* eln = entity_local_name(e);
2750 
2751  if(static_module_name_p(eln) && !type_functional_p(et)) {
2752  /* The variable name is wrong */
2753  const char* neln = strstr(eln, FILE_SEP_STRING)+1;
2754  const char* emn = entity_module_name(e);
2755 
2756  ne = FindOrCreateEntity(emn, neln);
2757 
2758  entity_type(ne) = copy_type(entity_type(e));
2761 
2762  pips_assert("entity has type variable", type_variable_p(et));
2763  pips_debug(1, "Entity %s should have a functional type\n", entity_name(e));
2764  pips_debug(1, "New Entity %s created\n", entity_name(ne));
2765  /* Entity e should be removed... but it's pretty dangerous. */
2766  /* let the caller do it */
2767  }
2768 
2769  return ne;
2770 }
type copy_type(type p)
TYPE.
Definition: ri.c:2655
value copy_value(value p)
VALUE.
Definition: ri.c:2784
storage copy_storage(storage p)
STORAGE.
Definition: ri.c:2228
bool static_module_name_p(const char *name)
Check if the given name is a static module name.
Definition: entity_names.c:122
#define FILE_SEP_STRING
Definition: naming-local.h:41
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
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092

References copy_storage(), copy_type(), copy_value(), entity_initial, entity_local_name(), entity_module_name(), entity_name, entity_storage, entity_type, FILE_SEP_STRING, FindOrCreateEntity(), pips_assert, pips_debug, static_module_name_p(), type_functional_p, and type_variable_p.

Referenced by CleanUpEntities().

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

◆ CModuleMemoryAllocation()

void CModuleMemoryAllocation ( entity  module)

This function is for MemoryAllocation for Module of C programs.

Parameters
moduleodule

Definition at line 1979 of file util.c.

1980 {
1982  entity var = entity_undefined;
1983 
1984  pips_debug(8,"MEMORY ALLOCATION BEGINS\n");
1986  //print_entities(ld);
1987  for(; !ENDP(ld); ld = CDR(ld))
1988  {
1989  var = ENTITY(CAR(ld));
1990 
1992  {
1993  storage s = entity_storage(var);
1994  if(storage_ram_p(s))
1995  {
1996  ram r = storage_ram(s);
1997  entity a = ram_section(r);
2000  if(a == StackArea)
2002  else
2003  add_C_variable_to_area(a,var);
2004  }
2005  else{
2006  if(ram_offset(r) == UNKNOWN_RAM_OFFSET)
2008  }
2009  }
2010  if(storage_formal_p(s))
2011  {
2012  //DO NOTHING
2013  }
2014  }
2015  }
2016 }
entity StackArea
Definition: area.c:60
#define storage_formal_p(x)
Definition: ri.h:2522

References add_C_variable_to_area(), area_size, CAR, CDR, code_externs, DYNAMIC_RAM_OFFSET, ENDP, ENTITY, entity_declarations, entity_initial, entity_storage, entity_type, entity_undefined, gen_in_list_p(), module, ModuleStatement, nodecl_p(), pips_debug, place_holder_variable_p(), ram_offset, ram_section, StackArea, storage_formal_p, storage_ram, storage_ram_p, type_area, type_variable_p, UNDEFINED_RAM_OFFSET, UNKNOWN_RAM_OFFSET, and value_code.

Referenced by ResetCurrentModule().

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

◆ ComputeAreaOffset()

int ComputeAreaOffset ( entity  a,
entity  v 
)

Update the size and layout of the area aa. This function is called too earlier, we may not have the size of v. To be changed !!!

FI: who wrote this? when should the offsets be computed? how do we deal with scoping?

area_size(aa) = offset + 0;

Definition at line 3324 of file util.c.

3325 {
3326  type ta = entity_type(a);
3327  area aa = type_area(ta);
3328  int offset = area_size(aa);
3329 
3330  pips_assert("Not used", false);
3331 
3332  /* Update the size and layout of the area aa.
3333  This function is called too earlier, we may not have the size of v.
3334  To be changed !!!
3335 
3336  FI: who wrote this? when should the offsets be computed? how do we deal with
3337  scoping?
3338  */
3339 
3340  pips_assert("Type is correctly defined", CSafeSizeOfArray(v)!=0);
3341 
3342  /* area_size(aa) = offset + 0; */
3343  area_size(aa) = offset + CSafeSizeOfArray(v);
3344  area_layout(aa) = gen_nconc(area_layout(aa), CONS(ENTITY, v, NIL));
3345  return offset;
3346 }
static Value offset
Definition: translation.c:283
int CSafeSizeOfArray(entity)
BEGIN_EOLE.
Definition: size.c:225

References area_layout, area_size, CONS, CSafeSizeOfArray(), ENTITY, entity_type, gen_nconc(), NIL, offset, pips_assert, and type_area.

+ Here is the call graph for this function:

◆ CreateEntityFromLocalNameAndPrefix()

entity CreateEntityFromLocalNameAndPrefix ( string  name,
string  prefix,
bool  is_external 
)

We have to know the context:

  • if the entity is declared outside any function, their scope is the CurrentCompilationUnit
  • if the entity is declared inside a function, we have to know the CurrentBlock, which is omitted for the moment
  • if the function is static, their scope is CurrentCompilationUnit::CurrentModule
  • if the function is global, their scope is CurrentModule

The entity is created local to the file. For instance, derived and user-named types. This makes type checking more difficult as types such as FILE * vary from C file to C file, but this is consistent with the C standard and the behavior of production compilers: the same local name can be used for two different types in two different files.

These types are created globally, which makes type checking much easier but forbid homonym types in different files.

Parameters
nameame
prefixrefix
is_externals_external

Definition at line 962 of file util.c.

963 {
964  /* We have to know the context:
965 
966  - if the entity is declared outside any function, their scope is
967  the CurrentCompilationUnit
968 
969  - if the entity is declared inside a function, we have to know
970  the CurrentBlock, which is omitted for the moment
971 
972  - if the function is static, their scope is
973  CurrentCompilationUnit#CurrentModule
974 
975  - if the function is global, their scope is CurrentModule
976  */
977  entity ent = entity_undefined;
978 
979  if (is_external) {
980  pips_debug(5,"Entity local name is %s with prefix %s\n",name,prefix);
981  char *local_name;
982  asprintf(&local_name,"%s%s",prefix,name);
983  // See TRAC Ticket #787
984 #define FILE_LOCAL_USER_DEFINED_TYPES_P (true)
986  /* The entity is created local to the file. For instance,
987  * derived and user-named types. This makes type checking more
988  * difficult as types such as FILE * vary from C file to C file,
989  * but this is consistent with the C standard and the behavior
990  * of production compilers: the same local name can be used for
991  * two different types in two different files.
992  */
994  }
995  else {
996  /* These types are created globally, which makes type checking
997  * much easier but forbid homonym types in different files.
998  */
1000  }
1001  free(local_name);
1002  }
1003  else {
1004  string scope = scope_to_block_scope(GetScope());
1005 
1006  pips_debug(5,"Entity local name is %s with prefix %s and scope \"%s\"\n",
1007  name,prefix,scope);
1008  pips_assert("scope is a block scope", string_block_scope_p(scope));
1009 
1010  char * local_name;
1011  asprintf(&local_name,"%s%s%s",scope,prefix,name);
1014  }
1015  else {
1017  }
1018  free(local_name);
1019  free(scope);
1020  }
1021  pips_debug(5,"Entity global name is %s\n",entity_name(ent));
1022  return ent;
1023 }
string compilation_unit_name
cproto-generated files
Definition: c_parser.c:49
string scope_to_block_scope(string)
Allocate a new string containing only block scope information.
Definition: cyacc.tab.c:268
string GetScope(void)
Definition: cyacc.tab.c:371
#define FILE_LOCAL_USER_DEFINED_TYPES_P
static bool is_external
to know if the variable is declared inside or outside a function, so its scope is the current functio...
Definition: cyacc.tab.c:115
const char * local_name(const char *s)
Does not take care of block scopes and returns a pointer.
Definition: entity_names.c:221
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
static const char * prefix
bool string_block_scope_p(string s)
Definition: entity.c:511
bool static_module_p(entity e)
Check if the given module entity is a static module.
Definition: module.c:80

References asprintf, compilation_unit_name, entity_name, entity_undefined, FILE_LOCAL_USER_DEFINED_TYPES_P, FindOrCreateEntity(), free(), get_current_module_entity(), get_current_module_name(), GetScope(), is_external, local_name(), pips_assert, pips_debug, prefix, scope_to_block_scope(), static_module_p(), string_block_scope_p(), and TOP_LEVEL_MODULE_NAME.

Referenced by FindOrCreateCurrentEntity(), FindOrCreateEntityFromLocalNameAndPrefix(), FindOrCreateEntityFromLocalNameAndPrefixAndScope(), and MakeDerivedEntity().

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

◆ CreateMemberScope()

string CreateMemberScope ( string  derived,
bool  is_external 
)

We have to know the context :

  • if the struct/union is declared outside any function, its scope is the CurrentCompilationUnit
  • if the struct/union is declared inside a function, we have to know the CurrentBlock, which is omitted for the moment
  • if the function is static, its scope is CurrentCompilationUnit!CurrentModule
  • if the function is global, its scope is CurrentModule

The name of the struct/union is then added to the field entity name, with the MEMBER_SEP_STRING

ompilation_unit_name,

Parameters
derivederived
is_externals_external

Definition at line 3261 of file util.c.

3262 {
3263  /* We have to know the context :
3264  - if the struct/union is declared outside any function, its scope is the CurrentCompilationUnit
3265  - if the struct/union is declared inside a function, we have to know the CurrentBlock,
3266  which is omitted for the moment
3267  - if the function is static, its scope is CurrentCompilationUnit!CurrentModule
3268  - if the function is global, its scope is CurrentModule
3269 
3270  The name of the struct/union is then added to the field entity name, with
3271  the MEMBER_SEP_STRING */
3272 
3273  string s = string_undefined;
3274 
3275  pips_debug(3,"Struc/union name is %s\n",derived);
3276 
3277  if (is_external)
3279  else {
3280  string scope = scope_to_block_scope(GetScope());
3281 
3282  pips_assert("scope is a block scope", string_block_scope_p(scope));
3283 
3285  s = strdup(concatenate(/*compilation_unit_name,*/
3287  scope, derived, MEMBER_SEP_STRING, NULL));
3288  else
3290  scope, derived, MEMBER_SEP_STRING, NULL));
3291  }
3292 
3293  pips_debug(3,"The struct/union member's scope is %s\n",s);
3294 
3295  return s;
3296 }
#define MODULE_SEP_STRING
Definition: naming-local.h:30
#define MEMBER_SEP_STRING
Definition: naming-local.h:53

References compilation_unit_name, concatenate(), get_current_module_entity(), get_current_module_name(), GetScope(), is_external, MEMBER_SEP_STRING, MODULE_SEP_STRING, pips_assert, pips_debug, scope_to_block_scope(), static_module_p(), strdup(), string_block_scope_p(), and string_undefined.

+ Here is the call graph for this function:

◆ CreateReturnEntity()

void CreateReturnEntity ( entity  f)

If necessary, create the return entity, which is a hidden variable used in PIPS internal representation to carry the value returned by a function.

c_parser_user_warning() should not be called as it may be some times too late to get significant line numbers.

Create the return value

set the language

Definition at line 2382 of file util.c.

2383 {
2385  /* c_parser_user_warning() should not be called as it may be some
2386  * times too late to get significant line numbers.
2387  */
2388  c_parser_user_warning("Type of \"%s\" is undefined."
2389  " Return value cannot be created.\n",
2390  entity_user_name(f));
2391  }
2392  else {
2394 
2395  pips_debug(8, "For module \"%s\"\n", entity_name(f));
2396 
2397  if(type_functional_p(ft)) {
2399 
2400  if(type_undefined_p(rt)) {
2401  c_parser_user_warning("Return type of \"%s\" is undefined."
2402  " Return value cannot be created.\n",
2403  entity_user_name(f));
2404  }
2405  else if(!type_void_p(rt)) {
2406  /* Create the return value */
2407  const char* fn = entity_local_name(f);
2408  entity re = FindOrCreateEntity(fn,fn);
2409  if(type_undefined_p(entity_type(re))) {
2410  entity_type(re) = copy_type(rt);
2412  /* set the language */
2414  AddToDeclarations(re, f);
2415  }
2416  }
2417  }
2418  else
2419  pips_internal_error("This function should only be called with a function entity");
2420  }
2421 }
value make_value_unknown(void)
Definition: ri.c:2847
storage make_storage_return(entity _field_)
Definition: ri.c:2276
void AddToDeclarations(entity e, entity mod)
FI: check the difference with AddEntityToDeclarations()
Definition: util.c:2924
#define functional_result(x)
Definition: ri.h:1444
#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

References AddToDeclarations(), c_parser_user_warning, copy_type(), entity_initial, entity_local_name(), entity_name, entity_storage, entity_type, entity_user_name(), f(), FindOrCreateEntity(), functional_result, make_storage_return(), make_value_unknown(), pips_debug, pips_internal_error, type_functional, type_functional_p, type_undefined_p, type_void_p, and ultimate_type().

Referenced by UpdateEntity(), and UpdateEntity2().

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

◆ FindEntityFromLocalName()

entity FindEntityFromLocalName ( string  name)

Find an entity from its local name. We have to look for all possible prefixes, which are: blank, STRUCT_PREFIX, UNION_PREFIX, ENUM_PREFIX, TYPEDEF_PREFIX

How about multiple results ? The order of prefixes ?

Is it a static function? It must have been parsed in the compilation unit

Parameters
nameame

Definition at line 778 of file util.c.

779 {
780  /* Find an entity from its local name.
781  We have to look for all possible prefixes, which are:
782  blank, STRUCT_PREFIX, UNION_PREFIX, ENUM_PREFIX, TYPEDEF_PREFIX
783 
784  How about multiple results ? The order of prefixes ? */
785 
786  entity ent = entity_undefined;
788  int i;
789  //c_parser_context cpc = GetScope();
790  //string scope = scope_to_block_scope(c_parser_context_scope(cpc));
791 
792  for (i=0; prefixes[i]!=NULL; i++)
793  {
795  return ent;
796  }
797 
798  if(entity_undefined_p(ent)) {
799  /* Is it a static function? It must have been parsed in the compilation unit */
800  string sname = strdup(concatenate(compilation_unit_name, name, NULL));
801  ent = FindEntity(compilation_unit_name, sname);
802  free(sname);
803  return ent;
804  }
805 
806  c_parser_user_warning("Cannot find entity %s\n", name);
807 
808  return entity_undefined;
809 }
entity FindEntityFromLocalNameAndPrefix(string name, string prefix)
Definition: util.c:877
#define TYPEDEF_PREFIX
Definition: naming-local.h:62
#define UNION_PREFIX
Definition: naming-local.h:58
#define ENUM_PREFIX
Definition: naming-local.h:60
#define STRUCT_PREFIX
Definition: naming-local.h:56
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
static string prefixes[]
Definition: entity.c:1433

References c_parser_user_warning, compilation_unit_name, concatenate(), entity_undefined, entity_undefined_p, ENUM_PREFIX, FindEntity(), FindEntityFromLocalNameAndPrefix(), free(), prefixes, strdup(), STRUCT_PREFIX, TYPEDEF_PREFIX, and UNION_PREFIX.

Referenced by IdentifierToExpression().

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

◆ FindEntityFromLocalNameAndPrefix()

entity FindEntityFromLocalNameAndPrefix ( string  name,
string  prefix 
)

Find an entity from its local name and prefix. We have to look from the most enclosing scope.

Possible name combinations and the looking order:

  1. FILE!MODULE:BLOCKPREFIXname or MODULE:BLOCKPREFIXname
  2. FILE!MODULE:PREFIXname or MODULE:PREFIXname
  3. FILE!:PREFIXname (used to be FILE!PREFIXname)
  4. TOP-LEVEL:PREFIXname

with 5 possible prefixes: blank, STRUCT_PREFIX, UNION_PREFIX, ENUM_PREFIX, TYPEDEF_PREFIX

"!" is FILE_SEP_STRING and ":" is MODULE_SEP_STRING and "`" is BLOCK_SEP_STRING

First, look up the surrounding scopes

Is it a formal parameter not yet converted in the function frame?

Should we change the current dummy parameter number?

Is it a static variable declared in the compilation unit?

we have an issue there : a static function will be declared FILE!MODULE:FILE!name, but a static variable will be declared FILE!MODULE:name so try both ... CleanupEntity has been fixed to remove buggy situations ...

Is it a global variable declared in the compilation unit?

Is it a local type used within a function declaration?

It may be a parser error or a normal behavior when an entity is used before it is defined as, for example, a struct in a typedef: typedef struct foo foo;

CParserError("Variable appears to be undefined\n");

Parameters
nameame
prefixrefix

Definition at line 877 of file util.c.

878 {
879  /* Find an entity from its local name and prefix.
880  We have to look from the most enclosing scope.
881 
882  Possible name combinations and the looking order:
883 
884  1. FILE!MODULE:BLOCK`PREFIXname or MODULE:BLOCK`PREFIXname
885  2. FILE!MODULE:PREFIXname or MODULE:PREFIXname
886  3. FILE!:PREFIXname (used to be FILE!PREFIXname)
887  4. TOP-LEVEL:PREFIXname
888 
889  with 5 possible prefixes: blank, STRUCT_PREFIX, UNION_PREFIX, ENUM_PREFIX, TYPEDEF_PREFIX
890 
891  "!" is FILE_SEP_STRING and ":" is MODULE_SEP_STRING and "`" is BLOCK_SEP_STRING
892  */
893 
894  entity ent = entity_undefined;
895  string global_name = string_undefined;
896  string scope = scope_to_block_scope(GetScope());
897  string ls = strdup(scope);
898  string ls_head = ls;
899 
900  pips_debug(5,"Entity local name is \"%s\" with prefix \"%s\" and scope \"%s\"\n",
901  name,prefix,scope);
902  pips_assert("Scope is a block scope", string_block_scope_p(scope));
903  free(scope);
904 
905  /* First, look up the surrounding scopes */
907 
908  /* Is it a formal parameter not yet converted in the function frame? */
909  if(entity_undefined_p(ent)) {
910  /* Should we change the current dummy parameter number? */
912 
914  prefix,name,NULL));
915  ent = gen_find_tabulated(global_name,entity_domain);
916  free(sn);
917  }
918 
919  /* Is it a static variable declared in the compilation unit? */
920  /* we have an issue there : a static function will be declared FILE!MODULE:FILE!name,
921  * but a static variable will be declared FILE!MODULE:name
922  * so try both ... CleanupEntity has been fixed to remove buggy situations ...*/
923  if(entity_undefined_p(ent)) {
925  prefix,name,NULL));
926  ent = gen_find_tabulated(global_name,entity_domain);
927  }
928  if(entity_undefined_p(ent)) {
930  prefix,name,NULL));
931  ent = gen_find_tabulated(global_name,entity_domain);
932  }
933 
934  /* Is it a global variable declared in the compilation unit? */
935  if(entity_undefined_p(ent)) {
937  prefix,name,NULL));
938  ent = gen_find_tabulated(global_name,entity_domain);
939  }
940 
941  /* Is it a local type used within a function declaration? */
942  if(entity_undefined_p(ent) && strcmp(ls, "")==0 && ScopeStackSize()>=2) {
943  string lls = strdup(scope_to_block_scope(GetParentScope()));
945  free(lls);
946  }
947 
948  if(entity_undefined_p(ent)) {
949  pips_debug(8, "Cannot find entity with local name \"%s\" with prefix \"%s\" at line %d\n",
951  /* It may be a parser error or a normal behavior when an entity is
952  used before it is defined as, for example, a struct in a typedef:
953  typedef struct foo foo; */
954  /* CParserError("Variable appears to be undefined\n"); */
955  } else
956  pips_debug(5,"Entity global name is %s\n",entity_name(ent));
957  //free(global_name);
958  free(ls_head);
959  return ent;
960 }
int ScopeStackSize(void)
Definition: cyacc.tab.c:366
string GetParentScope(void)
Definition: cyacc.tab.c:387
entity FindEntityFromLocalNameAndPrefixAndScope(string name, string prefix, string scope)
The parameter "scope" is potentially destroyed.
Definition: util.c:850
static int get_current_dummy_parameter_number(void)
Definition: util.c:147
#define DUMMY_PARAMETER_PREFIX
For dmmmy parameters in functions declarations.
Definition: naming-local.h:93
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
char * int2a(int i)
util.c
Definition: util.c:42

References compilation_unit_name, concatenate(), DUMMY_PARAMETER_PREFIX, entity_domain, entity_name, entity_undefined, entity_undefined_p, FindEntityFromLocalNameAndPrefixAndScope(), free(), gen_find_tabulated(), get_current_C_line_number(), get_current_dummy_parameter_number(), GetParentScope(), GetScope(), int2a(), MODULE_SEP_STRING, pips_assert, pips_debug, prefix, scope_to_block_scope(), ScopeStackSize(), strdup(), string_block_scope_p(), string_undefined, and TOP_LEVEL_MODULE_NAME.

Referenced by FindEntityFromLocalName(), FindOrCreateEntityFromLocalNameAndPrefix(), and FindOrCreateEntityFromLocalNameAndPrefixAndScope().

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

◆ FindEntityFromLocalNameAndPrefixAndScope()

entity FindEntityFromLocalNameAndPrefixAndScope ( string  name,
string  prefix,
string  scope 
)

The parameter "scope" is potentially destroyed.

Add block scope case here

ompilation_unit_name,

return values are not C variables... but they are entities.

Parameters
nameame
prefixrefix
scopecope

Definition at line 850 of file util.c.

851 {
852  entity ent = entity_undefined;
853 
855  string global_name = string_undefined;
856  /* Add block scope case here */
857  do {
859  global_name = (concatenate(/*compilation_unit_name,*/
861  scope,prefix,name,NULL));
862  else
864  scope,prefix,name,NULL));
865  ent = gen_find_tabulated(global_name,entity_domain);
866  /* return values are not C variables... but they are entities. */
867  if(!entity_undefined_p(ent)
869  && storage_return_p(entity_storage(ent))) {
870  ent = entity_undefined;
871  }
872  } while(entity_undefined_p(ent) && (scope = pop_block_scope(scope))!=NULL);
873  }
874  return ent;
875 }
string pop_block_scope(string)
The scope is moved up the scope tree and a NULL is return when there are no more scope to explore.
Definition: cyacc.tab.c:235
#define storage_return_p(x)
Definition: ri.h:2516
#define storage_undefined_p(x)
Definition: ri.h:2477

References concatenate(), entity_domain, entity_storage, entity_undefined, entity_undefined_p, gen_find_tabulated(), get_current_module_entity(), get_current_module_name(), MODULE_SEP_STRING, pop_block_scope(), prefix, static_module_p(), storage_return_p, storage_undefined_p, and string_undefined.

Referenced by FindEntityFromLocalNameAndPrefix().

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

◆ FindOrCreateCurrentEntity()

entity FindOrCreateCurrentEntity ( string  name,
stack ContextStack   __attribute__(__unused__),
stack  FormalStack,
stack  FunctionStack,
bool  is_external 
)

This function finds or creates the current entity.

Only entity full name is created, other fields such as type, storage and initial value are undefined.

function is only used for formal variables

Tell the lexer about the new type names : add to keyword_typedef_table. Because of scopes, different types can have the same name...

Prefix for the current struct: use full_scope

Maybe it would have been better to push "external" in the context

&& strstr(scope,TOP_LEVEL_MODULE_NAME) != NULL

This entity is declared in a compilation unit with keyword EXTERN. Add it to the storage of the compilation unit to help code prettyprint unless if has already been declared earlier in the current compilation unit. See C_syntax/global_extern.c

ent has not been declared earlier

A global entity may already have been seen in a previous compilation unit and so it is already typed but still must be declared as extern. See test case C_syntax/declarations.c

The bad news is: function are not yet fully typed when this is executed and their type is "variable", the future result type; hence, they are declared "extern" no matter what... Do we want to clean up the code_externs list later since the extern keyword is useless for functions? No other simple solution found...

FI: The test above may be stronger than the previous one, but I'm pretty conservative when dealing with the parser.

This variable is declared extern within a function body.

Impossible: this is not detected here

This entity may have already been declared external but is redeclared inside the same module. See C_syntax/global_extern.c

Formal parameter for a function declaration or for a function definition or for a pointer to a function or for a functional typedef

It is too early to define formal parameters. Let's start with dummy parameters

scope = NULL, not extern/typedef/struct/union/enum

This is a variable/function declared outside any module's body

If it is a function, we'd like to increase its name. If it's a variable, we'd like not to increase its name with the compilation unit name. But we do not have much information here to make the decision. Let's assume it's a function and postpone to UpdateEntity()

Depending on the type, we should or not introduce a MODULE_SEP_STRING, but the type is still not fully known. Wait for UpdateFunctionEntity().

We may have to remove it from the extern list: C_syntax/global_extern01.c

code_externs(value_code(entity_initial(com_unit))) =

arguments_rm_entity(el, ent);

This is a variable/function declared inside a module's body: add block scope here Attention, the scope of a function declared in module is the module, not global.

The module name is unambiguous because it is used by pipdbm

FI: why is ct not exploited? Because the information is later destroyed. I guess it is related to the type_stack stored in the entity_ initial field.

entity_type(ent) = copy_type(ct);

Definition at line 1088 of file util.c.

1093 {
1094  entity ent;
1096  string full_scope = c_parser_context_scope(context);
1097  string scope = strrchr(full_scope, BLOCK_SEP_CHAR);
1098  string block_scope = scope_to_block_scope(full_scope);
1100  bool is_typedef = c_parser_context_typedef(context);
1101  bool is_static = c_parser_context_static(context);
1102  entity function = entity_undefined;
1103  bool is_formal;
1104 
1105  if(scope!=NULL)
1106  scope++;
1107  else {
1108  scope = full_scope;
1109  }
1110 
1111  if(!string_block_scope_p(block_scope)) {
1112  pips_assert("block_scope is TOP-LEVEL:", same_string_p(block_scope, "TOP-LEVEL:"));
1113  free(block_scope);
1114  block_scope = empty_scope();
1115  }
1116 
1118  is_formal = false;
1119  else {
1120  is_formal= true;
1121  function = stack_head(FunctionStack);
1122  }
1123 
1124  ifdebug(5) {
1126  if(entity_undefined_p(f))
1127  pips_debug(5,"Entity local name \"%s\"\n",name);
1128  else {
1129  value fv = entity_initial(f);
1130  pips_debug(5,"Entity local name \"%s\" in function \"%s\"\n",name, entity_name(f));
1131  if(!value_undefined_p(fv)) {
1132  code fc = value_code(fv);
1133  if(!code_undefined_p(fc)) {
1134  list el = code_externs(fc);
1135  pips_assert("externs is an entity list", entity_list_p(el));
1136  }
1137  }
1138  }
1139  pips_debug(5,"Context %p\n",context);
1140  if (full_scope != NULL) {
1141  pips_debug(5,"Current scope: \"%s\"\n",full_scope);
1142  pips_debug(5,"Local declaration scope: \"%s\"\n",scope);
1143  pips_debug(5,"Block scope: \"%s\"\n",block_scope);
1144  pips_assert("block_scope is a block scope", string_block_scope_p(block_scope));
1145  }
1146  pips_debug(5,"type %p: %s\n", ct, list_to_string(safe_c_words_entity(ct, NIL)));
1147  pips_debug(5,"is_typedef: %d\n",is_typedef);
1148  pips_debug(5,"is_static: %d\n",is_static);
1149  pips_debug(5,"is_external: %d\n",is_external);
1150  pips_debug(5,"is_formal: %d\n",is_formal);
1151  if (is_formal)
1152  pips_debug(5,"of current function %s\n",entity_user_name(function));
1153  /* function is only used for formal variables*/
1154  }
1155 
1156  if (is_typedef)
1157  {
1158  /* Tell the lexer about the new type names : add to
1159  keyword_typedef_table. Because of scopes, different types
1160  can have the same name... */
1162  /*
1163  hash_put(keyword_typedef_table,strdup(name),(void *) TK_NAMED_TYPE);
1164  pips_debug(5,"Add typedef name %s to hash table\n",name);
1165  */
1167  }
1168  else
1169  {
1170  if (strcmp(scope,"") != 0 && !is_formal)
1171  {
1172  /* Prefix for the current struct: use full_scope */
1173  char * mname = strdup(module_name(full_scope));
1174  char * tname = name;
1175  asprintf(&name,"%s%s",local_name(full_scope),name);
1176  ent = FindOrCreateEntity(mname,name);
1177  free(mname);free(tname);
1178  if (is_external
1179  && !member_entity_p(ent) /* Maybe it would have been
1180  better to push "external" in
1181  the context */
1182  /* && strstr(scope,TOP_LEVEL_MODULE_NAME) != NULL*/ )
1183  {
1184  /* This entity is declared in a compilation unit with
1185  keyword EXTERN. Add it to the storage of the
1186  compilation unit to help code prettyprint unless if
1187  has already been declared earlier in the current
1188  compilation unit. See C_syntax/global_extern.c */
1190  code c = value_code(entity_initial(com_unit));
1191  list el = code_externs(c);
1192  if(type_undefined_p(entity_type(ent))
1193  || intrinsic_entity_p(ent)) {
1194  /* ent has not been declared earlier */
1195  //ram_shared(storage_ram(entity_storage(com_unit))) =
1196  //gen_nconc(ram_shared(storage_ram(entity_storage(com_unit))), CONS(ENTITY,ent,NIL));
1197  pips_debug(8, "Variable \"%s\" added to external declarations of \"%s\"\n",
1198  entity_name(ent), entity_name(com_unit));
1199  pips_assert("ent is an entity", entity_domain_number(ent)==entity_domain);
1200  pips_assert("com_unit is an entity", entity_domain_number(com_unit)==entity_domain);
1201  pips_assert("el is a pure entity list", entity_list_p(el));
1202  //code_externs(c) = gen_nconc(el,
1203  //CONS(ENTITY,ent,NIL));
1204  AddToExterns(ent, com_unit);
1205  el = code_externs(value_code(entity_initial(com_unit)));
1206  pips_assert("el is a pure entity list", entity_list_p(el));
1207  }
1208  else if(!gen_in_list_p(ent, el)
1209  && !type_undefined_p(entity_type(ent))
1210  && !type_functional_p(entity_type(ent))) {
1211  /* A global entity may already have been seen in a
1212  previous compilation unit and so it is already
1213  typed but still must be declared as extern. See
1214  test case C_syntax/declarations.c */
1215  /* The bad news is: function are not yet fully typed
1216  when this is executed and their type is "variable",
1217  the future result type; hence, they are declared
1218  "extern" no matter what... Do we want to clean up
1219  the code_externs list later since the extern
1220  keyword is useless for functions? No other simple
1221  solution found... */
1222  /* FI: The test above may be stronger than the previous one,
1223  but I'm pretty conservative when dealing with the
1224  parser. */
1225  AddToExterns(ent, com_unit);
1226  }
1227  }
1228  else if(strstr(full_scope,TOP_LEVEL_MODULE_NAME)!=NULL) {
1230  if(type_undefined_p(entity_type(ent))
1231  || !type_functional_p(entity_type(ent))) {
1232  /* This variable is declared extern within a function
1233  body. */
1234  AddToExterns(ent, function);
1235  }
1236  }
1237  else {
1238  /* Impossible: this is not detected here */
1239  /* This entity may have already been declared external but
1240  is redeclared inside the same module. See
1241  C_syntax/global_extern.c */
1242  /*
1243  entity com_unit = get_current_compilation_unit_entity();
1244  list el = code_externs(value_code(entity_initial(com_unit)));
1245  if(entity_is_argument_p(ent, el))
1246  code_externs(value_code(entity_initial(com_unit))) =
1247  arguments_rm_entity(el, ent);
1248  */
1249  }
1250  }
1251  else
1252  {
1253  if (is_formal) {
1254  /* Formal parameter for a function declaration or for a
1255  function definition or for a pointer to a function or
1256  for a functional typedef */
1257  stack st = get_from_entity_type_stack_table(function);
1259 
1260  if(typedef_entity_p(function)) {
1261  // To get a unique identifier for each function typedef
1263  char * module_name;
1265 
1266  ent = FindOrCreateEntity(module_name,name);
1267  free(module_name);
1268  }
1269  else if(!type_undefined_p(ft) && type_variable_p(ft)
1271 
1272  // To get a unique identifier for each function pointerdeclaration, dummy or not
1274  char * module_name;
1276 
1277  ent = FindOrCreateEntity(module_name,name);
1278  free(module_name);
1279  }
1280  else {
1281  /* It is too early to define formal parameters. Let's start with dummy parameters */
1282  // To get a unique identifier for each function (This
1283  // may not be sufficient as a function can be declared
1284  // any number of times with any parameter names)
1286  char * module_name;
1288  ent = FindOrCreateEntity(module_name,name);
1289  free(module_name);
1290  /*
1291  if(top_level_entity_p(function))
1292  ent = find_or_create_entity(strdup(concatenate(entity_user_name(function),
1293  MODULE_SEP_STRING,name,NULL)));
1294  else {
1295  // The function is local to a compilation unit
1296  // Was this the best possible design?
1297  string mn = entity_module_name(function);
1298  string ln = entity_local_name(function);
1299  ent = find_or_create_entity(strdup(concatenate(mn,ln,
1300  MODULE_SEP_STRING,name,NULL)));
1301  }
1302  */
1303  }
1304  }
1305  else
1306  {
1307  /* scope = NULL, not extern/typedef/struct/union/enum */
1308  if (is_external)
1309  {
1310  /* This is a variable/function declared outside any module's body*/
1311  if (is_static) {
1312  /* If it is a function, we'd like to increase its
1313  name. If it's a variable, we'd like not to
1314  increase its name with the compilation unit
1315  name. But we do not have much information here to
1316  make the decision. Let's assume it's a function
1317  and postpone to UpdateEntity() */
1318  /* Depending on the type, we should or not
1319  introduce a MODULE_SEP_STRING, but the type is
1320  still not fully known. Wait for UpdateFunctionEntity(). */
1321  char * local_name;
1324  free(local_name);
1325  }
1326  else {
1327  /* We may have to remove it from the extern list:
1328  C_syntax/global_extern01.c */
1331  list el = code_externs(value_code(entity_initial(com_unit)));
1332  if(entity_is_argument_p(ent, el)) {
1333  type ent_t = entity_type(ent);
1334  if(!type_undefined_p(ent_t) && !type_functional_p(ent_t))
1335  /* code_externs(value_code(entity_initial(com_unit))) = */
1336  /* arguments_rm_entity(el, ent); */
1337  RemoveFromExterns(ent);
1338  }
1339  }
1340  }
1341  else
1342  {
1343  /* This is a variable/function declared inside a module's body: add block scope here
1344  Attention, the scope of a function declared in module is the module, not global.*/
1345  char * local_name;
1346  asprintf(&local_name,"%s%s",block_scope,name);
1348  /* The module name is unambiguous because it is used by pipdbm */
1350  else
1352  free(local_name);
1353  /* FI: why is ct not exploited? Because the
1354  information is later destroyed. I guess it is
1355  related to the type_stack stored in the entity_
1356  initial field. */
1357  /* entity_type(ent) = copy_type(ct); */
1358  }
1359  }
1360  }
1361  }
1362  pips_debug(5,"Entity global name \"%s\"\n\n",entity_name(ent));
1363  free(block_scope);
1364  return ent;
1365 }
string list_to_string(list l)
Return the malloc()ed version of the concatenation of all the strings in the list.
Definition: args.c:74
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
stack get_from_entity_type_stack_table(entity key)
Definition: c_parser.c:146
stack FunctionStack
Definition: c_parser.c:118
stack FormalStack
Definition: c_parser.c:119
#define c_parser_context_static(x)
#define c_parser_context_type(x)
struct _newgen_struct_type_ * type
#define c_parser_context_typedef(x)
#define c_parser_context_scope(x)
c_parser_context GetContext(void)
Definition: cyacc.tab.c:458
static void set_current_dummy_parameter_number(int n)
Definition: util.c:139
entity CreateEntityFromLocalNameAndPrefix(string name, string prefix, bool is_external)
Definition: util.c:962
void AddToExterns(entity e, entity mod)
Definition: util.c:2898
void RemoveFromExterns(entity e)
Definition: util.c:2884
void c_parser_put_new_typedef(const char *name)
Store named type for the lexical analyzer, which has to decide if a character string is the name of a...
Definition: util.c:1060
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
#define BLOCK_SEP_CHAR
Definition: naming-local.h:51
bool stack_empty_p(const stack)
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
#define stack_undefined_p(s)
Definition: newgen_stack.h:56
intptr_t _int
_INT
Definition: newgen_types.h:53
list safe_c_words_entity(type t, list name)
string empty_scope()
Functions used to manage the block scoping in conjunction with ContextStack and yco ntext.
Definition: entity.c:498
bool typedef_entity_p(entity e)
Definition: entity.c:1902
bool member_entity_p(entity e)
Definition: entity.c:1921
bool compilation_unit_entity_p(entity e)
Check if the given module entity is a compilation unit.
Definition: module.c:87
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define variable_basic(x)
Definition: ri.h:3120
#define ifdebug(n)
Definition: sg.c:47
the stack head
Definition: stack.c:62
Definition: delay.c:253

References AddToExterns(), asprintf, basic_pointer_p, BLOCK_SEP_CHAR, c_parser_context_scope, c_parser_context_static, c_parser_context_type, c_parser_context_typedef, c_parser_put_new_typedef(), code_externs, code_undefined_p, compilation_unit_entity_p(), compilation_unit_name, CreateEntityFromLocalNameAndPrefix(), DUMMY_PARAMETER_PREFIX, empty_scope(), entity_domain, entity_domain_number, entity_initial, entity_is_argument_p(), entity_list_p(), entity_name, entity_type, entity_undefined, entity_undefined_p, entity_user_name(), f(), FindOrCreateEntity(), FormalStack, free(), FunctionStack, gen_in_list_p(), get_current_compilation_unit_entity(), get_current_dummy_parameter_number(), get_current_module_entity(), get_current_module_name(), get_from_entity_type_stack_table(), GetContext(), ifdebug, intrinsic_entity_p(), is_external, list_to_string(), local_name(), member_entity_p(), module_name(), NIL, pips_assert, pips_debug, RemoveFromExterns(), safe_c_words_entity(), same_string_p, scope_to_block_scope(), set_current_dummy_parameter_number(), stack_empty_p(), stack_head(), stack_undefined_p, static_module_p(), strdup(), string_block_scope_p(), TOP_LEVEL_MODULE_NAME, type_functional_p, type_undefined, type_undefined_p, type_variable, type_variable_p, typedef_entity_p(), TYPEDEF_PREFIX, value_code, value_undefined_p, and variable_basic.

+ Here is the call graph for this function:

◆ FindOrCreateEntityFromLocalNameAndPrefix()

entity FindOrCreateEntityFromLocalNameAndPrefix ( string  name,
string  prefix,
bool  is_external 
)
Parameters
nameame
prefixrefix
is_externals_external

Definition at line 811 of file util.c.

812 {
813  entity e;
814 
816  return e;
818 }

References CreateEntityFromLocalNameAndPrefix(), entity_undefined, FindEntityFromLocalNameAndPrefix(), is_external, and prefix.

+ Here is the call graph for this function:

◆ FindOrCreateEntityFromLocalNameAndPrefixAndScope()

entity FindOrCreateEntityFromLocalNameAndPrefixAndScope ( string  name,
string  prefix,
string  scope,
bool  is_external 
)

The current scope will be automatically added

Parameters
nameame
prefixrefix
scopecope
is_externals_external

Definition at line 820 of file util.c.

824 {
826  string ls = strdup(scope);
827  string ls_head = ls;
828 
829  pips_assert("Should not be used", false);
830 
831  pips_assert("scope is a block scope", string_block_scope_p(scope));
832 
833  do {
834  string sname = strdup(concatenate(ls, name, NULL));
836  free(sname);
837  }
838  while(e != entity_undefined && (ls = pop_block_scope(ls)));
839 
840  if(entity_undefined_p(e)) {
841  /* The current scope will be automatically added */
843  }
844  free(ls_head);
845  pips_debug(8, "Entity returned: \"%s\"\n", entity_name(e));
846  return e;
847 }

References concatenate(), CreateEntityFromLocalNameAndPrefix(), entity_name, entity_undefined, entity_undefined_p, FindEntityFromLocalNameAndPrefix(), free(), is_external, pips_assert, pips_debug, pop_block_scope(), prefix, strdup(), and string_block_scope_p().

+ Here is the call graph for this function:

◆ FindParameterEntity()

parameter FindParameterEntity ( string  s,
int  offset,
list  l 
)

to be verified in C, when by reference, when by value

Parameters
offsetffset

Definition at line 3384 of file util.c.

3385 {
3386  FOREACH(ENTITY,e,l)
3387  {
3388  const char* name = entity_user_name(e);
3389  if (strcmp(name,s)==0)
3390  {
3391  type t = entity_type(e);
3392  mode m = make_mode_value(); /* to be verified in C, when by reference, when by value*/
3393  /*
3394  What about the storage of
3395 
3396  void AMMPmonitor( vfs,ffs,nfs,op )
3397  int (*vfs[])(),(*ffs[])();
3398  int nfs;
3399  FILE *op;*/
3400 
3401  storage st = entity_storage(e);
3402  if (storage_formal_p(st))
3403  {
3404  formal f = storage_formal(st);
3405  formal_offset(f) = offset;
3406  }
3407  return make_parameter(t,m,make_dummy_identifier(e)); // FI: Could be entity_undefined
3408  }
3409  }
3410  return parameter_undefined;
3411 }
dummy make_dummy_identifier(entity _field_)
Definition: ri.c:620
#define formal_offset(x)
Definition: ri.h:1408
#define parameter_undefined
Definition: ri.h:1794
#define storage_formal(x)
Definition: ri.h:2524

References ENTITY, entity_storage, entity_type, entity_user_name(), f(), FOREACH, formal_offset, make_dummy_identifier(), make_mode_value(), make_parameter(), offset, parameter_undefined, storage_formal, and storage_formal_p.

Referenced by MakeParameterList().

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

◆ get_current_compilation_unit_entity()

entity get_current_compilation_unit_entity ( void  )

Definition at line 320 of file util.c.

References compilation_unit_name, FindOrCreateEntity(), and TOP_LEVEL_MODULE_NAME.

Referenced by callnodeclfilter(), FindOrCreateCurrentEntity(), MakeFunctionExpression(), MakeStorageRam(), and referencenodeclfilter().

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

◆ get_current_dummy_parameter_number()

static int get_current_dummy_parameter_number ( void  )
static

Definition at line 147 of file util.c.

static int current_dummy_parameter_number
The data structure to tackle the memory allocation problem due to reparsing of compilation unit.
Definition: util.c:137

References current_dummy_parameter_number.

Referenced by FindEntityFromLocalNameAndPrefix(), and FindOrCreateCurrentEntity().

+ Here is the caller graph for this function:

◆ get_top_level_entity()

entity get_top_level_entity ( void  )

Definition at line 152 of file util.c.

References FindOrCreateEntity(), and TOP_LEVEL_MODULE_NAME.

Referenced by MakeStorageRam(), and step_parameter().

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

◆ IdentifierToExpression()

expression IdentifierToExpression ( string  s)

Could this be non declared variables ?

This identifier has not been passed by the parser. It is probably a function call => try this case now and complete others later. The scope of this function is global

This may be a call or a reference in case a functional pointer is initialized

eturn MakeNullaryCall(ent);

FI: This may happen when a variable is used to initialize another variable within the same declaration statement: see decl29.c. This might not be a general fix as the type could be functional: to be checked. But setting up type earlier would require a huge change in the parser rules. Unless FindOrCreateCurrentEntity() could do a better job? But the information added is later destroyed by the parser.

Generate a call to an enum member

Definition at line 650 of file util.c.

651 {
654 
655  pips_debug(5,"Identifier is \"%s\" and entity_name is \"\%s\"\n",
656  s, safe_entity_name(ent));
657 
658  if (entity_undefined_p(ent)) {
659  /* Could this be non declared variables ?*/
660  /* This identifier has not been passed by the parser.
661  It is probably a function call => try this case now and complete others later.
662  The scope of this function is global */
663  pips_debug(5,"Create unparsed global function: %s\n",s);
665  //entity_storage(ent) = make_storage_return(ent);
669  /* This may be a call or a reference in case a functional pointer is initialized */
671  /*return MakeNullaryCall(ent);*/
672  }
673  else if(type_undefined_p(entity_type(ent))) {
674  /* FI: This may happen when a variable is used to initialize another
675  variable within the same declaration statement: see
676  decl29.c. This might not be a general fix as the type could be
677  functional: to be checked. But setting up type earlier would require a huge
678  change in the parser rules. Unless FindOrCreateCurrentEntity()
679  could do a better job? But the information added is later
680  destroyed by the parser. */
683  }
684  else {
685  switch (type_tag(entity_type(ent))) {
686  case is_type_variable:
687  case is_type_functional:
688  {
689  value iv = entity_initial(ent);
690 
691  if(!value_undefined_p(iv) && value_symbolic_p(iv))
692  /* Generate a call to an enum member */
694  else
697 
698  break;
699  }
700  default:
701  {
702  CParserError("Which kind of expression?\n");
703  }
704  }
705  }
706  return exp;
707 }
call make_call(entity a1, list a2)
Definition: ri.c:269
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
storage make_storage_rom(void)
Definition: ri.c:2285
type make_type_functional(functional _field_)
Definition: ri.c:2718
value make_value(enum value_utype tag, void *val)
Definition: ri.c:2832
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
code make_code(list a1, string a2, sequence a3, list a4, language a5)
Definition: ri.c:353
language make_language_c(void)
Definition: ri.c:1253
type make_type_unknown(void)
Definition: ri.c:2724
sequence make_sequence(list a)
Definition: ri.c:2125
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
entity FindEntityFromLocalName(string name)
Definition: util.c:778
string safe_entity_name(entity e)
predicates and functions for entities
Definition: entity.c:433
#define normalized_undefined
Definition: ri.h:1745
#define type_tag(x)
Definition: ri.h:2940
@ is_value_code
Definition: ri.h:3031
#define expression_undefined
Definition: ri.h:1223
#define value_symbolic_p(x)
Definition: ri.h:3068
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207

References CParserError(), entity_initial, entity_storage, entity_type, entity_undefined_p, exp, expression_undefined, FindEntityFromLocalName(), FindOrCreateEntity(), is_type_functional, is_type_variable, is_value_code, make_call(), make_code(), make_expression(), make_functional(), make_language_c(), make_reference(), make_sequence(), make_storage_rom(), make_syntax_call(), make_syntax_reference(), make_type_functional(), make_type_unknown(), make_value(), NIL, normalized_undefined, pips_debug, safe_entity_name(), strdup(), TOP_LEVEL_MODULE_NAME, type_tag, type_undefined_p, value_symbolic_p, and value_undefined_p.

Referenced by MemberDerivedIdentifierToExpression().

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

◆ init_c_areas()

void init_c_areas ( void  )

In C we have 4 areas.

  1. globalStaticArea: For the Global Variables, these variables are added into StaticArea.
  2. moduleStaticArea: For the Static module variables
  3. localStaticArea(SticArea): General Static variables
  4. DynamicArea The GlobalStaticArea and ModuleStaticArea are basically static areas but they are not defined globally. It is to be added to the Declarations for C

Create a hidden pointer in the heap area to modelize malloc and free effects and to keep track of the corresponding abstract state.

FI: I use a complex type to avoid seeing this variable in the transformers and preconditions... OK, it's not a clean way to do it. Should we create another area to allocate this abstract heap state?

FI: I keep the code below, because it may turn useful again if context-insensitive address values must be generated.

This is because of the reparsing of the compilation unit The area is set to zero and all the declarations are overrided and the memory is reallocated The area is reset to only when it is called by same compilation unit twice. The code is dangerous hence it is commented. Please have a look

if( get_current_compilation_unit_entity() == get_current_module_entity() && (get_current_compilation_unit_entity() == previouscompilationunit)) area_size(type_area(entity_type(msae))) = 0;

if( get_current_compilation_unit_entity() == get_current_module_entity() && (get_current_compilation_unit_entity() == previouscompilationunit)) area_size(type_area(entity_type(gsae))) = previoussizeofGlobalArea ;

Definition at line 186 of file util.c.

187 {
194 
201 
202  //HeapArea = FindOrCreateEntity(compilation_unit_name, HEAP_AREA_LOCAL_NAME);
209 
210  /* Create a hidden pointer in the heap area to modelize malloc and
211  free effects and to keep track of the corresponding abstract
212  state. */
213  /* FI: I use a complex type to avoid seeing this variable in the
214  transformers and preconditions... OK, it's not a clean way to
215  do it. Should we create another area to allocate this abstract
216  heap state? */
217  /* FI: I keep the code below, because it may turn useful again if
218  context-insensitive address values must be generated. */
219  /*
220  if(!compilation_unit_entity_p(get_current_module_entity())) {
221  make_entity(AddPackageToName(get_current_module_name(),
222  MALLOC_EFFECTS_NAME),
223  make_scalar_complex_type(DEFAULT_COMPLEX_TYPE_SIZE),
224 
225  Chose a storage... Maybe in MALLOC_EFFECTS_PACKAGE_NAME?
226 
227  make_storage(is_storage_ram,
228  make_ram(entity_undefined, DynamicArea, 0, NIL))
229 
230  make_storage(is_storage_ram,
231  make_ram(get_current_module_entity(),
232  HeapArea,
233  0, NIL)),
234  make_value(is_value_unknown, UU));
235  }
236  */
237 
238  // Dynamic variables whose size are not known are stored in Stack area
245 
249 
253 
254  /* This is because of the reparsing of the compilation unit
255  The area is set to zero and all the declarations are overrided and the memory is reallocated
256  The area is reset to only when it is called by same compilation unit twice.
257  The code is dangerous hence it is commented. Please have a look
258 
259  if( get_current_compilation_unit_entity() == get_current_module_entity() &&
260  (get_current_compilation_unit_entity() == previouscompilationunit))
261  area_size(type_area(entity_type(msae))) = 0;
262 
263  if( get_current_compilation_unit_entity() == get_current_module_entity() &&
264  (get_current_compilation_unit_entity() == previouscompilationunit))
265  area_size(type_area(entity_type(gsae))) = previoussizeofGlobalArea ;
266  */
267 }
area make_area(intptr_t a1, list a2)
Definition: ri.c:98
entity DynamicArea
These global variables are declared in ri-util/util.c.
Definition: area.c:57
entity HeapArea
Definition: area.c:59
entity StaticArea
Definition: area.c:58
#define DYNAMIC_AREA_LOCAL_NAME
Definition: naming-local.h:69
#define STACK_AREA_LOCAL_NAME
Definition: naming-local.h:72
#define STATIC_AREA_LOCAL_NAME
Definition: naming-local.h:70
#define HEAP_AREA_LOCAL_NAME
Definition: naming-local.h:71
@ ENTITY_STATIC_AREA
@ ABSTRACT_LOCATION
@ ENTITY_DYNAMIC_AREA
@ ENTITY_STACK_AREA
@ ENTITY_HEAP_AREA
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
#define entity_kind(x)
Definition: ri.h:2798
@ is_type_area
Definition: ri.h:2899

References ABSTRACT_LOCATION, AddEntityToDeclarations(), compilation_unit_name, DYNAMIC_AREA_LOCAL_NAME, DynamicArea, ENTITY_DYNAMIC_AREA, ENTITY_HEAP_AREA, entity_initial, entity_kind, ENTITY_STACK_AREA, ENTITY_STATIC_AREA, entity_storage, entity_type, FindOrCreateEntity(), get_current_module_entity(), get_current_module_name(), HEAP_AREA_LOCAL_NAME, HeapArea, is_type_area, make_area(), make_storage_rom(), make_type(), make_value_unknown(), NIL, STACK_AREA_LOCAL_NAME, StackArea, STATIC_AREA_LOCAL_NAME, StaticArea, and TOP_LEVEL_MODULE_NAME.

Referenced by MakeCurrentCompilationUnitEntity(), and MakeCurrentModule().

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

◆ init_c_implicit_variables()

void init_c_implicit_variables ( entity  m)

Function name variable function and FUNCTION

Should be static, but not compatible with FREIA inlining.

It is not clear if the encoding is correct or not. It may also be correct but not supported. This could be checked by computing the preconditions for strings and/or by adding initial values to the symbol table display.

Since the declarations are not added to a statement_declarations field, they are not going to be prettyprinted.

Definition at line 277 of file util.c.

278 {
279  /* Function name variable __function__ and __FUNCTION__ */
280  const char * mn = entity_local_name(m);
281  string bs = "0`"; // first local scope in a module: should be
282  // returned by a function to stay consistent in
283  // case of change
284  string fn1 = strdup(concatenate(bs, IMPLICIT_VARIABLE_NAME_1, NULL));
285  string fn2 = strdup(concatenate(bs, IMPLICIT_VARIABLE_NAME_2, NULL));
286  entity func_name1 = FindOrCreateEntity(mn, fn1);
287  entity func_name2 = FindOrCreateEntity(mn, fn2);
288  const char * name = entity_user_name(m);
289  string cn = strdup(concatenate("\"", mn, "\"", NULL));
292  strlen(name)+1);
293  free(cn);
294  entity a = DynamicArea; /* Should be static, but not compatible with
295  FREIA inlining. */
296 
297  entity_type(func_name1) = make_char_array_type(strlen(name)+1);
298  entity_storage(func_name1) =
300  /* It is not clear if the encoding is correct or not. It may also
301  be correct but not supported. This could be checked by computing
302  the preconditions for strings and/or by adding initial values to
303  the symbol table display. */
305  AddEntityToDeclarations(func_name1, m);
306 
307  entity_type(func_name2) = make_char_array_type(strlen(name)+1);
308  entity_storage(func_name2) =
311  AddEntityToDeclarations(func_name2, m);
312  /* Since the declarations are not added to a statement_declarations
313  field, they are not going to be prettyprinted. */
314 
315  free(fn1);
316  free(fn2);
317 }
value make_value_expression(expression _field_)
Definition: ri.c:2850
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
storage make_storage_ram(ram _field_)
Definition: ri.c:2279
entity make_C_constant_entity(string name, tag bt, size_t size)
Definition: util.c:269
#define IMPLICIT_VARIABLE_NAME_1
Implicit variable names for C.
#define IMPLICIT_VARIABLE_NAME_2
expression make_call_expression(entity e, list l)
Build an expression that call an function entity with an argument list.
Definition: expression.c:321
type make_char_array_type(int)
Definition: type.c:5213
@ is_basic_string
Definition: ri.h:576

References AddEntityToDeclarations(), concatenate(), DynamicArea, entity_initial, entity_local_name(), entity_storage, entity_type, entity_user_name(), FindOrCreateEntity(), free(), IMPLICIT_VARIABLE_NAME_1, IMPLICIT_VARIABLE_NAME_2, is_basic_string, make_C_constant_entity(), make_call_expression(), make_char_array_type(), make_ram(), make_storage_ram(), make_value_expression(), NIL, strdup(), and UNKNOWN_RAM_OFFSET.

Referenced by MakeCurrentModule().

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

◆ InitializeEnumMemberValues()

void InitializeEnumMemberValues ( list  lem)

The expression evaluation may have been delayed

Parameters
lemem

Definition at line 3104 of file util.c.

3105 {
3106  // enum member with implicit values are not yet fully instantiated
3107  list cem = list_undefined;
3108  _int cv = 0;
3109 
3110  for(cem = lem; !ENDP(cem); POP(cem)) {
3111  entity em = ENTITY(CAR(cem));
3112  value emv = entity_initial(em);
3113 
3114  if(value_undefined_p(emv)) {
3115  entity_initial(em) =
3117  make_constant(is_constant_int, (void *) cv)));
3118  }
3119  else {
3120  symbolic s = value_symbolic(emv);
3121  constant c = symbolic_constant(s);
3122 
3125  symbolic_constant(s) = make_constant(is_constant_int, (void *) cv);
3126  }
3127  else if(constant_unknown_p(c)) {
3128  /* The expression evaluation may have been delayed */
3132  }
3134  pips_assert("The symbolic field is consisten", symbolic_consistent_p(s));
3135  }
3136  cv++;
3137  }
3138 }
constant make_constant(enum constant_utype tag, void *val)
Definition: ri.c:406
bool symbolic_consistent_p(symbolic p)
Definition: ri.c:2342
symbolic make_symbolic(expression a1, constant a2)
Definition: ri.c:2369
value make_value_symbolic(symbolic _field_)
Definition: ri.c:2838
value EvalExpression(expression e)
Evaluate statically an expression.
Definition: eval.c:108
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
#define value_constant(x)
Definition: ri.h:3073
#define symbolic_constant(x)
Definition: ri.h:2599
#define constant_int(x)
Definition: ri.h:850
#define constant_unknown_p(x)
Definition: ri.h:863
@ is_constant_int
Definition: ri.h:817
#define value_constant_p(x)
Definition: ri.h:3071
#define value_symbolic(x)
Definition: ri.h:3070
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined_p(x)
Definition: ri.h:1224
#define symbolic_expression(x)
Definition: ri.h:2597

References CAR, constant_int, constant_int_p, constant_unknown_p, ENDP, ENTITY, entity_initial, EvalExpression(), expression_undefined_p, int_to_expression(), is_constant_int, list_undefined, make_constant(), make_symbolic(), make_value_symbolic(), pips_assert, POP, symbolic_consistent_p(), symbolic_constant, symbolic_expression, value_constant, value_constant_p, value_symbolic, and value_undefined_p.

+ Here is the call graph for this function:

◆ insert_qualifier()

list insert_qualifier ( list  ql,
qualifier  nq 
)

if qualifier "nq" does not already belong to qualifier list "ql", add it in front of the list.

The list is probably reversed somewhere else... for instance by the parsing grammar rules

FI: either the context was not stacked or it was not used and emptied...

Parameters
qll
nqq

Definition at line 3567 of file util.c.

3568 {
3569  bool found = false; // FI: Should never be useful...
3570  list nql = ql;
3571 
3572  FOREACH(QUALIFIER, q, ql) {
3573  if(qualifier_equal_p(q, nq)) {
3574  /* FI: either the context was not
3575  stacked or it was not used and
3576  emptied... */
3577  c_parser_user_warning("Dupliquate qualifier \"%s\"\n",
3578  qualifier_to_string(q));
3579  found = true;
3580  }
3581  }
3582 
3583  if(!found)
3584  //c_parser_context_qualifiers(ycontext) =
3585  nql = CONS(QUALIFIER, nq, ql);
3586 
3587  return nql;
3588 }
string qualifier_to_string(qualifier)
Definition: type.c:5427
bool qualifier_equal_p(qualifier, qualifier)
Definition: type.c:5420
#define QUALIFIER(x)
QUALIFIER.
Definition: ri.h:2106

References c_parser_user_warning, CONS, FOREACH, QUALIFIER, qualifier_equal_p(), and qualifier_to_string().

+ Here is the call graph for this function:

◆ make_C_constant_entity()

entity make_C_constant_entity ( string  name,
tag  bt,
size_t  size 
)
Parameters
nameame
btt
sizeize

Definition at line 269 of file util.c.

272 {
273  return make_C_or_Fortran_constant_entity(name, bt, size, false, c_parser_error);
274 }
bool c_parser_error(const char *func, const char *msg)
Output a parser message error.
Definition: c_parser.c:266
entity make_C_or_Fortran_constant_entity(const char *name, tag bt, size_t size, bool is_fortran, bool(*error_manager)(const char *, const char *))
This function creates a constant.
Definition: constant.c:148

References c_parser_error(), and make_C_or_Fortran_constant_entity().

Referenced by init_c_implicit_variables().

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

◆ MakeArrayExpression()

expression MakeArrayExpression ( expression  exp,
list  lexp 
)

FI: this function is called for a bracketed comma expression.

The two arguments are (should be) reused within the returned expression

There are two cases:

  1. Simple array reference, where the first argument is a simple array or pointer name. We create a reference expression (syntax = reference).
  2. Complicated subscripting array, where the first argument can be a function call (foo()[]), a structure or union member (str[5].field[7], ... We create a subscripting expression (syntax = subscript).

FI: Memory leak with exp?

FI: we might have preexisting subscript? No, in this context, only one index due to lack of type information?

Parameters
expxp
lexpexp

Definition at line 713 of file util.c.

714 {
715  /* There are two cases:
716 
717  1. Simple array reference, where the first argument is a simple
718  array or pointer name. We create a reference expression (syntax =
719  reference).
720 
721  2. Complicated subscripting array, where the first argument can be
722  a function call (foo()[]), a structure or union member
723  (str[5].field[7], ... We create a subscripting expression (syntax =
724  subscript).
725  */
726 
729  list sl = lexp;
730 
731  if(!ENDP(CDR(lexp))) {
733  sl = CONS(EXPRESSION, se, NIL);
734  }
735 
736  switch(syntax_tag(s)) {
737  case is_syntax_reference:
738  {
739  /* FI: Memory leak with exp? */
741  entity ent = reference_variable(r);
742  list l = reference_indices(r);
743  pips_debug(6,"Normal reference expression\n");
745  break;
746  }
747  case is_syntax_call:
748  case is_syntax_range:
749  case is_syntax_cast:
751  case is_syntax_subscript:
753  {
754  /* FI: we might have preexisting subscript? No, in this
755  context, only one index due to lack of type information? */
756  subscript a = make_subscript(exp,sl);
758  pips_debug(6,"Subscripting array expression\n");
760  break;
761  }
762  default:
763  {
764  pips_internal_error("unexpected syntax tag: %d", syntax_tag(s));
765  }
766  }
767  return e;
768 }
subscript make_subscript(expression a1, list a2)
Definition: ri.c:2327
syntax make_syntax_subscript(subscript _field_)
Definition: ri.c:2509
static list lexp
expression reference_to_expression(reference r)
Definition: expression.c:196
expression MakeCommaExpression(list l)
Definition: expression.c:3918
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define reference_variable(x)
Definition: ri.h:2326
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_application
Definition: ri.h:2697
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define reference_indices(x)
Definition: ri.h:2328
#define expression_syntax(x)
Definition: ri.h:1247

References CDR, CONS, ENDP, exp, EXPRESSION, expression_syntax, expression_undefined, gen_nconc(), is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, lexp, make_expression(), make_reference(), make_subscript(), make_syntax_subscript(), MakeCommaExpression(), NIL, normalized_undefined, pips_debug, pips_internal_error, reference_indices, reference_to_expression(), reference_variable, syntax_reference, and syntax_tag.

+ Here is the call graph for this function:

◆ MakeCurrentCompilationUnitEntity()

void MakeCurrentCompilationUnitEntity ( const char *  name)

A compilation unit is also considered as a module.

value v = entity_initial(e);

if(value_code_p(v)) {

code c = value_code(v);

language l = code_language(c);

if(language_unknown_p(l))

code_language(c) = make_language_c();

else if(language_fortran_p(l) || language_fortran95_p(l))

pips_internal_error("A compilation unit should have language \"C".
");

}

else

pips_internal_error("A compilation unit should have value \"code".
");

Parameters
nameame

Definition at line 328 of file util.c.

329 {
331  /* value v = entity_initial(e); */
332  /* if(value_code_p(v)) { */
333  /* code c = value_code(v); */
334  /* language l = code_language(c); */
335  /* if(language_unknown_p(l)) */
336  /* code_language(c) = make_language_c(); */
337  /* else if(language_fortran_p(l) || language_fortran95_p(l)) */
338  /* pips_internal_error("A compilation unit should have language \"C\".\n"); */
339  /* } */
340  /* else */
341  /* pips_internal_error("A compilation unit should have value \"code\".\n"); */
342 
343  pips_debug(4,"Set current module entity for compilation unit %s\n",name);
345  //init_stack_storage_table();
346  init_c_areas();
347 }
void init_c_areas()
In C we have 4 areas.
Definition: util.c:186
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity MakeCompilationUnitEntity(const char *name)
This is useful for the C language only.
Definition: entity.c:1954

References init_c_areas(), MakeCompilationUnitEntity(), pips_debug, and set_current_module_entity().

Referenced by actual_c_parser().

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

◆ MakeDerivedEntity()

entity MakeDerivedEntity ( string  name,
list  members,
bool  is_external,
int  i 
)

FI: What should the initial value be?

Parameters
nameame
membersembers
is_externals_external

Definition at line 3140 of file util.c.

3141 {
3142  entity ent = entity_undefined;
3143  switch (i) {
3144  case is_type_struct:
3145  {
3147  entity_type(ent) = make_type_struct(members);
3148  break;
3149  }
3150  case is_type_union:
3151  {
3153  entity_type(ent) = make_type_union(members);
3154  break;
3155  }
3156  case is_type_enum:
3157  {
3159  entity_type(ent) = make_type_enum(members);
3160  break;
3161  }
3162  }
3164  /* FI: What should the initial value be? */
3168 
3169  return ent;
3170 }
type make_type_union(list _field_)
Definition: ri.c:2733
type make_type_struct(list _field_)
Definition: ri.c:2730
type make_type_enum(list _field_)
Definition: ri.c:2736
@ is_type_enum
Definition: ri.h:2907
@ is_type_union
Definition: ri.h:2906
@ is_type_struct
Definition: ri.h:2905

References AddEntityToDeclarations(), CreateEntityFromLocalNameAndPrefix(), entity_initial, entity_storage, entity_type, entity_undefined, ENUM_PREFIX, get_current_module_entity(), is_external, is_type_enum, is_type_struct, is_type_union, make_storage_rom(), make_type_enum(), make_type_struct(), make_type_union(), make_value_unknown(), STRUCT_PREFIX, UNION_PREFIX, and value_undefined_p.

+ Here is the call graph for this function:

◆ MakeDimension()

dimension MakeDimension ( list  le,
list  ql 
)

Take only the first expression of le, do not know why it can be a list ?

use the integer value

If we do this, we cannot restitute the source code

Build a new expression e' == e-1

Parameters
lee
qll

Definition at line 1389 of file util.c.

1390 {
1391  dimension d;
1392  if (le == NIL)
1393  {
1395  pips_debug(5,"Unbounded dimension\n");
1396  }
1397  else
1398  {
1399  /* Take only the first expression of le, do not know why it can be a list ?*/
1400  expression e = EXPRESSION(CAR(le));
1401  intptr_t up;
1402 
1403  if (false && expression_integer_value(e,&up))
1404  /* use the integer value */ /* If we do this, we cannot restitute the source code */
1406  else
1407  /* Build a new expression e' == e-1 */
1410  e,
1411  int_to_expression(1)),
1412  ql);
1413 
1414  ifdebug(9)
1415  {
1416  pips_debug(5,"Array dimension:");
1417  print_expression(e);
1418  pips_debug(8,"Array lower bound:");
1420  pips_debug(5,"Array dimension:");
1422  }
1423  }
1424  return d;
1425 }
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
#define MINUS_C_OPERATOR_NAME
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
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression make_unbounded_expression()
Definition: expression.c:4339
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
#define dimension_lower(x)
Definition: ri.h:980
#define dimension_upper(x)
Definition: ri.h:982
#define intptr_t
Definition: stdint.in.h:294

References CAR, CreateIntrinsic(), dimension_lower, dimension_upper, EXPRESSION, expression_integer_value(), ifdebug, int_to_expression(), intptr_t, make_dimension(), make_unbounded_expression(), MakeBinaryCall(), MINUS_C_OPERATOR_NAME, NIL, pips_debug, and print_expression().

Referenced by UpdateArrayEntity().

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

◆ MakeEnumeratorInitialValue()

value MakeEnumeratorInitialValue ( list  enum_list,
int  counter 
)

The initial value = 0 if this is the first member in the enumerator list else, it is equal to : intial_value(predecessor) + 1

Find the predecessor of the counter-th member

Parameters
enum_listnum_list
counterounter

Definition at line 3299 of file util.c.

3300 {
3301  /* The initial value = 0 if this is the first member in the enumerator list
3302  else, it is equal to : intial_value(predecessor) + 1 */
3303  value v = value_undefined;
3304  if (counter == 1)
3306  else
3307  {
3308  /* Find the predecessor of the counter-th member */
3309  entity pre = ENTITY(gen_nth(counter-1, enum_list));
3310  value vp = entity_initial(pre);
3311  if (value_constant_p(vp))
3312  {
3313  constant c = value_constant(vp);
3314  if (constant_int_p(c))
3315  {
3316  int i = constant_int(c);
3318  }
3319  }
3320  }
3321  return v;
3322 }
value make_value_constant(constant _field_)
Definition: ri.c:2841
constant make_constant_int(intptr_t _field_)
Definition: ri.c:409
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#define value_undefined
Definition: ri.h:3016

References constant_int, constant_int_p, ENTITY, entity_initial, gen_nth(), make_constant_int(), make_value_constant(), value_constant, value_constant_p, and value_undefined.

+ Here is the call graph for this function:

◆ MakeFunctionExpression()

expression MakeFunctionExpression ( expression  e,
list  le 
)

e is now owned by returned expression and must not be used any longer

There are 2 cases:

  1. The first argument corresponds to a function name (an entity).

    In this case, we create a normal call expression and the corresponding entity is added to the list of callees.

  2. The first argument can be any expression denoting a called function (a pointer to a function,... such as (*ctx->Driver.RenderString)() in the benchmark mesa in SPEC2000). In this case, we create a function application expression.

Must be a pointer to a function

Undeclared functions return int by default

This cannot be checked unless bootstrap typing is improved for varargs intrinsics, mostly IOs.

Parameters
lee

Definition at line 368 of file util.c.

369 {
370  /* There are 2 cases:
371 
372  1. The first argument corresponds to a function name (an entity).
373 
374  In this case, we create a normal call expression and the
375  corresponding entity is added to the list of callees.
376 
377  2. The first argument can be any expression denoting a called
378  function (a pointer to a function,... such as
379  (*ctx->Driver.RenderString)() in the benchmark mesa in
380  SPEC2000). In this case, we create a function application
381  expression.
382  */
384  syntax s = expression_syntax(e);
385  switch (syntax_tag(s))
386  {
387  case is_syntax_reference:
388  {
390  free_expression(e);
392 
393  ifdebug(8) {
394  pips_debug(8, "Call to \"\%s\" with %zd argument(s)\n",
395  entity_name(ent), gen_length(le));
396  print_expressions(le);
397  }
398 
399  if(!intrinsic_entity_p(ent)) {
402  type ut = ultimate_type(entity_type(ent));
403 
404  if(type_functional_p(ut))
405  AddToCalledModules(ent);
406  else {
407  /* Must be a pointer to a function */
408  const char * eun = entity_user_name(ent);
409  c_parser_user_warning("Call to an unknown function via function pointer \"\%s\"\n",
410  eun);
411  }
412 
413  if(!gen_in_list_p(ent, cudl)) {
414  /* Undeclared functions return int by default */
415  type ft = entity_type(ent);
417 
418  pips_assert("function's type is ultimately functional or pointer to functional",
420  f = type_functional(ft);
423  AddToDeclarations(ent, cf);
424  }
425  }
426  pips_debug(6,"Normal function or intrinsics call\n");
427  (void)check_C_function_type(ent,le);
428  exp = make_call_expression(ent,le);
429  /* This cannot be checked unless bootstrap typing is improved
430  for varargs intrinsics, mostly IOs. */
431  /*
432  if(!ok) {
433  c_parser_user_warning("Actual arguments do not fit the declared formal "
434  "arguments of function \"%s\"\n",
435  entity_user_name(ent));
436  CParserError("Type mismatch\n");
437  }
438  */
439  break;
440  }
441  case is_syntax_call:
442  {
443  application a = make_application(e,le);
444  pips_debug(6,"Application function call\n");
446  break;
447  }
448  case is_syntax_range:
449  case is_syntax_cast:
451  case is_syntax_subscript:
453  CParserError("This is not a functional expression\n");
454  break;
455  default:
456  {
457  pips_internal_error("unexpected syntax tag: %d", syntax_tag(s));
458  }
459  }
460  return exp;
461 }
syntax make_syntax_application(application _field_)
Definition: ri.c:2512
application make_application(expression a1, list a2)
Definition: ri.c:56
void free_expression(expression p)
Definition: ri.c:853
void AddToCalledModules(entity e)
Definition: util.c:3413
void print_expressions(list le)
Definition: expression.c:98
bool call_compatible_type_p(type)
end of basic_concrete_types
Definition: type.c:3764
bool check_C_function_type(entity, list)
Check that an effective parameter list is compatible with a function type.
Definition: type.c:4716
type MakeIntegerResult(void)
Definition: type.c:276
#define type_unknown_p(x)
Definition: ri.h:2956

References AddToCalledModules(), AddToDeclarations(), c_parser_user_warning, call_compatible_type_p(), check_C_function_type(), code_declarations, CParserError(), entity_initial, entity_name, entity_type, entity_user_name(), exp, expression_syntax, expression_undefined, f(), free_expression(), functional_result, gen_in_list_p(), gen_length(), get_current_compilation_unit_entity(), get_current_module_entity(), ifdebug, intrinsic_entity_p(), is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, make_application(), make_call_expression(), make_expression(), make_syntax_application(), MakeIntegerResult(), normalized_undefined, pips_assert, pips_debug, pips_internal_error, print_expressions(), reference_variable, syntax_reference, syntax_tag, type_functional, type_functional_p, type_unknown_p, ultimate_type(), and value_code.

+ Here is the call graph for this function:

◆ MakeParameterList()

list MakeParameterList ( list  l1,
list  l2,
stack  FunctionStack 
)

l1 is a list of parameter names and it represents the exact order in the parameter list l2 is a list of entities with their type, storage,... and the order can be different from l1 In addition, l2 can be incomplete wrt l1, so other entities must be created from l1, with default type : scalar integer variable.

We create the list of parameters with the order of l1, and the parameter type and mode are retrieved from l2.

Since the offset of formal argument in l2 can be false, we have to update it here by using l1

s is not declared in l2, create the corresponding entity/ formal variable and add it to the declaration list, because it cannot be added with par_def in l2

Parameters
l11
l22
FunctionStackunctionStack

Definition at line 3348 of file util.c.

3349 {
3350  /* l1 is a list of parameter names and it represents the exact order in the parameter list
3351  l2 is a list of entities with their type, storage,... and the order can be different from l1
3352  In addition, l2 can be incomplete wrt l1, so other entities must be created from l1, with
3353  default type : scalar integer variable.
3354 
3355  We create the list of parameters with the order of l1, and the parameter type and mode
3356  are retrieved from l2.
3357 
3358  Since the offset of formal argument in l2 can be false, we have to update it here by using l1 */
3359  list l = NIL;
3360  int offset = 1;
3361  entity function = stack_head(FunctionStack);
3362  FOREACH(STRING, s,l1)
3363  {
3365  if (parameter_undefined_p(p))
3366  {
3367  /* s is not declared in l2, create the corresponding entity/ formal variable
3368  and add it to the declaration list, because it cannot be added with par_def in l2*/
3369  entity ent = FindOrCreateEntity(entity_user_name(function),s);
3371  entity_type(ent) = make_type_variable(v);
3373  AddToDeclarations(ent,function);
3374  p = make_parameter(entity_type(ent),
3375  make_mode_value(),
3376  make_dummy_identifier(ent)); // FI: could be unknown?
3377  }
3378  l = gen_nconc(l,CONS(PARAMETER,p,NIL));
3379  offset++;
3380  }
3381  return l;
3382 }
type make_type_variable(variable _field_)
Definition: ri.c:2715
basic make_basic_int(intptr_t _field_)
Definition: ri.c:158
storage make_storage_formal(formal _field_)
Definition: ri.c:2282
formal make_formal(entity a1, intptr_t a2)
Definition: ri.c:1067
parameter FindParameterEntity(string s, int offset, list l)
Definition: util.c:3384
#define parameter_undefined_p(x)
Definition: ri.h:1795

References AddToDeclarations(), CONS, DEFAULT_INTEGER_TYPE_SIZE, entity_storage, entity_type, entity_user_name(), FindOrCreateEntity(), FindParameterEntity(), FOREACH, FunctionStack, gen_nconc(), make_basic_int(), make_dummy_identifier(), make_formal(), make_mode_value(), make_parameter(), make_storage_formal(), make_type_variable(), make_variable(), NIL, offset, PARAMETER, parameter_undefined_p, stack_head(), and STRING.

+ Here is the call graph for this function:

◆ MakeStorageRam()

storage MakeStorageRam ( entity  v,
bool  is_external,
bool  is_static 
)

The storage part should not be called twice when reparsing compilation unit.

We assume that double declarations are dealt with someone else

ComputeAreaOffset(StaticArea,e)

he offset must be recomputed lately, when we know for sure the size of the variables

This must be a variable, not a function/typedef/struct/union/enum. The variable is declared outside any function, and hence is global

ComputeAreaOffset(get_top_level_entity(),e)

the offset must be recomputed lately, when we know for sure the size of the variable

Global variable can be declared in many different file

ADD BLOCK SCOPE

ComputeAreaOffset(StaticArea,e)

he offset must be recomputed lately, when we know for sure the size of the variable

ComputeAreaOffset(DynamicArea,e)

the offset must be recomputed lately, when we know for sure the size of the variable

Parameters
is_externals_external
is_statics_static

Definition at line 3177 of file util.c.

3178 {
3179  ram r = ram_undefined;
3183  area msa = type_area(entity_type(moduleStaticArea));
3185  area gsa = type_area(entity_type(globalStaticArea));
3187  //area heap = type_area (entity_type(HeapArea));
3188  //entity m = get_current_module_entity();
3189 
3190  pips_assert("RAM Storage is used only for variables", type_variable_p(entity_type(v)));
3191 
3192  if (is_external)
3193  {
3194  if (is_static)
3195  {
3197  moduleStaticArea,
3198  UNKNOWN_RAM_OFFSET /* ComputeAreaOffset(StaticArea,e) */,
3199  NIL);
3200 
3201  /*the offset must be recomputed lately, when we know for
3202  sure the size of the variables */
3204  || !gen_in_list_p(v,area_layout(msa)))
3205  area_layout(msa) = gen_nconc(area_layout(msa), CONS(ENTITY, v, NIL));
3206  }
3207  else
3208  {
3209  /* This must be a variable, not a function/typedef/struct/union/enum.
3210  The variable is declared outside any function, and hence is global*/
3211 
3213  globalStaticArea,
3214  UNKNOWN_RAM_OFFSET /* ComputeAreaOffset(get_top_level_entity(),e) */,
3215  NIL);
3216  /* the offset must be recomputed lately, when we know for
3217  sure the size of the variable */
3218  /* Global variable can be declared in many different file */
3219  if(!gen_in_list_p(v,area_layout(gsa)))
3220  area_layout(gsa) = gen_nconc(area_layout(gsa), CONS(ENTITY, v, NIL));
3221  }
3222  }
3223  else
3224  {
3225  /* ADD BLOCK SCOPE */
3226  if (is_static)
3227  {
3229  StaticArea,
3230  UNKNOWN_RAM_OFFSET /* ComputeAreaOffset(StaticArea,e) */,
3231  NIL);
3232  /*the offset must be recomputed lately, when we know for
3233  sure the size of the variable */
3234  area_layout(lsa) = gen_nconc(area_layout(lsa), CONS(ENTITY, v, NIL));
3235  }
3236  else
3237  {
3238  int s = 0;
3239  if(!SizeOfArray(v, &s))
3240  {
3242  StackArea,
3244  NIL);
3246  }
3247  else {
3249  DynamicArea,
3250  UNKNOWN_RAM_OFFSET /* ComputeAreaOffset(DynamicArea,e) */,
3251  NIL);
3252  /* the offset must be recomputed lately, when we know for
3253  sure the size of the variable */
3254  area_layout(dsa) = gen_nconc(area_layout(dsa), CONS(ENTITY, v, NIL));
3255  }
3256  }
3257  }
3258  return make_storage_ram(r);
3259 }
entity get_top_level_entity()
Definition: util.c:152
bool SizeOfArray(entity, int *)
This function computes the total size of a variable in bytes, ie.
Definition: size.c:87
#define ram_undefined
Definition: ri.h:2221

References area_layout, compilation_unit_name, CONS, DYNAMIC_RAM_OFFSET, DynamicArea, ENTITY, entity_type, FindOrCreateEntity(), gen_in_list_p(), gen_nconc(), get_current_compilation_unit_entity(), get_current_module_entity(), get_top_level_entity(), is_external, make_ram(), make_storage_ram(), NIL, pips_assert, ram_undefined, SizeOfArray(), StackArea, STATIC_AREA_LOCAL_NAME, StaticArea, TOP_LEVEL_MODULE_NAME, type_area, type_variable_p, and UNKNOWN_RAM_OFFSET.

Referenced by UpdateEntity().

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

◆ MakeTopLevelEntity()

void MakeTopLevelEntity ( void  )

To be economic, group this top-level entity to it areas

FI: this is not convenient if top-level:top-level is a module. All global variables should be declared there. I need also to generate stubs for global variables... Do I? Yes, because the points-to information is computed bottom-up.

Definition at line 157 of file util.c.

158 {
159  /* To be economic, group this top-level entity to it areas*/
160  /* FI: this is not convenient if top-level:top-level is a
161  module. All global variables should be declared there. I need
162  also to generate stubs for global variables... Do I? Yes, because
163  the points-to information is computed bottom-up. */
166  //entity_type(e) = make_type(is_type_area, make_area(0, NIL));
167  entity_type(e) =
169  //entity_initial(e) = make_value_unknown();
171  NIL, make_language_c());
173 }
value make_value_code(code _field_)
Definition: ri.c:2835
type make_type_void(list _field_)
Definition: ri.c:2727

References entity_initial, entity_storage, entity_type, FindOrCreateEntity(), make_code(), make_functional(), make_language_c(), make_sequence(), make_storage_rom(), make_type_functional(), make_type_void(), make_value_code(), NIL, strdup(), and TOP_LEVEL_MODULE_NAME.

Referenced by actual_c_parser().

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

◆ MemberDerivedIdentifierToExpression()

expression MemberDerivedIdentifierToExpression ( type  t,
string  m 
)

Definition at line 463 of file util.c.

464 {
465  if (type_variable_p(t))
466  {
468  pips_debug(6,"Basic tag is %d\n",basic_tag(b));
469  switch (basic_tag(b)) {
470  case is_basic_pointer:
471  {
472  type tp = basic_pointer(b);
474  }
475  case is_basic_typedef:
476  {
477  entity te = basic_typedef(b);
478  type tp = entity_type(te);
480  }
481  case is_basic_derived:
482  {
483  entity de = basic_derived(b);
484  const char * name = entity_user_name(de);
485  string id = strdup(concatenate(name,MEMBER_SEP_STRING,m,NULL));
487  free(id);
488  return exp;
489  }
490  default:
491  break;
492  }
493  }
494  CParserError("Cannot find the field identifier from current type\n");
495  return expression_undefined;
496 }
expression MemberDerivedIdentifierToExpression(type t, string m)
Definition: util.c:463
expression IdentifierToExpression(string s)
Definition: util.c:650
@ is_basic_derived
Definition: ri.h:579
@ is_basic_pointer
Definition: ri.h:578
@ is_basic_typedef
Definition: ri.h:580
#define basic_pointer(x)
Definition: ri.h:637
#define basic_derived(x)
Definition: ri.h:640
#define basic_tag(x)
Definition: ri.h:613
#define basic_typedef(x)
Definition: ri.h:643

References basic_derived, basic_pointer, basic_tag, basic_typedef, concatenate(), CParserError(), entity_type, entity_user_name(), exp, expression_undefined, free(), IdentifierToExpression(), is_basic_derived, is_basic_pointer, is_basic_typedef, MEMBER_SEP_STRING, MemberDerivedIdentifierToExpression(), pips_debug, strdup(), type_variable, type_variable_p, and variable_basic.

Referenced by MemberDerivedIdentifierToExpression(), and MemberIdentifierToExpression().

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

◆ MemberIdentifierToExpression()

expression MemberIdentifierToExpression ( expression  e,
string  m 
)

Find the name of struct/union of m from the type of expression e

The first expression must be a pointer

standard integer arithmetic: why bother? why take the CDR?

FI: seems too simple. No need to remember if you sarted with "." or "->"?

Let use the second argument

More types of call must be taken into account: typedef and pointer to functions

User defined call and intrinsics not processed above

A call must have occured somewhere...

An apply must have occured somewhere...

expression exp = subscript_array(syntax_subscript(s));

pips_debug(6,"Subscripting array expression\n");

return MemberIdentifierToExpression(exp, m);

Definition at line 498 of file util.c.

499 {
500  /* Find the name of struct/union of m from the type of expression e*/
501 
502  syntax s = expression_syntax(e);
503  ifdebug(6)
504  {
505  pips_debug(6,"Find the struct/union of \"%s\" from expression:\n",m);
506  print_expression(e);
507  }
508  switch (syntax_tag(s))
509  {
510  case is_syntax_call:
511  {
512  call c = syntax_call(s);
513  entity f = call_function(c);
514  pips_debug(6,"Called operator is \"%s\"\n",entity_name(f));
515  if(ENTITY_PLUS_C_P(f))
516  {
522 
524  exp = e1;
525  else if(basic_pointer_p(b2) && (basic_int_p(b1)||basic_bit_p(b1)))
526  exp = e2;
527  else
528  CParserError("Pointer arithmetic error, incompatible types");
529  free_basic(b1);
530  free_basic(b2);
531 
533  }
536  {
539  }
540  else if(ENTITY_MINUS_C_P(f))
541  {
542  /* The first expression must be a pointer */
545  }
546  else if(ENTITY_PLUS_P(f))
547  {
548  /* standard integer arithmetic: why bother? why take the CDR? */
551  }
552  else if (ENTITY_FIELD_P(f) || ENTITY_POINT_TO_P(f))
553  {
556  }
557  else if (ENTITY_DEREFERENCING_P(f))
558  {
561  }
562  /* FI: seems too simple. No need to remember if you sarted with "." or "->"? */
563  else if (ENTITY_ADDRESS_OF_P(f))
564  {
567  }
568  else if (ENTITY_ASSIGN_P(f))
569  {
572  }
573  else if (ENTITY_CONDITIONAL_P(f))
574  {
575  /* Let use the second argument */
578  }
579  /* More types of call must be taken into account: typedef and
580  pointer to functions */
581  else if (true || type_functional_p(entity_type(f)))
582  {
583  /* User defined call and intrinsics not processed above */
584  type ft = call_to_functional_type(c, true);
586  if(overloaded_type_p(t))
587  pips_internal_error("Unresolved expression type\n");
589  }
590  break;
591  }
592  case is_syntax_reference:
593  {
595  type t = ultimate_type(entity_type(ent));
596  pips_debug(6,"Reference expression\n");
597 
598  if(type_functional_p(t)) {
599  /* A call must have occured somewhere... */
602  }
605 
606  if(type_functional_p(pt)) {
607  /* An apply must have occured somewhere... */
610  }
611  else
613  }
614  else
616  }
617  case is_syntax_cast:
618  {
619  type t = cast_type(syntax_cast(s));
620  pips_debug(6,"Cast expression\n");
622  }
623  case is_syntax_range:
624  break;
626  break;
627  case is_syntax_subscript:
628  {
629  /* expression exp = subscript_array(syntax_subscript(s)); */
630  /* pips_debug(6,"Subscripting array expression\n"); */
631  /* return MemberIdentifierToExpression(exp, m); */
632  type t = expression_to_type(e);
634  }
636  {
638  return MemberIdentifierToExpression(fe, m);
639  break;
640  }
641  default:
642  {
643  pips_internal_error("unexpected syntax tag: %d", syntax_tag(s));
644  }
645  }
646  CParserError("Cannot find the field identifier from current expression\n");
647  return expression_undefined;
648 }
void free_basic(basic p)
Definition: ri.c:107
expression MemberIdentifierToExpression(expression e, string m)
Definition: util.c:498
#define ENTITY_ASSIGN_P(e)
#define ENTITY_DEREFERENCING_P(e)
#define ENTITY_PLUS_P(e)
#define ENTITY_POINT_TO_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_CONDITIONAL_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define ENTITY_PLUS_C_P(e)
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
#define ENTITY_MINUS_C_P(e)
#define ENTITY_ADDRESS_OF_P(e)
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
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
type call_to_functional_type(call, bool)
The function called can have a functional type, or a typedef type or a pointer type to a functional t...
Definition: type.c:3824
bool overloaded_type_p(type)
Returns true if t is a variable type with a basic overloaded.
Definition: type.c:2666
#define basic_int_p(x)
Definition: ri.h:614
#define syntax_cast(x)
Definition: ri.h:2739
#define syntax_application(x)
Definition: ri.h:2748
#define syntax_call(x)
Definition: ri.h:2736
#define cast_type(x)
Definition: ri.h:745
#define application_function(x)
Definition: ri.h:508
#define basic_bit_p(x)
Definition: ri.h:632
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105

References application_function, b1, b2, basic_bit_p, basic_int_p, basic_of_expression(), basic_pointer, basic_pointer_p, call_arguments, call_function, call_to_functional_type(), CAR, cast_type, CDR, CParserError(), ENTITY_ADDRESS_OF_P, ENTITY_ASSIGN_P, ENTITY_CONDITIONAL_P, ENTITY_DEREFERENCING_P, ENTITY_FIELD_P, ENTITY_MINUS_C_P, entity_name, ENTITY_PLUS_C_P, ENTITY_PLUS_P, ENTITY_POINT_TO_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, entity_type, exp, EXPRESSION, expression_syntax, expression_to_type(), expression_undefined, f(), free_basic(), functional_result, ifdebug, is_syntax_application, is_syntax_call, is_syntax_cast, is_syntax_range, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, MemberDerivedIdentifierToExpression(), MemberIdentifierToExpression(), overloaded_type_p(), pips_debug, pips_internal_error, print_expression(), reference_variable, syntax_application, syntax_call, syntax_cast, syntax_reference, syntax_tag, type_functional, type_functional_p, type_variable, type_variable_p, ultimate_type(), and variable_basic.

Referenced by MemberIdentifierToExpression().

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

◆ nodecl_p()

static void nodecl_p ( entity __attribute__((unused))  module,
statement  stat 
)
static

Definition at line 1868 of file util.c.

1869 {
1870  declarationerror_p = false;
1873 
1874  if(declarationerror_p)
1875  CParserError("Illegal Input\n");
1876 }
static bool declarationerror_p
Definition: util.c:1788
static bool referencenodeclfilter(reference r)
Definition: util.c:1790
static bool callnodeclfilter(call c)
Definition: util.c:1822
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338

References call_domain, callnodeclfilter(), CParserError(), declarationerror_p, gen_multi_recurse(), gen_null(), reference_domain, and referencenodeclfilter().

Referenced by CCompilationUnitMemoryAllocations(), and CModuleMemoryAllocation().

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

◆ NStackPop()

void NStackPop ( stack  s,
int  n 
)

Pop n times the stack s.

Definition at line 3442 of file util.c.

3443 {
3444  while (n-->0)
3445  gen_free(stack_pop(s));
3446 }
void gen_free(gen_chunk *obj)
version without shared_pointers.
Definition: genClib.c:992
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399

References gen_free(), and stack_pop().

Referenced by StackPop().

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

◆ put_new_typedef()

void put_new_typedef ( const char *  name)

This function is used by libraries "step"* and "task_parallelization".

FI: I have no idea why it works although the keyword_typedef_table should not be initialized... It could not be made static, because it might be used by any file in the c_syntax library.

Parameters
nameame

Definition at line 1078 of file util.c.

1079 {
1081  pips_debug(5,"Add typedef name %s to hash table\n",name);
1082 }

References hash_put(), keyword_typedef_table, pips_debug, strdup(), and TK_NAMED_TYPE.

Referenced by cast_STEP_ARG(), mpi_initialize(), mpi_type_mpi_comm(), mpi_type_mpi_request(), and mpi_type_mpi_status().

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

◆ referencenodeclfilter()

static bool referencenodeclfilter ( reference  r)
static

There can be a reference to variable of storage return when a function pointer is assigned a function

FI: this may be a bad decision choice to confuse a function and its return value. It might be better to keep storage "rom" systematically for functions and to restore this test.

Definition at line 1790 of file util.c.

1791 {
1792  entity e = reference_variable(r);
1795 
1796  if(variable_entity_p(e)) {
1798  || gen_in_list_p(e, entity_declarations(cu))))
1799  {
1800  declarationerror_p = true;
1801  user_log("\n\nNo declaration of variable \"%s\" (\"%s\") in module \"%s\'\n",
1803  }
1804  }
1805  /* There can be a reference to variable of storage return when a
1806  function pointer is assigned a function */
1807  /* FI: this may be a bad decision choice to confuse a function and
1808  its return value. It might be better to keep storage "rom"
1809  systematically for functions and to restore this test. */
1810  /*
1811  // if(storage_return_p(entity_storage(e))){
1812  // declarationerror_p = true;
1813  // user_log("\n\nNo declaration of variable \"%s\" (\"%s\") in module \"%s\"\n",
1814  // entity_user_name(e),entity_name(e),get_current_module_name());
1815  }
1816  */
1817 
1818  return true;
1819 }
void user_log(const char *format,...)
Definition: message.c:234
bool variable_entity_p(entity)
variable.c
Definition: variable.c:70

References declarationerror_p, entity_declarations, entity_local_name(), entity_name, gen_in_list_p(), get_current_compilation_unit_entity(), get_current_module_entity(), get_current_module_name(), reference_variable, user_log(), and variable_entity_p().

Referenced by nodecl_p().

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

◆ RemoveDummyArguments()

void RemoveDummyArguments ( entity  f,
list  refs 
)

To chase formals in type declarations.

If f has dummy formal parameters, replace them by standard formal parameters

make a list of formal dummy parameters

Since the compilation order is not known, the standard formal parameters may already exist and they should not be removed.

Update the "dummy" field of the "parameter" data structure

This special case could be ignored and handled like the next one to avoid cut-and-past and/or the definition of a new function.

no dummy naming information available as in foo(int);

FI: just in case?

Remore the dummy formals from f's declaration list (and from the symbol table?) but keep all pointers towards them in the declarations as in "void foo(n,a[n])"

FI: The storage might point to another dummy argument (although it should not)

Let's hope there are no other pointers towards dummy formal parameters

No, there may be occurences due to dependent types.

Parameters
refsefs

Definition at line 2224 of file util.c.

2225 {
2226  value fv = entity_initial(f);
2227 
2228  pips_assert("The function value is defined", !value_undefined_p(fv));
2229  pips_assert("The entity has a functional type", type_functional_p(entity_type(f)));
2230  pips_assert("The entity is not a typedef", !typedef_entity_p(f));
2231 
2232  if(!value_undefined_p(fv) && !value_intrinsic_p(fv)) {
2233  code fc = value_code(fv);
2234  list dl = code_declarations(fc);
2235  list cd = list_undefined;
2236  list formals = NIL;
2237  type ft = entity_type(f);
2239  list cformals = list_undefined;
2240  list cfp = list_undefined;
2241  int nformals=-1;
2242  int nfp = gen_length(fp);
2243 
2244  pips_assert("the value is code", value_code_p(fv));
2245 
2246  /* make a list of formal dummy parameters */
2247  for(cd = dl; !ENDP(cd); POP(cd)) {
2248  entity v = ENTITY(CAR(cd));
2249  if(entity_formal_p(v)) {
2250  pips_debug(8, "Formal dummy parameter: \"%s\"\n", entity_name(v));
2251  /* Since the compilation order is not known, the standard
2252  formal parameters may already exist and they should not be
2253  removed. */
2255  formals = gen_nconc(formals, CONS(ENTITY, v, NIL));
2256  }
2257  }
2258  nformals = gen_length(formals);
2259 
2260  /* Update the "dummy" field of the "parameter" data structure */
2261 
2262  if(nformals==nfp) {
2263  /* This special case could be ignored and handled like the next
2264  one to avoid cut-and-past and/or the definition of a new
2265  function. */
2266  for(cformals=formals, cfp = fp; !ENDP(cfp); POP(cformals), POP(cfp)) {
2267  parameter p = PARAMETER(CAR(cfp));
2268  entity ep = ENTITY(CAR(cformals));
2269  dummy d = parameter_dummy(p);
2270 
2271  if(dummy_identifier_p(d)) {
2272  entity oep = dummy_identifier(d);
2273 
2274  MAP(REFERENCE, r, {
2275  entity v = reference_variable(r);
2276 
2277  if(v==oep) {
2278  pips_debug(8, "Reference to \"\%s\" now refers \"\%s\"\n",
2279  entity_name(oep), entity_name(ep));
2280  reference_variable(r) = ep;
2281  }
2282  }, refs);
2283  }
2284 
2285  update_dummy_parameter(p, ep);
2286  }
2287  }
2288  else if(nformals>0) {
2289  int i = -1;
2290  for(cfp=fp, i= 1;!ENDP(cfp); POP(cfp), i++) {
2291  entity ep = find_ith_parameter(f,i);
2292  if(!entity_undefined_p(ep)) {
2293  parameter p = PARAMETER(CAR(cfp));
2294  dummy d = parameter_dummy(p);
2295 
2296  if(dummy_identifier_p(d)) {
2297  entity oep = dummy_identifier(d);
2298 
2299  MAP(REFERENCE, r, {
2300  entity v = reference_variable(r);
2301 
2302  if(v==oep) {
2303  pips_debug(8, "Reference to \"\%s\" now refers \"\%s\"\n",
2304  entity_name(oep), entity_name(ep));
2305  reference_variable(r) = ep;
2306  }
2307  }, refs);
2308  }
2309 
2310  update_dummy_parameter(p, ep);
2311  }
2312  }
2313  }
2314  else {
2315  /* no dummy naming information available as in foo(int); */
2316  ;
2317  }
2318 
2319  if(true) {
2320 
2321  /* FI: just in case? */
2322  remove_entity_type_stacks(formals);
2323 
2324  /* Remore the dummy formals from f's declaration list (and from
2325  the symbol table?) but keep all pointers towards them in the
2326  declarations as in "void foo(n,a[n])" */
2327  for(cd = formals; !ENDP(cd); POP(cd)) {
2328  entity p = ENTITY(CAR(cd));
2329  //type pt = entity_type(p);
2330  //storage ps = entity_storage(p);
2331  //formal pfs = storage_formal(ps);
2332 
2333  pips_debug(8, "Formal dummy parameter \"%s\" is removed from declarations\n",
2334  entity_name(p));
2335 
2336  //clean_up_dummy_parameter_type(pt, formals);
2337  gen_remove(&code_declarations(fc), (void *) p);
2338 
2339  /* FI: The storage might point to another dummy argument
2340  (although it should not) */
2341  //formal_function(pfs) = entity_undefined;
2342  /* Let's hope there are no other pointers towards dummy formal parameters */
2343  /* No, there may be occurences due to dependent types. */
2344  //free_entity(p);
2345  }
2346  }
2347  gen_free_list(formals);
2348  }
2349 }
void remove_entity_type_stacks(list el)
Definition: c_parser.c:179
int dummy
A dummy file, to prevent empty libraries from breaking builds.
Definition: dummy.c:41
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool dummy_parameter_entity_p(entity p)
is p a dummy parameter?
Definition: entity.c:1941
bool entity_formal_p(entity p)
is p a formal parameter?
Definition: entity.c:1935
void update_dummy_parameter(parameter p, entity ep)
Definition: entity.c:2072
entity find_ith_parameter(entity e, int i)
Definition: util.c:93
#define dummy_identifier(x)
Definition: ri.h:1033
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define parameter_dummy(x)
Definition: ri.h:1823
#define value_intrinsic_p(x)
Definition: ri.h:3074
#define functional_parameters(x)
Definition: ri.h:1442
#define dummy_identifier_p(x)
Definition: ri.h:1031

References CAR, code_declarations, CONS, dummy_identifier, dummy_identifier_p, dummy_parameter_entity_p(), ENDP, ENTITY, entity_formal_p(), entity_initial, entity_name, entity_type, entity_undefined_p, f(), find_ith_parameter(), functional_parameters, gen_free_list(), gen_length(), gen_nconc(), gen_remove(), list_undefined, MAP, NIL, PARAMETER, parameter_dummy, pips_assert, pips_debug, POP, REFERENCE, reference_variable, remove_entity_type_stacks(), type_functional, type_functional_p, typedef_entity_p(), update_dummy_parameter(), value_code, value_code_p, value_intrinsic_p, and value_undefined_p.

Referenced by UpdateEntity().

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

◆ RemoveFromExterns()

void RemoveFromExterns ( entity  e)

This may happen when functional arguments are dealt with

Definition at line 2884 of file util.c.

2885 {
2887  if(!entity_undefined_p(f)) {
2889 
2890  gen_remove(&code_externs(fc), (void *) e);
2891  }
2892  else {
2893  /* This may happen when functional arguments are dealt with */
2894  c_parser_user_warning("The C parser should not execute this call.\n");
2895  }
2896 }

References c_parser_user_warning, code_externs, entity_initial, entity_undefined_p, f(), gen_remove(), get_current_module_entity(), and value_code.

Referenced by actual_c_parser(), and FindOrCreateCurrentEntity().

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

◆ RenameFunctionEntity()

entity RenameFunctionEntity ( entity  oe)

Rename function oe if necessary.

The function name may be wrong because not enough information was available when it was created by FindOrCreateCurrentEntity().

oe must be a function and not a pointer to a function

oe should be added to the declarations of the current block

A C function or intrinsics name should include no scope information. But a functional typedef should.

In fact, we'd like to know if it is found before we create it...

FI I do not understand how formal parameters could be declared before

We assume oe is not already part of a declaration list since its formal parameters have been taken care of

Parameters
oee

Definition at line 1556 of file util.c.

1557 {
1558  entity ne = oe;
1559  string oen = entity_name(oe);
1560  const char* oeln = entity_local_name(oe);
1561  string sn = local_name_to_scope(oeln);
1562  //type oet = entity_type(oe);
1563 
1564  /* A C function or intrinsics name should include no scope
1565  information. But a functional typedef should. */
1566  if(!typedef_entity_p(oe) && !empty_string_p(sn)) {
1567  if(strchr(oen, MODULE_SEP)!=NULL) {
1568  //string mn = entity_module_name(ne);
1569  const char * ln = entity_user_name(ne);
1570  value voe = entity_initial(oe);
1572  stack ns = stack_copy(s);
1573 
1574  /* In fact, we'd like to know if it is found before we create it... */
1576  if(entity_undefined_p(ne)) {
1578  entity_type(ne) = copy_type(entity_type(oe));
1580  /* FI I do not understand how formal parameters could be declared before */
1581  if(value_undefined_p(voe) || value_unknown_p(voe))
1584  else {
1585  list dl = list_undefined;
1587 
1589  FOREACH(ENTITY, v, dl) {
1590  storage s = entity_storage(v);
1591  if(storage_formal_p(s)) {
1592  formal fs = storage_formal(s);
1593  formal_function(fs) = ne;
1594  }
1595  }
1596  }
1598  }
1599 
1600  pips_debug(1, "entity %s renamed %s\n", entity_name(oe), entity_name(ne));
1601 
1602  /* We assume oe is not already part of a declaration list since
1603  its formal parameters have been taken care of */
1605  }
1606  }
1607  free(sn);
1608  return ne;
1609 }
void put_to_entity_type_stack_table(entity key, stack value)
Definition: c_parser.c:139
bool empty_string_p(const char *s)
Definition: entity_names.c:239
#define MODULE_SEP
special characters to build entity names of various kinds
Definition: naming-local.h:27
stack stack_copy(const stack)
duplicate a stack with its contents.
Definition: stack.c:267
string local_name_to_scope(const char *ln)
allocates a new string
Definition: entity.c:563
#define formal_function(x)
Definition: ri.h:1406
void gen_clear_tabulated_element(gen_chunk *obj)
GEN_CLEAR_TABULATED_ELEMENT only clears the entry for object OBJ in the gen_tabulated_ and gen_tabula...
Definition: tabulated.c:251

References code_declarations, copy_storage(), copy_type(), copy_value(), empty_string_p(), ENTITY, entity_initial, entity_local_name(), entity_name, entity_storage, entity_type, entity_undefined_p, entity_user_name(), FindEntity(), FindOrCreateEntity(), FOREACH, formal_function, free(), gen_clear_tabulated_element(), get_from_entity_type_stack_table(), is_value_code, list_undefined, local_name_to_scope(), make_code(), make_language_c(), make_sequence(), make_value(), MODULE_SEP, NIL, pips_debug, put_to_entity_type_stack_table(), stack_copy(), storage_formal, storage_formal_p, strdup(), TOP_LEVEL_MODULE_NAME, typedef_entity_p(), value_code, value_undefined_p, and value_unknown_p.

+ Here is the call graph for this function:

◆ reset_current_dummy_parameter_number()

void reset_current_dummy_parameter_number ( void  )

Definition at line 144 of file util.c.

References current_dummy_parameter_number.

Referenced by actual_c_parser(), and c_parser_error().

+ Here is the caller graph for this function:

◆ reset_preprocessor_line_analysis()

void reset_preprocessor_line_analysis ( void  )

Definition at line 3592 of file util.c.

3593 {
3594  buffer_initialized_p = false;
3595 }

References buffer_initialized_p.

Referenced by actual_c_parser().

+ Here is the caller graph for this function:

◆ ResetCurrentCompilationUnitEntity()

void ResetCurrentCompilationUnitEntity ( bool  is_compilation_unit_parser)

Let's redo the memory allocation for variables whose name has changed:-(

reset_entity_type_stack_table();

Parameters
is_compilation_unit_parsers_compilation_unit_parser

Definition at line 349 of file util.c.

350 {
351  /* Let's redo the memory allocation for variables whose name has changed:-(*/
352  if(is_compilation_unit_parser)
354  else
356 
357  /* reset_entity_type_stack_table(); */
358  if (get_bool_property("PARSER_DUMP_SYMBOL_TABLE"))
360  pips_debug(4,"Reset current module entity for compilation unit \"%s\"\n",
363 }
void CCompilationUnitMemoryReallocation(entity module)
Definition: util.c:1972
void CCompilationUnitMemoryAllocation(entity module)
Definition: util.c:1967
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void fprint_C_environment(FILE *fd, entity m)
Definition: declarations.c:292

References CCompilationUnitMemoryAllocation(), CCompilationUnitMemoryReallocation(), fprint_C_environment(), get_bool_property(), get_current_module_entity(), get_current_module_name(), pips_debug, and reset_current_module_entity().

Referenced by actual_c_parser().

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

◆ set_current_dummy_parameter_number()

static void set_current_dummy_parameter_number ( int  n)
static

Definition at line 139 of file util.c.

int get_declaration_counter(void)
Definition: cyacc.tab.c:497

References current_dummy_parameter_number, and get_declaration_counter().

Referenced by FindOrCreateCurrentEntity().

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

◆ set_entity_initial()

void set_entity_initial ( entity  v,
expression  nie 
)

Be careful if the initial value has already been set.

Detect double definitions when possible

Take care of the special case of pointers to functions.

The compilation unit has already been scanned once for declarations. Double definitions are no surprise...

Generate initializations for pointers to functions and arrays of pointers to functions

A pointer to a function already has value code as initial value. We may not even know yet it's a pointer...

Parameters
nieie

Definition at line 3469 of file util.c.

3470 {
3471  value oiv = entity_initial(v);
3472 
3473  if(!value_undefined_p(oiv) && value_unknown_p(oiv)) {
3474  free_value(oiv);
3476  oiv = value_undefined;
3477  }
3478 
3479  if(!value_undefined_p(oiv)) {
3481  /* The compilation unit has already
3482  been scanned once for
3483  declarations. Double definitions
3484  are no surprise...*/
3485  if(value_code_p(oiv)) {
3486  /* Generate initializations for pointers to functions and arrays
3487  of pointers to functions */
3488  code c = value_code(oiv);
3490 
3492  }
3493  }
3494  else {
3495  type vt = entity_type(v);
3497  : ultimate_type(entity_type(v));
3498  if(!type_undefined_p(uvt) &&
3499  ((pointer_type_p(uvt) &&
3501  || type_functional_p(uvt)) ) {
3502  /* A pointer to a function already has value code as initial
3503  value. We may not even know yet it's a pointer... */
3504  code c = value_code(oiv);
3506 
3508  //c_parser_user_warning("The initialization of a function pointer is lost\n");
3509  }
3510  else {
3512  "double definition of initial"
3513  " value for variable \"%s\"", entity_name(v));
3514 
3515  // FI: I am not sure it so good to put any junk in any format in the
3516  // Warning file. FC: Indeed:-)
3517 
3518  string initv = expression_to_string(nie);
3519  string currv;
3520  if(value_expression_p(oiv))
3521  currv = expression_to_string(value_expression(oiv));
3522  else
3523  asprintf(&currv, "value tag: %d", value_tag(entity_initial(v)));
3524 
3525  pips_user_warning("New initial value expression:\n%s"
3526  "Current initial value:\n%s",
3527  initv, currv);
3528  free(initv);
3529  free(currv);
3530  pips_internal_error("Scoping might be the reason.");
3531  }
3532  }
3533  }
3534 
3537 }
void free_value(value p)
Definition: ri.c:2787
bool compilation_unit_p(const char *module_name)
The names of PIPS entities carry information about their nature.
Definition: entity_names.c:56
statement make_expression_statement(expression)
Build a statement from a given expression.
Definition: statement.c:1308
string expression_to_string(expression e)
Definition: expression.c:77
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
#define value_tag(x)
Definition: ri.h:3064
#define code_initializations(x)
Definition: ri.h:788
#define value_expression_p(x)
Definition: ri.h:3080
#define value_expression(x)
Definition: ri.h:3082
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413

References asprintf, basic_pointer, c_parser_user_warning, code_initializations, compilation_unit_p(), CONS, entity_initial, entity_name, entity_type, expression_to_string(), free(), free_value(), get_current_module_name(), make_expression_statement(), make_sequence(), make_value_expression(), NIL, pips_internal_error, pips_user_warning, pointer_type_p(), STATEMENT, type_functional_p, type_undefined, type_undefined_p, type_variable, ultimate_type(), value_code, value_code_p, value_expression, value_expression_p, value_tag, value_undefined, value_undefined_p, value_unknown_p, and variable_basic.

Referenced by freia_is_transpose_call().

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

◆ StackPop()

void StackPop ( stack  OffsetStack)

The OffsetStack is poped n times, where n is the number of formal arguments of the actual function.

Parameters
OffsetStackffsetStack

Definition at line 3450 of file util.c.

3451 {
3452  int n = basic_int((basic) stack_head(OffsetStack));
3454 }
stack OffsetStack
Definition: c_parser.c:120
void NStackPop(stack s, int n)
Pop n times the stack s.
Definition: util.c:3442
#define basic_int(x)
Definition: ri.h:616

References basic_int, NStackPop(), OffsetStack, and stack_head().

+ Here is the call graph for this function:

◆ StackPush()

void StackPush ( stack  OffsetStack)

The OffsetStack is pushed incrementally.

Parameters
OffsetStackffsetStack

Definition at line 3457 of file util.c.

3458 {
3459  int i = basic_int((basic) stack_head(OffsetStack));
3460  stack_push((char *) make_basic_int(i+1),OffsetStack);
3461 }
void stack_push(void *, stack)
stack use
Definition: stack.c:373

References basic_int, make_basic_int(), OffsetStack, stack_head(), and stack_push().

+ Here is the call graph for this function:

◆ SubstituteDummyParameters()

void SubstituteDummyParameters ( entity  f,
list  el 
)

The copy could be avoided by substituting v->s with nv->s

Store type information. Might be useless.

Inherit any attribute you can

Parameters
ell

Definition at line 2351 of file util.c.

2352 {
2353  for(list cel=el; !ENDP(cel); POP(cel)) {
2354  entity v = ENTITY(CAR(cel));
2355  if(dummy_parameter_entity_p(v)) {
2356  const char* mn = entity_local_name(f);
2357  const char * ln = entity_user_name(v);
2358  entity nv = FindOrCreateEntity(mn, ln);
2360  /* The copy could be avoided by substituting v->s with nv->s */
2361  stack ns = stack_copy(s);
2362  ENTITY_(CAR(cel)) = nv;
2363 
2364  /* Store type information. Might be useless. */
2367 
2368  /* Inherit any attribute you can */
2369  if(!type_undefined_p(entity_type(v)))
2370  entity_type(nv) = copy_type(entity_type(v));
2375  }
2376  }
2377 }
void remove_entity_type_stack(entity e)
Definition: c_parser.c:156
#define ENTITY_(x)
Definition: ri.h:2758

References CAR, copy_storage(), copy_type(), copy_value(), dummy_parameter_entity_p(), ENDP, ENTITY, ENTITY_, entity_initial, entity_local_name(), entity_storage, entity_type, entity_user_name(), f(), FindOrCreateEntity(), get_from_entity_type_stack_table(), POP, put_to_entity_type_stack_table(), remove_entity_type_stack(), stack_copy(), storage_undefined_p, type_undefined_p, and value_undefined_p.

+ Here is the call graph for this function:

◆ TakeDerivedEntities()

list TakeDerivedEntities ( list  le)

To simplify debugging

The list is stored there at line 2087 of cyacc.y (5 August 2009)

e->type==entity_domain

lres = gen_nconc(lres,ltmp);

The ltmp lists seem to be somehow shared as shown in ngspice/main.tpips. The previous implementation of the current function generated cyclic lists. The new implementation is incompatible with a proper memory management.

I do not understand what's done in c_syntax/cyacc.y. The trace obtained from C_syntax/ngspice01.c shows that the same derived entities appear several times when dummy structs and unions are embedded as in ngspice01.c

Parameters
lee

Definition at line 3020 of file util.c.

3021 {
3022  list lres = NIL;
3023 
3024  if(!ENDP(le)) { /* To simplify debugging */
3025 
3026  pips_debug(8, "Begin\n");
3027 
3028  ifdebug(8) {
3029  pips_debug(8, "Input entity list: ");
3030  print_entities(le);
3031  fprintf(stderr, "\n");
3032  }
3033 
3034  FOREACH (ENTITY, e, le) {
3035  /* The list is stored there at line 2087 of cyacc.y (5 August
3036  2009) */
3037  //list ltmp = (list) entity_initial(e);
3038  list sltmp = (list) entity_initial(e);
3039  if(!ENDP(sltmp)) {
3040  // pips_assert("sltmp has only one element", gen_length(sltmp)==1);
3041  // statement stmp = STATEMENT(CAR(sltmp));
3042  // list ltmp = statement_declarations(stmp);
3043  list ltmp = sltmp;
3044 
3045  //pips_assert("sltmp is a continue statement list",
3046  // continue_statements_p(sltmp));
3047  pips_assert("e is an entity",
3048  check_entity(e) /* e->_type_==entity_domain*/ );
3049  pips_debug(8, "entity e: %s (%p)\n", entity_name(e), e);
3050 
3051  if (ltmp != NIL) {
3052  /* lres = gen_nconc(lres,ltmp);*/
3053  FOREACH(ENTITY, de, ltmp) {
3054 
3055  pips_assert("de is an entity", de->_type_==entity_domain);
3056  pips_debug(8, "entity de: %s (%p)\n", entity_name(de), de);
3057 
3058  if(!gen_in_list_p(de, lres)) {
3059  lres = gen_nconc(lres, CONS(ENTITY, de, NIL));
3060  }
3061  }
3062  }
3063  }
3064  /* The ltmp lists seem to be somehow shared as shown in
3065  * ngspice/main.tpips. The previous implementation of the
3066  * current function generated cyclic lists. The new
3067  * implementation is incompatible with a proper memory
3068  * management.
3069  *
3070  * I do not understand what's done in c_syntax/cyacc.y. The
3071  * trace obtained from C_syntax/ngspice01.c shows that the same
3072  * derived entities appear several times when dummy structs and
3073  * unions are embedded as in ngspice01.c
3074  */
3075  //gen_free_list(ltmp);
3077  }
3078  pips_assert ("an acyclic list is generated", !gen_list_cyclic_p (lres));
3079 
3080  ifdebug(8) {
3081  pips_debug(8, "Output entity list: ");
3082  if(ENDP(lres)) {
3083  fprintf(stderr, "NIL\n");
3084  }
3085  else {
3086  print_entities(lres);
3087  fprintf(stderr, "\n");
3088  }
3089  }
3090 
3091  pips_debug(8, "End\n");
3092  }
3093 
3094  return lres;
3095 }
entity check_entity(entity p)
Definition: ri.c:2527
bool gen_list_cyclic_p(const list ml)
Definition: list.c:120
struct cons * list
Definition: newgen_types.h:106
void print_entities(list l)
Definition: entity.c:167
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References check_entity(), CONS, ENDP, ENTITY, entity_domain, entity_initial, entity_name, FOREACH, fprintf(), gen_in_list_p(), gen_list_cyclic_p(), gen_nconc(), ifdebug, NIL, pips_assert, pips_debug, print_entities(), and value_undefined.

+ Here is the call graph for this function:

◆ UpdateAbstractEntity()

void UpdateAbstractEntity ( entity  e,
stack  ContextStack 
)

Update the entity with final type, storage

tc must have variable type, add lq to its qualifiers

lse const void, void is not of type variable, store const where ????????? CParserError("Entity has qualifier but no type or is not variable type in the context?\n");

Use the type stack in entity_storage to create the final type for the entity

Parameters
ContextStackontextStack

Definition at line 2842 of file util.c.

2843 {
2844  /* Update the entity with final type, storage */
2845 
2846  //stack s = (stack) entity_storage(e);
2848  type t = entity_type(e);
2851  type t1,t2;
2853 
2854  pips_debug(3,"Update abstract entity %s\n",entity_name(e));
2855 
2856  if (lq != NIL)
2857  {
2858  /* tc must have variable type, add lq to its qualifiers */
2861  /*else
2862  const void, void is not of type variable, store const where ?????????
2863  CParserError("Entity has qualifier but no type or is not variable type in the context?\n");*/
2864  }
2865 
2866  /************************* TYPE PART *******************************************/
2867 
2868  /* Use the type stack in entity_storage to create the final type for the entity*/
2869  t2 = UpdateType(t,tc);
2870 
2871  while (stack_size(s) > 1)
2872  {
2873  t1 = stack_pop(s);
2874  t2 = UpdateType(t1,t2);
2875  }
2876  entity_type(e) = t2;
2877 
2878  /************************* STORAGE PART *******************************************/
2879 
2881 }
stack ContextStack
Definition: c_parser.c:117
#define c_parser_context_qualifiers(x)
type UpdateType(type t1, type t2)
This function replaces the undefined field in t1 by t2.
Definition: util.c:1693
int stack_size(const stack)
observers
static int tc
Internal variables
Definition: reindexing.c:107
#define variable_qualifiers(x)
Definition: ri.h:3124
#define storage_undefined
Definition: ri.h:2476

References c_parser_context_qualifiers, c_parser_context_type, ContextStack, entity_name, entity_storage, entity_type, get_from_entity_type_stack_table(), NIL, pips_debug, stack_head(), stack_pop(), stack_size(), storage_undefined, tc, type_undefined_p, type_variable, type_variable_p, UpdateType(), and variable_qualifiers.

+ Here is the call graph for this function:

◆ UpdateArrayEntity()

void UpdateArrayEntity ( entity  e,
list  lq,
list  le 
)

lq is for what ? e or le ????: lq should be for le

Parameters
lqq
lee

Definition at line 1514 of file util.c.

1515 {
1516  type t = entity_type(e);
1517  pips_debug(3,"Update array entity %s\n",entity_name(e));
1518 
1519  /* lq is for what ? e or le ????: lq should be for le*/
1520  if (type_undefined_p(t))
1521  {
1522  pips_debug(3,"First array dimension\n");
1523  entity_type(e) =
1525  CONS(DIMENSION,MakeDimension(le, lq),NIL),
1526  NIL));
1527  }
1528  else
1529  {
1530  pips_debug(3,"Next array dimension\n");
1531  if (type_variable_p(t))
1532  {
1533  variable v = type_variable(t);
1535  variable_dimensions(v) =
1537  CONS(DIMENSION, MakeDimension(le, lq), NIL));
1538  }
1539  else
1540  {
1541  CParserError("Dimension for not variable type\n");
1542  }
1543  }
1544 }
dimension MakeDimension(list le, list ql)
Definition: util.c:1389
#define basic_undefined
Definition: ri.h:556
#define variable_dimensions(x)
Definition: ri.h:3122

References basic_undefined, CONS, CParserError(), DIMENSION, entity_name, entity_type, gen_nconc(), make_type_variable(), make_variable(), MakeDimension(), NIL, pips_debug, type_undefined_p, type_variable, type_variable_p, variable_dimensions, and variable_qualifiers.

+ Here is the call graph for this function:

◆ UpdateDerivedEntities()

void UpdateDerivedEntities ( list  ld,
list  le,
stack  ContextStack 
)
Parameters
ldd
lee
ContextStackontextStack

Definition at line 3097 of file util.c.

3098 {
3099  FOREACH (ENTITY, e, le) {
3101  }
3102 }
void UpdateDerivedEntity(list ld, entity e, stack ContextStack)
Definition: util.c:2942

References ContextStack, ENTITY, FOREACH, and UpdateDerivedEntity().

+ Here is the call graph for this function:

◆ UpdateDerivedEntity()

void UpdateDerivedEntity ( list  ld,
entity  e,
stack  ContextStack 
)

Update the derived entity with final type and rom storage. If the entity has bit type, do not need to update its type

what about context qualifiers ?

What do we do for functional types for instance?

FI: I assume the qualifiers are carried by the result

What do we do for functional types for instance?

Although it should be popped from the stack, the current context seems to be used later in case of typedef, such as seen in decl24.c

Temporally put the list of struct/union entities defined in decl_psec_list to initial value of ent

Parameters
ldd
ContextStackontextStack

Definition at line 2942 of file util.c.

2943 {
2944  /* Update the derived entity with final type and rom storage.
2945  If the entity has bit type, do not need to update its type*/
2946  type t = entity_type(e);
2947  pips_debug(3,"Update derived entity %s\n",entity_name(e));
2948  if (!bit_type_p(t))
2949  {
2950  //stack s = (stack) entity_storage(e);
2954  type t1,t2;
2956 
2957  /* what about context qualifiers ? */
2958  t2 = UpdateType(t,tc);
2959 
2960  while (stack_size(s) > 1)
2961  {
2962  t1 = stack_pop(s);
2963  t2 = UpdateType(t1,t2);
2964  }
2965  entity_type(e) = t2;
2966 
2967  if(!ENDP(ql)) {
2968  if(type_void_p(t2)) {
2969  type_void(t2) = ql;
2970  }
2971  else if(type_variable_p(t2)) {
2972  if(pointer_type_p(t2)) {
2973  // The qualifiers must be stored on the effective pointed type
2974  // type pt = type_to_final_pointed_type(t2);
2975  // type pt = type_to_pointed_type(t2);
2977  if(type_void_p(pt))
2978  type_void(pt) = ql;
2979  else if(type_variable_p(pt)) {
2980  // If pt is a typedef, the typedef is altered...
2982  //variable_qualifiers(type_variable(t2)) = ql;
2983  }
2984  else if(type_functional_p(pt)) {
2985  /* What do we do for functional types for instance? */
2986  /* FI: I assume the qualifiers are carried by the
2987  result */
2989  type rt = functional_result(f);
2990  if(type_variable_p(rt))
2992  else
2993  pips_internal_error("???");
2994  }
2995  else {/* What do we do for functional types for instance? */
2996  // FI: I assume the qualifiers are carried by the result
2997  pips_internal_error("???");
2998  }
2999  }
3000  else {
3002  }
3003  }
3004  else
3005  pips_internal_error("unexpected type");
3006  /* Although it should be popped from the stack, the current
3007  context seems to be used later in case of typedef, such as
3008  seen in decl24.c */
3010  }
3011  }
3013 
3014  /* Temporally put the list of struct/union entities defined in
3015  decl_psec_list to initial value of ent */
3016  entity_initial(e) = (value) ld;
3017 
3018 }
bool bit_type_p(type)
Definition: type.c:2843
struct _newgen_struct_value_ * value
Definition: ri.h:455
#define type_void(x)
Definition: ri.h:2961

References basic_pointer, bit_type_p(), c_parser_context_qualifiers, c_parser_context_type, ContextStack, ENDP, entity_initial, entity_name, entity_storage, entity_type, f(), functional_result, get_from_entity_type_stack_table(), make_storage_rom(), NIL, pips_debug, pips_internal_error, pointer_type_p(), stack_head(), stack_pop(), stack_size(), tc, type_functional, type_functional_p, type_variable, type_variable_p, type_void, type_void_p, UpdateType(), variable_basic, and variable_qualifiers.

Referenced by UpdateDerivedEntities().

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

◆ UpdateEntities()

void UpdateEntities ( list  le,
stack  ContextStack,
stack  FormalStack,
stack  FunctionStack,
stack  OffsetStack,
bool  is_external,
bool  is_declaration 
)
Parameters
lee
ContextStackontextStack
FormalStackormalStack
FunctionStackunctionStack
OffsetStackffsetStack
is_externals_external
is_declarations_declaration

Definition at line 2733 of file util.c.

2735 {
2736  FOREACH(ENTITY, e, le) {
2737  if(!derived_entity_p(e))
2739  is_external,is_declaration);
2740  }
2741 }
void UpdateEntity(entity e, stack ContextStack, stack FormalStack, stack FunctionStack, stack OffsetStack, bool is_external, bool is_declaration)
Update the entity with final type, storage and initial value; and also (sometimes?...
Definition: util.c:2473
bool derived_entity_p(entity e)
Definition: entity.c:1048

References ContextStack, derived_entity_p(), ENTITY, FOREACH, FormalStack, FunctionStack, is_external, OffsetStack, and UpdateEntity().

+ Here is the call graph for this function:

◆ UpdateEntity()

void UpdateEntity ( entity  e,
stack  ContextStack,
stack  FormalStack,
stack  FunctionStack,
stack  OffsetStack,
bool  is_external,
bool  is_declaration 
)

Update the entity with final type, storage and initial value; and also (sometimes?) declare it at the module level.

Replace dummy arguments by formal arguments for functions

Generate the return variables for functions returning a result

And probably much more...

If e is an intrinsics, nothing should be done, unless you are in the compilation unit: but the intrinsic type has already been put aside in the type stack linked to the entity and destroyed

tc must have variable type, add lq to its qualifiers

lse const void, void is not of type variable, store const where ????????? CParserError("Entity has qualifier but no type or is not variable type in the context?\n");

Use the type stack in entity_storage to create the final type for the entity

The default type is int, or a function returning an int

FI: it might be a good idea to use the type "unknown" or a future type "default" to improve the prettyprinting by not adding implicit "int" declarations.

The default type is int

FI: This elseif branch is apparently useless because the probleme must be dealt with later in the parser

The default return type is int

FI: no longer true, I believe "this field is always pre-defined. It is temporarilly used to store a type. See cyacc.y rule direct-decl:"

FI: Intrinsic do not have formal named parameters in PIPS RI, however such parameters can be named in intrinsic declarations. Problem with Validation/C_syntax/memcof.c

|| type_variable_p(entity_type(function))

Storage does also matter for typedef (and function pointer)

How to access the information about the function type?

FI: This branch should never be executed

The entities for the type_variable is added to the current module and the declarations

It is too early to use extern_entity_p()

Keyword EXTERN has just been encountered

Yes, but this may have been already recognized in FindOrCreateCurrentEntity() and this may not imply the declaration as extern is another declaration of e has already been encountered.

To avoid multiple declarations

Too late to check that the first declaration did not include an initialization

The function should also added to the declarations

We are defining the current module entity

Test case C_syntax/function_name_conflict01.c

Unfortunately, an intrinsics cannot be redefined, just like a user function or subroutine after editing because intrinsics are not handled like user functions or subroutines. They are not added to the called_modules list of other modules, unless the redefining module is parsed FIRST. There is not mechanism in PIPS to control the parsing order.

Be careful if standard arguments are needed: replace the dummy parameters

FI: intrinsic may need to be processed here if they use dynamic typing, a.k.a. dependent types but they do not have a code value!

They cannot be removed in general because they may appear in declarations as in foo(int n, double a[n])

FI: I do not know if refs contains copies of references or just pointer to them

If e is a function pointer, check the storage of its formal parameters

Parameters
ContextStackontextStack
FormalStackormalStack
FunctionStackunctionStack
OffsetStackffsetStack
is_externals_external
is_declarations_declaration

Definition at line 2473 of file util.c.

2475 {
2476  //stack s = (stack) entity_storage(e);
2478  type t = entity_type(e);
2481  type t1,t2;
2483 
2484  pips_debug(3,"Update entity begins for \"%s\" with context %p\n", entity_name(e), context);
2485 
2486  /* If e is an intrinsics, nothing should be done, unless you are in
2487  the compilation unit: but the intrinsic type has already been
2488  put aside in the type stack linked to the entity and destroyed */
2490  return;
2491 
2492  if (lq != NIL)
2493  {
2494  /* tc must have variable type, add lq to its qualifiers */
2497  else if(type_void_p(tc))
2498  type_void(tc) = lq;
2499  /*else
2500  const void, void is not of type variable, store const where ?????????
2501  CParserError("Entity has qualifier but no type or is not variable type in the context?\n");*/
2503  }
2504 
2505  /************************* TYPE PART *******************************************/
2506 
2507  /* Use the type stack in entity_storage to create the final type for the entity*/
2508  //pips_assert("context type tc is defined", !type_undefined_p(tc));
2509  t2 = UpdateType(t,tc);
2510 
2511  if(t2!=t) {
2512  if(!stack_undefined_p(s)) {
2513  while (stack_size(s) > 1)
2514  {
2515  t1 = stack_pop(s);
2516  t2 = UpdateType(t1,t2);
2517  }
2518  if(type_undefined_p(t2)) {
2519  /* The default type is int, or a function returning an int */
2521  }
2522  }
2523  entity_type(e) = t2;
2524  }
2525 
2526  /* FI: it might be a good idea to use the type "unknown" or a
2527  future type "default" to improve the prettyprinting by not
2528  adding implicit "int" declarations. */
2529  if(type_undefined_p(entity_type(e))) {
2530  /* The default type is int */
2531  entity_type(e) =
2533  }
2534  /* FI: This elseif branch is apparently useless because the
2535  probleme must be dealt with later in the parser */
2536  else if(type_functional_p(entity_type(e))) {
2538  type rt = functional_result(f);
2539  if(type_undefined_p(rt)) {
2540  /* The default return type is int */
2541  functional_result(f) =
2543  }
2544  }
2545  pips_assert("the entity type is defined", !type_undefined_p(entity_type(e)));
2546 
2547  /************************* STORAGE PART *******************************************/
2548 
2549  /* FI: no longer true, I believe "this field is always
2550  pre-defined. It is temporarilly used to store a type. See cyacc.y
2551  rule direct-decl:" */
2552 
2553 
2555  pips_debug(3,"Current storage context is %d\n",
2558  if(typedef_entity_p(e)) {
2560  }
2561  }
2562  else if (!stack_undefined_p(FormalStack) && (FormalStack != NULL)
2563  && !stack_empty_p(FormalStack)) {
2564  entity function = stack_head(FunctionStack);
2566  pips_debug(3,"Create formal variable %s for function %s with offset %d\n",
2567  entity_name(e),entity_name(function),offset);
2568  if(!value_intrinsic_p(entity_initial(function))) {
2569  /* FI: Intrinsic do not have formal named parameters in PIPS
2570  RI, however such parameters can be named in intrinsic
2571  declarations. Problem with Validation/C_syntax/memcof.c */
2572  AddToDeclarations(e,function);
2573  }
2574  if(dummy_parameter_entity_p(e)) {
2575  if(typedef_entity_p(function) /* || type_variable_p(entity_type(function)) */)
2576  /* Storage does also matter for typedef (and function pointer) */
2577  /* How to access the information about the function type? */
2579  else
2581  }
2582  else
2583  /* FI: This branch should never be executed */
2585  }
2586  else if(type_variable_p(ultimate_type(entity_type(e)))) {
2587  /* The entities for the type_variable is added to the
2588  current module and the declarations*/
2589  entity function = get_current_module_entity();
2590 
2591  /* It is too early to use extern_entity_p() */
2592  //if(extern_entity_p(function, e))
2593  if(strstr(entity_name(e),TOP_LEVEL_MODULE_NAME) != NULL)
2595  /* Keyword EXTERN has just been encountered */
2596  /* Yes, but this may have been already recognized in
2597  FindOrCreateCurrentEntity() and this may not imply the
2598  declaration as extern is another declaration of e has
2599  already been encountered. */
2600  type et = ultimate_type(entity_type(e));
2601  if(type_functional_p(et))
2602  AddToExterns(e,function);
2603  }
2604 
2605  /* To avoid multiple declarations */
2606  list el = code_externs(value_code(entity_initial(function)));
2608  if(!gen_in_list_p(e, el) && gen_in_list_p(e, dl)) {
2609  if(compilation_unit_entity_p(function)) {
2610  /* Too late to check that the first declaration did not
2611  include an initialization */
2612  c_parser_user_warning("Multiple declarations of variable \"%s\".\n",
2613  entity_local_name(e));
2614  }
2615  else {
2616  user_log("Multiple declarations of variable \"%s\" in file\"%s\".\n",
2618  CParserError("Illegal Input");
2619  }
2620  }
2621 
2622  AddToDeclarations(e,function);
2623 
2624  // Check here if already stored the value
2626  entity_storage(e) =
2628  }
2630  /* The function should also added to the declarations */
2633  else if(!intrinsic_entity_p(e)) {
2634  /* We are defining the current module entity */
2635  CreateReturnEntity(e);
2636  }
2637  else {
2638  /* Test case C_syntax/function_name_conflict01.c */
2639  c_parser_user_warning("Intrinsic %s redefined.\n"
2640  "This is not supported by PIPS. Please rename \"%s\"\n",
2642  /* Unfortunately, an intrinsics cannot be redefined, just like a user function
2643  * or subroutine after editing because intrinsics are not handled like
2644  * user functions or subroutines. They are not added to the called_modules
2645  * list of other modules, unless the redefining module is parsed FIRST.
2646  * There is not mechanism in PIPS to control the parsing order.
2647  */
2648  CParserError("Name conflict between a "
2649  "function and an intrinsic\n");
2650  }
2652  }
2653  else
2654  pips_assert("not implemented yet", false);
2655 
2656 
2657  /************************* INITIAL VALUE PART ****************************************/
2660  //type t = entity_type(e);
2661  //type ut = ultimate_type(t);
2662  //if(type_functional(ut) && !typedef_entity_p(e))
2663  // entity_initial(e) = make_value_code(make_code(NIL, strdup(""),make_sequence(NIL),NIL, make_language_c()));
2664  //else
2665  // entity_initial(e) = make_value_unknown();
2666  }
2667 
2668  /* Be careful if standard arguments are needed: replace the dummy parameters */
2669  if(true || !is_declaration) {
2670  type t = entity_type(e);
2671  /* FI: intrinsic may need to be processed here if they use dynamic
2672  typing, a.k.a. dependent types but they do not have a code
2673  value!*/
2675  if(is_declaration) {
2676  /* They cannot be removed in general because they may appear
2677  in declarations as in foo(int n, double a[n]) */
2678  value ev = entity_initial(e);
2679  code ec = value_code(ev);
2680  list cmdl = code_declarations(ec);
2682 
2683  RemoveDummyArguments(e, refs);
2684 
2685  /* FI: I do not know if refs contains copies of references or just pointer to them */
2686  gen_free_list(refs);
2687  }
2688  else
2689  UseFormalArguments(e);
2690  }
2691  }
2692 
2693  /* If e is a function pointer, check the storage of its formal parameters */
2694  if(pointer_type_p(entity_type(e))) {
2696  if(type_functional_p(pt)) {
2697  code c = value_code(entity_initial(e));
2698 
2699  pips_assert("Although it's a pointer to a function, it has code...",
2701 
2702  if(code_undefined_p(c))
2703  pips_internal_error("Well, the code field is not defined yet...");
2704  else {
2705  list dl = code_declarations(c);
2706  list cl = list_undefined;
2707 
2708  for(cl=dl; !ENDP(cl); POP(cl)) {
2709  entity pe = ENTITY(CAR(cl));
2710 
2711  if(formal_parameter_p(pe)) {
2712  storage ps = entity_storage(pe);
2713 
2714  pips_debug(8, "Change storage from \"formal\" to \"rom\" for entity \"%s\"\n",
2715  entity_name(pe));
2716  free_storage(ps);
2718  }
2719  }
2720  }
2721  }
2722  }
2723 
2724  pips_debug(3,"Update entity ends for \"%s\" with type \"%s\" and storage \"%s\"\n",
2725  entity_name(e),
2728 
2729  pips_assert("Current entity is consistent",entity_consistent_p(e));
2730 }
void free_storage(storage p)
Definition: ri.c:2231
bool entity_consistent_p(entity p)
Definition: ri.c:2530
#define c_parser_context_storage(x)
storage MakeStorageRam(entity v, bool is_external, bool is_static)
The storage part should not be called twice when reparsing compilation unit.
Definition: util.c:3177
void UseFormalArguments(entity f)
If f has dummy formal parameters, replace them by standard formal parameters.
Definition: util.c:2063
void RemoveDummyArguments(entity f, list refs)
To chase formals in type declarations.
Definition: util.c:2224
void CreateReturnEntity(entity f)
If necessary, create the return entity, which is a hidden variable used in PIPS internal representati...
Definition: util.c:2382
string storage_to_string(storage s)
Definition: entity.c:2030
bool empty_scope_p(string s)
Definition: entity.c:500
list extract_references_from_declarations(list decls)
FI: this function has not yet been extended for C types!!!
Definition: entity.c:2834
type make_scalar_integer_type(_int)
Definition: type.c:712
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define storage_tag(x)
Definition: ri.h:2515

References AddToDeclarations(), AddToExterns(), basic_int, basic_pointer, c_parser_context_qualifiers, c_parser_context_scope, c_parser_context_static, c_parser_context_storage, c_parser_context_type, c_parser_user_warning, CAR, code_declarations, code_externs, code_undefined_p, compilation_unit_entity_p(), compilation_unit_p(), ContextStack, CParserError(), CreateReturnEntity(), DEFAULT_INTEGER_TYPE_SIZE, dummy_parameter_entity_p(), empty_scope_p(), ENDP, ENTITY, entity_consistent_p(), entity_initial, entity_local_name(), entity_name, entity_storage, entity_type, entity_undefined_p, extract_references_from_declarations(), f(), formal_parameter_p(), FormalStack, free_storage(), functional_result, FunctionStack, gen_free_list(), gen_in_list_p(), get_c_parser_current_input_file_name(), get_current_module_entity(), get_current_module_name(), get_from_entity_type_stack_table(), intrinsic_entity_p(), is_external, list_to_string(), list_undefined, make_basic_int(), make_formal(), make_scalar_integer_type(), make_storage_formal(), make_storage_rom(), make_type_variable(), make_value_unknown(), make_variable(), MakeStorageRam(), NIL, offset, OffsetStack, pips_assert, pips_debug, pips_internal_error, pointer_type_p(), POP, RemoveDummyArguments(), safe_c_words_entity(), stack_empty_p(), stack_head(), stack_pop(), stack_size(), stack_undefined_p, storage_tag, storage_to_string(), storage_undefined_p, tc, TOP_LEVEL_MODULE_NAME, type_functional, type_functional_p, type_undefined_p, type_variable, type_variable_p, type_void, type_void_p, typedef_entity_p(), ultimate_type(), UpdateType(), UseFormalArguments(), user_log(), value_code, value_code_p, value_intrinsic_p, value_undefined_p, variable_basic, and variable_qualifiers.

Referenced by UpdateEntities().

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

◆ UpdateEntity2()

void UpdateEntity2 ( entity  f,
stack FormalStack   __attribute__(__unused__),
stack OffsetStack   __attribute__(__unused__) 
)

A subset of UpdateEntity, used when the function entity is already more defined because the return type is implicit.

See call site cyacc.y

The return value is created when needed.

The dummy parameters are used to create the formal parameters.

Definition at line 2431 of file util.c.

2434 {
2437  list cl = list_undefined;
2438  int rank = 1; // formal parameter offset
2439 
2440  pips_assert("f has a functional type", type_functional_p(ft));
2441 
2443 
2444  for(cl = dl; !ENDP(cl); POP(cl)) {
2445  entity v = ENTITY(CAR(cl));
2446  if(dummy_parameter_entity_p(v)) {
2447  const char * ln = entity_user_name(v);
2448  const char* mn = entity_local_name(f);
2449  entity fp = FindEntity(mn, ln);
2450  if(entity_undefined_p(fp)) {
2451  fp = FindOrCreateEntity(mn, ln);
2452  entity_type(fp) = copy_type(entity_type(v));
2455  rank++;
2456  ENTITY_(CAR(cl)) = fp; // substitute v by fp in the declaration list
2457  }
2458  }
2459  }
2460 
2461 }
static entity rank

References CAR, code_declarations, copy_type(), CreateReturnEntity(), dummy_parameter_entity_p(), ENDP, ENTITY, ENTITY_, entity_initial, entity_local_name(), entity_storage, entity_type, entity_undefined_p, entity_user_name(), f(), FindEntity(), FindOrCreateEntity(), list_undefined, make_formal(), make_storage_formal(), make_value_unknown(), pips_assert, POP, rank, type_functional_p, ultimate_type(), and value_code.

+ Here is the call graph for this function:

◆ UpdateFinalPointer()

type UpdateFinalPointer ( type  pt,
type  t 
)

This function replaces the type pointed by the pointer pt (this can be a pointer of pointer,... so we have to go until the last one) by the type t

Parameters
ptt

Definition at line 1427 of file util.c.

1428 {
1429  /* This function replaces the type pointed by the pointer pt
1430  (this can be a pointer of pointer,... so we have to go until the last one)
1431  by the type t*/
1432  pips_debug(3,"Update final pointer type %d and %d\n", type_tag(pt), type_tag(t));
1434  {
1436  if (type_undefined_p(ppt))
1438  return UpdateFinalPointer(ppt,t);
1439  }
1440  CParserError("pt is not a pointer\n");
1441  return type_undefined;
1442 }
basic make_basic_pointer(type _field_)
Definition: ri.c:179
type UpdateFinalPointer(type pt, type t)
Definition: util.c:1427

References basic_pointer, basic_pointer_p, CParserError(), make_basic_pointer(), make_type_variable(), make_variable(), NIL, pips_debug, type_tag, type_undefined, type_undefined_p, type_variable, type_variable_p, UpdateFinalPointer(), variable_basic, and variable_qualifiers.

Referenced by UpdateFinalPointer().

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

◆ UpdateFunctionEntity()

void UpdateFunctionEntity ( entity  oe,
list  la 
)

The parser has found out that an entity is a function and partially sets its type.

The function may also be an intrinsics and be already fully defined.

If oe is an intrinsics, nothing should be done if we are compiling a function that redeclares intrinsics, because they are usually badly or at least only partly redeclared.

However, il should be updated if it's declared in a compilation unit as the header files may contain more up-to-date information than bootstrap. Or if its type has already been placed in the type stack and been undefined in the entity.

Note that a user function might have the same name as a C intrinsic. Then we are in trouble.

Is oe's name compatible with a function name? Well oe might be a pointer...

FI: We used never to bump into this case...

Parameters
oee
laa

Definition at line 1614 of file util.c.

1615 {
1616  type t = entity_type(oe);
1617  //string oeln = entity_local_name(oe);
1618  //string sn = local_name_to_scope(oeln);
1619  //entity ne = oe;
1620 
1621  pips_debug(3,"Update function entity \"%s\"\n",entity_name(oe));
1622 
1623  ifdebug(8) {
1624  pips_debug(8, "with type list la: ");
1625  if(ENDP(la)) {
1626  (void) fprintf(stderr, "empty list");
1627  }
1628  MAP(PARAMETER, at, {
1629  (void) fprintf(stderr, "%s, ", list_to_string(safe_c_words_entity(parameter_type(at), NIL)));
1630  }, la);
1631  (void) fprintf(stderr, "\n");
1632  }
1633 
1634  /* If oe is an intrinsics, nothing should be done if we are
1635  compiling a function that redeclares intrinsics, because they are
1636  usually badly or at least only partly redeclared.
1637 
1638  However, il should be updated if it's declared in a compilation unit
1639  as the header files may contain more up-to-date information than
1640  bootstrap. Or if its type has already been placed in the type
1641  stack and been undefined in the entity.
1642 
1643  Note that a user function might have the same name as a C
1644  intrinsic. Then we are in trouble.
1645  */
1646  if(intrinsic_entity_p(oe)
1649  && !type_undefined_p(entity_type(oe)))
1650  return;
1651 
1652  /* Is oe's name compatible with a function name? Well oe might be a
1653  pointer... */
1654  // pips_assert("A function name does not include a scope", empty_string_p(sn));
1655 
1656  if (type_undefined_p(t))
1658  else if(type_functional_p(t)) {
1659  /* FI: We used never to bump into this case... */
1661  functional_parameters(f) = la;
1662  }
1663  else {
1664  pips_internal_error("What should be done here?");
1665  CParserError("This entity must have undefined type\n");
1666  }
1667 
1668  pips_debug(3,"Update function entity \"%s\" with type \"\%s\"\n",
1669  entity_name(oe),
1671 }
#define parameter_type(x)
Definition: ri.h:1819

References compilation_unit_p(), CParserError(), ENDP, entity_name, entity_type, entity_undefined_p, f(), fprintf(), functional_parameters, get_current_module_entity(), get_current_module_name(), ifdebug, intrinsic_entity_p(), list_to_string(), make_functional(), make_type_functional(), MAP, NIL, PARAMETER, parameter_type, pips_debug, pips_internal_error, safe_c_words_entity(), type_functional, type_functional_p, type_undefined, and type_undefined_p.

+ Here is the call graph for this function:

◆ UpdateParenEntity()

void UpdateParenEntity ( entity  e,
list  lq 
)
Parameters
lqq

Definition at line 1368 of file util.c.

1369 {
1370  type t = entity_type(e);
1371  pips_debug(3,"Update entity in parentheses \"%s\" with type \"%s\"\n",
1373  if (lq != NIL) {
1374  if (type_undefined_p(t))
1376  else {
1377  if (type_variable_p(t)) {
1378  variable v = type_variable(t);
1380  }
1381  else {
1382  CParserError("Attributes for not variable type\n");
1383  }
1384  }
1385  }
1386 }
string safe_type_to_string(const type)
Definition: type.c:59

References basic_undefined, CParserError(), entity_name, entity_type, gen_nconc(), list_undefined, make_type_variable(), make_variable(), NIL, pips_debug, safe_type_to_string(), type_undefined_p, type_variable, type_variable_p, and variable_qualifiers.

+ Here is the call graph for this function:

◆ UpdatePointerEntity()

void UpdatePointerEntity ( entity  e,
type  pt,
list  lq 
)

Make e an array of pointers whose type is this of pt

Make e a function returns a pointer

Parameters
ptt
lqq

Definition at line 1444 of file util.c.

1445 {
1446  type t = entity_type(e);
1447  ifdebug(3) {
1448  list pdl = NIL;
1449  pips_debug(3,"Update pointer entity %s with type pt=\"%s\"\n",
1450  entity_name(e), list_to_string(c_words_entity(pt, NIL, &pdl)));
1451  gen_free_list(pdl);
1452  }
1453  if (type_undefined_p(t))
1454  {
1455  pips_debug(3,"Undefined entity type\n");
1456  entity_type(e) = pt;
1457  /*
1458  if(type_undefined_p(pt)) {
1459  type npt = make_type(is_type_variable,
1460  make_variable(make_basic(is_basic_pointer, type_undefined),
1461  NIL, NIL));
1462  entity_type(e) = npt;
1463  }
1464  else if(type_variable_p(pt) && basic_pointer_p(variable_basic(type_variable(pt))))
1465  entity_type(e) = pt;
1466  else {
1467  type npt = make_type(is_type_variable,
1468  make_variable(make_basic(is_basic_pointer, pt),
1469  NIL, NIL));
1470  entity_type(e) = npt;
1471  }
1472  */
1473 
1475  }
1476  else
1477  {
1478  switch (type_tag(t)) {
1479  case is_type_variable:
1480  {
1481  /* Make e an array of pointers whose type is this of pt */
1482  variable v = type_variable(t);
1483  pips_debug(3,"Array of pointers\n");
1486  gen_nconc(variable_qualifiers(v),lq)));
1487  break;
1488  }
1489  case is_type_functional:
1490  {
1491  /* Make e a function returns a pointer */
1493  pips_debug(3,"Function returns a pointer \n");
1494  entity_type(e) =
1496  break;
1497  }
1498  default:
1499  {
1500  CParserError("Entity is neither an array of pointers nor a pointer to a function?\n");
1501  }
1502  }
1503  }
1504  ifdebug(3) {
1505  list pdl = NIL;
1506  pips_debug(3,"Ends with type \"%s\" for entity %s\n",
1508  entity_name(e));
1509  gen_free_list(pdl);
1510  }
1511 
1512 }
list c_words_entity(type t, list name, list *ppdl)

References c_words_entity(), CParserError(), entity_name, entity_type, f(), functional_parameters, gen_free_list(), gen_nconc(), ifdebug, is_type_functional, is_type_variable, list_to_string(), make_functional(), make_type_functional(), make_type_variable(), make_variable(), NIL, pips_debug, type_functional, type_tag, type_undefined_p, type_variable, variable_basic, variable_dimensions, and variable_qualifiers.

+ Here is the call graph for this function:

◆ UpdateType()

type UpdateType ( type  t1,
type  t2 
)

This function replaces the undefined field in t1 by t2.

If t1 is an array type and the basic of t1 is undefined, it is replaced by the basic of t2.

If t1 is a pointer type, if the pointed type is undefined it is replaced by t2.

If t1 is a functional type, if the result type of t1 is undefined, it is replaced by t2.

If t1 is a void type, then either t2 also is a void type or an error is raised.

The function is recursive.

FI: This function used to create sharing between t1 and t2, which creates problems when t2 is later freed. t1 may be updated and returned or a new type may be created.

This may happen when a type is implicitly declared as in "extern m[3];"

We used to use type_unknown when the type was implicit, but type_unknown does not let us store dimension information. We need here a new kind of basic, basic unknown or basic implicit. This would let us be more respectful of the source code, but requires a modification of the internal representation. It is mostly a prettyprint issue. See ticket

Basic pointer

t1 is already fully defined

Redundant update

Could be a pips internal error...

Parameters
t11
t22

Definition at line 1693 of file util.c.

1694 {
1695  if (type_undefined_p(t1)) {
1696  if(!type_undefined_p(t2))
1697  return copy_type(t2);
1698  else
1699  return t2;
1700  }
1701 
1702  if(type_undefined_p(t2)) {
1703  /* This may happen when a type is implicitly declared as in
1704  "extern m[3];" */
1705  /* We used to use type_unknown when the type was implicit, but
1706  type_unknown does not let us store dimension information. We
1707  need here a new kind of basic, basic unknown or basic
1708  implicit. This would let us be more respectful of the source
1709  code, but requires a modification of the internal
1710  representation. It is mostly a prettyprint issue. See ticket
1711  225. */
1713  }
1714 
1715  switch (type_tag(t1))
1716  {
1717  case is_type_variable:
1718  {
1719  variable v = type_variable(t1);
1721  {
1722  pips_assert("type t2 is defined", !type_undefined_p(t2));
1723  if (type_variable_p(t2))
1728  CParserError("t1 is a variable type but not t2\n");
1729  }
1730  else
1731  {
1732  /* Basic pointer */
1734  {
1738  variable_qualifiers(v)));
1739  }
1740  else {
1741  /* t1 is already fully defined */
1742  if(type_equal_p(t1,t2))
1743  return t2;
1744  else if(overloaded_type_p(t1))
1745  return t2;
1746  else
1747  CParserError("This basic has an undefined field?\n");
1748  }
1749  }
1750  break;
1751  }
1752  case is_type_functional:
1753  {
1756  {
1757  type nt = type_undefined;
1758  if (type_undefined_p(t2))
1759  nt = make_type_unknown();
1760  else
1761  nt = copy_type(t2);
1763  }
1765  }
1766  case is_type_void:
1767  {
1768  if(type_void_p(t2)) {
1769  /* Redundant update */
1770  ;
1771  }
1772  else {
1773  /* Could be a pips internal error... */
1774  CParserError("void type to be updated by a non void type...\n");
1775  }
1776  return t1;
1777  }
1778  default:
1779  {
1780  CParserError("t1 has which kind of type?\n");
1781  }
1782  }
1783  return type_undefined;
1784 }
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
bool type_equal_p(type, type)
Definition: type.c:547
#define basic_undefined_p(x)
Definition: ri.h:557
@ is_type_void
Definition: ri.h:2904

References basic_pointer, basic_pointer_p, basic_undefined_p, copy_basic(), copy_type(), CParserError(), DEFAULT_INTEGER_TYPE_SIZE, f(), functional_parameters, functional_result, gen_full_copy_list(), gen_nconc(), is_type_functional, is_type_variable, is_type_void, make_basic_pointer(), make_functional(), make_scalar_integer_type(), make_type_functional(), make_type_unknown(), make_type_variable(), make_variable(), overloaded_type_p(), pips_assert, type_equal_p(), type_functional, type_tag, type_undefined, type_undefined_p, type_variable, type_variable_p, type_void_p, UpdateType(), variable_basic, variable_dimensions, and variable_qualifiers.

Referenced by UpdateAbstractEntity(), UpdateDerivedEntity(), UpdateEntity(), and UpdateType().

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

◆ UseDummyArguments()

void UseDummyArguments ( entity  f)

If f has regular formal parameters, destroy them.

make a list of formal parameters

Remove the formals from f's declaration list and from the symbol table

FI: The storage might point to another dummy argument (although it should not)

Let's hope there are no other pointers towards dummy formal parameters

Definition at line 2019 of file util.c.

2020 {
2021  value fv = entity_initial(f);
2022 
2023  pips_assert("The function value is defined", !value_undefined_p(fv));
2024  pips_assert("The entity has a functional type", type_functional_p(entity_type(f)));
2025  pips_assert("The entity is not a typedef", !typedef_entity_p(f));
2026 
2027  if(!value_undefined_p(fv)) {
2028  code fc = value_code(fv);
2029  list dl = code_declarations(fc);
2030  list cd = list_undefined;
2031  list formals = NIL;
2032 
2033  pips_assert("the value is code", value_code_p(fv));
2034 
2035  /* make a list of formal parameters */
2036  for(cd = dl; !ENDP(cd); POP(cd)) {
2037  entity v = ENTITY(CAR(cd));
2038  if(entity_formal_p(v)) {
2039  pips_debug(8, "Formal parameter: \"%s\"\n", entity_name(v));
2040  formals = gen_nconc(formals, CONS(ENTITY, v, NIL));
2041  }
2042  }
2043 
2044  /* Remove the formals from f's declaration list and from the
2045  symbol table */
2046  for(cd = formals; !ENDP(cd); POP(cd)) {
2047  entity p = ENTITY(CAR(cd));
2048  storage ps = entity_storage(p);
2049  formal pfs = storage_formal(ps);
2050 
2051  gen_remove(&code_declarations(fc), (void *) p);
2052  /* FI: The storage might point to another dummy argument
2053  (although it should not) */
2055  /* Let's hope there are no other pointers towards dummy formal parameters */
2056  //free_entity(p);
2057  }
2058  gen_free_list(formals);
2059  }
2060 }

References CAR, code_declarations, CONS, ENDP, ENTITY, entity_formal_p(), entity_initial, entity_name, entity_storage, entity_type, entity_undefined, f(), formal_function, gen_free_list(), gen_nconc(), gen_remove(), list_undefined, NIL, pips_assert, pips_debug, POP, storage_formal, type_functional_p, typedef_entity_p(), value_code, value_code_p, and value_undefined_p.

+ Here is the call graph for this function:

◆ UseFormalArguments()

void UseFormalArguments ( entity  f)

If f has dummy formal parameters, replace them by standard formal parameters.

make a list of formal dumy parameters; depending on the kind of function declaration, dummy formal parameters are used (new C function declaration style), or not (old C function declaration style).

FI: Maybe, it would be better to unify the use of summy formal parameter in the parser?

Is it a local function or global function?

mn = strdup(concatenate(entity_module_name(f),entity_local_name(f), NULL));

Remore the dummy formals from f's declaration list (and from the symbol table?) and replace them by equivalent regular formal parameters

Substitute p by new_p in the declaration references for cases such as "foo(n, double a[n])"

This only works if the refs list points to the actual references and not to copies...

sg: this test used to be if e == p, but it missed some cases because reference_variable may have been generated incorectly before using a TOP_LEVEL variable instead of the dummy

A substitution could be performed instead...

FI: The storage might point to another dummy argument (although it should not)

Let's hope there are no other pointers towards dummy formal parameters

Check substitution in formal parameter declarations

FI: just in case?

Do not free the dummy formal parameter variable as they are preserved in the dummy field for accurate prettyprinting

Definition at line 2063 of file util.c.

2064 {
2065  value fv = entity_initial(f);
2066 
2067  pips_assert("The function value is defined", !value_undefined_p(fv));
2068  pips_assert("The entity has a functional type", type_functional_p(entity_type(f)));
2069  pips_assert("The entity is not a typedef", !typedef_entity_p(f));
2070 
2071  if(!value_undefined_p(fv)) {
2072  code fc = value_code(fv);
2074  list cd = list_undefined;
2075  list formals = NIL;
2076  string mn = string_undefined;
2077  // This is a minimal list of references. We need all references.
2078  //list refs1 = extract_references_from_declarations(dl);
2080 
2081  ifdebug(8) {
2082  int l2 = gen_length(refs);
2083 
2084  pips_debug(8, "refs (%d elements):\n", l2);
2085  print_references(refs);
2086  }
2087 
2088  pips_assert("the value is code", value_code_p(fv));
2089 
2090  /* make a list of formal dumy parameters; depending on the kind of
2091  function declaration, dummy formal parameters are used (new C
2092  function declaration style), or not (old C function declaration
2093  style).
2094 
2095  FI: Maybe, it would be better to unify the use of summy formal
2096  parameter in the parser?
2097  */
2098  for(cd = dl; !ENDP(cd); POP(cd)) {
2099  entity v = ENTITY(CAR(cd));
2100  if(entity_formal_p(v)) {
2101  pips_debug(8, "Formal parameter: \"%s\"\n", entity_name(v));
2103  formals = gen_nconc(formals, CONS(ENTITY, v, NIL));
2104  //pips_assert("v is a dummy parameter", dummy_parameter_entity_p(v));
2105  }
2106  }
2107 
2108  /* Is it a local function or global function? */
2109  if(top_level_entity_p(f))
2110  mn = strdup(entity_user_name(f));
2111  else
2112  /* mn = strdup(concatenate(entity_module_name(f),entity_local_name(f), NULL)); */
2113  mn = strdup(entity_local_name(f));
2114 
2115  /* Remore the dummy formals from f's declaration list (and from the
2116  symbol table?) and replace them by equivalent regular formal parameters */
2117  for(cd = formals; !ENDP(cd); POP(cd)) {
2118  entity p = ENTITY(CAR(cd));
2119  const char * pn = entity_user_name(p);
2120  entity new_p = entity_undefined;
2121  //storage ps = entity_storage(p);
2122  //formal pfs = storage_formal(ps);
2123 
2125  new_p = FindOrCreateEntity(mn, pn );
2127  entity_type(new_p) = copy_type(entity_type(p));
2129  pips_debug(8, "Formal dummy parameter \"%s\" is replaced "
2130  "by standard formal parameter \"%s\"\n",
2131  entity_name(p), entity_name(new_p));
2132 
2133  /* Substitute p by new_p in the declaration references for cases
2134  such as "foo(n, double a[n])" */
2135  /* This only works if the refs list points to the actual
2136  references and not to copies... */
2137  FOREACH(REFERENCE, r, refs){
2138  entity e = reference_variable(r);
2139 
2140  /* sg: this test used to be if e == p, but it missed some cases
2141  * because reference_variable may have been generated incorectly before
2142  * using a TOP_LEVEL variable instead of the dummy */
2143  if(same_entity_lname_p(e,p)) {
2144  reference_variable(r) = new_p;
2145  pips_debug(8, "reference %p to \"%s\" changed into reference to \"\%s\"\n",
2146  r, entity_name(p), entity_name(new_p));
2147  }
2148  }
2149 
2150  /* A substitution could be performed instead...*/
2151  gen_remove(&code_declarations(fc), (void *) p);
2153 
2154  /* FI: The storage might point to another dummy argument
2155  (although it should not) */
2156  //formal_function(pfs) = entity_undefined;
2157  /* Let's hope there are no other pointers towards dummy formal parameters */
2158  //free_entity(p); // FI: we may use them in the type data structures in spite of the MAP on refs?
2159  }
2160  }
2161  gen_free_list(dl);
2162 
2163  ifdebug(1) {
2164  dl = module_all_declarations(f);
2165  /* Check substitution in formal parameter declarations */
2166  ifdebug(8) {
2167  pips_debug(8, "list of declared variables:\n");
2168  print_entities(dl);
2169  (void) fprintf(stderr, "\n");
2170  }
2172  MAP(REFERENCE, r, {
2173  entity v = reference_variable(r);
2174  if(dummy_parameter_entity_p(v)) {
2175  pips_debug(8, "Substitution failed for reference %p and variable \"%s\"\n",
2176  r, entity_name(v));
2177  pips_internal_error("Failed substitution");
2178  }
2179  }, refs);
2180  gen_free_list(dl);
2181  }
2182 
2183  /* FI: just in case? */
2184  remove_entity_type_stacks(formals);
2185 
2186  /* Do not free the dummy formal parameter variable as they are
2187  preserved in the dummy field for accurate prettyprinting */
2188  /*
2189  MAP(ENTITY, df, {
2190  free_entity(df);
2191  }, formals);
2192  */
2193 
2194  free(mn);
2195  gen_free_list(formals);
2196  }
2197 }
void print_references(list rl)
Definition: expression.c:163
bool same_entity_lname_p(entity, entity)
Definition: same_names.c:64
list module_all_declarations(entity m)
The function itself is not in its declarations.
Definition: module.c:419
list declaration_supporting_references(list dl)
Find all references in the declaration list.
Definition: module.c:392

References CAR, code_declarations, CONS, copy_storage(), copy_type(), copy_value(), declaration_supporting_references(), dummy_parameter_entity_p(), ENDP, ENTITY, entity_formal_p(), entity_initial, entity_local_name(), entity_name, entity_storage, entity_type, entity_undefined, entity_user_name(), f(), FindOrCreateEntity(), FOREACH, fprintf(), free(), gen_free_list(), gen_length(), gen_nconc(), gen_remove(), get_from_entity_type_stack_table(), ifdebug, list_undefined, MAP, module_all_declarations(), NIL, pips_assert, pips_debug, pips_internal_error, POP, print_entities(), print_references(), REFERENCE, reference_variable, remove_entity_type_stacks(), same_entity_lname_p(), stack_undefined_p, strdup(), string_undefined, top_level_entity_p(), type_functional_p, typedef_entity_p(), value_code, value_code_p, and value_undefined_p.

Referenced by UpdateEntity().

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

Variable Documentation

◆ buffer_initialized_p

bool buffer_initialized_p = false
static

Definition at line 3590 of file util.c.

Referenced by analyze_preprocessor_line(), and reset_preprocessor_line_analysis().

◆ current_dummy_parameter_number

int current_dummy_parameter_number =0
static

The data structure to tackle the memory allocation problem due to reparsing of compilation unit.

static int previoussizeofGlobalArea; entity previouscompunit; To keep track of the current dummy parameter naming. A function can be redeclared and it is difficult to make a difference between "void foo(int u, int u);", which not in the standard, and "void foo(int u); void foo(int u); which is fine"

Definition at line 137 of file util.c.

Referenced by get_current_dummy_parameter_number(), reset_current_dummy_parameter_number(), and set_current_dummy_parameter_number().

◆ declarationerror_p

bool declarationerror_p
static

Definition at line 1788 of file util.c.

Referenced by nodecl_p(), and referencenodeclfilter().