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