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