1 /* m2block.c provides an interface to maintaining block structures.
3 Copyright (C) 2012-2021 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 initialisation 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 /* end_statement_list - returns the current statement tree. The
264 current statement tree is popped from the statement stack and the
265 list node is returned. */
268 m2block_end_statement_list (tree t
)
270 /* should we do anything with, t? Specifically we may need to test
271 for the presence of a label --fixme-- check this */
275 /* findLevel - returns the binding level associated with, fndecl, one
276 is created if there is no existing one on head_binding_level. */
278 static struct binding_level
*
279 findLevel (tree fndecl
)
281 struct binding_level
*b
;
283 if (fndecl
== NULL_TREE
)
284 return global_binding_level
;
286 b
= head_binding_level
;
287 while ((b
!= NULL
) && (b
->fndecl
!= fndecl
))
295 b
->is_global
= FALSE
;
296 b
->list
= head_binding_level
;
302 /* pushFunctionScope - push a binding level. */
305 m2block_pushFunctionScope (tree fndecl
)
307 struct binding_level
*n
;
308 struct binding_level
*b
;
310 #if defined(DEBUGGING)
312 printf ("pushFunctionScope\n");
315 /* allow multiple consecutive pushes of the same scope. */
317 if (current_binding_level
!= NULL
318 && (current_binding_level
->fndecl
== fndecl
))
320 current_binding_level
->count
++;
324 /* firstly check to see that fndecl is not already on the binding
327 for (b
= current_binding_level
; b
!= NULL
; b
= b
->next
)
328 /* only allowed one instance of the binding on the stack at a time. */
329 ASSERT_CONDITION (b
->fndecl
!= fndecl
);
331 n
= findLevel (fndecl
);
333 /* Add this level to the front of the stack. */
334 n
->next
= current_binding_level
;
335 current_binding_level
= n
;
338 /* popFunctionScope - pops a binding level, returning the function
339 associated with the binding level. */
342 m2block_popFunctionScope (void)
344 tree fndecl
= current_binding_level
->fndecl
;
346 #if defined(DEBUGGING)
348 printf ("popFunctionScope\n");
351 if (current_binding_level
->count
> 0)
353 /* multiple pushes have occurred of the same function scope (and
354 ignored), pop them likewise. */
355 current_binding_level
->count
--;
358 ASSERT_CONDITION (current_binding_level
->fndecl
359 != NULL_TREE
); /* expecting local scope. */
361 ASSERT_CONDITION (current_binding_level
->constants
362 == NULL_TREE
); /* should not be used. */
363 ASSERT_CONDITION (current_binding_level
->names
364 == NULL_TREE
); /* should be cleared. */
365 ASSERT_CONDITION (current_binding_level
->decl
366 == NULL_TREE
); /* should be cleared. */
368 current_binding_level
= current_binding_level
->next
;
372 /* pushGlobalScope - push the global scope onto the binding level
373 stack. There can only ever be one instance of the global binding
374 level on the stack. */
377 m2block_pushGlobalScope (void)
379 #if defined(DEBUGGING)
380 printf ("pushGlobalScope\n");
382 m2block_pushFunctionScope (NULL_TREE
);
385 /* popGlobalScope - pops the current binding level, it expects this
386 binding level to be the global binding level. */
389 m2block_popGlobalScope (void)
392 current_binding_level
->is_global
); /* expecting global scope. */
393 ASSERT_CONDITION (current_binding_level
== global_binding_level
);
395 if (current_binding_level
->count
> 0)
397 current_binding_level
->count
--;
401 current_binding_level
= current_binding_level
->next
;
402 #if defined(DEBUGGING)
403 printf ("popGlobalScope\n");
406 assert_global_names ();
409 /* finishFunctionDecl - removes declarations from the current binding
410 level and places them inside fndecl. The current binding level is
411 then able to be destroyed by a call to popFunctionScope.
413 The extra tree nodes associated with fndecl will be created such
414 as BIND_EXPR, BLOCK and the initial STATEMENT_LIST containing the
415 DECL_EXPR is also created. */
418 m2block_finishFunctionDecl (location_t location
, tree fndecl
)
420 tree context
= current_binding_level
->context
;
421 tree block
= DECL_INITIAL (fndecl
);
422 tree bind_expr
= DECL_SAVED_TREE (fndecl
);
425 if (block
== NULL_TREE
)
427 block
= make_node (BLOCK
);
428 DECL_INITIAL (fndecl
) = block
;
429 TREE_USED (block
) = TRUE
;
430 BLOCK_SUBBLOCKS (block
) = NULL_TREE
;
432 BLOCK_SUPERCONTEXT (block
) = context
;
435 = chainon (BLOCK_VARS (block
), current_binding_level
->names
);
436 TREE_USED (fndecl
) = TRUE
;
438 if (bind_expr
== NULL_TREE
)
441 = build3 (BIND_EXPR
, void_type_node
, current_binding_level
->names
,
442 current_binding_level
->decl
, block
);
443 DECL_SAVED_TREE (fndecl
) = bind_expr
;
447 if (!chain_member (current_binding_level
->names
,
448 BIND_EXPR_VARS (bind_expr
)))
450 BIND_EXPR_VARS (bind_expr
) = chainon (BIND_EXPR_VARS (bind_expr
),
451 current_binding_level
->names
);
453 if (current_binding_level
->names
!= NULL_TREE
)
455 for (i
= current_binding_level
->names
; i
!= NULL_TREE
;
457 append_to_statement_list_force (i
,
458 &BIND_EXPR_BODY (bind_expr
));
463 SET_EXPR_LOCATION (bind_expr
, location
);
465 current_binding_level
->names
= NULL_TREE
;
466 current_binding_level
->decl
= NULL_TREE
;
469 /* finishFunctionCode - adds cur_stmt_list to fndecl. The current
470 binding level is then able to be destroyed by a call to
471 popFunctionScope. The cur_stmt_list is appended to the
475 m2block_finishFunctionCode (tree fndecl
)
479 tree statements
= m2block_pop_statement_list ();
480 tree_stmt_iterator i
;
482 statements
= m2block_end_statement_list (statements
);
483 ASSERT_CONDITION (DECL_SAVED_TREE (fndecl
) != NULL_TREE
);
485 bind_expr
= DECL_SAVED_TREE (fndecl
);
486 ASSERT_CONDITION (TREE_CODE (bind_expr
) == BIND_EXPR
);
488 block
= DECL_INITIAL (fndecl
);
489 ASSERT_CONDITION (TREE_CODE (block
) == BLOCK
);
491 if (current_binding_level
->names
!= NULL_TREE
)
493 BIND_EXPR_VARS (bind_expr
)
494 = chainon (BIND_EXPR_VARS (bind_expr
), current_binding_level
->names
);
495 current_binding_level
->names
= NULL_TREE
;
497 if (current_binding_level
->labels
!= NULL_TREE
)
501 for (t
= current_binding_level
->labels
; t
!= NULL_TREE
;
504 tree l
= TREE_VALUE (t
);
506 BIND_EXPR_VARS (bind_expr
) = chainon (BIND_EXPR_VARS (bind_expr
), l
);
508 current_binding_level
->labels
= NULL_TREE
;
511 BLOCK_VARS (block
) = BIND_EXPR_VARS (bind_expr
);
513 if (current_binding_level
->decl
!= NULL_TREE
)
514 for (i
= tsi_start (current_binding_level
->decl
); !tsi_end_p (i
);
516 append_to_statement_list_force (*tsi_stmt_ptr (i
),
517 &BIND_EXPR_BODY (bind_expr
));
519 for (i
= tsi_start (statements
); !tsi_end_p (i
); tsi_next (&i
))
520 append_to_statement_list_force (*tsi_stmt_ptr (i
),
521 &BIND_EXPR_BODY (bind_expr
));
523 current_binding_level
->decl
= NULL_TREE
;
527 m2block_finishGlobals (void)
529 tree context
= global_binding_level
->context
;
530 tree block
= make_node (BLOCK
);
531 tree p
= global_binding_level
->names
;
533 BLOCK_SUBBLOCKS (block
) = NULL
;
534 TREE_USED (block
) = 1;
536 BLOCK_VARS (block
) = p
;
538 DECL_INITIAL (context
) = block
;
539 BLOCK_SUPERCONTEXT (block
) = context
;
542 /* pushDecl - pushes a declaration onto the current binding level. */
545 m2block_pushDecl (tree decl
)
547 /* External objects aren't nested, other objects may be. */
549 if (decl
!= current_function_decl
)
550 DECL_CONTEXT (decl
) = current_binding_level
->context
;
552 /* Put the declaration on the list. The list of declarations is in
553 reverse order. The list will be reversed later if necessary. This
554 needs to be this way for compatibility with the back-end. */
556 TREE_CHAIN (decl
) = current_binding_level
->names
;
557 current_binding_level
->names
= decl
;
559 assert_global_names ();
564 /* includeDecl - pushes a declaration onto the current binding level
565 providing it is not already present. */
568 m2block_includeDecl (tree decl
)
570 tree p
= current_binding_level
->names
;
572 while (p
!= decl
&& p
!= NULL
)
575 m2block_pushDecl (decl
);
578 /* addDeclExpr - adds the DECL_EXPR node, t, to the statement list
579 current_binding_level->decl. This allows us to order all
580 declarations at the beginning of the function. */
583 m2block_addDeclExpr (tree t
)
585 append_to_statement_list_force (t
, ¤t_binding_level
->decl
);
588 /* RememberType - remember the type, t, in the ggc marked list. */
591 m2block_RememberType (tree t
)
593 global_binding_level
->types
594 = tree_cons (NULL_TREE
, t
, global_binding_level
->types
);
598 /* global_constant - returns t. It chains, t, onto the
599 global_binding_level list of constants, if it is not already
603 m2block_global_constant (tree t
)
607 if (global_binding_level
->constants
!= NULL_TREE
)
608 for (s
= global_binding_level
->constants
; s
!= NULL_TREE
;
611 tree c
= TREE_VALUE (s
);
617 global_binding_level
->constants
618 = tree_cons (NULL_TREE
, t
, global_binding_level
->constants
);
622 /* RememberConstant - adds a tree, t, onto the list of constants to
623 be marked whenever the ggc re-marks all used storage. Constants
624 live throughout the whole compilation - and they can be used by
625 many different functions if necessary. */
628 m2block_RememberConstant (tree t
)
630 if ((t
!= NULL
) && (m2tree_IsAConstant (t
)))
631 return m2block_global_constant (t
);
635 /* DumpGlobalConstants - displays all global constants and checks
636 none are poisoned. */
639 m2block_DumpGlobalConstants (void)
643 if (global_binding_level
->constants
!= NULL_TREE
)
644 for (s
= global_binding_level
->constants
; TREE_CHAIN (s
);
650 /* RememberInitModuleFunction - records tree, t, in the global
651 binding level. So that it will not be garbage collected. In
652 theory the inner modules could be placed inside the
653 current_binding_level I suspect. */
656 m2block_RememberInitModuleFunction (tree t
)
658 global_binding_level
->init_functions
659 = tree_cons (NULL_TREE
, t
, global_binding_level
->init_functions
);
663 /* toplevel - return TRUE if we are in the global scope. */
666 m2block_toplevel (void)
668 if (current_binding_level
== NULL
)
670 if (current_binding_level
->fndecl
== NULL
)
675 /* GetErrorNode - returns the gcc error_mark_node. */
678 m2block_GetErrorNode (void)
680 return error_mark_node
;
683 /* GetGlobals - returns a list of global variables, functions,
687 m2block_GetGlobals (void)
689 assert_global_names ();
690 return global_binding_level
->names
;
693 /* GetGlobalContext - returns the global context tree. */
696 m2block_GetGlobalContext (void)
698 return global_binding_level
->context
;
701 /* do_add_stmt - t is a statement. Add it to the statement-tree. */
706 if (current_binding_level
!= NULL
)
707 append_to_statement_list_force (t
, m2block_cur_stmt_list_addr ());
711 /* flush_pending_note - flushes a pending_statement note if
715 flush_pending_note (void)
717 if (pending_statement
&& (M2Options_GetM2g ()))
720 /* --fixme-- we need a machine independant way to generate a nop. */
721 tree instr
= m2decl_BuildStringConstant ("nop", 3);
723 = resolve_asm_operand_names (instr
, NULL_TREE
, NULL_TREE
, NULL_TREE
);
724 tree note
= build_stmt (pending_location
, ASM_EXPR
, string
, NULL_TREE
,
725 NULL_TREE
, NULL_TREE
, NULL_TREE
);
727 ASM_INPUT_P (note
) = FALSE
;
728 ASM_VOLATILE_P (note
) = FALSE
;
730 tree note
= build_empty_stmt (pending_location
);
732 pending_statement
= FALSE
;
737 /* add_stmt - t is a statement. Add it to the statement-tree. */
740 m2block_add_stmt (location_t location
, tree t
)
742 if ((CAN_HAVE_LOCATION_P (t
)) && (!EXPR_HAS_LOCATION (t
)))
743 SET_EXPR_LOCATION (t
, location
);
745 if (pending_statement
&& (pending_location
!= location
))
746 flush_pending_note ();
748 pending_statement
= FALSE
;
749 return do_add_stmt (t
);
752 /* addStmtNote - remember this location represents the start of a
753 Modula-2 statement. It is flushed if another different location
754 is generated or another tree is given to add_stmt. */
757 m2block_addStmtNote (location_t location
)
759 if (pending_statement
&& (pending_location
!= location
))
760 flush_pending_note ();
762 pending_statement
= TRUE
;
763 pending_location
= location
;
767 m2block_removeStmtNote (void)
769 pending_statement
= FALSE
;
772 /* init - initialise the data structures in this module. */
777 global_binding_level
= newLevel ();
778 global_binding_level
->context
= build_translation_unit_decl (NULL
);
779 global_binding_level
->is_global
= TRUE
;
780 current_binding_level
= NULL
;
783 #include "gt-m2-m2block.h"