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