PR111048: Set arg_npatterns correctly.
[official-gcc.git] / gcc / rust / rust-gcc.cc
blobcf20b5b98e02bf06376c079736ae38aeeeb4ecdb
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.
4 // forked from gccgo
6 // This file is part of GCC.
8 // GCC is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 3, or (at your option) any later
11 // version.
13 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with GCC; see the file COPYING3. If not see
20 // <http://www.gnu.org/licenses/>.
22 #include "rust-system.h"
24 // This has to be included outside of extern "C", so we have to
25 // include it here before tree.h includes it later.
26 #include <gmp.h>
28 #include "tree.h"
29 #include "opts.h"
30 #include "fold-const.h"
31 #include "stringpool.h"
32 #include "stor-layout.h"
33 #include "varasm.h"
34 #include "tree-iterator.h"
35 #include "tm.h"
36 #include "function.h"
37 #include "cgraph.h"
38 #include "convert.h"
39 #include "gimple-expr.h"
40 #include "gimplify.h"
41 #include "langhooks.h"
42 #include "toplev.h"
43 #include "output.h"
44 #include "realmpfr.h"
45 #include "builtins.h"
46 #include "print-tree.h"
47 #include "attribs.h"
49 #include "rust-location.h"
50 #include "rust-linemap.h"
51 #include "rust-backend.h"
52 #include "rust-object-export.h"
53 #include "rust-gcc.h"
55 #include "backend/rust-tree.h"
56 #include "backend/rust-builtins.h"
58 // Get the tree of a variable for use as an expression. If this is a
59 // zero-sized global, create an expression that refers to the decl but
60 // has zero size.
61 tree
62 Bvariable::get_tree (Location location) const
64 if (this->t_ == error_mark_node)
65 return error_mark_node;
67 TREE_USED (this->t_) = 1;
68 if (this->orig_type_ == NULL || TREE_TYPE (this->t_) == this->orig_type_)
70 return this->t_;
73 // Return *(orig_type*)&decl. */
74 tree t = build_fold_addr_expr_loc (location.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
88 public:
89 Gcc_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 ());
99 // Types.
101 tree unit_type ()
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 ());
111 return unit_type;
114 tree bool_type () { return boolean_type_node; }
116 tree char_type () { return char_type_node; }
118 tree wchar_type ()
120 tree wchar = make_unsigned_type (32);
121 TYPE_STRING_FLAG (wchar) = 1;
122 return wchar;
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,
144 const Location);
146 tree function_type_varadic (const typed_identifier &,
147 const std::vector<typed_identifier> &,
148 const std::vector<typed_identifier> &, tree,
149 const Location);
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);
169 // Expressions.
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,
215 Location);
217 tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right,
218 Location);
220 tree constructor_expression (tree, bool, const std::vector<tree> &, int,
221 Location);
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);
233 // Statements.
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,
242 Location);
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);
255 // Blocks.
257 tree block (tree, tree, const std::vector<Bvariable *> &, Location, Location);
259 void block_add_statements (tree, const std::vector<tree> &);
261 // Variables.
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 *,
273 Location);
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,
280 tree *);
282 // Labels.
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);
292 // Functions.
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,
298 Location);
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);
310 private:
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.
322 static inline tree
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
333 for ++ and --. */
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,
363 // NULL_TREE),
364 // builtin_const);
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),
372 // 0);
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),
379 // 0);
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),
386 // 0);
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,
392 // NULL_TREE),
393 // builtin_const);
394 // this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll",
395 // build_function_type_list (integer_type_node,
396 // long_long_unsigned_type_node,
397 // NULL_TREE),
398 // builtin_const);
399 // this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz",
400 // build_function_type_list (integer_type_node,
401 // unsigned_type_node,
402 // NULL_TREE),
403 // builtin_const);
404 // this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
405 // build_function_type_list (integer_type_node,
406 // long_long_unsigned_type_node,
407 // NULL_TREE),
408 // builtin_const);
409 // this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
410 // build_function_type_list (integer_type_node,
411 // unsigned_type_node,
412 // NULL_TREE),
413 // builtin_const);
414 // this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll",
415 // "popcountll",
416 // build_function_type_list (integer_type_node,
417 // long_long_unsigned_type_node,
418 // NULL_TREE),
419 // builtin_const);
420 // this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
421 // build_function_type_list (uint16_type_node,
422 // uint16_type_node, NULL_TREE),
423 // builtin_const);
424 // this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
425 // build_function_type_list (uint32_type_node,
426 // uint32_type_node, NULL_TREE),
427 // builtin_const);
428 // this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64",
429 // build_function_type_list (uint64_type_node,
430 // uint64_type_node, NULL_TREE),
431 // builtin_const);
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",
440 // NULL, t, 0);
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,
445 // 0);
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
454 // cases.
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,
463 // NULL_TREE),
464 // builtin_novops);
466 // The compiler uses __builtin_unreachable for cases that cannot
467 // occur.
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,
476 // 0);
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,
481 // 0);
483 // t = build_function_type_list (void_type_node, ptr_type_node,
484 // uint32_type_node,
485 // integer_type_node, NULL_TREE);
486 // this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t,
487 // 0);
489 // t = build_function_type_list (void_type_node, ptr_type_node,
490 // uint64_type_node,
491 // integer_type_node, NULL_TREE);
492 // this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t,
493 // 0);
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",
498 // NULL,
499 // t, 0);
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",
504 // NULL,
505 // t, 0);
507 // t = build_function_type_list (boolean_type_node, ptr_type_node,
508 // ptr_type_node,
509 // uint32_type_node, boolean_type_node,
510 // integer_type_node, integer_type_node,
511 // NULL_TREE);
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,
516 // ptr_type_node,
517 // uint64_type_node, boolean_type_node,
518 // integer_type_node, integer_type_node,
519 // NULL_TREE);
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",
526 // NULL, t, 0);
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",
531 // NULL, t, 0);
533 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
534 // unsigned_char_type_node, integer_type_node,
535 // NULL_TREE);
536 // this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
537 // NULL, t, 0);
538 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1",
539 // NULL, t, 0);
541 // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
542 // unsigned_char_type_node, integer_type_node,
543 // NULL_TREE);
544 // this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
545 // NULL,
546 // t, 0);
547 // this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1",
548 // NULL,
549 // t, 0);
552 // Get an unnamed integer type.
555 Gcc_backend::get_pointer_size ()
557 return POINTER_SIZE;
560 tree
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;
568 tree
569 Gcc_backend::integer_type (bool is_unsigned, int bits)
571 tree type;
572 if (is_unsigned)
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;
582 else
583 type = make_unsigned_type (bits);
585 else
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;
595 else
596 type = make_signed_type (bits);
598 return type;
601 // Get an unnamed float type.
603 tree
604 Gcc_backend::float_type (int bits)
606 tree type;
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;
613 else
615 type = make_node (REAL_TYPE);
616 TYPE_PRECISION (type) = bits;
617 layout_type (type);
619 return type;
622 // Get an unnamed complex type.
624 tree
625 Gcc_backend::complex_type (int bits)
627 tree type;
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;
634 else
636 type = make_node (REAL_TYPE);
637 TYPE_PRECISION (type) = bits / 2;
638 layout_type (type);
639 type = build_complex_type (type);
641 return type;
644 // Get a pointer type.
646 tree
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);
652 return type;
655 // Get a reference type.
657 tree
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);
663 return type;
666 // Get immutable type
668 tree
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);
674 return constified;
677 // Make a function type.
679 tree
680 Gcc_backend::function_type (const typed_identifier &receiver,
681 const std::vector<typed_identifier> &parameters,
682 const std::vector<typed_identifier> &results,
683 tree result_struct, Location)
685 tree args = NULL_TREE;
686 tree *pp = &args;
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)
699 tree t = p->type;
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;
710 tree result;
711 if (results.empty ())
712 result = void_type_node;
713 else if (results.size () == 1)
714 result = results.front ().type;
715 else
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);
738 tree
739 Gcc_backend::function_type_varadic (
740 const typed_identifier &receiver,
741 const std::vector<typed_identifier> &parameters,
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);
746 size_t offs = 0;
748 if (receiver.type != NULL_TREE)
750 tree t = receiver.type;
751 if (t == error_mark_node)
752 return error_mark_node;
754 args[offs++] = t;
757 for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
758 p != parameters.end (); ++p)
760 tree t = p->type;
761 if (t == error_mark_node)
762 return error_mark_node;
763 args[offs++] = t;
766 tree result;
767 if (results.empty ())
768 result = void_type_node;
769 else if (results.size () == 1)
770 result = results.front ().type;
771 else
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);
794 tree
795 Gcc_backend::function_ptr_type (tree result_type,
796 const std::vector<tree> &parameters,
797 Location /* locus */)
799 tree args = NULL_TREE;
800 tree *pp = &args;
802 for (auto &param : 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.
826 tree
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.
834 tree
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.
842 tree
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;
858 *pp = field;
859 pp = &DECL_CHAIN (field);
861 TYPE_FIELDS (fill) = field_trees;
862 layout_type (fill);
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);
870 return fill;
873 // Make an array type.
875 tree
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.
883 tree
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
894 // the length.
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);
901 layout_type (fill);
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));
910 return fill;
913 // Return a named version of a type.
915 tree
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;
933 return type;
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;
941 return copy;
944 // Return the size of a type.
946 int64_t
947 Gcc_backend::type_size (tree t)
949 if (t == error_mark_node)
950 return 1;
951 if (t == void_type_node)
952 return 0;
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)
958 return -1;
959 return ret;
962 // Return the alignment of a type.
964 int64_t
965 Gcc_backend::type_alignment (tree t)
967 if (t == error_mark_node)
968 return 1;
969 return TYPE_ALIGN_UNIT (t);
972 // Return the alignment of a struct field of type BTYPE.
974 int64_t
975 Gcc_backend::type_field_alignment (tree t)
977 if (t == error_mark_node)
978 return 1;
979 return rust_field_alignment (t);
982 // Return the offset of a field in a struct.
984 int64_t
985 Gcc_backend::type_field_offset (tree struct_tree, size_t index)
987 if (struct_tree == error_mark_node)
988 return 0;
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);
999 return ret;
1002 // Return the zero value for a type.
1004 tree
1005 Gcc_backend::zero_expression (tree t)
1007 tree ret;
1008 if (t == error_mark_node)
1009 ret = error_mark_node;
1010 else
1011 ret = build_zero_cst (t);
1012 return ret;
1015 // An expression that references a variable.
1017 tree
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
1026 tree
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));
1033 return ret;
1036 // Return a typed value as a constant floating-point number.
1038 tree
1039 Gcc_backend::float_constant_expression (tree t, mpfr_t val)
1041 tree ret;
1042 if (t == error_mark_node)
1043 return error_mark_node;
1045 REAL_VALUE_TYPE r1;
1046 real_from_mpfr (&r1, val, t, GMP_RNDN);
1047 REAL_VALUE_TYPE r2;
1048 real_convert (&r2, TYPE_MODE (t), &r1);
1049 ret = build_real (t, r2);
1050 return ret;
1053 // Return a typed real and imaginary value as a constant complex number.
1055 tree
1056 Gcc_backend::complex_constant_expression (tree t, mpc_t val)
1058 tree ret;
1059 if (t == error_mark_node)
1060 return error_mark_node;
1062 REAL_VALUE_TYPE r1;
1063 real_from_mpfr (&r1, mpc_realref (val), TREE_TYPE (t), GMP_RNDN);
1064 REAL_VALUE_TYPE r2;
1065 real_convert (&r2, TYPE_MODE (TREE_TYPE (t)), &r1);
1067 REAL_VALUE_TYPE r3;
1068 real_from_mpfr (&r3, mpc_imagref (val), TREE_TYPE (t), GMP_RNDN);
1069 REAL_VALUE_TYPE r4;
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));
1074 return ret;
1077 // Make a constant string expression.
1079 tree
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;
1089 return string_val;
1092 tree
1093 Gcc_backend::wchar_constant_expression (wchar_t c)
1095 return build_int_cst (this->wchar_type (), c);
1098 tree
1099 Gcc_backend::char_constant_expression (char c)
1101 return build_int_cst (this->char_type (), c);
1104 // Make a constant boolean expression.
1106 tree
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.
1114 tree
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)));
1120 tree ret
1121 = fold_build1_loc (location.gcc_location (), REALPART_EXPR,
1122 TREE_TYPE (TREE_TYPE (complex_tree)), complex_tree);
1123 return ret;
1126 // Return the imaginary part of a complex expression.
1128 tree
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)));
1134 tree ret
1135 = fold_build1_loc (location.gcc_location (), IMAGPART_EXPR,
1136 TREE_TYPE (TREE_TYPE (complex_tree)), complex_tree);
1137 return ret;
1140 // Make a complex expression given its real and imaginary parts.
1142 tree
1143 Gcc_backend::complex_expression (tree real_tree, tree imag_tree,
1144 Location location)
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);
1154 return ret;
1157 // An expression that converts an expression to a different type.
1159 tree
1160 Gcc_backend::convert_expression (tree type_tree, tree expr_tree,
1161 Location location)
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;
1167 tree ret;
1168 if (this->type_size (type_tree) == 0
1169 || TREE_TYPE (expr_tree) == void_type_node)
1171 // Do not convert zero-sized types.
1172 ret = expr_tree;
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);
1187 else
1188 ret = fold_convert_loc (location.gcc_location (), type_tree, expr_tree);
1190 return ret;
1193 // Return an expression for the field at INDEX in BSTRUCT.
1195 tree
1196 Gcc_backend::struct_field_expression (tree struct_tree, size_t index,
1197 Location location)
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;
1222 return ret;
1225 // Return an expression that executes BSTAT before BEXPR.
1227 tree
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);
1234 return ret;
1237 // Return an expression that executes THEN_EXPR if CONDITION is true, or
1238 // ELSE_EXPR otherwise.
1240 tree
1241 Gcc_backend::conditional_expression (tree, tree type_tree, tree cond_expr,
1242 tree then_expr, tree else_expr,
1243 Location location)
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);
1250 return ret;
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)
1259 switch (op)
1261 case NegationOperator::NEGATE:
1262 return NEGATE_EXPR;
1263 case NegationOperator::NOT:
1264 return TRUTH_NOT_EXPR;
1265 default:
1266 gcc_unreachable ();
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
1273 operands). */
1274 static enum tree_code
1275 operator_to_tree_code (ArithmeticOrLogicalOperator op, bool floating_point)
1277 switch (op)
1279 case ArithmeticOrLogicalOperator::ADD:
1280 return PLUS_EXPR;
1281 case ArithmeticOrLogicalOperator::SUBTRACT:
1282 return MINUS_EXPR;
1283 case ArithmeticOrLogicalOperator::MULTIPLY:
1284 return MULT_EXPR;
1285 case ArithmeticOrLogicalOperator::DIVIDE:
1286 if (floating_point)
1287 return RDIV_EXPR;
1288 else
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:
1299 return LSHIFT_EXPR;
1300 case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
1301 return RSHIFT_EXPR;
1302 default:
1303 gcc_unreachable ();
1307 static enum tree_code
1308 operator_to_tree_code (ComparisonOperator op)
1310 switch (op)
1312 case ComparisonOperator::EQUAL:
1313 return EQ_EXPR;
1314 case ComparisonOperator::NOT_EQUAL:
1315 return NE_EXPR;
1316 case ComparisonOperator::GREATER_THAN:
1317 return GT_EXPR;
1318 case ComparisonOperator::LESS_THAN:
1319 return LT_EXPR;
1320 case ComparisonOperator::GREATER_OR_EQUAL:
1321 return GE_EXPR;
1322 case ComparisonOperator::LESS_OR_EQUAL:
1323 return LE_EXPR;
1324 default:
1325 gcc_unreachable ();
1329 static enum tree_code
1330 operator_to_tree_code (LazyBooleanOperator op)
1332 switch (op)
1334 case LazyBooleanOperator::LOGICAL_OR:
1335 return TRUTH_ORIF_EXPR;
1336 case LazyBooleanOperator::LOGICAL_AND:
1337 return TRUTH_ANDIF_EXPR;
1338 default:
1339 gcc_unreachable ();
1343 /* Helper function for deciding if a tree is a floating point node. */
1344 bool
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.
1352 tree
1353 Gcc_backend::negation_expression (NegationOperator op, tree expr_tree,
1354 Location location)
1356 /* Check if the expression is an error, in which case we return an error
1357 expression. */
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
1362 operand. */
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;
1371 if (floating_point)
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);
1386 return new_tree;
1389 tree
1390 Gcc_backend::arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op,
1391 tree left, tree right,
1392 Location location)
1394 /* Check if either expression is an error, in which case we return an error
1395 expression. */
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
1400 arithmetics. */
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;
1414 if (floating_point)
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);
1432 return ret;
1435 static bool
1436 is_overflowing_expr (ArithmeticOrLogicalOperator op)
1438 switch (op)
1440 case ArithmeticOrLogicalOperator::ADD:
1441 case ArithmeticOrLogicalOperator::SUBTRACT:
1442 case ArithmeticOrLogicalOperator::MULTIPLY:
1443 return true;
1444 default:
1445 return false;
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;
1457 switch (op)
1459 case ArithmeticOrLogicalOperator::ADD:
1460 builtin_ctx.lookup_simple_builtin ("add_overflow", &builtin);
1461 break;
1462 case ArithmeticOrLogicalOperator::SUBTRACT:
1463 builtin_ctx.lookup_simple_builtin ("sub_overflow", &builtin);
1464 break;
1465 case ArithmeticOrLogicalOperator::MULTIPLY:
1466 builtin_ctx.lookup_simple_builtin ("mul_overflow", &builtin);
1467 break;
1468 default:
1469 gcc_unreachable ();
1470 break;
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
1479 // that
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
1492 tree
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
1498 expression. */
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;
1526 auto builtin_call
1527 = build_call_expr_loc (loc, builtin, 3, left, right, result_ref);
1528 auto overflow_check
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;
1539 return if_block;
1542 // Return an expression for the comparison operation LEFT OP RIGHT.
1543 tree
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
1548 expression. */
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);
1559 return new_tree;
1562 // Return an expression for the lazy boolean operation LEFT OP RIGHT.
1563 tree
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
1568 expression. */
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
1573 rhs operand. */
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);
1580 return new_tree;
1583 // Return an expression that constructs BTYPE with VALS.
1585 tree
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);
1600 if (is_variant)
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);
1611 tree nested_ctor
1612 = constructor_expression (TREE_TYPE (field), false, vals, -1, location);
1614 constructor_elt empty = {NULL, NULL};
1615 constructor_elt *elt = init->quick_push (empty);
1616 elt->index = field;
1617 elt->value
1618 = this->convert_tree (TREE_TYPE (field), nested_ctor, location);
1619 if (!TREE_CONSTANT (elt->value))
1620 is_constant = false;
1622 else
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);
1646 else
1648 constructor_elt empty = {NULL, NULL};
1649 constructor_elt *elt = init->quick_push (empty);
1650 elt->index = field;
1651 elt->value
1652 = this->convert_tree (TREE_TYPE (field), val, location);
1653 if (!TREE_CONSTANT (elt->value))
1654 is_constant = false;
1657 else
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);
1664 tree val = (*p);
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);
1677 continue;
1680 constructor_elt empty = {NULL, NULL};
1681 constructor_elt *elt = init->quick_push (empty);
1682 elt->index = field;
1683 elt->value
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);
1693 if (is_constant)
1694 TREE_CONSTANT (ret) = 1;
1695 if (sink != NULL_TREE)
1696 ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, type_tree,
1697 sink, ret);
1698 return ret;
1701 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]);
1721 tree val = vals[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);
1733 continue;
1736 if (!TREE_CONSTANT (val))
1737 is_constant = false;
1739 constructor_elt empty = {NULL, NULL};
1740 constructor_elt *elt = init->quick_push (empty);
1741 elt->index = index;
1742 elt->value = val;
1745 tree ret = build_constructor (type_tree, init);
1746 if (is_constant)
1747 TREE_CONSTANT (ret) = 1;
1748 if (sink != NULL_TREE)
1749 ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR, type_tree,
1750 sink, ret);
1751 return ret;
1754 // Build insns to create an array, initialize all elements of the array to
1755 // value, and return it
1756 tree
1757 Gcc_backend::array_initializer (tree fndecl, tree block, tree array_type,
1758 tree length, tree value, tree *tmp,
1759 Location locus)
1761 std::vector<tree> stmts;
1763 // Temporary array we initialize with the desired value.
1764 tree t = NULL_TREE;
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));
1778 tree ptr_init
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)),
1793 locus);
1795 t = this->exit_expression (t, locus);
1796 loop_stmts.push_back (t);
1798 // Assign value to the current pointer position
1799 // *ptr = value;
1800 t = this->assignment_statement (build_fold_indirect_ref (ptr), value, locus);
1801 loop_stmts.push_back (t);
1803 // Move pointer to next element
1804 // ptr++;
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.
1810 // length--;
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
1820 // initializes it.
1821 *tmp = tmp_array->get_tree (locus);
1822 return this->statement_list (stmts);
1825 // Return an expression representing ARRAY[INDEX]
1827 tree
1828 Gcc_backend::array_index_expression (tree array_tree, tree index_tree,
1829 Location location)
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.
1838 tree ret;
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);
1843 else
1844 ret = fold_build2_loc (location.gcc_location (), COMPOUND_EXPR,
1845 void_type_node, array_tree, index_tree);
1847 return ret;
1850 // Create an expression for a call to FN_EXPR with FN_ARGS.
1851 tree
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);
1868 tree fndecl = fn;
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)
1885 tree excess_fndecl
1886 = mathfn_built_in (excess_type, DECL_FUNCTION_CODE (fndecl));
1887 if (excess_fndecl == NULL_TREE)
1888 excess_type = NULL_TREE;
1889 else
1891 fn = build_fold_addr_expr_loc (location.gcc_location (),
1892 excess_fndecl);
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]);
1903 tree ret
1904 = build_call_array_loc (location.gcc_location (),
1905 excess_type != NULL_TREE ? excess_type : rettype,
1906 fn, nargs, args);
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);
1916 if (chain_expr)
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);
1926 delete[] args;
1927 return ret;
1930 // Variable initialization.
1932 tree
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);
1959 return ret;
1962 // Assignment.
1964 tree
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
1975 // anything anyhow.
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,
1985 lhs, rhs);
1988 // Return.
1990 tree
1991 Gcc_backend::return_statement (tree fntree, const std::vector<tree> &vals,
1992 Location location)
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++)
2010 tree val = (*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);
2018 return stmt_list;
2021 tree ret;
2022 if (vals.empty ())
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);
2035 else
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
2040 // statement.
2041 tree stmt_list = NULL_TREE;
2042 tree rettype = TREE_TYPE (result);
2044 if (DECL_STRUCT_FUNCTION (fntree) == NULL)
2045 push_struct_function (fntree);
2046 else
2047 push_cfun (DECL_STRUCT_FUNCTION (fntree));
2048 tree rettmp = create_tmp_var (rettype, "RESULT");
2049 pop_cfun ();
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);
2056 tree ref
2057 = fold_build3_loc (location.gcc_location (), COMPONENT_REF,
2058 TREE_TYPE (field), rettmp, field, NULL_TREE);
2059 tree val = (*p);
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);
2072 ret = stmt_list;
2074 return ret;
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; }
2083 tree
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);
2099 return try_stmt;
2102 // If.
2104 tree
2105 Gcc_backend::if_statement (tree, tree cond_tree, tree then_tree, tree else_tree,
2106 Location location)
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);
2113 return ret;
2116 // Loops
2118 tree
2119 Gcc_backend::loop_expression (tree body, Location locus)
2121 return fold_build1_loc (locus.gcc_location (), LOOP_EXPR, void_type_node,
2122 body);
2125 tree
2126 Gcc_backend::exit_expression (tree cond_tree, Location locus)
2128 return fold_build1_loc (locus.gcc_location (), EXIT_EXPR, void_type_node,
2129 cond_tree);
2132 // Pair of statements.
2134 tree
2135 Gcc_backend::compound_statement (tree s1, tree s2)
2137 tree stmt_list = NULL_TREE;
2138 tree t = s1;
2139 if (t == error_mark_node)
2140 return error_mark_node;
2141 append_to_statement_list (t, &stmt_list);
2142 t = s2;
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
2148 // at this point.
2149 if (stmt_list == NULL_TREE)
2150 stmt_list = integer_zero_node;
2152 return stmt_list;
2155 // List of statements.
2157 tree
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)
2164 tree t = (*p);
2165 if (t == error_mark_node)
2166 return error_mark_node;
2167 append_to_statement_list (t, &stmt_list);
2169 return 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
2175 // the Bblock.
2177 tree
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;
2194 else
2196 tree superblock_tree = DECL_INITIAL (fndecl);
2197 BLOCK_SUPERCONTEXT (block_tree) = superblock_tree;
2198 tree *pp;
2199 for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE;
2200 pp = &BLOCK_CHAIN (*pp))
2202 *pp = block_tree;
2205 else
2207 tree superblock_tree = BIND_EXPR_BLOCK (enclosing);
2208 gcc_assert (TREE_CODE (superblock_tree) == BLOCK);
2210 BLOCK_SUPERCONTEXT (block_tree) = superblock_tree;
2211 tree *pp;
2212 for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE;
2213 pp = &BLOCK_CHAIN (*pp))
2215 *pp = block_tree;
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);
2226 *pp = NULL_TREE;
2228 TREE_USED (block_tree) = 1;
2230 tree bind_tree
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;
2234 return bind_tree;
2237 // Add statements to a block.
2239 void
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)
2247 tree s = (*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.
2261 tree
2262 Gcc_backend::non_zero_size_type (tree type)
2264 if (int_size_in_bytes (type) != 0)
2265 return type;
2267 switch (TREE_CODE (type))
2269 case RECORD_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;
2284 *pp = f;
2285 pp = &DECL_CHAIN (f);
2287 TYPE_FIELDS (ns) = field_trees;
2288 layout_type (ns);
2289 return ns;
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;
2299 layout_type (type);
2300 rust_non_zero_struct = type;
2302 return rust_non_zero_struct;
2304 case ARRAY_TYPE: {
2305 tree element_type = non_zero_size_type (TREE_TYPE (type));
2306 return build_array_type_nelts (element_type, 1);
2309 default:
2310 gcc_unreachable ();
2313 gcc_unreachable ();
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.
2320 tree
2321 Gcc_backend::convert_tree (tree type_tree, tree expr_tree, Location location)
2323 if (type_tree == TREE_TYPE (expr_tree))
2324 return 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,
2342 expr_tree);
2343 return fold_build1_loc (location.gcc_location (), VIEW_CONVERT_EXPR,
2344 type_tree, expr_tree);
2347 gcc_unreachable ();
2350 // Make a global variable.
2352 Bvariable *
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);
2368 if (is_external)
2369 DECL_EXTERNAL (decl) = 1;
2370 else
2371 TREE_STATIC (decl) = 1;
2372 if (!is_hidden)
2374 TREE_PUBLIC (decl) = 1;
2375 SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
2377 else
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.
2394 void
2395 Gcc_backend::global_variable_set_init (Bvariable *var, tree expr_tree)
2397 if (expr_tree == error_mark_node)
2398 return;
2399 gcc_assert (TREE_CONSTANT (expr_tree));
2400 tree var_decl = var->get_decl ();
2401 if (var_decl == error_mark_node)
2402 return;
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.
2418 Bvariable *
2419 Gcc_backend::local_variable (tree function, const std::string &name,
2420 tree type_tree, Bvariable *decl_var,
2421 Location location)
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.
2440 Bvariable *
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.
2457 Bvariable *
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);
2473 if (f == NULL)
2475 push_struct_function (fndecl);
2476 pop_cfun ();
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.
2489 Bvariable *
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 ();
2502 tree var;
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);
2508 else
2509 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
2511 var = create_tmp_var (type_tree, "RUSTTMP");
2512 pop_cfun ();
2514 else
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;
2540 *pstatement
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);
2553 // Make a label.
2555 tree
2556 Gcc_backend::label (tree func_tree, const std::string &name, Location location)
2558 tree decl;
2559 if (name.empty ())
2561 if (DECL_STRUCT_FUNCTION (func_tree) == NULL)
2562 push_struct_function (func_tree);
2563 else
2564 push_cfun (DECL_STRUCT_FUNCTION (func_tree));
2566 decl = create_artificial_label (location.gcc_location ());
2568 pop_cfun ();
2570 else
2572 tree id = get_identifier_from_string (name);
2573 decl
2574 = build_decl (location.gcc_location (), LABEL_DECL, id, void_type_node);
2575 DECL_CONTEXT (decl) = func_tree;
2577 return decl;
2580 // Make a statement which defines a label.
2582 tree
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.
2591 tree
2592 Gcc_backend::goto_statement (tree label, Location location)
2594 return fold_build1_loc (location.gcc_location (), GOTO_EXPR, void_type_node,
2595 label);
2598 // Get the address of a label.
2600 tree
2601 Gcc_backend::label_address (tree label, Location location)
2603 TREE_USED (label) = 1;
2604 TREE_ADDRESSABLE (label) = 1;
2605 tree ret
2606 = fold_convert_loc (location.gcc_location (), ptr_type_node,
2607 build_fold_addr_expr_loc (location.gcc_location (),
2608 label));
2609 return ret;
2612 // Declare or define a new function.
2614 tree
2615 Gcc_backend::function (tree functype, const std::string &name,
2616 const std::string &asm_name, unsigned int flags,
2617 Location location)
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;
2628 tree decl
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;
2635 else
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);
2653 return decl;
2656 // Create a statement that runs all deferred calls for FUNCTION. This should
2657 // be a statement that looks like this in C++:
2658 // finish:
2659 // try { UNDEFER; } catch { CHECK_DEFER; goto finish; }
2661 tree
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);
2671 else
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);
2680 tree catch_body
2681 = build2 (COMPOUND_EXPR, void_type_node, defer_tree, jump_stmt);
2682 catch_body = build2 (CATCH_EXPR, void_type_node, NULL, catch_body);
2683 tree try_catch
2684 = build2 (TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
2685 append_to_statement_list (try_catch, &stmt_list);
2686 pop_cfun ();
2688 return 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.
2694 bool
2695 Gcc_backend::function_set_parameters (
2696 tree function, const std::vector<Bvariable *> &param_vars)
2698 if (function == error_mark_node)
2699 return false;
2701 tree params = NULL_TREE;
2702 tree *pp = &params;
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);
2710 *pp = NULL_TREE;
2711 DECL_ARGUMENTS (function) = params;
2712 return true;
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.
2719 void
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.
2731 size_t i = 0;
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)
2738 defs[i] = v;
2739 rust_preserve_from_gc (defs[i]);
2740 ++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]);
2753 ++i;
2756 for (std::vector<tree>::const_iterator p = constant_decls.begin ();
2757 p != constant_decls.end (); ++p)
2759 if ((*p) != error_mark_node)
2761 defs[i] = (*p);
2762 rust_preserve_from_gc (defs[i]);
2763 ++i;
2766 for (std::vector<tree>::const_iterator p = function_decls.begin ();
2767 p != function_decls.end (); ++p)
2769 tree decl = (*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);
2778 defs[i] = decl;
2779 ++i;
2783 // Pass everything back to the middle-end.
2785 wrapup_global_declarations (defs, i);
2787 delete[] defs;
2790 void
2791 Gcc_backend::write_export_data (const char *bytes, unsigned int size)
2793 rust_write_export_data (bytes, size);
2796 // Return the backend generator.
2798 Backend *
2799 rust_get_backend ()
2801 return new Gcc_backend ();