LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-base.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.7 % 518 444
Test Date: 2026-02-28 14:20:25 Functions: 79.3 % 29 23
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-compile-base.h"
      20              : #include "rust-abi.h"
      21              : #include "rust-compile-stmt.h"
      22              : #include "rust-compile-expr.h"
      23              : #include "rust-compile-fnparam.h"
      24              : #include "rust-compile-var-decl.h"
      25              : #include "rust-compile-type.h"
      26              : #include "rust-constexpr.h"
      27              : #include "rust-diagnostics.h"
      28              : #include "rust-expr.h" // for AST::AttrInputLiteral
      29              : #include "rust-hir-map.h"
      30              : #include "rust-macro.h" // for AST::MetaNameValueStr
      31              : #include "rust-hir-path-probe.h"
      32              : #include "rust-type-util.h"
      33              : #include "rust-compile-implitem.h"
      34              : #include "rust-attribute-values.h"
      35              : #include "rust-attributes.h"
      36              : #include "rust-immutable-name-resolution-context.h"
      37              : 
      38              : #include "fold-const.h"
      39              : #include "stringpool.h"
      40              : #include "attribs.h"
      41              : #include "tree.h"
      42              : #include "print-tree.h"
      43              : 
      44              : // rust-name-resolution-2.0
      45              : #include "options.h"
      46              : 
      47              : namespace Rust {
      48              : namespace Compile {
      49              : 
      50        12730 : bool inline should_mangle_item (const tree fndecl)
      51              : {
      52        12730 :   return lookup_attribute (Values::Attributes::NO_MANGLE,
      53        12730 :                            DECL_ATTRIBUTES (fndecl))
      54        12730 :          == NULL_TREE;
      55              : }
      56              : 
      57              : void
      58        12730 : HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point,
      59              :                               bool is_generic_fn, HIR::Visibility &visibility,
      60              :                               const HIR::FunctionQualifiers &qualifiers,
      61              :                               const AST::AttrVec &attrs)
      62              : {
      63              :   // if its the main fn or pub visibility mark its as DECL_PUBLIC
      64              :   // please see https://github.com/Rust-GCC/gccrs/pull/137
      65        12730 :   bool is_pub = visibility.get_vis_type () == HIR::Visibility::VisType::PUBLIC;
      66        12730 :   if (is_main_entry_point || (is_pub && !is_generic_fn))
      67              :     {
      68         5657 :       TREE_PUBLIC (fndecl) = 1;
      69              :     }
      70              : 
      71              :   // is it a const fn
      72        12730 :   DECL_DECLARED_CONSTEXPR_P (fndecl) = qualifiers.is_const ();
      73        12730 :   if (qualifiers.is_const ())
      74              :     {
      75          664 :       TREE_READONLY (fndecl) = 1;
      76              :     }
      77              : 
      78              :   // is it inline?
      79        28340 :   for (const auto &attr : attrs)
      80              :     {
      81        15610 :       bool is_inline
      82        15610 :         = attr.get_path ().as_string () == Values::Attributes::INLINE;
      83        15610 :       bool is_must_use
      84        15610 :         = attr.get_path ().as_string () == Values::Attributes::MUST_USE;
      85        15610 :       bool is_cold = attr.get_path ().as_string () == Values::Attributes::COLD;
      86        15610 :       bool is_link_section
      87        15610 :         = attr.get_path ().as_string () == Values::Attributes::LINK_SECTION;
      88        15610 :       bool no_mangle
      89        15610 :         = attr.get_path ().as_string () == Values::Attributes::NO_MANGLE;
      90        15610 :       bool is_deprecated
      91        15610 :         = attr.get_path ().as_string () == Values::Attributes::DEPRECATED;
      92        15610 :       bool is_proc_macro
      93        15610 :         = attr.get_path ().as_string () == Values::Attributes::PROC_MACRO;
      94        15610 :       bool is_proc_macro_attribute
      95        31220 :         = attr.get_path ().as_string ()
      96        15610 :           == Values::Attributes::PROC_MACRO_ATTRIBUTE;
      97        31220 :       bool is_proc_macro_derive = attr.get_path ().as_string ()
      98        15610 :                                   == Values::Attributes::PROC_MACRO_DERIVE;
      99              : 
     100        15610 :       if (is_inline)
     101              :         {
     102          943 :           handle_inline_attribute_on_fndecl (fndecl, attr);
     103              :         }
     104        14667 :       else if (is_must_use)
     105              :         {
     106         1089 :           handle_must_use_attribute_on_fndecl (fndecl, attr);
     107              :         }
     108        13578 :       else if (is_cold)
     109              :         {
     110            1 :           handle_cold_attribute_on_fndecl (fndecl, attr);
     111              :         }
     112        13577 :       else if (is_link_section)
     113              :         {
     114            1 :           handle_link_section_attribute_on_fndecl (fndecl, attr);
     115              :         }
     116        13576 :       else if (is_deprecated)
     117              :         {
     118            5 :           handle_deprecated_attribute_on_fndecl (fndecl, attr);
     119              :         }
     120        13571 :       else if (no_mangle)
     121              :         {
     122            1 :           handle_no_mangle_attribute_on_fndecl (fndecl, attr);
     123              :         }
     124        13570 :       else if (is_proc_macro)
     125              :         {
     126            0 :           handle_bang_proc_macro_attribute_on_fndecl (fndecl, attr);
     127              :         }
     128        13570 :       else if (is_proc_macro_attribute)
     129              :         {
     130            0 :           handle_attribute_proc_macro_attribute_on_fndecl (fndecl, attr);
     131              :         }
     132        13570 :       else if (is_proc_macro_derive)
     133              :         {
     134            0 :           handle_derive_proc_macro_attribute_on_fndecl (fndecl, attr);
     135              :         }
     136              :     }
     137        12730 : }
     138              : 
     139              : static void
     140            0 : handle_proc_macro_common (tree fndecl, const AST::Attribute &attr)
     141              : {
     142            0 :   DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("gccrs_proc_macro"),
     143            0 :                                         NULL, DECL_ATTRIBUTES (fndecl));
     144            0 : }
     145              : 
     146              : void
     147            0 : HIRCompileBase::handle_bang_proc_macro_attribute_on_fndecl (
     148              :   tree fndecl, const AST::Attribute &attr)
     149              : {
     150            0 :   handle_proc_macro_common (fndecl, attr);
     151            0 :   ctx->collect_bang_proc_macro (fndecl);
     152            0 : }
     153              : 
     154              : void
     155            0 : HIRCompileBase::handle_attribute_proc_macro_attribute_on_fndecl (
     156              :   tree fndecl, const AST::Attribute &attr)
     157              : {
     158            0 :   handle_proc_macro_common (fndecl, attr);
     159            0 :   ctx->collect_attribute_proc_macro (fndecl);
     160            0 : }
     161              : 
     162              : static std::vector<std::string>
     163            0 : get_attributes (const AST::Attribute &attr)
     164              : {
     165            0 :   std::vector<std::string> result;
     166              : 
     167            0 :   rust_assert (attr.get_attr_input ().get_attr_input_type ()
     168              :                == Rust::AST::AttrInput::TOKEN_TREE);
     169            0 :   const auto &tt
     170            0 :     = static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ());
     171              : 
     172              :   // TODO: Should we rely on fixed index ? Should we search for the
     173              :   // attribute tokentree instead ?
     174              : 
     175              :   // Derive proc macros have the following format:
     176              :   // #[proc_macro_derive(TraitName, attributes(attr1, attr2, attr3))]
     177              :   //                    -~~~~~~~~ - ~~~~~~~~~~---------------------
     178              :   //                    ^0  ^1    ^2     ^3           ^4
     179              :   // - "attributes" is stored at position 3 in the token tree
     180              :   // - attribute are stored in the delimited token tree in position 4
     181            0 :   constexpr size_t attr_kw_pos = 3;
     182            0 :   constexpr size_t attribute_list_pos = 4;
     183              : 
     184            0 :   if (tt.get_token_trees ().size () > attr_kw_pos)
     185              :     {
     186            0 :       rust_assert (tt.get_token_trees ()[attr_kw_pos]->as_string ()
     187              :                    == "attributes");
     188              : 
     189            0 :       auto attributes = static_cast<const AST::DelimTokenTree *> (
     190            0 :         tt.get_token_trees ()[attribute_list_pos].get ());
     191              : 
     192            0 :       auto &token_trees = attributes->get_token_trees ();
     193              : 
     194            0 :       for (auto i = token_trees.cbegin () + 1; // Skip opening parenthesis
     195            0 :            i < token_trees.cend ();
     196            0 :            i += 2) // Skip comma and closing parenthesis
     197              :         {
     198            0 :           result.push_back ((*i)->as_string ());
     199              :         }
     200              :     }
     201            0 :   return result;
     202              : }
     203              : 
     204              : static std::string
     205            0 : get_trait_name (const AST::Attribute &attr)
     206              : {
     207              :   // Derive proc macros have the following format:
     208              :   // #[proc_macro_derive(TraitName, attributes(attr1, attr2, attr3))]
     209              :   //                    -~~~~~~~~ - ~~~~~~~~~~---------------------
     210              :   //                    ^0  ^1    ^2     ^3           ^4
     211              :   // - The trait name is stored at position 1
     212            0 :   constexpr size_t trait_name_pos = 1;
     213              : 
     214            0 :   rust_assert (attr.get_attr_input ().get_attr_input_type ()
     215              :                == Rust::AST::AttrInput::TOKEN_TREE);
     216            0 :   const auto &tt
     217            0 :     = static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ());
     218            0 :   return tt.get_token_trees ()[trait_name_pos]->as_string ();
     219              : }
     220              : 
     221              : void
     222            0 : HIRCompileBase::handle_derive_proc_macro_attribute_on_fndecl (
     223              :   tree fndecl, const AST::Attribute &attr)
     224              : {
     225            0 :   handle_proc_macro_common (fndecl, attr);
     226              : 
     227            0 :   attr.get_attr_input ().parse_to_meta_item ();
     228            0 :   CustomDeriveInfo macro
     229            0 :     = {fndecl, get_trait_name (attr), get_attributes (attr)};
     230            0 :   ctx->collect_derive_proc_macro (macro);
     231            0 : }
     232              : 
     233              : void
     234            1 : HIRCompileBase::handle_cold_attribute_on_fndecl (tree fndecl,
     235              :                                                  const AST::Attribute &attr)
     236              : {
     237              :   // simple #[cold]
     238            1 :   if (!attr.has_attr_input ())
     239              :     {
     240            1 :       tree cold = get_identifier (Values::Attributes::COLD);
     241              :       // this will get handled by the GCC backend later
     242            1 :       DECL_ATTRIBUTES (fndecl)
     243            1 :         = tree_cons (cold, NULL_TREE, DECL_ATTRIBUTES (fndecl));
     244            1 :       return;
     245              :     }
     246              : 
     247            0 :   rust_error_at (attr.get_locus (),
     248              :                  "attribute %<cold%> does not accept any arguments");
     249              : }
     250              : 
     251              : void
     252            1 : HIRCompileBase::handle_link_section_attribute_on_fndecl (
     253              :   tree fndecl, const AST::Attribute &attr)
     254              : {
     255            1 :   auto msg_str = Analysis::Attributes::extract_string_literal (attr);
     256              : 
     257            1 :   if (!msg_str.has_value ())
     258              :     {
     259            0 :       rust_error_at (attr.get_locus (),
     260              :                      "malformed %<link_section%> attribute input");
     261            0 :       return;
     262              :     }
     263              : 
     264            1 :   if (decl_section_name (fndecl))
     265              :     {
     266            0 :       rust_warning_at (attr.get_locus (), 0, "section name redefined");
     267              :     }
     268              : 
     269            1 :   set_decl_section_name (fndecl, msg_str->c_str ());
     270            1 : }
     271              : 
     272              : void
     273            1 : HIRCompileBase::handle_no_mangle_attribute_on_fndecl (
     274              :   tree fndecl, const AST::Attribute &attr)
     275              : {
     276            1 :   if (attr.has_attr_input ())
     277              :     {
     278            0 :       rust_error_at (attr.get_locus (),
     279              :                      "attribute %<no_mangle%> does not accept any arguments");
     280            0 :       return;
     281              :     }
     282              : 
     283            1 :   DECL_ATTRIBUTES (fndecl)
     284            2 :     = tree_cons (get_identifier (Values::Attributes::NO_MANGLE), NULL_TREE,
     285            1 :                  DECL_ATTRIBUTES (fndecl));
     286              : }
     287              : 
     288              : void
     289            5 : HIRCompileBase::handle_deprecated_attribute_on_fndecl (
     290              :   tree fndecl, const AST::Attribute &attr)
     291              : {
     292            5 :   tree value = NULL_TREE;
     293            5 :   TREE_DEPRECATED (fndecl) = 1;
     294              : 
     295              :   // simple #[deprecated]
     296            5 :   if (!attr.has_attr_input ())
     297              :     return;
     298              : 
     299            4 :   const AST::AttrInput &input = attr.get_attr_input ();
     300            4 :   auto input_type = input.get_attr_input_type ();
     301              : 
     302            4 :   if (input_type == AST::AttrInput::AttrInputType::LITERAL)
     303              :     {
     304              :       // handle #[deprecated = "message"]
     305            1 :       auto &literal
     306            1 :         = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
     307            1 :       const auto &msg_str = literal.get_literal ().as_string ();
     308            1 :       value = build_string (msg_str.size (), msg_str.c_str ());
     309            1 :     }
     310            3 :   else if (input_type == AST::AttrInput::AttrInputType::TOKEN_TREE)
     311              :     {
     312              :       // handle #[deprecated(since = "...", note = "...")]
     313            3 :       const auto &option = static_cast<const AST::DelimTokenTree &> (input);
     314            3 :       AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item ();
     315            7 :       for (const auto &item : meta_item->get_items ())
     316              :         {
     317            4 :           auto converted_item = item->to_meta_name_value_str ();
     318            4 :           if (!converted_item)
     319            0 :             continue;
     320            4 :           auto key_value = converted_item->get_name_value_pair ();
     321            4 :           if (key_value.first.as_string ().compare ("since") == 0)
     322              :             {
     323              :               // valid, but this is handled by Cargo and some third-party
     324              :               // audit tools
     325            2 :               continue;
     326              :             }
     327            2 :           else if (key_value.first.as_string ().compare ("note") == 0)
     328              :             {
     329            1 :               const auto &msg_str = key_value.second;
     330            1 :               if (value)
     331            0 :                 rust_error_at (attr.get_locus (), "multiple %<note%> items");
     332            1 :               value = build_string (msg_str.size (), msg_str.c_str ());
     333              :             }
     334              :           else
     335              :             {
     336            1 :               rust_error_at (attr.get_locus (), ErrorCode::E0541,
     337              :                              "unknown meta item %qs",
     338            1 :                              key_value.first.as_string ().c_str ());
     339              :             }
     340            4 :         }
     341              :     }
     342              : 
     343            4 :   if (value)
     344              :     {
     345            2 :       tree attr_list = build_tree_list (NULL_TREE, value);
     346            2 :       DECL_ATTRIBUTES (fndecl)
     347            4 :         = tree_cons (get_identifier (Values::Attributes::DEPRECATED), attr_list,
     348            2 :                      DECL_ATTRIBUTES (fndecl));
     349              :     }
     350              : }
     351              : 
     352              : void
     353          943 : HIRCompileBase::handle_inline_attribute_on_fndecl (tree fndecl,
     354              :                                                    const AST::Attribute &attr)
     355              : {
     356              :   // simple #[inline]
     357          943 :   if (!attr.has_attr_input ())
     358              :     {
     359          938 :       DECL_DECLARED_INLINE_P (fndecl) = 1;
     360          940 :       return;
     361              :     }
     362              : 
     363            5 :   const AST::AttrInput &input = attr.get_attr_input ();
     364            5 :   bool is_token_tree
     365            5 :     = input.get_attr_input_type () == AST::AttrInput::AttrInputType::TOKEN_TREE;
     366            5 :   rust_assert (is_token_tree);
     367            5 :   const auto &option = static_cast<const AST::DelimTokenTree &> (input);
     368            5 :   AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item ();
     369            5 :   if (meta_item->get_items ().size () != 1)
     370              :     {
     371            2 :       rich_location rich_locus (line_table, attr.get_locus ());
     372            2 :       rich_locus.add_fixit_replace ("expected one argument");
     373            2 :       rust_error_at (rich_locus, ErrorCode::E0534,
     374              :                      "invalid number of arguments");
     375            2 :       return;
     376            2 :     }
     377              : 
     378            3 :   const std::string inline_option
     379            3 :     = meta_item->get_items ().at (0)->as_string ();
     380              : 
     381              :   // we only care about NEVER and ALWAYS else its an error
     382            3 :   bool is_always = inline_option.compare ("always") == 0;
     383            3 :   bool is_never = inline_option.compare ("never") == 0;
     384              : 
     385              :   // #[inline(never)]
     386            3 :   if (is_never)
     387              :     {
     388            1 :       DECL_UNINLINABLE (fndecl) = 1;
     389              :     }
     390              :   // #[inline(always)]
     391            2 :   else if (is_always)
     392              :     {
     393            1 :       DECL_DECLARED_INLINE_P (fndecl) = 1;
     394            1 :       DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"),
     395            1 :                                             NULL, DECL_ATTRIBUTES (fndecl));
     396              :     }
     397              :   else
     398              :     {
     399            1 :       rich_location rich_locus (line_table, attr.get_locus ());
     400            1 :       rich_locus.add_fixit_replace ("unknown inline option");
     401            1 :       rust_error_at (rich_locus, ErrorCode::E0535,
     402              :                      "invalid argument, %<inline%> attribute only accepts "
     403              :                      "%<always%> or %<never%>");
     404            1 :     }
     405            3 : }
     406              : 
     407              : void
     408         1089 : HIRCompileBase::handle_must_use_attribute_on_fndecl (tree fndecl,
     409              :                                                      const AST::Attribute &attr)
     410              : {
     411         1089 :   tree nodiscard = get_identifier ("nodiscard");
     412         1089 :   tree value = NULL_TREE;
     413              : 
     414         1089 :   if (attr.has_attr_input ())
     415              :     {
     416           15 :       auto msg_str = Analysis::Attributes::extract_string_literal (attr);
     417           15 :       rust_assert (msg_str.has_value ());
     418              : 
     419           15 :       tree message = build_string (msg_str->size (), msg_str->c_str ());
     420              : 
     421           15 :       value = tree_cons (nodiscard, message, NULL_TREE);
     422           15 :     }
     423              : 
     424         1089 :   DECL_ATTRIBUTES (fndecl)
     425         1089 :     = tree_cons (nodiscard, value, DECL_ATTRIBUTES (fndecl));
     426         1089 : }
     427              : 
     428              : void
     429        13797 : HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
     430              : {
     431        13797 :   tree abi_tree = NULL_TREE;
     432              : 
     433        13797 :   switch (abi)
     434              :     {
     435        13796 :     case Rust::ABI::RUST:
     436        13796 :     case Rust::ABI::INTRINSIC:
     437        13796 :     case Rust::ABI::C:
     438        13796 :     case Rust::ABI::CDECL:
     439              :       // `decl_attributes` function (not the macro) has the side-effect of
     440              :       // actually switching the codegen backend to use the ABI we annotated.
     441              :       // However, since `cdecl` is the default ABI GCC will be using,
     442              :       // explicitly specifying that ABI will cause GCC to emit a warning
     443              :       // saying the attribute is useless (which is confusing to the user as
     444              :       // the attribute is added by us).
     445        13796 :       DECL_ATTRIBUTES (fndecl)
     446        13796 :         = tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl));
     447              : 
     448        13796 :       return;
     449              : 
     450            0 :     case Rust::ABI::STDCALL:
     451            0 :       abi_tree = get_identifier ("stdcall");
     452              : 
     453            0 :       break;
     454              : 
     455            0 :     case Rust::ABI::FASTCALL:
     456            0 :       abi_tree = get_identifier ("fastcall");
     457              : 
     458            0 :       break;
     459              : 
     460            0 :     case Rust::ABI::SYSV64:
     461            0 :       abi_tree = get_identifier ("sysv_abi");
     462              : 
     463            0 :       break;
     464              : 
     465            1 :     case Rust::ABI::WIN_64:
     466            1 :       abi_tree = get_identifier ("ms_abi");
     467              : 
     468            1 :       break;
     469              : 
     470              :     default:
     471              :       break;
     472              :     }
     473              : 
     474            1 :   decl_attributes (&fndecl, build_tree_list (abi_tree, NULL_TREE), 0);
     475              : }
     476              : 
     477              : // ported from gcc/c/c-typecheck.c
     478              : //
     479              : // Mark EXP saying that we need to be able to take the
     480              : // address of it; it should not be allocated in a register.
     481              : // Returns true if successful.  ARRAY_REF_P is true if this
     482              : // is for ARRAY_REF construction - in that case we don't want
     483              : // to look through VIEW_CONVERT_EXPR from VECTOR_TYPE to ARRAY_TYPE,
     484              : // it is fine to use ARRAY_REFs for vector subscripts on vector
     485              : // register variables.
     486              : bool
     487        37335 : HIRCompileBase::mark_addressable (tree exp, location_t locus)
     488              : {
     489        37335 :   tree x = exp;
     490              : 
     491        39284 :   while (1)
     492        39284 :     switch (TREE_CODE (x))
     493              :       {
     494            0 :       case VIEW_CONVERT_EXPR:
     495            0 :         if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
     496            0 :             && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
     497              :           return true;
     498            0 :         x = TREE_OPERAND (x, 0);
     499            0 :         break;
     500              : 
     501         1949 :       case COMPONENT_REF:
     502              :         // TODO
     503              :         // if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
     504              :         //   {
     505              :         //     error ("cannot take address of bit-field %qD", TREE_OPERAND (x,
     506              :         //     1)); return false;
     507              :         //   }
     508              : 
     509              :         /* FALLTHRU */
     510         1949 :       case ADDR_EXPR:
     511         1949 :       case ARRAY_REF:
     512         1949 :       case REALPART_EXPR:
     513         1949 :       case IMAGPART_EXPR:
     514         1949 :         x = TREE_OPERAND (x, 0);
     515         1949 :         break;
     516              : 
     517            0 :       case COMPOUND_LITERAL_EXPR:
     518            0 :         TREE_ADDRESSABLE (x) = 1;
     519            0 :         TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (x)) = 1;
     520            0 :         return true;
     521              : 
     522          253 :       case CONSTRUCTOR:
     523          253 :         TREE_ADDRESSABLE (x) = 1;
     524          253 :         return true;
     525              : 
     526        27086 :       case VAR_DECL:
     527        27086 :       case CONST_DECL:
     528        27086 :       case PARM_DECL:
     529        27086 :       case RESULT_DECL:
     530              :         // (we don't have a concept of a "register" declaration)
     531              :         // fallthrough */
     532              : 
     533              :         /* FALLTHRU */
     534        27086 :       case FUNCTION_DECL:
     535        27086 :         TREE_ADDRESSABLE (x) = 1;
     536              : 
     537              :         /* FALLTHRU */
     538              :       default:
     539              :         return true;
     540              :       }
     541              : 
     542              :   return false;
     543              : }
     544              : 
     545              : tree
     546        37357 : HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty)
     547              : {
     548        37357 :   if (expr == error_mark_node)
     549              :     return error_mark_node;
     550              : 
     551        37335 :   if (!mark_addressable (expr, location))
     552            0 :     return error_mark_node;
     553              : 
     554        37335 :   if (ptrty == NULL || ptrty == error_mark_node)
     555        35589 :     ptrty = build_pointer_type (TREE_TYPE (expr));
     556              : 
     557        37335 :   return build_fold_addr_expr_with_type_loc (location, expr, ptrty);
     558              : }
     559              : 
     560              : tree
     561         1187 : HIRCompileBase::compile_constant_expr (
     562              :   Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type,
     563              :   TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path,
     564              :   HIR::Expr &const_value_expr, location_t locus, location_t expr_locus)
     565              : {
     566         1187 :   HIRCompileBase c (ctx);
     567         1187 :   return c.compile_constant_item (coercion_id, resolved_type, expected_type,
     568              :                                   canonical_path, const_value_expr, locus,
     569         1187 :                                   expr_locus);
     570         1187 : }
     571              : 
     572              : tree
     573         1187 : HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
     574              :                                           HIR::Expr &const_value_expr)
     575              : {
     576         1187 :   HIRCompileBase c (ctx);
     577              : 
     578         1187 :   ctx->push_const_context ();
     579              : 
     580         1187 :   HirId expr_id = const_value_expr.get_mappings ().get_hirid ();
     581         1187 :   location_t locus = const_value_expr.get_locus ();
     582         1187 :   tree capacity_expr = HIRCompileBase::compile_constant_expr (
     583         1187 :     ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (),
     584              :     const_value_expr, locus, locus);
     585              : 
     586         1187 :   ctx->pop_const_context ();
     587              : 
     588         1187 :   return fold_expr (capacity_expr);
     589         1187 : }
     590              : 
     591              : tree
     592        14084 : HIRCompileBase::indirect_expression (tree expr, location_t locus)
     593              : {
     594        14084 :   if (expr == error_mark_node)
     595              :     return error_mark_node;
     596              : 
     597        14084 :   return build_fold_indirect_ref_loc (locus, expr);
     598              : }
     599              : 
     600              : void
     601        12821 : HIRCompileBase::compile_function_body (tree fndecl,
     602              :                                        HIR::BlockExpr &function_body,
     603              :                                        TyTy::BaseType *fn_return_ty)
     604              : {
     605        26713 :   for (auto &s : function_body.get_statements ())
     606              :     {
     607        13892 :       auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
     608        13892 :       if (compiled_expr != nullptr)
     609              :         {
     610         4695 :           tree s = convert_to_void (compiled_expr, ICV_STATEMENT);
     611         4695 :           ctx->add_statement (s);
     612              :         }
     613              :     }
     614              : 
     615        12821 :   if (function_body.has_expr ())
     616              :     {
     617        10304 :       location_t locus = function_body.get_final_expr ().get_locus ();
     618        10304 :       tree return_value
     619        10304 :         = CompileExpr::Compile (function_body.get_final_expr (), ctx);
     620              : 
     621              :       // we can only return this if non unit value return type
     622        10304 :       if (!fn_return_ty->is_unit ())
     623              :         {
     624         9187 :           HirId id = function_body.get_mappings ().get_hirid ();
     625         9187 :           location_t lvalue_locus = function_body.get_locus ();
     626         9187 :           location_t rvalue_locus = locus;
     627              : 
     628         9187 :           TyTy::BaseType *expected = fn_return_ty;
     629         9187 :           TyTy::BaseType *actual = nullptr;
     630         9187 :           bool ok = ctx->get_tyctx ()->lookup_type (
     631         9187 :             function_body.expr->get_mappings ().get_hirid (), &actual);
     632         9187 :           rust_assert (ok);
     633              : 
     634         9187 :           return_value = coercion_site (id, return_value, actual, expected,
     635              :                                         lvalue_locus, rvalue_locus);
     636              : 
     637         9187 :           tree return_stmt
     638         9187 :             = Backend::return_statement (fndecl, return_value, locus);
     639         9187 :           ctx->add_statement (return_stmt);
     640              :         }
     641              :       else
     642              :         {
     643              :           // just add the stmt expression
     644         1117 :           ctx->add_statement (return_value);
     645              : 
     646              :           // now just return unit expression
     647         1117 :           tree unit_expr = unit_expression (locus);
     648         1117 :           tree return_stmt
     649         1117 :             = Backend::return_statement (fndecl, unit_expr, locus);
     650         1117 :           ctx->add_statement (return_stmt);
     651              :         }
     652              :     }
     653         2517 :   else if (fn_return_ty->is_unit ())
     654              :     {
     655              :       // we can only do this if the function is of unit type otherwise other
     656              :       // errors should have occurred
     657         2317 :       location_t locus = function_body.get_locus ();
     658         2317 :       tree return_value = unit_expression (locus);
     659         2317 :       tree return_stmt
     660         2317 :         = Backend::return_statement (fndecl, return_value, locus);
     661         2317 :       ctx->add_statement (return_stmt);
     662              :     }
     663        12821 : }
     664              : 
     665              : static ABI
     666        12730 : get_abi (const AST::AttrVec &outer_attrs,
     667              :          const HIR::FunctionQualifiers &qualifiers)
     668              : {
     669        12730 :   bool is_proc_macro = std::any_of (outer_attrs.cbegin (), outer_attrs.cend (),
     670        15610 :                                     [] (const AST::Attribute &attr) {
     671        15610 :                                       auto path = attr.get_path ().as_string ();
     672        15610 :                                       return path == "proc_macro"
     673        15610 :                                              || path == "proc_macro_derive"
     674        31220 :                                              || path == "proc_macro_attribute";
     675        15610 :                                     });
     676              : 
     677        12730 :   return is_proc_macro ? ABI::CDECL : qualifiers.get_abi ();
     678              : }
     679              : 
     680              : tree
     681        12730 : HIRCompileBase::compile_function (
     682              :   bool is_root_item, const std::string &fn_name,
     683              :   tl::optional<HIR::SelfParam> &self_param,
     684              :   std::vector<HIR::FunctionParam> &function_params,
     685              :   const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
     686              :   AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body,
     687              :   const Resolver::CanonicalPath &canonical_path, TyTy::FnType *fntype)
     688              : {
     689        12730 :   tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
     690        12730 :   std::string ir_symbol_name
     691        12730 :     = canonical_path.get () + fntype->subst_as_string ();
     692              : 
     693        12730 :   rust_debug_loc (locus, "--> Compiling [%s] - %s", ir_symbol_name.c_str (),
     694        12730 :                   fntype->get_name ().c_str ());
     695              : 
     696              :   // we don't mangle the main fn since we haven't implemented the main shim
     697         3727 :   bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item
     698        16455 :                     && canonical_path.size () <= 2;
     699         3724 :   if (is_main_fn)
     700              :     {
     701         3724 :       rust_assert (!main_identifier_node);
     702              :       /* So that 'MAIN_NAME_P' works.  */
     703         3724 :       main_identifier_node = get_identifier (ir_symbol_name.c_str ());
     704              :     }
     705              :   // Local name because fn_name is not mutable.
     706        12730 :   std::string asm_name = fn_name;
     707              : 
     708              :   // conditionally mangle the function name
     709        12730 :   bool should_mangle = true;
     710              : 
     711        28340 :   auto get_export_name = [] (AST::Attribute &attr) {
     712        15610 :     return attr.get_path ().as_string () == Values::Attributes::EXPORT_NAME;
     713              :   };
     714        12730 :   auto export_name_attr
     715        12730 :     = std::find_if (outer_attrs.begin (), outer_attrs.end (), get_export_name);
     716              : 
     717        12730 :   tl::optional<std::string> backend_asm_name = tl::nullopt;
     718              : 
     719        12730 :   if (export_name_attr != outer_attrs.end ())
     720              :     {
     721            1 :       asm_name
     722            1 :         = Analysis::Attributes::extract_string_literal (*export_name_attr)
     723            1 :             .value (); // Checked within attribute checker
     724            1 :       backend_asm_name = asm_name;
     725            1 :       should_mangle = false;
     726              :     }
     727              : 
     728        12730 :   unsigned int flags = 0;
     729        12730 :   tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name,
     730        12730 :                                    backend_asm_name, flags, locus);
     731              : 
     732        12730 :   setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
     733              :                 visibility, qualifiers, outer_attrs);
     734        12730 :   setup_abi_options (fndecl, get_abi (outer_attrs, qualifiers));
     735              : 
     736        12730 :   should_mangle &= should_mangle_item (fndecl);
     737        12730 :   if (!is_main_fn && should_mangle)
     738         9004 :     asm_name = ctx->mangle_item (fntype, canonical_path);
     739        12730 :   SET_DECL_ASSEMBLER_NAME (fndecl,
     740              :                            get_identifier_with_length (asm_name.data (),
     741              :                                                        asm_name.length ()));
     742              : 
     743              :   // insert into the context
     744        12730 :   ctx->insert_function_decl (fntype, fndecl);
     745              : 
     746              :   // setup the params
     747        12730 :   TyTy::BaseType *tyret = fntype->get_return_type ();
     748        12730 :   std::vector<Bvariable *> param_vars;
     749        12730 :   if (self_param)
     750              :     {
     751        10836 :       rust_assert (fntype->is_method ());
     752         5418 :       TyTy::BaseType *self_tyty_lookup = fntype->get_self_type ();
     753              : 
     754         5418 :       tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
     755         5418 :       Bvariable *compiled_self_param
     756         5418 :         = CompileSelfParam::compile (ctx, fndecl, self_param.value (),
     757         5418 :                                      self_type, self_param->get_locus ());
     758              : 
     759         5418 :       param_vars.push_back (compiled_self_param);
     760         5418 :       ctx->insert_var_decl (self_param->get_mappings ().get_hirid (),
     761              :                             compiled_self_param);
     762              :     }
     763              : 
     764              :   // offset from + 1 for the TyTy::FnType being used when this is a method to
     765              :   // skip over Self on the FnType
     766        12730 :   bool is_method = self_param.has_value ();
     767        12730 :   size_t i = is_method ? 1 : 0;
     768        19009 :   for (auto &referenced_param : function_params)
     769              :     {
     770         6279 :       auto &tyty_param = fntype->param_at (i++);
     771         6279 :       auto param_tyty = tyty_param.get_type ();
     772         6279 :       auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty);
     773              : 
     774         6279 :       location_t param_locus = referenced_param.get_locus ();
     775         6279 :       Bvariable *compiled_param_var
     776         6279 :         = CompileFnParam::compile (ctx, fndecl, referenced_param,
     777         6279 :                                    compiled_param_type, param_locus);
     778              : 
     779         6279 :       param_vars.push_back (compiled_param_var);
     780              : 
     781         6279 :       const HIR::Pattern &param_pattern = referenced_param.get_param_name ();
     782         6279 :       ctx->insert_var_decl (param_pattern.get_mappings ().get_hirid (),
     783              :                             compiled_param_var);
     784              :     }
     785              : 
     786        12730 :   if (!Backend::function_set_parameters (fndecl, param_vars))
     787            0 :     return error_mark_node;
     788              : 
     789        12730 :   tree enclosing_scope = NULL_TREE;
     790        12730 :   location_t start_location = function_body->get_locus ();
     791        12730 :   location_t end_location = function_body->get_end_locus ();
     792              : 
     793        12730 :   tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
     794              :                                     start_location, end_location);
     795        12730 :   ctx->push_block (code_block);
     796              : 
     797        12730 :   Bvariable *return_address = nullptr;
     798        12730 :   tree return_type = TyTyResolveCompile::compile (ctx, tyret);
     799              : 
     800        12730 :   bool address_is_taken = false;
     801        12730 :   tree ret_var_stmt = NULL_TREE;
     802        12730 :   return_address
     803        12730 :     = Backend::temporary_variable (fndecl, code_block, return_type, NULL,
     804              :                                    address_is_taken, locus, &ret_var_stmt);
     805              : 
     806        12730 :   ctx->add_statement (ret_var_stmt);
     807              : 
     808        12730 :   ctx->push_fn (fndecl, return_address, tyret);
     809        12730 :   compile_function_body (fndecl, *function_body, tyret);
     810        12730 :   tree bind_tree = ctx->pop_block ();
     811              : 
     812        12730 :   gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
     813        12730 :   DECL_SAVED_TREE (fndecl) = bind_tree;
     814              : 
     815        12730 :   ctx->pop_fn ();
     816        12730 :   ctx->push_function (fndecl);
     817              : 
     818        12730 :   if (DECL_DECLARED_CONSTEXPR_P (fndecl))
     819              :     {
     820          664 :       maybe_save_constexpr_fundef (fndecl);
     821              :     }
     822              : 
     823              :   return fndecl;
     824        12731 : }
     825              : 
     826              : tree
     827         1743 : HIRCompileBase::compile_constant_item (
     828              :   HirId coercion_id, TyTy::BaseType *resolved_type,
     829              :   TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path,
     830              :   HIR::Expr &const_value_expr, location_t locus, location_t expr_locus)
     831              : {
     832         1743 :   const std::string &ident = canonical_path.get ();
     833              : 
     834         1743 :   tree type = TyTyResolveCompile::compile (ctx, resolved_type);
     835         1743 :   tree const_type = build_qualified_type (type, TYPE_QUAL_CONST);
     836              : 
     837         1743 :   tree actual_type = TyTyResolveCompile::compile (ctx, expected_type);
     838         1743 :   tree actual_const_type = build_qualified_type (actual_type, TYPE_QUAL_CONST);
     839              : 
     840         1743 :   bool is_block_expr
     841         1743 :     = const_value_expr.get_expression_type () == HIR::Expr::ExprType::Block;
     842              : 
     843              :   // in order to compile a block expr we want to reuse as much existing
     844              :   // machineary that we already have. This means the best approach is to
     845              :   // make a _fake_ function with a block so it can hold onto temps then
     846              :   // use our constexpr code to fold it completely or error_mark_node
     847         1743 :   Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
     848         1743 :   tree compiled_fn_type = Backend::function_type (
     849         1743 :     receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL,
     850              :     locus);
     851         1743 :   tree fndecl
     852         1743 :     = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus);
     853         1743 :   TREE_READONLY (fndecl) = 1;
     854              : 
     855         1743 :   tree enclosing_scope = NULL_TREE;
     856         1743 :   location_t start_location = const_value_expr.get_locus ();
     857         1743 :   location_t end_location = const_value_expr.get_locus ();
     858         1743 :   if (is_block_expr)
     859              :     {
     860           39 :       HIR::BlockExpr &function_body
     861              :         = static_cast<HIR::BlockExpr &> (const_value_expr);
     862           39 :       start_location = function_body.get_locus ();
     863           39 :       end_location = function_body.get_end_locus ();
     864              :     }
     865              : 
     866         1743 :   tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
     867              :                                     start_location, end_location);
     868         1743 :   ctx->push_block (code_block);
     869              : 
     870         1743 :   bool address_is_taken = false;
     871         1743 :   tree ret_var_stmt = NULL_TREE;
     872         1743 :   Bvariable *return_address
     873         1743 :     = Backend::temporary_variable (fndecl, code_block, const_type, NULL,
     874              :                                    address_is_taken, locus, &ret_var_stmt);
     875              : 
     876         1743 :   ctx->add_statement (ret_var_stmt);
     877         1743 :   ctx->push_fn (fndecl, return_address, resolved_type);
     878              : 
     879         1743 :   if (is_block_expr)
     880              :     {
     881           39 :       HIR::BlockExpr &function_body
     882              :         = static_cast<HIR::BlockExpr &> (const_value_expr);
     883           39 :       compile_function_body (fndecl, function_body, resolved_type);
     884              :     }
     885              :   else
     886              :     {
     887         1704 :       tree value = CompileExpr::Compile (const_value_expr, ctx);
     888              : 
     889         1704 :       tree return_expr
     890         1704 :         = Backend::return_statement (fndecl, value,
     891         1704 :                                      const_value_expr.get_locus ());
     892         1704 :       ctx->add_statement (return_expr);
     893              :     }
     894              : 
     895         1743 :   tree bind_tree = ctx->pop_block ();
     896              : 
     897         1743 :   gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
     898         1743 :   DECL_SAVED_TREE (fndecl) = bind_tree;
     899         1743 :   DECL_DECLARED_CONSTEXPR_P (fndecl) = 1;
     900         1743 :   maybe_save_constexpr_fundef (fndecl);
     901              : 
     902         1743 :   ctx->pop_fn ();
     903              : 
     904              :   // lets fold it into a call expr
     905         1743 :   tree call = build_call_array_loc (locus, const_type, fndecl, 0, NULL);
     906         1743 :   tree folded_expr = fold_expr (call);
     907              : 
     908              :   // coercion site
     909         1743 :   tree coerced = coercion_site (coercion_id, folded_expr, resolved_type,
     910              :                                 expected_type, locus, expr_locus);
     911              : 
     912         1743 :   return named_constant_expression (actual_const_type, ident, coerced, locus);
     913         1743 : }
     914              : 
     915              : tree
     916         1743 : HIRCompileBase::named_constant_expression (tree type_tree,
     917              :                                            const std::string &name,
     918              :                                            tree const_val, location_t location)
     919              : {
     920         1743 :   if (type_tree == error_mark_node || const_val == error_mark_node)
     921              :     return error_mark_node;
     922              : 
     923         1731 :   tree name_tree = get_identifier_with_length (name.data (), name.length ());
     924         1731 :   tree decl = build_decl (location, CONST_DECL, name_tree, type_tree);
     925         1731 :   DECL_INITIAL (decl) = const_val;
     926         1731 :   TREE_CONSTANT (decl) = 1;
     927         1731 :   TREE_READONLY (decl) = 1;
     928              : 
     929         1731 :   rust_preserve_from_gc (decl);
     930         1731 :   return decl;
     931              : }
     932              : 
     933              : tree
     934         3920 : HIRCompileBase::resolve_method_address (TyTy::FnType *fntype,
     935              :                                         TyTy::BaseType *receiver,
     936              :                                         location_t expr_locus)
     937              : {
     938         3920 :   rust_debug_loc (expr_locus, "resolve_method_address for %s and receiver %s",
     939         7840 :                   fntype->debug_str ().c_str (),
     940         3920 :                   receiver->debug_str ().c_str ());
     941              : 
     942         3920 :   DefId id = fntype->get_id ();
     943         3920 :   rust_assert (id != UNKNOWN_DEFID);
     944              : 
     945              :   // Now we can try and resolve the address since this might be a forward
     946              :   // declared function, generic function which has not be compiled yet or
     947              :   // its an not yet trait bound function
     948         3920 :   if (auto resolved_item = ctx->get_mappings ().lookup_defid (id))
     949              :     {
     950         3007 :       if (!fntype->has_substitutions_defined ())
     951         3007 :         return CompileItem::compile (*resolved_item, ctx);
     952              : 
     953          744 :       return CompileItem::compile (*resolved_item, ctx, fntype);
     954              :     }
     955              : 
     956              :   // it might be resolved to a trait item
     957          913 :   HIR::TraitItem *trait_item
     958          913 :     = ctx->get_mappings ().lookup_trait_item_defid (id).value ();
     959          913 :   HIR::Trait *trait = ctx->get_mappings ().lookup_trait_item_mapping (
     960          913 :     trait_item->get_mappings ().get_hirid ());
     961              : 
     962          913 :   Resolver::TraitReference *trait_ref
     963          913 :     = &Resolver::TraitReference::error_node ();
     964          913 :   bool ok = ctx->get_tyctx ()->lookup_trait_reference (
     965          913 :     trait->get_mappings ().get_defid (), &trait_ref);
     966          913 :   rust_assert (ok);
     967              : 
     968              :   // the type resolver can only resolve type bounds to their trait
     969              :   // item so its up to us to figure out if this path should resolve
     970              :   // to an trait-impl-block-item or if it can be defaulted to the
     971              :   // trait-impl-item's definition
     972          913 :   const HIR::PathIdentSegment segment (trait_item->trait_identifier ());
     973          913 :   auto root = receiver->get_root ();
     974          913 :   auto candidates
     975          913 :     = Resolver::PathProbeImplTrait::Probe (root, segment, trait_ref);
     976          913 :   if (candidates.size () == 0)
     977              :     {
     978              :       // this means we are defaulting back to the trait_item if
     979              :       // possible
     980          131 :       Resolver::TraitItemReference *trait_item_ref = nullptr;
     981          131 :       bool ok = trait_ref->lookup_hir_trait_item (*trait_item, &trait_item_ref);
     982          131 :       rust_assert (ok);                             // found
     983          131 :       rust_assert (trait_item_ref->is_optional ()); // has definition
     984              : 
     985              :       // FIXME tl::optional means it has a definition and an associated
     986              :       // block which can be a default implementation, if it does not
     987              :       // contain an implementation we should actually return
     988              :       // error_mark_node
     989              : 
     990          131 :       return CompileTraitItem::Compile (trait_item_ref->get_hir_trait_item (),
     991              :                                         ctx, fntype, true, expr_locus);
     992              :     }
     993              : 
     994          782 :   const Resolver::PathProbeCandidate *selectedCandidate = nullptr;
     995          782 :   rust_debug_loc (expr_locus, "resolved to %lu candidates",
     996          782 :                   (unsigned long) candidates.size ());
     997              : 
     998              :   // filter for the possible case of non fn type items
     999          782 :   std::set<Resolver::PathProbeCandidate> filteredFunctionCandidates;
    1000         1603 :   for (auto &candidate : candidates)
    1001              :     {
    1002          821 :       bool is_fntype = candidate.ty->get_kind () == TyTy::TypeKind::FNDEF;
    1003          821 :       if (!is_fntype)
    1004            0 :         continue;
    1005              : 
    1006          821 :       filteredFunctionCandidates.insert (candidate);
    1007              :     }
    1008              : 
    1009              :   // look for the exact fntype
    1010          783 :   for (auto &candidate : filteredFunctionCandidates)
    1011              :     {
    1012          783 :       if (filteredFunctionCandidates.size () == 1)
    1013              :         {
    1014              :           selectedCandidate = &candidate;
    1015              :           break;
    1016              :         }
    1017              : 
    1018           40 :       bool compatable
    1019           40 :         = Resolver::types_compatable (TyTy::TyWithLocation (candidate.ty),
    1020           40 :                                       TyTy::TyWithLocation (fntype), expr_locus,
    1021              :                                       false);
    1022              : 
    1023           80 :       rust_debug_loc (candidate.locus, "candidate: %s vs %s compatable=%s",
    1024           80 :                       candidate.ty->debug_str ().c_str (),
    1025           40 :                       fntype->debug_str ().c_str (),
    1026              :                       compatable ? "true" : "false");
    1027              : 
    1028           40 :       if (compatable)
    1029              :         {
    1030              :           selectedCandidate = &candidate;
    1031              :           break;
    1032              :         }
    1033              :     }
    1034              : 
    1035              :   // FIXME eventually this should just return error mark node when we support
    1036              :   // going through all the passes
    1037          782 :   rust_assert (selectedCandidate != nullptr);
    1038              : 
    1039              :   // lets compile it
    1040          782 :   const Resolver::PathProbeCandidate &candidate = *selectedCandidate;
    1041          782 :   rust_assert (candidate.is_impl_candidate ());
    1042          782 :   rust_assert (candidate.ty->get_kind () == TyTy::TypeKind::FNDEF);
    1043          782 :   TyTy::FnType *candidate_call = static_cast<TyTy::FnType *> (candidate.ty);
    1044          782 :   HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
    1045              : 
    1046          782 :   TyTy::BaseType *monomorphized = candidate_call;
    1047          782 :   if (candidate_call->needs_generic_substitutions ())
    1048              :     {
    1049          102 :       TyTy::BaseType *infer_impl_call
    1050          102 :         = candidate_call->infer_substitions (expr_locus);
    1051          102 :       monomorphized
    1052          102 :         = Resolver::unify_site (fntype->get_ref (),
    1053          102 :                                 TyTy::TyWithLocation (infer_impl_call),
    1054          102 :                                 TyTy::TyWithLocation (fntype), expr_locus);
    1055              :     }
    1056              : 
    1057          782 :   return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
    1058         1695 : }
    1059              : 
    1060              : tree
    1061         6613 : HIRCompileBase::unit_expression (location_t locus)
    1062              : {
    1063         6613 :   tree unit_type = TyTyResolveCompile::get_unit_type (ctx);
    1064         6613 :   return Backend::constructor_expression (unit_type, false, {}, -1, locus);
    1065              : }
    1066              : 
    1067              : } // namespace Compile
    1068              : } // namespace Rust
        

Generated by: LCOV version 2.4-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.