Line data Source code
1 : // rust-gcc.cc -- Rust frontend to gcc IR.
2 : // Copyright (C) 2011-2026 Free Software Foundation, Inc.
3 : // Contributed by Ian Lance Taylor, Google.
4 : // forked from gccgo
5 :
6 : // This file is part of GCC.
7 :
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.
12 :
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.
17 :
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/>.
21 :
22 : #include "rust-system.h"
23 :
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>
27 :
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"
48 :
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"
54 :
55 : #include "backend/rust-tree.h"
56 : #include "backend/rust-builtins.h"
57 :
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 86149 : Bvariable::get_tree (location_t location) const
63 : {
64 86149 : if (error_operand_p (this->t_))
65 0 : return error_mark_node;
66 :
67 86149 : TREE_USED (this->t_) = 1;
68 86149 : if (this->orig_type_ == NULL || TREE_TYPE (this->t_) == this->orig_type_)
69 : {
70 86144 : return this->t_;
71 : }
72 :
73 : // Return *(orig_type*)&decl. */
74 5 : tree t = build_fold_addr_expr_loc (location, this->t_);
75 5 : t = fold_build1_loc (location, NOP_EXPR,
76 5 : build_pointer_type (this->orig_type_), t);
77 5 : return build_fold_indirect_ref_loc (location, t);
78 : }
79 :
80 : Bvariable *
81 11663 : Bvariable::error_variable ()
82 : {
83 11663 : return new Bvariable (error_mark_node);
84 : }
85 :
86 : // Get the tree of a variable for use as an expression
87 : tree
88 0 : LocalVariable::get_tree (location_t location) const
89 : {
90 0 : if (error_operand_p (t))
91 0 : return error_mark_node;
92 :
93 0 : TREE_USED (t) = 1;
94 0 : return t;
95 : }
96 :
97 : LocalVariable
98 6 : LocalVariable::error_variable ()
99 : {
100 6 : return LocalVariable (error_mark_node);
101 : }
102 :
103 : // This file implements the interface between the Rust frontend proper
104 : // and the gcc IR. This implements specific instantiations of
105 : // abstract classes defined by the Rust frontend proper. The Rust
106 : // frontend proper class methods of these classes to generate the
107 : // backend representation.
108 :
109 : // A helper function to create a GCC identifier from a C++ string.
110 :
111 : namespace Backend {
112 :
113 : // Define the built-in functions that are exposed to GCCRust.
114 :
115 : void
116 5117 : init ()
117 : {
118 : /* We need to define the fetch_and_add functions, since we use them
119 : for ++ and --. */
120 : // tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree ();
121 : // tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
122 : // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1,
123 : // "__sync_fetch_and_add_1",
124 : // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
125 :
126 : // t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree ();
127 : // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
128 : // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2,
129 : // "__sync_fetch_and_add_2",
130 : // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
131 :
132 : // t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree ();
133 : // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
134 : // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4,
135 : // "__sync_fetch_and_add_4",
136 : // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
137 :
138 : // t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree ();
139 : // p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE));
140 : // this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8,
141 : // "__sync_fetch_and_add_8",
142 : // NULL, build_function_type_list (t, p, t, NULL_TREE), 0);
143 :
144 : // // We use __builtin_expect for magic import functions.
145 : // this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL,
146 : // build_function_type_list (long_integer_type_node,
147 : // long_integer_type_node,
148 : // long_integer_type_node,
149 : // NULL_TREE),
150 : // builtin_const);
151 :
152 : // // We use __builtin_memcmp for struct comparisons.
153 : // this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp",
154 : // build_function_type_list (integer_type_node,
155 : // const_ptr_type_node,
156 : // const_ptr_type_node,
157 : // size_type_node, NULL_TREE),
158 : // 0);
159 :
160 : // // We use __builtin_memmove for copying data.
161 : // this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove",
162 : // build_function_type_list (void_type_node, ptr_type_node,
163 : // const_ptr_type_node,
164 : // size_type_node, NULL_TREE),
165 : // 0);
166 :
167 : // // We use __builtin_memset for zeroing data.
168 : // this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset",
169 : // build_function_type_list (void_type_node, ptr_type_node,
170 : // integer_type_node,
171 : // size_type_node, NULL_TREE),
172 : // 0);
173 :
174 : // // Used by runtime/internal/sys and math/bits.
175 : // this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz",
176 : // build_function_type_list (integer_type_node,
177 : // unsigned_type_node,
178 : // NULL_TREE),
179 : // builtin_const);
180 : // this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll",
181 : // build_function_type_list (integer_type_node,
182 : // long_long_unsigned_type_node,
183 : // NULL_TREE),
184 : // builtin_const);
185 : // this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz",
186 : // build_function_type_list (integer_type_node,
187 : // unsigned_type_node,
188 : // NULL_TREE),
189 : // builtin_const);
190 : // this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
191 : // build_function_type_list (integer_type_node,
192 : // long_long_unsigned_type_node,
193 : // NULL_TREE),
194 : // builtin_const);
195 : // this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
196 : // build_function_type_list (integer_type_node,
197 : // unsigned_type_node,
198 : // NULL_TREE),
199 : // builtin_const);
200 : // this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll",
201 : // "popcountll",
202 : // build_function_type_list (integer_type_node,
203 : // long_long_unsigned_type_node,
204 : // NULL_TREE),
205 : // builtin_const);
206 : // this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
207 : // build_function_type_list (uint16_type_node,
208 : // uint16_type_node, NULL_TREE),
209 : // builtin_const);
210 : // this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
211 : // build_function_type_list (uint32_type_node,
212 : // uint32_type_node, NULL_TREE),
213 : // builtin_const);
214 : // this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64",
215 : // build_function_type_list (uint64_type_node,
216 : // uint64_type_node, NULL_TREE),
217 : // builtin_const);
218 :
219 : // We provide some functions for the math library.
220 :
221 : // We use __builtin_return_address in the thunk we build for
222 : // functions which call recover, and for runtime.getcallerpc.
223 : // t = build_function_type_list (ptr_type_node, unsigned_type_node,
224 : // NULL_TREE); this->define_builtin (BUILT_IN_RETURN_ADDRESS,
225 : // "__builtin_return_address",
226 : // NULL, t, 0);
227 :
228 : // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp.
229 : // t = build_function_type_list (ptr_type_node, NULL_TREE);
230 : // this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t,
231 : // 0);
232 :
233 : // The runtime calls __builtin_extract_return_addr when recording
234 : // the address to which a function returns.
235 : // this->define_builtin (
236 : // BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL,
237 : // build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0);
238 :
239 : // The compiler uses __builtin_trap for some exception handling
240 : // cases.
241 : // this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL,
242 : // build_function_type (void_type_node, void_list_node),
243 : // builtin_noreturn);
244 :
245 : // The runtime uses __builtin_prefetch.
246 : // this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL,
247 : // build_varargs_function_type_list (void_type_node,
248 : // const_ptr_type_node,
249 : // NULL_TREE),
250 : // builtin_novops);
251 :
252 : // The compiler uses __builtin_unreachable for cases that cannot
253 : // occur.
254 : // this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
255 : // build_function_type (void_type_node, void_list_node),
256 : // builtin_const | builtin_noreturn);
257 :
258 : // We provide some atomic functions.
259 : // t = build_function_type_list (uint32_type_node, ptr_type_node,
260 : // integer_type_node, NULL_TREE);
261 : // this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t,
262 : // 0);
263 :
264 : // t = build_function_type_list (uint64_type_node, ptr_type_node,
265 : // integer_type_node, NULL_TREE);
266 : // this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t,
267 : // 0);
268 :
269 : // t = build_function_type_list (void_type_node, ptr_type_node,
270 : // uint32_type_node,
271 : // integer_type_node, NULL_TREE);
272 : // this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t,
273 : // 0);
274 :
275 : // t = build_function_type_list (void_type_node, ptr_type_node,
276 : // uint64_type_node,
277 : // integer_type_node, NULL_TREE);
278 : // this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t,
279 : // 0);
280 :
281 : // t = build_function_type_list (uint32_type_node, ptr_type_node,
282 : // uint32_type_node, integer_type_node, NULL_TREE);
283 : // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4",
284 : // NULL,
285 : // t, 0);
286 :
287 : // t = build_function_type_list (uint64_type_node, ptr_type_node,
288 : // uint64_type_node, integer_type_node, NULL_TREE);
289 : // this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8",
290 : // NULL,
291 : // t, 0);
292 :
293 : // t = build_function_type_list (boolean_type_node, ptr_type_node,
294 : // ptr_type_node,
295 : // uint32_type_node, boolean_type_node,
296 : // integer_type_node, integer_type_node,
297 : // NULL_TREE);
298 : // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
299 : // "__atomic_compare_exchange_4", NULL, t, 0);
300 :
301 : // t = build_function_type_list (boolean_type_node, ptr_type_node,
302 : // ptr_type_node,
303 : // uint64_type_node, boolean_type_node,
304 : // integer_type_node, integer_type_node,
305 : // NULL_TREE);
306 : // this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
307 : // "__atomic_compare_exchange_8", NULL, t, 0);
308 :
309 : // t = build_function_type_list (uint32_type_node, ptr_type_node,
310 : // uint32_type_node, integer_type_node, NULL_TREE);
311 : // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
312 : // NULL, t, 0);
313 :
314 : // t = build_function_type_list (uint64_type_node, ptr_type_node,
315 : // uint64_type_node, integer_type_node, NULL_TREE);
316 : // this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
317 : // NULL, t, 0);
318 :
319 : // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
320 : // unsigned_char_type_node, integer_type_node,
321 : // NULL_TREE);
322 : // this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
323 : // NULL, t, 0);
324 : // this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1",
325 : // NULL, t, 0);
326 :
327 : // t = build_function_type_list (unsigned_char_type_node, ptr_type_node,
328 : // unsigned_char_type_node, integer_type_node,
329 : // NULL_TREE);
330 : // this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
331 : // NULL,
332 : // t, 0);
333 : // this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1",
334 : // NULL,
335 : // t, 0);
336 :
337 : // eagerly initialize BuiltinsContext
338 5117 : (void) Rust::Compile::BuiltinsContext::get ();
339 5117 : }
340 :
341 : void
342 0 : debug (tree t)
343 : {
344 0 : debug_tree (t);
345 0 : };
346 :
347 : void
348 0 : debug (Bvariable *t)
349 : {
350 0 : debug_tree (t->get_decl ());
351 0 : };
352 :
353 : tree
354 13015 : get_identifier_node (const std::string &str)
355 : {
356 13015 : return get_identifier_with_length (str.data (), str.length ());
357 : }
358 :
359 : tree
360 5876 : wchar_type ()
361 : {
362 5876 : static tree wchar;
363 :
364 5876 : if (wchar == NULL_TREE)
365 : {
366 4707 : wchar = make_unsigned_type (32);
367 4707 : TYPE_STRING_FLAG (wchar) = 1;
368 : }
369 :
370 5876 : return wchar;
371 : }
372 :
373 : // Get an unnamed integer type.
374 :
375 : int
376 57744 : get_pointer_size ()
377 : {
378 57744 : return POINTER_SIZE;
379 : }
380 :
381 : tree
382 0 : raw_str_type ()
383 : {
384 0 : tree char_ptr = build_pointer_type (char_type_node);
385 0 : tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
386 0 : return const_char_type;
387 : }
388 :
389 : tree
390 199618 : integer_type (bool is_unsigned, int bits)
391 : {
392 199618 : tree type;
393 199618 : if (is_unsigned)
394 : {
395 100007 : if (bits == INT_TYPE_SIZE)
396 14867 : type = unsigned_type_node;
397 85140 : else if (bits == SHORT_TYPE_SIZE)
398 9932 : type = short_unsigned_type_node;
399 75208 : else if (bits == LONG_TYPE_SIZE)
400 53461 : type = long_unsigned_type_node;
401 21747 : else if (bits == LONG_LONG_TYPE_SIZE)
402 0 : type = long_long_unsigned_type_node;
403 : else
404 21747 : type = make_unsigned_type (bits);
405 : }
406 : else
407 : {
408 99611 : if (bits == INT_TYPE_SIZE)
409 52203 : type = integer_type_node;
410 47408 : else if (bits == SHORT_TYPE_SIZE)
411 5894 : type = short_integer_type_node;
412 41514 : else if (bits == LONG_TYPE_SIZE)
413 25579 : type = long_integer_type_node;
414 15935 : else if (bits == LONG_LONG_TYPE_SIZE)
415 0 : type = long_long_integer_type_node;
416 : else
417 15935 : type = make_signed_type (bits);
418 : }
419 199618 : return type;
420 : }
421 :
422 : // Get an unnamed float type.
423 :
424 : tree
425 15575 : float_type (int bits)
426 : {
427 15575 : tree type;
428 15575 : if (bits == TYPE_PRECISION (float_type_node))
429 : type = float_type_node;
430 7996 : else if (bits == TYPE_PRECISION (double_type_node))
431 : type = double_type_node;
432 0 : else if (bits == TYPE_PRECISION (long_double_type_node))
433 : type = long_double_type_node;
434 : else
435 : {
436 0 : type = make_node (REAL_TYPE);
437 0 : TYPE_PRECISION (type) = bits;
438 0 : layout_type (type);
439 : }
440 15575 : return type;
441 : }
442 :
443 : // Get a pointer type.
444 :
445 : tree
446 8151 : pointer_type (tree to_type)
447 : {
448 8151 : if (error_operand_p (to_type))
449 0 : return error_mark_node;
450 8151 : tree type = build_pointer_type_for_mode (to_type, VOIDmode, true);
451 8151 : return type;
452 : }
453 :
454 : // Get a reference type.
455 :
456 : tree
457 14080 : reference_type (tree to_type)
458 : {
459 14080 : if (error_operand_p (to_type))
460 0 : return error_mark_node;
461 14080 : tree type = build_reference_type (to_type);
462 14080 : return type;
463 : }
464 :
465 : // Get immutable type
466 :
467 : tree
468 48344 : immutable_type (tree base)
469 : {
470 48344 : if (error_operand_p (base))
471 0 : return error_mark_node;
472 48344 : tree constified = build_qualified_type (base, TYPE_QUAL_CONST);
473 48344 : return constified;
474 : }
475 :
476 : // Make a function type.
477 :
478 : tree
479 20052 : function_type (const typed_identifier &receiver,
480 : const std::vector<typed_identifier> ¶meters,
481 : const std::vector<typed_identifier> &results, tree result_struct,
482 : location_t)
483 : {
484 20052 : tree args = NULL_TREE;
485 20052 : tree *pp = &args;
486 20052 : if (receiver.type != NULL_TREE)
487 : {
488 0 : tree t = receiver.type;
489 0 : if (error_operand_p (t))
490 0 : return error_mark_node;
491 0 : *pp = tree_cons (NULL_TREE, t, NULL_TREE);
492 0 : pp = &TREE_CHAIN (*pp);
493 : }
494 :
495 38522 : for (const auto &p : parameters)
496 : {
497 18470 : tree t = p.type;
498 18470 : if (error_operand_p (t))
499 0 : return error_mark_node;
500 18470 : *pp = tree_cons (NULL_TREE, t, NULL_TREE);
501 18470 : pp = &TREE_CHAIN (*pp);
502 : }
503 :
504 : // Varargs is handled entirely at the Rust level. When converted to
505 : // GENERIC functions are not varargs.
506 20052 : *pp = void_list_node;
507 :
508 20052 : tree result;
509 20052 : if (results.empty ())
510 245 : result = void_type_node;
511 19807 : else if (results.size () == 1)
512 19807 : result = results.front ().type;
513 : else
514 : {
515 0 : gcc_assert (result_struct != NULL);
516 : result = result_struct;
517 : }
518 20052 : if (error_operand_p (result))
519 0 : return error_mark_node;
520 :
521 20052 : tree fntype = build_function_type (result, args);
522 20052 : if (error_operand_p (fntype))
523 0 : return error_mark_node;
524 :
525 20052 : return build_pointer_type (fntype);
526 : }
527 :
528 : tree
529 883 : function_type_variadic (const typed_identifier &receiver,
530 : const std::vector<typed_identifier> ¶meters,
531 : const std::vector<typed_identifier> &results,
532 : tree result_struct, location_t)
533 : {
534 883 : size_t n = parameters.size () + (receiver.type != NULL_TREE ? 1 : 0);
535 883 : tree *args = XALLOCAVEC (tree, n);
536 883 : size_t offs = 0;
537 883 : if (error_operand_p (receiver.type))
538 0 : return error_mark_node;
539 :
540 883 : if (receiver.type != NULL_TREE)
541 0 : args[offs++] = receiver.type;
542 :
543 1766 : for (const auto &p : parameters)
544 : {
545 883 : tree t = p.type;
546 883 : if (error_operand_p (t))
547 0 : return error_mark_node;
548 883 : args[offs++] = t;
549 : }
550 :
551 883 : tree result;
552 883 : if (results.empty ())
553 855 : result = void_type_node;
554 28 : else if (results.size () == 1)
555 28 : result = results.front ().type;
556 : else
557 : {
558 0 : gcc_assert (result_struct != NULL_TREE);
559 : result = result_struct;
560 : }
561 883 : if (error_operand_p (result))
562 0 : return error_mark_node;
563 :
564 883 : tree fntype = build_varargs_function_type_array (result, n, args);
565 883 : if (error_operand_p (fntype))
566 0 : return error_mark_node;
567 :
568 883 : return build_pointer_type (fntype);
569 : }
570 :
571 : tree
572 110 : function_ptr_type (tree result_type, const std::vector<tree> ¶meters,
573 : location_t /* locus */)
574 : {
575 110 : tree args = NULL_TREE;
576 110 : tree *pp = &args;
577 :
578 200 : for (auto ¶m : parameters)
579 : {
580 90 : if (error_operand_p (param))
581 0 : return error_mark_node;
582 :
583 90 : *pp = tree_cons (NULL_TREE, param, NULL_TREE);
584 90 : pp = &TREE_CHAIN (*pp);
585 : }
586 :
587 110 : *pp = void_list_node;
588 :
589 110 : tree result = result_type;
590 110 : if (result != void_type_node && int_size_in_bytes (result) == 0)
591 64 : result = void_type_node;
592 :
593 110 : tree fntype = build_function_type (result, args);
594 110 : if (error_operand_p (fntype))
595 0 : return error_mark_node;
596 :
597 110 : return build_pointer_type (fntype);
598 : }
599 :
600 : // Make a struct type.
601 :
602 : tree
603 60462 : struct_type (const std::vector<typed_identifier> &fields, bool layout)
604 : {
605 60462 : return fill_in_fields (make_node (RECORD_TYPE), fields, layout);
606 : }
607 :
608 : // Make a union type.
609 :
610 : tree
611 6963 : union_type (const std::vector<typed_identifier> &fields, bool layout)
612 : {
613 6963 : return fill_in_fields (make_node (UNION_TYPE), fields, layout);
614 : }
615 :
616 : // Fill in the fields of a struct or union type.
617 :
618 : tree
619 67425 : fill_in_fields (tree fill, const std::vector<typed_identifier> &fields,
620 : bool layout)
621 : {
622 67425 : tree field_trees = NULL_TREE;
623 67425 : tree *pp = &field_trees;
624 167213 : for (const auto &p : fields)
625 : {
626 99791 : tree name_tree = p.name.as_tree ();
627 99791 : tree type_tree = p.type;
628 99791 : if (error_operand_p (type_tree))
629 3 : return error_mark_node;
630 99788 : tree field = build_decl (p.location, FIELD_DECL, name_tree, type_tree);
631 99788 : DECL_CONTEXT (field) = fill;
632 99788 : *pp = field;
633 99788 : pp = &DECL_CHAIN (field);
634 : }
635 67422 : TYPE_FIELDS (fill) = field_trees;
636 :
637 67422 : if (layout)
638 38577 : layout_type (fill);
639 :
640 : // Because Rust permits converting between named struct types and
641 : // equivalent struct types, for which we use VIEW_CONVERT_EXPR, and
642 : // because we don't try to maintain TYPE_CANONICAL for struct types,
643 : // we need to tell the middle-end to use structural equality.
644 67422 : SET_TYPE_STRUCTURAL_EQUALITY (fill);
645 :
646 67422 : return fill;
647 : }
648 :
649 : // Make an array type.
650 :
651 : tree
652 0 : array_type (tree element_type, tree length)
653 : {
654 0 : return fill_in_array (make_node (ARRAY_TYPE), element_type, length);
655 : }
656 :
657 : // Fill in an array type.
658 :
659 : tree
660 0 : fill_in_array (tree fill, tree element_type, tree length_tree)
661 : {
662 0 : if (error_operand_p (element_type) || error_operand_p (length_tree))
663 0 : return error_mark_node;
664 :
665 0 : gcc_assert (TYPE_SIZE (element_type) != NULL_TREE);
666 :
667 0 : length_tree = fold_convert (sizetype, length_tree);
668 :
669 : // build_index_type takes the maximum index, which is one less than
670 : // the length.
671 0 : tree index_type_tree = build_index_type (
672 : fold_build2 (MINUS_EXPR, sizetype, length_tree, size_one_node));
673 :
674 0 : TREE_TYPE (fill) = element_type;
675 0 : TYPE_DOMAIN (fill) = index_type_tree;
676 0 : TYPE_ADDR_SPACE (fill) = TYPE_ADDR_SPACE (element_type);
677 0 : layout_type (fill);
678 :
679 0 : if (TYPE_STRUCTURAL_EQUALITY_P (element_type))
680 0 : SET_TYPE_STRUCTURAL_EQUALITY (fill);
681 0 : else if (TYPE_CANONICAL (element_type) != element_type
682 0 : || TYPE_CANONICAL (index_type_tree) != index_type_tree)
683 0 : TYPE_CANONICAL (fill) = build_array_type (TYPE_CANONICAL (element_type),
684 0 : TYPE_CANONICAL (index_type_tree));
685 :
686 : return fill;
687 : }
688 :
689 : // Return a named version of a type.
690 :
691 : tree
692 298682 : named_type (GGC::Ident name, tree type, location_t location)
693 : {
694 298682 : if (error_operand_p (type))
695 3 : return error_mark_node;
696 :
697 : // The middle-end expects a basic type to have a name. In Rust every
698 : // basic type will have a name. The first time we see a basic type,
699 : // give it whatever Rust name we have at this point.
700 450118 : if (TYPE_NAME (type) == NULL_TREE && location == BUILTINS_LOCATION
701 395003 : && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE
702 : || TREE_CODE (type) == COMPLEX_TYPE
703 : || TREE_CODE (type) == BOOLEAN_TYPE))
704 : {
705 84752 : tree decl
706 84752 : = build_decl (BUILTINS_LOCATION, TYPE_DECL, name.as_tree (), type);
707 84752 : TYPE_NAME (type) = decl;
708 84752 : return type;
709 : }
710 :
711 213927 : tree copy = build_variant_type_copy (type);
712 213927 : tree decl = build_decl (location, TYPE_DECL, name.as_tree (), copy);
713 213927 : DECL_ORIGINAL_TYPE (decl) = type;
714 213927 : TYPE_NAME (copy) = decl;
715 213927 : return copy;
716 : }
717 :
718 : // Return the size of a type.
719 :
720 : int64_t
721 40013 : type_size (tree t)
722 : {
723 40013 : if (error_operand_p (t))
724 : return 1;
725 40013 : if (t == void_type_node)
726 : return 0;
727 40013 : t = TYPE_SIZE_UNIT (t);
728 40013 : gcc_assert (tree_fits_uhwi_p (t));
729 40013 : unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW (t);
730 40013 : int64_t ret = static_cast<int64_t> (val_wide);
731 40013 : if (ret < 0 || static_cast<unsigned HOST_WIDE_INT> (ret) != val_wide)
732 : return -1;
733 : return ret;
734 : }
735 :
736 : // Return the alignment of a type.
737 :
738 : int64_t
739 0 : type_alignment (tree t)
740 : {
741 0 : if (error_operand_p (t))
742 : return 1;
743 0 : return TYPE_ALIGN_UNIT (t);
744 : }
745 :
746 : // Return the alignment of a struct field of type BTYPE.
747 :
748 : int64_t
749 0 : type_field_alignment (tree t)
750 : {
751 0 : if (error_operand_p (t))
752 : return 1;
753 0 : return rust_field_alignment (t);
754 : }
755 :
756 : // Return the offset of a field in a struct.
757 :
758 : int64_t
759 0 : type_field_offset (tree struct_tree, size_t index)
760 : {
761 0 : if (error_operand_p (struct_tree))
762 : return 0;
763 0 : gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE);
764 0 : tree field = TYPE_FIELDS (struct_tree);
765 0 : for (; index > 0; --index)
766 : {
767 0 : field = DECL_CHAIN (field);
768 0 : gcc_assert (field != NULL_TREE);
769 : }
770 0 : HOST_WIDE_INT offset_wide = int_byte_position (field);
771 0 : int64_t ret = static_cast<int64_t> (offset_wide);
772 0 : gcc_assert (ret == offset_wide);
773 0 : return ret;
774 : }
775 :
776 : // Return the zero value for a type.
777 :
778 : tree
779 105 : zero_expression (tree t)
780 : {
781 105 : tree ret;
782 105 : if (error_operand_p (t))
783 0 : ret = error_mark_node;
784 : else
785 105 : ret = build_zero_cst (t);
786 105 : return ret;
787 : }
788 :
789 : // An expression that references a variable.
790 :
791 : tree
792 76163 : var_expression (Bvariable *var, location_t location)
793 : {
794 76163 : return var->get_tree (location);
795 : }
796 :
797 : // Return a typed value as a constant floating-point number.
798 :
799 : tree
800 0 : float_constant_expression (tree t, mpfr_t val)
801 : {
802 0 : tree ret;
803 0 : if (error_operand_p (t))
804 0 : return error_mark_node;
805 :
806 0 : REAL_VALUE_TYPE r1;
807 0 : real_from_mpfr (&r1, val, t, GMP_RNDN);
808 0 : REAL_VALUE_TYPE r2;
809 0 : real_convert (&r2, TYPE_MODE (t), &r1);
810 0 : ret = build_real (t, r2);
811 0 : return ret;
812 : }
813 :
814 : // Make a constant string expression.
815 :
816 : tree
817 2421 : string_constant_expression (const std::string &val)
818 : {
819 2421 : tree index_type = build_index_type (size_int (val.length ()));
820 2421 : tree const_char_type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
821 2421 : tree string_type = build_array_type (const_char_type, index_type);
822 2421 : TYPE_STRING_FLAG (string_type) = 1;
823 2421 : tree string_val = build_string (val.length (), val.data ());
824 2421 : TREE_TYPE (string_val) = string_type;
825 :
826 2421 : return string_val;
827 : }
828 :
829 : tree
830 183 : wchar_constant_expression (wchar_t c)
831 : {
832 183 : return build_int_cst (wchar_type (), c);
833 : }
834 :
835 : tree
836 238 : char_constant_expression (char c)
837 : {
838 238 : return build_int_cst (char_type_node, c);
839 : }
840 :
841 : tree
842 340 : size_constant_expression (size_t val)
843 : {
844 340 : return size_int (val);
845 : }
846 :
847 : // Make a constant boolean expression.
848 :
849 : tree
850 4028 : boolean_constant_expression (bool val)
851 : {
852 4028 : return val ? boolean_true_node : boolean_false_node;
853 : }
854 :
855 : // An expression that converts an expression to a different type.
856 :
857 : tree
858 19 : convert_expression (tree type_tree, tree expr_tree, location_t location)
859 : {
860 19 : if (error_operand_p (type_tree) || error_operand_p (expr_tree))
861 0 : return error_mark_node;
862 :
863 19 : tree ret;
864 19 : if (type_size (type_tree) == 0 || TREE_TYPE (expr_tree) == void_type_node)
865 : {
866 : // Do not convert zero-sized types.
867 : ret = expr_tree;
868 : }
869 19 : else if (TREE_CODE (type_tree) == INTEGER_TYPE)
870 14 : ret = convert_to_integer (type_tree, expr_tree);
871 5 : else if (TREE_CODE (type_tree) == REAL_TYPE)
872 0 : ret = convert_to_real (type_tree, expr_tree);
873 5 : else if (TREE_CODE (type_tree) == COMPLEX_TYPE)
874 0 : ret = convert_to_complex (type_tree, expr_tree);
875 5 : else if (TREE_CODE (type_tree) == POINTER_TYPE
876 5 : && TREE_CODE (TREE_TYPE (expr_tree)) == INTEGER_TYPE)
877 0 : ret = convert_to_pointer (type_tree, expr_tree);
878 5 : else if (TREE_CODE (type_tree) == RECORD_TYPE
879 5 : || TREE_CODE (type_tree) == ARRAY_TYPE)
880 0 : ret = fold_build1_loc (location, VIEW_CONVERT_EXPR, type_tree, expr_tree);
881 : else
882 5 : ret = fold_convert_loc (location, type_tree, expr_tree);
883 :
884 : return ret;
885 : }
886 :
887 : // Return an expression for the field at INDEX in BSTRUCT.
888 :
889 : tree
890 18057 : struct_field_expression (tree struct_tree, size_t index, location_t location)
891 : {
892 18057 : if (error_operand_p (struct_tree))
893 0 : return error_mark_node;
894 :
895 18057 : if (VECTOR_TYPE_P (TREE_TYPE (struct_tree)))
896 : {
897 3 : tree vec_type = TREE_TYPE (struct_tree);
898 3 : tree element_type = TREE_TYPE (vec_type);
899 3 : tree part_width = TYPE_SIZE (element_type);
900 3 : tree bit_offset = bitsize_int (index * tree_to_uhwi (part_width));
901 :
902 3 : return fold_build3_loc (location, BIT_FIELD_REF, element_type,
903 3 : struct_tree, part_width, bit_offset);
904 : }
905 :
906 18054 : gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE
907 : || TREE_CODE (TREE_TYPE (struct_tree)) == UNION_TYPE);
908 18054 : tree field = TYPE_FIELDS (TREE_TYPE (struct_tree));
909 18054 : if (field == NULL_TREE)
910 : {
911 : // This can happen for a type which refers to itself indirectly
912 : // and then turns out to be erroneous.
913 0 : return error_mark_node;
914 : }
915 42203 : for (unsigned int i = index; i > 0; --i)
916 : {
917 24149 : field = DECL_CHAIN (field);
918 24149 : gcc_assert (field != NULL_TREE);
919 : }
920 18054 : if (error_operand_p (TREE_TYPE (field)))
921 0 : return error_mark_node;
922 18054 : tree ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (field),
923 : struct_tree, field, NULL_TREE);
924 18054 : if (TREE_CONSTANT (struct_tree))
925 520 : TREE_CONSTANT (ret) = 1;
926 : return ret;
927 : }
928 :
929 : // Return an expression that executes BSTAT before BEXPR.
930 :
931 : tree
932 105 : compound_expression (tree stat, tree expr, location_t location)
933 : {
934 105 : if (error_operand_p (stat) || error_operand_p (expr))
935 0 : return error_mark_node;
936 105 : tree ret
937 105 : = fold_build2_loc (location, COMPOUND_EXPR, TREE_TYPE (expr), stat, expr);
938 105 : return ret;
939 : }
940 :
941 : // Return an expression that executes THEN_EXPR if CONDITION is true, or
942 : // ELSE_EXPR otherwise.
943 :
944 : tree
945 0 : conditional_expression (tree, tree type_tree, tree cond_expr, tree then_expr,
946 : tree else_expr, location_t location)
947 : {
948 0 : if (error_operand_p (type_tree) || error_operand_p (cond_expr)
949 0 : || error_operand_p (then_expr) || error_operand_p (else_expr))
950 0 : return error_mark_node;
951 0 : tree ret = build3_loc (location, COND_EXPR, type_tree, cond_expr, then_expr,
952 : else_expr);
953 0 : return ret;
954 : }
955 :
956 : /* Helper function that converts rust operators to equivalent GCC tree_code.
957 : Note that CompoundAssignmentOperator don't get their corresponding tree_code,
958 : because they get compiled away when we lower AST to HIR. */
959 : static enum tree_code
960 210 : operator_to_tree_code (NegationOperator op)
961 : {
962 210 : switch (op)
963 : {
964 : case NegationOperator::NEGATE:
965 : return NEGATE_EXPR;
966 187 : case NegationOperator::NOT:
967 187 : return BIT_NOT_EXPR;
968 0 : default:
969 0 : rust_unreachable ();
970 : }
971 : }
972 :
973 : /* Note that GCC tree code distinguishes floating point division and integer
974 : division. These two types of division are represented as the same rust
975 : operator, and can only be distinguished via context(i.e. the TREE_TYPE of the
976 : operands). */
977 : static enum tree_code
978 2905 : operator_to_tree_code (ArithmeticOrLogicalOperator op, bool floating_point)
979 : {
980 2905 : switch (op)
981 : {
982 : case ArithmeticOrLogicalOperator::ADD:
983 : return PLUS_EXPR;
984 115 : case ArithmeticOrLogicalOperator::SUBTRACT:
985 115 : return MINUS_EXPR;
986 114 : case ArithmeticOrLogicalOperator::MULTIPLY:
987 114 : return MULT_EXPR;
988 45 : case ArithmeticOrLogicalOperator::DIVIDE:
989 45 : if (floating_point)
990 : return RDIV_EXPR;
991 : else
992 37 : return TRUNC_DIV_EXPR;
993 46 : case ArithmeticOrLogicalOperator::MODULUS:
994 46 : return TRUNC_MOD_EXPR;
995 1546 : case ArithmeticOrLogicalOperator::BITWISE_AND:
996 1546 : return BIT_AND_EXPR;
997 125 : case ArithmeticOrLogicalOperator::BITWISE_OR:
998 125 : return BIT_IOR_EXPR;
999 469 : case ArithmeticOrLogicalOperator::BITWISE_XOR:
1000 469 : return BIT_XOR_EXPR;
1001 71 : case ArithmeticOrLogicalOperator::LEFT_SHIFT:
1002 71 : return LSHIFT_EXPR;
1003 26 : case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
1004 26 : return RSHIFT_EXPR;
1005 0 : default:
1006 0 : rust_unreachable ();
1007 : }
1008 : }
1009 :
1010 : static enum tree_code
1011 4996 : operator_to_tree_code (ComparisonOperator op)
1012 : {
1013 4996 : switch (op)
1014 : {
1015 : case ComparisonOperator::EQUAL:
1016 : return EQ_EXPR;
1017 : case ComparisonOperator::NOT_EQUAL:
1018 : return NE_EXPR;
1019 : case ComparisonOperator::GREATER_THAN:
1020 : return GT_EXPR;
1021 : case ComparisonOperator::LESS_THAN:
1022 : return LT_EXPR;
1023 : case ComparisonOperator::GREATER_OR_EQUAL:
1024 : return GE_EXPR;
1025 : case ComparisonOperator::LESS_OR_EQUAL:
1026 : return LE_EXPR;
1027 0 : default:
1028 0 : rust_unreachable ();
1029 : }
1030 : }
1031 :
1032 : static enum tree_code
1033 417 : operator_to_tree_code (LazyBooleanOperator op)
1034 : {
1035 417 : switch (op)
1036 : {
1037 : case LazyBooleanOperator::LOGICAL_OR:
1038 : return TRUTH_ORIF_EXPR;
1039 339 : case LazyBooleanOperator::LOGICAL_AND:
1040 339 : return TRUTH_ANDIF_EXPR;
1041 0 : default:
1042 0 : rust_unreachable ();
1043 : }
1044 : }
1045 :
1046 : /* Returns true if the type of EXP is a floating point type.
1047 : False otherwise. */
1048 : bool
1049 7151 : is_floating_point (tree exp)
1050 : {
1051 7151 : return FLOAT_TYPE_P (TREE_TYPE (exp));
1052 : }
1053 :
1054 : // Return an expression for the negation operation OP EXPR.
1055 : tree
1056 210 : negation_expression (NegationOperator op, tree expr_tree, location_t location)
1057 : {
1058 : /* Check if the expression is an error, in which case we return an error
1059 : expression. */
1060 210 : if (error_operand_p (expr_tree))
1061 0 : return error_mark_node;
1062 :
1063 : /* For negation operators, the resulting type should be the same as its
1064 : operand. */
1065 210 : auto tree_type = TREE_TYPE (expr_tree);
1066 210 : auto original_type = tree_type;
1067 210 : auto tree_code = operator_to_tree_code (op);
1068 :
1069 : /* For floating point operations we may need to extend the precision of type.
1070 : For example, a 64-bit machine may not support operations on float32. */
1071 210 : bool floating_point = is_floating_point (expr_tree);
1072 210 : auto extended_type = NULL_TREE;
1073 210 : if (floating_point)
1074 : {
1075 0 : extended_type = excess_precision_type (tree_type);
1076 0 : if (extended_type != NULL_TREE)
1077 : {
1078 0 : expr_tree = convert (extended_type, expr_tree);
1079 0 : tree_type = extended_type;
1080 : }
1081 : }
1082 :
1083 : /* Construct a new tree and build an expression from it. */
1084 210 : auto new_tree = fold_build1_loc (location, tree_code, tree_type, expr_tree);
1085 210 : if (floating_point && extended_type != NULL_TREE)
1086 0 : new_tree = convert (original_type, expr_tree);
1087 : return new_tree;
1088 : }
1089 :
1090 : tree
1091 2906 : arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
1092 : tree right, location_t location)
1093 : {
1094 : /* Check if either expression is an error, in which case we return an error
1095 : expression. */
1096 2906 : if (error_operand_p (left) || error_operand_p (right))
1097 1 : return error_mark_node;
1098 :
1099 : // unwrap the const decls if set
1100 2905 : if (TREE_CODE (left) == CONST_DECL)
1101 142 : left = DECL_INITIAL (left);
1102 2905 : if (TREE_CODE (right) == CONST_DECL)
1103 31 : right = DECL_INITIAL (right);
1104 :
1105 : /* We need to determine if we're doing floating point arithmetics of integer
1106 : arithmetics. */
1107 2905 : bool floating_point = is_floating_point (left);
1108 2905 : auto ret = NULL_TREE;
1109 :
1110 : /* For arithmetic or logical operators, the resulting type should be the same
1111 : as the lhs operand. */
1112 2905 : auto tree_type = TREE_TYPE (left);
1113 2905 : auto original_type = tree_type;
1114 2905 : auto tree_code = operator_to_tree_code (op, floating_point);
1115 :
1116 : /* For floating point operations we may need to extend the precision of type.
1117 : For example, a 64-bit machine may not support operations on float32. */
1118 2905 : auto extended_type = NULL_TREE;
1119 2905 : if (floating_point)
1120 : {
1121 236 : extended_type = excess_precision_type (tree_type);
1122 236 : if (extended_type != NULL_TREE)
1123 : {
1124 0 : left = convert (extended_type, left);
1125 0 : right = convert (extended_type, right);
1126 0 : tree_type = extended_type;
1127 : }
1128 : }
1129 :
1130 2905 : ret = fold_build2_loc (location, tree_code, tree_type, left, right);
1131 2905 : TREE_CONSTANT (ret) = TREE_CONSTANT (left) & TREE_CONSTANT (right);
1132 :
1133 : // TODO: How do we handle floating point?
1134 2905 : if (floating_point && extended_type != NULL_TREE)
1135 0 : ret = convert (original_type, ret);
1136 :
1137 2905 : if (op == ArithmeticOrLogicalOperator::DIVIDE
1138 2905 : && (integer_zerop (right) || fixed_zerop (right)))
1139 : {
1140 4 : rust_error_at (location, "division by zero");
1141 : }
1142 2901 : else if (op == ArithmeticOrLogicalOperator::LEFT_SHIFT
1143 71 : && TREE_CODE (right) == INTEGER_CST
1144 2942 : && (compare_tree_int (right, TYPE_PRECISION (TREE_TYPE (ret))) >= 0))
1145 : {
1146 1 : rust_error_at (location, "left shift count >= width of type");
1147 : }
1148 :
1149 : return ret;
1150 : }
1151 :
1152 : static bool
1153 3814 : is_overflowing_expr (ArithmeticOrLogicalOperator op)
1154 : {
1155 3814 : switch (op)
1156 : {
1157 : case ArithmeticOrLogicalOperator::ADD:
1158 : case ArithmeticOrLogicalOperator::SUBTRACT:
1159 : case ArithmeticOrLogicalOperator::MULTIPLY:
1160 : return true;
1161 0 : default:
1162 0 : return false;
1163 : }
1164 : }
1165 :
1166 : static std::pair<tree, tree>
1167 3016 : fetch_overflow_builtins (ArithmeticOrLogicalOperator op)
1168 : {
1169 3016 : auto builtin_ctx = Rust::Compile::BuiltinsContext::get ();
1170 :
1171 3016 : auto builtin = NULL_TREE;
1172 3016 : auto abort = NULL_TREE;
1173 :
1174 3016 : switch (op)
1175 : {
1176 1750 : case ArithmeticOrLogicalOperator::ADD:
1177 1750 : builtin_ctx.lookup_simple_builtin ("__builtin_add_overflow", &builtin);
1178 1750 : break;
1179 1118 : case ArithmeticOrLogicalOperator::SUBTRACT:
1180 1118 : builtin_ctx.lookup_simple_builtin ("__builtin_sub_overflow", &builtin);
1181 1118 : break;
1182 148 : case ArithmeticOrLogicalOperator::MULTIPLY:
1183 148 : builtin_ctx.lookup_simple_builtin ("__builtin_mul_overflow", &builtin);
1184 148 : break;
1185 0 : default:
1186 0 : rust_unreachable ();
1187 3016 : break;
1188 3016 : };
1189 :
1190 3016 : builtin_ctx.lookup_simple_builtin ("__builtin_abort", &abort);
1191 :
1192 3016 : rust_assert (abort);
1193 3016 : rust_assert (builtin);
1194 :
1195 3016 : return {abort, builtin};
1196 3016 : }
1197 :
1198 : // Return an expression for the arithmetic or logical operation LEFT OP RIGHT
1199 : // with overflow checking when possible
1200 : tree
1201 4036 : arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
1202 : tree left, tree right,
1203 : location_t location,
1204 : Bvariable *receiver_var)
1205 : {
1206 : /* Check if either expression is an error, in which case we return an error
1207 : expression. */
1208 4036 : if (error_operand_p (left) || error_operand_p (right))
1209 0 : return error_mark_node;
1210 :
1211 : // FIXME: Add `if (!debug_mode)`
1212 : // No overflow checks for floating point operations or divisions. In that
1213 : // case, simply assign the result of the operation to the receiver variable
1214 4036 : if (is_floating_point (left) || !is_overflowing_expr (op))
1215 1020 : return assignment_statement (
1216 : receiver_var->get_tree (location),
1217 1020 : arithmetic_or_logical_expression (op, left, right, location), location);
1218 :
1219 3016 : auto receiver = receiver_var->get_tree (location);
1220 3016 : TREE_ADDRESSABLE (receiver) = 1;
1221 3016 : auto result_ref = build_fold_addr_expr_loc (location, receiver);
1222 :
1223 3016 : auto builtins = fetch_overflow_builtins (op);
1224 3016 : auto abort = builtins.first;
1225 3016 : auto builtin = builtins.second;
1226 :
1227 3016 : auto abort_call = build_call_expr_loc (location, abort, 0);
1228 :
1229 3016 : auto builtin_call
1230 3016 : = build_call_expr_loc (location, builtin, 3, left, right, result_ref);
1231 3016 : auto overflow_check
1232 3016 : = build2_loc (location, EQ_EXPR, boolean_type_node, builtin_call,
1233 : boolean_constant_expression (true));
1234 :
1235 3016 : auto if_block = build3_loc (location, COND_EXPR, void_type_node,
1236 : overflow_check, abort_call, NULL_TREE);
1237 :
1238 3016 : return if_block;
1239 : }
1240 :
1241 : // Return an expression for the comparison operation LEFT OP RIGHT.
1242 : tree
1243 4997 : comparison_expression (ComparisonOperator op, tree left_tree, tree right_tree,
1244 : location_t location)
1245 : {
1246 : /* Check if either expression is an error, in which case we return an error
1247 : expression. */
1248 4997 : if (error_operand_p (left_tree) || error_operand_p (right_tree))
1249 1 : return error_mark_node;
1250 :
1251 : /* For comparison operators, the resulting type should be boolean. */
1252 4996 : auto tree_type = boolean_type_node;
1253 4996 : auto tree_code = operator_to_tree_code (op);
1254 :
1255 : /* Construct a new tree and build an expression from it. */
1256 4996 : auto new_tree
1257 4996 : = fold_build2_loc (location, tree_code, tree_type, left_tree, right_tree);
1258 4996 : return new_tree;
1259 : }
1260 :
1261 : // Return an expression for the lazy boolean operation LEFT OP RIGHT.
1262 : tree
1263 417 : lazy_boolean_expression (LazyBooleanOperator op, tree left_tree,
1264 : tree right_tree, location_t location)
1265 : {
1266 : /* Check if either expression is an error, in which case we return an error
1267 : expression. */
1268 417 : if (error_operand_p (left_tree) || error_operand_p (right_tree))
1269 0 : return error_mark_node;
1270 :
1271 : /* For lazy boolean operators, the resulting type should be the same as the
1272 : rhs operand. */
1273 417 : auto tree_type = TREE_TYPE (right_tree);
1274 417 : auto tree_code = operator_to_tree_code (op);
1275 :
1276 : /* Construct a new tree and build an expression from it. */
1277 417 : auto new_tree
1278 417 : = fold_build2_loc (location, tree_code, tree_type, left_tree, right_tree);
1279 417 : return new_tree;
1280 : }
1281 :
1282 : // Return an expression that constructs BTYPE with VALS.
1283 :
1284 : tree
1285 21754 : constructor_expression (tree type_tree, bool is_variant,
1286 : const std::vector<tree> &vals, int union_index,
1287 : location_t location)
1288 : {
1289 21754 : if (error_operand_p (type_tree))
1290 1 : return error_mark_node;
1291 :
1292 21753 : vec<constructor_elt, va_gc> *init;
1293 42433 : vec_alloc (init, union_index != -1 ? 1 : vals.size ());
1294 :
1295 21753 : if (VECTOR_TYPE_P (type_tree))
1296 : {
1297 2 : tree element_type = TREE_TYPE (type_tree);
1298 2 : bool is_constant = true;
1299 10 : for (size_t i = 0; i < vals.size (); ++i)
1300 : {
1301 8 : tree val = vals[i];
1302 8 : if (error_operand_p (val))
1303 0 : return error_mark_node;
1304 :
1305 8 : constructor_elt empty = {NULL, NULL};
1306 8 : constructor_elt *elt = init->quick_push (empty);
1307 8 : elt->index = size_int (i);
1308 8 : elt->value = convert_tree (element_type, val, location);
1309 :
1310 8 : if (!TREE_CONSTANT (elt->value))
1311 8 : is_constant = false;
1312 : }
1313 :
1314 2 : tree ret = build_constructor (type_tree, init);
1315 2 : if (is_constant)
1316 0 : TREE_CONSTANT (ret) = 1;
1317 :
1318 : return ret;
1319 : }
1320 :
1321 21751 : tree sink = NULL_TREE;
1322 21751 : bool is_constant = true;
1323 21751 : tree field = TYPE_FIELDS (type_tree);
1324 :
1325 21751 : if (is_variant)
1326 : {
1327 973 : gcc_assert (union_index != -1);
1328 973 : gcc_assert (TREE_CODE (type_tree) == UNION_TYPE);
1329 :
1330 1890 : for (int i = 0; i < union_index; i++)
1331 : {
1332 917 : gcc_assert (field != NULL_TREE);
1333 917 : field = DECL_CHAIN (field);
1334 : }
1335 :
1336 973 : tree nested_ctor
1337 973 : = constructor_expression (TREE_TYPE (field), false, vals, -1, location);
1338 :
1339 973 : constructor_elt empty = {NULL, NULL};
1340 973 : constructor_elt *elt = init->quick_push (empty);
1341 973 : elt->index = field;
1342 973 : elt->value = convert_tree (TREE_TYPE (field), nested_ctor, location);
1343 973 : if (!TREE_CONSTANT (elt->value))
1344 291 : is_constant = false;
1345 : }
1346 : else
1347 : {
1348 20778 : if (union_index != -1)
1349 : {
1350 100 : gcc_assert (TREE_CODE (type_tree) == UNION_TYPE);
1351 100 : tree val = vals.front ();
1352 209 : for (int i = 0; i < union_index; i++)
1353 : {
1354 109 : gcc_assert (field != NULL_TREE);
1355 109 : field = DECL_CHAIN (field);
1356 : }
1357 :
1358 100 : if (TREE_TYPE (field) == error_mark_node || error_operand_p (val))
1359 : return error_mark_node;
1360 :
1361 100 : if (int_size_in_bytes (TREE_TYPE (field)) == 0)
1362 : {
1363 : // GIMPLE cannot represent indices of zero-sized types so
1364 : // trying to construct a map with zero-sized keys might lead
1365 : // to errors. Instead, we evaluate each expression that
1366 : // would have been added as a map element for its
1367 : // side-effects and construct an empty map.
1368 0 : append_to_statement_list (val, &sink);
1369 : }
1370 : else
1371 : {
1372 100 : constructor_elt empty = {NULL, NULL};
1373 100 : constructor_elt *elt = init->quick_push (empty);
1374 100 : elt->index = field;
1375 100 : elt->value = convert_tree (TREE_TYPE (field), val, location);
1376 100 : if (!TREE_CONSTANT (elt->value))
1377 61 : is_constant = false;
1378 : }
1379 : }
1380 : else
1381 : {
1382 20678 : gcc_assert (TREE_CODE (type_tree) == RECORD_TYPE);
1383 20678 : for (std::vector<tree>::const_iterator p = vals.begin ();
1384 36822 : p != vals.end (); ++p, field = DECL_CHAIN (field))
1385 : {
1386 16144 : gcc_assert (field != NULL_TREE);
1387 16144 : tree val = (*p);
1388 16144 : if (TREE_TYPE (field) == error_mark_node || error_operand_p (val))
1389 0 : return error_mark_node;
1390 :
1391 16144 : if (int_size_in_bytes (TREE_TYPE (field)) == 0)
1392 : {
1393 : // GIMPLE cannot represent indices of zero-sized types so
1394 : // trying to construct a map with zero-sized keys might lead
1395 : // to errors. Instead, we evaluate each expression that
1396 : // would have been added as a map element for its
1397 : // side-effects and construct an empty map.
1398 99 : append_to_statement_list (val, &sink);
1399 99 : continue;
1400 : }
1401 :
1402 16045 : constructor_elt empty = {NULL, NULL};
1403 16045 : constructor_elt *elt = init->quick_push (empty);
1404 16045 : elt->index = field;
1405 16045 : elt->value = convert_tree (TREE_TYPE (field), val, location);
1406 16045 : if (!TREE_CONSTANT (elt->value))
1407 3310 : is_constant = false;
1408 : }
1409 : // gcc_assert (field == NULL_TREE);
1410 : }
1411 : }
1412 :
1413 21751 : tree ret = build_constructor (type_tree, init);
1414 21751 : if (is_constant)
1415 19448 : TREE_CONSTANT (ret) = 1;
1416 21751 : if (sink != NULL_TREE)
1417 2 : ret = fold_build2_loc (location, COMPOUND_EXPR, type_tree, sink, ret);
1418 : return ret;
1419 : }
1420 :
1421 : tree
1422 336 : array_constructor_expression (tree type_tree,
1423 : const std::vector<unsigned long> &indexes,
1424 : const std::vector<tree> &vals,
1425 : location_t location)
1426 : {
1427 336 : if (error_operand_p (type_tree))
1428 0 : return error_mark_node;
1429 :
1430 336 : gcc_assert (indexes.size () == vals.size ());
1431 :
1432 336 : tree element_type = TREE_TYPE (type_tree);
1433 336 : HOST_WIDE_INT element_size = int_size_in_bytes (element_type);
1434 336 : vec<constructor_elt, va_gc> *init;
1435 669 : vec_alloc (init, element_size == 0 ? 0 : vals.size ());
1436 :
1437 336 : tree sink = NULL_TREE;
1438 336 : bool is_constant = true;
1439 2189 : for (size_t i = 0; i < vals.size (); ++i)
1440 : {
1441 1853 : tree index = size_int (indexes[i]);
1442 1853 : tree val = vals[i];
1443 :
1444 1853 : if (error_operand_p (index) || error_operand_p (val))
1445 0 : return error_mark_node;
1446 :
1447 1853 : if (element_size == 0)
1448 : {
1449 : // GIMPLE cannot represent arrays of zero-sized types so trying
1450 : // to construct an array of zero-sized values might lead to errors.
1451 : // Instead, we evaluate each expression that would have been added as
1452 : // an array value for its side-effects and construct an empty array.
1453 4 : append_to_statement_list (val, &sink);
1454 4 : continue;
1455 : }
1456 :
1457 1849 : if (!TREE_CONSTANT (val))
1458 9 : is_constant = false;
1459 :
1460 1849 : constructor_elt empty = {NULL, NULL};
1461 1849 : constructor_elt *elt = init->quick_push (empty);
1462 1849 : elt->index = index;
1463 1849 : elt->value = val;
1464 : }
1465 :
1466 336 : tree ret = build_constructor (type_tree, init);
1467 336 : if (is_constant)
1468 327 : TREE_CONSTANT (ret) = 1;
1469 336 : if (sink != NULL_TREE)
1470 3 : ret = fold_build2_loc (location, COMPOUND_EXPR, type_tree, sink, ret);
1471 : return ret;
1472 : }
1473 :
1474 : // Build insns to create an array, initialize all elements of the array to
1475 : // value, and return it
1476 : tree
1477 105 : array_initializer (tree fndecl, tree block, tree array_type, tree length,
1478 : tree value, tree *tmp, location_t locus)
1479 : {
1480 105 : std::vector<tree> stmts;
1481 :
1482 : // Temporary array we initialize with the desired value.
1483 105 : tree t = NULL_TREE;
1484 105 : Bvariable *tmp_array = temporary_variable (fndecl, block, array_type,
1485 : NULL_TREE, true, locus, &t);
1486 105 : tree arr = tmp_array->get_tree (locus);
1487 105 : stmts.push_back (t);
1488 :
1489 : // Temporary for the array length used for initialization loop guard.
1490 105 : Bvariable *tmp_len = temporary_variable (fndecl, block, size_type_node,
1491 : length, true, locus, &t);
1492 105 : tree len = tmp_len->get_tree (locus);
1493 105 : stmts.push_back (t);
1494 :
1495 : // Temporary variable for pointer used to initialize elements.
1496 105 : tree ptr_type = pointer_type (TREE_TYPE (array_type));
1497 105 : tree ptr_init
1498 105 : = build1_loc (locus, ADDR_EXPR, ptr_type,
1499 : array_index_expression (arr, integer_zero_node, locus));
1500 105 : Bvariable *tmp_ptr
1501 105 : = temporary_variable (fndecl, block, ptr_type, ptr_init, false, locus, &t);
1502 105 : tree ptr = tmp_ptr->get_tree (locus);
1503 105 : stmts.push_back (t);
1504 :
1505 : // push statement list for the loop
1506 105 : std::vector<tree> loop_stmts;
1507 :
1508 : // Loop exit condition:
1509 : // if (length == 0) break;
1510 105 : t = comparison_expression (ComparisonOperator::EQUAL, len,
1511 105 : zero_expression (TREE_TYPE (len)), locus);
1512 :
1513 105 : t = exit_expression (t, locus);
1514 105 : loop_stmts.push_back (t);
1515 :
1516 : // Assign value to the current pointer position
1517 : // *ptr = value;
1518 105 : t = assignment_statement (build_fold_indirect_ref (ptr), value, locus);
1519 105 : loop_stmts.push_back (t);
1520 :
1521 : // Move pointer to next element
1522 : // ptr++;
1523 105 : tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptr_type));
1524 105 : t = build2 (POSTINCREMENT_EXPR, ptr_type, ptr, convert (ptr_type, size));
1525 105 : loop_stmts.push_back (t);
1526 :
1527 : // Decrement loop counter.
1528 : // length--;
1529 105 : t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (len), len,
1530 105 : convert (TREE_TYPE (len), integer_one_node));
1531 105 : loop_stmts.push_back (t);
1532 :
1533 : // pop statments and finish loop
1534 105 : tree loop_body = statement_list (loop_stmts);
1535 105 : stmts.push_back (loop_expression (loop_body, locus));
1536 :
1537 : // Return the temporary in the provided pointer and the statement list which
1538 : // initializes it.
1539 105 : *tmp = tmp_array->get_tree (locus);
1540 105 : return statement_list (stmts);
1541 105 : }
1542 :
1543 : // Return an expression representing ARRAY[INDEX]
1544 :
1545 : tree
1546 476 : array_index_expression (tree array_tree, tree index_tree, location_t location)
1547 : {
1548 476 : if (error_operand_p (array_tree) || error_operand_p (index_tree))
1549 0 : return error_mark_node;
1550 :
1551 : // A function call that returns a zero sized object will have been
1552 : // changed to return void. If we see void here, assume we are
1553 : // dealing with a zero sized type and just evaluate the operands.
1554 476 : tree ret;
1555 476 : if (TREE_TYPE (array_tree) != void_type_node)
1556 476 : ret = build4_loc (location, ARRAY_REF, TREE_TYPE (TREE_TYPE (array_tree)),
1557 : array_tree, index_tree, NULL_TREE, NULL_TREE);
1558 : else
1559 0 : ret = fold_build2_loc (location, COMPOUND_EXPR, void_type_node, array_tree,
1560 : index_tree);
1561 :
1562 : return ret;
1563 : }
1564 :
1565 : // Return an expression representing SLICE[INDEX]
1566 :
1567 : tree
1568 150 : slice_index_expression (tree slice_tree, tree index_tree, location_t location)
1569 : {
1570 150 : if (error_operand_p (slice_tree) || error_operand_p (index_tree))
1571 0 : return error_mark_node;
1572 :
1573 : // A slice is created in TyTyResolvecompile::create_slice_type_record
1574 : // For example:
1575 : // &[i32] is turned directly into a struct { i32* data, usize len };
1576 : // [i32] is also turned into struct { i32* data, usize len }
1577 :
1578 : // it should have RS_DST_FLAG set to 1
1579 150 : rust_assert (RS_DST_FLAG_P (TREE_TYPE (slice_tree)));
1580 :
1581 150 : tree data_field = struct_field_expression (slice_tree, 0, location);
1582 150 : tree data_field_deref = build_fold_indirect_ref_loc (location, data_field);
1583 :
1584 150 : tree element_type = TREE_TYPE (data_field_deref);
1585 150 : tree data_pointer = TREE_OPERAND (data_field_deref, 0);
1586 150 : rust_assert (POINTER_TYPE_P (TREE_TYPE (data_pointer)));
1587 150 : tree data_offset_expr
1588 150 : = Rust::pointer_offset_expression (data_pointer, index_tree, location);
1589 :
1590 150 : return build1_loc (location, INDIRECT_REF, element_type, data_offset_expr);
1591 : }
1592 :
1593 : // Create an expression for a call to FN_EXPR with FN_ARGS.
1594 : tree
1595 16527 : call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
1596 : location_t location)
1597 : {
1598 16527 : if (error_operand_p (fn))
1599 19 : return error_mark_node;
1600 :
1601 16508 : gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn)));
1602 16508 : tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
1603 :
1604 16508 : size_t nargs = fn_args.size ();
1605 16508 : tree *args = nargs == 0 ? NULL : new tree[nargs];
1606 37720 : for (size_t i = 0; i < nargs; ++i)
1607 : {
1608 21212 : args[i] = fn_args.at (i);
1609 : }
1610 :
1611 16508 : tree fndecl = fn;
1612 16508 : if (TREE_CODE (fndecl) == ADDR_EXPR)
1613 16259 : fndecl = TREE_OPERAND (fndecl, 0);
1614 :
1615 : // This is to support builtin math functions when using 80387 math.
1616 16508 : tree excess_type = NULL_TREE;
1617 13243 : if (optimize && TREE_CODE (fndecl) == FUNCTION_DECL
1618 13041 : && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
1619 1830 : && DECL_IS_UNDECLARED_BUILTIN (fndecl) && nargs > 0
1620 17674 : && ((SCALAR_FLOAT_TYPE_P (rettype)
1621 252 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[0])))
1622 914 : || (COMPLEX_FLOAT_TYPE_P (rettype)
1623 0 : && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args[0])))))
1624 : {
1625 252 : excess_type = excess_precision_type (TREE_TYPE (args[0]));
1626 252 : if (excess_type != NULL_TREE)
1627 : {
1628 0 : tree excess_fndecl
1629 0 : = mathfn_built_in (excess_type, DECL_FUNCTION_CODE (fndecl));
1630 0 : if (excess_fndecl == NULL_TREE)
1631 : excess_type = NULL_TREE;
1632 : else
1633 : {
1634 0 : fn = build_fold_addr_expr_loc (location, excess_fndecl);
1635 0 : for (size_t i = 0; i < nargs; ++i)
1636 : {
1637 0 : if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[i]))
1638 0 : || COMPLEX_FLOAT_TYPE_P (TREE_TYPE (args[i])))
1639 0 : args[i] = ::convert (excess_type, args[i]);
1640 : }
1641 : }
1642 : }
1643 : }
1644 :
1645 16508 : tree ret
1646 16508 : = build_call_array_loc (location,
1647 : excess_type != NULL_TREE ? excess_type : rettype,
1648 : fn, nargs, args);
1649 :
1650 : // check for deprecated function usage
1651 16508 : if (fndecl && TREE_DEPRECATED (fndecl))
1652 : {
1653 : // set up the call-site information for `warn_deprecated_use`
1654 5 : input_location = location;
1655 5 : warn_deprecated_use (fndecl, NULL_TREE);
1656 : }
1657 :
1658 16508 : if (chain_expr)
1659 0 : CALL_EXPR_STATIC_CHAIN (ret) = chain_expr;
1660 :
1661 16508 : if (excess_type != NULL_TREE)
1662 : {
1663 : // Calling convert here can undo our excess precision change.
1664 : // That may or may not be a bug in convert_to_real.
1665 0 : ret = build1_loc (location, NOP_EXPR, rettype, ret);
1666 : }
1667 :
1668 16508 : delete[] args;
1669 : return ret;
1670 : }
1671 :
1672 : // Variable initialization.
1673 :
1674 : tree
1675 11958 : init_statement (tree, Bvariable *var, tree init_tree)
1676 : {
1677 11958 : tree var_tree = var->get_decl ();
1678 11958 : if (error_operand_p (var_tree) || error_operand_p (init_tree))
1679 3 : return error_mark_node;
1680 11955 : gcc_assert (TREE_CODE (var_tree) == VAR_DECL);
1681 :
1682 : // To avoid problems with GNU ld, we don't make zero-sized
1683 : // externally visible variables. That might lead us to doing an
1684 : // initialization of a zero-sized expression to a non-zero sized
1685 : // variable, or vice-versa. Avoid crashes by omitting the
1686 : // initializer. Such initializations don't mean anything anyhow.
1687 23581 : if (int_size_in_bytes (TREE_TYPE (var_tree)) != 0 && init_tree != NULL_TREE
1688 11626 : && TREE_TYPE (init_tree) != void_type_node
1689 23581 : && int_size_in_bytes (TREE_TYPE (init_tree)) != 0)
1690 : {
1691 11623 : DECL_INITIAL (var_tree) = init_tree;
1692 11623 : init_tree = NULL_TREE;
1693 : }
1694 :
1695 11955 : tree ret = build1_loc (DECL_SOURCE_LOCATION (var_tree), DECL_EXPR,
1696 : void_type_node, var_tree);
1697 11955 : if (init_tree != NULL_TREE)
1698 332 : ret = build2_loc (DECL_SOURCE_LOCATION (var_tree), COMPOUND_EXPR,
1699 : void_type_node, init_tree, ret);
1700 :
1701 : return ret;
1702 : }
1703 :
1704 : // Assignment.
1705 :
1706 : tree
1707 25833 : assignment_statement (tree lhs, tree rhs, location_t location)
1708 : {
1709 25833 : if (error_operand_p (lhs) || error_operand_p (rhs))
1710 4 : return error_mark_node;
1711 :
1712 : // To avoid problems with GNU ld, we don't make zero-sized
1713 : // externally visible variables. That might lead us to doing an
1714 : // assignment of a zero-sized expression to a non-zero sized
1715 : // expression; avoid crashes here by avoiding assignments of
1716 : // zero-sized expressions. Such assignments don't really mean
1717 : // anything anyhow.
1718 25829 : if (TREE_TYPE (lhs) == void_type_node
1719 25829 : || int_size_in_bytes (TREE_TYPE (lhs)) == 0
1720 21137 : || TREE_TYPE (rhs) == void_type_node
1721 46963 : || int_size_in_bytes (TREE_TYPE (rhs)) == 0)
1722 4769 : return compound_statement (lhs, rhs);
1723 :
1724 21060 : rhs = convert_tree (TREE_TYPE (lhs), rhs, location);
1725 :
1726 21060 : return fold_build2_loc (location, MODIFY_EXPR, void_type_node, lhs, rhs);
1727 : }
1728 :
1729 : // Return.
1730 :
1731 : tree
1732 19476 : return_statement (tree fntree, tree val, location_t location)
1733 : {
1734 19476 : if (error_operand_p (fntree))
1735 0 : return error_mark_node;
1736 :
1737 19476 : tree result = DECL_RESULT (fntree);
1738 19476 : if (error_operand_p (result))
1739 0 : return error_mark_node;
1740 :
1741 19476 : if (error_operand_p (val))
1742 9 : return error_mark_node;
1743 :
1744 19467 : tree set
1745 19467 : = fold_build2_loc (location, MODIFY_EXPR, void_type_node, result, val);
1746 19467 : return fold_build1_loc (location, RETURN_EXPR, void_type_node, set);
1747 : }
1748 :
1749 : // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an
1750 : // error occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and if not
1751 : // NULL, it will always be executed. This is used for handling defers in Rust
1752 : // functions. In C++, the resulting code is of this form:
1753 : // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }
1754 :
1755 : tree
1756 54 : exception_handler_statement (tree try_stmt, tree except_stmt, tree finally_stmt,
1757 : location_t location)
1758 : {
1759 108 : if (error_operand_p (try_stmt) || error_operand_p (except_stmt)
1760 108 : || error_operand_p (finally_stmt))
1761 0 : return error_mark_node;
1762 :
1763 54 : if (except_stmt != NULL_TREE)
1764 2 : try_stmt = build2_loc (location, TRY_CATCH_EXPR, void_type_node, try_stmt,
1765 : build2_loc (location, CATCH_EXPR, void_type_node,
1766 : NULL, except_stmt));
1767 54 : if (finally_stmt != NULL_TREE)
1768 52 : try_stmt = build2_loc (location, TRY_FINALLY_EXPR, void_type_node, try_stmt,
1769 : finally_stmt);
1770 : return try_stmt;
1771 : }
1772 :
1773 : // If.
1774 :
1775 : tree
1776 4601 : if_statement (tree, tree cond_tree, tree then_tree, tree else_tree,
1777 : location_t location)
1778 : {
1779 9202 : if (error_operand_p (cond_tree) || error_operand_p (then_tree)
1780 9202 : || error_operand_p (else_tree))
1781 0 : return error_mark_node;
1782 4601 : tree ret = build3_loc (location, COND_EXPR, void_type_node, cond_tree,
1783 : then_tree, else_tree);
1784 4601 : return ret;
1785 : }
1786 :
1787 : // Loops
1788 :
1789 : tree
1790 349 : loop_expression (tree body, location_t locus)
1791 : {
1792 349 : return fold_build1_loc (locus, LOOP_EXPR, void_type_node, body);
1793 : }
1794 :
1795 : tree
1796 282 : exit_expression (tree cond_tree, location_t locus)
1797 : {
1798 282 : return fold_build1_loc (locus, EXIT_EXPR, void_type_node, cond_tree);
1799 : }
1800 :
1801 : // Pair of statements.
1802 :
1803 : tree
1804 4803 : compound_statement (tree s1, tree s2)
1805 : {
1806 4803 : if (error_operand_p (s1) || error_operand_p (s2))
1807 0 : return error_mark_node;
1808 :
1809 4803 : tree stmt_list = NULL_TREE;
1810 4803 : append_to_statement_list (s1, &stmt_list);
1811 4803 : append_to_statement_list (s2, &stmt_list);
1812 :
1813 : // If neither statement has any side effects, stmt_list can be NULL
1814 : // at this point.
1815 4803 : if (stmt_list == NULL_TREE)
1816 4186 : stmt_list = integer_zero_node;
1817 :
1818 4803 : return stmt_list;
1819 : }
1820 :
1821 : // List of statements.
1822 :
1823 : tree
1824 311 : statement_list (const std::vector<tree> &statements)
1825 : {
1826 311 : tree stmt_list = NULL_TREE;
1827 1406 : for (tree t : statements)
1828 : {
1829 1095 : if (error_operand_p (t))
1830 0 : return error_mark_node;
1831 1095 : append_to_statement_list (t, &stmt_list);
1832 : }
1833 311 : return stmt_list;
1834 : }
1835 :
1836 : // Make a block. For some reason gcc uses a dual structure for
1837 : // blocks: BLOCK tree nodes and BIND_EXPR tree nodes. Since the
1838 : // BIND_EXPR node points to the BLOCK node, we store the BIND_EXPR in
1839 : // the Bblock.
1840 :
1841 : tree
1842 46109 : block (tree fndecl, tree enclosing, const std::vector<Bvariable *> &vars,
1843 : location_t start_location, location_t)
1844 : {
1845 46109 : tree block_tree = make_node (BLOCK);
1846 46109 : if (enclosing == NULL)
1847 : {
1848 19552 : gcc_assert (fndecl != NULL_TREE);
1849 :
1850 : // We may have already created a block for local variables when
1851 : // we take the address of a parameter.
1852 19552 : if (DECL_INITIAL (fndecl) == NULL_TREE)
1853 : {
1854 19548 : BLOCK_SUPERCONTEXT (block_tree) = fndecl;
1855 19548 : DECL_INITIAL (fndecl) = block_tree;
1856 : }
1857 : else
1858 : {
1859 4 : tree superblock_tree = DECL_INITIAL (fndecl);
1860 4 : BLOCK_SUPERCONTEXT (block_tree) = superblock_tree;
1861 4 : tree *pp;
1862 6 : for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE;
1863 2 : pp = &BLOCK_CHAIN (*pp))
1864 : ;
1865 4 : *pp = block_tree;
1866 : }
1867 : }
1868 : else
1869 : {
1870 26557 : tree superblock_tree = BIND_EXPR_BLOCK (enclosing);
1871 26557 : gcc_assert (TREE_CODE (superblock_tree) == BLOCK);
1872 :
1873 26557 : BLOCK_SUPERCONTEXT (block_tree) = superblock_tree;
1874 26557 : tree *pp;
1875 38052 : for (pp = &BLOCK_SUBBLOCKS (superblock_tree); *pp != NULL_TREE;
1876 11495 : pp = &BLOCK_CHAIN (*pp))
1877 : ;
1878 26557 : *pp = block_tree;
1879 : }
1880 :
1881 : // Chain the variables of the scope together so they are all connected
1882 : // to the block.
1883 46109 : tree *pp = &BLOCK_VARS (block_tree);
1884 46582 : for (Bvariable *bv : vars)
1885 : {
1886 473 : *pp = bv->get_decl ();
1887 473 : if (!error_operand_p (*pp))
1888 473 : pp = &DECL_CHAIN (*pp);
1889 : }
1890 46109 : *pp = NULL_TREE;
1891 :
1892 46109 : TREE_USED (block_tree) = 1;
1893 :
1894 46109 : tree bind_tree = build3_loc (start_location, BIND_EXPR, void_type_node,
1895 46109 : BLOCK_VARS (block_tree), NULL_TREE, block_tree);
1896 46109 : TREE_SIDE_EFFECTS (bind_tree) = 1;
1897 46109 : return bind_tree;
1898 : }
1899 :
1900 : // Add statements to a block.
1901 :
1902 : void
1903 46093 : block_add_statements (tree bind_tree, const std::vector<tree> &statements)
1904 : {
1905 46093 : tree stmt_list = NULL_TREE;
1906 172746 : for (tree s : statements)
1907 : {
1908 126653 : if (!error_operand_p (s))
1909 126582 : append_to_statement_list (s, &stmt_list);
1910 : }
1911 :
1912 46093 : gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
1913 46093 : BIND_EXPR_BODY (bind_tree) = stmt_list;
1914 46093 : }
1915 :
1916 : // This is not static because we declare it with GTY(()) in rust-c.h.
1917 : tree rust_non_zero_struct;
1918 :
1919 : // Return a type corresponding to TYPE with non-zero size.
1920 :
1921 : tree
1922 5 : non_zero_size_type (tree type)
1923 : {
1924 5 : if (int_size_in_bytes (type) != 0)
1925 : return type;
1926 :
1927 5 : switch (TREE_CODE (type))
1928 : {
1929 5 : case RECORD_TYPE:
1930 5 : if (TYPE_FIELDS (type) != NULL_TREE)
1931 : {
1932 0 : tree ns = make_node (RECORD_TYPE);
1933 0 : tree field_trees = NULL_TREE;
1934 0 : tree *pp = &field_trees;
1935 0 : for (tree field = TYPE_FIELDS (type); field != NULL_TREE;
1936 0 : field = DECL_CHAIN (field))
1937 : {
1938 0 : tree ft = TREE_TYPE (field);
1939 0 : if (field == TYPE_FIELDS (type))
1940 0 : ft = non_zero_size_type (ft);
1941 0 : tree f = build_decl (DECL_SOURCE_LOCATION (field), FIELD_DECL,
1942 0 : DECL_NAME (field), ft);
1943 0 : DECL_CONTEXT (f) = ns;
1944 0 : *pp = f;
1945 0 : pp = &DECL_CHAIN (f);
1946 : }
1947 0 : TYPE_FIELDS (ns) = field_trees;
1948 0 : layout_type (ns);
1949 0 : return ns;
1950 : }
1951 :
1952 5 : if (rust_non_zero_struct == NULL_TREE)
1953 : {
1954 4 : type = make_node (RECORD_TYPE);
1955 4 : tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
1956 : get_identifier ("dummy"), boolean_type_node);
1957 4 : DECL_CONTEXT (field) = type;
1958 4 : TYPE_FIELDS (type) = field;
1959 4 : layout_type (type);
1960 4 : rust_non_zero_struct = type;
1961 : }
1962 5 : return rust_non_zero_struct;
1963 :
1964 0 : case ARRAY_TYPE:
1965 0 : {
1966 0 : tree element_type = non_zero_size_type (TREE_TYPE (type));
1967 0 : return build_array_type_nelts (element_type, 1);
1968 : }
1969 :
1970 0 : default:
1971 0 : rust_unreachable ();
1972 : }
1973 :
1974 : rust_unreachable ();
1975 : }
1976 :
1977 : // Convert EXPR_TREE to TYPE_TREE. Sometimes the same unnamed Rust type
1978 : // can be created multiple times and thus have multiple tree
1979 : // representations. Make sure this does not confuse the middle-end.
1980 :
1981 : tree
1982 43032 : convert_tree (tree type_tree, tree expr_tree, location_t location)
1983 : {
1984 43032 : if (type_tree == TREE_TYPE (expr_tree))
1985 : return expr_tree;
1986 :
1987 9601 : if (error_operand_p (type_tree) || error_operand_p (expr_tree))
1988 0 : return error_mark_node;
1989 :
1990 9601 : if (POINTER_TYPE_P (type_tree) || INTEGRAL_TYPE_P (type_tree)
1991 9601 : || SCALAR_FLOAT_TYPE_P (type_tree) || COMPLEX_FLOAT_TYPE_P (type_tree))
1992 8457 : return fold_convert_loc (location, type_tree, expr_tree);
1993 1144 : else if (TREE_CODE (type_tree) == RECORD_TYPE
1994 : || TREE_CODE (type_tree) == UNION_TYPE
1995 1144 : || TREE_CODE (type_tree) == ARRAY_TYPE || VECTOR_TYPE_P (type_tree))
1996 : {
1997 1144 : gcc_assert (int_size_in_bytes (type_tree)
1998 : == int_size_in_bytes (TREE_TYPE (expr_tree)));
1999 1144 : if (TYPE_MAIN_VARIANT (type_tree)
2000 1144 : == TYPE_MAIN_VARIANT (TREE_TYPE (expr_tree)))
2001 1112 : return fold_build1_loc (location, NOP_EXPR, type_tree, expr_tree);
2002 32 : return fold_build1_loc (location, VIEW_CONVERT_EXPR, type_tree,
2003 32 : expr_tree);
2004 : }
2005 :
2006 0 : rust_unreachable ();
2007 : }
2008 :
2009 : // Make a global variable.
2010 :
2011 : Bvariable *
2012 221 : global_variable (GGC::Ident var_name, GGC::Ident asm_name, tree type_tree,
2013 : bool is_external, bool is_hidden, bool in_unique_section,
2014 : location_t location)
2015 : {
2016 221 : if (error_operand_p (type_tree))
2017 0 : return Bvariable::error_variable ();
2018 :
2019 : // The GNU linker does not like dynamic variables with zero size.
2020 221 : tree orig_type_tree = type_tree;
2021 221 : if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0)
2022 5 : type_tree = non_zero_size_type (type_tree);
2023 :
2024 221 : tree decl = build_decl (location, VAR_DECL, var_name.as_tree (), type_tree);
2025 221 : if (is_external)
2026 0 : DECL_EXTERNAL (decl) = 1;
2027 : else
2028 221 : TREE_STATIC (decl) = 1;
2029 221 : if (!is_hidden)
2030 : {
2031 54 : TREE_PUBLIC (decl) = 1;
2032 54 : SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
2033 : }
2034 : else
2035 : {
2036 167 : SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
2037 : }
2038 :
2039 221 : TREE_USED (decl) = 1;
2040 :
2041 221 : if (in_unique_section)
2042 221 : resolve_unique_section (decl, 0, 1);
2043 :
2044 221 : rust_preserve_from_gc (decl);
2045 :
2046 221 : return new Bvariable (decl, orig_type_tree);
2047 : }
2048 :
2049 : // Set the initial value of a global variable.
2050 :
2051 : void
2052 221 : global_variable_set_init (Bvariable *var, tree expr_tree)
2053 : {
2054 221 : if (error_operand_p (expr_tree))
2055 : return;
2056 219 : gcc_assert (TREE_CONSTANT (expr_tree));
2057 219 : tree var_decl = var->get_decl ();
2058 219 : if (error_operand_p (var_decl))
2059 : return;
2060 219 : DECL_INITIAL (var_decl) = expr_tree;
2061 :
2062 : // If this variable goes in a unique section, it may need to go into
2063 : // a different one now that DECL_INITIAL is set.
2064 219 : if (symtab_node::get (var_decl)
2065 219 : && symtab_node::get (var_decl)->implicit_section)
2066 : {
2067 219 : set_decl_section_name (var_decl, (const char *) NULL);
2068 219 : resolve_unique_section (var_decl, compute_reloc_for_constant (expr_tree),
2069 : 1);
2070 : }
2071 : }
2072 :
2073 : // Make a local variable.
2074 :
2075 : LocalVariable
2076 0 : local_variable (tree function, GGC::Ident name, tree type_tree,
2077 : Bvariable *decl_var, location_t location)
2078 : {
2079 0 : if (error_operand_p (type_tree))
2080 0 : return LocalVariable::error_variable ();
2081 0 : tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree);
2082 0 : DECL_CONTEXT (decl) = function;
2083 :
2084 0 : if (decl_var != NULL)
2085 : {
2086 0 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
2087 0 : SET_DECL_VALUE_EXPR (decl, decl_var->get_decl ());
2088 : }
2089 0 : rust_preserve_from_gc (decl);
2090 0 : return LocalVariable (decl);
2091 : }
2092 :
2093 : // Make a function parameter variable.
2094 :
2095 : LocalVariable
2096 18001 : parameter_variable (tree function, GGC::Ident name, tree type_tree,
2097 : location_t location)
2098 : {
2099 18001 : if (error_operand_p (type_tree))
2100 0 : return LocalVariable::error_variable ();
2101 18001 : tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
2102 18001 : DECL_CONTEXT (decl) = function;
2103 18001 : DECL_ARG_TYPE (decl) = type_tree;
2104 :
2105 18001 : rust_preserve_from_gc (decl);
2106 18001 : return LocalVariable (decl);
2107 : }
2108 :
2109 : // Make a static chain variable.
2110 :
2111 : LocalVariable
2112 0 : static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree,
2113 : location_t location)
2114 : {
2115 0 : if (error_operand_p (type_tree))
2116 0 : return LocalVariable::error_variable ();
2117 0 : tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
2118 0 : DECL_CONTEXT (decl) = fndecl;
2119 0 : DECL_ARG_TYPE (decl) = type_tree;
2120 0 : TREE_USED (decl) = 1;
2121 0 : DECL_ARTIFICIAL (decl) = 1;
2122 0 : DECL_IGNORED_P (decl) = 1;
2123 0 : TREE_READONLY (decl) = 1;
2124 :
2125 0 : struct function *f = DECL_STRUCT_FUNCTION (fndecl);
2126 0 : if (f == NULL)
2127 : {
2128 0 : push_struct_function (fndecl);
2129 0 : pop_cfun ();
2130 0 : f = DECL_STRUCT_FUNCTION (fndecl);
2131 : }
2132 0 : gcc_assert (f->static_chain_decl == NULL);
2133 0 : f->static_chain_decl = decl;
2134 0 : DECL_STATIC_CHAIN (fndecl) = 1;
2135 :
2136 0 : rust_preserve_from_gc (decl);
2137 0 : return LocalVariable (decl);
2138 : }
2139 :
2140 : // Make a temporary variable.
2141 :
2142 : LocalVariable
2143 29740 : temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
2144 : bool is_address_taken, location_t location,
2145 : tree *pstatement)
2146 : {
2147 29740 : gcc_assert (fndecl != NULL_TREE);
2148 59480 : if (error_operand_p (type_tree) || error_operand_p (init_tree)
2149 59474 : || error_operand_p (fndecl))
2150 : {
2151 6 : *pstatement = error_mark_node;
2152 6 : return LocalVariable::error_variable ();
2153 : }
2154 :
2155 29734 : tree var;
2156 : // We can only use create_tmp_var if the type is not addressable.
2157 29734 : if (!TREE_ADDRESSABLE (type_tree))
2158 : {
2159 29734 : if (DECL_STRUCT_FUNCTION (fndecl) == NULL)
2160 16504 : push_struct_function (fndecl);
2161 : else
2162 13230 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
2163 :
2164 29734 : var = create_tmp_var (type_tree, "RUSTTMP");
2165 29734 : pop_cfun ();
2166 : }
2167 : else
2168 : {
2169 0 : gcc_assert (bind_tree != NULL_TREE);
2170 0 : var = build_decl (location, VAR_DECL, create_tmp_var_name ("RUSTTMP"),
2171 : type_tree);
2172 0 : DECL_ARTIFICIAL (var) = 1;
2173 0 : DECL_IGNORED_P (var) = 1;
2174 0 : TREE_USED (var) = 1;
2175 0 : DECL_CONTEXT (var) = fndecl;
2176 :
2177 : // We have to add this variable to the BLOCK and the BIND_EXPR.
2178 0 : gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
2179 0 : tree block_tree = BIND_EXPR_BLOCK (bind_tree);
2180 0 : gcc_assert (TREE_CODE (block_tree) == BLOCK);
2181 0 : DECL_CHAIN (var) = BLOCK_VARS (block_tree);
2182 0 : BLOCK_VARS (block_tree) = var;
2183 0 : BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree);
2184 : }
2185 :
2186 51969 : if (type_size (type_tree) != 0 && init_tree != NULL_TREE
2187 34580 : && TREE_TYPE (init_tree) != void_type_node)
2188 4846 : DECL_INITIAL (var) = convert_tree (type_tree, init_tree, location);
2189 :
2190 29734 : if (is_address_taken)
2191 4718 : TREE_ADDRESSABLE (var) = 1;
2192 :
2193 29734 : *pstatement = build1_loc (location, DECL_EXPR, void_type_node, var);
2194 :
2195 : // For a zero sized type, don't initialize VAR with BINIT, but still
2196 : // evaluate BINIT for its side effects.
2197 29734 : if (init_tree != NULL_TREE
2198 29734 : && (type_size (type_tree) == 0
2199 4846 : || TREE_TYPE (init_tree) == void_type_node))
2200 34 : *pstatement = compound_statement (init_tree, *pstatement);
2201 :
2202 29734 : return LocalVariable (var);
2203 : }
2204 :
2205 : // Make a label.
2206 :
2207 : tree
2208 1394 : label (tree func_tree, tl::optional<GGC::Ident> name, location_t location)
2209 : {
2210 1394 : tree decl;
2211 1394 : if (!name.has_value ())
2212 : {
2213 1289 : if (DECL_STRUCT_FUNCTION (func_tree) == NULL)
2214 0 : push_struct_function (func_tree);
2215 : else
2216 1289 : push_cfun (DECL_STRUCT_FUNCTION (func_tree));
2217 :
2218 1289 : decl = create_artificial_label (location);
2219 :
2220 1289 : pop_cfun ();
2221 : }
2222 : else
2223 : {
2224 105 : tree id = name->as_tree ();
2225 105 : decl = build_decl (location, LABEL_DECL, id, void_type_node);
2226 105 : DECL_CONTEXT (decl) = func_tree;
2227 : }
2228 1394 : return decl;
2229 : }
2230 :
2231 : // Make a statement which defines a label.
2232 :
2233 : tree
2234 1394 : label_definition_statement (tree label)
2235 : {
2236 1394 : return fold_build1_loc (DECL_SOURCE_LOCATION (label), LABEL_EXPR,
2237 1394 : void_type_node, label);
2238 : }
2239 :
2240 : // Make a goto statement.
2241 :
2242 : tree
2243 58 : goto_statement (tree label, location_t location)
2244 : {
2245 58 : return fold_build1_loc (location, GOTO_EXPR, void_type_node, label);
2246 : }
2247 :
2248 : // Get the address of a label.
2249 :
2250 : tree
2251 0 : label_address (tree label, location_t location)
2252 : {
2253 0 : TREE_USED (label) = 1;
2254 0 : TREE_ADDRESSABLE (label) = 1;
2255 0 : tree ret = fold_convert_loc (location, ptr_type_node,
2256 : build_fold_addr_expr_loc (location, label));
2257 0 : return ret;
2258 : }
2259 :
2260 : // Declare or define a new function.
2261 :
2262 : tree
2263 20692 : function (tree functype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
2264 : unsigned int flags, location_t location)
2265 : {
2266 20692 : if (error_operand_p (functype))
2267 0 : return error_mark_node;
2268 :
2269 20692 : gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
2270 20692 : functype = TREE_TYPE (functype);
2271 20692 : tree id = name.as_tree ();
2272 20692 : if (error_operand_p (id))
2273 0 : return error_mark_node;
2274 :
2275 20692 : tree decl = build_decl (location, FUNCTION_DECL, id, functype);
2276 20692 : if (asm_name.has_value ())
2277 4541 : SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ());
2278 :
2279 20692 : if ((flags & function_is_declaration) != 0)
2280 1140 : DECL_EXTERNAL (decl) = 1;
2281 : else
2282 : {
2283 19552 : tree restype = TREE_TYPE (functype);
2284 19552 : tree resdecl = build_decl (location, RESULT_DECL, NULL_TREE, restype);
2285 19552 : DECL_ARTIFICIAL (resdecl) = 1;
2286 19552 : DECL_IGNORED_P (resdecl) = 1;
2287 19552 : DECL_CONTEXT (resdecl) = decl;
2288 19552 : DECL_RESULT (decl) = resdecl;
2289 : }
2290 20692 : if ((flags & function_is_uninlinable) != 0)
2291 0 : DECL_UNINLINABLE (decl) = 1;
2292 20692 : if ((flags & function_does_not_return) != 0)
2293 0 : TREE_THIS_VOLATILE (decl) = 1;
2294 20692 : if ((flags & function_in_unique_section) != 0)
2295 0 : resolve_unique_section (decl, 0, 1);
2296 :
2297 20692 : rust_preserve_from_gc (decl);
2298 20692 : return decl;
2299 : }
2300 :
2301 : // Create a statement that runs all deferred calls for FUNCTION. This should
2302 : // be a statement that looks like this in C++:
2303 : // finish:
2304 : // try { UNDEFER; } catch { CHECK_DEFER; goto finish; }
2305 :
2306 : tree
2307 0 : function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
2308 : location_t location)
2309 : {
2310 0 : if (error_operand_p (undefer_tree) || error_operand_p (defer_tree)
2311 0 : || error_operand_p (function))
2312 0 : return error_mark_node;
2313 :
2314 0 : if (DECL_STRUCT_FUNCTION (function) == NULL)
2315 0 : push_struct_function (function);
2316 : else
2317 0 : push_cfun (DECL_STRUCT_FUNCTION (function));
2318 :
2319 0 : tree stmt_list = NULL;
2320 0 : tree label = Backend::label (function, tl::nullopt, location);
2321 0 : tree label_def = label_definition_statement (label);
2322 0 : append_to_statement_list (label_def, &stmt_list);
2323 :
2324 0 : tree jump_stmt = goto_statement (label, location);
2325 0 : tree catch_body
2326 0 : = build2 (COMPOUND_EXPR, void_type_node, defer_tree, jump_stmt);
2327 0 : catch_body = build2 (CATCH_EXPR, void_type_node, NULL, catch_body);
2328 0 : tree try_catch
2329 0 : = build2 (TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
2330 0 : append_to_statement_list (try_catch, &stmt_list);
2331 0 : pop_cfun ();
2332 :
2333 0 : return stmt_list;
2334 : }
2335 :
2336 : // Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
2337 : // This will only be called for a function definition.
2338 :
2339 : bool
2340 16930 : function_set_parameters (tree function,
2341 : const std::vector<Bvariable *> ¶m_vars)
2342 : {
2343 16930 : if (error_operand_p (function))
2344 : return false;
2345 :
2346 16930 : tree params = NULL_TREE;
2347 16930 : tree *pp = ¶ms;
2348 34930 : for (Bvariable *bv : param_vars)
2349 : {
2350 18001 : *pp = bv->get_decl ();
2351 18001 : gcc_assert (!error_operand_p (*pp));
2352 18000 : pp = &DECL_CHAIN (*pp);
2353 : }
2354 16929 : *pp = NULL_TREE;
2355 16929 : DECL_ARGUMENTS (function) = params;
2356 16929 : return true;
2357 : }
2358 :
2359 : // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
2360 : // FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
2361 : // emit early debugging information.
2362 :
2363 : void
2364 4390 : write_global_definitions (const std::vector<tree> &type_decls,
2365 : const std::vector<tree> &constant_decls,
2366 : const std::vector<tree> &function_decls,
2367 : const std::vector<Bvariable *> &variable_decls)
2368 : {
2369 4390 : size_t count_definitions = type_decls.size () + constant_decls.size ()
2370 4390 : + function_decls.size () + variable_decls.size ();
2371 :
2372 4390 : tree *defs = new tree[count_definitions];
2373 :
2374 : // Convert all non-erroneous declarations into Gimple form.
2375 4390 : size_t i = 0;
2376 8999 : for (Bvariable *bv : variable_decls)
2377 : {
2378 219 : tree v = bv->get_decl ();
2379 219 : if (error_operand_p (v))
2380 0 : continue;
2381 219 : defs[i] = v;
2382 219 : rust_preserve_from_gc (defs[i]);
2383 219 : ++i;
2384 : }
2385 :
2386 90011 : for (tree type_tree : type_decls)
2387 : {
2388 85621 : if (!error_operand_p (type_tree) && IS_TYPE_OR_DECL_P (type_tree))
2389 : {
2390 85621 : defs[i] = TYPE_NAME (type_tree);
2391 85621 : gcc_assert (defs[i] != NULL);
2392 85621 : rust_preserve_from_gc (defs[i]);
2393 85621 : ++i;
2394 : }
2395 : }
2396 4905 : for (tree t : constant_decls)
2397 : {
2398 515 : if (!error_operand_p (t))
2399 : {
2400 515 : defs[i] = t;
2401 515 : rust_preserve_from_gc (defs[i]);
2402 515 : ++i;
2403 : }
2404 : }
2405 21773 : for (tree decl : function_decls)
2406 : {
2407 17383 : if (!error_operand_p (decl))
2408 : {
2409 17383 : rust_preserve_from_gc (decl);
2410 17383 : if (DECL_STRUCT_FUNCTION (decl) == NULL)
2411 2983 : allocate_struct_function (decl, false);
2412 17383 : dump_function (TDI_original, decl);
2413 17383 : cgraph_node::finalize_function (decl, true);
2414 :
2415 17383 : defs[i] = decl;
2416 17383 : ++i;
2417 : }
2418 : }
2419 :
2420 : // Pass everything back to the middle-end.
2421 :
2422 4390 : wrapup_global_declarations (defs, i);
2423 :
2424 4390 : delete[] defs;
2425 4390 : }
2426 :
2427 : tree
2428 14 : lookup_field (const_tree type, tree component)
2429 : {
2430 14 : tree field;
2431 :
2432 21 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
2433 : {
2434 21 : if (DECL_NAME (field) == NULL_TREE
2435 21 : && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
2436 : {
2437 0 : tree anon = lookup_field (TREE_TYPE (field), component);
2438 :
2439 0 : if (anon)
2440 0 : return tree_cons (NULL_TREE, field, anon);
2441 : }
2442 :
2443 21 : if (DECL_NAME (field) == component)
2444 : break;
2445 : }
2446 :
2447 14 : if (field == NULL_TREE)
2448 : return NULL_TREE;
2449 :
2450 14 : return tree_cons (NULL_TREE, field, NULL_TREE);
2451 : }
2452 :
2453 : } // namespace Backend
|