LCOV - code coverage report
Current view: top level - gcc/m2/gm2-gcc - m2block.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.1 % 274 244
Test Date: 2024-04-13 14:00:49 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-2024 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                 :     7743720 : assert_global_names (void)
     122                 :             : {
     123                 :     7743720 :   tree p = global_binding_level->names;
     124                 :             : 
     125                 :  2602798927 :   while (p)
     126                 :  2595055207 :     p = TREE_CHAIN (p);
     127                 :     7743720 : }
     128                 :             : 
     129                 :             : /* lookupLabel return label tree in current scope, otherwise
     130                 :             :    NULL_TREE.  */
     131                 :             : 
     132                 :             : static tree
     133                 :      183253 : lookupLabel (tree id)
     134                 :             : {
     135                 :      183253 :   tree t;
     136                 :             : 
     137                 :      659300 :   for (t = current_binding_level->labels; t != NULL_TREE; t = TREE_CHAIN (t))
     138                 :             :     {
     139                 :      578080 :       tree l = TREE_VALUE (t);
     140                 :             : 
     141                 :      578080 :       if (id == DECL_NAME (l))
     142                 :      102033 :         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                 :      183253 : m2block_getLabel (location_t location, char *name)
     152                 :             : {
     153                 :      183253 :   tree id = get_identifier (name);
     154                 :      183253 :   tree label = lookupLabel (id);
     155                 :             : 
     156                 :      183253 :   if (label == NULL_TREE)
     157                 :             :     {
     158                 :       81220 :       label = build_decl (location, LABEL_DECL, id, void_type_node);
     159                 :       81220 :       current_binding_level->labels
     160                 :       81220 :           = tree_cons (NULL_TREE, label, current_binding_level->labels);
     161                 :             :     }
     162                 :      183253 :   if (DECL_CONTEXT (label) == NULL_TREE)
     163                 :       81220 :     DECL_CONTEXT (label) = current_function_decl;
     164                 :      183253 :   ASSERT ((DECL_CONTEXT (label) == current_function_decl),
     165                 :      183253 :           current_function_decl);
     166                 :             : 
     167                 :      183253 :   DECL_MODE (label) = VOIDmode;
     168                 :      183253 :   return label;
     169                 :             : }
     170                 :             : 
     171                 :             : static void
     172                 :      101692 : init_binding_level (struct binding_level *l)
     173                 :             : {
     174                 :      101692 :   l->fndecl = NULL;
     175                 :      101692 :   l->names = NULL;
     176                 :      101692 :   l->is_global = 0;
     177                 :      101692 :   l->context = NULL;
     178                 :      101692 :   l->next = NULL;
     179                 :      101692 :   l->list = NULL;
     180                 :      101692 :   vec_alloc (l->m2_statements, 1);
     181                 :      101692 :   l->constants = NULL;
     182                 :      101692 :   l->init_functions = NULL;
     183                 :      101692 :   l->types = NULL;
     184                 :      101692 :   l->decl = NULL;
     185                 :      101692 :   l->labels = NULL;
     186                 :      101692 :   l->count = 0;
     187                 :      101692 : }
     188                 :             : 
     189                 :             : static struct binding_level *
     190                 :      101692 : newLevel (void)
     191                 :             : {
     192                 :      101692 :   struct binding_level *newlevel = ggc_alloc<binding_level> ();
     193                 :             : 
     194                 :      101692 :   init_binding_level (newlevel);
     195                 :             : 
     196                 :             :   /* Now we a push_statement_list.  */
     197                 :      101692 :   vec_safe_push (newlevel->m2_statements, m2block_begin_statement_list ());
     198                 :      101692 :   return newlevel;
     199                 :             : }
     200                 :             : 
     201                 :             : tree *
     202                 :     1075235 : m2block_cur_stmt_list_addr (void)
     203                 :             : {
     204                 :     1075235 :   ASSERT_CONDITION (current_binding_level != NULL);
     205                 :     1075235 :   int l = vec_safe_length (current_binding_level->m2_statements) - 1;
     206                 :             : 
     207                 :     1075235 :   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                 :       74329 : m2block_push_statement_list (tree t)
     234                 :             : {
     235                 :       74329 :   ASSERT_CONDITION (current_binding_level != NULL);
     236                 :       74329 :   vec_safe_push (current_binding_level->m2_statements, t);
     237                 :       74329 :   return t;
     238                 :             : }
     239                 :             : 
     240                 :             : /* pop_statement_list pops and returns a statement list from the
     241                 :             :    current binding level.  */
     242                 :             : 
     243                 :             : tree
     244                 :      163052 : m2block_pop_statement_list (void)
     245                 :             : {
     246                 :      163052 :   ASSERT_CONDITION (current_binding_level != NULL);
     247                 :      163052 :   {
     248                 :      163052 :     tree t = current_binding_level->m2_statements->pop ();
     249                 :             : 
     250                 :      163052 :     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                 :      176021 : m2block_begin_statement_list (void)
     259                 :             : {
     260                 :      176021 :   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                 :     2382814 : findLevel (tree fndecl)
     268                 :             : {
     269                 :     2382814 :   struct binding_level *b;
     270                 :             : 
     271                 :     2382814 :   if (fndecl == NULL_TREE)
     272                 :     2294085 :     return global_binding_level;
     273                 :             : 
     274                 :       88729 :   b = head_binding_level;
     275                 :       88729 :   while ((b != NULL) && (b->fndecl != fndecl))
     276                 :           0 :     b = b->list;
     277                 :             : 
     278                 :       88729 :   if (b == NULL)
     279                 :             :     {
     280                 :       88729 :       b = newLevel ();
     281                 :       88729 :       b->fndecl = fndecl;
     282                 :       88729 :       b->context = fndecl;
     283                 :       88729 :       b->is_global = false;
     284                 :       88729 :       b->list = head_binding_level;
     285                 :       88729 :       b->next = NULL;
     286                 :             :     }
     287                 :             :   return b;
     288                 :             : }
     289                 :             : 
     290                 :             : /* pushFunctionScope push a binding level.  */
     291                 :             : 
     292                 :             : void
     293                 :     2446329 : m2block_pushFunctionScope (tree fndecl)
     294                 :             : {
     295                 :     2446329 :   struct binding_level *n;
     296                 :     2446329 :   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                 :     2446329 :   if (current_binding_level != NULL
     306                 :       90205 :       && (current_binding_level->fndecl == fndecl))
     307                 :             :     {
     308                 :       63515 :       current_binding_level->count++;
     309                 :       63515 :       return;
     310                 :             :     }
     311                 :             : 
     312                 :             :   /* Firstly check to see that fndecl is not already on the binding
     313                 :             :      stack.  */
     314                 :             : 
     315                 :     2409678 :   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                 :       26864 :     ASSERT_CONDITION (b->fndecl != fndecl);
     318                 :             : 
     319                 :     2382814 :   n = findLevel (fndecl);
     320                 :             : 
     321                 :             :   /* Add this level to the front of the stack.  */
     322                 :     2382814 :   n->next = current_binding_level;
     323                 :     2382814 :   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                 :      152238 : m2block_popFunctionScope (void)
     331                 :             : {
     332                 :      152238 :   tree fndecl = current_binding_level->fndecl;
     333                 :             : 
     334                 :             : #if defined(DEBUGGING)
     335                 :             :   if (fndecl != NULL)
     336                 :             :     printf ("popFunctionScope\n");
     337                 :             : #endif
     338                 :             : 
     339                 :      152238 :   if (current_binding_level->count > 0)
     340                 :             :     {
     341                 :             :       /* Multiple pushes have occurred of the same function scope (and
     342                 :             :          ignored), pop them likewise.  */
     343                 :       63515 :       current_binding_level->count--;
     344                 :       63515 :       return fndecl;
     345                 :             :     }
     346                 :       88723 :   ASSERT_CONDITION (current_binding_level->fndecl
     347                 :       88723 :                     != NULL_TREE); /* Expecting local scope.  */
     348                 :             : 
     349                 :       88723 :   ASSERT_CONDITION (current_binding_level->constants
     350                 :       88723 :                     == NULL_TREE); /* Should not be used.  */
     351                 :       88723 :   ASSERT_CONDITION (current_binding_level->names
     352                 :       88723 :                     == NULL_TREE); /* Should be cleared.  */
     353                 :       88723 :   ASSERT_CONDITION (current_binding_level->decl
     354                 :       88723 :                     == NULL_TREE); /* Should be cleared.  */
     355                 :             : 
     356                 :       88723 :   current_binding_level = current_binding_level->next;
     357                 :       88723 :   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                 :     2294085 : m2block_pushGlobalScope (void)
     366                 :             : {
     367                 :             : #if defined(DEBUGGING)
     368                 :             :   printf ("pushGlobalScope\n");
     369                 :             : #endif
     370                 :     2294085 :   m2block_pushFunctionScope (NULL_TREE);
     371                 :     2294085 : }
     372                 :             : 
     373                 :             : /* popGlobalScope pops the current binding level, it expects this
     374                 :             :    binding level to be the global binding level.  */
     375                 :             : 
     376                 :             : void
     377                 :     2294025 : m2block_popGlobalScope (void)
     378                 :             : {
     379                 :     2294025 :   ASSERT_CONDITION (
     380                 :     2294025 :       current_binding_level->is_global);  /* Expecting global scope.  */
     381                 :     2294025 :   ASSERT_CONDITION (current_binding_level == global_binding_level);
     382                 :             : 
     383                 :     2294025 :   if (current_binding_level->count > 0)
     384                 :             :     {
     385                 :           0 :       current_binding_level->count--;
     386                 :           0 :       return;
     387                 :             :     }
     388                 :             : 
     389                 :     2294025 :   current_binding_level = current_binding_level->next;
     390                 :             : #if defined(DEBUGGING)
     391                 :             :   printf ("popGlobalScope\n");
     392                 :             : #endif
     393                 :             : 
     394                 :     2294025 :   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                 :       89767 : m2block_finishFunctionDecl (location_t location, tree fndecl)
     407                 :             : {
     408                 :       89767 :   tree context = current_binding_level->context;
     409                 :       89767 :   tree block = DECL_INITIAL (fndecl);
     410                 :       89767 :   tree bind_expr = DECL_SAVED_TREE (fndecl);
     411                 :       89767 :   tree i;
     412                 :             : 
     413                 :       89767 :   if (block == NULL_TREE)
     414                 :             :     {
     415                 :       88723 :       block = make_node (BLOCK);
     416                 :       88723 :       DECL_INITIAL (fndecl) = block;
     417                 :       88723 :       TREE_USED (block) = true;
     418                 :       88723 :       BLOCK_SUBBLOCKS (block) = NULL_TREE;
     419                 :             :     }
     420                 :       89767 :   BLOCK_SUPERCONTEXT (block) = context;
     421                 :             : 
     422                 :      179534 :   BLOCK_VARS (block)
     423                 :       89767 :       = chainon (BLOCK_VARS (block), current_binding_level->names);
     424                 :       89767 :   TREE_USED (fndecl) = true;
     425                 :             : 
     426                 :       89767 :   if (bind_expr == NULL_TREE)
     427                 :             :     {
     428                 :       88723 :       bind_expr
     429                 :       88723 :           = build3 (BIND_EXPR, void_type_node, current_binding_level->names,
     430                 :             :                     current_binding_level->decl, block);
     431                 :       88723 :       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                 :       89767 :   SET_EXPR_LOCATION (bind_expr, location);
     452                 :             : 
     453                 :       89767 :   current_binding_level->names = NULL_TREE;
     454                 :       89767 :   current_binding_level->decl = NULL_TREE;
     455                 :       89767 : }
     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                 :       88723 : m2block_finishFunctionCode (tree fndecl)
     464                 :             : {
     465                 :       88723 :   tree bind_expr;
     466                 :       88723 :   tree block;
     467                 :       88723 :   tree statements = m2block_pop_statement_list ();
     468                 :       88723 :   tree_stmt_iterator i;
     469                 :             : 
     470                 :       88723 :   ASSERT_CONDITION (DECL_SAVED_TREE (fndecl) != NULL_TREE);
     471                 :             : 
     472                 :       88723 :   bind_expr = DECL_SAVED_TREE (fndecl);
     473                 :       88723 :   ASSERT_CONDITION (TREE_CODE (bind_expr) == BIND_EXPR);
     474                 :             : 
     475                 :       88723 :   block = DECL_INITIAL (fndecl);
     476                 :       88723 :   ASSERT_CONDITION (TREE_CODE (block) == BLOCK);
     477                 :             : 
     478                 :       88723 :   if (current_binding_level->names != NULL_TREE)
     479                 :             :     {
     480                 :       56604 :       BIND_EXPR_VARS (bind_expr)
     481                 :       56604 :           = chainon (BIND_EXPR_VARS (bind_expr), current_binding_level->names);
     482                 :       56604 :       current_binding_level->names = NULL_TREE;
     483                 :             :     }
     484                 :       88723 :   if (current_binding_level->labels != NULL_TREE)
     485                 :             :     {
     486                 :             :       tree t;
     487                 :             : 
     488                 :      102096 :       for (t = current_binding_level->labels; t != NULL_TREE;
     489                 :       81220 :            t = TREE_CHAIN (t))
     490                 :             :         {
     491                 :       81220 :           tree l = TREE_VALUE (t);
     492                 :             : 
     493                 :       81220 :           BIND_EXPR_VARS (bind_expr) = chainon (BIND_EXPR_VARS (bind_expr), l);
     494                 :             :         }
     495                 :       20876 :       current_binding_level->labels = NULL_TREE;
     496                 :             :     }
     497                 :             : 
     498                 :       88723 :   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
     499                 :             : 
     500                 :       88723 :   if (current_binding_level->decl != NULL_TREE)
     501                 :      484220 :     for (i = tsi_start (current_binding_level->decl); !tsi_end_p (i);
     502                 :      427616 :          tsi_next (&i))
     503                 :      427616 :       append_to_statement_list_force (*tsi_stmt_ptr (i),
     504                 :             :                                       &BIND_EXPR_BODY (bind_expr));
     505                 :             : 
     506                 :     1060231 :   for (i = tsi_start (statements); !tsi_end_p (i); tsi_next (&i))
     507                 :      971508 :     append_to_statement_list_force (*tsi_stmt_ptr (i),
     508                 :             :                                     &BIND_EXPR_BODY (bind_expr));
     509                 :             : 
     510                 :       88723 :   current_binding_level->decl = NULL_TREE;
     511                 :       88723 : }
     512                 :             : 
     513                 :             : void
     514                 :       12143 : m2block_finishGlobals (void)
     515                 :             : {
     516                 :       12143 :   tree context = global_binding_level->context;
     517                 :       12143 :   tree block = make_node (BLOCK);
     518                 :       12143 :   tree p = global_binding_level->names;
     519                 :             : 
     520                 :       12143 :   BLOCK_SUBBLOCKS (block) = NULL;
     521                 :       12143 :   TREE_USED (block) = 1;
     522                 :             : 
     523                 :       12143 :   BLOCK_VARS (block) = p;
     524                 :             : 
     525                 :       12143 :   DECL_INITIAL (context) = block;
     526                 :       12143 :   BLOCK_SUPERCONTEXT (block) = context;
     527                 :       12143 : }
     528                 :             : 
     529                 :             : /* pushDecl pushes a declaration onto the current binding level.  */
     530                 :             : 
     531                 :             : tree
     532                 :     5449695 : m2block_pushDecl (tree decl)
     533                 :             : {
     534                 :             :   /* External objects aren't nested, other objects may be.  */
     535                 :             : 
     536                 :     5449695 :   if (decl != current_function_decl)
     537                 :     5449695 :     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                 :     5449695 :   TREE_CHAIN (decl) = current_binding_level->names;
     544                 :     5449695 :   current_binding_level->names = decl;
     545                 :             : 
     546                 :     5449695 :   assert_global_names ();
     547                 :             : 
     548                 :     5449695 :   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                 :      501426 : m2block_addDeclExpr (tree t)
     571                 :             : {
     572                 :      501426 :   append_to_statement_list_force (t, &current_binding_level->decl);
     573                 :      501426 : }
     574                 :             : 
     575                 :             : /* RememberType remember the type t in the ggc marked list.  */
     576                 :             : 
     577                 :             : tree
     578                 :     1066322 : m2block_RememberType (tree t)
     579                 :             : {
     580                 :     1066322 :   global_binding_level->types
     581                 :     1066322 :       = tree_cons (NULL_TREE, t, global_binding_level->types);
     582                 :     1066322 :   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                 :     7879702 : m2block_global_constant (tree t)
     591                 :             : {
     592                 :     7879702 :   tree s;
     593                 :             : 
     594                 :     7879702 :   if (global_binding_level->constants != NULL_TREE)
     595                 :   921982571 :     for (s = global_binding_level->constants; s != NULL_TREE;
     596                 :   914115832 :          s = TREE_CHAIN (s))
     597                 :             :       {
     598                 :   919505189 :         tree c = TREE_VALUE (s);
     599                 :             : 
     600                 :   919505189 :         if (c == t)
     601                 :             :           return t;
     602                 :             :       }
     603                 :             : 
     604                 :     2490345 :   global_binding_level->constants
     605                 :     2490345 :       = tree_cons (NULL_TREE, t, global_binding_level->constants);
     606                 :     2490345 :   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                 :    16148897 : m2block_RememberConstant (tree t)
     616                 :             : {
     617                 :    16148897 :   if ((t != NULL) && (m2tree_IsAConstant (t)))
     618                 :     7829648 :     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                 :       96982 : m2block_toplevel (void)
     654                 :             : {
     655                 :       96982 :   if (current_binding_level == NULL)
     656                 :             :     return true;
     657                 :       96982 :   if (current_binding_level->fndecl == NULL)
     658                 :       96958 :     return true;
     659                 :             :   return false;
     660                 :             : }
     661                 :             : 
     662                 :             : /* GetErrorNode returns the gcc error_mark_node.  */
     663                 :             : 
     664                 :             : tree
     665                 :     9839435 : m2block_GetErrorNode (void)
     666                 :             : {
     667                 :     9839435 :   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                 :       99588 : m2block_GetGlobalContext (void)
     684                 :             : {
     685                 :       99588 :   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                 :     1075235 : do_add_stmt (tree t)
     692                 :             : {
     693                 :     1075235 :   if (current_binding_level != NULL)
     694                 :     1075235 :     append_to_statement_list_force (t, m2block_cur_stmt_list_addr ());
     695                 :     1075235 :   return t;
     696                 :             : }
     697                 :             : 
     698                 :             : /* flush_pending_note - flushes a pending_statement note if
     699                 :             :    necessary.  */
     700                 :             : 
     701                 :             : static void
     702                 :      325913 : flush_pending_note (void)
     703                 :             : {
     704                 :      325913 :   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_INPUT_P (note) = false;
     715                 :             :       ASM_VOLATILE_P (note) = false;
     716                 :             : #else
     717                 :       55396 :       tree note = build_empty_stmt (pending_location);
     718                 :             : #endif
     719                 :       55396 :       pending_statement = false;
     720                 :       55396 :       do_add_stmt (note);
     721                 :             :     }
     722                 :      325913 : }
     723                 :             : 
     724                 :             : /* add_stmt t is a statement.  Add it to the statement-tree.  */
     725                 :             : 
     726                 :             : tree
     727                 :     1019839 : m2block_add_stmt (location_t location, tree t)
     728                 :             : {
     729                 :     1019839 :   if ((CAN_HAVE_LOCATION_P (t)) && (!EXPR_HAS_LOCATION (t)))
     730                 :      816261 :     SET_EXPR_LOCATION (t, location);
     731                 :             : 
     732                 :     1019839 :   if (pending_statement && (pending_location != location))
     733                 :      211641 :     flush_pending_note ();
     734                 :             : 
     735                 :     1019839 :   pending_statement = false;
     736                 :     1019839 :   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                 :      381219 : m2block_addStmtNote (location_t location)
     745                 :             : {
     746                 :      381219 :   if (pending_statement && (pending_location != location))
     747                 :      114272 :     flush_pending_note ();
     748                 :             : 
     749                 :      381219 :   pending_statement = true;
     750                 :      381219 :   pending_location = location;
     751                 :      381219 : }
     752                 :             : 
     753                 :             : void
     754                 :      124942 : m2block_removeStmtNote (void)
     755                 :             : {
     756                 :      124942 :   pending_statement = false;
     757                 :      124942 : }
     758                 :             : 
     759                 :             : /* init - initialize the data structures in this module.  */
     760                 :             : 
     761                 :             : void
     762                 :       12963 : m2block_init (void)
     763                 :             : {
     764                 :       12963 :   global_binding_level = newLevel ();
     765                 :       12963 :   global_binding_level->context = build_translation_unit_decl (NULL);
     766                 :       12963 :   global_binding_level->is_global = true;
     767                 :       12963 :   current_binding_level = NULL;
     768                 :       12963 : }
     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.