diff options
-rw-r--r-- | gcc/rust/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-base.cc | 92 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-base.h | 6 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-extern.h | 11 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-implitem.h | 17 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-item.h | 24 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 4 | ||||
-rw-r--r-- | gcc/rust/rust-backend.h | 69 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 61 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 20 | ||||
-rw-r--r-- | gcc/rust/util/rust-abi.cc | 64 | ||||
-rw-r--r-- | gcc/rust/util/rust-abi.h (renamed from gcc/rust/rust-abi.h) | 8 |
12 files changed, 214 insertions, 164 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index d2f7962..2d74595 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -75,6 +75,7 @@ GRS_OBJS = \ rust/rust-macro-expand.o \ rust/rust-hir-full-test.o \ rust/rust-hir-map.o \ + rust/rust-abi.o \ rust/rust-ast-lower.o \ rust/rust-ast-lower-pattern.o \ rust/rust-ast-resolve.o \ @@ -99,6 +100,7 @@ GRS_OBJS = \ rust/rust-compile-expr.o \ rust/rust-compile-type.o \ rust/rust-constexpr.o \ + rust/rust-compile-base.o \ $(END) # removed object files from here diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc new file mode 100644 index 0000000..82a38e7 --- /dev/null +++ b/gcc/rust/backend/rust-compile-base.cc @@ -0,0 +1,92 @@ +// 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/>. + +#include "rust-compile-base.h" +#include "stringpool.h" + +namespace Rust { +namespace Compile { + +void +HIRCompileBase::setup_attributes_on_fndecl ( + tree fndecl, bool is_main_entry_point, bool has_visibility, + const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs) +{ + // if its the main fn or pub visibility mark its as DECL_PUBLIC + // please see https://github.com/Rust-GCC/gccrs/pull/137 + if (is_main_entry_point || has_visibility) + { + TREE_PUBLIC (fndecl) = 1; + } + + // is it a const fn + if (qualifiers.is_const ()) + { + TREE_READONLY (fndecl) = 1; + } + + // is it inline? + for (const auto &attr : attrs) + { + bool is_inline = attr.get_path ().as_string ().compare ("inline") == 0; + if (is_inline) + { + DECL_DECLARED_INLINE_P (fndecl) = 1; + + // do we want to force inline regardless of optimisation level? + // https://gcc.gnu.org/onlinedocs/gcc/Inline.html + // + // /* Add attribute "always_inline": */ + // DECL_ATTRIBUTES (fndecl) + // = tree_cons (get_identifier ("always_inline"), NULL, + // DECL_ATTRIBUTES (fndecl)); + } + } +} + +void +HIRCompileBase::setup_abi_options (tree fndecl, ABI abi) +{ + switch (abi) + { + case Rust::ABI::RUST: + case Rust::ABI::INTRINSIC: + case Rust::ABI::C: + case Rust::ABI::CDECL: + DECL_ATTRIBUTES (fndecl) + = tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl)); + break; + + case Rust::ABI::STDCALL: + DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("stdcall"), NULL, + DECL_ATTRIBUTES (fndecl)); + break; + + case Rust::ABI::FASTCALL: + DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("fastcall"), NULL, + DECL_ATTRIBUTES (fndecl)); + + break; + + default: + break; + } +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 902bedc..f318e81 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -71,6 +71,12 @@ protected: tree resolve_deref_adjustment (Resolver::Adjustment &adjustment, tree expression, Location locus); + + static void setup_attributes_on_fndecl ( + tree fndecl, bool is_main_entry_point, bool has_visibility, + const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs); + + static void setup_abi_options (tree fndecl, ABI abi); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index 507865a..143b240 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -125,19 +125,16 @@ public: } tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); - compiled_fn_type - = ctx->get_backend ()->specify_abi_attribute (compiled_fn_type, - fntype->get_abi ()); - - const unsigned int flags - = Backend::function_is_declaration | Backend::function_is_visible; - std::string ir_symbol_name = function.get_item_name (); std::string asm_name = function.get_item_name (); + 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); } diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index d646c83..9320276 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -133,13 +133,6 @@ public: // convert to the actual function type tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); - unsigned int flags = 0; - - // if its the main fn or pub visibility mark its as DECL_PUBLIC - // please see https://github.com/Rust-GCC/gccrs/pull/137 - if (function.has_visibility ()) - flags |= Backend::function_is_visible; - const Resolver::CanonicalPath *canonical_path = nullptr; bool ok = ctx->get_mappings ()->lookup_canonical_path ( function.get_mappings ().get_crate_num (), @@ -150,9 +143,13 @@ public: = canonical_path->get () + fntype->subst_as_string (); std::string asm_name = ctx->mangle_item (fntype, *canonical_path); + unsigned int flags = 0; tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, flags, function.get_locus ()); + setup_attributes_on_fndecl (fndecl, false, function.has_visibility (), + function.get_qualifiers (), + function.get_outer_attrs ()); ctx->insert_function_decl (fntype, fndecl); // setup the params @@ -395,9 +392,7 @@ public: // convert to the actual function type tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); - HIR::TraitFunctionDecl &function = func.get_decl (); - unsigned int flags = 0; const Resolver::CanonicalPath *canonical_path = nullptr; bool ok = ctx->get_mappings ()->lookup_canonical_path ( @@ -408,9 +403,13 @@ public: std::string fn_identifier = canonical_path->get (); std::string asm_name = ctx->mangle_item (fntype, *canonical_path); + unsigned int flags = 0; tree fndecl = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, asm_name, flags, func.get_locus ()); + setup_attributes_on_fndecl (fndecl, false, false, + func.get_decl ().get_qualifiers (), + func.get_outer_attrs ()); ctx->insert_function_decl (fntype, fndecl); // setup the params diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 73f6967..70b5415 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -144,9 +144,9 @@ public: NULL, constant.get_locus ()); tree fndecl - = ctx->get_backend ()->function (compiled_fn_type, ident, "", - Backend::function_read_only, + = ctx->get_backend ()->function (compiled_fn_type, ident, "", 0, constant.get_locus ()); + TREE_READONLY (fndecl) = 1; tree enclosing_scope = NULL_TREE; HIR::BlockExpr *function_body @@ -255,18 +255,6 @@ public: tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); - unsigned int flags = 0; - bool is_main_fn = function.get_function_name ().compare ("main") == 0; - - // if its the main fn or pub visibility mark its as DECL_PUBLIC - // please see https://github.com/Rust-GCC/gccrs/pull/137 - if (is_main_fn || function.has_visibility ()) - flags |= Backend::function_is_visible; - - // is it a const function? - if (function.get_qualifiers ().is_const ()) - flags |= Backend::function_read_only; - const Resolver::CanonicalPath *canonical_path = nullptr; bool ok = ctx->get_mappings ()->lookup_canonical_path ( function.get_mappings ().get_crate_num (), @@ -275,19 +263,25 @@ public: std::string ir_symbol_name = canonical_path->get () + fntype->subst_as_string (); - std::string asm_name = function.get_function_name (); // we don't mangle the main fn since we haven't implemented the main shim // yet + bool is_main_fn = function.get_function_name ().compare ("main") == 0; if (!is_main_fn) { asm_name = ctx->mangle_item (fntype, *canonical_path); } + unsigned int flags = 0; tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, flags, function.get_locus ()); + setup_attributes_on_fndecl (fndecl, is_main_fn, function.has_visibility (), + function.get_qualifiers (), + function.get_outer_attrs ()); + + // insert into the context ctx->insert_function_decl (fntype, fndecl); // setup the params diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index c245a56..5fdf806 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -2262,6 +2262,8 @@ public: } std::vector<FunctionParam> &get_function_params () { return function_params; } + + const FunctionQualifiers &get_qualifiers () const { return qualifiers; } }; // Actual trait item function declaration within traits @@ -2339,6 +2341,8 @@ public: return TraitItemKind::FUNC; } + AST::AttrVec get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method TraitItemFunc *clone_trait_item_impl () const override diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 03b6cb4..2a7691c 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -27,8 +27,6 @@ #include "rust-linemap.h" #include "rust-diagnostics.h" #include "operator.h" -#include "rust-abi.h" - #include "tree.h" extern bool @@ -74,49 +72,6 @@ public: virtual void debug (tree) = 0; virtual void debug (Bvariable *) = 0; - static Rust::ABI get_abi_from_string (const std::string &abi, Location locus) - { - if (abi.compare ("rust") == 0) - return Rust::ABI::C; - else if (abi.compare ("rust-intrinsic") == 0) - return Rust::ABI::INTRINSIC; - else if (abi.compare ("C") == 0) - return Rust::ABI::C; - else if (abi.compare ("cdecl") == 0) - return Rust::ABI::CDECL; - else if (abi.compare ("stdcall") == 0) - return Rust::ABI::STDCALL; - else if (abi.compare ("fastcall") == 0) - return Rust::ABI::FASTCALL; - - rust_error_at (locus, "unknown abi specified"); - - return Rust::ABI::UNKNOWN; - } - - static std::string get_string_from_abi (Rust::ABI abi) - { - switch (abi) - { - case Rust::ABI::RUST: - return "rust"; - case Rust::ABI::INTRINSIC: - return "rust-intrinsic"; - case Rust::ABI::C: - return "C"; - case Rust::ABI::CDECL: - return "cdecl"; - case Rust::ABI::STDCALL: - return "stdcall"; - case Rust::ABI::FASTCALL: - return "fastcall"; - - case Rust::ABI::UNKNOWN: - return "unknown"; - } - return "unknown"; - } - virtual tree get_identifier_node (const std::string &str) = 0; // Types. @@ -681,35 +636,21 @@ public: // Bit flags to pass to the function method. - // Set if the function should be visible outside of the current - // compilation unit. - static const unsigned int function_is_visible = 1 << 0; - // Set if this is a function declaration rather than a definition; // the definition will be in another compilation unit. - static const unsigned int function_is_declaration = 1 << 1; + static const unsigned int function_is_declaration = 1 << 0; // Set if the function should never be inlined because they call // recover and must be visible for correct panic recovery. - static const unsigned int function_is_uninlinable = 1 << 2; + static const unsigned int function_is_uninlinable = 1 << 1; // Set if the function does not return. This is set for the // implementation of panic. - static const unsigned int function_does_not_return = 1 << 3; + static const unsigned int function_does_not_return = 1 << 2; // Set if the function should be put in a unique section if // possible. This is used for field tracking. - static const unsigned int function_in_unique_section = 1 << 4; - - // Set if the function should be available for inlining in the - // backend, but should not be emitted as a standalone function. Any - // call to the function that is not inlined should be treated as a - // call to a function defined in a different compilation unit. This - // is like a C99 function marked inline but not extern. - static const unsigned int function_only_inline = 1 << 5; - - // const function - static const unsigned int function_read_only = 1 << 6; + static const unsigned int function_in_unique_section = 1 << 3; // Declare or define a function of FNTYPE. // NAME is the Go name of the function. ASM_NAME, if not the empty @@ -721,8 +662,6 @@ public: Location) = 0; - virtual tree specify_abi_attribute (tree type, Rust::ABI abi) = 0; - // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: // finish: diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 13cfe23..62c9d80 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -160,10 +160,6 @@ public: tree immutable_type (tree); - tree specify_abi_attribute (tree, Rust::ABI); - - tree insert_type_attribute (tree, const std::string &); - tree function_type (const typed_identifier &, const std::vector<typed_identifier> &, const std::vector<typed_identifier> &, tree, @@ -769,52 +765,6 @@ Gcc_backend::immutable_type (tree base) return constified; } -// ABI - -tree -Gcc_backend::specify_abi_attribute (tree type, Rust::ABI abi) -{ - std::string abi_string; - switch (abi) - { - case Rust::ABI::UNKNOWN: - return error_type (); - - case Rust::ABI::RUST: - case Rust::ABI::INTRINSIC: - case Rust::ABI::C: - case Rust::ABI::CDECL: - abi_string = "cdecl"; - break; - - case Rust::ABI::STDCALL: - abi_string = "stdcall"; - break; - case Rust::ABI::FASTCALL: - abi_string = "fastcall"; - break; - } - - return insert_type_attribute (type, abi_string); -} - -tree -Gcc_backend::insert_type_attribute (tree type, const std::string &attrname) -{ - tree ident = get_identifier (attrname.c_str ()); - - tree attribs = NULL_TREE; - tree old_attrs = TYPE_ATTRIBUTES (type); - if (old_attrs) - attribs = merge_type_attributes (old_attrs, - tree_cons (ident, NULL_TREE, NULL_TREE)); - else - attribs = tree_cons (ident, NULL_TREE, NULL_TREE); - - tree res = build_type_attribute_variant (type, attribs); - return res; -} - // Make a function type. tree @@ -2965,8 +2915,7 @@ Gcc_backend::function (tree functype, const std::string &name, = build_decl (location.gcc_location (), FUNCTION_DECL, id, functype); if (!asm_name.empty ()) SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name)); - if ((flags & function_is_visible) != 0) - TREE_PUBLIC (decl) = 1; + if ((flags & function_is_declaration) != 0) DECL_EXTERNAL (decl) = 1; else @@ -2985,14 +2934,6 @@ Gcc_backend::function (tree functype, const std::string &name, TREE_THIS_VOLATILE (decl) = 1; if ((flags & function_in_unique_section) != 0) resolve_unique_section (decl, 0, 1); - if ((flags & function_only_inline) != 0) - { - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - DECL_DECLARED_INLINE_P (decl) = 1; - } - if ((flags & function_read_only) != 0) - TREE_READONLY (decl) = 1; rust_preserve_from_gc (decl); return decl; diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 10d4ea8..b5c0dbc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -126,14 +126,18 @@ public: CanonicalPath::new_seg (function.get_mappings ().get_nodeid (), function.get_item_name ()), function.get_locus ()}; - auto fnType - = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_item_name (), ident, flags, - ::Backend::get_abi_from_string (parent.get_abi (), - parent.get_locus ()), - std::move (params), ret_type, - std::move (substitutions)); + + auto abi = get_abi_from_string (parent.get_abi ()); + if (abi == ABI::UNKNOWN) + { + rust_error_at (parent.get_locus (), "unknown abi"); + } + + auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), + function.get_item_name (), ident, flags, + abi, std::move (params), ret_type, + std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } diff --git a/gcc/rust/util/rust-abi.cc b/gcc/rust/util/rust-abi.cc new file mode 100644 index 0000000..c27e382 --- /dev/null +++ b/gcc/rust/util/rust-abi.cc @@ -0,0 +1,64 @@ +// 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/>. + +#include "rust-abi.h" + +namespace Rust { + +Rust::ABI +get_abi_from_string (const std::string &abi) +{ + if (abi.compare ("rust") == 0) + return Rust::ABI::C; + else if (abi.compare ("rust-intrinsic") == 0) + return Rust::ABI::INTRINSIC; + else if (abi.compare ("C") == 0) + return Rust::ABI::C; + else if (abi.compare ("cdecl") == 0) + return Rust::ABI::CDECL; + else if (abi.compare ("stdcall") == 0) + return Rust::ABI::STDCALL; + else if (abi.compare ("fastcall") == 0) + return Rust::ABI::FASTCALL; + + return Rust::ABI::UNKNOWN; +} + +std::string +get_string_from_abi (Rust::ABI abi) +{ + switch (abi) + { + case Rust::ABI::RUST: + return "rust"; + case Rust::ABI::INTRINSIC: + return "rust-intrinsic"; + case Rust::ABI::C: + return "C"; + case Rust::ABI::CDECL: + return "cdecl"; + case Rust::ABI::STDCALL: + return "stdcall"; + case Rust::ABI::FASTCALL: + return "fastcall"; + + case Rust::ABI::UNKNOWN: + return "unknown"; + } + return "unknown"; +} + +} // namespace Rust diff --git a/gcc/rust/rust-abi.h b/gcc/rust/util/rust-abi.h index bd30432..04224ee 100644 --- a/gcc/rust/rust-abi.h +++ b/gcc/rust/util/rust-abi.h @@ -17,6 +17,8 @@ #ifndef RUST_ABI_OPTIONS_H #define RUST_ABI_OPTIONS_H +#include <string> + namespace Rust { enum ABI @@ -30,6 +32,12 @@ enum ABI FASTCALL, }; +extern Rust::ABI +get_abi_from_string (const std::string &abi); + +extern std::string +get_string_from_abi (Rust::ABI abi); + } // namespace Rust #endif // RUST_ABI_OPTIONS_H |