1 // rust-gcc.cc -- Rust frontend to gcc IR.
2 // Copyright (C) 2011-2023 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 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
.gcc_location (), this->t_
);
75 t
= fold_build1_loc (location
.gcc_location (), NOP_EXPR
,
76 build_pointer_type (this->orig_type_
), t
);
77 return build_fold_indirect_ref_loc (location
.gcc_location (), t
);
80 // This file implements the interface between the Rust frontend proper
81 // and the gcc IR. This implements specific instantiations of
82 // abstract classes defined by the Rust frontend proper. The Rust
83 // frontend proper class methods of these classes to generate the
84 // backend representation.
86 class Gcc_backend
: public Backend
91 void debug (tree t
) { debug_tree (t
); };
92 void debug (Bvariable
*t
) { debug_tree (t
->get_decl ()); };
94 tree
get_identifier_node (const std::string
&str
)
96 return get_identifier_with_length (str
.data (), str
.length ());
103 static tree unit_type
;
104 if (unit_type
== nullptr)
106 auto unit_type_node
= struct_type ({});
107 unit_type
= named_type ("()", unit_type_node
,
108 ::Linemap::predeclared_location ());
114 tree
bool_type () { return boolean_type_node
; }
116 tree
char_type () { return char_type_node
; }
120 tree wchar
= make_unsigned_type (32);
121 TYPE_STRING_FLAG (wchar
) = 1;
125 int get_pointer_size ();
127 tree
raw_str_type ();
129 tree
integer_type (bool, int);
131 tree
float_type (int);
133 tree
complex_type (int);
135 tree
pointer_type (tree
);
137 tree
reference_type (tree
);
139 tree
immutable_type (tree
);
141 tree
function_type (const typed_identifier
&,
142 const std::vector
<typed_identifier
> &,
143 const std::vector
<typed_identifier
> &, tree
,
146 tree
function_type_varadic (const typed_identifier
&,
147 const std::vector
<typed_identifier
> &,
148 const std::vector
<typed_identifier
> &, tree
,
151 tree
function_ptr_type (tree
, const std::vector
<tree
> &, Location
);
153 tree
struct_type (const std::vector
<typed_identifier
> &);
155 tree
union_type (const std::vector
<typed_identifier
> &);
157 tree
array_type (tree
, tree
);
159 tree
named_type (const std::string
&, tree
, Location
);
161 int64_t type_size (tree
);
163 int64_t type_alignment (tree
);
165 int64_t type_field_alignment (tree
);
167 int64_t type_field_offset (tree
, size_t index
);
171 tree
zero_expression (tree
);
173 tree
unit_expression () { return integer_zero_node
; }
175 tree
var_expression (Bvariable
*var
, Location
);
177 tree
integer_constant_expression (tree type
, mpz_t val
);
179 tree
float_constant_expression (tree type
, mpfr_t val
);
181 tree
complex_constant_expression (tree type
, mpc_t val
);
183 tree
string_constant_expression (const std::string
&val
);
185 tree
wchar_constant_expression (wchar_t c
);
187 tree
char_constant_expression (char c
);
189 tree
boolean_constant_expression (bool val
);
191 tree
real_part_expression (tree bcomplex
, Location
);
193 tree
imag_part_expression (tree bcomplex
, Location
);
195 tree
complex_expression (tree breal
, tree bimag
, Location
);
197 tree
convert_expression (tree type
, tree expr
, Location
);
199 tree
struct_field_expression (tree
, size_t, Location
);
201 tree
compound_expression (tree
, tree
, Location
);
203 tree
conditional_expression (tree
, tree
, tree
, tree
, tree
, Location
);
205 tree
negation_expression (NegationOperator op
, tree expr
, Location
);
207 tree
arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op
,
208 tree left
, tree right
, Location
);
210 tree
arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op
,
211 tree left
, tree right
,
212 Location
, Bvariable
*receiver
);
214 tree
comparison_expression (ComparisonOperator op
, tree left
, tree right
,
217 tree
lazy_boolean_expression (LazyBooleanOperator op
, tree left
, tree right
,
220 tree
constructor_expression (tree
, bool, const std::vector
<tree
> &, int,
223 tree
array_constructor_expression (tree
, const std::vector
<unsigned long> &,
224 const std::vector
<tree
> &, Location
);
226 tree
array_initializer (tree
, tree
, tree
, tree
, tree
, tree
*, Location
);
228 tree
array_index_expression (tree array
, tree index
, Location
);
230 tree
call_expression (tree fn
, const std::vector
<tree
> &args
,
231 tree static_chain
, Location
);
235 tree
init_statement (tree
, Bvariable
*var
, tree init
);
237 tree
assignment_statement (tree lhs
, tree rhs
, Location
);
239 tree
return_statement (tree
, const std::vector
<tree
> &, Location
);
241 tree
if_statement (tree
, tree condition
, tree then_block
, tree else_block
,
244 tree
compound_statement (tree
, tree
);
246 tree
statement_list (const std::vector
<tree
> &);
248 tree
exception_handler_statement (tree bstat
, tree except_stmt
,
249 tree finally_stmt
, Location
);
251 tree
loop_expression (tree body
, Location
);
253 tree
exit_expression (tree condition
, Location
);
257 tree
block (tree
, tree
, const std::vector
<Bvariable
*> &, Location
, Location
);
259 void block_add_statements (tree
, const std::vector
<tree
> &);
263 Bvariable
*error_variable () { return new Bvariable (error_mark_node
); }
265 Bvariable
*global_variable (const std::string
&var_name
,
266 const std::string
&asm_name
, tree type
,
267 bool is_external
, bool is_hidden
,
268 bool in_unique_section
, Location location
);
270 void global_variable_set_init (Bvariable
*, tree
);
272 Bvariable
*local_variable (tree
, const std::string
&, tree
, Bvariable
*,
275 Bvariable
*parameter_variable (tree
, const std::string
&, tree
, Location
);
277 Bvariable
*static_chain_variable (tree
, const std::string
&, tree
, Location
);
279 Bvariable
*temporary_variable (tree
, tree
, tree
, tree
, bool, Location
,
284 tree
label (tree
, const std::string
&name
, Location
);
286 tree
label_definition_statement (tree
);
288 tree
goto_statement (tree
, Location
);
290 tree
label_address (tree
, Location
);
294 tree
function (tree fntype
, const std::string
&name
,
295 const std::string
&asm_name
, unsigned int flags
, Location
);
297 tree
function_defer_statement (tree function
, tree undefer
, tree defer
,
300 bool function_set_parameters (tree function
,
301 const std::vector
<Bvariable
*> &);
303 void write_global_definitions (const std::vector
<tree
> &,
304 const std::vector
<tree
> &,
305 const std::vector
<tree
> &,
306 const std::vector
<Bvariable
*> &);
308 void write_export_data (const char *bytes
, unsigned int size
);
311 tree
fill_in_fields (tree
, const std::vector
<typed_identifier
> &);
313 tree
fill_in_array (tree
, tree
, tree
);
315 tree
non_zero_size_type (tree
);
317 tree
convert_tree (tree
, tree
, Location
);
320 // A helper function to create a GCC identifier from a C++ string.
323 get_identifier_from_string (const std::string
&str
)
325 return get_identifier_with_length (str
.data (), str
.length ());
328 // Define the built-in functions that are exposed to GCCRust.
330 Gcc_backend::Gcc_backend ()
332 /* We need to define the fetch_and_add functions, since we use them
334 // tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree ();
335 // tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
336 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1,
337 // "__sync_fetch_and_add_1",
338 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
340 // t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree ();
341 // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
342 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2,
343 // "__sync_fetch_and_add_2",
344 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
346 // t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree ();
347 // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
348 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4,
349 // "__sync_fetch_and_add_4",
350 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
352 // t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree ();
353 // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
354 // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8,
355 // "__sync_fetch_and_add_8",
356 // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
358 // // We use __builtin_expect for magic import functions.
359 // this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL,
360 // build_function_type_list (long_integer_type_node,
361 // long_integer_type_node,
362 // long_integer_type_node,
366 // // We use __builtin_memcmp for struct comparisons.
367 // this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp",
368 // build_function_type_list (integer_type_node,
369 // const_ptr_type_node,
370 // const_ptr_type_node,
371 // size_type_node, NULL_TREE),
374 // // We use __builtin_memmove for copying data.
375 // this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove",
376 // build_function_type_list (void_type_node, ptr_type_node,
377 // const_ptr_type_node,
378 // size_type_node, NULL_TREE),
381 // // We use __builtin_memset for zeroing data.
382 // this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset",
383 // build_function_type_list (void_type_node, ptr_type_node,
384 // integer_type_node,
385 // size_type_node, NULL_TREE),
388 // // Used by runtime/internal/sys and math/bits.
389 // this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz",
390 // build_function_type_list (integer_type_node,
391 // unsigned_type_node,
394 // this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll",
395 // build_function_type_list (integer_type_node,
396 // long_long_unsigned_type_node,
399 // this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz",
400 // build_function_type_list (integer_type_node,
401 // unsigned_type_node,
404 // this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
405 // build_function_type_list (integer_type_node,
406 // long_long_unsigned_type_node,
409 // this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
410 // build_function_type_list (integer_type_node,
411 // unsigned_type_node,
414 // this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll",
416 // build_function_type_list (integer_type_node,
417 // long_long_unsigned_type_node,
420 // this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
421 // build_function_type_list (uint16_type_node,
422 // uint16_type_node, NULL_TREE),
424 // this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
425 // build_function_type_list (uint32_type_node,
426 // uint32_type_node, NULL_TREE),
428 // this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64",
429 // build_function_type_list (uint64_type_node,
430 // uint64_type_node, NULL_TREE),
433 // We provide some functions for the math library.
435 // We use __builtin_return_address in the thunk we build for
436 // functions which call recover, and for runtime.getcallerpc.
437 // t = build_function_type_list (ptr_type_node, unsigned_type_node,
438 // NULL_TREE); this->define_builtin (BUILT_IN_RETURN_ADDRESS,
439 // "__builtin_return_address",
442 // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp.
443 // t = build_function_type_list (ptr_type_node, NULL_TREE);
444 // this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t,
447 // The runtime calls __builtin_extract_return_addr when recording
448 // the address to which a function returns.
449 // this->define_builtin (
450 // BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL,
451 // build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0);
453 // The compiler uses __builtin_trap for some exception handling
455 // this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL,
456 // build_function_type (void_type_node, void_list_node),
457 // builtin_noreturn);
459 // The runtime uses __builtin_prefetch.
460 // this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL,
461 // build_varargs_function_type_list (void_type_node,
462 // const_ptr_type_node,
466 // The compiler uses __builtin_unreachable for cases that cannot
468 // this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
469 // build_function_type (void_type_node, void_list_node),
470 // builtin_const | builtin_noreturn);
472 // We provide some atomic functions.
473 // t = build_function_type_list (uint32_type_node, ptr_type_node,
474 // integer_type_node, NULL_TREE);
475 // this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t,
478 // t = build_function_type_list (uint64_type_node, ptr_type_node,
479 // integer_type_node, NULL_TREE);
480 // this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t,
483 // t = build_function_type_list (void_type_node, ptr_type_node,
485 // integer_type_node, NULL_TREE);
486 // this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t,
489 // t = build_function_type_list (void_type_node, ptr_type_node,
491 // integer_type_node, NULL_TREE);
492 // this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t,
495 // t = build_function_type_list (uint32_type_node, ptr_type_node,
496 // uint32_type_node, integer_type_node, NULL_TREE);
497 // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4",
501 // t = build_function_type_list (uint64_type_node, ptr_type_node,
502 // uint64_type_node, integer_type_node, NULL_TREE);
503 // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8",
507 // t = build_function_type_list (boolean_type_node, ptr_type_node,
509 // uint32_type_node, boolean_type_node,
510 // integer_type_node, integer_type_node,
512 // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
513 // "__atomic_compare_exchange_4", NULL, t, 0);
515 // t = build_function_type_list (boolean_type_node, ptr_type_node,
517 // uint64_type_node, boolean_type_node,
518 // integer_type_node, integer_type_node,
520 // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
521 // "__atomic_compare_exchange_8", NULL, t, 0);
523 // t = build_function_type_list (uint32_type_node, ptr_type_node,
524 // uint32_type_node, integer_type_node, NULL_TREE);
525 // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
528 // t = build_function_type_list (uint64_type_node, ptr_type_node,
529 // uint64_type_node, integer_type_node, NULL_TREE);
530 // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
533 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
534 // unsigned_char_type_node, integer_type_node,
536 // this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
538 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1",
541 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
542 // unsigned_char_type_node, integer_type_node,
544 // this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
547 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1",
552 // Get an unnamed integer type.
555 Gcc_backend::get_pointer_size ()
561 Gcc_backend::raw_str_type ()
563 tree char_ptr
= build_pointer_type (char_type_node
);
564 tree const_char_type
= build_qualified_type (char_ptr
, TYPE_QUAL_CONST
);
565 return const_char_type
;
569 Gcc_backend::integer_type (bool is_unsigned
, int bits
)
574 if (bits
== INT_TYPE_SIZE
)
575 type
= unsigned_type_node
;
576 else if (bits
== SHORT_TYPE_SIZE
)
577 type
= short_unsigned_type_node
;
578 else if (bits
== LONG_TYPE_SIZE
)
579 type
= long_unsigned_type_node
;
580 else if (bits
== LONG_LONG_TYPE_SIZE
)
581 type
= long_long_unsigned_type_node
;
583 type
= make_unsigned_type (bits
);
587 if (bits
== INT_TYPE_SIZE
)
588 type
= integer_type_node
;
589 else if (bits
== SHORT_TYPE_SIZE
)
590 type
= short_integer_type_node
;
591 else if (bits
== LONG_TYPE_SIZE
)
592 type
= long_integer_type_node
;
593 else if (bits
== LONG_LONG_TYPE_SIZE
)
594 type
= long_long_integer_type_node
;
596 type
= make_signed_type (bits
);
601 // Get an unnamed float type.
604 Gcc_backend::float_type (int bits
)
607 if (bits
== FLOAT_TYPE_SIZE
)
608 type
= float_type_node
;
609 else if (bits
== DOUBLE_TYPE_SIZE
)
610 type
= double_type_node
;
611 else if (bits
== LONG_DOUBLE_TYPE_SIZE
)
612 type
= long_double_type_node
;
615 type
= make_node (REAL_TYPE
);
616 TYPE_PRECISION (type
) = bits
;
622 // Get an unnamed complex type.
625 Gcc_backend::complex_type (int bits
)
628 if (bits
== FLOAT_TYPE_SIZE
* 2)
629 type
= complex_float_type_node
;
630 else if (bits
== DOUBLE_TYPE_SIZE
* 2)
631 type
= complex_double_type_node
;
632 else if (bits
== LONG_DOUBLE_TYPE_SIZE
* 2)
633 type
= complex_long_double_type_node
;
636 type
= make_node (REAL_TYPE
);
637 TYPE_PRECISION (type
) = bits
/ 2;
639 type
= build_complex_type (type
);
644 // Get a pointer type.
647 Gcc_backend::pointer_type (tree to_type
)
649 if (to_type
== error_mark_node
)
650 return error_mark_node
;
651 tree type
= build_pointer_type (to_type
);
655 // Get a reference type.
658 Gcc_backend::reference_type (tree to_type
)
660 if (to_type
== error_mark_node
)
661 return error_mark_node
;
662 tree type
= build_reference_type (to_type
);
666 // Get immutable type
669 Gcc_backend::immutable_type (tree base
)
671 if (base
== error_mark_node
)
672 return error_mark_node
;
673 tree constified
= build_qualified_type (base
, TYPE_QUAL_CONST
);
677 // Make a function type.
680 Gcc_backend::function_type (const typed_identifier
&receiver
,
681 const std::vector
<typed_identifier
> ¶meters
,
682 const std::vector
<typed_identifier
> &results
,
683 tree result_struct
, Location
)
685 tree args
= NULL_TREE
;
687 if (receiver
.type
!= NULL_TREE
)
689 tree t
= receiver
.type
;
690 if (t
== error_mark_node
)
691 return error_mark_node
;
692 *pp
= tree_cons (NULL_TREE
, t
, NULL_TREE
);
693 pp
= &TREE_CHAIN (*pp
);
696 for (std::vector
<typed_identifier
>::const_iterator p
= parameters
.begin ();
697 p
!= parameters
.end (); ++p
)
700 if (t
== error_mark_node
)
701 return error_mark_node
;
702 *pp
= tree_cons (NULL_TREE
, t
, NULL_TREE
);
703 pp
= &TREE_CHAIN (*pp
);
706 // Varargs is handled entirely at the Rust level. When converted to
707 // GENERIC functions are not varargs.
708 *pp
= void_list_node
;
711 if (results
.empty ())
712 result
= void_type_node
;
713 else if (results
.size () == 1)
714 result
= results
.front ().type
;
717 gcc_assert (result_struct
!= NULL
);
718 result
= result_struct
;
720 if (result
== error_mark_node
)
721 return error_mark_node
;
723 // The libffi library cannot represent a zero-sized object. To
724 // avoid causing confusion on 32-bit SPARC, we treat a function that
725 // returns a zero-sized value as returning void. That should do no
726 // harm since there is no actual value to be returned. See
727 // https://gcc.gnu.org/PR72814 for details.
728 if (result
!= void_type_node
&& int_size_in_bytes (result
) == 0)
729 result
= void_type_node
;
731 tree fntype
= build_function_type (result
, args
);
732 if (fntype
== error_mark_node
)
733 return error_mark_node
;
735 return build_pointer_type (fntype
);
739 Gcc_backend::function_type_varadic (
740 const typed_identifier
&receiver
,
741 const std::vector
<typed_identifier
> ¶meters
,
742 const std::vector
<typed_identifier
> &results
, tree result_struct
, Location
)
744 size_t n
= parameters
.size () + (receiver
.type
!= NULL_TREE
? 1 : 0);
745 tree
*args
= XALLOCAVEC (tree
, n
);
748 if (receiver
.type
!= NULL_TREE
)
750 tree t
= receiver
.type
;
751 if (t
== error_mark_node
)
752 return error_mark_node
;
757 for (std::vector
<typed_identifier
>::const_iterator p
= parameters
.begin ();
758 p
!= parameters
.end (); ++p
)
761 if (t
== error_mark_node
)
762 return error_mark_node
;
767 if (results
.empty ())
768 result
= void_type_node
;
769 else if (results
.size () == 1)
770 result
= results
.front ().type
;
773 gcc_assert (result_struct
!= NULL_TREE
);
774 result
= result_struct
;
776 if (result
== error_mark_node
)
777 return error_mark_node
;
779 // The libffi library cannot represent a zero-sized object. To
780 // avoid causing confusion on 32-bit SPARC, we treat a function that
781 // returns a zero-sized value as returning void. That should do no
782 // harm since there is no actual value to be returned. See
783 // https://gcc.gnu.org/PR72814 for details.
784 if (result
!= void_type_node
&& int_size_in_bytes (result
) == 0)
785 result
= void_type_node
;
787 tree fntype
= build_varargs_function_type_array (result
, n
, args
);
788 if (fntype
== error_mark_node
)
789 return error_mark_node
;
791 return build_pointer_type (fntype
);
795 Gcc_backend::function_ptr_type (tree result_type
,
796 const std::vector
<tree
> ¶meters
,
797 Location
/* locus */)
799 tree args
= NULL_TREE
;
802 for (auto ¶m
: parameters
)
804 if (param
== error_mark_node
)
805 return error_mark_node
;
807 *pp
= tree_cons (NULL_TREE
, param
, NULL_TREE
);
808 pp
= &TREE_CHAIN (*pp
);
811 *pp
= void_list_node
;
813 tree result
= result_type
;
814 if (result
!= void_type_node
&& int_size_in_bytes (result
) == 0)
815 result
= void_type_node
;
817 tree fntype
= build_function_type (result
, args
);
818 if (fntype
== error_mark_node
)
819 return error_mark_node
;
821 return build_pointer_type (fntype
);
824 // Make a struct type.
827 Gcc_backend::struct_type (const std::vector
<typed_identifier
> &fields
)
829 return this->fill_in_fields (make_node (RECORD_TYPE
), fields
);
832 // Make a union type.
835 Gcc_backend::union_type (const std::vector
<typed_identifier
> &fields
)
837 return this->fill_in_fields (make_node (UNION_TYPE
), fields
);
840 // Fill in the fields of a struct or union type.
843 Gcc_backend::fill_in_fields (tree fill
,
844 const std::vector
<typed_identifier
> &fields
)
846 tree field_trees
= NULL_TREE
;
847 tree
*pp
= &field_trees
;
848 for (std::vector
<typed_identifier
>::const_iterator p
= fields
.begin ();
849 p
!= fields
.end (); ++p
)
851 tree name_tree
= get_identifier_from_string (p
->name
);
852 tree type_tree
= p
->type
;
853 if (type_tree
== error_mark_node
)
854 return error_mark_node
;
855 tree field
= build_decl (p
->location
.gcc_location (), FIELD_DECL
,
856 name_tree
, type_tree
);
857 DECL_CONTEXT (field
) = fill
;
859 pp
= &DECL_CHAIN (field
);
861 TYPE_FIELDS (fill
) = field_trees
;
864 // Because Rust permits converting between named struct types and
865 // equivalent struct types, for which we use VIEW_CONVERT_EXPR, and
866 // because we don't try to maintain TYPE_CANONICAL for struct types,
867 // we need to tell the middle-end to use structural equality.
868 SET_TYPE_STRUCTURAL_EQUALITY (fill
);
873 // Make an array type.
876 Gcc_backend::array_type (tree element_type
, tree length
)
878 return this->fill_in_array (make_node (ARRAY_TYPE
), element_type
, length
);
881 // Fill in an array type.
884 Gcc_backend::fill_in_array (tree fill
, tree element_type
, tree length_tree
)
886 if (element_type
== error_mark_node
|| length_tree
== error_mark_node
)
887 return error_mark_node
;
889 gcc_assert (TYPE_SIZE (element_type
) != NULL_TREE
);
891 length_tree
= fold_convert (sizetype
, length_tree
);
893 // build_index_type takes the maximum index, which is one less than
895 tree index_type_tree
= build_index_type (
896 fold_build2 (MINUS_EXPR
, sizetype
, length_tree
, size_one_node
));
898 TREE_TYPE (fill
) = element_type
;
899 TYPE_DOMAIN (fill
) = index_type_tree
;
900 TYPE_ADDR_SPACE (fill
) = TYPE_ADDR_SPACE (element_type
);
903 if (TYPE_STRUCTURAL_EQUALITY_P (element_type
))
904 SET_TYPE_STRUCTURAL_EQUALITY (fill
);
905 else if (TYPE_CANONICAL (element_type
) != element_type
906 || TYPE_CANONICAL (index_type_tree
) != index_type_tree
)
907 TYPE_CANONICAL (fill
) = build_array_type (TYPE_CANONICAL (element_type
),
908 TYPE_CANONICAL (index_type_tree
));
913 // Return a named version of a type.
916 Gcc_backend::named_type (const std::string
&name
, tree type
, Location location
)
918 if (type
== error_mark_node
)
919 return error_mark_node
;
921 // The middle-end expects a basic type to have a name. In Rust every
922 // basic type will have a name. The first time we see a basic type,
923 // give it whatever Rust name we have at this point.
924 if (TYPE_NAME (type
) == NULL_TREE
925 && location
.gcc_location () == BUILTINS_LOCATION
926 && (TREE_CODE (type
) == INTEGER_TYPE
|| TREE_CODE (type
) == REAL_TYPE
927 || TREE_CODE (type
) == COMPLEX_TYPE
928 || TREE_CODE (type
) == BOOLEAN_TYPE
))
930 tree decl
= build_decl (BUILTINS_LOCATION
, TYPE_DECL
,
931 get_identifier_from_string (name
), type
);
932 TYPE_NAME (type
) = decl
;
936 tree copy
= build_variant_type_copy (type
);
937 tree decl
= build_decl (location
.gcc_location (), TYPE_DECL
,
938 get_identifier_from_string (name
), copy
);
939 DECL_ORIGINAL_TYPE (decl
) = type
;
940 TYPE_NAME (copy
) = decl
;
944 // Return the size of a type.
947 Gcc_backend::type_size (tree t
)
949 if (t
== error_mark_node
)
951 if (t
== void_type_node
)
953 t
= TYPE_SIZE_UNIT (t
);
954 gcc_assert (tree_fits_uhwi_p (t
));
955 unsigned HOST_WIDE_INT val_wide
= TREE_INT_CST_LOW (t
);
956 int64_t ret
= static_cast<int64_t> (val_wide
);
957 if (ret
< 0 || static_cast<unsigned HOST_WIDE_INT
> (ret
) != val_wide
)
962 // Return the alignment of a type.
965 Gcc_backend::type_alignment (tree t
)
967 if (t
== error_mark_node
)
969 return TYPE_ALIGN_UNIT (t
);
972 // Return the alignment of a struct field of type BTYPE.
975 Gcc_backend::type_field_alignment (tree t
)
977 if (t
== error_mark_node
)
979 return rust_field_alignment (t
);
982 // Return the offset of a field in a struct.
985 Gcc_backend::type_field_offset (tree struct_tree
, size_t index
)
987 if (struct_tree
== error_mark_node
)
989 gcc_assert (TREE_CODE (struct_tree
) == RECORD_TYPE
);
990 tree field
= TYPE_FIELDS (struct_tree
);
991 for (; index
> 0; --index
)
993 field
= DECL_CHAIN (field
);
994 gcc_assert (field
!= NULL_TREE
);
996 HOST_WIDE_INT offset_wide
= int_byte_position (field
);
997 int64_t ret
= static_cast<int64_t> (offset_wide
);
998 gcc_assert (ret
== offset_wide
);
1002 // Return the zero value for a type.
1005 Gcc_backend::zero_expression (tree t
)
1008 if (t
== error_mark_node
)
1009 ret
= error_mark_node
;
1011 ret
= build_zero_cst (t
);
1015 // An expression that references a variable.
1018 Gcc_backend::var_expression (Bvariable
*var
, Location location
)
1020 return var
->get_tree (location
);
1023 // Return a typed value as a constant integer.
1024 // This function does not release the memory of @val
1027 Gcc_backend::integer_constant_expression (tree t
, mpz_t val
)
1029 if (t
== error_mark_node
)
1030 return error_mark_node
;
1032 tree ret
= wide_int_to_tree (t
, wi::from_mpz (t
, val
, true));
1036 // Return a typed value as a constant floating-point number.
1039 Gcc_backend::float_constant_expression (tree t
, mpfr_t val
)
1042 if (t
== error_mark_node
)
1043 return error_mark_node
;
1046 real_from_mpfr (&r1
, val
, t
, GMP_RNDN
);
1048 real_convert (&r2
, TYPE_MODE (t
), &r1
);
1049 ret
= build_real (t
, r2
);
1053 // Return a typed real and imaginary value as a constant complex number.
1056 Gcc_backend::complex_constant_expression (tree t
, mpc_t val
)
1059 if (t
== error_mark_node
)
1060 return error_mark_node
;
1063 real_from_mpfr (&r1
, mpc_realref (val
), TREE_TYPE (t
), GMP_RNDN
);
1065 real_convert (&r2
, TYPE_MODE (TREE_TYPE (t
)), &r1
);
1068 real_from_mpfr (&r3
, mpc_imagref (val
), TREE_TYPE (t
), GMP_RNDN
);
1070 real_convert (&r4
, TYPE_MODE (TREE_TYPE (t
)), &r3
);
1072 ret
= build_complex (t
, build_real (TREE_TYPE (t
), r2
),
1073 build_real (TREE_TYPE (t
), r4
));
1077 // Make a constant string expression.
1080 Gcc_backend::string_constant_expression (const std::string
&val
)
1082 tree index_type
= build_index_type (size_int (val
.length ()));
1083 tree const_char_type
= build_qualified_type (char_type_node
, TYPE_QUAL_CONST
);
1084 tree string_type
= build_array_type (const_char_type
, index_type
);
1085 TYPE_STRING_FLAG (string_type
) = 1;
1086 tree string_val
= build_string (val
.length (), val
.data ());
1087 TREE_TYPE (string_val
) = string_type
;
1093 Gcc_backend::wchar_constant_expression (wchar_t c
)
1095 return build_int_cst (this->wchar_type (), c
);
1099 Gcc_backend::char_constant_expression (char c
)
1101 return build_int_cst (this->char_type (), c
);
1104 // Make a constant boolean expression.
1107 Gcc_backend::boolean_constant_expression (bool val
)
1109 return val
? boolean_true_node
: boolean_false_node
;
1112 // Return the real part of a complex expression.
1115 Gcc_backend::real_part_expression (tree complex_tree
, Location location
)
1117 if (complex_tree
== error_mark_node
)
1118 return error_mark_node
;
1119 gcc_assert (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (complex_tree
)));
1121 = fold_build1_loc (location
.gcc_location (), REALPART_EXPR
,
1122 TREE_TYPE (TREE_TYPE (complex_tree
)), complex_tree
);
1126 // Return the imaginary part of a complex expression.
1129 Gcc_backend::imag_part_expression (tree complex_tree
, Location location
)
1131 if (complex_tree
== error_mark_node
)
1132 return error_mark_node
;
1133 gcc_assert (COMPLEX_FLOAT_TYPE_P (TREE_TYPE (complex_tree
)));
1135 = fold_build1_loc (location
.gcc_location (), IMAGPART_EXPR
,
1136 TREE_TYPE (TREE_TYPE (complex_tree
)), complex_tree
);
1140 // Make a complex expression given its real and imaginary parts.
1143 Gcc_backend::complex_expression (tree real_tree
, tree imag_tree
,
1146 if (real_tree
== error_mark_node
|| imag_tree
== error_mark_node
)
1147 return error_mark_node
;
1148 gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (real_tree
))
1149 == TYPE_MAIN_VARIANT (TREE_TYPE (imag_tree
)));
1150 gcc_assert (SCALAR_FLOAT_TYPE_P (TREE_TYPE (real_tree
)));
1151 tree ret
= fold_build2_loc (location
.gcc_location (), COMPLEX_EXPR
,
1152 build_complex_type (TREE_TYPE (real_tree
)),
1153 real_tree
, imag_tree
);
1157 // An expression that converts an expression to a different type.
1160 Gcc_backend::convert_expression (tree type_tree
, tree expr_tree
,
1163 if (type_tree
== error_mark_node
|| expr_tree
== error_mark_node
1164 || TREE_TYPE (expr_tree
) == error_mark_node
)
1165 return error_mark_node
;
1168 if (this->type_size (type_tree
) == 0
1169 || TREE_TYPE (expr_tree
) == void_type_node
)
1171 // Do not convert zero-sized types.
1174 else if (TREE_CODE (type_tree
) == INTEGER_TYPE
)
1175 ret
= convert_to_integer (type_tree
, expr_tree
);
1176 else if (TREE_CODE (type_tree
) == REAL_TYPE
)
1177 ret
= convert_to_real (type_tree
, expr_tree
);
1178 else if (TREE_CODE (type_tree
) == COMPLEX_TYPE
)
1179 ret
= convert_to_complex (type_tree
, expr_tree
);
1180 else if (TREE_CODE (type_tree
) == POINTER_TYPE
1181 && TREE_CODE (TREE_TYPE (expr_tree
)) == INTEGER_TYPE
)
1182 ret
= convert_to_pointer (type_tree
, expr_tree
);
1183 else if (TREE_CODE (type_tree
) == RECORD_TYPE
1184 || TREE_CODE (type_tree
) == ARRAY_TYPE
)
1185 ret
= fold_build1_loc (location
.gcc_location (), VIEW_CONVERT_EXPR
,
1186 type_tree
, expr_tree
);
1188 ret
= fold_convert_loc (location
.gcc_location (), type_tree
, expr_tree
);
1193 // Return an expression for the field at INDEX in BSTRUCT.
1196 Gcc_backend::struct_field_expression (tree struct_tree
, size_t index
,
1199 if (struct_tree
== error_mark_node
1200 || TREE_TYPE (struct_tree
) == error_mark_node
)
1201 return error_mark_node
;
1202 gcc_assert (TREE_CODE (TREE_TYPE (struct_tree
)) == RECORD_TYPE
1203 || TREE_CODE (TREE_TYPE (struct_tree
)) == UNION_TYPE
);
1204 tree field
= TYPE_FIELDS (TREE_TYPE (struct_tree
));
1205 if (field
== NULL_TREE
)
1207 // This can happen for a type which refers to itself indirectly
1208 // and then turns out to be erroneous.
1209 return error_mark_node
;
1211 for (unsigned int i
= index
; i
> 0; --i
)
1213 field
= DECL_CHAIN (field
);
1214 gcc_assert (field
!= NULL_TREE
);
1216 if (TREE_TYPE (field
) == error_mark_node
)
1217 return error_mark_node
;
1218 tree ret
= fold_build3_loc (location
.gcc_location (), COMPONENT_REF
,
1219 TREE_TYPE (field
), struct_tree
, field
, NULL_TREE
);
1220 if (TREE_CONSTANT (struct_tree
))
1221 TREE_CONSTANT (ret
) = 1;
1225 // Return an expression that executes BSTAT before BEXPR.
1228 Gcc_backend::compound_expression (tree stat
, tree expr
, Location location
)
1230 if (stat
== error_mark_node
|| expr
== error_mark_node
)
1231 return error_mark_node
;
1232 tree ret
= fold_build2_loc (location
.gcc_location (), COMPOUND_EXPR
,
1233 TREE_TYPE (expr
), stat
, expr
);
1237 // Return an expression that executes THEN_EXPR if CONDITION is true, or
1238 // ELSE_EXPR otherwise.
1241 Gcc_backend::conditional_expression (tree
, tree type_tree
, tree cond_expr
,
1242 tree then_expr
, tree else_expr
,
1245 if (type_tree
== error_mark_node
|| cond_expr
== error_mark_node
1246 || then_expr
== error_mark_node
|| else_expr
== error_mark_node
)
1247 return error_mark_node
;
1248 tree ret
= build3_loc (location
.gcc_location (), COND_EXPR
, type_tree
,
1249 cond_expr
, then_expr
, else_expr
);
1253 /* Helper function that converts rust operators to equivalent GCC tree_code.
1254 Note that CompoundAssignmentOperator don't get their corresponding tree_code,
1255 because they get compiled away when we lower AST to HIR. */
1256 static enum tree_code
1257 operator_to_tree_code (NegationOperator op
)
1261 case NegationOperator::NEGATE
:
1263 case NegationOperator::NOT
:
1264 return TRUTH_NOT_EXPR
;
1270 /* Note that GCC tree code distinguishes floating point division and integer
1271 division. These two types of division are represented as the same rust
1272 operator, and can only be distinguished via context(i.e. the TREE_TYPE of the
1274 static enum tree_code
1275 operator_to_tree_code (ArithmeticOrLogicalOperator op
, bool floating_point
)
1279 case ArithmeticOrLogicalOperator::ADD
:
1281 case ArithmeticOrLogicalOperator::SUBTRACT
:
1283 case ArithmeticOrLogicalOperator::MULTIPLY
:
1285 case ArithmeticOrLogicalOperator::DIVIDE
:
1289 return TRUNC_DIV_EXPR
;
1290 case ArithmeticOrLogicalOperator::MODULUS
:
1291 return TRUNC_MOD_EXPR
;
1292 case ArithmeticOrLogicalOperator::BITWISE_AND
:
1293 return BIT_AND_EXPR
;
1294 case ArithmeticOrLogicalOperator::BITWISE_OR
:
1295 return BIT_IOR_EXPR
;
1296 case ArithmeticOrLogicalOperator::BITWISE_XOR
:
1297 return BIT_XOR_EXPR
;
1298 case ArithmeticOrLogicalOperator::LEFT_SHIFT
:
1300 case ArithmeticOrLogicalOperator::RIGHT_SHIFT
:
1307 static enum tree_code
1308 operator_to_tree_code (ComparisonOperator op
)
1312 case ComparisonOperator::EQUAL
:
1314 case ComparisonOperator::NOT_EQUAL
:
1316 case ComparisonOperator::GREATER_THAN
:
1318 case ComparisonOperator::LESS_THAN
:
1320 case ComparisonOperator::GREATER_OR_EQUAL
:
1322 case ComparisonOperator::LESS_OR_EQUAL
:
1329 static enum tree_code
1330 operator_to_tree_code (LazyBooleanOperator op
)
1334 case LazyBooleanOperator::LOGICAL_OR
:
1335 return TRUTH_ORIF_EXPR
;
1336 case LazyBooleanOperator::LOGICAL_AND
:
1337 return TRUTH_ANDIF_EXPR
;
1343 /* Helper function for deciding if a tree is a floating point node. */
1345 is_floating_point (tree t
)
1347 auto tree_type
= TREE_CODE (TREE_TYPE (t
));
1348 return tree_type
== REAL_TYPE
|| tree_type
== COMPLEX_TYPE
;
1351 // Return an expression for the negation operation OP EXPR.
1353 Gcc_backend::negation_expression (NegationOperator op
, tree expr_tree
,
1356 /* Check if the expression is an error, in which case we return an error
1358 if (expr_tree
== error_mark_node
|| TREE_TYPE (expr_tree
) == error_mark_node
)
1359 return error_mark_node
;
1361 /* For negation operators, the resulting type should be the same as its
1363 auto tree_type
= TREE_TYPE (expr_tree
);
1364 auto original_type
= tree_type
;
1365 auto tree_code
= operator_to_tree_code (op
);
1367 /* For floating point operations we may need to extend the precision of type.
1368 For example, a 64-bit machine may not support operations on float32. */
1369 bool floating_point
= is_floating_point (expr_tree
);
1370 auto extended_type
= NULL_TREE
;
1373 extended_type
= excess_precision_type (tree_type
);
1374 if (extended_type
!= NULL_TREE
)
1376 expr_tree
= convert (extended_type
, expr_tree
);
1377 tree_type
= extended_type
;
1381 /* Construct a new tree and build an expression from it. */
1382 auto new_tree
= fold_build1_loc (location
.gcc_location (), tree_code
,
1383 tree_type
, expr_tree
);
1384 if (floating_point
&& extended_type
!= NULL_TREE
)
1385 new_tree
= convert (original_type
, expr_tree
);
1390 Gcc_backend::arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op
,
1391 tree left
, tree right
,
1394 /* Check if either expression is an error, in which case we return an error
1396 if (left
== error_mark_node
|| right
== error_mark_node
)
1397 return error_mark_node
;
1399 /* We need to determine if we're doing floating point arithmetics of integer
1401 bool floating_point
= is_floating_point (left
);
1402 auto ret
= NULL_TREE
;
1404 /* For arithmetic or logical operators, the resulting type should be the same
1405 as the lhs operand. */
1406 auto tree_type
= TREE_TYPE (left
);
1407 auto original_type
= tree_type
;
1408 auto loc
= location
.gcc_location ();
1409 auto tree_code
= operator_to_tree_code (op
, floating_point
);
1411 /* For floating point operations we may need to extend the precision of type.
1412 For example, a 64-bit machine may not support operations on float32. */
1413 auto extended_type
= NULL_TREE
;
1416 extended_type
= excess_precision_type (tree_type
);
1417 if (extended_type
!= NULL_TREE
)
1419 left
= convert (extended_type
, left
);
1420 right
= convert (extended_type
, right
);
1421 tree_type
= extended_type
;
1425 ret
= fold_build2_loc (loc
, tree_code
, tree_type
, left
, right
);
1426 TREE_CONSTANT (ret
) = TREE_CONSTANT (left
) & TREE_CONSTANT (right
);
1428 // TODO: How do we handle floating point?
1429 if (floating_point
&& extended_type
!= NULL_TREE
)
1430 ret
= convert (original_type
, ret
);
1436 is_overflowing_expr (ArithmeticOrLogicalOperator op
)
1440 case ArithmeticOrLogicalOperator::ADD
:
1441 case ArithmeticOrLogicalOperator::SUBTRACT
:
1442 case ArithmeticOrLogicalOperator::MULTIPLY
:
1449 static std::pair
<tree
, tree
>
1450 fetch_overflow_builtins (ArithmeticOrLogicalOperator op
)
1452 auto builtin_ctx
= Rust::Compile::BuiltinsContext::get ();
1454 auto builtin
= NULL_TREE
;
1455 auto abort
= NULL_TREE
;
1459 case ArithmeticOrLogicalOperator::ADD
:
1460 builtin_ctx
.lookup_simple_builtin ("add_overflow", &builtin
);
1462 case ArithmeticOrLogicalOperator::SUBTRACT
:
1463 builtin_ctx
.lookup_simple_builtin ("sub_overflow", &builtin
);
1465 case ArithmeticOrLogicalOperator::MULTIPLY
:
1466 builtin_ctx
.lookup_simple_builtin ("mul_overflow", &builtin
);
1473 builtin_ctx
.lookup_simple_builtin ("abort", &abort
);
1475 rust_assert (abort
);
1476 rust_assert (builtin
);
1478 // FIXME: ARTHUR: This is really ugly. The builtin context should take care of
1480 TREE_SIDE_EFFECTS (abort
) = 1;
1481 TREE_READONLY (abort
) = 0;
1483 // FIXME: ARTHUR: Same here. Remove these!
1484 TREE_SIDE_EFFECTS (builtin
) = 1;
1485 TREE_READONLY (builtin
) = 0;
1487 return {abort
, builtin
};
1490 // Return an expression for the arithmetic or logical operation LEFT OP RIGHT
1491 // with overflow checking when possible
1493 Gcc_backend::arithmetic_or_logical_expression_checked (
1494 ArithmeticOrLogicalOperator op
, tree left
, tree right
, Location location
,
1495 Bvariable
*receiver_var
)
1497 /* Check if either expression is an error, in which case we return an error
1499 if (left
== error_mark_node
|| right
== error_mark_node
)
1500 return error_mark_node
;
1502 auto loc
= location
.gcc_location ();
1504 // FIXME: Add `if (!debug_mode)`
1505 // No overflow checks for floating point operations or divisions. In that
1506 // case, simply assign the result of the operation to the receiver variable
1507 if (is_floating_point (left
) || !is_overflowing_expr (op
))
1508 return assignment_statement (
1509 receiver_var
->get_tree (location
),
1510 arithmetic_or_logical_expression (op
, left
, right
, location
), location
);
1512 auto receiver
= receiver_var
->get_tree (location
);
1513 TREE_ADDRESSABLE (receiver
) = 1;
1514 auto result_ref
= build_fold_addr_expr_loc (loc
, receiver
);
1516 auto builtins
= fetch_overflow_builtins (op
);
1517 auto abort
= builtins
.first
;
1518 auto builtin
= builtins
.second
;
1520 auto abort_call
= build_call_expr_loc (loc
, abort
, 0);
1522 // FIXME: ARTHUR: Is that needed?
1523 TREE_SIDE_EFFECTS (abort_call
) = 1;
1524 TREE_READONLY (abort_call
) = 0;
1527 = build_call_expr_loc (loc
, builtin
, 3, left
, right
, result_ref
);
1529 = build2_loc (loc
, EQ_EXPR
, boolean_type_node
, builtin_call
,
1530 boolean_constant_expression (true));
1532 auto if_block
= build3_loc (loc
, COND_EXPR
, void_type_node
, overflow_check
,
1533 abort_call
, NULL_TREE
);
1535 // FIXME: ARTHUR: Needed?
1536 TREE_SIDE_EFFECTS (if_block
) = 1;
1537 TREE_READONLY (if_block
) = 0;
1542 // Return an expression for the comparison operation LEFT OP RIGHT.
1544 Gcc_backend::comparison_expression (ComparisonOperator op
, tree left_tree
,
1545 tree right_tree
, Location location
)
1547 /* Check if either expression is an error, in which case we return an error
1549 if (left_tree
== error_mark_node
|| right_tree
== error_mark_node
)
1550 return error_mark_node
;
1552 /* For comparison operators, the resulting type should be boolean. */
1553 auto tree_type
= boolean_type_node
;
1554 auto tree_code
= operator_to_tree_code (op
);
1556 /* Construct a new tree and build an expression from it. */
1557 auto new_tree
= fold_build2_loc (location
.gcc_location (), tree_code
,
1558 tree_type
, left_tree
, right_tree
);
1562 // Return an expression for the lazy boolean operation LEFT OP RIGHT.
1564 Gcc_backend::lazy_boolean_expression (LazyBooleanOperator op
, tree left_tree
,
1565 tree right_tree
, Location location
)
1567 /* Check if either expression is an error, in which case we return an error
1569 if (left_tree
== error_mark_node
|| right_tree
== error_mark_node
)
1570 return error_mark_node
;
1572 /* For lazy boolean operators, the resulting type should be the same as the
1574 auto tree_type
= TREE_TYPE (right_tree
);
1575 auto tree_code
= operator_to_tree_code (op
);
1577 /* Construct a new tree and build an expression from it. */
1578 auto new_tree
= fold_build2_loc (location
.gcc_location (), tree_code
,
1579 tree_type
, left_tree
, right_tree
);
1583 // Return an expression that constructs BTYPE with VALS.
1586 Gcc_backend::constructor_expression (tree type_tree
, bool is_variant
,
1587 const std::vector
<tree
> &vals
,
1588 int union_index
, Location location
)
1590 if (type_tree
== error_mark_node
)
1591 return error_mark_node
;
1593 vec
<constructor_elt
, va_gc
> *init
;
1594 vec_alloc (init
, vals
.size ());
1596 tree sink
= NULL_TREE
;
1597 bool is_constant
= true;
1598 tree field
= TYPE_FIELDS (type_tree
);
1602 gcc_assert (union_index
!= -1);
1603 gcc_assert (TREE_CODE (type_tree
) == UNION_TYPE
);
1605 for (int i
= 0; i
< union_index
; i
++)
1607 gcc_assert (field
!= NULL_TREE
);
1608 field
= DECL_CHAIN (field
);
1612 = constructor_expression (TREE_TYPE (field
), false, vals
, -1, location
);
1614 constructor_elt empty
= {NULL
, NULL
};
1615 constructor_elt
*elt
= init
->quick_push (empty
);
1618 = this->convert_tree (TREE_TYPE (field
), nested_ctor
, location
);
1619 if (!TREE_CONSTANT (elt
->value
))
1620 is_constant
= false;
1624 if (union_index
!= -1)
1626 gcc_assert (TREE_CODE (type_tree
) == UNION_TYPE
);
1627 tree val
= vals
.front ();
1628 for (int i
= 0; i
< union_index
; i
++)
1630 gcc_assert (field
!= NULL_TREE
);
1631 field
= DECL_CHAIN (field
);
1633 if (TREE_TYPE (field
) == error_mark_node
|| val
== error_mark_node
1634 || TREE_TYPE (val
) == error_mark_node
)
1635 return error_mark_node
;
1637 if (int_size_in_bytes (TREE_TYPE (field
)) == 0)
1639 // GIMPLE cannot represent indices of zero-sized types so
1640 // trying to construct a map with zero-sized keys might lead
1641 // to errors. Instead, we evaluate each expression that
1642 // would have been added as a map element for its
1643 // side-effects and construct an empty map.
1644 append_to_statement_list (val
, &sink
);
1648 constructor_elt empty
= {NULL
, NULL
};
1649 constructor_elt
*elt
= init
->quick_push (empty
);
1652 = this->convert_tree (TREE_TYPE (field
), val
, location
);
1653 if (!TREE_CONSTANT (elt
->value
))
1654 is_constant
= false;
1659 gcc_assert (TREE_CODE (type_tree
) == RECORD_TYPE
);
1660 for (std::vector
<tree
>::const_iterator p
= vals
.begin ();
1661 p
!= vals
.end (); ++p
, field
= DECL_CHAIN (field
))
1663 gcc_assert (field
!= NULL_TREE
);
1665 if (TREE_TYPE (field
) == error_mark_node
|| val
== error_mark_node
1666 || TREE_TYPE (val
) == error_mark_node
)
1667 return error_mark_node
;
1669 if (int_size_in_bytes (TREE_TYPE (field
)) == 0)
1671 // GIMPLE cannot represent indices of zero-sized types so
1672 // trying to construct a map with zero-sized keys might lead
1673 // to errors. Instead, we evaluate each expression that
1674 // would have been added as a map element for its
1675 // side-effects and construct an empty map.
1676 append_to_statement_list (val
, &sink
);
1680 constructor_elt empty
= {NULL
, NULL
};
1681 constructor_elt
*elt
= init
->quick_push (empty
);
1684 = this->convert_tree (TREE_TYPE (field
), val
, location
);
1685 if (!TREE_CONSTANT (elt
->value
))
1686 is_constant
= false;
1688 gcc_assert (field
== NULL_TREE
);
1692 tree ret
= build_constructor (type_tree
, init
);
1694 TREE_CONSTANT (ret
) = 1;
1695 if (sink
!= NULL_TREE
)
1696 ret
= fold_build2_loc (location
.gcc_location (), COMPOUND_EXPR
, type_tree
,
1702 Gcc_backend::array_constructor_expression (
1703 tree type_tree
, const std::vector
<unsigned long> &indexes
,
1704 const std::vector
<tree
> &vals
, Location location
)
1706 if (type_tree
== error_mark_node
)
1707 return error_mark_node
;
1709 gcc_assert (indexes
.size () == vals
.size ());
1711 tree element_type
= TREE_TYPE (type_tree
);
1712 HOST_WIDE_INT element_size
= int_size_in_bytes (element_type
);
1713 vec
<constructor_elt
, va_gc
> *init
;
1714 vec_alloc (init
, element_size
== 0 ? 0 : vals
.size ());
1716 tree sink
= NULL_TREE
;
1717 bool is_constant
= true;
1718 for (size_t i
= 0; i
< vals
.size (); ++i
)
1720 tree index
= size_int (indexes
[i
]);
1723 if (index
== error_mark_node
|| val
== error_mark_node
)
1724 return error_mark_node
;
1726 if (element_size
== 0)
1728 // GIMPLE cannot represent arrays of zero-sized types so trying
1729 // to construct an array of zero-sized values might lead to errors.
1730 // Instead, we evaluate each expression that would have been added as
1731 // an array value for its side-effects and construct an empty array.
1732 append_to_statement_list (val
, &sink
);
1736 if (!TREE_CONSTANT (val
))
1737 is_constant
= false;
1739 constructor_elt empty
= {NULL
, NULL
};
1740 constructor_elt
*elt
= init
->quick_push (empty
);
1745 tree ret
= build_constructor (type_tree
, init
);
1747 TREE_CONSTANT (ret
) = 1;
1748 if (sink
!= NULL_TREE
)
1749 ret
= fold_build2_loc (location
.gcc_location (), COMPOUND_EXPR
, type_tree
,
1754 // Build insns to create an array, initialize all elements of the array to
1755 // value, and return it
1757 Gcc_backend::array_initializer (tree fndecl
, tree block
, tree array_type
,
1758 tree length
, tree value
, tree
*tmp
,
1761 std::vector
<tree
> stmts
;
1763 // Temporary array we initialize with the desired value.
1765 Bvariable
*tmp_array
= this->temporary_variable (fndecl
, block
, array_type
,
1766 NULL_TREE
, true, locus
, &t
);
1767 tree arr
= tmp_array
->get_tree (locus
);
1768 stmts
.push_back (t
);
1770 // Temporary for the array length used for initialization loop guard.
1771 Bvariable
*tmp_len
= this->temporary_variable (fndecl
, block
, size_type_node
,
1772 length
, true, locus
, &t
);
1773 tree len
= tmp_len
->get_tree (locus
);
1774 stmts
.push_back (t
);
1776 // Temporary variable for pointer used to initialize elements.
1777 tree ptr_type
= this->pointer_type (TREE_TYPE (array_type
));
1779 = build1_loc (locus
.gcc_location (), ADDR_EXPR
, ptr_type
,
1780 this->array_index_expression (arr
, integer_zero_node
, locus
));
1781 Bvariable
*tmp_ptr
= this->temporary_variable (fndecl
, block
, ptr_type
,
1782 ptr_init
, false, locus
, &t
);
1783 tree ptr
= tmp_ptr
->get_tree (locus
);
1784 stmts
.push_back (t
);
1786 // push statement list for the loop
1787 std::vector
<tree
> loop_stmts
;
1789 // Loop exit condition:
1790 // if (length == 0) break;
1791 t
= this->comparison_expression (ComparisonOperator::EQUAL
, len
,
1792 this->zero_expression (TREE_TYPE (len
)),
1795 t
= this->exit_expression (t
, locus
);
1796 loop_stmts
.push_back (t
);
1798 // Assign value to the current pointer position
1800 t
= this->assignment_statement (build_fold_indirect_ref (ptr
), value
, locus
);
1801 loop_stmts
.push_back (t
);
1803 // Move pointer to next element
1805 tree size
= TYPE_SIZE_UNIT (TREE_TYPE (ptr_type
));
1806 t
= build2 (POSTINCREMENT_EXPR
, ptr_type
, ptr
, convert (ptr_type
, size
));
1807 loop_stmts
.push_back (t
);
1809 // Decrement loop counter.
1811 t
= build2 (POSTDECREMENT_EXPR
, TREE_TYPE (len
), len
,
1812 convert (TREE_TYPE (len
), integer_one_node
));
1813 loop_stmts
.push_back (t
);
1815 // pop statments and finish loop
1816 tree loop_body
= this->statement_list (loop_stmts
);
1817 stmts
.push_back (this->loop_expression (loop_body
, locus
));
1819 // Return the temporary in the provided pointer and the statement list which
1821 *tmp
= tmp_array
->get_tree (locus
);
1822 return this->statement_list (stmts
);
1825 // Return an expression representing ARRAY[INDEX]
1828 Gcc_backend::array_index_expression (tree array_tree
, tree index_tree
,
1831 if (array_tree
== error_mark_node
|| TREE_TYPE (array_tree
) == error_mark_node
1832 || index_tree
== error_mark_node
)
1833 return error_mark_node
;
1835 // A function call that returns a zero sized object will have been
1836 // changed to return void. If we see void here, assume we are
1837 // dealing with a zero sized type and just evaluate the operands.
1839 if (TREE_TYPE (array_tree
) != void_type_node
)
1840 ret
= build4_loc (location
.gcc_location (), ARRAY_REF
,
1841 TREE_TYPE (TREE_TYPE (array_tree
)), array_tree
,
1842 index_tree
, NULL_TREE
, NULL_TREE
);
1844 ret
= fold_build2_loc (location
.gcc_location (), COMPOUND_EXPR
,
1845 void_type_node
, array_tree
, index_tree
);
1850 // Create an expression for a call to FN_EXPR with FN_ARGS.
1852 Gcc_backend::call_expression (tree fn
, const std::vector
<tree
> &fn_args
,
1853 tree chain_expr
, Location location
)
1855 if (fn
== error_mark_node
|| TREE_TYPE (fn
) == error_mark_node
)
1856 return error_mark_node
;
1858 gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn
)));
1859 tree rettype
= TREE_TYPE (TREE_TYPE (TREE_TYPE (fn
)));
1861 size_t nargs
= fn_args
.size ();
1862 tree
*args
= nargs
== 0 ? NULL
: new tree
[nargs
];
1863 for (size_t i
= 0; i
< nargs
; ++i
)
1865 args
[i
] = fn_args
.at (i
);
1869 if (TREE_CODE (fndecl
) == ADDR_EXPR
)
1870 fndecl
= TREE_OPERAND (fndecl
, 0);
1872 // This is to support builtin math functions when using 80387 math.
1873 tree excess_type
= NULL_TREE
;
1874 if (optimize
&& TREE_CODE (fndecl
) == FUNCTION_DECL
1875 && fndecl_built_in_p (fndecl
, BUILT_IN_NORMAL
)
1876 && DECL_IS_UNDECLARED_BUILTIN (fndecl
) && nargs
> 0
1877 && ((SCALAR_FLOAT_TYPE_P (rettype
)
1878 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (args
[0])))
1879 || (COMPLEX_FLOAT_TYPE_P (rettype
)
1880 && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args
[0])))))
1882 excess_type
= excess_precision_type (TREE_TYPE (args
[0]));
1883 if (excess_type
!= NULL_TREE
)
1886 = mathfn_built_in (excess_type
, DECL_FUNCTION_CODE (fndecl
));
1887 if (excess_fndecl
== NULL_TREE
)
1888 excess_type
= NULL_TREE
;
1891 fn
= build_fold_addr_expr_loc (location
.gcc_location (),
1893 for (size_t i
= 0; i
< nargs
; ++i
)
1895 if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (args
[i
]))
1896 || COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args
[i
])))
1897 args
[i
] = ::convert (excess_type
, args
[i
]);
1904 = build_call_array_loc (location
.gcc_location (),
1905 excess_type
!= NULL_TREE
? excess_type
: rettype
,
1908 // check for deprecated function usage
1909 if (fndecl
&& TREE_DEPRECATED (fndecl
))
1911 // set up the call-site information for `warn_deprecated_use`
1912 input_location
= location
.gcc_location ();
1913 warn_deprecated_use (fndecl
, NULL_TREE
);
1917 CALL_EXPR_STATIC_CHAIN (ret
) = chain_expr
;
1919 if (excess_type
!= NULL_TREE
)
1921 // Calling convert here can undo our excess precision change.
1922 // That may or may not be a bug in convert_to_real.
1923 ret
= build1_loc (location
.gcc_location (), NOP_EXPR
, rettype
, ret
);
1930 // Variable initialization.
1933 Gcc_backend::init_statement (tree
, Bvariable
*var
, tree init_tree
)
1935 tree var_tree
= var
->get_decl ();
1936 if (var_tree
== error_mark_node
|| init_tree
== error_mark_node
)
1937 return error_mark_node
;
1938 gcc_assert (TREE_CODE (var_tree
) == VAR_DECL
);
1940 // To avoid problems with GNU ld, we don't make zero-sized
1941 // externally visible variables. That might lead us to doing an
1942 // initialization of a zero-sized expression to a non-zero sized
1943 // variable, or vice-versa. Avoid crashes by omitting the
1944 // initializer. Such initializations don't mean anything anyhow.
1945 if (int_size_in_bytes (TREE_TYPE (var_tree
)) != 0 && init_tree
!= NULL_TREE
1946 && TREE_TYPE (init_tree
) != void_type_node
1947 && int_size_in_bytes (TREE_TYPE (init_tree
)) != 0)
1949 DECL_INITIAL (var_tree
) = init_tree
;
1950 init_tree
= NULL_TREE
;
1953 tree ret
= build1_loc (DECL_SOURCE_LOCATION (var_tree
), DECL_EXPR
,
1954 void_type_node
, var_tree
);
1955 if (init_tree
!= NULL_TREE
)
1956 ret
= build2_loc (DECL_SOURCE_LOCATION (var_tree
), COMPOUND_EXPR
,
1957 void_type_node
, init_tree
, ret
);
1965 Gcc_backend::assignment_statement (tree lhs
, tree rhs
, Location location
)
1967 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
1968 return error_mark_node
;
1970 // To avoid problems with GNU ld, we don't make zero-sized
1971 // externally visible variables. That might lead us to doing an
1972 // assignment of a zero-sized expression to a non-zero sized
1973 // expression; avoid crashes here by avoiding assignments of
1974 // zero-sized expressions. Such assignments don't really mean
1976 if (TREE_TYPE (lhs
) == void_type_node
1977 || int_size_in_bytes (TREE_TYPE (lhs
)) == 0
1978 || TREE_TYPE (rhs
) == void_type_node
1979 || int_size_in_bytes (TREE_TYPE (rhs
)) == 0)
1980 return this->compound_statement (lhs
, rhs
);
1982 rhs
= this->convert_tree (TREE_TYPE (lhs
), rhs
, location
);
1984 return fold_build2_loc (location
.gcc_location (), MODIFY_EXPR
, void_type_node
,
1991 Gcc_backend::return_statement (tree fntree
, const std::vector
<tree
> &vals
,
1994 if (fntree
== error_mark_node
)
1995 return error_mark_node
;
1996 tree result
= DECL_RESULT (fntree
);
1997 if (result
== error_mark_node
)
1998 return error_mark_node
;
2000 // If the result size is zero bytes, we have set the function type
2001 // to have a result type of void, so don't return anything.
2002 // See the function_type method.
2003 tree res_type
= TREE_TYPE (result
);
2004 if (res_type
== void_type_node
|| int_size_in_bytes (res_type
) == 0)
2006 tree stmt_list
= NULL_TREE
;
2007 for (std::vector
<tree
>::const_iterator p
= vals
.begin ();
2008 p
!= vals
.end (); p
++)
2011 if (val
== error_mark_node
)
2012 return error_mark_node
;
2013 append_to_statement_list (val
, &stmt_list
);
2015 tree ret
= fold_build1_loc (location
.gcc_location (), RETURN_EXPR
,
2016 void_type_node
, NULL_TREE
);
2017 append_to_statement_list (ret
, &stmt_list
);
2023 ret
= fold_build1_loc (location
.gcc_location (), RETURN_EXPR
,
2024 void_type_node
, NULL_TREE
);
2025 else if (vals
.size () == 1)
2027 tree val
= vals
.front ();
2028 if (val
== error_mark_node
)
2029 return error_mark_node
;
2030 tree set
= fold_build2_loc (location
.gcc_location (), MODIFY_EXPR
,
2031 void_type_node
, result
, vals
.front ());
2032 ret
= fold_build1_loc (location
.gcc_location (), RETURN_EXPR
,
2033 void_type_node
, set
);
2037 // To return multiple values, copy the values into a temporary
2038 // variable of the right structure type, and then assign the
2039 // temporary variable to the DECL_RESULT in the return
2041 tree stmt_list
= NULL_TREE
;
2042 tree rettype
= TREE_TYPE (result
);
2044 if (DECL_STRUCT_FUNCTION (fntree
) == NULL
)
2045 push_struct_function (fntree
);
2047 push_cfun (DECL_STRUCT_FUNCTION (fntree
));
2048 tree rettmp
= create_tmp_var (rettype
, "RESULT");
2051 tree field
= TYPE_FIELDS (rettype
);
2052 for (std::vector
<tree
>::const_iterator p
= vals
.begin ();
2053 p
!= vals
.end (); p
++, field
= DECL_CHAIN (field
))
2055 gcc_assert (field
!= NULL_TREE
);
2057 = fold_build3_loc (location
.gcc_location (), COMPONENT_REF
,
2058 TREE_TYPE (field
), rettmp
, field
, NULL_TREE
);
2060 if (val
== error_mark_node
)
2061 return error_mark_node
;
2062 tree set
= fold_build2_loc (location
.gcc_location (), MODIFY_EXPR
,
2063 void_type_node
, ref
, (*p
));
2064 append_to_statement_list (set
, &stmt_list
);
2066 gcc_assert (field
== NULL_TREE
);
2067 tree set
= fold_build2_loc (location
.gcc_location (), MODIFY_EXPR
,
2068 void_type_node
, result
, rettmp
);
2069 tree ret_expr
= fold_build1_loc (location
.gcc_location (), RETURN_EXPR
,
2070 void_type_node
, set
);
2071 append_to_statement_list (ret_expr
, &stmt_list
);
2077 // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an
2078 // error occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and if not
2079 // NULL, it will always be executed. This is used for handling defers in Rust
2080 // functions. In C++, the resulting code is of this form:
2081 // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }
2084 Gcc_backend::exception_handler_statement (tree try_stmt
, tree except_stmt
,
2085 tree finally_stmt
, Location location
)
2087 if (try_stmt
== error_mark_node
|| except_stmt
== error_mark_node
2088 || finally_stmt
== error_mark_node
)
2089 return error_mark_node
;
2091 if (except_stmt
!= NULL_TREE
)
2092 try_stmt
= build2_loc (location
.gcc_location (), TRY_CATCH_EXPR
,
2093 void_type_node
, try_stmt
,
2094 build2_loc (location
.gcc_location (), CATCH_EXPR
,
2095 void_type_node
, NULL
, except_stmt
));
2096 if (finally_stmt
!= NULL_TREE
)
2097 try_stmt
= build2_loc (location
.gcc_location (), TRY_FINALLY_EXPR
,
2098 void_type_node
, try_stmt
, finally_stmt
);
2105 Gcc_backend::if_statement (tree
, tree cond_tree
, tree then_tree
, tree else_tree
,
2108 if (cond_tree
== error_mark_node
|| then_tree
== error_mark_node
2109 || else_tree
== error_mark_node
)
2110 return error_mark_node
;
2111 tree ret
= build3_loc (location
.gcc_location (), COND_EXPR
, void_type_node
,
2112 cond_tree
, then_tree
, else_tree
);
2119 Gcc_backend::loop_expression (tree body
, Location locus
)
2121 return fold_build1_loc (locus
.gcc_location (), LOOP_EXPR
, void_type_node
,
2126 Gcc_backend::exit_expression (tree cond_tree
, Location locus
)
2128 return fold_build1_loc (locus
.gcc_location (), EXIT_EXPR
, void_type_node
,
2132 // Pair of statements.
2135 Gcc_backend::compound_statement (tree s1
, tree s2
)
2137 tree stmt_list
= NULL_TREE
;
2139 if (t
== error_mark_node
)
2140 return error_mark_node
;
2141 append_to_statement_list (t
, &stmt_list
);
2143 if (t
== error_mark_node
)
2144 return error_mark_node
;
2145 append_to_statement_list (t
, &stmt_list
);
2147 // If neither statement has any side effects, stmt_list can be NULL
2149 if (stmt_list
== NULL_TREE
)
2150 stmt_list
= integer_zero_node
;
2155 // List of statements.
2158 Gcc_backend::statement_list (const std::vector
<tree
> &statements
)
2160 tree stmt_list
= NULL_TREE
;
2161 for (std::vector
<tree
>::const_iterator p
= statements
.begin ();
2162 p
!= statements
.end (); ++p
)
2165 if (t
== error_mark_node
)
2166 return error_mark_node
;
2167 append_to_statement_list (t
, &stmt_list
);
2172 // Make a block. For some reason gcc uses a dual structure for
2173 // blocks: BLOCK tree nodes and BIND_EXPR tree nodes. Since the
2174 // BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in
2178 Gcc_backend::block (tree fndecl
, tree enclosing
,
2179 const std::vector
<Bvariable
*> &vars
,
2180 Location start_location
, Location
)
2182 tree block_tree
= make_node (BLOCK
);
2183 if (enclosing
== NULL
)
2185 gcc_assert (fndecl
!= NULL_TREE
);
2187 // We may have already created a block for local variables when
2188 // we take the address of a parameter.
2189 if (DECL_INITIAL (fndecl
) == NULL_TREE
)
2191 BLOCK_SUPERCONTEXT (block_tree
) = fndecl
;
2192 DECL_INITIAL (fndecl
) = block_tree
;
2196 tree superblock_tree
= DECL_INITIAL (fndecl
);
2197 BLOCK_SUPERCONTEXT (block_tree
) = superblock_tree
;
2199 for (pp
= &BLOCK_SUBBLOCKS (superblock_tree
); *pp
!= NULL_TREE
;
2200 pp
= &BLOCK_CHAIN (*pp
))
2207 tree superblock_tree
= BIND_EXPR_BLOCK (enclosing
);
2208 gcc_assert (TREE_CODE (superblock_tree
) == BLOCK
);
2210 BLOCK_SUPERCONTEXT (block_tree
) = superblock_tree
;
2212 for (pp
= &BLOCK_SUBBLOCKS (superblock_tree
); *pp
!= NULL_TREE
;
2213 pp
= &BLOCK_CHAIN (*pp
))
2218 tree
*pp
= &BLOCK_VARS (block_tree
);
2219 for (std::vector
<Bvariable
*>::const_iterator pv
= vars
.begin ();
2220 pv
!= vars
.end (); ++pv
)
2222 *pp
= (*pv
)->get_decl ();
2223 if (*pp
!= error_mark_node
)
2224 pp
= &DECL_CHAIN (*pp
);
2228 TREE_USED (block_tree
) = 1;
2231 = build3_loc (start_location
.gcc_location (), BIND_EXPR
, void_type_node
,
2232 BLOCK_VARS (block_tree
), NULL_TREE
, block_tree
);
2233 TREE_SIDE_EFFECTS (bind_tree
) = 1;
2237 // Add statements to a block.
2240 Gcc_backend::block_add_statements (tree bind_tree
,
2241 const std::vector
<tree
> &statements
)
2243 tree stmt_list
= NULL_TREE
;
2244 for (std::vector
<tree
>::const_iterator p
= statements
.begin ();
2245 p
!= statements
.end (); ++p
)
2248 if (s
!= error_mark_node
)
2249 append_to_statement_list (s
, &stmt_list
);
2252 gcc_assert (TREE_CODE (bind_tree
) == BIND_EXPR
);
2253 BIND_EXPR_BODY (bind_tree
) = stmt_list
;
2256 // This is not static because we declare it with GTY(()) in rust-c.h.
2257 tree rust_non_zero_struct
;
2259 // Return a type corresponding to TYPE with non-zero size.
2262 Gcc_backend::non_zero_size_type (tree type
)
2264 if (int_size_in_bytes (type
) != 0)
2267 switch (TREE_CODE (type
))
2270 if (TYPE_FIELDS (type
) != NULL_TREE
)
2272 tree ns
= make_node (RECORD_TYPE
);
2273 tree field_trees
= NULL_TREE
;
2274 tree
*pp
= &field_trees
;
2275 for (tree field
= TYPE_FIELDS (type
); field
!= NULL_TREE
;
2276 field
= DECL_CHAIN (field
))
2278 tree ft
= TREE_TYPE (field
);
2279 if (field
== TYPE_FIELDS (type
))
2280 ft
= non_zero_size_type (ft
);
2281 tree f
= build_decl (DECL_SOURCE_LOCATION (field
), FIELD_DECL
,
2282 DECL_NAME (field
), ft
);
2283 DECL_CONTEXT (f
) = ns
;
2285 pp
= &DECL_CHAIN (f
);
2287 TYPE_FIELDS (ns
) = field_trees
;
2292 if (rust_non_zero_struct
== NULL_TREE
)
2294 type
= make_node (RECORD_TYPE
);
2295 tree field
= build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
2296 get_identifier ("dummy"), boolean_type_node
);
2297 DECL_CONTEXT (field
) = type
;
2298 TYPE_FIELDS (type
) = field
;
2300 rust_non_zero_struct
= type
;
2302 return rust_non_zero_struct
;
2305 tree element_type
= non_zero_size_type (TREE_TYPE (type
));
2306 return build_array_type_nelts (element_type
, 1);
2316 // Convert EXPR_TREE to TYPE_TREE. Sometimes the same unnamed Rust type
2317 // can be created multiple times and thus have multiple tree
2318 // representations. Make sure this does not confuse the middle-end.
2321 Gcc_backend::convert_tree (tree type_tree
, tree expr_tree
, Location location
)
2323 if (type_tree
== TREE_TYPE (expr_tree
))
2326 if (type_tree
== error_mark_node
|| expr_tree
== error_mark_node
2327 || TREE_TYPE (expr_tree
) == error_mark_node
)
2328 return error_mark_node
;
2330 if (POINTER_TYPE_P (type_tree
) || INTEGRAL_TYPE_P (type_tree
)
2331 || SCALAR_FLOAT_TYPE_P (type_tree
) || COMPLEX_FLOAT_TYPE_P (type_tree
))
2332 return fold_convert_loc (location
.gcc_location (), type_tree
, expr_tree
);
2333 else if (TREE_CODE (type_tree
) == RECORD_TYPE
2334 || TREE_CODE (type_tree
) == UNION_TYPE
2335 || TREE_CODE (type_tree
) == ARRAY_TYPE
)
2337 gcc_assert (int_size_in_bytes (type_tree
)
2338 == int_size_in_bytes (TREE_TYPE (expr_tree
)));
2339 if (TYPE_MAIN_VARIANT (type_tree
)
2340 == TYPE_MAIN_VARIANT (TREE_TYPE (expr_tree
)))
2341 return fold_build1_loc (location
.gcc_location (), NOP_EXPR
, type_tree
,
2343 return fold_build1_loc (location
.gcc_location (), VIEW_CONVERT_EXPR
,
2344 type_tree
, expr_tree
);
2350 // Make a global variable.
2353 Gcc_backend::global_variable (const std::string
&var_name
,
2354 const std::string
&asm_name
, tree type_tree
,
2355 bool is_external
, bool is_hidden
,
2356 bool in_unique_section
, Location location
)
2358 if (type_tree
== error_mark_node
)
2359 return this->error_variable ();
2361 // The GNU linker does not like dynamic variables with zero size.
2362 tree orig_type_tree
= type_tree
;
2363 if ((is_external
|| !is_hidden
) && int_size_in_bytes (type_tree
) == 0)
2364 type_tree
= this->non_zero_size_type (type_tree
);
2366 tree decl
= build_decl (location
.gcc_location (), VAR_DECL
,
2367 get_identifier_from_string (var_name
), type_tree
);
2369 DECL_EXTERNAL (decl
) = 1;
2371 TREE_STATIC (decl
) = 1;
2374 TREE_PUBLIC (decl
) = 1;
2375 SET_DECL_ASSEMBLER_NAME (decl
, get_identifier_from_string (asm_name
));
2379 SET_DECL_ASSEMBLER_NAME (decl
, get_identifier_from_string (asm_name
));
2382 TREE_USED (decl
) = 1;
2384 if (in_unique_section
)
2385 resolve_unique_section (decl
, 0, 1);
2387 rust_preserve_from_gc (decl
);
2389 return new Bvariable (decl
, orig_type_tree
);
2392 // Set the initial value of a global variable.
2395 Gcc_backend::global_variable_set_init (Bvariable
*var
, tree expr_tree
)
2397 if (expr_tree
== error_mark_node
)
2399 gcc_assert (TREE_CONSTANT (expr_tree
));
2400 tree var_decl
= var
->get_decl ();
2401 if (var_decl
== error_mark_node
)
2403 DECL_INITIAL (var_decl
) = expr_tree
;
2405 // If this variable goes in a unique section, it may need to go into
2406 // a different one now that DECL_INITIAL is set.
2407 if (symtab_node::get (var_decl
)
2408 && symtab_node::get (var_decl
)->implicit_section
)
2410 set_decl_section_name (var_decl
, (const char *) NULL
);
2411 resolve_unique_section (var_decl
, compute_reloc_for_constant (expr_tree
),
2416 // Make a local variable.
2419 Gcc_backend::local_variable (tree function
, const std::string
&name
,
2420 tree type_tree
, Bvariable
*decl_var
,
2423 if (type_tree
== error_mark_node
)
2424 return this->error_variable ();
2425 tree decl
= build_decl (location
.gcc_location (), VAR_DECL
,
2426 get_identifier_from_string (name
), type_tree
);
2427 DECL_CONTEXT (decl
) = function
;
2429 if (decl_var
!= NULL
)
2431 DECL_HAS_VALUE_EXPR_P (decl
) = 1;
2432 SET_DECL_VALUE_EXPR (decl
, decl_var
->get_decl ());
2434 rust_preserve_from_gc (decl
);
2435 return new Bvariable (decl
);
2438 // Make a function parameter variable.
2441 Gcc_backend::parameter_variable (tree function
, const std::string
&name
,
2442 tree type_tree
, Location location
)
2444 if (type_tree
== error_mark_node
)
2445 return this->error_variable ();
2446 tree decl
= build_decl (location
.gcc_location (), PARM_DECL
,
2447 get_identifier_from_string (name
), type_tree
);
2448 DECL_CONTEXT (decl
) = function
;
2449 DECL_ARG_TYPE (decl
) = type_tree
;
2451 rust_preserve_from_gc (decl
);
2452 return new Bvariable (decl
);
2455 // Make a static chain variable.
2458 Gcc_backend::static_chain_variable (tree fndecl
, const std::string
&name
,
2459 tree type_tree
, Location location
)
2461 if (type_tree
== error_mark_node
)
2462 return this->error_variable ();
2463 tree decl
= build_decl (location
.gcc_location (), PARM_DECL
,
2464 get_identifier_from_string (name
), type_tree
);
2465 DECL_CONTEXT (decl
) = fndecl
;
2466 DECL_ARG_TYPE (decl
) = type_tree
;
2467 TREE_USED (decl
) = 1;
2468 DECL_ARTIFICIAL (decl
) = 1;
2469 DECL_IGNORED_P (decl
) = 1;
2470 TREE_READONLY (decl
) = 1;
2472 struct function
*f
= DECL_STRUCT_FUNCTION (fndecl
);
2475 push_struct_function (fndecl
);
2477 f
= DECL_STRUCT_FUNCTION (fndecl
);
2479 gcc_assert (f
->static_chain_decl
== NULL
);
2480 f
->static_chain_decl
= decl
;
2481 DECL_STATIC_CHAIN (fndecl
) = 1;
2483 rust_preserve_from_gc (decl
);
2484 return new Bvariable (decl
);
2487 // Make a temporary variable.
2490 Gcc_backend::temporary_variable (tree fndecl
, tree bind_tree
, tree type_tree
,
2491 tree init_tree
, bool is_address_taken
,
2492 Location location
, tree
*pstatement
)
2494 gcc_assert (fndecl
!= NULL_TREE
);
2495 if (type_tree
== error_mark_node
|| init_tree
== error_mark_node
2496 || fndecl
== error_mark_node
)
2498 *pstatement
= error_mark_node
;
2499 return this->error_variable ();
2503 // We can only use create_tmp_var if the type is not addressable.
2504 if (!TREE_ADDRESSABLE (type_tree
))
2506 if (DECL_STRUCT_FUNCTION (fndecl
) == NULL
)
2507 push_struct_function (fndecl
);
2509 push_cfun (DECL_STRUCT_FUNCTION (fndecl
));
2511 var
= create_tmp_var (type_tree
, "RUSTTMP");
2516 gcc_assert (bind_tree
!= NULL_TREE
);
2517 var
= build_decl (location
.gcc_location (), VAR_DECL
,
2518 create_tmp_var_name ("RUSTTMP"), type_tree
);
2519 DECL_ARTIFICIAL (var
) = 1;
2520 DECL_IGNORED_P (var
) = 1;
2521 TREE_USED (var
) = 1;
2522 DECL_CONTEXT (var
) = fndecl
;
2524 // We have to add this variable to the BLOCK and the BIND_EXPR.
2525 gcc_assert (TREE_CODE (bind_tree
) == BIND_EXPR
);
2526 tree block_tree
= BIND_EXPR_BLOCK (bind_tree
);
2527 gcc_assert (TREE_CODE (block_tree
) == BLOCK
);
2528 DECL_CHAIN (var
) = BLOCK_VARS (block_tree
);
2529 BLOCK_VARS (block_tree
) = var
;
2530 BIND_EXPR_VARS (bind_tree
) = BLOCK_VARS (block_tree
);
2533 if (this->type_size (type_tree
) != 0 && init_tree
!= NULL_TREE
2534 && TREE_TYPE (init_tree
) != void_type_node
)
2535 DECL_INITIAL (var
) = this->convert_tree (type_tree
, init_tree
, location
);
2537 if (is_address_taken
)
2538 TREE_ADDRESSABLE (var
) = 1;
2541 = build1_loc (location
.gcc_location (), DECL_EXPR
, void_type_node
, var
);
2543 // For a zero sized type, don't initialize VAR with BINIT, but still
2544 // evaluate BINIT for its side effects.
2545 if (init_tree
!= NULL_TREE
2546 && (this->type_size (type_tree
) == 0
2547 || TREE_TYPE (init_tree
) == void_type_node
))
2548 *pstatement
= this->compound_statement (init_tree
, *pstatement
);
2550 return new Bvariable (var
);
2556 Gcc_backend::label (tree func_tree
, const std::string
&name
, Location location
)
2561 if (DECL_STRUCT_FUNCTION (func_tree
) == NULL
)
2562 push_struct_function (func_tree
);
2564 push_cfun (DECL_STRUCT_FUNCTION (func_tree
));
2566 decl
= create_artificial_label (location
.gcc_location ());
2572 tree id
= get_identifier_from_string (name
);
2574 = build_decl (location
.gcc_location (), LABEL_DECL
, id
, void_type_node
);
2575 DECL_CONTEXT (decl
) = func_tree
;
2580 // Make a statement which defines a label.
2583 Gcc_backend::label_definition_statement (tree label
)
2585 return fold_build1_loc (DECL_SOURCE_LOCATION (label
), LABEL_EXPR
,
2586 void_type_node
, label
);
2589 // Make a goto statement.
2592 Gcc_backend::goto_statement (tree label
, Location location
)
2594 return fold_build1_loc (location
.gcc_location (), GOTO_EXPR
, void_type_node
,
2598 // Get the address of a label.
2601 Gcc_backend::label_address (tree label
, Location location
)
2603 TREE_USED (label
) = 1;
2604 TREE_ADDRESSABLE (label
) = 1;
2606 = fold_convert_loc (location
.gcc_location (), ptr_type_node
,
2607 build_fold_addr_expr_loc (location
.gcc_location (),
2612 // Declare or define a new function.
2615 Gcc_backend::function (tree functype
, const std::string
&name
,
2616 const std::string
&asm_name
, unsigned int flags
,
2619 if (functype
!= error_mark_node
)
2621 gcc_assert (FUNCTION_POINTER_TYPE_P (functype
));
2622 functype
= TREE_TYPE (functype
);
2624 tree id
= get_identifier_from_string (name
);
2625 if (functype
== error_mark_node
|| id
== error_mark_node
)
2626 return error_mark_node
;
2629 = build_decl (location
.gcc_location (), FUNCTION_DECL
, id
, functype
);
2630 if (!asm_name
.empty ())
2631 SET_DECL_ASSEMBLER_NAME (decl
, get_identifier_from_string (asm_name
));
2633 if ((flags
& function_is_declaration
) != 0)
2634 DECL_EXTERNAL (decl
) = 1;
2637 tree restype
= TREE_TYPE (functype
);
2638 tree resdecl
= build_decl (location
.gcc_location (), RESULT_DECL
,
2639 NULL_TREE
, restype
);
2640 DECL_ARTIFICIAL (resdecl
) = 1;
2641 DECL_IGNORED_P (resdecl
) = 1;
2642 DECL_CONTEXT (resdecl
) = decl
;
2643 DECL_RESULT (decl
) = resdecl
;
2645 if ((flags
& function_is_uninlinable
) != 0)
2646 DECL_UNINLINABLE (decl
) = 1;
2647 if ((flags
& function_does_not_return
) != 0)
2648 TREE_THIS_VOLATILE (decl
) = 1;
2649 if ((flags
& function_in_unique_section
) != 0)
2650 resolve_unique_section (decl
, 0, 1);
2652 rust_preserve_from_gc (decl
);
2656 // Create a statement that runs all deferred calls for FUNCTION. This should
2657 // be a statement that looks like this in C++:
2659 // try { UNDEFER; } catch { CHECK_DEFER; goto finish; }
2662 Gcc_backend::function_defer_statement (tree function
, tree undefer_tree
,
2663 tree defer_tree
, Location location
)
2665 if (undefer_tree
== error_mark_node
|| defer_tree
== error_mark_node
2666 || function
== error_mark_node
)
2667 return error_mark_node
;
2669 if (DECL_STRUCT_FUNCTION (function
) == NULL
)
2670 push_struct_function (function
);
2672 push_cfun (DECL_STRUCT_FUNCTION (function
));
2674 tree stmt_list
= NULL
;
2675 tree label
= this->label (function
, "", location
);
2676 tree label_def
= this->label_definition_statement (label
);
2677 append_to_statement_list (label_def
, &stmt_list
);
2679 tree jump_stmt
= this->goto_statement (label
, location
);
2681 = build2 (COMPOUND_EXPR
, void_type_node
, defer_tree
, jump_stmt
);
2682 catch_body
= build2 (CATCH_EXPR
, void_type_node
, NULL
, catch_body
);
2684 = build2 (TRY_CATCH_EXPR
, void_type_node
, undefer_tree
, catch_body
);
2685 append_to_statement_list (try_catch
, &stmt_list
);
2691 // Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
2692 // This will only be called for a function definition.
2695 Gcc_backend::function_set_parameters (
2696 tree function
, const std::vector
<Bvariable
*> ¶m_vars
)
2698 if (function
== error_mark_node
)
2701 tree params
= NULL_TREE
;
2703 for (std::vector
<Bvariable
*>::const_iterator pv
= param_vars
.begin ();
2704 pv
!= param_vars
.end (); ++pv
)
2706 *pp
= (*pv
)->get_decl ();
2707 gcc_assert (*pp
!= error_mark_node
);
2708 pp
= &DECL_CHAIN (*pp
);
2711 DECL_ARGUMENTS (function
) = params
;
2715 // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
2716 // FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
2717 // emit early debugging information.
2720 Gcc_backend::write_global_definitions (
2721 const std::vector
<tree
> &type_decls
, const std::vector
<tree
> &constant_decls
,
2722 const std::vector
<tree
> &function_decls
,
2723 const std::vector
<Bvariable
*> &variable_decls
)
2725 size_t count_definitions
= type_decls
.size () + constant_decls
.size ()
2726 + function_decls
.size () + variable_decls
.size ();
2728 tree
*defs
= new tree
[count_definitions
];
2730 // Convert all non-erroneous declarations into Gimple form.
2732 for (std::vector
<Bvariable
*>::const_iterator p
= variable_decls
.begin ();
2733 p
!= variable_decls
.end (); ++p
)
2735 tree v
= (*p
)->get_decl ();
2736 if (v
!= error_mark_node
)
2739 rust_preserve_from_gc (defs
[i
]);
2744 for (std::vector
<tree
>::const_iterator p
= type_decls
.begin ();
2745 p
!= type_decls
.end (); ++p
)
2747 tree type_tree
= (*p
);
2748 if (type_tree
!= error_mark_node
&& IS_TYPE_OR_DECL_P (type_tree
))
2750 defs
[i
] = TYPE_NAME (type_tree
);
2751 gcc_assert (defs
[i
] != NULL
);
2752 rust_preserve_from_gc (defs
[i
]);
2756 for (std::vector
<tree
>::const_iterator p
= constant_decls
.begin ();
2757 p
!= constant_decls
.end (); ++p
)
2759 if ((*p
) != error_mark_node
)
2762 rust_preserve_from_gc (defs
[i
]);
2766 for (std::vector
<tree
>::const_iterator p
= function_decls
.begin ();
2767 p
!= function_decls
.end (); ++p
)
2770 if (decl
!= error_mark_node
)
2772 rust_preserve_from_gc (decl
);
2773 if (DECL_STRUCT_FUNCTION (decl
) == NULL
)
2774 allocate_struct_function (decl
, false);
2775 dump_function (TDI_original
, decl
);
2776 cgraph_node::finalize_function (decl
, true);
2783 // Pass everything back to the middle-end.
2785 wrapup_global_declarations (defs
, i
);
2791 Gcc_backend::write_export_data (const char *bytes
, unsigned int size
)
2793 rust_write_export_data (bytes
, size
);
2796 // Return the backend generator.
2801 return new Gcc_backend ();