1 /* m2block.cc provides an interface to maintaining block structures.
3 Copyright (C) 2012-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
6 This file is part of GNU Modula-2.
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)
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.
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/>. */
22 #include "gcc-consolidation.h"
28 #include "m2options.h"
30 #include "m2treelib.h"
32 /* For each binding contour we allocate a binding_level structure
33 which records the entities defined or declared in that contour.
36 the global one one for each subprogram definition
38 Binding contours are used to create GCC tree BLOCK nodes. */
40 struct GTY (()) binding_level
42 /* The function associated with the scope. This is NULL_TREE for the
46 /* A chain of _DECL nodes for all variables, constants, functions,
47 and typedef types. These are in the reverse of the order supplied. */
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. */
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. */
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
;
63 /* All binding levels are placed onto this list. */
64 struct binding_level
*list
;
66 /* A varray of trees, which represent the list of statement
68 vec
<tree
, va_gc
> *m2_statements
;
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. */
75 /* A list of inner module initialization functions. */
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
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
88 /* A list of labels which have been created in this scope. */
91 /* The number of times this level has been pushed. */
95 /* The binding level currently in effect. */
97 static GTY (()) struct binding_level
*current_binding_level
;
99 /* The outermost binding level, for names of file scope. This is
100 created when the compiler is started and exists through the entire
103 static GTY (()) struct binding_level
*global_binding_level
;
105 /* The head of the binding level lists. */
106 static GTY (()) struct binding_level
*head_binding_level
;
108 /* The current statement tree. */
110 typedef struct stmt_tree_s
*stmt_tree_t
;
114 static location_t pending_location
;
115 static int pending_statement
= false;
117 /* assert_global_names asserts that the global_binding_level->names
121 assert_global_names (void)
123 tree p
= global_binding_level
->names
;
129 /* lookupLabel return label tree in current scope, otherwise
133 lookupLabel (tree id
)
137 for (t
= current_binding_level
->labels
; t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
139 tree l
= TREE_VALUE (t
);
141 if (id
== DECL_NAME (l
))
147 /* getLabel return the label name or create a label name in the
151 m2block_getLabel (location_t location
, char *name
)
153 tree id
= get_identifier (name
);
154 tree label
= lookupLabel (id
);
156 if (label
== NULL_TREE
)
158 label
= build_decl (location
, LABEL_DECL
, id
, void_type_node
);
159 current_binding_level
->labels
160 = tree_cons (NULL_TREE
, label
, current_binding_level
->labels
);
162 if (DECL_CONTEXT (label
) == NULL_TREE
)
163 DECL_CONTEXT (label
) = current_function_decl
;
164 ASSERT ((DECL_CONTEXT (label
) == current_function_decl
),
165 current_function_decl
);
167 DECL_MODE (label
) = VOIDmode
;
172 init_binding_level (struct binding_level
*l
)
180 vec_alloc (l
->m2_statements
, 1);
182 l
->init_functions
= NULL
;
189 static struct binding_level
*
192 struct binding_level
*newlevel
= ggc_alloc
<binding_level
> ();
194 init_binding_level (newlevel
);
196 /* Now we a push_statement_list. */
197 vec_safe_push (newlevel
->m2_statements
, m2block_begin_statement_list ());
202 m2block_cur_stmt_list_addr (void)
204 ASSERT_CONDITION (current_binding_level
!= NULL
);
205 int l
= vec_safe_length (current_binding_level
->m2_statements
) - 1;
207 return &(*current_binding_level
->m2_statements
)[l
];
211 m2block_cur_stmt_list (void)
213 tree
*t
= m2block_cur_stmt_list_addr ();
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. */
223 m2block_is_building_stmt_list (void)
225 ASSERT_CONDITION (current_binding_level
!= NULL
);
226 return !vec_safe_is_empty (current_binding_level
->m2_statements
);
229 /* push_statement_list pushes the statement list t onto the
230 current binding level. */
233 m2block_push_statement_list (tree t
)
235 ASSERT_CONDITION (current_binding_level
!= NULL
);
236 vec_safe_push (current_binding_level
->m2_statements
, t
);
240 /* pop_statement_list pops and returns a statement list from the
241 current binding level. */
244 m2block_pop_statement_list (void)
246 ASSERT_CONDITION (current_binding_level
!= NULL
);
248 tree t
= current_binding_level
->m2_statements
->pop ();
254 /* begin_statement_list starts a tree statement. It pushes the
255 statement list and returns the list node. */
258 m2block_begin_statement_list (void)
260 return alloc_stmt_list ();
263 /* findLevel returns the binding level associated with fndecl one
264 is created if there is no existing one on head_binding_level. */
266 static struct binding_level
*
267 findLevel (tree fndecl
)
269 struct binding_level
*b
;
271 if (fndecl
== NULL_TREE
)
272 return global_binding_level
;
274 b
= head_binding_level
;
275 while ((b
!= NULL
) && (b
->fndecl
!= fndecl
))
283 b
->is_global
= false;
284 b
->list
= head_binding_level
;
290 /* pushFunctionScope push a binding level. */
293 m2block_pushFunctionScope (tree fndecl
)
295 struct binding_level
*n
;
296 struct binding_level
*b
;
298 #if defined(DEBUGGING)
300 printf ("pushFunctionScope\n");
303 /* Allow multiple consecutive pushes of the same scope. */
305 if (current_binding_level
!= NULL
306 && (current_binding_level
->fndecl
== fndecl
))
308 current_binding_level
->count
++;
312 /* Firstly check to see that fndecl is not already on the binding
315 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 ASSERT_CONDITION (b
->fndecl
!= fndecl
);
319 n
= findLevel (fndecl
);
321 /* Add this level to the front of the stack. */
322 n
->next
= current_binding_level
;
323 current_binding_level
= n
;
326 /* popFunctionScope - pops a binding level, returning the function
327 associated with the binding level. */
330 m2block_popFunctionScope (void)
332 tree fndecl
= current_binding_level
->fndecl
;
334 #if defined(DEBUGGING)
336 printf ("popFunctionScope\n");
339 if (current_binding_level
->count
> 0)
341 /* Multiple pushes have occurred of the same function scope (and
342 ignored), pop them likewise. */
343 current_binding_level
->count
--;
346 ASSERT_CONDITION (current_binding_level
->fndecl
347 != NULL_TREE
); /* Expecting local scope. */
349 ASSERT_CONDITION (current_binding_level
->constants
350 == NULL_TREE
); /* Should not be used. */
351 ASSERT_CONDITION (current_binding_level
->names
352 == NULL_TREE
); /* Should be cleared. */
353 ASSERT_CONDITION (current_binding_level
->decl
354 == NULL_TREE
); /* Should be cleared. */
356 current_binding_level
= current_binding_level
->next
;
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. */
365 m2block_pushGlobalScope (void)
367 #if defined(DEBUGGING)
368 printf ("pushGlobalScope\n");
370 m2block_pushFunctionScope (NULL_TREE
);
373 /* popGlobalScope pops the current binding level, it expects this
374 binding level to be the global binding level. */
377 m2block_popGlobalScope (void)
380 current_binding_level
->is_global
); /* Expecting global scope. */
381 ASSERT_CONDITION (current_binding_level
== global_binding_level
);
383 if (current_binding_level
->count
> 0)
385 current_binding_level
->count
--;
389 current_binding_level
= current_binding_level
->next
;
390 #if defined(DEBUGGING)
391 printf ("popGlobalScope\n");
394 assert_global_names ();
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.
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. */
406 m2block_finishFunctionDecl (location_t location
, tree fndecl
)
408 tree context
= current_binding_level
->context
;
409 tree block
= DECL_INITIAL (fndecl
);
410 tree bind_expr
= DECL_SAVED_TREE (fndecl
);
413 if (block
== NULL_TREE
)
415 block
= make_node (BLOCK
);
416 DECL_INITIAL (fndecl
) = block
;
417 TREE_USED (block
) = true;
418 BLOCK_SUBBLOCKS (block
) = NULL_TREE
;
420 BLOCK_SUPERCONTEXT (block
) = context
;
423 = chainon (BLOCK_VARS (block
), current_binding_level
->names
);
424 TREE_USED (fndecl
) = true;
426 if (bind_expr
== NULL_TREE
)
429 = build3 (BIND_EXPR
, void_type_node
, current_binding_level
->names
,
430 current_binding_level
->decl
, block
);
431 DECL_SAVED_TREE (fndecl
) = bind_expr
;
435 if (!chain_member (current_binding_level
->names
,
436 BIND_EXPR_VARS (bind_expr
)))
438 BIND_EXPR_VARS (bind_expr
) = chainon (BIND_EXPR_VARS (bind_expr
),
439 current_binding_level
->names
);
441 if (current_binding_level
->names
!= NULL_TREE
)
443 for (i
= current_binding_level
->names
; i
!= NULL_TREE
;
445 append_to_statement_list_force (i
,
446 &BIND_EXPR_BODY (bind_expr
));
451 SET_EXPR_LOCATION (bind_expr
, location
);
453 current_binding_level
->names
= NULL_TREE
;
454 current_binding_level
->decl
= NULL_TREE
;
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
463 m2block_finishFunctionCode (tree fndecl
)
467 tree statements
= m2block_pop_statement_list ();
468 tree_stmt_iterator i
;
470 ASSERT_CONDITION (DECL_SAVED_TREE (fndecl
) != NULL_TREE
);
472 bind_expr
= DECL_SAVED_TREE (fndecl
);
473 ASSERT_CONDITION (TREE_CODE (bind_expr
) == BIND_EXPR
);
475 block
= DECL_INITIAL (fndecl
);
476 ASSERT_CONDITION (TREE_CODE (block
) == BLOCK
);
478 if (current_binding_level
->names
!= NULL_TREE
)
480 BIND_EXPR_VARS (bind_expr
)
481 = chainon (BIND_EXPR_VARS (bind_expr
), current_binding_level
->names
);
482 current_binding_level
->names
= NULL_TREE
;
484 if (current_binding_level
->labels
!= NULL_TREE
)
488 for (t
= current_binding_level
->labels
; t
!= NULL_TREE
;
491 tree l
= TREE_VALUE (t
);
493 BIND_EXPR_VARS (bind_expr
) = chainon (BIND_EXPR_VARS (bind_expr
), l
);
495 current_binding_level
->labels
= NULL_TREE
;
498 BLOCK_VARS (block
) = BIND_EXPR_VARS (bind_expr
);
500 if (current_binding_level
->decl
!= NULL_TREE
)
501 for (i
= tsi_start (current_binding_level
->decl
); !tsi_end_p (i
);
503 append_to_statement_list_force (*tsi_stmt_ptr (i
),
504 &BIND_EXPR_BODY (bind_expr
));
506 for (i
= tsi_start (statements
); !tsi_end_p (i
); tsi_next (&i
))
507 append_to_statement_list_force (*tsi_stmt_ptr (i
),
508 &BIND_EXPR_BODY (bind_expr
));
510 current_binding_level
->decl
= NULL_TREE
;
514 m2block_finishGlobals (void)
516 tree context
= global_binding_level
->context
;
517 tree block
= make_node (BLOCK
);
518 tree p
= global_binding_level
->names
;
520 BLOCK_SUBBLOCKS (block
) = NULL
;
521 TREE_USED (block
) = 1;
523 BLOCK_VARS (block
) = p
;
525 DECL_INITIAL (context
) = block
;
526 BLOCK_SUPERCONTEXT (block
) = context
;
529 /* pushDecl pushes a declaration onto the current binding level. */
532 m2block_pushDecl (tree decl
)
534 /* External objects aren't nested, other objects may be. */
536 if (decl
!= current_function_decl
)
537 DECL_CONTEXT (decl
) = current_binding_level
->context
;
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. */
543 TREE_CHAIN (decl
) = current_binding_level
->names
;
544 current_binding_level
->names
= decl
;
546 assert_global_names ();
551 /* includeDecl pushes a declaration onto the current binding level
552 providing it is not already present. */
555 m2block_includeDecl (tree decl
)
557 tree p
= current_binding_level
->names
;
559 while (p
!= decl
&& p
!= NULL
)
562 m2block_pushDecl (decl
);
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. */
570 m2block_addDeclExpr (tree t
)
572 append_to_statement_list_force (t
, ¤t_binding_level
->decl
);
575 /* RememberType remember the type t in the ggc marked list. */
578 m2block_RememberType (tree t
)
580 global_binding_level
->types
581 = tree_cons (NULL_TREE
, t
, global_binding_level
->types
);
585 /* global_constant returns t. It chains t onto the
586 global_binding_level list of constants, if it is not already
590 m2block_global_constant (tree t
)
594 if (global_binding_level
->constants
!= NULL_TREE
)
595 for (s
= global_binding_level
->constants
; s
!= NULL_TREE
;
598 tree c
= TREE_VALUE (s
);
604 global_binding_level
->constants
605 = tree_cons (NULL_TREE
, t
, global_binding_level
->constants
);
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. */
615 m2block_RememberConstant (tree t
)
617 if ((t
!= NULL
) && (m2tree_IsAConstant (t
)))
618 return m2block_global_constant (t
);
622 /* DumpGlobalConstants displays all global constants and checks
623 none are poisoned. */
626 m2block_DumpGlobalConstants (void)
630 if (global_binding_level
->constants
!= NULL_TREE
)
631 for (s
= global_binding_level
->constants
; TREE_CHAIN (s
);
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. */
643 m2block_RememberInitModuleFunction (tree t
)
645 global_binding_level
->init_functions
646 = tree_cons (NULL_TREE
, t
, global_binding_level
->init_functions
);
650 /* toplevel return true if we are in the global scope. */
653 m2block_toplevel (void)
655 if (current_binding_level
== NULL
)
657 if (current_binding_level
->fndecl
== NULL
)
662 /* GetErrorNode returns the gcc error_mark_node. */
665 m2block_GetErrorNode (void)
667 return error_mark_node
;
670 /* GetGlobals - returns a list of global variables, functions,
674 m2block_GetGlobals (void)
676 assert_global_names ();
677 return global_binding_level
->names
;
680 /* GetGlobalContext - returns the global context tree. */
683 m2block_GetGlobalContext (void)
685 return global_binding_level
->context
;
688 /* do_add_stmt - t is a statement. Add it to the statement-tree. */
693 if (current_binding_level
!= NULL
)
694 append_to_statement_list_force (t
, m2block_cur_stmt_list_addr ());
698 /* flush_pending_note - flushes a pending_statement note if
702 flush_pending_note (void)
704 if (pending_statement
&& (M2Options_GetM2g ()))
707 /* --fixme-- we need a machine independant way to generate a nop. */
708 tree instr
= m2decl_BuildStringConstant ("nop", 3);
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
);
714 ASM_INPUT_P (note
) = false;
715 ASM_VOLATILE_P (note
) = false;
717 tree note
= build_empty_stmt (pending_location
);
719 pending_statement
= false;
724 /* add_stmt t is a statement. Add it to the statement-tree. */
727 m2block_add_stmt (location_t location
, tree t
)
729 if ((CAN_HAVE_LOCATION_P (t
)) && (!EXPR_HAS_LOCATION (t
)))
730 SET_EXPR_LOCATION (t
, location
);
732 if (pending_statement
&& (pending_location
!= location
))
733 flush_pending_note ();
735 pending_statement
= false;
736 return do_add_stmt (t
);
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. */
744 m2block_addStmtNote (location_t location
)
746 if (pending_statement
&& (pending_location
!= location
))
747 flush_pending_note ();
749 pending_statement
= true;
750 pending_location
= location
;
754 m2block_removeStmtNote (void)
756 pending_statement
= false;
759 /* init - initialize the data structures in this module. */
764 global_binding_level
= newLevel ();
765 global_binding_level
->context
= build_translation_unit_decl (NULL
);
766 global_binding_level
->is_global
= true;
767 current_binding_level
= NULL
;
770 #include "gt-m2-m2block.h"