diff options
Diffstat (limited to 'gcc/rust/backend/rust-compile-extern.h')
-rw-r--r-- | gcc/rust/backend/rust-compile-extern.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h new file mode 100644 index 0000000..45a507e --- /dev/null +++ b/gcc/rust/backend/rust-compile-extern.h @@ -0,0 +1,172 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_EXTERN_ITEM +#define RUST_COMPILE_EXTERN_ITEM + +#include "rust-compile-base.h" +#include "rust-compile-intrinsic.h" + +namespace Rust { +namespace Compile { + +class CompileExternItem : public HIRCompileBase, + public HIR::HIRExternalItemVisitor +{ +public: + static tree compile (HIR::ExternalItem *item, Context *ctx, + TyTy::BaseType *concrete = nullptr, + bool is_query_mode = false, + Location ref_locus = Location ()) + { + CompileExternItem compiler (ctx, concrete, ref_locus); + item->accept_vis (compiler); + + if (is_query_mode && compiler.reference == error_mark_node) + rust_internal_error_at (ref_locus, "failed to compile extern item: %s", + item->as_string ().c_str ()); + + return compiler.reference; + } + + void visit (HIR::ExternalStaticItem &item) override + { + // check if its already been compiled + Bvariable *lookup = ctx->get_backend ()->error_variable (); + if (ctx->lookup_var_decl (item.get_mappings ().get_hirid (), &lookup)) + { + reference = ctx->get_backend ()->var_expression (lookup, ref_locus); + return; + } + + TyTy::BaseType *resolved_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type (item.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + std::string name = item.get_item_name (); + // FIXME this is assuming C ABI + std::string asm_name = name; + + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + bool is_external = true; + bool is_hidden = false; + bool in_unique_section = false; + + Bvariable *static_global + = ctx->get_backend ()->global_variable (name, asm_name, type, is_external, + is_hidden, in_unique_section, + item.get_locus ()); + ctx->insert_var_decl (item.get_mappings ().get_hirid (), static_global); + ctx->push_var (static_global); + + reference = ctx->get_backend ()->var_expression (static_global, ref_locus); + } + + void visit (HIR::ExternalFunctionItem &function) override + { + TyTy::BaseType *fntype_tyty; + if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), + &fntype_tyty)) + { + rust_fatal_error (function.get_locus (), + "failed to lookup function type"); + return; + } + + rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty); + if (fntype->has_subsititions_defined ()) + { + // we cant do anything for this only when it is used and a concrete type + // is given + if (concrete == nullptr) + return; + else + { + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + fntype = static_cast<TyTy::FnType *> (concrete); + } + } + + // items can be forward compiled which means we may not need to invoke this + // code. We might also have already compiled this generic function as well. + tree lookup = NULL_TREE; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, + fntype->get_id (), fntype)) + { + reference = address_expression (lookup, ref_locus); + return; + } + + if (fntype->has_subsititions_defined ()) + { + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + + if (fntype->get_abi () == ABI::INTRINSIC) + { + Intrinsics compile (ctx); + tree fndecl = compile.compile (fntype); + ctx->insert_function_decl (fntype, fndecl); + return; + } + + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + std::string ir_symbol_name = function.get_item_name (); + std::string asm_name = function.get_item_name (); + if (fntype->get_abi () == ABI::RUST) + { + // then we need to get the canonical path of it and mangle it + const Resolver::CanonicalPath *canonical_path = nullptr; + bool ok = ctx->get_mappings ()->lookup_canonical_path ( + function.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + ir_symbol_name = canonical_path->get () + fntype->subst_as_string (); + asm_name = ctx->mangle_item (fntype, *canonical_path); + } + + const unsigned int flags = Backend::function_is_declaration; + tree fndecl + = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, + asm_name, flags, function.get_locus ()); + TREE_PUBLIC (fndecl) = 1; + setup_abi_options (fndecl, fntype->get_abi ()); + + ctx->insert_function_decl (fntype, fndecl); + + reference = address_expression (fndecl, ref_locus); + } + +private: + CompileExternItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus) + : HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node), + ref_locus (ref_locus) + {} + + TyTy::BaseType *concrete; + tree reference; + Location ref_locus; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_EXTERN_ITEM |