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