LCOV - code coverage report
Current view: top level - gcc/rust - rust-gcc.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 78.7 % 980 771
Test Date: 2025-04-12 15:46:39 Functions: 82.9 % 82 68
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

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.