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