diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-09-09 15:01:14 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-09-09 15:25:24 +0100 |
commit | 995bc1c9834f4b881a5d620cf4d707962c3841a7 (patch) | |
tree | 04b6329d942216060c2e81246535907e9980d06a | |
parent | 55f60bd6fe2db6831762e243577515824e2fca5c (diff) | |
download | gcc-995bc1c9834f4b881a5d620cf4d707962c3841a7.zip gcc-995bc1c9834f4b881a5d620cf4d707962c3841a7.tar.gz gcc-995bc1c9834f4b881a5d620cf4d707962c3841a7.tar.bz2 |
Add support for choosing stdcall fastcall and cdecl in the extern options
GCC adds these as options to the function type as far as I can see, I was
able to test this with linking against some C code. More testing is
required here.
-rw-r--r-- | gcc/rust/backend/rust-compile-extern.h | 8 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 3 | ||||
-rw-r--r-- | gcc/rust/rust-abi.h | 35 | ||||
-rw-r--r-- | gcc/rust/rust-backend.h | 47 | ||||
-rw-r--r-- | gcc/rust/rust-gcc.cc | 51 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-base.h | 1 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 16 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-stmt.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 12 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 39 |
11 files changed, 157 insertions, 59 deletions
diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index d78a566..f0aacee 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -119,7 +119,7 @@ public: fntype->override_context (); } - if (fntype->get_abi () == TyTy::FnType::ABI::INTRINSIC) + if (fntype->get_abi () == ABI::INTRINSIC) { Intrinsics compile (ctx); Bfunction *fndecl = compile.compile (fntype); @@ -127,19 +127,21 @@ public: return; } - rust_assert (fntype->get_abi () == TyTy::FnType::ABI::C); ::Btype *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 (); - // 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); } diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 4068a7a..66d36e3 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -24,8 +24,9 @@ Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} Bfunction * Intrinsics::compile (TyTy::FnType *fntype) { - rust_assert (fntype->get_abi () == TyTy::FnType::ABI::INTRINSIC); + rust_assert (fntype->get_abi () == ABI::INTRINSIC); + // https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs // https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs // https://github.com/Rust-GCC/gccrs/issues/658 diff --git a/gcc/rust/rust-abi.h b/gcc/rust/rust-abi.h new file mode 100644 index 0000000..bd30432 --- /dev/null +++ b/gcc/rust/rust-abi.h @@ -0,0 +1,35 @@ +// 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_ABI_OPTIONS_H +#define RUST_ABI_OPTIONS_H + +namespace Rust { + +enum ABI +{ + UNKNOWN, + RUST, + INTRINSIC, + C, + CDECL, + STDCALL, + FASTCALL, +}; + +} // namespace Rust + +#endif // RUST_ABI_OPTIONS_H diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 105b2ea..b6f18f8 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -25,7 +25,9 @@ #include "rust-location.h" #include "rust-linemap.h" +#include "rust-diagnostics.h" #include "operator.h" +#include "rust-abi.h" extern bool saw_errors (void); @@ -98,6 +100,49 @@ public: virtual std::string const_size_val_to_string (Bexpression *) = 0; virtual bool const_values_equal (Bexpression *, Bexpression *) = 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"; + } + // Types. // Produce an error type. Actually the backend could probably just @@ -818,6 +863,8 @@ public: Location) = 0; + virtual Btype *specify_abi_attribute (Btype *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 4c1dda8..0b17865 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -44,6 +44,7 @@ #include "realmpfr.h" #include "builtins.h" #include "print-tree.h" +#include "attribs.h" #include "rust-location.h" #include "rust-linemap.h" @@ -251,6 +252,10 @@ public: Btype *immutable_type (Btype *); + Btype *specify_abi_attribute (Btype *, Rust::ABI); + + Btype *insert_type_attribute (Btype *, const std::string &); + Btype *function_type (const Btyped_identifier &, const std::vector<Btyped_identifier> &, const std::vector<Btyped_identifier> &, Btype *, @@ -925,6 +930,52 @@ Gcc_backend::immutable_type (Btype *base) return this->make_type (constified); } +// ABI + +Btype * +Gcc_backend::specify_abi_attribute (Btype *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); +} + +Btype * +Gcc_backend::insert_type_attribute (Btype *type, const std::string &attrname) +{ + tree ident = get_identifier (attrname.c_str ()); + + tree attribs = NULL_TREE; + tree old_attrs = TYPE_ATTRIBUTES (type->get_tree ()); + 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->get_tree (), attribs); + return this->make_type (res); +} + // Make a function type. Btype * diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 26fb506..0b4daea 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -24,6 +24,7 @@ #include "rust-name-resolver.h" #include "rust-hir-visitor.h" #include "rust-hir-map.h" +#include "rust-backend.h" namespace Rust { namespace Resolver { diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index b1eb2e3..d3977c3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -118,8 +118,7 @@ public: auto fnType = new TyTy::FnType ( function.get_mappings ().get_hirid (), function.get_mappings ().get_defid (), function.get_item_name (), flags, - TyTy::FnType::get_abi_from_string (parent.get_abi (), - parent.get_locus ()), + ::Backend::get_abi_from_string (parent.get_abi (), parent.get_locus ()), std::move (params), ret_type, std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } @@ -238,14 +237,11 @@ public: context->insert_type (param.get_mappings (), param_tyty); } - auto fnType - = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_function_name (), - function.is_method () ? FNTYPE_IS_METHOD_FLAG - : FNTYPE_DEFAULT_FLAGS, - TyTy::FnType::ABI::RUST, std::move (params), ret_type, - std::move (substitutions)); + auto fnType = new TyTy::FnType ( + function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), function.get_function_name (), + function.is_method () ? FNTYPE_IS_METHOD_FLAG : FNTYPE_DEFAULT_FLAGS, + ABI::RUST, std::move (params), ret_type, std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 54280e8..5f4721b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -333,7 +333,7 @@ public: = new TyTy::FnType (function.get_mappings ().get_hirid (), function.get_mappings ().get_defid (), function.get_function_name (), FNTYPE_DEFAULT_FLAGS, - TyTy::FnType::ABI::RUST, std::move (params), ret_type, + ABI::RUST, std::move (params), ret_type, std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 6ec17a9..9fac813 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -291,7 +291,7 @@ public: = new TyTy::FnType (function.get_mappings ().get_hirid (), function.get_mappings ().get_defid (), function.get_function_name (), FNTYPE_DEFAULT_FLAGS, - TyTy::FnType::ABI::RUST, std::move (params), ret_type, + ABI::RUST, std::move (params), ret_type, std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index bee2748..f960f77 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -546,11 +546,13 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const context->insert_type (param.get_mappings (), param_tyty); } - auto resolved = new TyTy::FnType ( - fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (), - function.get_function_name (), - function.is_method () ? FNTYPE_IS_METHOD_FLAG : FNTYPE_DEFAULT_FLAGS, - TyTy::FnType::ABI::RUST, std::move (params), ret_type, substitutions); + auto resolved + = new TyTy::FnType (fn.get_mappings ().get_hirid (), + fn.get_mappings ().get_defid (), + function.get_function_name (), + function.is_method () ? FNTYPE_IS_METHOD_FLAG + : FNTYPE_DEFAULT_FLAGS, + ABI::RUST, std::move (params), ret_type, substitutions); context->insert_type (fn.get_mappings (), resolved); return resolved; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 7f149a9..33dc88b 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -23,6 +23,7 @@ #include "rust-hir-map.h" #include "rust-hir-full.h" #include "rust-diagnostics.h" +#include "rust-abi.h" namespace Rust { namespace Resolver { @@ -1077,44 +1078,6 @@ public: #define FNTYPE_IS_EXTERN_FLAG 0x02 #define FNTYPE_IS_VARADIC_FLAG 0X04 - enum ABI - { - UNKNOWN, - RUST, - INTRINSIC, - C, - }; - - static ABI get_abi_from_string (const std::string &abi, Location locus) - { - if (abi.compare ("rust") == 0) - return ABI::C; - else if (abi.compare ("rust-intrinsic") == 0) - return ABI::INTRINSIC; - else if (abi.compare ("C") == 0) - return ABI::C; - - rust_error_at (locus, "unknown abi specified"); - return ABI::UNKNOWN; - } - - static std::string get_string_from_abi (ABI abi) - { - switch (abi) - { - case ABI::RUST: - return "rust"; - case ABI::INTRINSIC: - return "rust-intrinsic"; - case ABI::C: - return "C"; - - case ABI::UNKNOWN: - return "unknown"; - } - return "unknown"; - } - FnType (HirId ref, DefId id, std::string identifier, uint8_t flags, ABI abi, std::vector<std::pair<HIR::Pattern *, BaseType *>> params, BaseType *type, std::vector<SubstitutionParamMapping> subst_refs, |