LCOV - code coverage report
Current view: top level - gcc/m2/gm2-gcc - m2block.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.7 % 277 243
Test Date: 2025-09-20 13:40:47 Functions: 79.5 % 39 31
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* m2block.cc provides an interface to maintaining block structures.
       2                 :             : 
       3                 :             : Copyright (C) 2012-2025 Free Software Foundation, Inc.
       4                 :             : Contributed by Gaius Mulley <gaius@glam.ac.uk>.
       5                 :             : 
       6                 :             : This file is part of GNU Modula-2.
       7                 :             : 
       8                 :             : GNU Modula-2 is free software; you can redistribute it and/or modify
       9                 :             : it under the terms of the GNU General Public License as published by
      10                 :             : the Free Software Foundation; either version 3, or (at your option)
      11                 :             : any later version.
      12                 :             : 
      13                 :             : GNU Modula-2 is distributed in the hope that it will be useful, but
      14                 :             : WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16                 :             : General Public License for more details.
      17                 :             : 
      18                 :             : You should have received a copy of the GNU General Public License
      19                 :             : along with GNU Modula-2; see the file COPYING3.  If not see
      20                 :             : <http://www.gnu.org/licenses/>.  */
      21                 :             : 
      22                 :             : #include "gcc-consolidation.h"
      23                 :             : 
      24                 :             : #define m2block_c
      25                 :             : #include "m2assert.h"
      26                 :             : #include "m2block.h"
      27                 :             : #include "m2decl.h"
      28                 :             : #include "m2options.h"
      29                 :             : #include "m2tree.h"
      30                 :             : #include "m2treelib.h"
      31                 :             : #include "m2pp.h"
      32                 :             : 
      33                 :             : /* For each binding contour we allocate a binding_level structure
      34                 :             :    which records the entities defined or declared in that contour.
      35                 :             :    Contours include:
      36                 :             : 
      37                 :             :    the global one one for each subprogram definition
      38                 :             : 
      39                 :             :    Binding contours are used to create GCC tree BLOCK nodes.  */
      40                 :             : 
      41                 :             : struct GTY (()) binding_level
      42                 :             : {
      43                 :             :   /* The function associated with the scope.  This is NULL_TREE for the
      44                 :             :      global scope.  */
      45                 :             :   tree fndecl;
      46                 :             : 
      47                 :             :   /* A chain of _DECL nodes for all variables, constants, functions,
      48                 :             :      and typedef types.  These are in the reverse of the order supplied.  */
      49                 :             :   tree names;
      50                 :             : 
      51                 :             :   /* A boolean to indicate whether this is binding level is a global ie
      52                 :             :      outer module scope.  In which case fndecl will be NULL_TREE.  */
      53                 :             :   int is_global;
      54                 :             : 
      55                 :             :   /* The context of the binding level, for a function binding level
      56                 :             :      this will be the same as fndecl, however for a global binding level
      57                 :             :      this is a translation_unit.  */
      58                 :             :   tree context;
      59                 :             : 
      60                 :             :   /* The binding level below this one.  This field is only used when
      61                 :             :      the binding level has been pushed by pushFunctionScope.  */
      62                 :             :   struct binding_level *next;
      63                 :             : 
      64                 :             :   /* All binding levels are placed onto this list.  */
      65                 :             :   struct binding_level *list;
      66                 :             : 
      67                 :             :   /* A varray of trees, which represent the list of statement
      68                 :             :      sequences.  */
      69                 :             :   vec<tree, va_gc> *m2_statements;
      70                 :             : 
      71                 :             :   /* A list of constants (only kept in the global binding level).
      72                 :             :      Constants need to be kept through the life of the compilation, as the
      73                 :             :      same constants can be used in any scope.  */
      74                 :             :   tree constants;
      75                 :             : 
      76                 :             :   /* A list of inner module initialization functions.  */
      77                 :             :   tree init_functions;
      78                 :             : 
      79                 :             :   /* A list of types created by M2GCCDeclare prior to code generation
      80                 :             :      and those which may not be specifically declared and saved via a
      81                 :             :      push_decl.  */
      82                 :             :   tree types;
      83                 :             : 
      84                 :             :   /* A list of all DECL_EXPR created within this binding level.  This
      85                 :             :      will be prepended to the statement list once the binding level (scope
      86                 :             :      is finished).  */
      87                 :             :   tree decl;
      88                 :             : 
      89                 :             :   /* A list of labels which have been created in this scope.  */
      90                 :             :   tree labels;
      91                 :             : 
      92                 :             :   /* The number of times this level has been pushed.  */
      93                 :             :   int count;
      94                 :             : };
      95                 :             : 
      96                 :             : /* The binding level currently in effect.  */
      97                 :             : 
      98                 :             : static GTY (()) struct binding_level *current_binding_level;
      99                 :             : 
     100                 :             : /* The outermost binding level, for names of file scope.  This is
     101                 :             :    created when the compiler is started and exists through the entire
     102                 :             :    run.  */
     103                 :             : 
     104                 :             : static GTY (()) struct binding_level *global_binding_level;
     105                 :             : 
     106                 :             : /* The head of the binding level lists.  */
     107                 :             : static GTY (()) struct binding_level *head_binding_level;
     108                 :             : 
     109                 :             : /* The current statement tree.  */
     110                 :             : 
     111                 :             : typedef struct stmt_tree_s *stmt_tree_t;
     112                 :             : 
     113                 :             : #undef DEBUGGING
     114                 :             : 
     115                 :             : static location_t pending_location;
     116                 :             : static int pending_statement = false;
     117                 :             : 
     118                 :             : /* GetTotalConstants returns the number of global constants.  */
     119                 :             : 
     120                 :             : int
     121                 :           0 : m2block_GetTotalConstants (void)
     122                 :             : {
     123                 :           0 :   return m2treelib_nCount (global_binding_level->constants);
     124                 :             : }
     125                 :             : 
     126                 :             : /* GetGlobalTypes returns the number of global types.  */
     127                 :             : 
     128                 :             : int
     129                 :           0 : m2block_GetGlobalTypes (void)
     130                 :             : {
     131                 :           0 :   return m2treelib_nCount (global_binding_level->types);
     132                 :             : }
     133                 :             : 
     134                 :             : /* assert_global_names asserts that the global_binding_level->names
     135                 :             :    can be chained.  */
     136                 :             : 
     137                 :             : static void
     138                 :    12763183 : assert_global_names (void)
     139                 :             : {
     140                 :    12763183 :   tree p = global_binding_level->names;
     141                 :             : 
     142                 :  6286681336 :   while (p)
     143                 :  6273918153 :     p = TREE_CHAIN (p);
     144                 :    12763183 : }
     145                 :             : 
     146                 :             : /* lookupLabel return label tree in current scope, otherwise
     147                 :             :    NULL_TREE.  */
     148                 :             : 
     149                 :             : static tree
     150                 :      252607 : lookupLabel (tree id)
     151                 :             : {
     152                 :      252607 :   tree t;
     153                 :             : 
     154                 :      902460 :   for (t = current_binding_level->labels; t != NULL_TREE; t = TREE_CHAIN (t))
     155                 :             :     {
     156                 :      787431 :       tree l = TREE_VALUE (t);
     157                 :             : 
     158                 :      787431 :       if (id == DECL_NAME (l))
     159                 :             :         return l;
     160                 :             :     }
     161                 :             :   return NULL_TREE;
     162                 :             : }
     163                 :             : 
     164                 :             : /* getLabel return the label name or create a label name in the
     165                 :             :    current scope.  */
     166                 :             : 
     167                 :             : tree
     168                 :      252607 : m2block_getLabel (location_t location, char *name)
     169                 :             : {
     170                 :      252607 :   tree id = get_identifier (name);
     171                 :      252607 :   tree label = lookupLabel (id);
     172                 :             : 
     173                 :      252607 :   if (label == NULL_TREE)
     174                 :             :     {
     175                 :      115029 :       label = build_decl (location, LABEL_DECL, id, void_type_node);
     176                 :      115029 :       current_binding_level->labels
     177                 :      115029 :           = tree_cons (NULL_TREE, label, current_binding_level->labels);
     178                 :             :     }
     179                 :      252607 :   if (DECL_CONTEXT (label) == NULL_TREE)
     180                 :      115041 :     DECL_CONTEXT (label) = current_function_decl;
     181                 :      252607 :   ASSERT ((DECL_CONTEXT (label) == current_function_decl),
     182                 :      252607 :           current_function_decl);
     183                 :             : 
     184                 :      252607 :   DECL_MODE (label) = VOIDmode;
     185                 :      252607 :   return label;
     186                 :             : }
     187                 :             : 
     188                 :             : static void
     189                 :      134710 : init_binding_level (struct binding_level *l)
     190                 :             : {
     191                 :      134710 :   l->fndecl = NULL;
     192                 :      134710 :   l->names = NULL;
     193                 :      134710 :   l->is_global = 0;
     194                 :      134710 :   l->context = NULL;
     195                 :      134710 :   l->next = NULL;
     196                 :      134710 :   l->list = NULL;
     197                 :      134710 :   vec_alloc (l->m2_statements, 1);
     198                 :      134710 :   l->constants = NULL;
     199                 :      134710 :   l->init_functions = NULL;
     200                 :      134710 :   l->types = NULL;
     201                 :      134710 :   l->decl = NULL;
     202                 :      134710 :   l->labels = NULL;
     203                 :      134710 :   l->count = 0;
     204                 :      134710 : }
     205                 :             : 
     206                 :             : static struct binding_level *
     207                 :      134710 : newLevel (void)
     208                 :             : {
     209                 :      134710 :   struct binding_level *newlevel = ggc_alloc<binding_level> ();
     210                 :             : 
     211                 :      134710 :   init_binding_level (newlevel);
     212                 :             : 
     213                 :             :   /* Now we a push_statement_list.  */
     214                 :      134710 :   vec_safe_push (newlevel->m2_statements, m2block_begin_statement_list ());
     215                 :      134710 :   return newlevel;
     216                 :             : }
     217                 :             : 
     218                 :             : tree *
     219                 :     1425946 : m2block_cur_stmt_list_addr (void)
     220                 :             : {
     221                 :     1425946 :   ASSERT_CONDITION (current_binding_level != NULL);
     222                 :     1425946 :   int l = vec_safe_length (current_binding_level->m2_statements) - 1;
     223                 :             : 
     224                 :     1425946 :   return &(*current_binding_level->m2_statements)[l];
     225                 :             : }
     226                 :             : 
     227                 :             : tree
     228                 :           0 : m2block_cur_stmt_list (void)
     229                 :             : {
     230                 :           0 :   tree *t = m2block_cur_stmt_list_addr ();
     231                 :             : 
     232                 :           0 :   return *t;
     233                 :             : }
     234                 :             : 
     235                 :             : /* is_building_stmt_list returns true if we are building a
     236                 :             :    statement list.  true is returned if we are in a binding level and
     237                 :             :    a statement list is under construction.  */
     238                 :             : 
     239                 :             : int
     240                 :           0 : m2block_is_building_stmt_list (void)
     241                 :             : {
     242                 :           0 :   ASSERT_CONDITION (current_binding_level != NULL);
     243                 :           0 :   return !vec_safe_is_empty (current_binding_level->m2_statements);
     244                 :             : }
     245                 :             : 
     246                 :             : /* push_statement_list pushes the statement list t onto the
     247                 :             :    current binding level.  */
     248                 :             : 
     249                 :             : tree
     250                 :       96136 : m2block_push_statement_list (tree t)
     251                 :             : {
     252                 :       96136 :   ASSERT_CONDITION (current_binding_level != NULL);
     253                 :       96136 :   vec_safe_push (current_binding_level->m2_statements, t);
     254                 :       96136 :   return t;
     255                 :             : }
     256                 :             : 
     257                 :             : /* pop_statement_list pops and returns a statement list from the
     258                 :             :    current binding level.  */
     259                 :             : 
     260                 :             : tree
     261                 :      213896 : m2block_pop_statement_list (void)
     262                 :             : {
     263                 :      213896 :   ASSERT_CONDITION (current_binding_level != NULL);
     264                 :      213896 :   {
     265                 :      213896 :     tree t = current_binding_level->m2_statements->pop ();
     266                 :             : 
     267                 :      213896 :     return t;
     268                 :             :   }
     269                 :             : }
     270                 :             : 
     271                 :             : /* begin_statement_list starts a tree statement.  It pushes the
     272                 :             :    statement list and returns the list node.  */
     273                 :             : 
     274                 :             : tree
     275                 :      230846 : m2block_begin_statement_list (void)
     276                 :             : {
     277                 :      230846 :   return alloc_stmt_list ();
     278                 :             : }
     279                 :             : 
     280                 :             : /* findLevel returns the binding level associated with fndecl one
     281                 :             :    is created if there is no existing one on head_binding_level.  */
     282                 :             : 
     283                 :             : static struct binding_level *
     284                 :     4391267 : findLevel (tree fndecl)
     285                 :             : {
     286                 :     4391267 :   struct binding_level *b;
     287                 :             : 
     288                 :     4391267 :   if (fndecl == NULL_TREE)
     289                 :     4273495 :     return global_binding_level;
     290                 :             : 
     291                 :      117772 :   b = head_binding_level;
     292                 :      117772 :   while ((b != NULL) && (b->fndecl != fndecl))
     293                 :           0 :     b = b->list;
     294                 :             : 
     295                 :      117772 :   if (b == NULL)
     296                 :             :     {
     297                 :      117772 :       b = newLevel ();
     298                 :      117772 :       b->fndecl = fndecl;
     299                 :      117772 :       b->context = fndecl;
     300                 :      117772 :       b->is_global = false;
     301                 :      117772 :       b->list = head_binding_level;
     302                 :      117772 :       b->next = NULL;
     303                 :             :     }
     304                 :             :   return b;
     305                 :             : }
     306                 :             : 
     307                 :             : /* pushFunctionScope push a binding level.  */
     308                 :             : 
     309                 :             : void
     310                 :     4476761 : m2block_pushFunctionScope (tree fndecl)
     311                 :             : {
     312                 :     4476761 :   struct binding_level *n;
     313                 :     4476761 :   struct binding_level *b;
     314                 :             : 
     315                 :             : #if defined(DEBUGGING)
     316                 :             :   if (fndecl != NULL)
     317                 :             :     printf ("pushFunctionScope\n");
     318                 :             : #endif
     319                 :             : 
     320                 :             :   /* Allow multiple consecutive pushes of the same scope.  */
     321                 :             : 
     322                 :     4476761 :   if (current_binding_level != NULL
     323                 :      119248 :       && (current_binding_level->fndecl == fndecl))
     324                 :             :     {
     325                 :       85494 :       current_binding_level->count++;
     326                 :       85494 :       return;
     327                 :             :     }
     328                 :             : 
     329                 :             :   /* Firstly check to see that fndecl is not already on the binding
     330                 :             :      stack.  */
     331                 :             : 
     332                 :     4425195 :   for (b = current_binding_level; b != NULL; b = b->next)
     333                 :             :     /* Only allowed one instance of the binding on the stack at a time.  */
     334                 :       33928 :     ASSERT_CONDITION (b->fndecl != fndecl);
     335                 :             : 
     336                 :     4391267 :   n = findLevel (fndecl);
     337                 :             : 
     338                 :             :   /* Add this level to the front of the stack.  */
     339                 :     4391267 :   n->next = current_binding_level;
     340                 :     4391267 :   current_binding_level = n;
     341                 :             : }
     342                 :             : 
     343                 :             : /* popFunctionScope - pops a binding level, returning the function
     344                 :             :    associated with the binding level.  */
     345                 :             : 
     346                 :             : tree
     347                 :      203254 : m2block_popFunctionScope (void)
     348                 :             : {
     349                 :      203254 :   tree fndecl = current_binding_level->fndecl;
     350                 :             : 
     351                 :             : #if defined(DEBUGGING)
     352                 :             :   if (fndecl != NULL)
     353                 :             :     printf ("popFunctionScope\n");
     354                 :             : #endif
     355                 :             : 
     356                 :      203254 :   if (current_binding_level->count > 0)
     357                 :             :     {
     358                 :             :       /* Multiple pushes have occurred of the same function scope (and
     359                 :             :          ignored), pop them likewise.  */
     360                 :       85494 :       current_binding_level->count--;
     361                 :       85494 :       return fndecl;
     362                 :             :     }
     363                 :      117760 :   ASSERT_CONDITION (current_binding_level->fndecl
     364                 :      117760 :                     != NULL_TREE); /* Expecting local scope.  */
     365                 :             : 
     366                 :      117760 :   ASSERT_CONDITION (current_binding_level->constants
     367                 :      117760 :                     == NULL_TREE); /* Should not be used.  */
     368                 :      117760 :   ASSERT_CONDITION (current_binding_level->names
     369                 :      117760 :                     == NULL_TREE); /* Should be cleared.  */
     370                 :      117760 :   ASSERT_CONDITION (current_binding_level->decl
     371                 :      117760 :                     == NULL_TREE); /* Should be cleared.  */
     372                 :             : 
     373                 :      117760 :   current_binding_level = current_binding_level->next;
     374                 :      117760 :   return fndecl;
     375                 :             : }
     376                 :             : 
     377                 :             : /* pushGlobalScope push the global scope onto the binding level
     378                 :             :    stack.  There can only ever be one instance of the global binding
     379                 :             :    level on the stack.  */
     380                 :             : 
     381                 :             : void
     382                 :     4273495 : m2block_pushGlobalScope (void)
     383                 :             : {
     384                 :             : #if defined(DEBUGGING)
     385                 :             :   printf ("pushGlobalScope\n");
     386                 :             : #endif
     387                 :     4273495 :   m2block_pushFunctionScope (NULL_TREE);
     388                 :     4273495 : }
     389                 :             : 
     390                 :             : /* popGlobalScope pops the current binding level, it expects this
     391                 :             :    binding level to be the global binding level.  */
     392                 :             : 
     393                 :             : void
     394                 :     4273453 : m2block_popGlobalScope (void)
     395                 :             : {
     396                 :     4273453 :   ASSERT_CONDITION (
     397                 :     4273453 :       current_binding_level->is_global);  /* Expecting global scope.  */
     398                 :     4273453 :   ASSERT_CONDITION (current_binding_level == global_binding_level);
     399                 :             : 
     400                 :     4273453 :   if (current_binding_level->count > 0)
     401                 :             :     {
     402                 :           0 :       current_binding_level->count--;
     403                 :           0 :       return;
     404                 :             :     }
     405                 :             : 
     406                 :     4273453 :   current_binding_level = current_binding_level->next;
     407                 :             : #if defined(DEBUGGING)
     408                 :             :   printf ("popGlobalScope\n");
     409                 :             : #endif
     410                 :             : 
     411                 :     4273453 :   assert_global_names ();
     412                 :             : }
     413                 :             : 
     414                 :             : /* finishFunctionDecl removes declarations from the current binding
     415                 :             :    level and places them inside fndecl.  The current binding level is
     416                 :             :    then able to be destroyed by a call to popFunctionScope.
     417                 :             : 
     418                 :             :    The extra tree nodes associated with fndecl will be created such
     419                 :             :    as BIND_EXPR, BLOCK and the initial STATEMENT_LIST containing the
     420                 :             :    DECL_EXPR is also created.  */
     421                 :             : 
     422                 :             : void
     423                 :      118816 : m2block_finishFunctionDecl (location_t location, tree fndecl)
     424                 :             : {
     425                 :      118816 :   tree context = current_binding_level->context;
     426                 :      118816 :   tree block = DECL_INITIAL (fndecl);
     427                 :      118816 :   tree bind_expr = DECL_SAVED_TREE (fndecl);
     428                 :      118816 :   tree i;
     429                 :             : 
     430                 :      118816 :   if (block == NULL_TREE)
     431                 :             :     {
     432                 :      117772 :       block = make_node (BLOCK);
     433                 :      117772 :       DECL_INITIAL (fndecl) = block;
     434                 :      117772 :       TREE_USED (block) = true;
     435                 :      117772 :       BLOCK_SUBBLOCKS (block) = NULL_TREE;
     436                 :             :     }
     437                 :      118816 :   BLOCK_SUPERCONTEXT (block) = context;
     438                 :             : 
     439                 :      237632 :   BLOCK_VARS (block)
     440                 :      118816 :       = chainon (BLOCK_VARS (block), current_binding_level->names);
     441                 :      118816 :   TREE_USED (fndecl) = true;
     442                 :             : 
     443                 :      118816 :   if (bind_expr == NULL_TREE)
     444                 :             :     {
     445                 :      117772 :       bind_expr
     446                 :      117772 :           = build3 (BIND_EXPR, void_type_node, current_binding_level->names,
     447                 :             :                     current_binding_level->decl, block);
     448                 :      117772 :       DECL_SAVED_TREE (fndecl) = bind_expr;
     449                 :             :     }
     450                 :             :   else
     451                 :             :     {
     452                 :        2088 :       if (!chain_member (current_binding_level->names,
     453                 :        1044 :                          BIND_EXPR_VARS (bind_expr)))
     454                 :             :         {
     455                 :         630 :           BIND_EXPR_VARS (bind_expr) = chainon (BIND_EXPR_VARS (bind_expr),
     456                 :             :                                                 current_binding_level->names);
     457                 :             : 
     458                 :         630 :           if (current_binding_level->names != NULL_TREE)
     459                 :             :             {
     460                 :         198 :               for (i = current_binding_level->names; i != NULL_TREE;
     461                 :         102 :                    i = DECL_CHAIN (i))
     462                 :         102 :                 append_to_statement_list_force (i,
     463                 :             :                                                 &BIND_EXPR_BODY (bind_expr));
     464                 :             : 
     465                 :             :             }
     466                 :             :         }
     467                 :             :     }
     468                 :      118816 :   SET_EXPR_LOCATION (bind_expr, location);
     469                 :             : 
     470                 :      118816 :   current_binding_level->names = NULL_TREE;
     471                 :      118816 :   current_binding_level->decl = NULL_TREE;
     472                 :      118816 : }
     473                 :             : 
     474                 :             : /* finishFunctionCode adds cur_stmt_list to fndecl.  The current
     475                 :             :    binding level is then able to be destroyed by a call to
     476                 :             :    popFunctionScope.  The cur_stmt_list is appended to the
     477                 :             :    STATEMENT_LIST.  */
     478                 :             : 
     479                 :             : void
     480                 :      117760 : m2block_finishFunctionCode (tree fndecl)
     481                 :             : {
     482                 :      117760 :   tree bind_expr;
     483                 :      117760 :   tree block;
     484                 :      117760 :   tree statements = m2block_pop_statement_list ();
     485                 :      117760 :   tree_stmt_iterator i;
     486                 :             : 
     487                 :      117760 :   ASSERT_CONDITION (DECL_SAVED_TREE (fndecl) != NULL_TREE);
     488                 :             : 
     489                 :      117760 :   bind_expr = DECL_SAVED_TREE (fndecl);
     490                 :      117760 :   ASSERT_CONDITION (TREE_CODE (bind_expr) == BIND_EXPR);
     491                 :             : 
     492                 :      117760 :   block = DECL_INITIAL (fndecl);
     493                 :      117760 :   ASSERT_CONDITION (TREE_CODE (block) == BLOCK);
     494                 :             : 
     495                 :      117760 :   if (current_binding_level->names != NULL_TREE)
     496                 :             :     {
     497                 :       76639 :       BIND_EXPR_VARS (bind_expr)
     498                 :       76639 :           = chainon (BIND_EXPR_VARS (bind_expr), current_binding_level->names);
     499                 :       76639 :       current_binding_level->names = NULL_TREE;
     500                 :             :     }
     501                 :      117760 :   if (current_binding_level->labels != NULL_TREE)
     502                 :             :     {
     503                 :             :       tree t;
     504                 :             : 
     505                 :      143643 :       for (t = current_binding_level->labels; t != NULL_TREE;
     506                 :      115011 :            t = TREE_CHAIN (t))
     507                 :             :         {
     508                 :      115011 :           tree l = TREE_VALUE (t);
     509                 :             : 
     510                 :      115011 :           BIND_EXPR_VARS (bind_expr) = chainon (BIND_EXPR_VARS (bind_expr), l);
     511                 :             :         }
     512                 :       28632 :       current_binding_level->labels = NULL_TREE;
     513                 :             :     }
     514                 :             : 
     515                 :      117760 :   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
     516                 :             : 
     517                 :      117760 :   if (current_binding_level->decl != NULL_TREE)
     518                 :      673955 :     for (i = tsi_start (current_binding_level->decl); !tsi_end_p (i);
     519                 :      597316 :          tsi_next (&i))
     520                 :      597316 :       append_to_statement_list_force (*tsi_stmt_ptr (i),
     521                 :             :                                       &BIND_EXPR_BODY (bind_expr));
     522                 :             : 
     523                 :     1414480 :   for (i = tsi_start (statements); !tsi_end_p (i); tsi_next (&i))
     524                 :     1296720 :     append_to_statement_list_force (*tsi_stmt_ptr (i),
     525                 :             :                                     &BIND_EXPR_BODY (bind_expr));
     526                 :             : 
     527                 :      117760 :   current_binding_level->decl = NULL_TREE;
     528                 :      117760 : }
     529                 :             : 
     530                 :             : void
     531                 :       15466 : m2block_finishGlobals (void)
     532                 :             : {
     533                 :       15466 :   tree context = global_binding_level->context;
     534                 :       15466 :   tree block = make_node (BLOCK);
     535                 :       15466 :   tree p = global_binding_level->names;
     536                 :             : 
     537                 :       15466 :   BLOCK_SUBBLOCKS (block) = NULL;
     538                 :       15466 :   TREE_USED (block) = 1;
     539                 :             : 
     540                 :       15466 :   BLOCK_VARS (block) = p;
     541                 :             : 
     542                 :       15466 :   DECL_INITIAL (context) = block;
     543                 :       15466 :   BLOCK_SUPERCONTEXT (block) = context;
     544                 :       15466 : }
     545                 :             : 
     546                 :             : /* pushDecl pushes a declaration onto the current binding level.  */
     547                 :             : 
     548                 :             : tree
     549                 :     8489730 : m2block_pushDecl (tree decl)
     550                 :             : {
     551                 :             :   /* External objects aren't nested, other objects may be.  */
     552                 :             : 
     553                 :     8489730 :   if (decl != current_function_decl)
     554                 :     8489730 :     DECL_CONTEXT (decl) = current_binding_level->context;
     555                 :             : 
     556                 :             :   /* Put the declaration on the list.  The list of declarations is in
     557                 :             :      reverse order.  The list will be reversed later if necessary.  This
     558                 :             :      needs to be this way for compatibility with the back-end.  */
     559                 :             : 
     560                 :     8489730 :   TREE_CHAIN (decl) = current_binding_level->names;
     561                 :     8489730 :   current_binding_level->names = decl;
     562                 :             : 
     563                 :     8489730 :   assert_global_names ();
     564                 :             : 
     565                 :     8489730 :   return decl;
     566                 :             : }
     567                 :             : 
     568                 :             : /* includeDecl pushes a declaration onto the current binding level
     569                 :             :    providing it is not already present.  */
     570                 :             : 
     571                 :             : void
     572                 :           0 : m2block_includeDecl (tree decl)
     573                 :             : {
     574                 :           0 :   tree p = current_binding_level->names;
     575                 :             : 
     576                 :           0 :   while (p != decl && p != NULL)
     577                 :           0 :     p = TREE_CHAIN (p);
     578                 :           0 :   if (p != decl)
     579                 :           0 :     m2block_pushDecl (decl);
     580                 :           0 : }
     581                 :             : 
     582                 :             : /* addDeclExpr adds the DECL_EXPR node t to the statement list
     583                 :             :    current_binding_level->decl.  This allows us to order all
     584                 :             :    declarations at the beginning of the function.  */
     585                 :             : 
     586                 :             : void
     587                 :      679086 : m2block_addDeclExpr (tree t)
     588                 :             : {
     589                 :      679086 :   append_to_statement_list_force (t, &current_binding_level->decl);
     590                 :      679086 : }
     591                 :             : 
     592                 :             : /* RememberType remember the type t in the ggc marked list.  */
     593                 :             : 
     594                 :             : tree
     595                 :     1812113 : m2block_RememberType (tree t)
     596                 :             : {
     597                 :     1812113 :   global_binding_level->types
     598                 :     1812113 :       = tree_cons (NULL_TREE, t, global_binding_level->types);
     599                 :     1812113 :   return t;
     600                 :             : }
     601                 :             : 
     602                 :             : /* global_constant returns t.  It chains t onto the
     603                 :             :    global_binding_level list of constants, if it is not already
     604                 :             :    present.  */
     605                 :             : 
     606                 :             : tree
     607                 :    11509324 : m2block_global_constant (tree t)
     608                 :             : {
     609                 :    11509324 :   tree s;
     610                 :             : 
     611                 :    11509324 :   if (global_binding_level->constants != NULL_TREE)
     612                 :  1755304024 :     for (s = global_binding_level->constants; s != NULL_TREE;
     613                 :  1743811638 :          s = TREE_CHAIN (s))
     614                 :             :       {
     615                 :  1752069840 :         tree c = TREE_VALUE (s);
     616                 :             : 
     617                 :  1752069840 :         if (c == t)
     618                 :             :           return t;
     619                 :             :       }
     620                 :             : 
     621                 :     3251122 :   global_binding_level->constants
     622                 :     3251122 :       = tree_cons (NULL_TREE, t, global_binding_level->constants);
     623                 :     3251122 :   return t;
     624                 :             : }
     625                 :             : 
     626                 :             : /* RememberConstant adds a tree t onto the list of constants to
     627                 :             :    be marked whenever the ggc re-marks all used storage.  Constants
     628                 :             :    live throughout the whole compilation and they can be used by
     629                 :             :    many different functions if necessary.  */
     630                 :             : 
     631                 :             : tree
     632                 :    26488344 : m2block_RememberConstant (tree t)
     633                 :             : {
     634                 :    26488344 :   if ((t != NULL) && (m2tree_IsAConstant (t)))
     635                 :    11441336 :     return m2block_global_constant (t);
     636                 :             :   return t;
     637                 :             : }
     638                 :             : 
     639                 :             : /* DumpGlobalConstants displays all global constants and checks
     640                 :             :    none are poisoned.  */
     641                 :             : 
     642                 :             : tree
     643                 :           0 : m2block_DumpGlobalConstants (void)
     644                 :             : {
     645                 :           0 :   tree s;
     646                 :             : 
     647                 :           0 :   if (global_binding_level->constants != NULL_TREE)
     648                 :           0 :     for (s = global_binding_level->constants; TREE_CHAIN (s);
     649                 :           0 :          s = TREE_CHAIN (s))
     650                 :           0 :       debug_tree (s);
     651                 :           0 :   return NULL_TREE;
     652                 :             : }
     653                 :             : 
     654                 :             : /* RememberInitModuleFunction records tree t in the global
     655                 :             :    binding level.  So that it will not be garbage collected.  In
     656                 :             :    theory the inner modules could be placed inside the
     657                 :             :    current_binding_level I suspect.  */
     658                 :             : 
     659                 :             : tree
     660                 :           0 : m2block_RememberInitModuleFunction (tree t)
     661                 :             : {
     662                 :           0 :   global_binding_level->init_functions
     663                 :           0 :       = tree_cons (NULL_TREE, t, global_binding_level->init_functions);
     664                 :           0 :   return t;
     665                 :             : }
     666                 :             : 
     667                 :             : /* toplevel return true if we are in the global scope.  */
     668                 :             : 
     669                 :             : bool
     670                 :      147450 : m2block_toplevel (void)
     671                 :             : {
     672                 :      147450 :   if (current_binding_level == NULL)
     673                 :             :     return true;
     674                 :      147450 :   if (current_binding_level->fndecl == NULL)
     675                 :      147450 :     return true;
     676                 :             :   return false;
     677                 :             : }
     678                 :             : 
     679                 :             : /* GetErrorNode returns the gcc error_mark_node.  */
     680                 :             : 
     681                 :             : tree
     682                 :    17414536 : m2block_GetErrorNode (void)
     683                 :             : {
     684                 :    17414536 :   return error_mark_node;
     685                 :             : }
     686                 :             : 
     687                 :             : /* GetGlobals returns a list of global variables, functions and constants.  */
     688                 :             : 
     689                 :             : tree
     690                 :           0 : m2block_GetGlobals (void)
     691                 :             : {
     692                 :           0 :   assert_global_names ();
     693                 :           0 :   return global_binding_level->names;
     694                 :             : }
     695                 :             : 
     696                 :             : /* GetGlobalContext - returns the global context tree.  */
     697                 :             : 
     698                 :             : tree
     699                 :      106250 : m2block_GetGlobalContext (void)
     700                 :             : {
     701                 :      106250 :   return global_binding_level->context;
     702                 :             : }
     703                 :             : 
     704                 :             : /* do_add_stmt t is a statement.  Add it to the statement-tree.  */
     705                 :             : 
     706                 :             : static tree
     707                 :     1425946 : do_add_stmt (tree t)
     708                 :             : {
     709                 :     1425946 :   if (current_binding_level != NULL)
     710                 :     1425946 :     append_to_statement_list_force (t, m2block_cur_stmt_list_addr ());
     711                 :     1425946 :   return t;
     712                 :             : }
     713                 :             : 
     714                 :             : /* flush_pending_note flushes a pending_statement note if necessary.  */
     715                 :             : 
     716                 :             : static void
     717                 :      443144 : flush_pending_note (void)
     718                 :             : {
     719                 :      443144 :   if (pending_statement && (M2Options_GetM2g ()))
     720                 :             :     {
     721                 :       55692 :       tree note = build_empty_stmt (pending_location);
     722                 :       55692 :       pending_statement = false;
     723                 :       55692 :       do_add_stmt (note);
     724                 :             :     }
     725                 :      443144 : }
     726                 :             : 
     727                 :             : /* add_stmt t is a statement.  Add it to the statement-tree.  */
     728                 :             : 
     729                 :             : tree
     730                 :     1370254 : m2block_add_stmt (location_t location, tree t)
     731                 :             : {
     732                 :     1370254 :   if ((CAN_HAVE_LOCATION_P (t)) && (!EXPR_HAS_LOCATION (t)))
     733                 :     1089742 :     SET_EXPR_LOCATION (t, location);
     734                 :             : 
     735                 :     1370254 :   if (pending_statement && (pending_location != location))
     736                 :      277437 :     flush_pending_note ();
     737                 :             : 
     738                 :     1370254 :   pending_statement = false;
     739                 :     1370254 :   return do_add_stmt (t);
     740                 :             : }
     741                 :             : 
     742                 :             : /* addStmtNote remember this location represents the start of a
     743                 :             :    Modula-2 statement.  It is flushed if another different location
     744                 :             :    is generated or another tree is given to add_stmt.  */
     745                 :             : 
     746                 :             : void
     747                 :      545793 : m2block_addStmtNote (location_t location)
     748                 :             : {
     749                 :      545793 :   if (pending_statement && (pending_location != location))
     750                 :      165707 :     flush_pending_note ();
     751                 :             : 
     752                 :      545793 :   pending_statement = true;
     753                 :      545793 :   pending_location = location;
     754                 :      545793 : }
     755                 :             : 
     756                 :             : void
     757                 :      168888 : m2block_removeStmtNote (void)
     758                 :             : {
     759                 :      168888 :   pending_statement = false;
     760                 :      168888 : }
     761                 :             : 
     762                 :             : /* init - initialize the data structures in this module.  */
     763                 :             : 
     764                 :             : void
     765                 :       16938 : m2block_init (void)
     766                 :             : {
     767                 :       16938 :   global_binding_level = newLevel ();
     768                 :       16938 :   global_binding_level->context = build_translation_unit_decl (NULL);
     769                 :       16938 :   global_binding_level->is_global = true;
     770                 :       16938 :   current_binding_level = NULL;
     771                 :       16938 : }
     772                 :             : 
     773                 :             : #include "gt-m2-m2block.h"
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.