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 110259 : m2statement_BuildStartFunctionCode (location_t location, tree fndecl,
51 : bool isexported, bool isinline)
52 : {
53 110259 : tree param_decl;
54 :
55 110259 : ASSERT_BOOL (isexported);
56 110259 : ASSERT_BOOL (isinline);
57 : /* Announce we are compiling this function. */
58 110259 : announce_function (fndecl);
59 :
60 : /* Set up to compile the function and enter it. */
61 :
62 110259 : DECL_INITIAL (fndecl) = NULL_TREE;
63 :
64 110259 : current_function_decl = fndecl;
65 110259 : m2block_pushFunctionScope (fndecl);
66 110259 : m2statement_SetBeginLocation (location);
67 :
68 110259 : ASSERT_BOOL ((cfun != NULL));
69 : /* Initialize the RTL code for the function. */
70 110259 : allocate_struct_function (fndecl, false);
71 : /* Begin the statement tree for this function. */
72 110259 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
73 :
74 : /* Set the context of these parameters to this function. */
75 293736 : for (param_decl = DECL_ARGUMENTS (fndecl); param_decl;
76 183477 : param_decl = TREE_CHAIN (param_decl))
77 183477 : DECL_CONTEXT (param_decl) = fndecl;
78 :
79 : /* This function exists in static storage. (This does not mean
80 : `static' in the C sense!) */
81 110259 : TREE_STATIC (fndecl) = 1;
82 110259 : TREE_PUBLIC (fndecl) = isexported;
83 : /* We could do better here by detecting ADR
84 : or type PROC used on this function. --fixme-- */
85 110259 : TREE_ADDRESSABLE (fndecl) = 1;
86 110259 : DECL_DECLARED_INLINE_P (fndecl) = 0; /* isinline; */
87 110259 : }
88 :
89 : /* BuildEndFunctionCode generates the function epilogue. */
90 :
91 : void
92 110247 : m2statement_BuildEndFunctionCode (location_t location, tree fndecl, bool nested)
93 : {
94 110247 : tree block = DECL_INITIAL (fndecl);
95 :
96 110247 : BLOCK_SUPERCONTEXT (block) = fndecl;
97 :
98 : /* Must mark the RESULT_DECL as being in this function. */
99 110247 : DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
100 :
101 : /* And attach it to the function. */
102 110247 : DECL_INITIAL (fndecl) = block;
103 :
104 110247 : m2block_finishFunctionCode (fndecl);
105 110247 : m2statement_SetEndLocation (location);
106 :
107 110247 : m2pp_dump_gimple (M2PP_DUMP_PRE_GENERICIZE, fndecl);
108 110247 : gm2_genericize (fndecl);
109 110247 : if (nested)
110 744 : (void)cgraph_node::get_create (fndecl);
111 : else
112 : {
113 109503 : m2pp_dump_gimple (M2PP_DUMP_POST_GENERICIZE, fndecl);
114 109503 : cgraph_node::finalize_function (fndecl, false);
115 : }
116 :
117 110247 : 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 110247 : set_cfun (NULL);
123 110247 : current_function_decl = NULL;
124 110247 : }
125 :
126 : /* BuildPushFunctionContext pushes the current function context.
127 : Maps onto push_function_context in ../function.cc. */
128 :
129 : void
130 79597 : m2statement_BuildPushFunctionContext (void)
131 : {
132 79597 : push_function_context ();
133 79597 : }
134 :
135 : /* BuildPopFunctionContext pops the current function context. Maps
136 : onto pop_function_context in ../function.cc. */
137 :
138 : void
139 79597 : m2statement_BuildPopFunctionContext (void)
140 : {
141 79597 : pop_function_context ();
142 79597 : }
143 :
144 : void
145 189856 : m2statement_SetBeginLocation (location_t location)
146 : {
147 189856 : if (cfun != NULL)
148 0 : cfun->function_start_locus = location;
149 189856 : }
150 :
151 : void
152 110247 : m2statement_SetEndLocation (location_t location)
153 : {
154 110247 : if (cfun != NULL)
155 110247 : cfun->function_end_locus = location;
156 110247 : }
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 : /* CopyMemcpy copy bytes from src into dest using builtin_memcpy. */
218 :
219 : void
220 2434 : m2statement_CopyMemcpy (location_t location, tree dest, tree src, tree bytes)
221 : {
222 2434 : tree addr_dest = m2expr_BuildAddr (location, dest, false);
223 2434 : tree result = m2builtins_BuiltinMemCopy (location,
224 : addr_dest,
225 : m2expr_BuildAddr (location, src, false),
226 : bytes);
227 2434 : TREE_SIDE_EFFECTS (result) = true;
228 2434 : TREE_USED (dest) = true;
229 2434 : TREE_USED (src) = true;
230 2434 : add_stmt (location, result);
231 2434 : }
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 : m2statement_CopyMemcpy (location, left, right,
253 : m2expr_GetSizeOf (location, left));
254 84 : else if (right_code == STRING_CST)
255 84 : copy_strncpy (location, left, right);
256 : else
257 0 : m2statement_BuildAssignmentStatement (location, left, right);
258 156 : }
259 :
260 : /* CopyByField recursively checks each field to ensure GCC
261 : type equivalence and if so it uses assignment.
262 : Otherwise use strncpy or memcpy depending upon type. */
263 :
264 : void
265 204 : m2statement_CopyByField (location_t location, tree des, tree expr)
266 : {
267 204 : if (m2type_IsGccStrictTypeEquivalent (des, expr))
268 48 : m2statement_BuildAssignmentStatement (location, des, expr);
269 : else
270 156 : CopyByField_Lower (location, des, expr);
271 204 : }
272 :
273 : /* BuildAssignmentTree builds the assignment of des and expr.
274 : It returns des. */
275 :
276 : void
277 703050 : m2statement_BuildAssignmentTree (location_t location, tree des, tree expr)
278 : {
279 703050 : tree result;
280 :
281 703050 : m2assert_AssertLocation (location);
282 1417298 : STRIP_TYPE_NOPS (expr);
283 :
284 703050 : if (TREE_CODE (expr) == FUNCTION_DECL)
285 672 : result = build2 (MODIFY_EXPR, TREE_TYPE (des), des,
286 : m2expr_BuildAddr (location, expr, false));
287 : else
288 : {
289 702378 : gcc_assert (TREE_CODE (TREE_TYPE (des)) != TYPE_DECL);
290 702378 : if ((TREE_CODE (expr) == CONSTRUCTOR)
291 702378 : && (TREE_CODE (TREE_TYPE (des)) == ARRAY_TYPE))
292 : {
293 1502 : m2statement_CopyMemcpy (location, des, expr,
294 : m2expr_GetSizeOf (location,
295 : m2type_GetTreeType (des)));
296 1502 : return;
297 : }
298 700876 : else if (TREE_TYPE (expr) == TREE_TYPE (des))
299 420431 : result = build2 (MODIFY_EXPR, TREE_TYPE (des), des, expr);
300 : else
301 560890 : result = build2 (
302 280445 : MODIFY_EXPR, TREE_TYPE (des), des,
303 280445 : m2convert_BuildConvert (location, TREE_TYPE (des), expr, false));
304 : }
305 :
306 701548 : TREE_SIDE_EFFECTS (result) = true;
307 701548 : TREE_USED (des) = true;
308 701548 : TREE_USED (expr) = true;
309 701548 : add_stmt (location, result);
310 : }
311 :
312 : /* BuildAssignmentStatement builds the assignment of des and expr. */
313 :
314 : void
315 702006 : m2statement_BuildAssignmentStatement (location_t location, tree des, tree expr)
316 : {
317 702006 : m2statement_BuildAssignmentTree (location, des, expr);
318 702006 : }
319 :
320 : /* BuildGoto builds a goto operation. */
321 :
322 : void
323 126638 : m2statement_BuildGoto (location_t location, char *name)
324 : {
325 126638 : tree label = m2block_getLabel (location, name);
326 :
327 126638 : m2assert_AssertLocation (location);
328 126638 : TREE_USED (label) = true;
329 126638 : add_stmt (location, build1 (GOTO_EXPR, void_type_node, label));
330 126638 : }
331 :
332 : /* DeclareLabel create a label, name. */
333 :
334 : void
335 106576 : m2statement_DeclareLabel (location_t location, char *name)
336 : {
337 106576 : tree label = m2block_getLabel (location, name);
338 :
339 106576 : m2assert_AssertLocation (location);
340 106576 : add_stmt (location, build1 (LABEL_EXPR, void_type_node, label));
341 106576 : }
342 :
343 : /* BuildParam build a list of parameters, ready for a subsequent
344 : procedure call. */
345 :
346 : void
347 628610 : m2statement_BuildParam (location_t location, tree param)
348 : {
349 628610 : m2assert_AssertLocation (location);
350 :
351 628610 : TREE_USED (param) = true;
352 628610 : if (TREE_CODE (param) == FUNCTION_DECL)
353 45882 : param = m2expr_BuildAddr (location, param, false);
354 :
355 628610 : param_list = chainon (build_tree_list (NULL_TREE, param), param_list);
356 628610 : }
357 :
358 : /* nCount return the number of chained tree nodes in list, t. */
359 :
360 : static int
361 237982 : nCount (tree t)
362 : {
363 237982 : int i = 0;
364 :
365 864938 : while (t != NULL)
366 : {
367 626956 : i++;
368 626956 : t = TREE_CHAIN (t);
369 : }
370 237982 : return i;
371 : }
372 :
373 : /* BuildProcedureCallTree creates a procedure call from a procedure
374 : and parameter list and the return type, rettype. */
375 :
376 : tree
377 237258 : m2statement_BuildProcedureCallTree (location_t location, tree procedure,
378 : tree rettype)
379 : {
380 237258 : tree functype = TREE_TYPE (procedure);
381 237258 : tree funcptr = build1 (ADDR_EXPR, build_pointer_type (functype), procedure);
382 237258 : tree call;
383 237258 : int n = nCount (param_list);
384 237258 : tree *argarray = XALLOCAVEC (tree, n);
385 237258 : tree t = param_list;
386 237258 : int i;
387 :
388 237258 : m2assert_AssertLocation (location);
389 237258 : ASSERT_CONDITION (
390 : last_function
391 237258 : == NULL_TREE); /* Previous function value has not been collected. */
392 237258 : TREE_USED (procedure) = true;
393 :
394 863048 : for (i = 0; i < n; i++)
395 : {
396 625790 : argarray[i] = TREE_VALUE (t);
397 625790 : t = TREE_CHAIN (t);
398 : }
399 :
400 237258 : if (rettype == NULL_TREE)
401 : {
402 162877 : rettype = void_type_node;
403 162877 : call = build_call_array_loc (location, rettype, funcptr, n, argarray);
404 162877 : TREE_USED (call) = true;
405 162877 : TREE_SIDE_EFFECTS (call) = true;
406 :
407 : #if defined(DEBUG_PROCEDURE_CALLS)
408 : fprintf (stderr, "built the modula-2 call, here is the tree\n");
409 : fflush (stderr);
410 : debug_tree (call);
411 : #endif
412 :
413 162877 : param_list
414 162877 : = NULL_TREE; /* Ready for the next time we call a procedure. */
415 162877 : last_function = NULL_TREE;
416 162877 : return call;
417 : }
418 : else
419 : {
420 74381 : last_function = build_call_array_loc (
421 : location, m2tree_skip_type_decl (rettype), funcptr, n, argarray);
422 74381 : TREE_USED (last_function) = true;
423 74381 : TREE_SIDE_EFFECTS (last_function) = true;
424 74381 : param_list
425 74381 : = NULL_TREE; /* Ready for the next time we call a procedure. */
426 74381 : return last_function;
427 : }
428 : }
429 :
430 : /* BuildIndirectProcedureCallTree creates a procedure call from a
431 : procedure and parameter list and the return type, rettype. */
432 :
433 : tree
434 724 : m2statement_BuildIndirectProcedureCallTree (location_t location,
435 : tree procedure, tree rettype)
436 : {
437 724 : tree call;
438 724 : int n = nCount (param_list);
439 724 : tree *argarray = XALLOCAVEC (tree, n);
440 724 : tree t = param_list;
441 724 : int i;
442 :
443 724 : m2assert_AssertLocation (location);
444 724 : TREE_USED (procedure) = true;
445 724 : TREE_SIDE_EFFECTS (procedure) = true;
446 :
447 1890 : for (i = 0; i < n; i++)
448 : {
449 1166 : argarray[i] = TREE_VALUE (t);
450 1166 : t = TREE_CHAIN (t);
451 : }
452 :
453 724 : if (rettype == NULL_TREE)
454 : {
455 636 : rettype = void_type_node;
456 636 : call = build_call_array_loc (location, rettype, procedure, n, argarray);
457 636 : TREE_USED (call) = true;
458 636 : TREE_SIDE_EFFECTS (call) = true;
459 :
460 : #if defined(DEBUG_PROCEDURE_CALLS)
461 : fprintf (stderr, "built the modula-2 call, here is the tree\n");
462 : fflush (stderr);
463 : debug_tree (call);
464 : #endif
465 :
466 636 : last_function = NULL_TREE;
467 636 : param_list
468 636 : = NULL_TREE; /* Ready for the next time we call a procedure. */
469 636 : return call;
470 : }
471 : else
472 : {
473 88 : last_function = build_call_array_loc (
474 : location, m2tree_skip_type_decl (rettype), procedure, n, argarray);
475 88 : TREE_USED (last_function) = true;
476 88 : TREE_SIDE_EFFECTS (last_function) = true;
477 88 : param_list
478 88 : = NULL_TREE; /* Ready for the next time we call a procedure. */
479 88 : return last_function;
480 : }
481 : }
482 :
483 :
484 : /* BuildBuiltinCallTree calls the builtin procedure. */
485 :
486 : tree
487 1146 : m2statement_BuildBuiltinCallTree (tree func)
488 : {
489 1146 : TREE_USED (func) = true;
490 1146 : TREE_SIDE_EFFECTS (func) = true;
491 1146 : param_list
492 1146 : = NULL_TREE; /* Ready for the next time we call a procedure. */
493 1146 : return func;
494 : }
495 :
496 :
497 : /* BuildFunctValue generates code for
498 : value := last_function (foobar). */
499 :
500 : tree
501 86693 : m2statement_BuildFunctValue (location_t location, tree value)
502 : {
503 86693 : tree assign
504 86693 : = m2treelib_build_modify_expr (location, value, NOP_EXPR, last_function);
505 :
506 86693 : m2assert_AssertLocation (location);
507 86693 : ASSERT_CONDITION (
508 : last_function
509 86693 : != NULL_TREE); /* No value available, possible used before. */
510 :
511 86693 : TREE_SIDE_EFFECTS (assign) = true;
512 86693 : TREE_USED (assign) = true;
513 86693 : TREE_USED (value) = true;
514 86693 : last_function = NULL_TREE;
515 86693 : return assign;
516 : }
517 :
518 : /* BuildCall2 builds a tree representing: function (arg1, arg2). */
519 :
520 : tree
521 0 : m2statement_BuildCall2 (location_t location, tree function, tree rettype,
522 : tree arg1, tree arg2)
523 : {
524 0 : m2assert_AssertLocation (location);
525 0 : ASSERT_CONDITION (param_list == NULL_TREE);
526 :
527 0 : param_list = chainon (build_tree_list (NULL_TREE, arg2), param_list);
528 0 : param_list = chainon (build_tree_list (NULL_TREE, arg1), param_list);
529 0 : return m2statement_BuildProcedureCallTree (location, function, rettype);
530 : }
531 :
532 : /* BuildCall3 builds a tree representing: function (arg1, arg2, arg3). */
533 :
534 : tree
535 0 : m2statement_BuildCall3 (location_t location, tree function, tree rettype,
536 : tree arg1, tree arg2, tree arg3)
537 : {
538 0 : m2assert_AssertLocation (location);
539 0 : ASSERT_CONDITION (param_list == NULL_TREE);
540 :
541 0 : param_list = chainon (build_tree_list (NULL_TREE, arg3), param_list);
542 0 : param_list = chainon (build_tree_list (NULL_TREE, arg2), param_list);
543 0 : param_list = chainon (build_tree_list (NULL_TREE, arg1), param_list);
544 0 : return m2statement_BuildProcedureCallTree (location, function, rettype);
545 : }
546 :
547 : /* BuildFunctionCallTree creates a procedure function call from
548 : a procedure and parameter list and the return type, rettype.
549 : No tree is returned as the tree is held in the last_function global
550 : variable. It is expected the BuildFunctValue is to be called after
551 : a call to BuildFunctionCallTree. */
552 :
553 : void
554 5840 : m2statement_BuildFunctionCallTree (location_t location, tree procedure,
555 : tree rettype)
556 : {
557 5840 : m2statement_BuildProcedureCallTree (location, procedure, rettype);
558 5840 : }
559 :
560 : /* SetLastFunction assigns last_function to, t. */
561 :
562 : void
563 229545 : m2statement_SetLastFunction (tree t)
564 : {
565 229545 : last_function = t;
566 229545 : }
567 :
568 : /* SetParamList assigns param_list to, t. */
569 :
570 : void
571 1152 : m2statement_SetParamList (tree t)
572 : {
573 1152 : param_list = t;
574 1152 : }
575 :
576 : /* GetLastFunction returns, last_function. */
577 :
578 : tree
579 0 : m2statement_GetLastFunction (void)
580 : {
581 0 : return last_function;
582 : }
583 :
584 : /* GetParamList returns, param_list. */
585 :
586 : tree
587 1152 : m2statement_GetParamList (void)
588 : {
589 1152 : return param_list;
590 : }
591 :
592 : /* GetCurrentFunction returns the current_function. */
593 :
594 : tree
595 0 : m2statement_GetCurrentFunction (void)
596 : {
597 0 : return current_function_decl;
598 : }
599 :
600 : /* GetParamTree return parameter, i. */
601 :
602 : tree
603 0 : m2statement_GetParamTree (tree call, unsigned int i)
604 : {
605 0 : return CALL_EXPR_ARG (call, i);
606 : }
607 :
608 : /* BuildTryFinally returns a TRY_FINALL_EXPR with the call and
609 : cleanups attached. */
610 :
611 : tree
612 0 : m2statement_BuildTryFinally (location_t location, tree call, tree cleanups)
613 : {
614 0 : return build_stmt (location, TRY_FINALLY_EXPR, call, cleanups);
615 : }
616 :
617 : /* BuildCleanUp return a CLEANUP_POINT_EXPR which will clobber,
618 : param. */
619 :
620 : tree
621 0 : m2statement_BuildCleanUp (tree param)
622 : {
623 0 : tree clobber = build_constructor (TREE_TYPE (param), NULL);
624 0 : TREE_THIS_VOLATILE (clobber) = 1;
625 0 : return build2 (MODIFY_EXPR, TREE_TYPE (param), param, clobber);
626 : }
627 :
628 : /* BuildAsm generates an inline assembler instruction. */
629 :
630 : void
631 27 : m2statement_BuildAsm (location_t location, tree instr, bool isVolatile,
632 : bool isSimple, tree inputs, tree outputs, tree trash,
633 : tree labels)
634 : {
635 27 : tree string = resolve_asm_operand_names (instr, outputs, inputs, labels);
636 27 : tree args = build_stmt (location, ASM_EXPR, string, outputs, inputs, trash,
637 : labels);
638 :
639 27 : m2assert_AssertLocation (location);
640 :
641 : /* ASM statements without outputs, including simple ones, are treated
642 : as volatile. */
643 27 : ASM_BASIC_P (args) = isSimple;
644 27 : ASM_VOLATILE_P (args) = isVolatile;
645 :
646 27 : add_stmt (location, args);
647 27 : }
648 :
649 : /* BuildStart creates a module initialization function. We make
650 : this function public if it is not an inner module. The linker
651 : will create a call list for all linked modules which determines
652 : the initialization sequence for all modules. */
653 :
654 : tree
655 0 : m2statement_BuildStart (location_t location, char *name, bool inner_module)
656 : {
657 0 : tree fntype;
658 0 : tree fndecl;
659 :
660 0 : m2assert_AssertLocation (location);
661 : /* The function type depends on the return type and type of args. */
662 0 : fntype = build_function_type (integer_type_node, NULL_TREE);
663 0 : fndecl = build_decl (location, FUNCTION_DECL, get_identifier (name), fntype);
664 :
665 0 : DECL_EXTERNAL (fndecl) = 0;
666 0 : if (inner_module)
667 0 : TREE_PUBLIC (fndecl) = 0;
668 : else
669 0 : TREE_PUBLIC (fndecl) = 1;
670 :
671 0 : TREE_STATIC (fndecl) = 1;
672 0 : DECL_RESULT (fndecl)
673 0 : = build_decl (location, RESULT_DECL, NULL_TREE, integer_type_node);
674 0 : DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
675 :
676 : /* Prevent the optimizer from removing it if it is public. */
677 0 : if (TREE_PUBLIC (fndecl))
678 0 : gm2_mark_addressable (fndecl);
679 :
680 0 : m2statement_BuildStartFunctionCode (location, fndecl, !inner_module,
681 : inner_module);
682 0 : return fndecl;
683 : }
684 :
685 : /* BuildEnd complete the initialization function for this module. */
686 :
687 : void
688 0 : m2statement_BuildEnd (location_t location, tree fndecl, bool nested)
689 : {
690 0 : m2statement_BuildEndFunctionCode (location, fndecl, nested);
691 0 : current_function_decl = NULL;
692 0 : set_cfun (NULL);
693 0 : }
694 :
695 : /* BuildCallInner call the inner module function. It has no
696 : parameters and no return value. */
697 :
698 : void
699 672 : m2statement_BuildCallInner (location_t location, tree fndecl)
700 : {
701 672 : m2assert_AssertLocation (location);
702 672 : param_list = NULL_TREE;
703 672 : add_stmt (location,
704 : m2statement_BuildProcedureCallTree (location, fndecl, NULL_TREE));
705 672 : }
706 :
707 :
708 : /* BuildIfThenDoEnd returns a tree which will only execute
709 : statement, s, if, condition, is true. */
710 :
711 : tree
712 121006 : m2statement_BuildIfThenDoEnd (tree condition, tree then_block)
713 : {
714 121006 : if (then_block == NULL_TREE)
715 : return NULL_TREE;
716 : else
717 17043 : return fold_build3 (COND_EXPR, void_type_node, condition, then_block,
718 : alloc_stmt_list ());
719 : }
720 :
721 : /* BuildIfThenElseEnd returns a tree which will execute then_block
722 : or else_block depending upon, condition. */
723 :
724 : tree
725 6972 : m2statement_BuildIfThenElseEnd (tree condition, tree then_block,
726 : tree else_block)
727 : {
728 6972 : if (then_block == NULL_TREE)
729 : return NULL_TREE;
730 : else
731 1188 : return fold_build3 (COND_EXPR, void_type_node, condition, then_block,
732 : else_block);
733 : }
734 :
735 : /* BuildReturnValueCode generates the code associated with:
736 : RETURN ( value ). */
737 :
738 : void
739 27853 : m2statement_BuildReturnValueCode (location_t location, tree fndecl, tree value)
740 : {
741 27853 : tree ret_stmt;
742 27853 : tree t;
743 :
744 27853 : m2assert_AssertLocation (location);
745 83559 : t = build2 (
746 27853 : MODIFY_EXPR, TREE_TYPE (DECL_RESULT (fndecl)), DECL_RESULT (fndecl),
747 : m2convert_BuildConvert (
748 27853 : location, m2tree_skip_type_decl (TREE_TYPE (DECL_RESULT (fndecl))),
749 : value, false));
750 :
751 27853 : ret_stmt = build_stmt (location, RETURN_EXPR, t);
752 27853 : add_stmt (location, ret_stmt);
753 27853 : }
754 :
755 : /* IfExprJump if expr then jump to the label. */
756 :
757 : void
758 79899 : m2statement_IfExprJump (location_t location, tree exp, char *label)
759 : {
760 79899 : tree if_jump;
761 :
762 79899 : m2assert_AssertLocation (location);
763 79899 : if (TREE_CODE (TREE_TYPE (exp)) != BOOLEAN_TYPE)
764 79881 : exp = convert_loc (location, m2type_GetBooleanType (), exp);
765 :
766 79899 : m2block_push_statement_list (m2block_begin_statement_list ());
767 79899 : m2statement_BuildGoto (location, label);
768 79899 : if_jump = build3 (COND_EXPR, void_type_node, exp,
769 : m2block_pop_statement_list (),
770 : alloc_stmt_list ());
771 79899 : add_stmt (location, if_jump);
772 79899 : }
773 :
774 :
775 : /* IfBitInSetJump if bit in set jump to label. */
776 :
777 : void
778 0 : m2statement_IfBitInSetJump (location_t location, bool invertCondition,
779 : tree setvalue, tree bit, char *label)
780 : {
781 0 : tree condition;
782 :
783 0 : condition = m2expr_BuildNotEqualTo (location,
784 : m2expr_BuildLogicalAnd (location,
785 : m2expr_BuildLSL (location,
786 : m2expr_GetWordOne (location),
787 : bit, false),
788 : setvalue),
789 : m2expr_GetWordZero (location)) ;
790 0 : if (invertCondition)
791 0 : condition = m2expr_BuildEqualTo (location, condition,
792 : m2type_GetBooleanFalse ());
793 0 : m2statement_IfExprJump (location, condition, label);
794 0 : }
795 :
796 : #include "gt-m2-m2statement.h"
|