diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h new file mode 100644 index 000000000000..1eba011c6fac --- /dev/null +++ b/gcc/rust/backend/rust-compile-extern.h @@ -0,0 +1,150 @@ +// Copyright (C) 2020 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 +// . + +#ifndef RUST_COMPILE_EXTERN_ITEM +#define RUST_COMPILE_EXTERN_ITEM + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-implitem.h" +#include "rust-compile-var-decl.h" +#include "rust-compile-stmt.h" +#include "rust-compile-expr.h" +#include "rust-compile-fnparam.h" + +namespace Rust { +namespace Compile { + +class CompileExternItem : public HIRCompileBase +{ + using Rust::Compile::HIRCompileBase::visit; + +public: + static void compile (HIR::ExternalItem *item, Context *ctx, + bool compile_fns = true, + TyTy::BaseType *concrete = nullptr) + { + CompileExternItem compiler (ctx, compile_fns, concrete); + item->accept_vis (compiler); + } + + void visit (HIR::ExternalStaticItem &item) override + { + 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; + + Btype *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); + } + + void visit (HIR::ExternalFunctionItem &function) override + { + if (!compile_fns) + return; + + 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 (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 (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. + Bfunction *lookup = nullptr; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + Bfunction *dummy = nullptr; + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) + ctx->insert_function_decl (fntype->get_ty_ref (), lookup, fntype); + + return; + } + } + + if (fntype->has_subsititions_defined ()) + { + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + + ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + + const unsigned int flags + = Backend::function_is_declaration | Backend::function_is_visible; + + std::string ir_symbol_name = function.get_item_name (); + // FIXME this assumes C ABI + std::string asm_name = function.get_item_name (); + + Bfunction *fndecl + = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, + asm_name, flags, function.get_locus ()); + ctx->insert_function_decl (fntype->get_ty_ref (), fndecl, fntype); + } + +private: + CompileExternItem (Context *ctx, bool compile_fns, TyTy::BaseType *concrete) + : HIRCompileBase (ctx), compile_fns (compile_fns), concrete (concrete) + {} + + bool compile_fns; + TyTy::BaseType *concrete; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_EXTERN_ITEM diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index eacfda90a79c..a6bc7f3f73bf 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -26,6 +26,7 @@ #include "rust-compile-stmt.h" #include "rust-compile-expr.h" #include "rust-compile-fnparam.h" +#include "rust-compile-extern.h" namespace Rust { namespace Compile { @@ -274,6 +275,14 @@ class CompileItem : public HIRCompileBase compile_fns); } + void visit (HIR::ExternBlock &extern_block) override + { + for (auto &item : extern_block.get_extern_items ()) + { + CompileExternItem::compile (item.get (), ctx, compile_fns, concrete); + } + } + private: CompileItem (Context *ctx, bool compile_fns, TyTy::BaseType *concrete) : HIRCompileBase (ctx), compile_fns (compile_fns), concrete (concrete)