Branch data Line data Source code
1 : : /* m2statement.cc provides an interface to GCC statement trees.
2 : :
3 : : Copyright (C) 2012-2025 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 : 117772 : m2statement_BuildStartFunctionCode (location_t location, tree fndecl,
51 : : bool isexported, bool isinline)
52 : : {
53 : 117772 : tree param_decl;
54 : :
55 : 117772 : ASSERT_BOOL (isexported);
56 : 117772 : ASSERT_BOOL (isinline);
57 : : /* Announce we are compiling this function. */
58 : 117772 : announce_function (fndecl);
59 : :
60 : : /* Set up to compile the function and enter it. */
61 : :
62 : 117772 : DECL_INITIAL (fndecl) = NULL_TREE;
63 : :
64 : 117772 : current_function_decl = fndecl;
65 : 117772 : m2block_pushFunctionScope (fndecl);
66 : 117772 : m2statement_SetBeginLocation (location);
67 : :
68 : 117772 : ASSERT_BOOL ((cfun != NULL));
69 : : /* Initialize the RTL code for the function. */
70 : 117772 : allocate_struct_function (fndecl, false);
71 : : /* Begin the statement tree for this function. */
72 : 117772 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
73 : :
74 : : /* Set the context of these parameters to this function. */
75 : 312497 : for (param_decl = DECL_ARGUMENTS (fndecl); param_decl;
76 : 194725 : param_decl = TREE_CHAIN (param_decl))
77 : 194725 : DECL_CONTEXT (param_decl) = fndecl;
78 : :
79 : : /* This function exists in static storage. (This does not mean
80 : : `static' in the C sense!) */
81 : 117772 : TREE_STATIC (fndecl) = 1;
82 : 117772 : TREE_PUBLIC (fndecl) = isexported;
83 : : /* We could do better here by detecting ADR
84 : : or type PROC used on this function. --fixme-- */
85 : 117772 : TREE_ADDRESSABLE (fndecl) = 1;
86 : 117772 : DECL_DECLARED_INLINE_P (fndecl) = 0; /* isinline; */
87 : 117772 : }
88 : :
89 : : /* BuildEndFunctionCode generates the function epilogue. */
90 : :
91 : : void
92 : 117760 : m2statement_BuildEndFunctionCode (location_t location, tree fndecl, bool nested)
93 : : {
94 : 117760 : tree block = DECL_INITIAL (fndecl);
95 : :
96 : 117760 : BLOCK_SUPERCONTEXT (block) = fndecl;
97 : :
98 : : /* Must mark the RESULT_DECL as being in this function. */
99 : 117760 : DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
100 : :
101 : : /* And attach it to the function. */
102 : 117760 : DECL_INITIAL (fndecl) = block;
103 : :
104 : 117760 : m2block_finishFunctionCode (fndecl);
105 : 117760 : m2statement_SetEndLocation (location);
106 : :
107 : 117760 : m2pp_dump_gimple (M2PP_DUMP_PRE_GENERICIZE, fndecl);
108 : 117760 : gm2_genericize (fndecl);
109 : 117760 : if (nested)
110 : 744 : (void)cgraph_node::get_create (fndecl);
111 : : else
112 : : {
113 : 117016 : m2pp_dump_gimple (M2PP_DUMP_POST_GENERICIZE, fndecl);
114 : 117016 : cgraph_node::finalize_function (fndecl, false);
115 : : }
116 : :
117 : 117760 : 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 : 117760 : set_cfun (NULL);
123 : 117760 : current_function_decl = NULL;
124 : 117760 : }
125 : :
126 : : /* BuildPushFunctionContext pushes the current function context.
127 : : Maps onto push_function_context in ../function.cc. */
128 : :
129 : : void
130 : 84444 : m2statement_BuildPushFunctionContext (void)
131 : : {
132 : 84444 : push_function_context ();
133 : 84444 : }
134 : :
135 : : /* BuildPopFunctionContext pops the current function context. Maps
136 : : onto pop_function_context in ../function.cc. */
137 : :
138 : : void
139 : 84444 : m2statement_BuildPopFunctionContext (void)
140 : : {
141 : 84444 : pop_function_context ();
142 : 84444 : }
143 : :
144 : : void
145 : 202216 : m2statement_SetBeginLocation (location_t location)
146 : : {
147 : 202216 : if (cfun != NULL)
148 : 0 : cfun->function_start_locus = location;
149 : 202216 : }
150 : :
151 : : void
152 : 117760 : m2statement_SetEndLocation (location_t location)
153 : : {
154 : 117760 : if (cfun != NULL)
155 : 117760 : cfun->function_end_locus = location;
156 : 117760 : }
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 : 742886 : m2statement_BuildAssignmentTree (location_t location, tree des, tree expr)
277 : : {
278 : 742886 : tree result;
279 : :
280 : 742886 : m2assert_AssertLocation (location);
281 : 1497155 : STRIP_TYPE_NOPS (expr);
282 : :
283 : 742886 : 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 : 742214 : gcc_assert (TREE_CODE (TREE_TYPE (des)) != TYPE_DECL);
289 : 742214 : if (TREE_TYPE (expr) == TREE_TYPE (des))
290 : 447235 : result = build2 (MODIFY_EXPR, TREE_TYPE (des), des, expr);
291 : : else
292 : 589958 : result = build2 (
293 : 294979 : MODIFY_EXPR, TREE_TYPE (des), des,
294 : 294979 : m2convert_BuildConvert (location, TREE_TYPE (des), expr, false));
295 : : }
296 : :
297 : 742886 : TREE_SIDE_EFFECTS (result) = true;
298 : 742886 : TREE_USED (des) = true;
299 : 742886 : TREE_USED (expr) = true;
300 : 742886 : add_stmt (location, result);
301 : 742886 : return des;
302 : : }
303 : :
304 : : /* BuildAssignmentStatement builds the assignment of, des, and, expr. */
305 : :
306 : : void
307 : 741842 : m2statement_BuildAssignmentStatement (location_t location, tree des, tree expr)
308 : : {
309 : 741842 : m2statement_BuildAssignmentTree (location, des, expr);
310 : 741842 : }
311 : :
312 : : /* BuildGoto builds a goto operation. */
313 : :
314 : : void
315 : 137578 : m2statement_BuildGoto (location_t location, char *name)
316 : : {
317 : 137578 : tree label = m2block_getLabel (location, name);
318 : :
319 : 137578 : m2assert_AssertLocation (location);
320 : 137578 : TREE_USED (label) = true;
321 : 137578 : add_stmt (location, build1 (GOTO_EXPR, void_type_node, label));
322 : 137578 : }
323 : :
324 : : /* DeclareLabel create a label, name. */
325 : :
326 : : void
327 : 115029 : m2statement_DeclareLabel (location_t location, char *name)
328 : : {
329 : 115029 : tree label = m2block_getLabel (location, name);
330 : :
331 : 115029 : m2assert_AssertLocation (location);
332 : 115029 : add_stmt (location, build1 (LABEL_EXPR, void_type_node, label));
333 : 115029 : }
334 : :
335 : : /* BuildParam build a list of parameters, ready for a subsequent
336 : : procedure call. */
337 : :
338 : : void
339 : 662656 : m2statement_BuildParam (location_t location, tree param)
340 : : {
341 : 662656 : m2assert_AssertLocation (location);
342 : :
343 : 662656 : TREE_USED (param) = true;
344 : 662656 : if (TREE_CODE (param) == FUNCTION_DECL)
345 : 49912 : param = m2expr_BuildAddr (location, param, false);
346 : :
347 : 662656 : param_list = chainon (build_tree_list (NULL_TREE, param), param_list);
348 : 662656 : }
349 : :
350 : : /* nCount return the number of chained tree nodes in list, t. */
351 : :
352 : : static int
353 : 253024 : nCount (tree t)
354 : : {
355 : 253024 : int i = 0;
356 : :
357 : 914026 : while (t != NULL)
358 : : {
359 : 661002 : i++;
360 : 661002 : t = TREE_CHAIN (t);
361 : : }
362 : 253024 : 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 : 252324 : m2statement_BuildProcedureCallTree (location_t location, tree procedure,
370 : : tree rettype)
371 : : {
372 : 252324 : tree functype = TREE_TYPE (procedure);
373 : 252324 : tree funcptr = build1 (ADDR_EXPR, build_pointer_type (functype), procedure);
374 : 252324 : tree call;
375 : 252324 : int n = nCount (param_list);
376 : 252324 : tree *argarray = XALLOCAVEC (tree, n);
377 : 252324 : tree t = param_list;
378 : 252324 : int i;
379 : :
380 : 252324 : m2assert_AssertLocation (location);
381 : 252324 : ASSERT_CONDITION (
382 : : last_function
383 : 252324 : == NULL_TREE); /* Previous function value has not been collected. */
384 : 252324 : TREE_USED (procedure) = true;
385 : :
386 : 912196 : for (i = 0; i < n; i++)
387 : : {
388 : 659872 : argarray[i] = TREE_VALUE (t);
389 : 659872 : t = TREE_CHAIN (t);
390 : : }
391 : :
392 : 252324 : if (rettype == NULL_TREE)
393 : : {
394 : 175068 : rettype = void_type_node;
395 : 175068 : call = build_call_array_loc (location, rettype, funcptr, n, argarray);
396 : 175068 : TREE_USED (call) = true;
397 : 175068 : 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 : 175068 : param_list
406 : 175068 : = NULL_TREE; /* Ready for the next time we call a procedure. */
407 : 175068 : last_function = NULL_TREE;
408 : 175068 : return call;
409 : : }
410 : : else
411 : : {
412 : 77256 : last_function = build_call_array_loc (
413 : : location, m2tree_skip_type_decl (rettype), funcptr, n, argarray);
414 : 77256 : TREE_USED (last_function) = true;
415 : 77256 : TREE_SIDE_EFFECTS (last_function) = true;
416 : 77256 : param_list
417 : 77256 : = NULL_TREE; /* Ready for the next time we call a procedure. */
418 : 77256 : 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 : 700 : m2statement_BuildIndirectProcedureCallTree (location_t location,
427 : : tree procedure, tree rettype)
428 : : {
429 : 700 : tree call;
430 : 700 : int n = nCount (param_list);
431 : 700 : tree *argarray = XALLOCAVEC (tree, n);
432 : 700 : tree t = param_list;
433 : 700 : int i;
434 : :
435 : 700 : m2assert_AssertLocation (location);
436 : 700 : TREE_USED (procedure) = true;
437 : 700 : TREE_SIDE_EFFECTS (procedure) = true;
438 : :
439 : 1830 : for (i = 0; i < n; i++)
440 : : {
441 : 1130 : argarray[i] = TREE_VALUE (t);
442 : 1130 : t = TREE_CHAIN (t);
443 : : }
444 : :
445 : 700 : if (rettype == NULL_TREE)
446 : : {
447 : 624 : rettype = void_type_node;
448 : 624 : call = build_call_array_loc (location, rettype, procedure, n, argarray);
449 : 624 : TREE_USED (call) = true;
450 : 624 : 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 : 624 : last_function = NULL_TREE;
459 : 624 : param_list
460 : 624 : = NULL_TREE; /* Ready for the next time we call a procedure. */
461 : 624 : return call;
462 : : }
463 : : else
464 : : {
465 : 76 : last_function = build_call_array_loc (
466 : : location, m2tree_skip_type_decl (rettype), procedure, n, argarray);
467 : 76 : TREE_USED (last_function) = true;
468 : 76 : TREE_SIDE_EFFECTS (last_function) = true;
469 : 76 : param_list
470 : 76 : = NULL_TREE; /* Ready for the next time we call a procedure. */
471 : 76 : 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 : 90540 : m2statement_BuildFunctValue (location_t location, tree value)
494 : : {
495 : 90540 : tree assign
496 : 90540 : = m2treelib_build_modify_expr (location, value, NOP_EXPR, last_function);
497 : :
498 : 90540 : m2assert_AssertLocation (location);
499 : 90540 : ASSERT_CONDITION (
500 : : last_function
501 : 90540 : != NULL_TREE); /* No value available, possible used before. */
502 : :
503 : 90540 : TREE_SIDE_EFFECTS (assign) = true;
504 : 90540 : TREE_USED (assign) = true;
505 : 90540 : TREE_USED (value) = true;
506 : 90540 : last_function = NULL_TREE;
507 : 90540 : 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 : 5708 : m2statement_BuildFunctionCallTree (location_t location, tree procedure,
547 : : tree rettype)
548 : : {
549 : 5708 : m2statement_BuildProcedureCallTree (location, procedure, rettype);
550 : 5708 : }
551 : :
552 : : /* SetLastFunction assigns last_function to, t. */
553 : :
554 : : void
555 : 245949 : m2statement_SetLastFunction (tree t)
556 : : {
557 : 245949 : last_function = t;
558 : 245949 : }
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 : 133295 : m2statement_BuildIfThenDoEnd (tree condition, tree then_block)
705 : : {
706 : 133295 : 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 : 7482 : m2statement_BuildIfThenElseEnd (tree condition, tree then_block,
718 : : tree else_block)
719 : : {
720 : 7482 : 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 : 28143 : m2statement_BuildReturnValueCode (location_t location, tree fndecl, tree value)
732 : : {
733 : 28143 : tree ret_stmt;
734 : 28143 : tree t;
735 : :
736 : 28143 : m2assert_AssertLocation (location);
737 : 84429 : t = build2 (
738 : 28143 : MODIFY_EXPR, TREE_TYPE (DECL_RESULT (fndecl)), DECL_RESULT (fndecl),
739 : : m2convert_BuildConvert (
740 : 28143 : location, m2tree_skip_type_decl (TREE_TYPE (DECL_RESULT (fndecl))),
741 : : value, false));
742 : :
743 : 28143 : ret_stmt = build_stmt (location, RETURN_EXPR, t);
744 : 28143 : add_stmt (location, ret_stmt);
745 : 28143 : }
746 : :
747 : : /* IfExprJump if expr then jump to the label. */
748 : :
749 : : void
750 : 87484 : m2statement_IfExprJump (location_t location, tree exp, char *label)
751 : : {
752 : 87484 : tree if_jump;
753 : :
754 : 87484 : m2assert_AssertLocation (location);
755 : 87484 : if (TREE_CODE (TREE_TYPE (exp)) != BOOLEAN_TYPE)
756 : 87466 : exp = convert_loc (location, m2type_GetBooleanType (), exp);
757 : :
758 : 87484 : m2block_push_statement_list (m2block_begin_statement_list ());
759 : 87484 : m2statement_BuildGoto (location, label);
760 : 87484 : if_jump = build3 (COND_EXPR, void_type_node, exp,
761 : : m2block_pop_statement_list (),
762 : : alloc_stmt_list ());
763 : 87484 : add_stmt (location, if_jump);
764 : 87484 : }
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"
|