Line data Source code
1 : /* m2statement.cc provides an interface to GCC statement trees.
2 :
3 : Copyright (C) 2012-2026 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 : #include "../gm2-lang.h"
25 : #include "../m2-tree.h"
26 :
27 : /* Prototypes. */
28 :
29 : #define m2statement_c
30 : #include "m2assert.h"
31 : #include "m2block.h"
32 : #include "m2decl.h"
33 : #include "m2expr.h"
34 : #include "m2statement.h"
35 : #include "m2tree.h"
36 : #include "m2treelib.h"
37 : #include "m2type.h"
38 : #include "m2convert.h"
39 : #include "m2builtins.h"
40 : #include "m2pp.h"
41 :
42 : static GTY (()) tree param_list = NULL_TREE; /* Ready for the next time we
43 : call/define a function. */
44 : static GTY (()) tree last_function = NULL_TREE;
45 :
46 :
47 : /* BuildStartFunctionCode generate function entry code. */
48 :
49 : void
50 105973 : m2statement_BuildStartFunctionCode (location_t location, tree fndecl,
51 : bool isexported, bool isinline)
52 : {
53 105973 : tree param_decl;
54 :
55 105973 : ASSERT_BOOL (isexported);
56 105973 : ASSERT_BOOL (isinline);
57 : /* Announce we are compiling this function. */
58 105973 : announce_function (fndecl);
59 :
60 : /* Set up to compile the function and enter it. */
61 :
62 105973 : DECL_INITIAL (fndecl) = NULL_TREE;
63 :
64 105973 : current_function_decl = fndecl;
65 105973 : m2block_pushFunctionScope (fndecl);
66 105973 : m2statement_SetBeginLocation (location);
67 :
68 105973 : ASSERT_BOOL ((cfun != NULL));
69 : /* Initialize the RTL code for the function. */
70 105973 : allocate_struct_function (fndecl, false);
71 : /* Begin the statement tree for this function. */
72 105973 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
73 :
74 : /* Set the context of these parameters to this function. */
75 282884 : for (param_decl = DECL_ARGUMENTS (fndecl); param_decl;
76 176911 : param_decl = TREE_CHAIN (param_decl))
77 176911 : DECL_CONTEXT (param_decl) = fndecl;
78 :
79 : /* This function exists in static storage. (This does not mean
80 : `static' in the C sense!) */
81 105973 : TREE_STATIC (fndecl) = 1;
82 105973 : TREE_PUBLIC (fndecl) = isexported;
83 : /* We could do better here by detecting ADR
84 : or type PROC used on this function. --fixme-- */
85 105973 : TREE_ADDRESSABLE (fndecl) = 1;
86 105973 : DECL_DECLARED_INLINE_P (fndecl) = 0; /* isinline; */
87 105973 : }
88 :
89 : /* BuildEndFunctionCode generates the function epilogue. */
90 :
91 : void
92 105961 : m2statement_BuildEndFunctionCode (location_t location, tree fndecl, bool nested)
93 : {
94 105961 : tree block = DECL_INITIAL (fndecl);
95 :
96 105961 : BLOCK_SUPERCONTEXT (block) = fndecl;
97 :
98 : /* Must mark the RESULT_DECL as being in this function. */
99 105961 : DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
100 :
101 : /* And attach it to the function. */
102 105961 : DECL_INITIAL (fndecl) = block;
103 :
104 105961 : m2block_finishFunctionCode (fndecl);
105 105961 : m2statement_SetEndLocation (location);
106 :
107 105961 : m2pp_dump_gimple (M2PP_DUMP_PRE_GENERICIZE, fndecl);
108 105961 : gm2_genericize (fndecl);
109 105961 : if (nested)
110 744 : (void)cgraph_node::get_create (fndecl);
111 : else
112 : {
113 105217 : m2pp_dump_gimple (M2PP_DUMP_POST_GENERICIZE, fndecl);
114 105217 : cgraph_node::finalize_function (fndecl, false);
115 : }
116 :
117 105961 : m2block_popFunctionScope ();
118 :
119 : /* We're leaving the context of this function, so zap cfun. It's
120 : still in DECL_STRUCT_FUNCTION, and we'll restore it in
121 : tree_rest_of_compilation. */
122 105961 : set_cfun (NULL);
123 105961 : current_function_decl = NULL;
124 105961 : }
125 :
126 : /* BuildPushFunctionContext pushes the current function context.
127 : Maps onto push_function_context in ../function.cc. */
128 :
129 : void
130 76755 : m2statement_BuildPushFunctionContext (void)
131 : {
132 76755 : push_function_context ();
133 76755 : }
134 :
135 : /* BuildPopFunctionContext pops the current function context. Maps
136 : onto pop_function_context in ../function.cc. */
137 :
138 : void
139 76755 : m2statement_BuildPopFunctionContext (void)
140 : {
141 76755 : pop_function_context ();
142 76755 : }
143 :
144 : void
145 182728 : m2statement_SetBeginLocation (location_t location)
146 : {
147 182728 : if (cfun != NULL)
148 0 : cfun->function_start_locus = location;
149 182728 : }
150 :
151 : void
152 105961 : m2statement_SetEndLocation (location_t location)
153 : {
154 105961 : if (cfun != NULL)
155 105961 : cfun->function_end_locus = location;
156 105961 : }
157 :
158 : /* copy_record_fields copy each record field from right to left. */
159 :
160 : static
161 : void
162 72 : copy_record_fields (location_t location, tree left, tree right)
163 : {
164 72 : unsigned int i;
165 72 : tree right_value;
166 72 : tree left_type = TREE_TYPE (left);
167 72 : vec<constructor_elt, va_gc> *values = CONSTRUCTOR_ELTS (right);
168 204 : FOR_EACH_CONSTRUCTOR_VALUE (values, i, right_value)
169 : {
170 132 : tree left_field = m2treelib_get_field_no (left_type, NULL_TREE, false, i);
171 132 : tree left_ref = m2expr_BuildComponentRef (location, left, left_field);
172 132 : m2statement_CopyByField (location, left_ref, right_value);
173 : }
174 72 : }
175 :
176 : /* copy_array copy each element of an array from array right to array left. */
177 :
178 : static
179 : void
180 0 : copy_array (location_t location, tree left, tree right)
181 : {
182 0 : unsigned int i;
183 0 : tree value;
184 0 : vec<constructor_elt, va_gc> *values = CONSTRUCTOR_ELTS (right);
185 0 : tree array_type = TREE_TYPE (left);
186 0 : tree index_type = TYPE_DOMAIN (array_type);
187 0 : tree elt_type = TREE_TYPE (array_type);
188 0 : tree low_indice = TYPE_MIN_VALUE (index_type);
189 0 : low_indice
190 0 : = m2convert_BuildConvert (location, index_type, low_indice, false);
191 0 : FOR_EACH_CONSTRUCTOR_VALUE (values, i, value)
192 : {
193 0 : tree idx = m2decl_BuildIntegerConstant (i);
194 0 : idx = m2convert_BuildConvert (location, index_type, idx, false);
195 0 : tree array_ref = build4_loc (location, ARRAY_REF, elt_type, left,
196 : idx, low_indice, NULL_TREE);
197 0 : m2statement_CopyByField (location, array_ref, value);
198 : }
199 0 : }
200 :
201 : /* copy_array cst into left using strncpy. */
202 :
203 : static
204 : void
205 84 : copy_strncpy (location_t location, tree left, tree cst)
206 : {
207 84 : tree result = m2builtins_BuiltinStrNCopy (location,
208 : m2expr_BuildAddr (location, left, false),
209 : m2expr_BuildAddr (location, cst, false),
210 84 : m2decl_BuildIntegerConstant (m2expr_StringLength (cst)));
211 84 : TREE_SIDE_EFFECTS (result) = true;
212 84 : TREE_USED (left) = true;
213 84 : TREE_USED (cst) = true;
214 84 : add_stmt (location, result);
215 84 : }
216 :
217 : /* copy_memcpy copy right into left using builtin_memcpy. */
218 :
219 : static
220 : void
221 0 : copy_memcpy (location_t location, tree left, tree right)
222 : {
223 0 : tree result = m2builtins_BuiltinMemCopy (location,
224 : m2expr_BuildAddr (location, left, false),
225 : m2expr_BuildAddr (location, right, false),
226 : m2expr_GetSizeOf (location, left));
227 0 : TREE_SIDE_EFFECTS (result) = true;
228 0 : TREE_USED (left) = true;
229 0 : TREE_USED (right) = true;
230 0 : add_stmt (location, result);
231 0 : }
232 :
233 : /* CopyByField_Lower copy right to left using memcpy for unions,
234 : strncpy for string cst, field assignment for records,
235 : array element assignment for array constructors. For all
236 : other types it uses BuildAssignmentStatement. */
237 :
238 : static
239 : void
240 156 : CopyByField_Lower (location_t location,
241 : tree left, tree right)
242 : {
243 156 : tree left_type = TREE_TYPE (left);
244 156 : enum tree_code right_code = TREE_CODE (right);
245 156 : enum tree_code left_code = TREE_CODE (left_type);
246 :
247 156 : if (left_code == RECORD_TYPE && right_code == CONSTRUCTOR)
248 72 : copy_record_fields (location, left, right);
249 84 : else if (left_code == ARRAY_TYPE && right_code == CONSTRUCTOR)
250 0 : copy_array (location, left, right);
251 84 : else if (left_code == UNION_TYPE && right_code == CONSTRUCTOR)
252 0 : copy_memcpy (location, left, right);
253 84 : else if (right_code == STRING_CST)
254 84 : copy_strncpy (location, left, right);
255 : else
256 0 : m2statement_BuildAssignmentStatement (location, left, right);
257 156 : }
258 :
259 : /* CopyByField recursively checks each field to ensure GCC
260 : type equivalence and if so it uses assignment.
261 : Otherwise use strncpy or memcpy depending upon type. */
262 :
263 : void
264 204 : m2statement_CopyByField (location_t location, tree des, tree expr)
265 : {
266 204 : if (m2type_IsGccStrictTypeEquivalent (des, expr))
267 48 : m2statement_BuildAssignmentStatement (location, des, expr);
268 : else
269 156 : CopyByField_Lower (location, des, expr);
270 204 : }
271 :
272 : /* BuildAssignmentTree builds the assignment of, des, and, expr.
273 : It returns, des. */
274 :
275 : tree
276 683718 : m2statement_BuildAssignmentTree (location_t location, tree des, tree expr)
277 : {
278 683718 : tree result;
279 :
280 683718 : m2assert_AssertLocation (location);
281 1378560 : STRIP_TYPE_NOPS (expr);
282 :
283 683718 : if (TREE_CODE (expr) == FUNCTION_DECL)
284 672 : result = build2 (MODIFY_EXPR, TREE_TYPE (des), des,
285 : m2expr_BuildAddr (location, expr, false));
286 : else
287 : {
288 683046 : gcc_assert (TREE_CODE (TREE_TYPE (des)) != TYPE_DECL);
289 683046 : if (TREE_TYPE (expr) == TREE_TYPE (des))
290 410699 : result = build2 (MODIFY_EXPR, TREE_TYPE (des), des, expr);
291 : else
292 544694 : result = build2 (
293 272347 : MODIFY_EXPR, TREE_TYPE (des), des,
294 272347 : m2convert_BuildConvert (location, TREE_TYPE (des), expr, false));
295 : }
296 :
297 683718 : TREE_SIDE_EFFECTS (result) = true;
298 683718 : TREE_USED (des) = true;
299 683718 : TREE_USED (expr) = true;
300 683718 : add_stmt (location, result);
301 683718 : return des;
302 : }
303 :
304 : /* BuildAssignmentStatement builds the assignment of, des, and, expr. */
305 :
306 : void
307 682674 : m2statement_BuildAssignmentStatement (location_t location, tree des, tree expr)
308 : {
309 682674 : m2statement_BuildAssignmentTree (location, des, expr);
310 682674 : }
311 :
312 : /* BuildGoto builds a goto operation. */
313 :
314 : void
315 121886 : m2statement_BuildGoto (location_t location, char *name)
316 : {
317 121886 : tree label = m2block_getLabel (location, name);
318 :
319 121886 : m2assert_AssertLocation (location);
320 121886 : TREE_USED (label) = true;
321 121886 : add_stmt (location, build1 (GOTO_EXPR, void_type_node, label));
322 121886 : }
323 :
324 : /* DeclareLabel create a label, name. */
325 :
326 : void
327 102806 : m2statement_DeclareLabel (location_t location, char *name)
328 : {
329 102806 : tree label = m2block_getLabel (location, name);
330 :
331 102806 : m2assert_AssertLocation (location);
332 102806 : add_stmt (location, build1 (LABEL_EXPR, void_type_node, label));
333 102806 : }
334 :
335 : /* BuildParam build a list of parameters, ready for a subsequent
336 : procedure call. */
337 :
338 : void
339 609034 : m2statement_BuildParam (location_t location, tree param)
340 : {
341 609034 : m2assert_AssertLocation (location);
342 :
343 609034 : TREE_USED (param) = true;
344 609034 : if (TREE_CODE (param) == FUNCTION_DECL)
345 43702 : param = m2expr_BuildAddr (location, param, false);
346 :
347 609034 : param_list = chainon (build_tree_list (NULL_TREE, param), param_list);
348 609034 : }
349 :
350 : /* nCount return the number of chained tree nodes in list, t. */
351 :
352 : static int
353 230028 : nCount (tree t)
354 : {
355 230028 : int i = 0;
356 :
357 837408 : while (t != NULL)
358 : {
359 607380 : i++;
360 607380 : t = TREE_CHAIN (t);
361 : }
362 230028 : return i;
363 : }
364 :
365 : /* BuildProcedureCallTree creates a procedure call from a procedure
366 : and parameter list and the return type, rettype. */
367 :
368 : tree
369 229304 : m2statement_BuildProcedureCallTree (location_t location, tree procedure,
370 : tree rettype)
371 : {
372 229304 : tree functype = TREE_TYPE (procedure);
373 229304 : tree funcptr = build1 (ADDR_EXPR, build_pointer_type (functype), procedure);
374 229304 : tree call;
375 229304 : int n = nCount (param_list);
376 229304 : tree *argarray = XALLOCAVEC (tree, n);
377 229304 : tree t = param_list;
378 229304 : int i;
379 :
380 229304 : m2assert_AssertLocation (location);
381 229304 : ASSERT_CONDITION (
382 : last_function
383 229304 : == NULL_TREE); /* Previous function value has not been collected. */
384 229304 : TREE_USED (procedure) = true;
385 :
386 835518 : for (i = 0; i < n; i++)
387 : {
388 606214 : argarray[i] = TREE_VALUE (t);
389 606214 : t = TREE_CHAIN (t);
390 : }
391 :
392 229304 : if (rettype == NULL_TREE)
393 : {
394 156603 : rettype = void_type_node;
395 156603 : call = build_call_array_loc (location, rettype, funcptr, n, argarray);
396 156603 : TREE_USED (call) = true;
397 156603 : TREE_SIDE_EFFECTS (call) = true;
398 :
399 : #if defined(DEBUG_PROCEDURE_CALLS)
400 : fprintf (stderr, "built the modula-2 call, here is the tree\n");
401 : fflush (stderr);
402 : debug_tree (call);
403 : #endif
404 :
405 156603 : param_list
406 156603 : = NULL_TREE; /* Ready for the next time we call a procedure. */
407 156603 : last_function = NULL_TREE;
408 156603 : return call;
409 : }
410 : else
411 : {
412 72701 : last_function = build_call_array_loc (
413 : location, m2tree_skip_type_decl (rettype), funcptr, n, argarray);
414 72701 : TREE_USED (last_function) = true;
415 72701 : TREE_SIDE_EFFECTS (last_function) = true;
416 72701 : param_list
417 72701 : = NULL_TREE; /* Ready for the next time we call a procedure. */
418 72701 : return last_function;
419 : }
420 : }
421 :
422 : /* BuildIndirectProcedureCallTree creates a procedure call from a
423 : procedure and parameter list and the return type, rettype. */
424 :
425 : tree
426 724 : m2statement_BuildIndirectProcedureCallTree (location_t location,
427 : tree procedure, tree rettype)
428 : {
429 724 : tree call;
430 724 : int n = nCount (param_list);
431 724 : tree *argarray = XALLOCAVEC (tree, n);
432 724 : tree t = param_list;
433 724 : int i;
434 :
435 724 : m2assert_AssertLocation (location);
436 724 : TREE_USED (procedure) = true;
437 724 : TREE_SIDE_EFFECTS (procedure) = true;
438 :
439 1890 : for (i = 0; i < n; i++)
440 : {
441 1166 : argarray[i] = TREE_VALUE (t);
442 1166 : t = TREE_CHAIN (t);
443 : }
444 :
445 724 : if (rettype == NULL_TREE)
446 : {
447 636 : rettype = void_type_node;
448 636 : call = build_call_array_loc (location, rettype, procedure, n, argarray);
449 636 : TREE_USED (call) = true;
450 636 : TREE_SIDE_EFFECTS (call) = true;
451 :
452 : #if defined(DEBUG_PROCEDURE_CALLS)
453 : fprintf (stderr, "built the modula-2 call, here is the tree\n");
454 : fflush (stderr);
455 : debug_tree (call);
456 : #endif
457 :
458 636 : last_function = NULL_TREE;
459 636 : param_list
460 636 : = NULL_TREE; /* Ready for the next time we call a procedure. */
461 636 : return call;
462 : }
463 : else
464 : {
465 88 : last_function = build_call_array_loc (
466 : location, m2tree_skip_type_decl (rettype), procedure, n, argarray);
467 88 : TREE_USED (last_function) = true;
468 88 : TREE_SIDE_EFFECTS (last_function) = true;
469 88 : param_list
470 88 : = NULL_TREE; /* Ready for the next time we call a procedure. */
471 88 : return last_function;
472 : }
473 : }
474 :
475 :
476 : /* BuildBuiltinCallTree calls the builtin procedure. */
477 :
478 : tree
479 1146 : m2statement_BuildBuiltinCallTree (tree func)
480 : {
481 1146 : TREE_USED (func) = true;
482 1146 : TREE_SIDE_EFFECTS (func) = true;
483 1146 : param_list
484 1146 : = NULL_TREE; /* Ready for the next time we call a procedure. */
485 1146 : return func;
486 : }
487 :
488 :
489 : /* BuildFunctValue generates code for
490 : value := last_function (foobar). */
491 :
492 : tree
493 85797 : m2statement_BuildFunctValue (location_t location, tree value)
494 : {
495 85797 : tree assign
496 85797 : = m2treelib_build_modify_expr (location, value, NOP_EXPR, last_function);
497 :
498 85797 : m2assert_AssertLocation (location);
499 85797 : ASSERT_CONDITION (
500 : last_function
501 85797 : != NULL_TREE); /* No value available, possible used before. */
502 :
503 85797 : TREE_SIDE_EFFECTS (assign) = true;
504 85797 : TREE_USED (assign) = true;
505 85797 : TREE_USED (value) = true;
506 85797 : last_function = NULL_TREE;
507 85797 : return assign;
508 : }
509 :
510 : /* BuildCall2 builds a tree representing: function (arg1, arg2). */
511 :
512 : tree
513 0 : m2statement_BuildCall2 (location_t location, tree function, tree rettype,
514 : tree arg1, tree arg2)
515 : {
516 0 : m2assert_AssertLocation (location);
517 0 : ASSERT_CONDITION (param_list == NULL_TREE);
518 :
519 0 : param_list = chainon (build_tree_list (NULL_TREE, arg2), param_list);
520 0 : param_list = chainon (build_tree_list (NULL_TREE, arg1), param_list);
521 0 : return m2statement_BuildProcedureCallTree (location, function, rettype);
522 : }
523 :
524 : /* BuildCall3 builds a tree representing: function (arg1, arg2, arg3). */
525 :
526 : tree
527 0 : m2statement_BuildCall3 (location_t location, tree function, tree rettype,
528 : tree arg1, tree arg2, tree arg3)
529 : {
530 0 : m2assert_AssertLocation (location);
531 0 : ASSERT_CONDITION (param_list == NULL_TREE);
532 :
533 0 : param_list = chainon (build_tree_list (NULL_TREE, arg3), param_list);
534 0 : param_list = chainon (build_tree_list (NULL_TREE, arg2), param_list);
535 0 : param_list = chainon (build_tree_list (NULL_TREE, arg1), param_list);
536 0 : return m2statement_BuildProcedureCallTree (location, function, rettype);
537 : }
538 :
539 : /* BuildFunctionCallTree creates a procedure function call from
540 : a procedure and parameter list and the return type, rettype.
541 : No tree is returned as the tree is held in the last_function global
542 : variable. It is expected the BuildFunctValue is to be called after
543 : a call to BuildFunctionCallTree. */
544 :
545 : void
546 5720 : m2statement_BuildFunctionCallTree (location_t location, tree procedure,
547 : tree rettype)
548 : {
549 5720 : m2statement_BuildProcedureCallTree (location, procedure, rettype);
550 5720 : }
551 :
552 : /* SetLastFunction assigns last_function to, t. */
553 :
554 : void
555 222691 : m2statement_SetLastFunction (tree t)
556 : {
557 222691 : last_function = t;
558 222691 : }
559 :
560 : /* SetParamList assigns param_list to, t. */
561 :
562 : void
563 1152 : m2statement_SetParamList (tree t)
564 : {
565 1152 : param_list = t;
566 1152 : }
567 :
568 : /* GetLastFunction returns, last_function. */
569 :
570 : tree
571 0 : m2statement_GetLastFunction (void)
572 : {
573 0 : return last_function;
574 : }
575 :
576 : /* GetParamList returns, param_list. */
577 :
578 : tree
579 1152 : m2statement_GetParamList (void)
580 : {
581 1152 : return param_list;
582 : }
583 :
584 : /* GetCurrentFunction returns the current_function. */
585 :
586 : tree
587 0 : m2statement_GetCurrentFunction (void)
588 : {
589 0 : return current_function_decl;
590 : }
591 :
592 : /* GetParamTree return parameter, i. */
593 :
594 : tree
595 0 : m2statement_GetParamTree (tree call, unsigned int i)
596 : {
597 0 : return CALL_EXPR_ARG (call, i);
598 : }
599 :
600 : /* BuildTryFinally returns a TRY_FINALL_EXPR with the call and
601 : cleanups attached. */
602 :
603 : tree
604 0 : m2statement_BuildTryFinally (location_t location, tree call, tree cleanups)
605 : {
606 0 : return build_stmt (location, TRY_FINALLY_EXPR, call, cleanups);
607 : }
608 :
609 : /* BuildCleanUp return a CLEANUP_POINT_EXPR which will clobber,
610 : param. */
611 :
612 : tree
613 0 : m2statement_BuildCleanUp (tree param)
614 : {
615 0 : tree clobber = build_constructor (TREE_TYPE (param), NULL);
616 0 : TREE_THIS_VOLATILE (clobber) = 1;
617 0 : return build2 (MODIFY_EXPR, TREE_TYPE (param), param, clobber);
618 : }
619 :
620 : /* BuildAsm generates an inline assembler instruction. */
621 :
622 : void
623 27 : m2statement_BuildAsm (location_t location, tree instr, bool isVolatile,
624 : bool isSimple, tree inputs, tree outputs, tree trash,
625 : tree labels)
626 : {
627 27 : tree string = resolve_asm_operand_names (instr, outputs, inputs, labels);
628 27 : tree args = build_stmt (location, ASM_EXPR, string, outputs, inputs, trash,
629 : labels);
630 :
631 27 : m2assert_AssertLocation (location);
632 :
633 : /* ASM statements without outputs, including simple ones, are treated
634 : as volatile. */
635 27 : ASM_BASIC_P (args) = isSimple;
636 27 : ASM_VOLATILE_P (args) = isVolatile;
637 :
638 27 : add_stmt (location, args);
639 27 : }
640 :
641 : /* BuildStart creates a module initialization function. We make
642 : this function public if it is not an inner module. The linker
643 : will create a call list for all linked modules which determines
644 : the initialization sequence for all modules. */
645 :
646 : tree
647 0 : m2statement_BuildStart (location_t location, char *name, bool inner_module)
648 : {
649 0 : tree fntype;
650 0 : tree fndecl;
651 :
652 0 : m2assert_AssertLocation (location);
653 : /* The function type depends on the return type and type of args. */
654 0 : fntype = build_function_type (integer_type_node, NULL_TREE);
655 0 : fndecl = build_decl (location, FUNCTION_DECL, get_identifier (name), fntype);
656 :
657 0 : DECL_EXTERNAL (fndecl) = 0;
658 0 : if (inner_module)
659 0 : TREE_PUBLIC (fndecl) = 0;
660 : else
661 0 : TREE_PUBLIC (fndecl) = 1;
662 :
663 0 : TREE_STATIC (fndecl) = 1;
664 0 : DECL_RESULT (fndecl)
665 0 : = build_decl (location, RESULT_DECL, NULL_TREE, integer_type_node);
666 0 : DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
667 :
668 : /* Prevent the optimizer from removing it if it is public. */
669 0 : if (TREE_PUBLIC (fndecl))
670 0 : gm2_mark_addressable (fndecl);
671 :
672 0 : m2statement_BuildStartFunctionCode (location, fndecl, !inner_module,
673 : inner_module);
674 0 : return fndecl;
675 : }
676 :
677 : /* BuildEnd complete the initialization function for this module. */
678 :
679 : void
680 0 : m2statement_BuildEnd (location_t location, tree fndecl, bool nested)
681 : {
682 0 : m2statement_BuildEndFunctionCode (location, fndecl, nested);
683 0 : current_function_decl = NULL;
684 0 : set_cfun (NULL);
685 0 : }
686 :
687 : /* BuildCallInner call the inner module function. It has no
688 : parameters and no return value. */
689 :
690 : void
691 672 : m2statement_BuildCallInner (location_t location, tree fndecl)
692 : {
693 672 : m2assert_AssertLocation (location);
694 672 : param_list = NULL_TREE;
695 672 : add_stmt (location,
696 : m2statement_BuildProcedureCallTree (location, fndecl, NULL_TREE));
697 672 : }
698 :
699 :
700 : /* BuildIfThenDoEnd returns a tree which will only execute
701 : statement, s, if, condition, is true. */
702 :
703 : tree
704 115700 : m2statement_BuildIfThenDoEnd (tree condition, tree then_block)
705 : {
706 115700 : if (then_block == NULL_TREE)
707 : return NULL_TREE;
708 : else
709 16843 : return fold_build3 (COND_EXPR, void_type_node, condition, then_block,
710 : alloc_stmt_list ());
711 : }
712 :
713 : /* BuildIfThenElseEnd returns a tree which will execute then_block
714 : or else_block depending upon, condition. */
715 :
716 : tree
717 6768 : m2statement_BuildIfThenElseEnd (tree condition, tree then_block,
718 : tree else_block)
719 : {
720 6768 : if (then_block == NULL_TREE)
721 : return NULL_TREE;
722 : else
723 1188 : return fold_build3 (COND_EXPR, void_type_node, condition, then_block,
724 : else_block);
725 : }
726 :
727 : /* BuildReturnValueCode generates the code associated with:
728 : RETURN ( value ). */
729 :
730 : void
731 27443 : m2statement_BuildReturnValueCode (location_t location, tree fndecl, tree value)
732 : {
733 27443 : tree ret_stmt;
734 27443 : tree t;
735 :
736 27443 : m2assert_AssertLocation (location);
737 82329 : t = build2 (
738 27443 : MODIFY_EXPR, TREE_TYPE (DECL_RESULT (fndecl)), DECL_RESULT (fndecl),
739 : m2convert_BuildConvert (
740 27443 : location, m2tree_skip_type_decl (TREE_TYPE (DECL_RESULT (fndecl))),
741 : value, false));
742 :
743 27443 : ret_stmt = build_stmt (location, RETURN_EXPR, t);
744 27443 : add_stmt (location, ret_stmt);
745 27443 : }
746 :
747 : /* IfExprJump if expr then jump to the label. */
748 :
749 : void
750 76689 : m2statement_IfExprJump (location_t location, tree exp, char *label)
751 : {
752 76689 : tree if_jump;
753 :
754 76689 : m2assert_AssertLocation (location);
755 76689 : if (TREE_CODE (TREE_TYPE (exp)) != BOOLEAN_TYPE)
756 76671 : exp = convert_loc (location, m2type_GetBooleanType (), exp);
757 :
758 76689 : m2block_push_statement_list (m2block_begin_statement_list ());
759 76689 : m2statement_BuildGoto (location, label);
760 76689 : if_jump = build3 (COND_EXPR, void_type_node, exp,
761 : m2block_pop_statement_list (),
762 : alloc_stmt_list ());
763 76689 : add_stmt (location, if_jump);
764 76689 : }
765 :
766 :
767 : /* IfBitInSetJump if bit in set jump to label. */
768 :
769 : void
770 0 : m2statement_IfBitInSetJump (location_t location, bool invertCondition,
771 : tree setvalue, tree bit, char *label)
772 : {
773 0 : tree condition;
774 :
775 0 : condition = m2expr_BuildNotEqualTo (location,
776 : m2expr_BuildLogicalAnd (location,
777 : m2expr_BuildLSL (location,
778 : m2expr_GetWordOne (location),
779 : bit, false),
780 : setvalue),
781 : m2expr_GetWordZero (location)) ;
782 0 : if (invertCondition)
783 0 : condition = m2expr_BuildEqualTo (location, condition,
784 : m2type_GetBooleanFalse ());
785 0 : m2statement_IfExprJump (location, condition, label);
786 0 : }
787 :
788 : #include "gt-m2-m2statement.h"
|