libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / rust-gcc.cc
blob38169c08985d3057018f12a04071b89c6bf2d57d
1 // rust-gcc.cc -- Rust frontend to gcc IR.
2 // Copyright (C) 2011-2024 Free Software Foundation, Inc.
3 // Contributed by Ian Lance Taylor, Google.
4 // forked from gccgo
6 // This file is part of GCC.
8 // GCC is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 3, or (at your option) any later
11 // version.
13 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with GCC; see the file COPYING3. If not see
20 // <http://www.gnu.org/licenses/>.
22 #include "rust-system.h"
24 // This has to be included outside of extern "C", so we have to
25 // include it here before tree.h includes it later.
26 #include <gmp.h>
28 #include "tree.h"
29 #include "opts.h"
30 #include "fold-const.h"
31 #include "stringpool.h"
32 #include "stor-layout.h"
33 #include "varasm.h"
34 #include "tree-iterator.h"
35 #include "tm.h"
36 #include "function.h"
37 #include "cgraph.h"
38 #include "convert.h"
39 #include "gimple-expr.h"
40 #include "gimplify.h"
41 #include "langhooks.h"
42 #include "toplev.h"
43 #include "output.h"
44 #include "realmpfr.h"
45 #include "builtins.h"
46 #include "print-tree.h"
47 #include "attribs.h"
49 #include "rust-location.h"
50 #include "rust-linemap.h"
51 #include "rust-backend.h"
52 #include "rust-object-export.h"
53 #include "rust-gcc.h"
55 #include "backend/rust-tree.h"
56 #include "backend/rust-builtins.h"
58 // Get the tree of a variable for use as an expression. If this is a
59 // zero-sized global, create an expression that refers to the decl but
60 // has zero size.
61 tree
62 Bvariable::get_tree (location_t location) const
64 if (this->t_ == error_mark_node)
65 return error_mark_node;
67 TREE_USED (this->t_) = 1;
68 if (this->orig_type_ == NULL || TREE_TYPE (this->t_) == this->orig_type_)
70 return this->t_;
73 // Return *(orig_type*)&decl. */
74 tree t = build_fold_addr_expr_loc (location, this->t_);
75 t = fold_build1_loc (location, NOP_EXPR,
76 build_pointer_type (this->orig_type_), t);
77 return build_fold_indirect_ref_loc (location, t);
80 Bvariable *
81 Bvariable::error_variable ()
83 return new Bvariable (error_mark_node);
86 // This file implements the interface between the Rust frontend proper
87 // and the gcc IR. This implements specific instantiations of
88 // abstract classes defined by the Rust frontend proper. The Rust
89 // frontend proper class methods of these classes to generate the
90 // backend representation.
92 // A helper function to create a GCC identifier from a C++ string.
94 static inline tree
95 get_identifier_from_string (const std::string &str)
97 return get_identifier_with_length (str.data (), str.length ());
100 namespace Backend {
102 // Define the built-in functions that are exposed to GCCRust.
104 void
105 init ()
107 /* We need to define the fetch_and_add functions, since we use them
108 for ++ and --. */
109 // tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree ();
110 // tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
111 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1,
112 // "__sync_fetch_and_add_1",
113 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
115 // t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree ();
116 // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
117 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2,
118 // "__sync_fetch_and_add_2",
119 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
121 // t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree ();
122 // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
123 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4,
124 // "__sync_fetch_and_add_4",
125 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
127 // t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree ();
128 // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
129 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8,
130 // "__sync_fetch_and_add_8",
131 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
133 // // We use __builtin_expect for magic import functions.
134 // this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL,
135 // build_function_type_list (long_integer_type_node,
136 // long_integer_type_node,
137 // long_integer_type_node,
138 // NULL_TREE),
139 // builtin_const);
141 // // We use __builtin_memcmp for struct comparisons.
142 // this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp",
143 // build_function_type_list (integer_type_node,
144 // const_ptr_type_node,
145 // const_ptr_type_node,
146 // size_type_node, NULL_TREE),
147 // 0);
149 // // We use __builtin_memmove for copying data.
150 // this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove",
151 // build_function_type_list (void_type_node, ptr_type_node,
152 // const_ptr_type_node,
153 // size_type_node, NULL_TREE),
154 // 0);
156 // // We use __builtin_memset for zeroing data.
157 // this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset",
158 // build_function_type_list (void_type_node, ptr_type_node,
159 // integer_type_node,
160 // size_type_node, NULL_TREE),
161 // 0);
163 // // Used by runtime/internal/sys and math/bits.
164 // this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz",
165 // build_function_type_list (integer_type_node,
166 // unsigned_type_node,
167 // NULL_TREE),
168 // builtin_const);
169 // this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll",
170 // build_function_type_list (integer_type_node,
171 // long_long_unsigned_type_node,
172 // NULL_TREE),
173 // builtin_const);
174 // this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz",
175 // build_function_type_list (integer_type_node,
176 // unsigned_type_node,
177 // NULL_TREE),
178 // builtin_const);
179 // this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
180 // build_function_type_list (integer_type_node,
181 // long_long_unsigned_type_node,
182 // NULL_TREE),
183 // builtin_const);
184 // this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
185 // build_function_type_list (integer_type_node,
186 // unsigned_type_node,
187 // NULL_TREE),
188 // builtin_const);
189 // this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll",
190 // "popcountll",
191 // build_function_type_list (integer_type_node,
192 // long_long_unsigned_type_node,
193 // NULL_TREE),
194 // builtin_const);
195 // this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
196 // build_function_type_list (uint16_type_node,
197 // uint16_type_node, NULL_TREE),
198 // builtin_const);
199 // this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
200 // build_function_type_list (uint32_type_node,
201 // uint32_type_node, NULL_TREE),
202 // builtin_const);
203 // this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64",
204 // build_function_type_list (uint64_type_node,
205 // uint64_type_node, NULL_TREE),
206 // builtin_const);
208 // We provide some functions for the math library.
210 // We use __builtin_return_address in the thunk we build for
211 // functions which call recover, and for runtime.getcallerpc.
212 // t = build_function_type_list (ptr_type_node, unsigned_type_node,
213 // NULL_TREE); this->define_builtin (BUILT_IN_RETURN_ADDRESS,
214 // "__builtin_return_address",
215 // NULL, t, 0);
217 // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp.
218 // t = build_function_type_list (ptr_type_node, NULL_TREE);
219 // this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t,
220 // 0);
222 // The runtime calls __builtin_extract_return_addr when recording
223 // the address to which a function returns.
224 // this->define_builtin (
225 // BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL,
226 // build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0);
228 // The compiler uses __builtin_trap for some exception handling
229 // cases.
230 // this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL,
231 // build_function_type (void_type_node, void_list_node),
232 // builtin_noreturn);
234 // The runtime uses __builtin_prefetch.
235 // this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL,
236 // build_varargs_function_type_list (void_type_node,
237 // const_ptr_type_node,
238 // NULL_TREE),
239 // builtin_novops);
241 // The compiler uses __builtin_unreachable for cases that cannot
242 // occur.
243 // this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
244 // build_function_type (void_type_node, void_list_node),
245 // builtin_const | builtin_noreturn);
247 // We provide some atomic functions.
248 // t = build_function_type_list (uint32_type_node, ptr_type_node,
249 // integer_type_node, NULL_TREE);
250 // this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t,
251 // 0);
253 // t = build_function_type_list (uint64_type_node, ptr_type_node,
254 // integer_type_node, NULL_TREE);
255 // this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t,
256 // 0);
258 // t = build_function_type_list (void_type_node, ptr_type_node,
259 // uint32_type_node,
260 // integer_type_node, NULL_TREE);
261 // this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t,
262 // 0);
264 // t = build_function_type_list (void_type_node, ptr_type_node,
265 // uint64_type_node,
266 // integer_type_node, NULL_TREE);
267 // this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t,
268 // 0);
270 // t = build_function_type_list (uint32_type_node, ptr_type_node,
271 // uint32_type_node, integer_type_node, NULL_TREE);
272 // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4",
273 // NULL,
274 // t, 0);
276 // t = build_function_type_list (uint64_type_node, ptr_type_node,
277 // uint64_type_node, integer_type_node, NULL_TREE);
278 // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8",
279 // NULL,
280 // t, 0);
282 // t = build_function_type_list (boolean_type_node, ptr_type_node,
283 // ptr_type_node,
284 // uint32_type_node, boolean_type_node,
285 // integer_type_node, integer_type_node,
286 // NULL_TREE);
287 // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
288 // "__atomic_compare_exchange_4", NULL, t, 0);
290 // t = build_function_type_list (boolean_type_node, ptr_type_node,
291 // ptr_type_node,
292 // uint64_type_node, boolean_type_node,
293 // integer_type_node, integer_type_node,
294 // NULL_TREE);
295 // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
296 // "__atomic_compare_exchange_8", NULL, t, 0);
298 // t = build_function_type_list (uint32_type_node, ptr_type_node,
299 // uint32_type_node, integer_type_node, NULL_TREE);
300 // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
301 // NULL, t, 0);
303 // t = build_function_type_list (uint64_type_node, ptr_type_node,
304 // uint64_type_node, integer_type_node, NULL_TREE);
305 // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
306 // NULL, t, 0);
308 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
309 // unsigned_char_type_node, integer_type_node,
310 // NULL_TREE);
311 // this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
312 // NULL, t, 0);
313 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1",
314 // NULL, t, 0);
316 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
317 // unsigned_char_type_node, integer_type_node,
318 // NULL_TREE);
319 // this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
320 // NULL,
321 // t, 0);
322 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1",
323 // NULL,
324 // t, 0);
327 void
328 debug (tree t)
330 debug_tree (t);
333 void
334 debug (Bvariable *t)
336 debug_tree (t->get_decl ());
339 tree
340 get_identifier_node (const std::string &str)
342 return get_identifier_with_length (str.data (), str.length ());
345 tree
346 wchar_type ()
348 static tree wchar;
350 if (wchar == NULL_TREE)
352 wchar = make_unsigned_type (32);
353 TYPE_STRING_FLAG (wchar) = 1;
356 return wchar;
359 // Get an unnamed integer type.
362 get_pointer_size ()
364 return POINTER_SIZE;
367 tree
368 raw_str_type ()
370 tree char_ptr = build_pointer_type (char_type_node);
371 tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
372 return const_char_type;
375 tree
376 integer_type (bool is_unsigned, int bits)
378 tree type;
379 if (is_unsigned)
381 if (bits == INT_TYPE_SIZE)
382 type = unsigned_type_node;
383 else if (bits == SHORT_TYPE_SIZE)
384 type = short_unsigned_type_node;
385 else if (bits == LONG_TYPE_SIZE)
386 type = long_unsigned_type_node;
387 else if (bits == LONG_LONG_TYPE_SIZE)
388 type = long_long_unsigned_type_node;
389 else
390 type = make_unsigned_type (bits);
392 else
394 if (bits == INT_TYPE_SIZE)
395 type = integer_type_node;
396 else if (bits == SHORT_TYPE_SIZE)
397 type = short_integer_type_node;
398 else if (bits == LONG_TYPE_SIZE)
399 type = long_integer_type_node;
400 else if (bits == LONG_LONG_TYPE_SIZE)
401 type = long_long_integer_type_node;
402 else
403 type = make_signed_type (bits);
405 return type;
408 // Get an unnamed float type.
410 tree
411 float_type (int bits)
413 tree type;
414 if (bits == TYPE_PRECISION (float_type_node))
415 type = float_type_node;
416 else if (bits == TYPE_PRECISION (double_type_node))
417 type = double_type_node;
418 else if (bits == TYPE_PRECISION (long_double_type_node))
419 type = long_double_type_node;
420 else
422 type = make_node (REAL_TYPE);
423 TYPE_PRECISION (type) = bits;
424 layout_type (type);
426 return type;
429 // Get a pointer type.
431 tree
432 pointer_type (tree to_type)
434 if (to_type == error_mark_node)
435 return error_mark_node;
436 tree type = build_pointer_type (to_type);
437 return type;
440 // Get a reference type.
442 tree
443 reference_type (tree to_type)
445 if (to_type == error_mark_node)
446 return error_mark_node;
447 tree type = build_reference_type (to_type);
448 return type;
451 // Get immutable type
453 tree
454 immutable_type (tree base)
456 if (base == error_mark_node)
457 return error_mark_node;
458 tree constified = build_qualified_type (base, TYPE_QUAL_CONST);
459 return constified;
462 // Make a function type.
464 tree
465 function_type (const typed_identifier &receiver,
466 const std::vector<typed_identifier> &parameters,
467 const std::vector<typed_identifier> &results, tree result_struct,
468 location_t)
470 tree args = NULL_TREE;
471 tree *pp = &args;
472 if (receiver.type != NULL_TREE)
474 tree t = receiver.type;
475 if (t == error_mark_node)
476 return error_mark_node;
477 *pp = tree_cons (NULL_TREE, t, NULL_TREE);
478 pp = &TREE_CHAIN (*pp);
481 for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
482 p != parameters.end (); ++p)
484 tree t = p->type;
485 if (t == error_mark_node)
486 return error_mark_node;
487 *pp = tree_cons (NULL_TREE, t, NULL_TREE);
488 pp = &TREE_CHAIN (*pp);
491 // Varargs is handled entirely at the Rust level. When converted to
492 // GENERIC functions are not varargs.
493 *pp = void_list_node;
495 tree result;
496 if (results.empty ())
497 result = void_type_node;
498 else if (results.size () == 1)
499 result = results.front ().type;
500 else
502 gcc_assert (result_struct != NULL);
503 result = result_struct;
505 if (result == error_mark_node)
506 return error_mark_node;
508 tree fntype = build_function_type (result, args);
509 if (fntype == error_mark_node)
510 return error_mark_node;
512 return build_pointer_type (fntype);
515 tree
516 function_type_variadic (const typed_identifier &receiver,
517 const std::vector<typed_identifier> &parameters,
518 const std::vector<typed_identifier> &results,
519 tree result_struct, location_t)
521 size_t n = parameters.size () + (receiver.type != NULL_TREE ? 1 : 0);
522 tree *args = XALLOCAVEC (tree, n);
523 size_t offs = 0;
525 if (receiver.type != NULL_TREE)
527 tree t = receiver.type;
528 if (t == error_mark_node)
529 return error_mark_node;
531 args[offs++] = t;
534 for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
535 p != parameters.end (); ++p)
537 tree t = p->type;
538 if (t == error_mark_node)
539 return error_mark_node;
540 args[offs++] = t;
543 tree result;
544 if (results.empty ())
545 result = void_type_node;
546 else if (results.size () == 1)
547 result = results.front ().type;
548 else
550 gcc_assert (result_struct != NULL_TREE);
551 result = result_struct;
553 if (result == error_mark_node)
554 return error_mark_node;
556 tree fntype = build_varargs_function_type_array (result, n, args);
557 if (fntype == error_mark_node)
558 return error_mark_node;
560 return build_pointer_type (fntype);
563 tree
564 function_ptr_type (tree result_type, const std::vector<tree> &parameters,
565 location_t /* locus */)
567 tree args = NULL_TREE;
568 tree *pp = &args;
570 for (auto &param : parameters)
572 if (param == error_mark_node)
573 return error_mark_node;
575 *pp = tree_cons (NULL_TREE, param, NULL_TREE);
576 pp = &TREE_CHAIN (*pp);
579 *pp = void_list_node;
581 tree result = result_type;
582 if (result != void_type_node && int_size_in_bytes (result) == 0)
583 result = void_type_node;
585 tree fntype = build_function_type (result, args);
586 if (fntype == error_mark_node)
587 return error_mark_node;
589 return build_pointer_type (fntype);
592 // Make a struct type.
594 tree
595 struct_type (const std::vector<typed_identifier> &fields)
597 return fill_in_fields (make_node (RECORD_TYPE), fields);
600 // Make a union type.
602 tree
603 union_type (const std::vector<typed_identifier> &fields)
605 return fill_in_fields (make_node (UNION_TYPE), fields);
608 // Fill in the fields of a struct or union type.
610 tree
611 fill_in_fields (tree fill, const std::vector<typed_identifier> &fields)
613 tree field_trees = NULL_TREE;
614 tree *pp = &field_trees;
615 for (std::vector<typed_identifier>::const_iterator p = fields.begin ();
616 p != fields.end (); ++p)
618 tree name_tree = get_identifier_from_string (p->name);
619 tree type_tree = p->type;
620 if (type_tree == error_mark_node)
621 return error_mark_node;
622 tree field = build_decl (p->location, FIELD_DECL, name_tree, type_tree);
623 DECL_CONTEXT (field) = fill;
624 *pp = field;
625 pp = &DECL_CHAIN (field);
627 TYPE_FIELDS (fill) = field_trees;
628 layout_type (fill);
630 // Because Rust permits converting between named struct types and
631 // equivalent struct types, for which we use VIEW_CONVERT_EXPR, and
632 // because we don't try to maintain TYPE_CANONICAL for struct types,
633 // we need to tell the middle-end to use structural equality.
634 SET_TYPE_STRUCTURAL_EQUALITY (fill);
636 return fill;
639 // Make an array type.
641 tree
642 array_type (tree element_type, tree length)
644 return fill_in_array (make_node (ARRAY_TYPE), element_type, length);
647 // Fill in an array type.
649 tree
650 fill_in_array (tree fill, tree element_type, tree length_tree)
652 if (element_type == error_mark_node || length_tree == error_mark_node)
653 return error_mark_node;
655 gcc_assert (TYPE_SIZE (element_type) != NULL_TREE);
657 length_tree = fold_convert (sizetype, length_tree);
659 // build_index_type takes the maximum index, which is one less than
660 // the length.
661 tree index_type_tree = build_index_type (
662 fold_build2 (MINUS_EXPR, sizetype, length_tree, size_one_node));
664 TREE_TYPE (fill) = element_type;
665 TYPE_DOMAIN (fill) = index_type_tree;
666 TYPE_ADDR_SPACE (fill) = TYPE_ADDR_SPACE (element_type);
667 layout_type (fill);
669 if (TYPE_STRUCTURAL_EQUALITY_P (element_type))
670 SET_TYPE_STRUCTURAL_EQUALITY (fill);
671 else if (TYPE_CANONICAL (element_type) != element_type
672 || TYPE_CANONICAL (index_type_tree) != index_type_tree)
673 TYPE_CANONICAL (fill) = build_array_type (TYPE_CANONICAL (element_type),
674 TYPE_CANONICAL (index_type_tree));
676 return fill;
679 // Return a named version of a type.
681 tree
682 named_type (const std::string &name, tree type, location_t location)
684 if (type == error_mark_node)
685 return error_mark_node;
687 // The middle-end expects a basic type to have a name. In Rust every
688 // basic type will have a name. The first time we see a basic type,
689 // give it whatever Rust name we have at this point.
690 if (TYPE_NAME (type) == NULL_TREE && location == BUILTINS_LOCATION
691 && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE
692 || TREE_CODE (type) == COMPLEX_TYPE
693 || TREE_CODE (type) == BOOLEAN_TYPE))
695 tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
696 get_identifier_from_string (name), type);
697 TYPE_NAME (type) = decl;
698 return type;
701 tree copy = build_variant_type_copy (type);
702 tree decl
703 = build_decl (location, TYPE_DECL, get_identifier_from_string (name), copy);
704 DECL_ORIGINAL_TYPE (decl) = type;
705 TYPE_NAME (copy) = decl;
706 return copy;
709 // Return the size of a type.
711 int64_t
712 type_size (tree t)
714 if (t == error_mark_node)
715 return 1;
716 if (t == void_type_node)
717 return 0;
718 t = TYPE_SIZE_UNIT (t);
719 gcc_assert (tree_fits_uhwi_p (t));
720 unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW (t);
721 int64_t ret = static_cast<int64_t> (val_wide);
722 if (ret < 0 || static_cast<unsigned HOST_WIDE_INT> (ret) != val_wide)
723 return -1;
724 return ret;
727 // Return the alignment of a type.
729 int64_t
730 type_alignment (tree t)
732 if (t == error_mark_node)
733 return 1;
734 return TYPE_ALIGN_UNIT (t);
737 // Return the alignment of a struct field of type BTYPE.
739 int64_t
740 type_field_alignment (tree t)
742 if (t == error_mark_node)
743 return 1;
744 return rust_field_alignment (t);
747 // Return the offset of a field in a struct.
749 int64_t
750 type_field_offset (tree struct_tree, size_t index)
752 if (struct_tree == error_mark_node)
753 return 0;
754 gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE);
755 tree field = TYPE_FIELDS (struct_tree);
756 for (; index > 0; --index)
758 field = DECL_CHAIN (field);
759 gcc_assert (field != NULL_TREE);
761 HOST_WIDE_INT offset_wide = int_byte_position (field);
762 int64_t ret = static_cast<int64_t> (offset_wide);
763 gcc_assert (ret == offset_wide);
764 return ret;
767 // Return the zero value for a type.
769 tree
770 zero_expression (tree t)
772 tree ret;
773 if (t == error_mark_node)
774 ret = error_mark_node;
775 else
776 ret = build_zero_cst (t);
777 return ret;
780 // An expression that references a variable.
782 tree
783 var_expression (Bvariable *var, location_t location)
785 return var->get_tree (location);
788 // Return a typed value as a constant floating-point number.
790 tree
791 float_constant_expression (tree t, mpfr_t val)
793 tree ret;
794 if (t == error_mark_node)
795 return error_mark_node;
797 REAL_VALUE_TYPE r1;
798 real_from_mpfr (&r1, val, t, GMP_RNDN);
799 REAL_VALUE_TYPE r2;
800 real_convert (&r2, TYPE_MODE (t), &r1);
801 ret = build_real (t, r2);
802 return ret;
805 // Make a constant string expression.
807 tree
808 string_constant_expression (const std::string &val)
810 tree index_type = build_index_type (size_int (val.length ()));
811 tree const_char_type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
812 tree string_type = build_array_type (const_char_type, index_type);
813 TYPE_STRING_FLAG (string_type) = 1;
814 tree string_val = build_string (val.length (), val.data ());
815 TREE_TYPE (string_val) = string_type;
817 return string_val;
820 tree
821 wchar_constant_expression (wchar_t c)
823 return build_int_cst (wchar_type (), c);
826 tree
827 char_constant_expression (char c)
829 return build_int_cst (char_type_node, c);
832 // Make a constant boolean expression.
834 tree
835 boolean_constant_expression (bool val)
837 return val ? boolean_true_node : boolean_false_node;
840 // An expression that converts an expression to a different type.
842 tree
843 convert_expression (tree type_tree, tree expr_tree, location_t location)
845 if (type_tree == error_mark_node || expr_tree == error_mark_node
846 || TREE_TYPE (expr_tree) == error_mark_node)
847 return error_mark_node;
849 tree ret;
850 if (type_size (type_tree) == 0 || TREE_TYPE (expr_tree) == void_type_node)
852 // Do not convert zero-sized types.
853 ret = expr_tree;
855 else if (TREE_CODE (type_tree) == INTEGER_TYPE)
856 ret = convert_to_integer (type_tree, expr_tree);
857 else if (TREE_CODE (type_tree) == REAL_TYPE)
858 ret = convert_to_real (type_tree, expr_tree);
859 else if (TREE_CODE (type_tree) == COMPLEX_TYPE)
860 ret = convert_to_complex (type_tree, expr_tree);
861 else if (TREE_CODE (type_tree) == POINTER_TYPE
862 && TREE_CODE (TREE_TYPE (expr_tree)) == INTEGER_TYPE)
863 ret = convert_to_pointer (type_tree, expr_tree);
864 else if (TREE_CODE (type_tree) == RECORD_TYPE
865 || TREE_CODE (type_tree) == ARRAY_TYPE)
866 ret = fold_build1_loc (location, VIEW_CONVERT_EXPR, type_tree, expr_tree);
867 else
868 ret = fold_convert_loc (location, type_tree, expr_tree);
870 return ret;
873 // Return an expression for the field at INDEX in BSTRUCT.
875 tree
876 struct_field_expression (tree struct_tree, size_t index, location_t location)
878 if (struct_tree == error_mark_node
879 || TREE_TYPE (struct_tree) == error_mark_node)
880 return error_mark_node;
881 gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE
882 || TREE_CODE (TREE_TYPE (struct_tree)) == UNION_TYPE);
883 tree field = TYPE_FIELDS (TREE_TYPE (struct_tree));
884 if (field == NULL_TREE)
886 // This can happen for a type which refers to itself indirectly
887 // and then turns out to be erroneous.
888 return error_mark_node;
890 for (unsigned int i = index; i > 0; --i)
892 field = DECL_CHAIN (field);
893 gcc_assert (field != NULL_TREE);
895 if (TREE_TYPE (field) == error_mark_node)
896 return error_mark_node;
897 tree ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (field),
898 struct_tree, field, NULL_TREE);
899 if (TREE_CONSTANT (struct_tree))
900 TREE_CONSTANT (ret) = 1;
901 return ret;
904 // Return an expression that executes BSTAT before BEXPR.
906 tree
907 compound_expression (tree stat, tree expr, location_t location)
909 if (stat == error_mark_node || expr == error_mark_node)
910 return error_mark_node;
911 tree ret
912 = fold_build2_loc (location, COMPOUND_EXPR, TREE_TYPE (expr), stat, expr);
913 return ret;
916 // Return an expression that executes THEN_EXPR if CONDITION is true, or
917 // ELSE_EXPR otherwise.
919 tree
920 conditional_expression (tree, tree type_tree, tree cond_expr, tree then_expr,
921 tree else_expr, location_t location)
923 if (type_tree == error_mark_node || cond_expr == error_mark_node
924 || then_expr == error_mark_node || else_expr == error_mark_node)
925 return error_mark_node;
926 tree ret = build3_loc (location, COND_EXPR, type_tree, cond_expr, then_expr,
927 else_expr);
928 return ret;
931 /* Helper function that converts rust operators to equivalent GCC tree_code.
932 Note that CompoundAssignmentOperator don't get their corresponding tree_code,
933 because they get compiled away when we lower AST to HIR. */
934 static enum tree_code
935 operator_to_tree_code (NegationOperator op)
937 switch (op)
939 case NegationOperator::NEGATE:
940 return NEGATE_EXPR;
941 case NegationOperator::NOT:
942 return TRUTH_NOT_EXPR;
943 default:
944 rust_unreachable ();
948 /* Note that GCC tree code distinguishes floating point division and integer
949 division. These two types of division are represented as the same rust
950 operator, and can only be distinguished via context(i.e. the TREE_TYPE of the
951 operands). */
952 static enum tree_code
953 operator_to_tree_code (ArithmeticOrLogicalOperator op, bool floating_point)
955 switch (op)
957 case ArithmeticOrLogicalOperator::ADD:
958 return PLUS_EXPR;
959 case ArithmeticOrLogicalOperator::SUBTRACT:
960 return MINUS_EXPR;
961 case ArithmeticOrLogicalOperator::MULTIPLY:
962 return MULT_EXPR;
963 case ArithmeticOrLogicalOperator::DIVIDE:
964 if (floating_point)
965 return RDIV_EXPR;
966 else
967 return TRUNC_DIV_EXPR;
968 case ArithmeticOrLogicalOperator::MODULUS:
969 return TRUNC_MOD_EXPR;
970 case ArithmeticOrLogicalOperator::BITWISE_AND:
971 return BIT_AND_EXPR;
972 case ArithmeticOrLogicalOperator::BITWISE_OR:
973 return BIT_IOR_EXPR;
974 case ArithmeticOrLogicalOperator::BITWISE_XOR:
975 return BIT_XOR_EXPR;
976 case ArithmeticOrLogicalOperator::LEFT_SHIFT:
977 return LSHIFT_EXPR;
978 case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
979 return RSHIFT_EXPR;
980 default:
981 rust_unreachable ();
985 static enum tree_code
986 operator_to_tree_code (ComparisonOperator op)
988 switch (op)
990 case ComparisonOperator::EQUAL:
991 return EQ_EXPR;
992 case ComparisonOperator::NOT_EQUAL:
993 return NE_EXPR;
994 case ComparisonOperator::GREATER_THAN:
995 return GT_EXPR;
996 case ComparisonOperator::LESS_THAN:
997 return LT_EXPR;
998 case ComparisonOperator::GREATER_OR_EQUAL:
999 return GE_EXPR;
1000 case ComparisonOperator::LESS_OR_EQUAL:
1001 return LE_EXPR;
1002 default:
1003 rust_unreachable ();
1007 static enum tree_code
1008 operator_to_tree_code (LazyBooleanOperator op)
1010 switch (op)
1012 case LazyBooleanOperator::LOGICAL_OR:
1013 return TRUTH_ORIF_EXPR;
1014 case LazyBooleanOperator::LOGICAL_AND:
1015 return TRUTH_ANDIF_EXPR;
1016 default:
1017 rust_unreachable ();
1021 /* Helper function for deciding if a tree is a floating point node. */
1022 bool
1023 is_floating_point (tree t)
1025 auto tree_type = TREE_CODE (TREE_TYPE (t));
1026 return tree_type == REAL_TYPE || tree_type == COMPLEX_TYPE;
1029 // Return an expression for the negation operation OP EXPR.
1030 tree
1031 negation_expression (NegationOperator op, tree expr_tree, location_t location)
1033 /* Check if the expression is an error, in which case we return an error
1034 expression. */
1035 if (expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node)
1036 return error_mark_node;
1038 /* For negation operators, the resulting type should be the same as its
1039 operand. */
1040 auto tree_type = TREE_TYPE (expr_tree);
1041 auto original_type = tree_type;
1042 auto tree_code = operator_to_tree_code (op);
1044 /* For floating point operations we may need to extend the precision of type.
1045 For example, a 64-bit machine may not support operations on float32. */
1046 bool floating_point = is_floating_point (expr_tree);
1047 auto extended_type = NULL_TREE;
1048 if (floating_point)
1050 extended_type = excess_precision_type (tree_type);
1051 if (extended_type != NULL_TREE)
1053 expr_tree = convert (extended_type, expr_tree);
1054 tree_type = extended_type;
1058 /* Construct a new tree and build an expression from it. */
1059 auto new_tree = fold_build1_loc (location, tree_code, tree_type, expr_tree);
1060 if (floating_point && extended_type != NULL_TREE)
1061 new_tree = convert (original_type, expr_tree);
1062 return new_tree;
1065 tree
1066 arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
1067 tree right, location_t location)
1069 /* Check if either expression is an error, in which case we return an error
1070 expression. */
1071 if (left == error_mark_node || right == error_mark_node)
1072 return error_mark_node;
1074 /* We need to determine if we're doing floating point arithmetics of integer
1075 arithmetics. */
1076 bool floating_point = is_floating_point (left);
1077 auto ret = NULL_TREE;
1079 /* For arithmetic or logical operators, the resulting type should be the same
1080 as the lhs operand. */
1081 auto tree_type = TREE_TYPE (left);
1082 auto original_type = tree_type;
1083 auto tree_code = operator_to_tree_code (op, floating_point);
1085 /* For floating point operations we may need to extend the precision of type.
1086 For example, a 64-bit machine may not support operations on float32. */
1087 auto extended_type = NULL_TREE;
1088 if (floating_point)
1090 extended_type = excess_precision_type (tree_type);
1091 if (extended_type != NULL_TREE)
1093 left = convert (extended_type, left);
1094 right = convert (extended_type, right);
1095 tree_type = extended_type;
1099 ret = fold_build2_loc (location, tree_code, tree_type, left, right);
1100 TREE_CONSTANT (ret) = TREE_CONSTANT (left) & TREE_CONSTANT (right);
1102 // TODO: How do we handle floating point?
1103 if (floating_point && extended_type != NULL_TREE)
1104 ret = convert (original_type, ret);
1106 return ret;
1109 static bool
1110 is_overflowing_expr (ArithmeticOrLogicalOperator op)
1112 switch (op)
1114 case ArithmeticOrLogicalOperator::ADD:
1115 case ArithmeticOrLogicalOperator::SUBTRACT:
1116 case ArithmeticOrLogicalOperator::MULTIPLY:
1117 return true;
1118 default:
1119 return false;
1123 static std::pair<tree, tree>
1124 fetch_overflow_builtins (ArithmeticOrLogicalOperator op)
1126 auto builtin_ctx = Rust::Compile::BuiltinsContext::get ();
1128 auto builtin = NULL_TREE;
1129 auto abort = NULL_TREE;
1131 switch (op)
1133 case ArithmeticOrLogicalOperator::ADD:
1134 builtin_ctx.lookup_simple_builtin ("__builtin_add_overflow", &builtin);
1135 break;
1136 case ArithmeticOrLogicalOperator::SUBTRACT:
1137 builtin_ctx.lookup_simple_builtin ("__builtin_sub_overflow", &builtin);
1138 break;
1139 case ArithmeticOrLogicalOperator::MULTIPLY:
1140 builtin_ctx.lookup_simple_builtin ("__builtin_mul_overflow", &builtin);
1141 break;
1142 default:
1143 rust_unreachable ();
1144 break;
1147 builtin_ctx.lookup_simple_builtin ("__builtin_abort", &abort);
1149 rust_assert (abort);
1150 rust_assert (builtin);
1152 // FIXME: ARTHUR: This is really ugly. The builtin context should take care of
1153 // that
1154 TREE_SIDE_EFFECTS (abort) = 1;
1155 TREE_READONLY (abort) = 0;
1157 // FIXME: ARTHUR: Same here. Remove these!
1158 TREE_SIDE_EFFECTS (builtin) = 1;
1159 TREE_READONLY (builtin) = 0;
1161 return {abort, builtin};
1164 // Return an expression for the arithmetic or logical operation LEFT OP RIGHT
1165 // with overflow checking when possible
1166 tree
1167 arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
1168 tree left, tree right,
1169 location_t location,
1170 Bvariable *receiver_var)
1172 /* Check if either expression is an error, in which case we return an error
1173 expression. */
1174 if (left == error_mark_node || right == error_mark_node)
1175 return error_mark_node;
1177 // FIXME: Add `if (!debug_mode)`
1178 // No overflow checks for floating point operations or divisions. In that
1179 // case, simply assign the result of the operation to the receiver variable
1180 if (is_floating_point (left) || !is_overflowing_expr (op))
1181 return assignment_statement (
1182 receiver_var->get_tree (location),
1183 arithmetic_or_logical_expression (op, left, right, location), location);
1185 auto receiver = receiver_var->get_tree (location);
1186 TREE_ADDRESSABLE (receiver) = 1;
1187 auto result_ref = build_fold_addr_expr_loc (location, receiver);
1189 auto builtins = fetch_overflow_builtins (op);
1190 auto abort = builtins.first;
1191 auto builtin = builtins.second;
1193 auto abort_call = build_call_expr_loc (location, abort, 0);
1195 // FIXME: ARTHUR: Is that needed?
1196 TREE_SIDE_EFFECTS (abort_call) = 1;
1197 TREE_READONLY (abort_call) = 0;
1199 auto builtin_call
1200 = build_call_expr_loc (location, builtin, 3, left, right, result_ref);
1201 auto overflow_check
1202 = build2_loc (location, EQ_EXPR, boolean_type_node, builtin_call,
1203 boolean_constant_expression (true));
1205 auto if_block = build3_loc (location, COND_EXPR, void_type_node,
1206 overflow_check, abort_call, NULL_TREE);
1208 // FIXME: ARTHUR: Needed?
1209 TREE_SIDE_EFFECTS (if_block) = 1;
1210 TREE_READONLY (if_block) = 0;
1212 return if_block;
1215 // Return an expression for the comparison operation LEFT OP RIGHT.
1216 tree
1217 comparison_expression (ComparisonOperator op, tree left_tree, tree right_tree,
1218 location_t location)
1220 /* Check if either expression is an error, in which case we return an error
1221 expression. */
1222 if (left_tree == error_mark_node || right_tree == error_mark_node)
1223 return error_mark_node;
1225 /* For comparison operators, the resulting type should be boolean. */
1226 auto tree_type = boolean_type_node;
1227 auto tree_code = operator_to_tree_code (op);
1229 /* Construct a new tree and build an expression from it. */
1230 auto new_tree
1231 = fold_build2_loc (location, tree_code, tree_type, left_tree, right_tree);
1232 return new_tree;
1235 // Return an expression for the lazy boolean operation LEFT OP RIGHT.
1236 tree
1237 lazy_boolean_expression (LazyBooleanOperator op, tree left_tree,
1238 tree right_tree, location_t location)
1240 /* Check if either expression is an error, in which case we return an error
1241 expression. */
1242 if (left_tree == error_mark_node || right_tree == error_mark_node)
1243 return error_mark_node;
1245 /* For lazy boolean operators, the resulting type should be the same as the
1246 rhs operand. */
1247 auto tree_type = TREE_TYPE (right_tree);
1248 auto tree_code = operator_to_tree_code (op);
1250 /* Construct a new tree and build an expression from it. */
1251 auto new_tree
1252 = fold_build2_loc (location, tree_code, tree_type, left_tree, right_tree);
1253 return new_tree;
1256 // Return an expression that constructs BTYPE with VALS.
1258 tree
1259 constructor_expression (tree type_tree, bool is_variant,
1260 const std::vector<tree> &vals, int union_index,
1261 location_t location)
1263 if (type_tree == error_mark_node)
1264 return error_mark_node;
1266 vec<constructor_elt, va_gc> *init;
1267 vec_alloc (init, vals.size ());
1269 tree sink = NULL_TREE;
1270 bool is_constant = true;
1271 tree field = TYPE_FIELDS (type_tree);
1273 if (is_variant)
1275 gcc_assert (union_index != -1);
1276 gcc_assert (TREE_CODE (type_tree) == UNION_TYPE);
1278 for (int i = 0; i < union_index; i++)
1280 gcc_assert (field != NULL_TREE);
1281 field = DECL_CHAIN (field);
1284 tree nested_ctor
1285 = constructor_expression (TREE_TYPE (field), false, vals, -1, location);
1287 constructor_elt empty = {NULL, NULL};
1288 constructor_elt *elt = init->quick_push (empty);
1289 elt->index = field;
1290 elt->value = convert_tree (TREE_TYPE (field), nested_ctor, location);
1291 if (!TREE_CONSTANT (elt->value))
1292 is_constant = false;
1294 else
1296 if (union_index != -1)
1298 gcc_assert (TREE_CODE (type_tree) == UNION_TYPE);
1299 tree val = vals.front ();
1300 for (int i = 0; i < union_index; i++)
1302 gcc_assert (field != NULL_TREE);
1303 field = DECL_CHAIN (field);
1305 if (TREE_TYPE (field) == error_mark_node || val == error_mark_node
1306 || TREE_TYPE (val) == error_mark_node)
1307 return error_mark_node;
1309 if (int_size_in_bytes (TREE_TYPE (field)) == 0)
1311 // GIMPLE cannot represent indices of zero-sized types so
1312 // trying to construct a map with zero-sized keys might lead
1313 // to errors. Instead, we evaluate each expression that
1314 // would have been added as a map element for its
1315 // side-effects and construct an empty map.
1316 append_to_statement_list (val, &sink);
1318 else
1320 constructor_elt empty = {NULL, NULL};
1321 constructor_elt *elt = init->quick_push (empty);
1322 elt->index = field;
1323 elt->value = convert_tree (TREE_TYPE (field), val, location);
1324 if (!TREE_CONSTANT (elt->value))
1325 is_constant = false;
1328 else
1330 gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE);
1331 for (std::vector<tree>::const_iterator p = vals.begin ();
1332 p != vals.end (); ++p, field = DECL_CHAIN (field))
1334 gcc_assert (field != NULL_TREE);
1335 tree val = (*p);
1336 if (TREE_TYPE (field) == error_mark_node || val == error_mark_node
1337 || TREE_TYPE (val) == error_mark_node)
1338 return error_mark_node;
1340 if (int_size_in_bytes (TREE_TYPE (field)) == 0)
1342 // GIMPLE cannot represent indices of zero-sized types so
1343 // trying to construct a map with zero-sized keys might lead
1344 // to errors. Instead, we evaluate each expression that
1345 // would have been added as a map element for its
1346 // side-effects and construct an empty map.
1347 append_to_statement_list (val, &sink);
1348 continue;
1351 constructor_elt empty = {NULL, NULL};
1352 constructor_elt *elt = init->quick_push (empty);
1353 elt->index = field;
1354 elt->value = convert_tree (TREE_TYPE (field), val, location);
1355 if (!TREE_CONSTANT (elt->value))
1356 is_constant = false;
1358 gcc_assert (field == NULL_TREE);
1362 tree ret = build_constructor (type_tree, init);
1363 if (is_constant)
1364 TREE_CONSTANT (ret) = 1;
1365 if (sink != NULL_TREE)
1366 ret = fold_build2_loc (location, COMPOUND_EXPR, type_tree, sink, ret);
1367 return ret;
1370 tree
1371 array_constructor_expression (tree type_tree,
1372 const std::vector<unsigned long> &indexes,
1373 const std::vector<tree> &vals,
1374 location_t location)
1376 if (type_tree == error_mark_node)
1377 return error_mark_node;
1379 gcc_assert (indexes.size () == vals.size ());
1381 tree element_type = TREE_TYPE (type_tree);
1382 HOST_WIDE_INT element_size = int_size_in_bytes (element_type);
1383 vec<constructor_elt, va_gc> *init;
1384 vec_alloc (init, element_size == 0 ? 0 : vals.size ());
1386 tree sink = NULL_TREE;
1387 bool is_constant = true;
1388 for (size_t i = 0; i < vals.size (); ++i)
1390 tree index = size_int (indexes[i]);
1391 tree val = vals[i];
1393 if (index == error_mark_node || val == error_mark_node)
1394 return error_mark_node;
1396 if (element_size == 0)
1398 // GIMPLE cannot represent arrays of zero-sized types so trying
1399 // to construct an array of zero-sized values might lead to errors.
1400 // Instead, we evaluate each expression that would have been added as
1401 // an array value for its side-effects and construct an empty array.
1402 append_to_statement_list (val, &sink);
1403 continue;
1406 if (!TREE_CONSTANT (val))
1407 is_constant = false;
1409 constructor_elt empty = {NULL, NULL};
1410 constructor_elt *elt = init->quick_push (empty);
1411 elt->index = index;
1412 elt->value = val;
1415 tree ret = build_constructor (type_tree, init);
1416 if (is_constant)
1417 TREE_CONSTANT (ret) = 1;
1418 if (sink != NULL_TREE)
1419 ret = fold_build2_loc (location, COMPOUND_EXPR, type_tree, sink, ret);
1420 return ret;
1423 // Build insns to create an array, initialize all elements of the array to
1424 // value, and return it
1425 tree
1426 array_initializer (tree fndecl, tree block, tree array_type, tree length,
1427 tree value, tree *tmp, location_t locus)
1429 std::vector<tree> stmts;
1431 // Temporary array we initialize with the desired value.
1432 tree t = NULL_TREE;
1433 Bvariable *tmp_array = temporary_variable (fndecl, block, array_type,
1434 NULL_TREE, true, locus, &t);
1435 tree arr = tmp_array->get_tree (locus);
1436 stmts.push_back (t);
1438 // Temporary for the array length used for initialization loop guard.
1439 Bvariable *tmp_len = temporary_variable (fndecl, block, size_type_node,
1440 length, true, locus, &t);
1441 tree len = tmp_len->get_tree (locus);
1442 stmts.push_back (t);
1444 // Temporary variable for pointer used to initialize elements.
1445 tree ptr_type = pointer_type (TREE_TYPE (array_type));
1446 tree ptr_init
1447 = build1_loc (locus, ADDR_EXPR, ptr_type,
1448 array_index_expression (arr, integer_zero_node, locus));
1449 Bvariable *tmp_ptr
1450 = temporary_variable (fndecl, block, ptr_type, ptr_init, false, locus, &t);
1451 tree ptr = tmp_ptr->get_tree (locus);
1452 stmts.push_back (t);
1454 // push statement list for the loop
1455 std::vector<tree> loop_stmts;
1457 // Loop exit condition:
1458 // if (length == 0) break;
1459 t = comparison_expression (ComparisonOperator::EQUAL, len,
1460 zero_expression (TREE_TYPE (len)), locus);
1462 t = exit_expression (t, locus);
1463 loop_stmts.push_back (t);
1465 // Assign value to the current pointer position
1466 // *ptr = value;
1467 t = assignment_statement (build_fold_indirect_ref (ptr), value, locus);
1468 loop_stmts.push_back (t);
1470 // Move pointer to next element
1471 // ptr++;
1472 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptr_type));
1473 t = build2 (POSTINCREMENT_EXPR, ptr_type, ptr, convert (ptr_type, size));
1474 loop_stmts.push_back (t);
1476 // Decrement loop counter.
1477 // length--;
1478 t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (len), len,
1479 convert (TREE_TYPE (len), integer_one_node));
1480 loop_stmts.push_back (t);
1482 // pop statments and finish loop
1483 tree loop_body = statement_list (loop_stmts);
1484 stmts.push_back (loop_expression (loop_body, locus));
1486 // Return the temporary in the provided pointer and the statement list which
1487 // initializes it.
1488 *tmp = tmp_array->get_tree (locus);
1489 return statement_list (stmts);
1492 // Return an expression representing ARRAY[INDEX]
1494 tree
1495 array_index_expression (tree array_tree, tree index_tree, location_t location)
1497 if (array_tree == error_mark_node || TREE_TYPE (array_tree) == error_mark_node
1498 || index_tree == error_mark_node)
1499 return error_mark_node;
1501 // A function call that returns a zero sized object will have been
1502 // changed to return void. If we see void here, assume we are
1503 // dealing with a zero sized type and just evaluate the operands.
1504 tree ret;
1505 if (TREE_TYPE (array_tree) != void_type_node)
1506 ret = build4_loc (location, ARRAY_REF, TREE_TYPE (TREE_TYPE (array_tree)),
1507 array_tree, index_tree, NULL_TREE, NULL_TREE);
1508 else
1509 ret = fold_build2_loc (location, COMPOUND_EXPR, void_type_node, array_tree,
1510 index_tree);
1512 return ret;
1515 // Create an expression for a call to FN_EXPR with FN_ARGS.
1516 tree
1517 call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
1518 location_t location)
1520 if (fn == error_mark_node || TREE_TYPE (fn) == error_mark_node)
1521 return error_mark_node;
1523 gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn)));
1524 tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
1526 size_t nargs = fn_args.size ();
1527 tree *args = nargs == 0 ? NULL : new tree[nargs];
1528 for (size_t i = 0; i < nargs; ++i)
1530 args[i] = fn_args.at (i);
1533 tree fndecl = fn;
1534 if (TREE_CODE (fndecl) == ADDR_EXPR)
1535 fndecl = TREE_OPERAND (fndecl, 0);
1537 // This is to support builtin math functions when using 80387 math.
1538 tree excess_type = NULL_TREE;
1539 if (optimize && TREE_CODE (fndecl) == FUNCTION_DECL
1540 && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
1541 && DECL_IS_UNDECLARED_BUILTIN (fndecl) && nargs > 0
1542 && ((SCALAR_FLOAT_TYPE_P (rettype)
1543 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[0])))
1544 || (COMPLEX_FLOAT_TYPE_P (rettype)
1545 && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args[0])))))
1547 excess_type = excess_precision_type (TREE_TYPE (args[0]));
1548 if (excess_type != NULL_TREE)
1550 tree excess_fndecl
1551 = mathfn_built_in (excess_type, DECL_FUNCTION_CODE (fndecl));
1552 if (excess_fndecl == NULL_TREE)
1553 excess_type = NULL_TREE;
1554 else
1556 fn = build_fold_addr_expr_loc (location, excess_fndecl);
1557 for (size_t i = 0; i < nargs; ++i)
1559 if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[i]))
1560 || COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args[i])))
1561 args[i] = ::convert (excess_type, args[i]);
1567 tree ret
1568 = build_call_array_loc (location,
1569 excess_type != NULL_TREE ? excess_type : rettype,
1570 fn, nargs, args);
1572 // check for deprecated function usage
1573 if (fndecl && TREE_DEPRECATED (fndecl))
1575 // set up the call-site information for `warn_deprecated_use`
1576 input_location = location;
1577 warn_deprecated_use (fndecl, NULL_TREE);
1580 if (chain_expr)
1581 CALL_EXPR_STATIC_CHAIN (ret) = chain_expr;
1583 if (excess_type != NULL_TREE)
1585 // Calling convert here can undo our excess precision change.
1586 // That may or may not be a bug in convert_to_real.
1587 ret = build1_loc (location, NOP_EXPR, rettype, ret);
1590 delete[] args;
1591 return ret;
1594 // Variable initialization.
1596 tree
1597 init_statement (tree, Bvariable *var, tree init_tree)
1599 tree var_tree = var->get_decl ();
1600 if (var_tree == error_mark_node || init_tree == error_mark_node)
1601 return error_mark_node;
1602 gcc_assert (TREE_CODE (var_tree) == VAR_DECL);
1604 // To avoid problems with GNU ld, we don't make zero-sized
1605 // externally visible variables. That might lead us to doing an
1606 // initialization of a zero-sized expression to a non-zero sized
1607 // variable, or vice-versa. Avoid crashes by omitting the
1608 // initializer. Such initializations don't mean anything anyhow.
1609 if (int_size_in_bytes (TREE_TYPE (var_tree)) != 0 && init_tree != NULL_TREE
1610 && TREE_TYPE (init_tree) != void_type_node
1611 && int_size_in_bytes (TREE_TYPE (init_tree)) != 0)
1613 DECL_INITIAL (var_tree) = init_tree;
1614 init_tree = NULL_TREE;
1617 tree ret = build1_loc (DECL_SOURCE_LOCATION (var_tree), DECL_EXPR,
1618 void_type_node, var_tree);
1619 if (init_tree != NULL_TREE)
1620 ret = build2_loc (DECL_SOURCE_LOCATION (var_tree), COMPOUND_EXPR,
1621 void_type_node, init_tree, ret);
1623 return ret;
1626 // Assignment.
1628 tree
1629 assignment_statement (tree lhs, tree rhs, location_t location)
1631 if (lhs == error_mark_node || rhs == error_mark_node)
1632 return error_mark_node;
1634 // To avoid problems with GNU ld, we don't make zero-sized
1635 // externally visible variables. That might lead us to doing an
1636 // assignment of a zero-sized expression to a non-zero sized
1637 // expression; avoid crashes here by avoiding assignments of
1638 // zero-sized expressions. Such assignments don't really mean
1639 // anything anyhow.
1640 if (TREE_TYPE (lhs) == void_type_node
1641 || int_size_in_bytes (TREE_TYPE (lhs)) == 0
1642 || TREE_TYPE (rhs) == void_type_node
1643 || int_size_in_bytes (TREE_TYPE (rhs)) == 0)
1644 return compound_statement (lhs, rhs);
1646 rhs = convert_tree (TREE_TYPE (lhs), rhs, location);
1648 return fold_build2_loc (location, MODIFY_EXPR, void_type_node, lhs, rhs);
1651 // Return.
1653 tree
1654 return_statement (tree fntree, tree val, location_t location)
1656 if (fntree == error_mark_node)
1657 return error_mark_node;
1659 tree result = DECL_RESULT (fntree);
1660 if (result == error_mark_node)
1661 return error_mark_node;
1663 if (val == error_mark_node)
1664 return error_mark_node;
1666 tree set
1667 = fold_build2_loc (location, MODIFY_EXPR, void_type_node, result, val);
1668 return fold_build1_loc (location, RETURN_EXPR, void_type_node, set);
1671 // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an
1672 // error occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and if not
1673 // NULL, it will always be executed. This is used for handling defers in Rust
1674 // functions. In C++, the resulting code is of this form:
1675 // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }
1677 tree
1678 exception_handler_statement (tree try_stmt, tree except_stmt, tree finally_stmt,
1679 location_t location)
1681 if (try_stmt == error_mark_node || except_stmt == error_mark_node
1682 || finally_stmt == error_mark_node)
1683 return error_mark_node;
1685 if (except_stmt != NULL_TREE)
1686 try_stmt = build2_loc (location, TRY_CATCH_EXPR, void_type_node, try_stmt,
1687 build2_loc (location, CATCH_EXPR, void_type_node,
1688 NULL, except_stmt));
1689 if (finally_stmt != NULL_TREE)
1690 try_stmt = build2_loc (location, TRY_FINALLY_EXPR, void_type_node, try_stmt,
1691 finally_stmt);
1692 return try_stmt;
1695 // If.
1697 tree
1698 if_statement (tree, tree cond_tree, tree then_tree, tree else_tree,
1699 location_t location)
1701 if (cond_tree == error_mark_node || then_tree == error_mark_node
1702 || else_tree == error_mark_node)
1703 return error_mark_node;
1704 tree ret = build3_loc (location, COND_EXPR, void_type_node, cond_tree,
1705 then_tree, else_tree);
1706 return ret;
1709 // Loops
1711 tree
1712 loop_expression (tree body, location_t locus)
1714 return fold_build1_loc (locus, LOOP_EXPR, void_type_node, body);
1717 tree
1718 exit_expression (tree cond_tree, location_t locus)
1720 return fold_build1_loc (locus, EXIT_EXPR, void_type_node, cond_tree);
1723 // Pair of statements.
1725 tree
1726 compound_statement (tree s1, tree s2)
1728 tree stmt_list = NULL_TREE;
1729 tree t = s1;
1730 if (t == error_mark_node)
1731 return error_mark_node;
1732 append_to_statement_list (t, &stmt_list);
1733 t = s2;
1734 if (t == error_mark_node)
1735 return error_mark_node;
1736 append_to_statement_list (t, &stmt_list);
1738 // If neither statement has any side effects, stmt_list can be NULL
1739 // at this point.
1740 if (stmt_list == NULL_TREE)
1741 stmt_list = integer_zero_node;
1743 return stmt_list;
1746 // List of statements.
1748 tree
1749 statement_list (const std::vector<tree> &statements)
1751 tree stmt_list = NULL_TREE;
1752 for (std::vector<tree>::const_iterator p = statements.begin ();
1753 p != statements.end (); ++p)
1755 tree t = (*p);
1756 if (t == error_mark_node)
1757 return error_mark_node;
1758 append_to_statement_list (t, &stmt_list);
1760 return stmt_list;
1763 // Make a block. For some reason gcc uses a dual structure for
1764 // blocks: BLOCK tree nodes and BIND_EXPR tree nodes. Since the
1765 // BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in
1766 // the Bblock.
1768 tree
1769 block (tree fndecl, tree enclosing, const std::vector<Bvariable *> &vars,
1770 location_t start_location, location_t)
1772 tree block_tree = make_node (BLOCK);
1773 if (enclosing == NULL)
1775 gcc_assert (fndecl != NULL_TREE);
1777 // We may have already created a block for local variables when
1778 // we take the address of a parameter.
1779 if (DECL_INITIAL (fndecl) == NULL_TREE)
1781 BLOCK_SUPERCONTEXT (block_tree) = fndecl;
1782 DECL_INITIAL (fndecl) = block_tree;
1784 else
1786 tree superblock_tree = DECL_INITIAL (fndecl);
1787 BLOCK_SUPERCONTEXT (block_tree) = superblock_tree;
1788 tree *pp;
1789 for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE;
1790 pp = &BLOCK_CHAIN (*pp))
1792 *pp = block_tree;
1795 else
1797 tree superblock_tree = BIND_EXPR_BLOCK (enclosing);
1798 gcc_assert (TREE_CODE (superblock_tree) == BLOCK);
1800 BLOCK_SUPERCONTEXT (block_tree) = superblock_tree;
1801 tree *pp;
1802 for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE;
1803 pp = &BLOCK_CHAIN (*pp))
1805 *pp = block_tree;
1808 tree *pp = &BLOCK_VARS (block_tree);
1809 for (std::vector<Bvariable *>::const_iterator pv = vars.begin ();
1810 pv != vars.end (); ++pv)
1812 *pp = (*pv)->get_decl ();
1813 if (*pp != error_mark_node)
1814 pp = &DECL_CHAIN (*pp);
1816 *pp = NULL_TREE;
1818 TREE_USED (block_tree) = 1;
1820 tree bind_tree = build3_loc (start_location, BIND_EXPR, void_type_node,
1821 BLOCK_VARS (block_tree), NULL_TREE, block_tree);
1822 TREE_SIDE_EFFECTS (bind_tree) = 1;
1823 return bind_tree;
1826 // Add statements to a block.
1828 void
1829 block_add_statements (tree bind_tree, const std::vector<tree> &statements)
1831 tree stmt_list = NULL_TREE;
1832 for (std::vector<tree>::const_iterator p = statements.begin ();
1833 p != statements.end (); ++p)
1835 tree s = (*p);
1836 if (s != error_mark_node)
1837 append_to_statement_list (s, &stmt_list);
1840 gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
1841 BIND_EXPR_BODY (bind_tree) = stmt_list;
1844 // This is not static because we declare it with GTY(()) in rust-c.h.
1845 tree rust_non_zero_struct;
1847 // Return a type corresponding to TYPE with non-zero size.
1849 tree
1850 non_zero_size_type (tree type)
1852 if (int_size_in_bytes (type) != 0)
1853 return type;
1855 switch (TREE_CODE (type))
1857 case RECORD_TYPE:
1858 if (TYPE_FIELDS (type) != NULL_TREE)
1860 tree ns = make_node (RECORD_TYPE);
1861 tree field_trees = NULL_TREE;
1862 tree *pp = &field_trees;
1863 for (tree field = TYPE_FIELDS (type); field != NULL_TREE;
1864 field = DECL_CHAIN (field))
1866 tree ft = TREE_TYPE (field);
1867 if (field == TYPE_FIELDS (type))
1868 ft = non_zero_size_type (ft);
1869 tree f = build_decl (DECL_SOURCE_LOCATION (field), FIELD_DECL,
1870 DECL_NAME (field), ft);
1871 DECL_CONTEXT (f) = ns;
1872 *pp = f;
1873 pp = &DECL_CHAIN (f);
1875 TYPE_FIELDS (ns) = field_trees;
1876 layout_type (ns);
1877 return ns;
1880 if (rust_non_zero_struct == NULL_TREE)
1882 type = make_node (RECORD_TYPE);
1883 tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
1884 get_identifier ("dummy"), boolean_type_node);
1885 DECL_CONTEXT (field) = type;
1886 TYPE_FIELDS (type) = field;
1887 layout_type (type);
1888 rust_non_zero_struct = type;
1890 return rust_non_zero_struct;
1892 case ARRAY_TYPE: {
1893 tree element_type = non_zero_size_type (TREE_TYPE (type));
1894 return build_array_type_nelts (element_type, 1);
1897 default:
1898 rust_unreachable ();
1901 rust_unreachable ();
1904 // Convert EXPR_TREE to TYPE_TREE. Sometimes the same unnamed Rust type
1905 // can be created multiple times and thus have multiple tree
1906 // representations. Make sure this does not confuse the middle-end.
1908 tree
1909 convert_tree (tree type_tree, tree expr_tree, location_t location)
1911 if (type_tree == TREE_TYPE (expr_tree))
1912 return expr_tree;
1914 if (type_tree == error_mark_node || expr_tree == error_mark_node
1915 || TREE_TYPE (expr_tree) == error_mark_node)
1916 return error_mark_node;
1918 if (POINTER_TYPE_P (type_tree) || INTEGRAL_TYPE_P (type_tree)
1919 || SCALAR_FLOAT_TYPE_P (type_tree) || COMPLEX_FLOAT_TYPE_P (type_tree))
1920 return fold_convert_loc (location, type_tree, expr_tree);
1921 else if (TREE_CODE (type_tree) == RECORD_TYPE
1922 || TREE_CODE (type_tree) == UNION_TYPE
1923 || TREE_CODE (type_tree) == ARRAY_TYPE)
1925 gcc_assert (int_size_in_bytes (type_tree)
1926 == int_size_in_bytes (TREE_TYPE (expr_tree)));
1927 if (TYPE_MAIN_VARIANT (type_tree)
1928 == TYPE_MAIN_VARIANT (TREE_TYPE (expr_tree)))
1929 return fold_build1_loc (location, NOP_EXPR, type_tree, expr_tree);
1930 return fold_build1_loc (location, VIEW_CONVERT_EXPR, type_tree,
1931 expr_tree);
1934 rust_unreachable ();
1937 // Make a global variable.
1939 Bvariable *
1940 global_variable (const std::string &var_name, const std::string &asm_name,
1941 tree type_tree, bool is_external, bool is_hidden,
1942 bool in_unique_section, location_t location)
1944 if (type_tree == error_mark_node)
1945 return Bvariable::error_variable ();
1947 // The GNU linker does not like dynamic variables with zero size.
1948 tree orig_type_tree = type_tree;
1949 if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0)
1950 type_tree = non_zero_size_type (type_tree);
1952 tree decl = build_decl (location, VAR_DECL,
1953 get_identifier_from_string (var_name), type_tree);
1954 if (is_external)
1955 DECL_EXTERNAL (decl) = 1;
1956 else
1957 TREE_STATIC (decl) = 1;
1958 if (!is_hidden)
1960 TREE_PUBLIC (decl) = 1;
1961 SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
1963 else
1965 SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
1968 TREE_USED (decl) = 1;
1970 if (in_unique_section)
1971 resolve_unique_section (decl, 0, 1);
1973 rust_preserve_from_gc (decl);
1975 return new Bvariable (decl, orig_type_tree);
1978 // Set the initial value of a global variable.
1980 void
1981 global_variable_set_init (Bvariable *var, tree expr_tree)
1983 if (expr_tree == error_mark_node)
1984 return;
1985 gcc_assert (TREE_CONSTANT (expr_tree));
1986 tree var_decl = var->get_decl ();
1987 if (var_decl == error_mark_node)
1988 return;
1989 DECL_INITIAL (var_decl) = expr_tree;
1991 // If this variable goes in a unique section, it may need to go into
1992 // a different one now that DECL_INITIAL is set.
1993 if (symtab_node::get (var_decl)
1994 && symtab_node::get (var_decl)->implicit_section)
1996 set_decl_section_name (var_decl, (const char *) NULL);
1997 resolve_unique_section (var_decl, compute_reloc_for_constant (expr_tree),
2002 // Make a local variable.
2004 Bvariable *
2005 local_variable (tree function, const std::string &name, tree type_tree,
2006 Bvariable *decl_var, location_t location)
2008 if (type_tree == error_mark_node)
2009 return Bvariable::error_variable ();
2010 tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name),
2011 type_tree);
2012 DECL_CONTEXT (decl) = function;
2014 if (decl_var != NULL)
2016 DECL_HAS_VALUE_EXPR_P (decl) = 1;
2017 SET_DECL_VALUE_EXPR (decl, decl_var->get_decl ());
2019 rust_preserve_from_gc (decl);
2020 return new Bvariable (decl);
2023 // Make a function parameter variable.
2025 Bvariable *
2026 parameter_variable (tree function, const std::string &name, tree type_tree,
2027 location_t location)
2029 if (type_tree == error_mark_node)
2030 return Bvariable::error_variable ();
2031 tree decl = build_decl (location, PARM_DECL,
2032 get_identifier_from_string (name), type_tree);
2033 DECL_CONTEXT (decl) = function;
2034 DECL_ARG_TYPE (decl) = type_tree;
2036 rust_preserve_from_gc (decl);
2037 return new Bvariable (decl);
2040 // Make a static chain variable.
2042 Bvariable *
2043 static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
2044 location_t location)
2046 if (type_tree == error_mark_node)
2047 return Bvariable::error_variable ();
2048 tree decl = build_decl (location, PARM_DECL,
2049 get_identifier_from_string (name), type_tree);
2050 DECL_CONTEXT (decl) = fndecl;
2051 DECL_ARG_TYPE (decl) = type_tree;
2052 TREE_USED (decl) = 1;
2053 DECL_ARTIFICIAL (decl) = 1;
2054 DECL_IGNORED_P (decl) = 1;
2055 TREE_READONLY (decl) = 1;
2057 struct function *f = DECL_STRUCT_FUNCTION (fndecl);
2058 if (f == NULL)
2060 push_struct_function (fndecl);
2061 pop_cfun ();
2062 f = DECL_STRUCT_FUNCTION (fndecl);
2064 gcc_assert (f->static_chain_decl == NULL);
2065 f->static_chain_decl = decl;
2066 DECL_STATIC_CHAIN (fndecl) = 1;
2068 rust_preserve_from_gc (decl);
2069 return new Bvariable (decl);
2072 // Make a temporary variable.
2074 Bvariable *
2075 temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
2076 bool is_address_taken, location_t location,
2077 tree *pstatement)
2079 gcc_assert (fndecl != NULL_TREE);
2080 if (type_tree == error_mark_node || init_tree == error_mark_node
2081 || fndecl == error_mark_node)
2083 *pstatement = error_mark_node;
2084 return Bvariable::error_variable ();
2087 tree var;
2088 // We can only use create_tmp_var if the type is not addressable.
2089 if (!TREE_ADDRESSABLE (type_tree))
2091 if (DECL_STRUCT_FUNCTION (fndecl) == NULL)
2092 push_struct_function (fndecl);
2093 else
2094 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
2096 var = create_tmp_var (type_tree, "RUSTTMP");
2097 pop_cfun ();
2099 else
2101 gcc_assert (bind_tree != NULL_TREE);
2102 var = build_decl (location, VAR_DECL, create_tmp_var_name ("RUSTTMP"),
2103 type_tree);
2104 DECL_ARTIFICIAL (var) = 1;
2105 DECL_IGNORED_P (var) = 1;
2106 TREE_USED (var) = 1;
2107 DECL_CONTEXT (var) = fndecl;
2109 // We have to add this variable to the BLOCK and the BIND_EXPR.
2110 gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
2111 tree block_tree = BIND_EXPR_BLOCK (bind_tree);
2112 gcc_assert (TREE_CODE (block_tree) == BLOCK);
2113 DECL_CHAIN (var) = BLOCK_VARS (block_tree);
2114 BLOCK_VARS (block_tree) = var;
2115 BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree);
2118 if (type_size (type_tree) != 0 && init_tree != NULL_TREE
2119 && TREE_TYPE (init_tree) != void_type_node)
2120 DECL_INITIAL (var) = convert_tree (type_tree, init_tree, location);
2122 if (is_address_taken)
2123 TREE_ADDRESSABLE (var) = 1;
2125 *pstatement = build1_loc (location, DECL_EXPR, void_type_node, var);
2127 // For a zero sized type, don't initialize VAR with BINIT, but still
2128 // evaluate BINIT for its side effects.
2129 if (init_tree != NULL_TREE
2130 && (type_size (type_tree) == 0
2131 || TREE_TYPE (init_tree) == void_type_node))
2132 *pstatement = compound_statement (init_tree, *pstatement);
2134 return new Bvariable (var);
2137 // Make a label.
2139 tree
2140 label (tree func_tree, const std::string &name, location_t location)
2142 tree decl;
2143 if (name.empty ())
2145 if (DECL_STRUCT_FUNCTION (func_tree) == NULL)
2146 push_struct_function (func_tree);
2147 else
2148 push_cfun (DECL_STRUCT_FUNCTION (func_tree));
2150 decl = create_artificial_label (location);
2152 pop_cfun ();
2154 else
2156 tree id = get_identifier_from_string (name);
2157 decl = build_decl (location, LABEL_DECL, id, void_type_node);
2158 DECL_CONTEXT (decl) = func_tree;
2160 return decl;
2163 // Make a statement which defines a label.
2165 tree
2166 label_definition_statement (tree label)
2168 return fold_build1_loc (DECL_SOURCE_LOCATION (label), LABEL_EXPR,
2169 void_type_node, label);
2172 // Make a goto statement.
2174 tree
2175 goto_statement (tree label, location_t location)
2177 return fold_build1_loc (location, GOTO_EXPR, void_type_node, label);
2180 // Get the address of a label.
2182 tree
2183 label_address (tree label, location_t location)
2185 TREE_USED (label) = 1;
2186 TREE_ADDRESSABLE (label) = 1;
2187 tree ret = fold_convert_loc (location, ptr_type_node,
2188 build_fold_addr_expr_loc (location, label));
2189 return ret;
2192 // Declare or define a new function.
2194 tree
2195 function (tree functype, const std::string &name, const std::string &asm_name,
2196 unsigned int flags, location_t location)
2198 if (functype != error_mark_node)
2200 gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
2201 functype = TREE_TYPE (functype);
2203 tree id = get_identifier_from_string (name);
2204 if (functype == error_mark_node || id == error_mark_node)
2205 return error_mark_node;
2207 tree decl = build_decl (location, FUNCTION_DECL, id, functype);
2208 if (!asm_name.empty ())
2209 SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
2211 if ((flags & function_is_declaration) != 0)
2212 DECL_EXTERNAL (decl) = 1;
2213 else
2215 tree restype = TREE_TYPE (functype);
2216 tree resdecl = build_decl (location, RESULT_DECL, NULL_TREE, restype);
2217 DECL_ARTIFICIAL (resdecl) = 1;
2218 DECL_IGNORED_P (resdecl) = 1;
2219 DECL_CONTEXT (resdecl) = decl;
2220 DECL_RESULT (decl) = resdecl;
2222 if ((flags & function_is_uninlinable) != 0)
2223 DECL_UNINLINABLE (decl) = 1;
2224 if ((flags & function_does_not_return) != 0)
2225 TREE_THIS_VOLATILE (decl) = 1;
2226 if ((flags & function_in_unique_section) != 0)
2227 resolve_unique_section (decl, 0, 1);
2229 rust_preserve_from_gc (decl);
2230 return decl;
2233 // Create a statement that runs all deferred calls for FUNCTION. This should
2234 // be a statement that looks like this in C++:
2235 // finish:
2236 // try { UNDEFER; } catch { CHECK_DEFER; goto finish; }
2238 tree
2239 function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
2240 location_t location)
2242 if (undefer_tree == error_mark_node || defer_tree == error_mark_node
2243 || function == error_mark_node)
2244 return error_mark_node;
2246 if (DECL_STRUCT_FUNCTION (function) == NULL)
2247 push_struct_function (function);
2248 else
2249 push_cfun (DECL_STRUCT_FUNCTION (function));
2251 tree stmt_list = NULL;
2252 tree label = Backend::label (function, "", location);
2253 tree label_def = label_definition_statement (label);
2254 append_to_statement_list (label_def, &stmt_list);
2256 tree jump_stmt = goto_statement (label, location);
2257 tree catch_body
2258 = build2 (COMPOUND_EXPR, void_type_node, defer_tree, jump_stmt);
2259 catch_body = build2 (CATCH_EXPR, void_type_node, NULL, catch_body);
2260 tree try_catch
2261 = build2 (TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
2262 append_to_statement_list (try_catch, &stmt_list);
2263 pop_cfun ();
2265 return stmt_list;
2268 // Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
2269 // This will only be called for a function definition.
2271 bool
2272 function_set_parameters (tree function,
2273 const std::vector<Bvariable *> &param_vars)
2275 if (function == error_mark_node)
2276 return false;
2278 tree params = NULL_TREE;
2279 tree *pp = &params;
2280 for (std::vector<Bvariable *>::const_iterator pv = param_vars.begin ();
2281 pv != param_vars.end (); ++pv)
2283 *pp = (*pv)->get_decl ();
2284 gcc_assert (*pp != error_mark_node);
2285 pp = &DECL_CHAIN (*pp);
2287 *pp = NULL_TREE;
2288 DECL_ARGUMENTS (function) = params;
2289 return true;
2292 // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
2293 // FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
2294 // emit early debugging information.
2296 void
2297 write_global_definitions (const std::vector<tree> &type_decls,
2298 const std::vector<tree> &constant_decls,
2299 const std::vector<tree> &function_decls,
2300 const std::vector<Bvariable *> &variable_decls)
2302 size_t count_definitions = type_decls.size () + constant_decls.size ()
2303 + function_decls.size () + variable_decls.size ();
2305 tree *defs = new tree[count_definitions];
2307 // Convert all non-erroneous declarations into Gimple form.
2308 size_t i = 0;
2309 for (std::vector<Bvariable *>::const_iterator p = variable_decls.begin ();
2310 p != variable_decls.end (); ++p)
2312 tree v = (*p)->get_decl ();
2313 if (v != error_mark_node)
2315 defs[i] = v;
2316 rust_preserve_from_gc (defs[i]);
2317 ++i;
2321 for (std::vector<tree>::const_iterator p = type_decls.begin ();
2322 p != type_decls.end (); ++p)
2324 tree type_tree = (*p);
2325 if (type_tree != error_mark_node && IS_TYPE_OR_DECL_P (type_tree))
2327 defs[i] = TYPE_NAME (type_tree);
2328 gcc_assert (defs[i] != NULL);
2329 rust_preserve_from_gc (defs[i]);
2330 ++i;
2333 for (std::vector<tree>::const_iterator p = constant_decls.begin ();
2334 p != constant_decls.end (); ++p)
2336 if ((*p) != error_mark_node)
2338 defs[i] = (*p);
2339 rust_preserve_from_gc (defs[i]);
2340 ++i;
2343 for (std::vector<tree>::const_iterator p = function_decls.begin ();
2344 p != function_decls.end (); ++p)
2346 tree decl = (*p);
2347 if (decl != error_mark_node)
2349 rust_preserve_from_gc (decl);
2350 if (DECL_STRUCT_FUNCTION (decl) == NULL)
2351 allocate_struct_function (decl, false);
2352 dump_function (TDI_original, decl);
2353 cgraph_node::finalize_function (decl, true);
2355 defs[i] = decl;
2356 ++i;
2360 // Pass everything back to the middle-end.
2362 wrapup_global_declarations (defs, i);
2364 delete[] defs;
2367 } // namespace Backend