LCOV - code coverage report
Current view: top level - gcc/rust - rust-gcc.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 75.0 % 1022 767
Test Date: 2025-09-20 13:40:47 Functions: 83.5 % 85 71
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             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> &parameters,
     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> &parameters,
     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> &parameters,
     553                 :             :                    location_t /* locus */)
     554                 :             : {
     555                 :          66 :   tree args = NULL_TREE;
     556                 :          66 :   tree *pp = &args;
     557                 :             : 
     558                 :         136 :   for (auto &param : 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 *> &param_vars)
    2284                 :             : {
    2285                 :       14196 :   if (error_operand_p (function))
    2286                 :             :     return false;
    2287                 :             : 
    2288                 :       14196 :   tree params = NULL_TREE;
    2289                 :       14196 :   tree *pp = &params;
    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
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.