1 /* m2statement.cc provides an interface to GCC statement trees.
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"
24 #include "../gm2-lang.h"
25 #include "../m2-tree.h"
34 #include "m2statement.h"
36 #include "m2treelib.h"
38 #include "m2convert.h"
40 static GTY (()) tree param_list
= NULL_TREE
; /* Ready for the next time we
41 call/define a function. */
42 static GTY (()) tree last_function
= NULL_TREE
;
45 /* BuildStartFunctionCode - generate function entry code. */
48 m2statement_BuildStartFunctionCode (location_t location
, tree fndecl
,
49 bool isexported
, bool isinline
)
53 ASSERT_BOOL (isexported
);
54 ASSERT_BOOL (isinline
);
55 /* Announce we are compiling this function. */
56 announce_function (fndecl
);
58 /* Set up to compile the function and enter it. */
60 DECL_INITIAL (fndecl
) = NULL_TREE
;
62 current_function_decl
= fndecl
;
63 m2block_pushFunctionScope (fndecl
);
64 m2statement_SetBeginLocation (location
);
66 ASSERT_BOOL ((cfun
!= NULL
));
67 /* Initialize the RTL code for the function. */
68 allocate_struct_function (fndecl
, false);
69 /* Begin the statement tree for this function. */
70 DECL_SAVED_TREE (fndecl
) = NULL_TREE
;
72 /* Set the context of these parameters to this function. */
73 for (param_decl
= DECL_ARGUMENTS (fndecl
); param_decl
;
74 param_decl
= TREE_CHAIN (param_decl
))
75 DECL_CONTEXT (param_decl
) = fndecl
;
77 /* This function exists in static storage. (This does not mean
78 `static' in the C sense!) */
79 TREE_STATIC (fndecl
) = 1;
80 TREE_PUBLIC (fndecl
) = isexported
;
81 /* We could do better here by detecting ADR
82 or type PROC used on this function. --fixme-- */
83 TREE_ADDRESSABLE (fndecl
) = 1;
84 DECL_DECLARED_INLINE_P (fndecl
) = 0; /* isinline; */
87 /* BuildEndFunctionCode - generates the function epilogue. */
90 m2statement_BuildEndFunctionCode (location_t location
, tree fndecl
, bool nested
)
92 tree block
= DECL_INITIAL (fndecl
);
94 BLOCK_SUPERCONTEXT (block
) = fndecl
;
96 /* Must mark the RESULT_DECL as being in this function. */
97 DECL_CONTEXT (DECL_RESULT (fndecl
)) = fndecl
;
99 /* And attach it to the function. */
100 DECL_INITIAL (fndecl
) = block
;
102 m2block_finishFunctionCode (fndecl
);
103 m2statement_SetEndLocation (location
);
105 gm2_genericize (fndecl
);
107 (void)cgraph_node::get_create (fndecl
);
109 cgraph_node::finalize_function (fndecl
, false);
111 m2block_popFunctionScope ();
113 /* We're leaving the context of this function, so zap cfun. It's
114 still in DECL_STRUCT_FUNCTION, and we'll restore it in
115 tree_rest_of_compilation. */
117 current_function_decl
= NULL
;
120 /* BuildPushFunctionContext - pushes the current function context.
121 Maps onto push_function_context in ../function.cc. */
124 m2statement_BuildPushFunctionContext (void)
126 push_function_context ();
129 /* BuildPopFunctionContext - pops the current function context. Maps
130 onto pop_function_context in ../function.cc. */
133 m2statement_BuildPopFunctionContext (void)
135 pop_function_context ();
139 m2statement_SetBeginLocation (location_t location
)
142 cfun
->function_start_locus
= location
;
146 m2statement_SetEndLocation (location_t location
)
149 cfun
->function_end_locus
= location
;
152 /* BuildAssignmentTree builds the assignment of, des, and, expr.
156 m2statement_BuildAssignmentTree (location_t location
, tree des
, tree expr
)
160 m2assert_AssertLocation (location
);
161 STRIP_TYPE_NOPS (expr
);
163 if (TREE_CODE (expr
) == FUNCTION_DECL
)
164 result
= build2 (MODIFY_EXPR
, TREE_TYPE (des
), des
,
165 m2expr_BuildAddr (location
, expr
, false));
168 gcc_assert (TREE_CODE (TREE_TYPE (des
)) != TYPE_DECL
);
169 if (TREE_TYPE (expr
) == TREE_TYPE (des
))
170 result
= build2 (MODIFY_EXPR
, TREE_TYPE (des
), des
, expr
);
173 MODIFY_EXPR
, TREE_TYPE (des
), des
,
174 m2convert_BuildConvert (location
, TREE_TYPE (des
), expr
, false));
177 TREE_SIDE_EFFECTS (result
) = true;
178 TREE_USED (des
) = true;
179 TREE_USED (expr
) = true;
180 add_stmt (location
, result
);
184 /* BuildAssignmentStatement builds the assignment of, des, and, expr. */
187 m2statement_BuildAssignmentStatement (location_t location
, tree des
, tree expr
)
189 m2statement_BuildAssignmentTree (location
, des
, expr
);
192 /* BuildGoto builds a goto operation. */
195 m2statement_BuildGoto (location_t location
, char *name
)
197 tree label
= m2block_getLabel (location
, name
);
199 m2assert_AssertLocation (location
);
200 TREE_USED (label
) = true;
201 add_stmt (location
, build1 (GOTO_EXPR
, void_type_node
, label
));
204 /* DeclareLabel - create a label, name. */
207 m2statement_DeclareLabel (location_t location
, char *name
)
209 tree label
= m2block_getLabel (location
, name
);
211 m2assert_AssertLocation (location
);
212 add_stmt (location
, build1 (LABEL_EXPR
, void_type_node
, label
));
215 /* BuildParam - build a list of parameters, ready for a subsequent
219 m2statement_BuildParam (location_t location
, tree param
)
221 m2assert_AssertLocation (location
);
223 TREE_USED (param
) = true;
224 if (TREE_CODE (param
) == FUNCTION_DECL
)
225 param
= m2expr_BuildAddr (location
, param
, false);
227 param_list
= chainon (build_tree_list (NULL_TREE
, param
), param_list
);
230 /* nCount - return the number of chained tree nodes in list, t. */
245 /* BuildProcedureCallTree - creates a procedure call from a procedure
246 and parameter list and the return type, rettype. */
249 m2statement_BuildProcedureCallTree (location_t location
, tree procedure
,
252 tree functype
= TREE_TYPE (procedure
);
253 tree funcptr
= build1 (ADDR_EXPR
, build_pointer_type (functype
), procedure
);
255 int n
= nCount (param_list
);
256 tree
*argarray
= XALLOCAVEC (tree
, n
);
260 m2assert_AssertLocation (location
);
263 == NULL_TREE
); /* Previous function value has not been collected. */
264 TREE_USED (procedure
) = true;
266 for (i
= 0; i
< n
; i
++)
268 argarray
[i
] = TREE_VALUE (t
);
272 if (rettype
== NULL_TREE
)
274 rettype
= void_type_node
;
275 call
= build_call_array_loc (location
, rettype
, funcptr
, n
, argarray
);
276 TREE_USED (call
) = true;
277 TREE_SIDE_EFFECTS (call
) = true;
279 #if defined(DEBUG_PROCEDURE_CALLS)
280 fprintf (stderr
, "built the modula-2 call, here is the tree\n");
286 = NULL_TREE
; /* Ready for the next time we call a procedure. */
287 last_function
= NULL_TREE
;
292 last_function
= build_call_array_loc (
293 location
, m2tree_skip_type_decl (rettype
), funcptr
, n
, argarray
);
294 TREE_USED (last_function
) = true;
295 TREE_SIDE_EFFECTS (last_function
) = true;
297 = NULL_TREE
; /* Ready for the next time we call a procedure. */
298 return last_function
;
302 /* BuildIndirectProcedureCallTree - creates a procedure call from a
303 procedure and parameter list and the return type, rettype. */
306 m2statement_BuildIndirectProcedureCallTree (location_t location
,
307 tree procedure
, tree rettype
)
310 int n
= nCount (param_list
);
311 tree
*argarray
= XALLOCAVEC (tree
, n
);
315 m2assert_AssertLocation (location
);
316 TREE_USED (procedure
) = true;
317 TREE_SIDE_EFFECTS (procedure
) = true;
319 for (i
= 0; i
< n
; i
++)
321 argarray
[i
] = TREE_VALUE (t
);
325 if (rettype
== NULL_TREE
)
327 rettype
= void_type_node
;
328 call
= build_call_array_loc (location
, rettype
, procedure
, n
, argarray
);
329 TREE_USED (call
) = true;
330 TREE_SIDE_EFFECTS (call
) = true;
332 #if defined(DEBUG_PROCEDURE_CALLS)
333 fprintf (stderr
, "built the modula-2 call, here is the tree\n");
338 last_function
= NULL_TREE
;
340 = NULL_TREE
; /* Ready for the next time we call a procedure. */
345 last_function
= build_call_array_loc (
346 location
, m2tree_skip_type_decl (rettype
), procedure
, n
, argarray
);
347 TREE_USED (last_function
) = true;
348 TREE_SIDE_EFFECTS (last_function
) = true;
350 = NULL_TREE
; /* Ready for the next time we call a procedure. */
351 return last_function
;
356 /* BuildBuiltinCallTree calls the builtin procedure. */
359 m2statement_BuildBuiltinCallTree (location_t location
, tree func
)
361 TREE_USED (func
) = true;
362 TREE_SIDE_EFFECTS (func
) = true;
364 = NULL_TREE
; /* Ready for the next time we call a procedure. */
369 /* BuildFunctValue - generates code for value :=
370 last_function(foobar); */
373 m2statement_BuildFunctValue (location_t location
, tree value
)
376 = m2treelib_build_modify_expr (location
, value
, NOP_EXPR
, last_function
);
378 m2assert_AssertLocation (location
);
381 != NULL_TREE
); /* No value available, possible used before. */
383 TREE_SIDE_EFFECTS (assign
) = true;
384 TREE_USED (assign
) = true;
385 TREE_USED (value
) = true;
386 last_function
= NULL_TREE
;
388 // return m2statement_BuildAssignmentTree (location, value, assign);
391 /* BuildCall2 - builds a tree representing: function (arg1, arg2). */
394 m2statement_BuildCall2 (location_t location
, tree function
, tree rettype
,
395 tree arg1
, tree arg2
)
397 m2assert_AssertLocation (location
);
398 ASSERT_CONDITION (param_list
== NULL_TREE
);
400 param_list
= chainon (build_tree_list (NULL_TREE
, arg2
), param_list
);
401 param_list
= chainon (build_tree_list (NULL_TREE
, arg1
), param_list
);
402 return m2statement_BuildProcedureCallTree (location
, function
, rettype
);
405 /* BuildCall3 - builds a tree representing: function (arg1, arg2,
409 m2statement_BuildCall3 (location_t location
, tree function
, tree rettype
,
410 tree arg1
, tree arg2
, tree arg3
)
412 m2assert_AssertLocation (location
);
413 ASSERT_CONDITION (param_list
== NULL_TREE
);
415 param_list
= chainon (build_tree_list (NULL_TREE
, arg3
), param_list
);
416 param_list
= chainon (build_tree_list (NULL_TREE
, arg2
), param_list
);
417 param_list
= chainon (build_tree_list (NULL_TREE
, arg1
), param_list
);
418 return m2statement_BuildProcedureCallTree (location
, function
, rettype
);
421 /* BuildFunctionCallTree - creates a procedure function call from
422 a procedure and parameter list and the return type, rettype.
423 No tree is returned as the tree is held in the last_function global
424 variable. It is expected the BuildFunctValue is to be called after
425 a call to BuildFunctionCallTree. */
428 m2statement_BuildFunctionCallTree (location_t location
, tree procedure
,
431 m2statement_BuildProcedureCallTree (location
, procedure
, rettype
);
434 /* SetLastFunction - assigns last_function to, t. */
437 m2statement_SetLastFunction (tree t
)
442 /* SetParamList - assigns param_list to, t. */
445 m2statement_SetParamList (tree t
)
450 /* GetLastFunction - returns, last_function. */
453 m2statement_GetLastFunction (void)
455 return last_function
;
458 /* GetParamList - returns, param_list. */
461 m2statement_GetParamList (void)
466 /* GetCurrentFunction - returns the current_function. */
469 m2statement_GetCurrentFunction (void)
471 return current_function_decl
;
474 /* GetParamTree - return parameter, i. */
477 m2statement_GetParamTree (tree call
, unsigned int i
)
479 return CALL_EXPR_ARG (call
, i
);
482 /* BuildTryFinally - returns a TRY_FINALL_EXPR with the call and
483 cleanups attached. */
486 m2statement_BuildTryFinally (location_t location
, tree call
, tree cleanups
)
488 return build_stmt (location
, TRY_FINALLY_EXPR
, call
, cleanups
);
491 /* BuildCleanUp - return a CLEANUP_POINT_EXPR which will clobber,
495 m2statement_BuildCleanUp (tree param
)
497 tree clobber
= build_constructor (TREE_TYPE (param
), NULL
);
498 TREE_THIS_VOLATILE (clobber
) = 1;
499 return build2 (MODIFY_EXPR
, TREE_TYPE (param
), param
, clobber
);
502 /* BuildAsm - generates an inline assembler instruction. */
505 m2statement_BuildAsm (location_t location
, tree instr
, bool isVolatile
,
506 bool isSimple
, tree inputs
, tree outputs
, tree trash
,
509 tree string
= resolve_asm_operand_names (instr
, outputs
, inputs
, labels
);
510 tree args
= build_stmt (location
, ASM_EXPR
, string
, outputs
, inputs
, trash
,
513 m2assert_AssertLocation (location
);
515 /* ASM statements without outputs, including simple ones, are treated
517 ASM_INPUT_P (args
) = isSimple
;
518 ASM_VOLATILE_P (args
) = isVolatile
;
520 add_stmt (location
, args
);
523 /* BuildUnaryForeachWordDo - provides the large set operators. Each
524 word (or less) of the set can be calculated by unop. This
525 procedure runs along each word of the large set invoking the unop. */
528 m2statement_BuildUnaryForeachWordDo (location_t location
, tree type
, tree op1
,
530 tree (*unop
) (location_t
, tree
, bool),
531 bool is_op1lvalue
, bool is_op2lvalue
,
532 bool is_op1const
, bool is_op2const
)
534 tree size
= m2expr_GetSizeOf (location
, type
);
536 m2assert_AssertLocation (location
);
537 ASSERT_BOOL (is_op1lvalue
);
538 ASSERT_BOOL (is_op2lvalue
);
539 ASSERT_BOOL (is_op1const
);
540 ASSERT_BOOL (is_op2const
);
541 if (m2expr_CompareTrees (
542 size
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
))
544 /* Small set size <= TSIZE(WORD). */
545 m2statement_BuildAssignmentTree (
546 location
, m2treelib_get_rvalue (location
, op1
, type
, is_op1lvalue
),
548 m2treelib_get_rvalue (location
, op2
, type
, is_op2lvalue
),
552 /* Large set size > TSIZE(WORD). */
553 unsigned int fieldNo
= 0;
554 tree field1
= m2treelib_get_field_no (type
, op1
, is_op1const
, fieldNo
);
555 tree field2
= m2treelib_get_field_no (type
, op2
, is_op2const
, fieldNo
);
558 error ("internal error: not expecting operand1 to be a constant set");
560 while (field1
!= NULL
&& field2
!= NULL
)
562 m2statement_BuildAssignmentTree (
563 location
, m2treelib_get_set_field_des (location
, op1
, field1
),
565 m2treelib_get_set_field_rhs (location
, op2
, field2
),
568 field1
= m2treelib_get_field_no (type
, op1
, is_op1const
, fieldNo
);
569 field2
= m2treelib_get_field_no (type
, op2
, is_op2const
, fieldNo
);
574 /* BuildExcludeVarConst - builds the EXCL(op1, 1<<op2) operation for
575 a small sets. Large sets call this routine to exclude the bit in
576 the particular word. op2 is a constant. */
579 m2statement_BuildExcludeVarConst (location_t location
, tree type
, tree op1
,
580 tree op2
, bool is_lvalue
, int fieldno
)
582 tree size
= m2expr_GetSizeOf (location
, type
);
584 m2assert_AssertLocation (location
);
585 ASSERT_BOOL (is_lvalue
);
586 if (m2expr_CompareTrees (
587 size
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
))
590 /* Small set size <= TSIZE(WORD). */
591 m2statement_BuildAssignmentTree (
592 location
, m2treelib_get_rvalue (location
, op1
, type
, is_lvalue
),
593 m2expr_BuildLogicalAnd (
594 location
, m2treelib_get_rvalue (location
, op1
, type
, is_lvalue
),
595 m2expr_BuildSetNegate (
597 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
), op2
,
604 tree fieldlist
= TYPE_FIELDS (type
);
607 for (field
= fieldlist
; (field
!= NULL
) && (fieldno
> 0);
608 field
= TREE_CHAIN (field
))
611 m2statement_BuildAssignmentTree (
612 location
, m2treelib_get_set_field_des (location
, op1
, field
),
613 m2expr_BuildLogicalAnd (
614 location
, m2treelib_get_set_field_rhs (location
, op1
, field
),
615 m2expr_BuildSetNegate (
617 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
), op2
,
624 /* BuildExcludeVarVar - builds the EXCL(varset, 1<<varel) operation
625 for a small and large sets. varel is a variable. */
628 m2statement_BuildExcludeVarVar (location_t location
, tree type
, tree varset
,
629 tree varel
, bool is_lvalue
, tree low
)
631 tree size
= m2expr_GetSizeOf (location
, type
);
633 m2assert_AssertLocation (location
);
634 ASSERT_BOOL (is_lvalue
);
635 /* Calculate the index from the first bit, ie bit 0 represents low value. */
637 = m2expr_BuildSub (location
, m2convert_ToInteger (location
, varel
),
638 m2convert_ToInteger (location
, low
), false);
640 if (m2expr_CompareTrees (
641 size
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
))
643 /* Small set size <= TSIZE(WORD). */
644 m2statement_BuildAssignmentTree (
645 location
, m2treelib_get_rvalue (location
, varset
, type
, is_lvalue
),
646 m2expr_BuildLogicalAnd (
647 location
, m2treelib_get_rvalue (location
, varset
, type
, is_lvalue
),
648 m2expr_BuildSetNegate (
650 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
),
651 m2convert_ToWord (location
, index
), false),
656 tree p1
= m2treelib_get_set_address (location
, varset
, is_lvalue
);
657 /* Calculate the index from the first bit. */
659 /* Which word do we need to fetch? */
660 tree word_index
= m2expr_BuildDivTrunc (
661 location
, index
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
), false);
662 /* Calculate the bit in this word. */
663 tree offset_into_word
= m2expr_BuildModTrunc (
664 location
, index
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
), false);
668 /* Calculate the address of the word we are interested in. */
669 p1
= m2expr_BuildAddAddress (
670 location
, m2convert_convertToPtr (location
, p1
),
672 location
, word_index
,
673 m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
),
676 v1
= m2expr_BuildLogicalAnd (
678 m2expr_BuildIndirect (location
, p1
, m2type_GetBitsetType ()),
679 m2expr_BuildSetNegate (
681 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
),
682 m2convert_ToWord (location
, offset_into_word
),
687 /* Set bit offset_into_word within the word pointer at by p1. */
688 m2statement_BuildAssignmentTree (
690 m2expr_BuildIndirect (location
, p1
, m2type_GetBitsetType ()),
691 m2convert_ToBitset (location
, v1
));
695 /* BuildIncludeVarConst - builds the INCL(op1, 1<<op2) operation for
696 a small sets. Large sets call this routine to include the bit in
697 the particular word. op2 is a constant. */
700 m2statement_BuildIncludeVarConst (location_t location
, tree type
, tree op1
,
701 tree op2
, bool is_lvalue
, int fieldno
)
703 tree size
= m2expr_GetSizeOf (location
, type
);
705 m2assert_AssertLocation (location
);
706 ASSERT_BOOL (is_lvalue
);
707 if (m2expr_CompareTrees (
708 size
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
))
711 /* Small set size <= TSIZE(WORD). */
712 m2statement_BuildAssignmentTree (
713 location
, m2treelib_get_rvalue (location
, op1
, type
, is_lvalue
),
714 m2expr_BuildLogicalOr (
715 location
, m2treelib_get_rvalue (location
, op1
, type
, is_lvalue
),
716 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
),
717 m2convert_ToWord (location
, op2
), false),
722 tree fieldlist
= TYPE_FIELDS (type
);
725 for (field
= fieldlist
; (field
!= NULL
) && (fieldno
> 0);
726 field
= TREE_CHAIN (field
))
729 m2statement_BuildAssignmentTree (
731 /* Would like to use: m2expr_BuildComponentRef (location, p, field)
732 but strangely we have to take the address of the field and
733 dereference it to satify the gimplifier. See
734 testsuite/gm2/pim/pass/timeio?.mod for testcases. */
735 m2treelib_get_set_field_des (location
, op1
, field
),
736 m2expr_BuildLogicalOr (
737 location
, m2treelib_get_set_field_rhs (location
, op1
, field
),
738 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
),
739 m2convert_ToWord (location
, op2
), false),
744 /* BuildIncludeVarVar - builds the INCL(varset, 1<<varel) operation
745 for a small and large sets. op2 is a variable. */
748 m2statement_BuildIncludeVarVar (location_t location
, tree type
, tree varset
,
749 tree varel
, bool is_lvalue
, tree low
)
751 tree size
= m2expr_GetSizeOf (location
, type
);
753 m2assert_AssertLocation (location
);
754 ASSERT_BOOL (is_lvalue
);
755 /* Calculate the index from the first bit, ie bit 0 represents low value. */
757 = m2expr_BuildSub (location
, m2convert_ToInteger (location
, varel
),
758 m2convert_ToInteger (location
, low
), false);
759 tree indexw
= m2convert_ToWord (location
, index
);
761 if (m2expr_CompareTrees (
762 size
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
))
764 /* Small set size <= TSIZE(WORD). */
765 m2statement_BuildAssignmentTree (
766 location
, m2treelib_get_rvalue (location
, varset
, type
, is_lvalue
),
769 m2expr_BuildLogicalOr (
771 m2treelib_get_rvalue (location
, varset
, type
, is_lvalue
),
772 m2expr_BuildLSL (location
, m2expr_GetWordOne (location
),
777 tree p1
= m2treelib_get_set_address (location
, varset
, is_lvalue
);
778 /* Which word do we need to fetch? */
779 tree word_index
= m2expr_BuildDivTrunc (
780 location
, index
, m2decl_BuildIntegerConstant (SET_WORD_SIZE
), false);
781 /* Calculate the bit in this word. */
782 tree offset_into_word
= m2convert_BuildConvert (
783 location
, m2type_GetWordType (),
784 m2expr_BuildModTrunc (location
, index
,
785 m2decl_BuildIntegerConstant (SET_WORD_SIZE
),
790 /* Calculate the address of the word we are interested in. */
791 p1
= m2expr_BuildAddAddress (
792 location
, m2convert_convertToPtr (location
, p1
),
794 location
, word_index
,
795 m2decl_BuildIntegerConstant (SET_WORD_SIZE
/ BITS_PER_UNIT
),
797 v1
= m2expr_BuildLogicalOr (
799 m2expr_BuildIndirect (location
, p1
, m2type_GetBitsetType ()),
800 m2convert_ToBitset (location
,
801 m2expr_BuildLSL (location
,
802 m2expr_GetWordOne (location
),
803 offset_into_word
, false)),
806 /* Set bit offset_into_word within the word pointer at by p1. */
807 m2statement_BuildAssignmentTree (
809 m2expr_BuildIndirect (location
, p1
, m2type_GetBitsetType ()),
810 m2convert_ToBitset (location
, v1
));
814 /* BuildStart - creates a module initialization function. We make
815 this function public if it is not an inner module. The linker
816 will create a call list for all linked modules which determines
817 the initialization sequence for all modules. */
820 m2statement_BuildStart (location_t location
, char *name
, bool inner_module
)
825 m2assert_AssertLocation (location
);
826 /* The function type depends on the return type and type of args. */
827 fntype
= build_function_type (integer_type_node
, NULL_TREE
);
828 fndecl
= build_decl (location
, FUNCTION_DECL
, get_identifier (name
), fntype
);
830 DECL_EXTERNAL (fndecl
) = 0;
832 TREE_PUBLIC (fndecl
) = 0;
834 TREE_PUBLIC (fndecl
) = 1;
836 TREE_STATIC (fndecl
) = 1;
838 = build_decl (location
, RESULT_DECL
, NULL_TREE
, integer_type_node
);
839 DECL_CONTEXT (DECL_RESULT (fndecl
)) = fndecl
;
841 /* Prevent the optimizer from removing it if it is public. */
842 if (TREE_PUBLIC (fndecl
))
843 gm2_mark_addressable (fndecl
);
845 m2statement_BuildStartFunctionCode (location
, fndecl
, !inner_module
,
850 /* BuildEnd - complete the initialization function for this module. */
853 m2statement_BuildEnd (location_t location
, tree fndecl
, bool nested
)
855 m2statement_BuildEndFunctionCode (location
, fndecl
, nested
);
856 current_function_decl
= NULL
;
860 /* BuildCallInner - call the inner module function. It has no
861 parameters and no return value. */
864 m2statement_BuildCallInner (location_t location
, tree fndecl
)
866 m2assert_AssertLocation (location
);
867 param_list
= NULL_TREE
;
869 m2statement_BuildProcedureCallTree (location
, fndecl
, NULL_TREE
));
873 /* BuildIfThenDoEnd - returns a tree which will only execute
874 statement, s, if, condition, is true. */
877 m2statement_BuildIfThenDoEnd (tree condition
, tree then_block
)
879 if (then_block
== NULL_TREE
)
882 return fold_build3 (COND_EXPR
, void_type_node
, condition
, then_block
,
886 /* BuildIfThenElseEnd - returns a tree which will execute then_block
887 or else_block depending upon, condition. */
890 m2statement_BuildIfThenElseEnd (tree condition
, tree then_block
,
893 if (then_block
== NULL_TREE
)
896 return fold_build3 (COND_EXPR
, void_type_node
, condition
, then_block
,
900 /* BuildReturnValueCode - generates the code associated with: RETURN(
904 m2statement_BuildReturnValueCode (location_t location
, tree fndecl
, tree value
)
909 m2assert_AssertLocation (location
);
911 MODIFY_EXPR
, TREE_TYPE (DECL_RESULT (fndecl
)), DECL_RESULT (fndecl
),
912 m2convert_BuildConvert (
913 location
, m2tree_skip_type_decl (TREE_TYPE (DECL_RESULT (fndecl
))),
916 ret_stmt
= build_stmt (location
, RETURN_EXPR
, t
);
917 add_stmt (location
, ret_stmt
);
920 /* DoJump - jump to the appropriate label depending whether result of
921 the expression is true or false. */
924 m2statement_DoJump (location_t location
, tree exp
, char *falselabel
,
929 m2assert_AssertLocation (location
);
930 if (TREE_CODE (TREE_TYPE (exp
)) != BOOLEAN_TYPE
)
931 exp
= convert_loc (location
, m2type_GetBooleanType (), exp
);
933 if ((falselabel
!= NULL
) && (truelabel
== NULL
))
935 m2block_push_statement_list (m2block_begin_statement_list ());
937 m2statement_BuildGoto (location
, falselabel
);
938 c
= build3 (COND_EXPR
, void_type_node
, exp
,
939 m2block_pop_statement_list (),
942 else if ((falselabel
== NULL
) && (truelabel
!= NULL
))
944 m2block_push_statement_list (m2block_begin_statement_list ());
946 m2statement_BuildGoto (location
, truelabel
);
947 c
= build3 (COND_EXPR
, void_type_node
, exp
,
948 m2block_pop_statement_list (),
952 error_at (location
, "expecting one and only one label to be declared");
954 add_stmt (location
, c
);
957 #include "gt-m2-m2statement.h"