1 // rust-gcc.cc -- Rust frontend to gcc IR.
2 // Copyright (C) 2011-2025 Free Software Foundation, Inc.
3 // Contributed by Ian Lance Taylor, Google.
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
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
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.
30 #include "fold-const.h"
31 #include "stringpool.h"
32 #include "stor-layout.h"
34 #include "tree-iterator.h"
39 #include "gimple-expr.h"
41 #include "langhooks.h"
46 #include "print-tree.h"
49 #include "rust-location.h"
50 #include "rust-linemap.h"
51 #include "rust-backend.h"
52 #include "rust-object-export.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
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_
)
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
);
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.
95 get_identifier_from_string (const std::string
&str
)
97 return get_identifier_with_length (str
.data (), str
.length ());
102 // Define the built-in functions that are exposed to GCCRust.
107 /* We need to define the fetch_and_add functions, since we use them
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,
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),
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),
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),
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,
169 // this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll",
170 // build_function_type_list (integer_type_node,
171 // long_long_unsigned_type_node,
174 // this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz",
175 // build_function_type_list (integer_type_node,
176 // unsigned_type_node,
179 // this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
180 // build_function_type_list (integer_type_node,
181 // long_long_unsigned_type_node,
184 // this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
185 // build_function_type_list (integer_type_node,
186 // unsigned_type_node,
189 // this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll",
191 // build_function_type_list (integer_type_node,
192 // long_long_unsigned_type_node,
195 // this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
196 // build_function_type_list (uint16_type_node,
197 // uint16_type_node, NULL_TREE),
199 // this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
200 // build_function_type_list (uint32_type_node,
201 // uint32_type_node, NULL_TREE),
203 // this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64",
204 // build_function_type_list (uint64_type_node,
205 // uint64_type_node, NULL_TREE),
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",
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,
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
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,
241 // The compiler uses __builtin_unreachable for cases that cannot
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,
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,
258 // t = build_function_type_list (void_type_node, ptr_type_node,
260 // integer_type_node, NULL_TREE);
261 // this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t,
264 // t = build_function_type_list (void_type_node, ptr_type_node,
266 // integer_type_node, NULL_TREE);
267 // this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t,
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",
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",
282 // t = build_function_type_list (boolean_type_node, ptr_type_node,
284 // uint32_type_node, boolean_type_node,
285 // integer_type_node, integer_type_node,
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,
292 // uint64_type_node, boolean_type_node,
293 // integer_type_node, integer_type_node,
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",
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",
308 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
309 // unsigned_char_type_node, integer_type_node,
311 // this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
313 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1",
316 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
317 // unsigned_char_type_node, integer_type_node,
319 // this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
322 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1",
336 debug_tree (t
->get_decl ());
340 get_identifier_node (const std::string
&str
)
342 return get_identifier_with_length (str
.data (), str
.length ());
350 if (wchar
== NULL_TREE
)
352 wchar
= make_unsigned_type (32);
353 TYPE_STRING_FLAG (wchar
) = 1;
359 // Get an unnamed integer 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
;
376 integer_type (bool is_unsigned
, int bits
)
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
;
390 type
= make_unsigned_type (bits
);
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
;
403 type
= make_signed_type (bits
);
408 // Get an unnamed float type.
411 float_type (int bits
)
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
;
422 type
= make_node (REAL_TYPE
);
423 TYPE_PRECISION (type
) = bits
;
429 // Get a pointer type.
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
);
440 // Get a reference type.
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
);
451 // Get immutable type
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
);
462 // Make a function type.
465 function_type (const typed_identifier
&receiver
,
466 const std::vector
<typed_identifier
> ¶meters
,
467 const std::vector
<typed_identifier
> &results
, tree result_struct
,
470 tree args
= NULL_TREE
;
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
)
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
;
496 if (results
.empty ())
497 result
= void_type_node
;
498 else if (results
.size () == 1)
499 result
= results
.front ().type
;
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
);
516 function_type_variadic (const typed_identifier
&receiver
,
517 const std::vector
<typed_identifier
> ¶meters
,
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
);
525 if (receiver
.type
!= NULL_TREE
)
527 tree t
= receiver
.type
;
528 if (t
== error_mark_node
)
529 return error_mark_node
;
534 for (std::vector
<typed_identifier
>::const_iterator p
= parameters
.begin ();
535 p
!= parameters
.end (); ++p
)
538 if (t
== error_mark_node
)
539 return error_mark_node
;
544 if (results
.empty ())
545 result
= void_type_node
;
546 else if (results
.size () == 1)
547 result
= results
.front ().type
;
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
);
564 function_ptr_type (tree result_type
, const std::vector
<tree
> ¶meters
,
565 location_t
/* locus */)
567 tree args
= NULL_TREE
;
570 for (auto ¶m
: 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.
595 struct_type (const std::vector
<typed_identifier
> &fields
)
597 return fill_in_fields (make_node (RECORD_TYPE
), fields
);
600 // Make a union type.
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.
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
;
625 pp
= &DECL_CHAIN (field
);
627 TYPE_FIELDS (fill
) = field_trees
;
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
);
639 // Make an array type.
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.
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
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
);
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
));
679 // Return a named version of a type.
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
;
701 tree copy
= build_variant_type_copy (type
);
703 = build_decl (location
, TYPE_DECL
, get_identifier_from_string (name
), copy
);
704 DECL_ORIGINAL_TYPE (decl
) = type
;
705 TYPE_NAME (copy
) = decl
;
709 // Return the size of a type.
714 if (t
== error_mark_node
)
716 if (t
== void_type_node
)
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
)
727 // Return the alignment of a type.
730 type_alignment (tree t
)
732 if (t
== error_mark_node
)
734 return TYPE_ALIGN_UNIT (t
);
737 // Return the alignment of a struct field of type BTYPE.
740 type_field_alignment (tree t
)
742 if (t
== error_mark_node
)
744 return rust_field_alignment (t
);
747 // Return the offset of a field in a struct.
750 type_field_offset (tree struct_tree
, size_t index
)
752 if (struct_tree
== error_mark_node
)
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
);
767 // Return the zero value for a type.
770 zero_expression (tree t
)
773 if (t
== error_mark_node
)
774 ret
= error_mark_node
;
776 ret
= build_zero_cst (t
);
780 // An expression that references a variable.
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.
791 float_constant_expression (tree t
, mpfr_t val
)
794 if (t
== error_mark_node
)
795 return error_mark_node
;
798 real_from_mpfr (&r1
, val
, t
, GMP_RNDN
);
800 real_convert (&r2
, TYPE_MODE (t
), &r1
);
801 ret
= build_real (t
, r2
);
805 // Make a constant string expression.
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
;
821 wchar_constant_expression (wchar_t c
)
823 return build_int_cst (wchar_type (), c
);
827 char_constant_expression (char c
)
829 return build_int_cst (char_type_node
, c
);
832 // Make a constant boolean expression.
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.
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
;
850 if (type_size (type_tree
) == 0 || TREE_TYPE (expr_tree
) == void_type_node
)
852 // Do not convert zero-sized types.
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
);
868 ret
= fold_convert_loc (location
, type_tree
, expr_tree
);
873 // Return an expression for the field at INDEX in BSTRUCT.
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;
904 // Return an expression that executes BSTAT before BEXPR.
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
;
912 = fold_build2_loc (location
, COMPOUND_EXPR
, TREE_TYPE (expr
), stat
, expr
);
916 // Return an expression that executes THEN_EXPR if CONDITION is true, or
917 // ELSE_EXPR otherwise.
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
,
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
)
939 case NegationOperator::NEGATE
:
941 case NegationOperator::NOT
:
942 return TRUTH_NOT_EXPR
;
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
952 static enum tree_code
953 operator_to_tree_code (ArithmeticOrLogicalOperator op
, bool floating_point
)
957 case ArithmeticOrLogicalOperator::ADD
:
959 case ArithmeticOrLogicalOperator::SUBTRACT
:
961 case ArithmeticOrLogicalOperator::MULTIPLY
:
963 case ArithmeticOrLogicalOperator::DIVIDE
:
967 return TRUNC_DIV_EXPR
;
968 case ArithmeticOrLogicalOperator::MODULUS
:
969 return TRUNC_MOD_EXPR
;
970 case ArithmeticOrLogicalOperator::BITWISE_AND
:
972 case ArithmeticOrLogicalOperator::BITWISE_OR
:
974 case ArithmeticOrLogicalOperator::BITWISE_XOR
:
976 case ArithmeticOrLogicalOperator::LEFT_SHIFT
:
978 case ArithmeticOrLogicalOperator::RIGHT_SHIFT
:
985 static enum tree_code
986 operator_to_tree_code (ComparisonOperator op
)
990 case ComparisonOperator::EQUAL
:
992 case ComparisonOperator::NOT_EQUAL
:
994 case ComparisonOperator::GREATER_THAN
:
996 case ComparisonOperator::LESS_THAN
:
998 case ComparisonOperator::GREATER_OR_EQUAL
:
1000 case ComparisonOperator::LESS_OR_EQUAL
:
1003 rust_unreachable ();
1007 static enum tree_code
1008 operator_to_tree_code (LazyBooleanOperator op
)
1012 case LazyBooleanOperator::LOGICAL_OR
:
1013 return TRUTH_ORIF_EXPR
;
1014 case LazyBooleanOperator::LOGICAL_AND
:
1015 return TRUTH_ANDIF_EXPR
;
1017 rust_unreachable ();
1021 /* Helper function for deciding if a tree is a floating point node. */
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.
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
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
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
;
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
);
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
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
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
;
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
);
1110 is_overflowing_expr (ArithmeticOrLogicalOperator op
)
1114 case ArithmeticOrLogicalOperator::ADD
:
1115 case ArithmeticOrLogicalOperator::SUBTRACT
:
1116 case ArithmeticOrLogicalOperator::MULTIPLY
:
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
;
1133 case ArithmeticOrLogicalOperator::ADD
:
1134 builtin_ctx
.lookup_simple_builtin ("__builtin_add_overflow", &builtin
);
1136 case ArithmeticOrLogicalOperator::SUBTRACT
:
1137 builtin_ctx
.lookup_simple_builtin ("__builtin_sub_overflow", &builtin
);
1139 case ArithmeticOrLogicalOperator::MULTIPLY
:
1140 builtin_ctx
.lookup_simple_builtin ("__builtin_mul_overflow", &builtin
);
1143 rust_unreachable ();
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
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
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
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;
1200 = build_call_expr_loc (location
, builtin
, 3, left
, right
, result_ref
);
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;
1215 // Return an expression for the comparison operation LEFT OP RIGHT.
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
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. */
1231 = fold_build2_loc (location
, tree_code
, tree_type
, left_tree
, right_tree
);
1235 // Return an expression for the lazy boolean operation LEFT OP RIGHT.
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
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
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. */
1252 = fold_build2_loc (location
, tree_code
, tree_type
, left_tree
, right_tree
);
1256 // Return an expression that constructs BTYPE with VALS.
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
);
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
);
1285 = constructor_expression (TREE_TYPE (field
), false, vals
, -1, location
);
1287 constructor_elt empty
= {NULL
, NULL
};
1288 constructor_elt
*elt
= init
->quick_push (empty
);
1290 elt
->value
= convert_tree (TREE_TYPE (field
), nested_ctor
, location
);
1291 if (!TREE_CONSTANT (elt
->value
))
1292 is_constant
= false;
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
);
1320 constructor_elt empty
= {NULL
, NULL
};
1321 constructor_elt
*elt
= init
->quick_push (empty
);
1323 elt
->value
= convert_tree (TREE_TYPE (field
), val
, location
);
1324 if (!TREE_CONSTANT (elt
->value
))
1325 is_constant
= false;
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
);
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
);
1351 constructor_elt empty
= {NULL
, NULL
};
1352 constructor_elt
*elt
= init
->quick_push (empty
);
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
);
1364 TREE_CONSTANT (ret
) = 1;
1365 if (sink
!= NULL_TREE
)
1366 ret
= fold_build2_loc (location
, COMPOUND_EXPR
, type_tree
, sink
, ret
);
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
]);
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
);
1406 if (!TREE_CONSTANT (val
))
1407 is_constant
= false;
1409 constructor_elt empty
= {NULL
, NULL
};
1410 constructor_elt
*elt
= init
->quick_push (empty
);
1415 tree ret
= build_constructor (type_tree
, init
);
1417 TREE_CONSTANT (ret
) = 1;
1418 if (sink
!= NULL_TREE
)
1419 ret
= fold_build2_loc (location
, COMPOUND_EXPR
, type_tree
, sink
, ret
);
1423 // Build insns to create an array, initialize all elements of the array to
1424 // value, and return it
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.
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
));
1447 = build1_loc (locus
, ADDR_EXPR
, ptr_type
,
1448 array_index_expression (arr
, integer_zero_node
, locus
));
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
1467 t
= assignment_statement (build_fold_indirect_ref (ptr
), value
, locus
);
1468 loop_stmts
.push_back (t
);
1470 // Move pointer to next element
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.
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
1488 *tmp
= tmp_array
->get_tree (locus
);
1489 return statement_list (stmts
);
1492 // Return an expression representing ARRAY[INDEX]
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.
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
);
1509 ret
= fold_build2_loc (location
, COMPOUND_EXPR
, void_type_node
, array_tree
,
1515 // Create an expression for a call to FN_EXPR with FN_ARGS.
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
);
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
)
1551 = mathfn_built_in (excess_type
, DECL_FUNCTION_CODE (fndecl
));
1552 if (excess_fndecl
== NULL_TREE
)
1553 excess_type
= NULL_TREE
;
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
]);
1568 = build_call_array_loc (location
,
1569 excess_type
!= NULL_TREE
? excess_type
: rettype
,
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
);
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
);
1594 // Variable initialization.
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
);
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
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
);
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
;
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; }
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
,
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
);
1712 loop_expression (tree body
, location_t locus
)
1714 return fold_build1_loc (locus
, LOOP_EXPR
, void_type_node
, body
);
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.
1726 compound_statement (tree s1
, tree s2
)
1728 tree stmt_list
= NULL_TREE
;
1730 if (t
== error_mark_node
)
1731 return error_mark_node
;
1732 append_to_statement_list (t
, &stmt_list
);
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
1740 if (stmt_list
== NULL_TREE
)
1741 stmt_list
= integer_zero_node
;
1746 // List of statements.
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
)
1756 if (t
== error_mark_node
)
1757 return error_mark_node
;
1758 append_to_statement_list (t
, &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
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
;
1786 tree superblock_tree
= DECL_INITIAL (fndecl
);
1787 BLOCK_SUPERCONTEXT (block_tree
) = superblock_tree
;
1789 for (pp
= &BLOCK_SUBBLOCKS (superblock_tree
); *pp
!= NULL_TREE
;
1790 pp
= &BLOCK_CHAIN (*pp
))
1797 tree superblock_tree
= BIND_EXPR_BLOCK (enclosing
);
1798 gcc_assert (TREE_CODE (superblock_tree
) == BLOCK
);
1800 BLOCK_SUPERCONTEXT (block_tree
) = superblock_tree
;
1802 for (pp
= &BLOCK_SUBBLOCKS (superblock_tree
); *pp
!= NULL_TREE
;
1803 pp
= &BLOCK_CHAIN (*pp
))
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
);
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;
1826 // Add statements to a block.
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
)
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.
1850 non_zero_size_type (tree type
)
1852 if (int_size_in_bytes (type
) != 0)
1855 switch (TREE_CODE (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
;
1873 pp
= &DECL_CHAIN (f
);
1875 TYPE_FIELDS (ns
) = field_trees
;
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
;
1888 rust_non_zero_struct
= type
;
1890 return rust_non_zero_struct
;
1893 tree element_type
= non_zero_size_type (TREE_TYPE (type
));
1894 return build_array_type_nelts (element_type
, 1);
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.
1909 convert_tree (tree type_tree
, tree expr_tree
, location_t location
)
1911 if (type_tree
== TREE_TYPE (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
,
1934 rust_unreachable ();
1937 // Make a global variable.
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
);
1955 DECL_EXTERNAL (decl
) = 1;
1957 TREE_STATIC (decl
) = 1;
1960 TREE_PUBLIC (decl
) = 1;
1961 SET_DECL_ASSEMBLER_NAME (decl
, get_identifier_from_string (asm_name
));
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.
1981 global_variable_set_init (Bvariable
*var
, tree expr_tree
)
1983 if (expr_tree
== error_mark_node
)
1985 gcc_assert (TREE_CONSTANT (expr_tree
));
1986 tree var_decl
= var
->get_decl ();
1987 if (var_decl
== error_mark_node
)
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.
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
),
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.
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.
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
);
2060 push_struct_function (fndecl
);
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.
2075 temporary_variable (tree fndecl
, tree bind_tree
, tree type_tree
, tree init_tree
,
2076 bool is_address_taken
, location_t location
,
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 ();
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
);
2094 push_cfun (DECL_STRUCT_FUNCTION (fndecl
));
2096 var
= create_tmp_var (type_tree
, "RUSTTMP");
2101 gcc_assert (bind_tree
!= NULL_TREE
);
2102 var
= build_decl (location
, VAR_DECL
, create_tmp_var_name ("RUSTTMP"),
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
);
2140 label (tree func_tree
, const std::string
&name
, location_t location
)
2145 if (DECL_STRUCT_FUNCTION (func_tree
) == NULL
)
2146 push_struct_function (func_tree
);
2148 push_cfun (DECL_STRUCT_FUNCTION (func_tree
));
2150 decl
= create_artificial_label (location
);
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
;
2163 // Make a statement which defines a label.
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.
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.
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
));
2192 // Declare or define a new function.
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;
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
);
2233 // Create a statement that runs all deferred calls for FUNCTION. This should
2234 // be a statement that looks like this in C++:
2236 // try { UNDEFER; } catch { CHECK_DEFER; goto finish; }
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
);
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
);
2258 = build2 (COMPOUND_EXPR
, void_type_node
, defer_tree
, jump_stmt
);
2259 catch_body
= build2 (CATCH_EXPR
, void_type_node
, NULL
, catch_body
);
2261 = build2 (TRY_CATCH_EXPR
, void_type_node
, undefer_tree
, catch_body
);
2262 append_to_statement_list (try_catch
, &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.
2272 function_set_parameters (tree function
,
2273 const std::vector
<Bvariable
*> ¶m_vars
)
2275 if (function
== error_mark_node
)
2278 tree params
= NULL_TREE
;
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
);
2288 DECL_ARGUMENTS (function
) = params
;
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.
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.
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
)
2316 rust_preserve_from_gc (defs
[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
]);
2333 for (std::vector
<tree
>::const_iterator p
= constant_decls
.begin ();
2334 p
!= constant_decls
.end (); ++p
)
2336 if ((*p
) != error_mark_node
)
2339 rust_preserve_from_gc (defs
[i
]);
2343 for (std::vector
<tree
>::const_iterator p
= function_decls
.begin ();
2344 p
!= function_decls
.end (); ++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);
2360 // Pass everything back to the middle-end.
2362 wrapup_global_declarations (defs
, i
);
2367 } // namespace Backend