(root)/
gcc-13.2.0/
gcc/
rust/
backend/
rust-compile-extern.h
       1  // Copyright (C) 2020-2023 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  #ifndef RUST_COMPILE_EXTERN_ITEM
      20  #define RUST_COMPILE_EXTERN_ITEM
      21  
      22  #include "rust-compile-base.h"
      23  #include "rust-compile-intrinsic.h"
      24  
      25  namespace Rust {
      26  namespace Compile {
      27  
      28  class CompileExternItem : public HIRCompileBase,
      29  			  public HIR::HIRExternalItemVisitor
      30  {
      31  public:
      32    static tree compile (HIR::ExternalItem *item, Context *ctx,
      33  		       TyTy::BaseType *concrete = nullptr,
      34  		       bool is_query_mode = false,
      35  		       Location ref_locus = Location ())
      36    {
      37      CompileExternItem compiler (ctx, concrete, ref_locus);
      38      item->accept_vis (compiler);
      39  
      40      if (is_query_mode && compiler.reference == error_mark_node)
      41        rust_internal_error_at (ref_locus, "failed to compile extern item: %s",
      42  			      item->as_string ().c_str ());
      43  
      44      return compiler.reference;
      45    }
      46  
      47    void visit (HIR::ExternalStaticItem &item) override
      48    {
      49      // check if its already been compiled
      50      Bvariable *lookup = ctx->get_backend ()->error_variable ();
      51      if (ctx->lookup_var_decl (item.get_mappings ().get_hirid (), &lookup))
      52        {
      53  	reference = ctx->get_backend ()->var_expression (lookup, ref_locus);
      54  	return;
      55        }
      56  
      57      TyTy::BaseType *resolved_type = nullptr;
      58      bool ok = ctx->get_tyctx ()->lookup_type (item.get_mappings ().get_hirid (),
      59  					      &resolved_type);
      60      rust_assert (ok);
      61  
      62      std::string name = item.get_item_name ();
      63      // FIXME this is assuming C ABI
      64      std::string asm_name = name;
      65  
      66      tree type = TyTyResolveCompile::compile (ctx, resolved_type);
      67      bool is_external = true;
      68      bool is_hidden = false;
      69      bool in_unique_section = false;
      70  
      71      Bvariable *static_global
      72        = ctx->get_backend ()->global_variable (name, asm_name, type, is_external,
      73  					      is_hidden, in_unique_section,
      74  					      item.get_locus ());
      75      ctx->insert_var_decl (item.get_mappings ().get_hirid (), static_global);
      76      ctx->push_var (static_global);
      77  
      78      reference = ctx->get_backend ()->var_expression (static_global, ref_locus);
      79    }
      80  
      81    void visit (HIR::ExternalFunctionItem &function) override
      82    {
      83      TyTy::BaseType *fntype_tyty;
      84      if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
      85  					 &fntype_tyty))
      86        {
      87  	rust_fatal_error (function.get_locus (),
      88  			  "failed to lookup function type");
      89  	return;
      90        }
      91  
      92      rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
      93      TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
      94      if (fntype->has_subsititions_defined ())
      95        {
      96  	// we cant do anything for this only when it is used and a concrete type
      97  	// is given
      98  	if (concrete == nullptr)
      99  	  return;
     100  	else
     101  	  {
     102  	    rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
     103  	    fntype = static_cast<TyTy::FnType *> (concrete);
     104  	  }
     105        }
     106  
     107      // items can be forward compiled which means we may not need to invoke this
     108      // code. We might also have already compiled this generic function as well.
     109      tree lookup = NULL_TREE;
     110      if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
     111  				   fntype->get_id (), fntype))
     112        {
     113  	reference = address_expression (lookup, ref_locus);
     114  	return;
     115        }
     116  
     117      if (fntype->has_subsititions_defined ())
     118        {
     119  	// override the Hir Lookups for the substituions in this context
     120  	fntype->override_context ();
     121        }
     122  
     123      if (fntype->get_abi () == ABI::INTRINSIC)
     124        {
     125  	Intrinsics compile (ctx);
     126  	tree fndecl = compile.compile (fntype);
     127  	ctx->insert_function_decl (fntype, fndecl);
     128  	return;
     129        }
     130  
     131      tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
     132      std::string ir_symbol_name = function.get_item_name ();
     133      std::string asm_name = function.get_item_name ();
     134      if (fntype->get_abi () == ABI::RUST)
     135        {
     136  	// then we need to get the canonical path of it and mangle it
     137  	const Resolver::CanonicalPath *canonical_path = nullptr;
     138  	bool ok = ctx->get_mappings ()->lookup_canonical_path (
     139  	  function.get_mappings ().get_nodeid (), &canonical_path);
     140  	rust_assert (ok);
     141  
     142  	ir_symbol_name = canonical_path->get () + fntype->subst_as_string ();
     143  	asm_name = ctx->mangle_item (fntype, *canonical_path);
     144        }
     145  
     146      const unsigned int flags = Backend::function_is_declaration;
     147      tree fndecl
     148        = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name,
     149  				       asm_name, flags, function.get_locus ());
     150      TREE_PUBLIC (fndecl) = 1;
     151      setup_abi_options (fndecl, fntype->get_abi ());
     152  
     153      ctx->insert_function_decl (fntype, fndecl);
     154  
     155      reference = address_expression (fndecl, ref_locus);
     156    }
     157  
     158  private:
     159    CompileExternItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus)
     160      : HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node),
     161        ref_locus (ref_locus)
     162    {}
     163  
     164    TyTy::BaseType *concrete;
     165    tree reference;
     166    Location ref_locus;
     167  };
     168  
     169  } // namespace Compile
     170  } // namespace Rust
     171  
     172  #endif // RUST_COMPILE_EXTERN_ITEM