aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-09-09 15:01:14 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-09-09 15:25:24 +0100
commit995bc1c9834f4b881a5d620cf4d707962c3841a7 (patch)
tree04b6329d942216060c2e81246535907e9980d06a
parent55f60bd6fe2db6831762e243577515824e2fca5c (diff)
downloadgcc-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.h8
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc3
-rw-r--r--gcc/rust/rust-abi.h35
-rw-r--r--gcc/rust/rust-backend.h47
-rw-r--r--gcc/rust/rust-gcc.cc51
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc12
-rw-r--r--gcc/rust/typecheck/rust-tyty.h39
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,