LCOV - code coverage report
Current view: top level - gcc/m2/gm2-gcc - m2block.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.0 % 273 243
Test Date: 2025-06-28 16:12:38 Functions: 83.8 % 37 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                 :             : /* assert_global_names asserts that the global_binding_level->names
     119                 :             :    can be chained.  */
     120                 :             : 
     121                 :             : static void
     122                 :     9346141 : assert_global_names (void)
     123                 :             : {
     124                 :     9346141 :   tree p = global_binding_level->names;
     125                 :             : 
     126                 :  3102807575 :   while (p)
     127                 :  3093461434 :     p = TREE_CHAIN (p);
     128                 :     9346141 : }
     129                 :             : 
     130                 :             : /* lookupLabel return label tree in current scope, otherwise
     131                 :             :    NULL_TREE.  */
     132                 :             : 
     133                 :             : static tree
     134                 :      212467 : lookupLabel (tree id)
     135                 :             : {
     136                 :      212467 :   tree t;
     137                 :             : 
     138                 :      748738 :   for (t = current_binding_level->labels; t != NULL_TREE; t = TREE_CHAIN (t))
     139                 :             :     {
     140                 :      654383 :       tree l = TREE_VALUE (t);
     141                 :             : 
     142                 :      654383 :       if (id == DECL_NAME (l))
     143                 :             :         return l;
     144                 :             :     }
     145                 :             :   return NULL_TREE;
     146                 :             : }
     147                 :             : 
     148                 :             : /* getLabel return the label name or create a label name in the
     149                 :             :    current scope.  */
     150                 :             : 
     151                 :             : tree
     152                 :      212467 : m2block_getLabel (location_t location, char *name)
     153                 :             : {
     154                 :      212467 :   tree id = get_identifier (name);
     155                 :      212467 :   tree label = lookupLabel (id);
     156                 :             : 
     157                 :      212467 :   if (label == NULL_TREE)
     158                 :             :     {
     159                 :       94355 :       label = build_decl (location, LABEL_DECL, id, void_type_node);
     160                 :       94355 :       current_binding_level->labels
     161                 :       94355 :           = tree_cons (NULL_TREE, label, current_binding_level->labels);
     162                 :             :     }
     163                 :      212467 :   if (DECL_CONTEXT (label) == NULL_TREE)
     164                 :       94367 :     DECL_CONTEXT (label) = current_function_decl;
     165                 :      212467 :   ASSERT ((DECL_CONTEXT (label) == current_function_decl),
     166                 :      212467 :           current_function_decl);
     167                 :             : 
     168                 :      212467 :   DECL_MODE (label) = VOIDmode;
     169                 :      212467 :   return label;
     170                 :             : }
     171                 :             : 
     172                 :             : static void
     173                 :      120198 : init_binding_level (struct binding_level *l)
     174                 :             : {
     175                 :      120198 :   l->fndecl = NULL;
     176                 :      120198 :   l->names = NULL;
     177                 :      120198 :   l->is_global = 0;
     178                 :      120198 :   l->context = NULL;
     179                 :      120198 :   l->next = NULL;
     180                 :      120198 :   l->list = NULL;
     181                 :      120198 :   vec_alloc (l->m2_statements, 1);
     182                 :      120198 :   l->constants = NULL;
     183                 :      120198 :   l->init_functions = NULL;
     184                 :      120198 :   l->types = NULL;
     185                 :      120198 :   l->decl = NULL;
     186                 :      120198 :   l->labels = NULL;
     187                 :      120198 :   l->count = 0;
     188                 :      120198 : }
     189                 :             : 
     190                 :             : static struct binding_level *
     191                 :      120198 : newLevel (void)
     192                 :             : {
     193                 :      120198 :   struct binding_level *newlevel = ggc_alloc<binding_level> ();
     194                 :             : 
     195                 :      120198 :   init_binding_level (newlevel);
     196                 :             : 
     197                 :             :   /* Now we a push_statement_list.  */
     198                 :      120198 :   vec_safe_push (newlevel->m2_statements, m2block_begin_statement_list ());
     199                 :      120198 :   return newlevel;
     200                 :             : }
     201                 :             : 
     202                 :             : tree *
     203                 :     1218310 : m2block_cur_stmt_list_addr (void)
     204                 :             : {
     205                 :     1218310 :   ASSERT_CONDITION (current_binding_level != NULL);
     206                 :     1218310 :   int l = vec_safe_length (current_binding_level->m2_statements) - 1;
     207                 :             : 
     208                 :     1218310 :   return &(*current_binding_level->m2_statements)[l];
     209                 :             : }
     210                 :             : 
     211                 :             : tree
     212                 :           0 : m2block_cur_stmt_list (void)
     213                 :             : {
     214                 :           0 :   tree *t = m2block_cur_stmt_list_addr ();
     215                 :             : 
     216                 :           0 :   return *t;
     217                 :             : }
     218                 :             : 
     219                 :             : /* is_building_stmt_list returns true if we are building a
     220                 :             :    statement list.  true is returned if we are in a binding level and
     221                 :             :    a statement list is under construction.  */
     222                 :             : 
     223                 :             : int
     224                 :           0 : m2block_is_building_stmt_list (void)
     225                 :             : {
     226                 :           0 :   ASSERT_CONDITION (current_binding_level != NULL);
     227                 :           0 :   return !vec_safe_is_empty (current_binding_level->m2_statements);
     228                 :             : }
     229                 :             : 
     230                 :             : /* push_statement_list pushes the statement list t onto the
     231                 :             :    current binding level.  */
     232                 :             : 
     233                 :             : tree
     234                 :       85692 : m2block_push_statement_list (tree t)
     235                 :             : {
     236                 :       85692 :   ASSERT_CONDITION (current_binding_level != NULL);
     237                 :       85692 :   vec_safe_push (current_binding_level->m2_statements, t);
     238                 :       85692 :   return t;
     239                 :             : }
     240                 :             : 
     241                 :             : /* pop_statement_list pops and returns a statement list from the
     242                 :             :    current binding level.  */
     243                 :             : 
     244                 :             : tree
     245                 :      189718 : m2block_pop_statement_list (void)
     246                 :             : {
     247                 :      189718 :   ASSERT_CONDITION (current_binding_level != NULL);
     248                 :      189718 :   {
     249                 :      189718 :     tree t = current_binding_level->m2_statements->pop ();
     250                 :             : 
     251                 :      189718 :     return t;
     252                 :             :   }
     253                 :             : }
     254                 :             : 
     255                 :             : /* begin_statement_list starts a tree statement.  It pushes the
     256                 :             :    statement list and returns the list node.  */
     257                 :             : 
     258                 :             : tree
     259                 :      205890 : m2block_begin_statement_list (void)
     260                 :             : {
     261                 :      205890 :   return alloc_stmt_list ();
     262                 :             : }
     263                 :             : 
     264                 :             : /* findLevel returns the binding level associated with fndecl one
     265                 :             :    is created if there is no existing one on head_binding_level.  */
     266                 :             : 
     267                 :             : static struct binding_level *
     268                 :     2809350 : findLevel (tree fndecl)
     269                 :             : {
     270                 :     2809350 :   struct binding_level *b;
     271                 :             : 
     272                 :     2809350 :   if (fndecl == NULL_TREE)
     273                 :     2705312 :     return global_binding_level;
     274                 :             : 
     275                 :      104038 :   b = head_binding_level;
     276                 :      104038 :   while ((b != NULL) && (b->fndecl != fndecl))
     277                 :           0 :     b = b->list;
     278                 :             : 
     279                 :      104038 :   if (b == NULL)
     280                 :             :     {
     281                 :      104038 :       b = newLevel ();
     282                 :      104038 :       b->fndecl = fndecl;
     283                 :      104038 :       b->context = fndecl;
     284                 :      104038 :       b->is_global = false;
     285                 :      104038 :       b->list = head_binding_level;
     286                 :      104038 :       b->next = NULL;
     287                 :             :     }
     288                 :             :   return b;
     289                 :             : }
     290                 :             : 
     291                 :             : /* pushFunctionScope push a binding level.  */
     292                 :             : 
     293                 :             : void
     294                 :     2882930 : m2block_pushFunctionScope (tree fndecl)
     295                 :             : {
     296                 :     2882930 :   struct binding_level *n;
     297                 :     2882930 :   struct binding_level *b;
     298                 :             : 
     299                 :             : #if defined(DEBUGGING)
     300                 :             :   if (fndecl != NULL)
     301                 :             :     printf ("pushFunctionScope\n");
     302                 :             : #endif
     303                 :             : 
     304                 :             :   /* Allow multiple consecutive pushes of the same scope.  */
     305                 :             : 
     306                 :     2882930 :   if (current_binding_level != NULL
     307                 :      105514 :       && (current_binding_level->fndecl == fndecl))
     308                 :             :     {
     309                 :       73580 :       current_binding_level->count++;
     310                 :       73580 :       return;
     311                 :             :     }
     312                 :             : 
     313                 :             :   /* Firstly check to see that fndecl is not already on the binding
     314                 :             :      stack.  */
     315                 :             : 
     316                 :     2841458 :   for (b = current_binding_level; b != NULL; b = b->next)
     317                 :             :     /* Only allowed one instance of the binding on the stack at a time.  */
     318                 :       32108 :     ASSERT_CONDITION (b->fndecl != fndecl);
     319                 :             : 
     320                 :     2809350 :   n = findLevel (fndecl);
     321                 :             : 
     322                 :             :   /* Add this level to the front of the stack.  */
     323                 :     2809350 :   n->next = current_binding_level;
     324                 :     2809350 :   current_binding_level = n;
     325                 :             : }
     326                 :             : 
     327                 :             : /* popFunctionScope - pops a binding level, returning the function
     328                 :             :    associated with the binding level.  */
     329                 :             : 
     330                 :             : tree
     331                 :      177606 : m2block_popFunctionScope (void)
     332                 :             : {
     333                 :      177606 :   tree fndecl = current_binding_level->fndecl;
     334                 :             : 
     335                 :             : #if defined(DEBUGGING)
     336                 :             :   if (fndecl != NULL)
     337                 :             :     printf ("popFunctionScope\n");
     338                 :             : #endif
     339                 :             : 
     340                 :      177606 :   if (current_binding_level->count > 0)
     341                 :             :     {
     342                 :             :       /* Multiple pushes have occurred of the same function scope (and
     343                 :             :          ignored), pop them likewise.  */
     344                 :       73580 :       current_binding_level->count--;
     345                 :       73580 :       return fndecl;
     346                 :             :     }
     347                 :      104026 :   ASSERT_CONDITION (current_binding_level->fndecl
     348                 :      104026 :                     != NULL_TREE); /* Expecting local scope.  */
     349                 :             : 
     350                 :      104026 :   ASSERT_CONDITION (current_binding_level->constants
     351                 :      104026 :                     == NULL_TREE); /* Should not be used.  */
     352                 :      104026 :   ASSERT_CONDITION (current_binding_level->names
     353                 :      104026 :                     == NULL_TREE); /* Should be cleared.  */
     354                 :      104026 :   ASSERT_CONDITION (current_binding_level->decl
     355                 :      104026 :                     == NULL_TREE); /* Should be cleared.  */
     356                 :             : 
     357                 :      104026 :   current_binding_level = current_binding_level->next;
     358                 :      104026 :   return fndecl;
     359                 :             : }
     360                 :             : 
     361                 :             : /* pushGlobalScope push the global scope onto the binding level
     362                 :             :    stack.  There can only ever be one instance of the global binding
     363                 :             :    level on the stack.  */
     364                 :             : 
     365                 :             : void
     366                 :     2705312 : m2block_pushGlobalScope (void)
     367                 :             : {
     368                 :             : #if defined(DEBUGGING)
     369                 :             :   printf ("pushGlobalScope\n");
     370                 :             : #endif
     371                 :     2705312 :   m2block_pushFunctionScope (NULL_TREE);
     372                 :     2705312 : }
     373                 :             : 
     374                 :             : /* popGlobalScope pops the current binding level, it expects this
     375                 :             :    binding level to be the global binding level.  */
     376                 :             : 
     377                 :             : void
     378                 :     2705270 : m2block_popGlobalScope (void)
     379                 :             : {
     380                 :     2705270 :   ASSERT_CONDITION (
     381                 :     2705270 :       current_binding_level->is_global);  /* Expecting global scope.  */
     382                 :     2705270 :   ASSERT_CONDITION (current_binding_level == global_binding_level);
     383                 :             : 
     384                 :     2705270 :   if (current_binding_level->count > 0)
     385                 :             :     {
     386                 :           0 :       current_binding_level->count--;
     387                 :           0 :       return;
     388                 :             :     }
     389                 :             : 
     390                 :     2705270 :   current_binding_level = current_binding_level->next;
     391                 :             : #if defined(DEBUGGING)
     392                 :             :   printf ("popGlobalScope\n");
     393                 :             : #endif
     394                 :             : 
     395                 :     2705270 :   assert_global_names ();
     396                 :             : }
     397                 :             : 
     398                 :             : /* finishFunctionDecl removes declarations from the current binding
     399                 :             :    level and places them inside fndecl.  The current binding level is
     400                 :             :    then able to be destroyed by a call to popFunctionScope.
     401                 :             : 
     402                 :             :    The extra tree nodes associated with fndecl will be created such
     403                 :             :    as BIND_EXPR, BLOCK and the initial STATEMENT_LIST containing the
     404                 :             :    DECL_EXPR is also created.  */
     405                 :             : 
     406                 :             : void
     407                 :      105082 : m2block_finishFunctionDecl (location_t location, tree fndecl)
     408                 :             : {
     409                 :      105082 :   tree context = current_binding_level->context;
     410                 :      105082 :   tree block = DECL_INITIAL (fndecl);
     411                 :      105082 :   tree bind_expr = DECL_SAVED_TREE (fndecl);
     412                 :      105082 :   tree i;
     413                 :             : 
     414                 :      105082 :   if (block == NULL_TREE)
     415                 :             :     {
     416                 :      104038 :       block = make_node (BLOCK);
     417                 :      104038 :       DECL_INITIAL (fndecl) = block;
     418                 :      104038 :       TREE_USED (block) = true;
     419                 :      104038 :       BLOCK_SUBBLOCKS (block) = NULL_TREE;
     420                 :             :     }
     421                 :      105082 :   BLOCK_SUPERCONTEXT (block) = context;
     422                 :             : 
     423                 :      210164 :   BLOCK_VARS (block)
     424                 :      105082 :       = chainon (BLOCK_VARS (block), current_binding_level->names);
     425                 :      105082 :   TREE_USED (fndecl) = true;
     426                 :             : 
     427                 :      105082 :   if (bind_expr == NULL_TREE)
     428                 :             :     {
     429                 :      104038 :       bind_expr
     430                 :      104038 :           = build3 (BIND_EXPR, void_type_node, current_binding_level->names,
     431                 :             :                     current_binding_level->decl, block);
     432                 :      104038 :       DECL_SAVED_TREE (fndecl) = bind_expr;
     433                 :             :     }
     434                 :             :   else
     435                 :             :     {
     436                 :        2088 :       if (!chain_member (current_binding_level->names,
     437                 :        1044 :                          BIND_EXPR_VARS (bind_expr)))
     438                 :             :         {
     439                 :         630 :           BIND_EXPR_VARS (bind_expr) = chainon (BIND_EXPR_VARS (bind_expr),
     440                 :             :                                                 current_binding_level->names);
     441                 :             : 
     442                 :         630 :           if (current_binding_level->names != NULL_TREE)
     443                 :             :             {
     444                 :         198 :               for (i = current_binding_level->names; i != NULL_TREE;
     445                 :         102 :                    i = DECL_CHAIN (i))
     446                 :         102 :                 append_to_statement_list_force (i,
     447                 :             :                                                 &BIND_EXPR_BODY (bind_expr));
     448                 :             : 
     449                 :             :             }
     450                 :             :         }
     451                 :             :     }
     452                 :      105082 :   SET_EXPR_LOCATION (bind_expr, location);
     453                 :             : 
     454                 :      105082 :   current_binding_level->names = NULL_TREE;
     455                 :      105082 :   current_binding_level->decl = NULL_TREE;
     456                 :      105082 : }
     457                 :             : 
     458                 :             : /* finishFunctionCode adds cur_stmt_list to fndecl.  The current
     459                 :             :    binding level is then able to be destroyed by a call to
     460                 :             :    popFunctionScope.  The cur_stmt_list is appended to the
     461                 :             :    STATEMENT_LIST.  */
     462                 :             : 
     463                 :             : void
     464                 :      104026 : m2block_finishFunctionCode (tree fndecl)
     465                 :             : {
     466                 :      104026 :   tree bind_expr;
     467                 :      104026 :   tree block;
     468                 :      104026 :   tree statements = m2block_pop_statement_list ();
     469                 :      104026 :   tree_stmt_iterator i;
     470                 :             : 
     471                 :      104026 :   ASSERT_CONDITION (DECL_SAVED_TREE (fndecl) != NULL_TREE);
     472                 :             : 
     473                 :      104026 :   bind_expr = DECL_SAVED_TREE (fndecl);
     474                 :      104026 :   ASSERT_CONDITION (TREE_CODE (bind_expr) == BIND_EXPR);
     475                 :             : 
     476                 :      104026 :   block = DECL_INITIAL (fndecl);
     477                 :      104026 :   ASSERT_CONDITION (TREE_CODE (block) == BLOCK);
     478                 :             : 
     479                 :      104026 :   if (current_binding_level->names != NULL_TREE)
     480                 :             :     {
     481                 :       66189 :       BIND_EXPR_VARS (bind_expr)
     482                 :       66189 :           = chainon (BIND_EXPR_VARS (bind_expr), current_binding_level->names);
     483                 :       66189 :       current_binding_level->names = NULL_TREE;
     484                 :             :     }
     485                 :      104026 :   if (current_binding_level->labels != NULL_TREE)
     486                 :             :     {
     487                 :             :       tree t;
     488                 :             : 
     489                 :      118459 :       for (t = current_binding_level->labels; t != NULL_TREE;
     490                 :       94337 :            t = TREE_CHAIN (t))
     491                 :             :         {
     492                 :       94337 :           tree l = TREE_VALUE (t);
     493                 :             : 
     494                 :       94337 :           BIND_EXPR_VARS (bind_expr) = chainon (BIND_EXPR_VARS (bind_expr), l);
     495                 :             :         }
     496                 :       24122 :       current_binding_level->labels = NULL_TREE;
     497                 :             :     }
     498                 :             : 
     499                 :      104026 :   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
     500                 :             : 
     501                 :      104026 :   if (current_binding_level->decl != NULL_TREE)
     502                 :      557763 :     for (i = tsi_start (current_binding_level->decl); !tsi_end_p (i);
     503                 :      491574 :          tsi_next (&i))
     504                 :      491574 :       append_to_statement_list_force (*tsi_stmt_ptr (i),
     505                 :             :                                       &BIND_EXPR_BODY (bind_expr));
     506                 :             : 
     507                 :     1204592 :   for (i = tsi_start (statements); !tsi_end_p (i); tsi_next (&i))
     508                 :     1100566 :     append_to_statement_list_force (*tsi_stmt_ptr (i),
     509                 :             :                                     &BIND_EXPR_BODY (bind_expr));
     510                 :             : 
     511                 :      104026 :   current_binding_level->decl = NULL_TREE;
     512                 :      104026 : }
     513                 :             : 
     514                 :             : void
     515                 :       14714 : m2block_finishGlobals (void)
     516                 :             : {
     517                 :       14714 :   tree context = global_binding_level->context;
     518                 :       14714 :   tree block = make_node (BLOCK);
     519                 :       14714 :   tree p = global_binding_level->names;
     520                 :             : 
     521                 :       14714 :   BLOCK_SUBBLOCKS (block) = NULL;
     522                 :       14714 :   TREE_USED (block) = 1;
     523                 :             : 
     524                 :       14714 :   BLOCK_VARS (block) = p;
     525                 :             : 
     526                 :       14714 :   DECL_INITIAL (context) = block;
     527                 :       14714 :   BLOCK_SUPERCONTEXT (block) = context;
     528                 :       14714 : }
     529                 :             : 
     530                 :             : /* pushDecl pushes a declaration onto the current binding level.  */
     531                 :             : 
     532                 :             : tree
     533                 :     6640871 : m2block_pushDecl (tree decl)
     534                 :             : {
     535                 :             :   /* External objects aren't nested, other objects may be.  */
     536                 :             : 
     537                 :     6640871 :   if (decl != current_function_decl)
     538                 :     6640871 :     DECL_CONTEXT (decl) = current_binding_level->context;
     539                 :             : 
     540                 :             :   /* Put the declaration on the list.  The list of declarations is in
     541                 :             :      reverse order.  The list will be reversed later if necessary.  This
     542                 :             :      needs to be this way for compatibility with the back-end.  */
     543                 :             : 
     544                 :     6640871 :   TREE_CHAIN (decl) = current_binding_level->names;
     545                 :     6640871 :   current_binding_level->names = decl;
     546                 :             : 
     547                 :     6640871 :   assert_global_names ();
     548                 :             : 
     549                 :     6640871 :   return decl;
     550                 :             : }
     551                 :             : 
     552                 :             : /* includeDecl pushes a declaration onto the current binding level
     553                 :             :    providing it is not already present.  */
     554                 :             : 
     555                 :             : void
     556                 :           0 : m2block_includeDecl (tree decl)
     557                 :             : {
     558                 :           0 :   tree p = current_binding_level->names;
     559                 :             : 
     560                 :           0 :   while (p != decl && p != NULL)
     561                 :           0 :     p = TREE_CHAIN (p);
     562                 :           0 :   if (p != decl)
     563                 :           0 :     m2block_pushDecl (decl);
     564                 :           0 : }
     565                 :             : 
     566                 :             : /* addDeclExpr adds the DECL_EXPR node t to the statement list
     567                 :             :    current_binding_level->decl.  This allows us to order all
     568                 :             :    declarations at the beginning of the function.  */
     569                 :             : 
     570                 :             : void
     571                 :      568950 : m2block_addDeclExpr (tree t)
     572                 :             : {
     573                 :      568950 :   append_to_statement_list_force (t, &current_binding_level->decl);
     574                 :      568950 : }
     575                 :             : 
     576                 :             : /* RememberType remember the type t in the ggc marked list.  */
     577                 :             : 
     578                 :             : tree
     579                 :     1208171 : m2block_RememberType (tree t)
     580                 :             : {
     581                 :     1208171 :   global_binding_level->types
     582                 :     1208171 :       = tree_cons (NULL_TREE, t, global_binding_level->types);
     583                 :     1208171 :   return t;
     584                 :             : }
     585                 :             : 
     586                 :             : /* global_constant returns t.  It chains t onto the
     587                 :             :    global_binding_level list of constants, if it is not already
     588                 :             :    present.  */
     589                 :             : 
     590                 :             : tree
     591                 :     9665178 : m2block_global_constant (tree t)
     592                 :             : {
     593                 :     9665178 :   tree s;
     594                 :             : 
     595                 :     9665178 :   if (global_binding_level->constants != NULL_TREE)
     596                 :  1229791283 :     for (s = global_binding_level->constants; s != NULL_TREE;
     597                 :  1220142265 :          s = TREE_CHAIN (s))
     598                 :             :       {
     599                 :  1226773230 :         tree c = TREE_VALUE (s);
     600                 :             : 
     601                 :  1226773230 :         if (c == t)
     602                 :             :           return t;
     603                 :             :       }
     604                 :             : 
     605                 :     3034213 :   global_binding_level->constants
     606                 :     3034213 :       = tree_cons (NULL_TREE, t, global_binding_level->constants);
     607                 :     3034213 :   return t;
     608                 :             : }
     609                 :             : 
     610                 :             : /* RememberConstant adds a tree t onto the list of constants to
     611                 :             :    be marked whenever the ggc re-marks all used storage.  Constants
     612                 :             :    live throughout the whole compilation and they can be used by
     613                 :             :    many different functions if necessary.  */
     614                 :             : 
     615                 :             : tree
     616                 :    19515178 : m2block_RememberConstant (tree t)
     617                 :             : {
     618                 :    19515178 :   if ((t != NULL) && (m2tree_IsAConstant (t)))
     619                 :     9614996 :     return m2block_global_constant (t);
     620                 :             :   return t;
     621                 :             : }
     622                 :             : 
     623                 :             : /* DumpGlobalConstants displays all global constants and checks
     624                 :             :    none are poisoned.  */
     625                 :             : 
     626                 :             : tree
     627                 :           0 : m2block_DumpGlobalConstants (void)
     628                 :             : {
     629                 :           0 :   tree s;
     630                 :             : 
     631                 :           0 :   if (global_binding_level->constants != NULL_TREE)
     632                 :           0 :     for (s = global_binding_level->constants; TREE_CHAIN (s);
     633                 :           0 :          s = TREE_CHAIN (s))
     634                 :           0 :       debug_tree (s);
     635                 :           0 :   return NULL_TREE;
     636                 :             : }
     637                 :             : 
     638                 :             : /* RememberInitModuleFunction records tree t in the global
     639                 :             :    binding level.  So that it will not be garbage collected.  In
     640                 :             :    theory the inner modules could be placed inside the
     641                 :             :    current_binding_level I suspect.  */
     642                 :             : 
     643                 :             : tree
     644                 :           0 : m2block_RememberInitModuleFunction (tree t)
     645                 :             : {
     646                 :           0 :   global_binding_level->init_functions
     647                 :           0 :       = tree_cons (NULL_TREE, t, global_binding_level->init_functions);
     648                 :           0 :   return t;
     649                 :             : }
     650                 :             : 
     651                 :             : /* toplevel return true if we are in the global scope.  */
     652                 :             : 
     653                 :             : bool
     654                 :      109221 : m2block_toplevel (void)
     655                 :             : {
     656                 :      109221 :   if (current_binding_level == NULL)
     657                 :             :     return true;
     658                 :      109221 :   if (current_binding_level->fndecl == NULL)
     659                 :      109197 :     return true;
     660                 :             :   return false;
     661                 :             : }
     662                 :             : 
     663                 :             : /* GetErrorNode returns the gcc error_mark_node.  */
     664                 :             : 
     665                 :             : tree
     666                 :    11628900 : m2block_GetErrorNode (void)
     667                 :             : {
     668                 :    11628900 :   return error_mark_node;
     669                 :             : }
     670                 :             : 
     671                 :             : /* GetGlobals returns a list of global variables, functions and constants.  */
     672                 :             : 
     673                 :             : tree
     674                 :           0 : m2block_GetGlobals (void)
     675                 :             : {
     676                 :           0 :   assert_global_names ();
     677                 :           0 :   return global_binding_level->names;
     678                 :             : }
     679                 :             : 
     680                 :             : /* GetGlobalContext - returns the global context tree.  */
     681                 :             : 
     682                 :             : tree
     683                 :      104194 : m2block_GetGlobalContext (void)
     684                 :             : {
     685                 :      104194 :   return global_binding_level->context;
     686                 :             : }
     687                 :             : 
     688                 :             : /* do_add_stmt t is a statement.  Add it to the statement-tree.  */
     689                 :             : 
     690                 :             : static tree
     691                 :     1218310 : do_add_stmt (tree t)
     692                 :             : {
     693                 :     1218310 :   if (current_binding_level != NULL)
     694                 :     1218310 :     append_to_statement_list_force (t, m2block_cur_stmt_list_addr ());
     695                 :     1218310 :   return t;
     696                 :             : }
     697                 :             : 
     698                 :             : /* flush_pending_note flushes a pending_statement note if necessary.  */
     699                 :             : 
     700                 :             : static void
     701                 :      357428 : flush_pending_note (void)
     702                 :             : {
     703                 :      357428 :   if (pending_statement && (M2Options_GetM2g ()))
     704                 :             :     {
     705                 :       53012 :       tree note = build_empty_stmt (pending_location);
     706                 :       53012 :       pending_statement = false;
     707                 :       53012 :       do_add_stmt (note);
     708                 :             :     }
     709                 :      357428 : }
     710                 :             : 
     711                 :             : /* add_stmt t is a statement.  Add it to the statement-tree.  */
     712                 :             : 
     713                 :             : tree
     714                 :     1165298 : m2block_add_stmt (location_t location, tree t)
     715                 :             : {
     716                 :     1165298 :   if ((CAN_HAVE_LOCATION_P (t)) && (!EXPR_HAS_LOCATION (t)))
     717                 :      930702 :     SET_EXPR_LOCATION (t, location);
     718                 :             : 
     719                 :     1165298 :   if (pending_statement && (pending_location != location))
     720                 :      225647 :     flush_pending_note ();
     721                 :             : 
     722                 :     1165298 :   pending_statement = false;
     723                 :     1165298 :   return do_add_stmt (t);
     724                 :             : }
     725                 :             : 
     726                 :             : /* addStmtNote remember this location represents the start of a
     727                 :             :    Modula-2 statement.  It is flushed if another different location
     728                 :             :    is generated or another tree is given to add_stmt.  */
     729                 :             : 
     730                 :             : void
     731                 :      445879 : m2block_addStmtNote (location_t location)
     732                 :             : {
     733                 :      445879 :   if (pending_statement && (pending_location != location))
     734                 :      131781 :     flush_pending_note ();
     735                 :             : 
     736                 :      445879 :   pending_statement = true;
     737                 :      445879 :   pending_location = location;
     738                 :      445879 : }
     739                 :             : 
     740                 :             : void
     741                 :      145060 : m2block_removeStmtNote (void)
     742                 :             : {
     743                 :      145060 :   pending_statement = false;
     744                 :      145060 : }
     745                 :             : 
     746                 :             : /* init - initialize the data structures in this module.  */
     747                 :             : 
     748                 :             : void
     749                 :       16160 : m2block_init (void)
     750                 :             : {
     751                 :       16160 :   global_binding_level = newLevel ();
     752                 :       16160 :   global_binding_level->context = build_translation_unit_decl (NULL);
     753                 :       16160 :   global_binding_level->is_global = true;
     754                 :       16160 :   current_binding_level = NULL;
     755                 :       16160 : }
     756                 :             : 
     757                 :             : #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.