diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index bb4f0abbbf9e..0aaf084f04f0 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -371,9 +371,14 @@ class TyTyResolveCompile : public TyTy::TyVisitor
parameters.push_back (compiled_param);
}
- translated = ctx->get_backend ()->function_type (
- receiver, parameters, results, NULL,
- ctx->get_mappings ()->lookup_location (type.get_ref ()));
+ if (!type.is_varadic ())
+ translated = ctx->get_backend ()->function_type (
+ receiver, parameters, results, NULL,
+ ctx->get_mappings ()->lookup_location (type.get_ref ()));
+ else
+ translated = ctx->get_backend ()->function_type_varadic (
+ receiver, parameters, results, NULL,
+ ctx->get_mappings ()->lookup_location (type.get_ref ()));
}
void visit (TyTy::FnPtr &type) override
diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h
new file mode 100644
index 000000000000..a0ad2002bef7
--- /dev/null
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -0,0 +1,148 @@
+// 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)
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index 2d0856ddde44..3ddc29ac1ab7 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -95,9 +95,15 @@ class TyTyCompile : public TyTy::TyVisitor
parameters.push_back (compiled_param);
}
- translated
- = backend->function_type (receiver, parameters, results, NULL,
- mappings->lookup_location (type.get_ref ()));
+ if (!type.is_varadic ())
+ translated
+ = backend->function_type (receiver, parameters, results, NULL,
+ mappings->lookup_location (type.get_ref ()));
+ else
+ translated
+ = backend->function_type_varadic (receiver, parameters, results, NULL,
+ mappings->lookup_location (
+ type.get_ref ()));
}
void visit (TyTy::BoolType &) override
diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h
index 1cc0c8e47285..4ea0019d7195 100644
--- a/gcc/rust/hir/rust-ast-lower-extern.h
+++ b/gcc/rust/hir/rust-ast-lower-extern.h
@@ -47,8 +47,6 @@ class ASTLoweringExternItem : public ASTLoweringBase
Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
mappings->get_next_hir_id (crate_num),
mappings->get_next_localdef_id (crate_num));
- mappings->insert_location (crate_num, mapping.get_hirid (),
- item.get_locus ());
HIR::ExternalStaticItem *static_item
= new HIR::ExternalStaticItem (mapping, item.get_identifier (),
@@ -58,6 +56,11 @@ class ASTLoweringExternItem : public ASTLoweringBase
item.get_locus ());
translated = static_item;
+
+ mappings->insert_hir_extern_item (crate_num, mapping.get_hirid (),
+ translated);
+ mappings->insert_location (crate_num, mapping.get_hirid (),
+ item.get_locus ());
}
void visit (AST::ExternalFunctionItem &function) override
@@ -97,8 +100,6 @@ class ASTLoweringExternItem : public ASTLoweringBase
Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
mappings->get_next_hir_id (crate_num),
mappings->get_next_localdef_id (crate_num));
- mappings->insert_location (crate_num, mapping.get_hirid (),
- function.get_locus ());
HIR::ExternalFunctionItem *function_item = new HIR::ExternalFunctionItem (
mapping, function.get_identifier (), std::move (generic_params),
@@ -107,6 +108,11 @@ class ASTLoweringExternItem : public ASTLoweringBase
function.get_outer_attrs (), function.get_locus ());
translated = function_item;
+
+ mappings->insert_hir_extern_item (crate_num, mapping.get_hirid (),
+ translated);
+ mappings->insert_location (crate_num, mapping.get_hirid (),
+ function.get_locus ());
}
private:
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index e53b739747ec..80ca29859fba 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -571,10 +571,6 @@ class ASTLoweringItem : public ASTLoweringBase
mappings->get_next_hir_id (crate_num),
mappings->get_next_localdef_id (crate_num));
- mappings->insert_defid_mapping (mapping.get_defid (), translated);
- mappings->insert_location (crate_num, mapping.get_hirid (),
- extern_block.get_locus ());
-
HIR::ExternBlock *hir_extern_block
= new HIR::ExternBlock (mapping, extern_block.get_abi (),
std::move (extern_items), std::move (vis),
@@ -583,6 +579,12 @@ class ASTLoweringItem : public ASTLoweringBase
extern_block.get_locus ());
translated = hir_extern_block;
+
+ mappings->insert_defid_mapping (mapping.get_defid (), translated);
+ mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+ translated);
+ mappings->insert_location (crate_num, mapping.get_hirid (),
+ extern_block.get_locus ());
}
private:
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 6d53711942fd..7d976c5c991c 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -2713,6 +2713,8 @@ class ExternalItem
Analysis::NodeMapping get_mappings () const { return mappings; }
+ Identifier get_item_name () const { return item_name; }
+
protected:
ExternalItem (Analysis::NodeMapping mappings, Identifier item_name,
Visibility vis, AST::AttrVec outer_attrs, Location locus)
@@ -2746,9 +2748,6 @@ class ExternalItem
// Clone function implementation as pure virtual method
virtual ExternalItem *clone_external_item_impl () const = 0;
-
- // possibly make this public if required
- std::string get_item_name () const { return item_name; }
};
// A static item used in an extern block
@@ -2790,6 +2789,8 @@ class ExternalStaticItem : public ExternalItem
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr &get_item_type () { return item_type; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2840,6 +2841,12 @@ struct NamedFunctionParam
NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
std::string as_string () const;
+
+ Identifier get_param_name () const { return name; }
+
+ std::unique_ptr &get_type () { return param_type; }
+
+ Analysis::NodeMapping get_mappings () const { return mappings; }
};
// A function item used in an extern block
@@ -2920,6 +2927,20 @@ class ExternalFunctionItem : public ExternalItem
void accept_vis (HIRVisitor &vis) override;
+ std::vector > &get_generic_params ()
+ {
+ return generic_params;
+ }
+
+ std::unique_ptr &get_return_type () { return return_type; }
+
+ std::vector &get_function_params ()
+ {
+ return function_params;
+ }
+
+ bool is_variadic () const { return has_variadics; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2999,6 +3020,11 @@ class ExternBlock : public VisItem
void accept_vis (HIRVisitor &vis) override;
+ std::vector > &get_extern_items ()
+ {
+ return extern_items;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index ccf3872ac044..539229d60fa2 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -619,7 +619,7 @@ class ResolveExternItem : public ResolverBase
private:
ResolveExternItem () : ResolverBase (UNKNOWN_NODEID) {}
-}; // namespace Resolver
+};
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 9cc833ff3ba2..06a341a0586a 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -637,7 +637,9 @@ ResolveItem::resolve_impl_item (AST::InherentImplItem *item,
void
ResolveItem::resolve_extern_item (AST::ExternalItem *item)
-{}
+{
+ ResolveExternItem::go (item);
+}
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 1dd4aba12ca4..be23fd3d852c 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -163,6 +163,13 @@ class Backend
Btype *result_struct, Location location)
= 0;
+ virtual Btype *
+ function_type_varadic (const Btyped_identifier &receiver,
+ const std::vector ¶meters,
+ const std::vector &results,
+ Btype *result_struct, Location location)
+ = 0;
+
virtual Btype *function_ptr_type (Btype *result,
const std::vector &praameters,
Location location)
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 23a91ad9bcbc..44617a68d2a4 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -256,6 +256,11 @@ class Gcc_backend : public Backend
const std::vector &, Btype *,
const Location);
+ Btype *function_type_varadic (const Btyped_identifier &,
+ const std::vector &,
+ const std::vector &, Btype *,
+ const Location);
+
Btype *function_ptr_type (Btype *, const std::vector &, Location);
Btype *struct_type (const std::vector &);
@@ -1048,6 +1053,62 @@ Gcc_backend::function_type (const Btyped_identifier &receiver,
return this->make_type (build_pointer_type (fntype));
}
+Btype *
+Gcc_backend::function_type_varadic (
+ const Btyped_identifier &receiver,
+ const std::vector ¶meters,
+ const std::vector &results, Btype *result_struct, Location)
+{
+ size_t n = parameters.size () + (receiver.btype != NULL ? 1 : 0);
+ tree *args = XALLOCAVEC (tree, n);
+ size_t offs = 0;
+
+ if (receiver.btype != NULL)
+ {
+ tree t = receiver.btype->get_tree ();
+ if (t == error_mark_node)
+ return this->error_type ();
+
+ args[offs++] = t;
+ }
+
+ for (std::vector::const_iterator p = parameters.begin ();
+ p != parameters.end (); ++p)
+ {
+ tree t = p->btype->get_tree ();
+ if (t == error_mark_node)
+ return this->error_type ();
+ args[offs++] = t;
+ }
+
+ tree result;
+ if (results.empty ())
+ result = void_type_node;
+ else if (results.size () == 1)
+ result = results.front ().btype->get_tree ();
+ else
+ {
+ gcc_assert (result_struct != NULL);
+ result = result_struct->get_tree ();
+ }
+ if (result == error_mark_node)
+ return this->error_type ();
+
+ // The libffi library cannot represent a zero-sized object. To
+ // avoid causing confusion on 32-bit SPARC, we treat a function that
+ // returns a zero-sized value as returning void. That should do no
+ // harm since there is no actual value to be returned. See
+ // https://gcc.gnu.org/PR72814 for details.
+ if (result != void_type_node && int_size_in_bytes (result) == 0)
+ result = void_type_node;
+
+ tree fntype = build_varargs_function_type_array (result, n, args);
+ if (fntype == error_mark_node)
+ return this->error_type ();
+
+ return this->make_type (build_pointer_type (fntype));
+}
+
Btype *
Gcc_backend::function_ptr_type (Btype *result_type,
const std::vector ¶meters,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index 5f6fcd99cdc5..65088be4d9cd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -28,6 +28,105 @@
namespace Rust {
namespace Resolver {
+class TypeCheckTopLevelExternItem : public TypeCheckBase
+{
+ using Rust::Resolver::TypeCheckBase::visit;
+
+public:
+ static void Resolve (HIR::ExternalItem *item)
+ {
+ TypeCheckTopLevelExternItem resolver;
+ item->accept_vis (resolver);
+ }
+
+ void visit (HIR::ExternalStaticItem &item) override
+ {
+ TyTy::BaseType *actual_type
+ = TypeCheckType::Resolve (item.get_item_type ().get ());
+
+ context->insert_type (item.get_mappings (), actual_type);
+ }
+
+ void visit (HIR::ExternalFunctionItem &function) override
+ {
+ std::vector substitutions;
+ if (function.has_generics ())
+ {
+ for (auto &generic_param : function.get_generic_params ())
+ {
+ switch (generic_param.get ()->get_kind ())
+ {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ // Skipping Lifetime completely until better handling.
+ break;
+
+ case HIR::GenericParam::GenericKind::TYPE: {
+ auto param_type
+ = TypeResolveGenericParam::Resolve (generic_param.get ());
+ context->insert_type (generic_param->get_mappings (),
+ param_type);
+
+ substitutions.push_back (TyTy::SubstitutionParamMapping (
+ static_cast (*generic_param),
+ param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ TyTy::BaseType *ret_type = nullptr;
+ if (!function.has_return_type ())
+ ret_type = new TyTy::TupleType (function.get_mappings ().get_hirid ());
+ else
+ {
+ auto resolved
+ = TypeCheckType::Resolve (function.get_return_type ().get ());
+ if (resolved == nullptr)
+ {
+ rust_error_at (function.get_locus (),
+ "failed to resolve return type");
+ return;
+ }
+
+ ret_type = resolved->clone ();
+ ret_type->set_ref (
+ function.get_return_type ()->get_mappings ().get_hirid ());
+ }
+
+ std::vector > params;
+ for (auto ¶m : function.get_function_params ())
+ {
+ // get the name as well required for later on
+ auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
+
+ HIR::IdentifierPattern *param_pattern = new HIR::IdentifierPattern (
+ param.get_param_name (), Location (), false, false,
+ std::unique_ptr (nullptr));
+
+ params.push_back (
+ std::pair (param_pattern,
+ param_tyty));
+
+ context->insert_type (param.get_mappings (), param_tyty);
+ }
+
+ uint8_t flags = FNTYPE_IS_EXTERN_FLAG;
+ if (function.is_variadic ())
+ flags |= FNTYPE_IS_VARADIC_FLAG;
+
+ auto fnType
+ = new TyTy::FnType (function.get_mappings ().get_hirid (),
+ function.get_mappings ().get_defid (),
+ function.get_item_name (), flags, std::move (params),
+ ret_type, std::move (substitutions));
+ context->insert_type (function.get_mappings (), fnType);
+ }
+
+private:
+ TypeCheckTopLevelExternItem () : TypeCheckBase () {}
+};
+
class TypeCheckTopLevelImplItem : public TypeCheckBase
{
using Rust::Resolver::TypeCheckBase::visit;
@@ -134,11 +233,11 @@ class TypeCheckTopLevelImplItem : public TypeCheckBase
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 (), 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,
+ 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 dd3dd751ad6c..18f3e7254164 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -230,9 +230,9 @@ class TypeCheckTopLevel : public TypeCheckBase
auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
function.get_mappings ().get_defid (),
- function.get_function_name (), false,
- std::move (params), ret_type,
- std::move (substitutions));
+ function.get_function_name (),
+ FNTYPE_DEFAULT_FLAGS, std::move (params),
+ ret_type, std::move (substitutions));
context->insert_type (function.get_mappings (), fnType);
}
@@ -274,6 +274,14 @@ class TypeCheckTopLevel : public TypeCheckBase
substitutions);
}
+ void visit (HIR::ExternBlock &extern_block) override
+ {
+ for (auto &item : extern_block.get_extern_items ())
+ {
+ TypeCheckTopLevelExternItem::Resolve (item.get ());
+ }
+ }
+
private:
TypeCheckTopLevel () : TypeCheckBase () {}
};
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index bb5d6c0bb154..1ca28fae061f 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -816,7 +816,7 @@ FnType::clone ()
std::pair (p.first, p.second->clone ()));
return new FnType (get_ref (), get_ty_ref (), get_id (), get_identifier (),
- is_method_flag, std::move (cloned_params),
+ flags, std::move (cloned_params),
get_return_type ()->clone (), clone_substs (),
get_combined_refs ());
}
@@ -2055,15 +2055,27 @@ TypeCheckCallExpr::visit (FnType &type)
{
if (call.num_params () != type.num_params ())
{
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- call.num_params (), type.num_params ());
- return;
+ if (type.is_varadic ())
+ {
+ if (call.num_params () < type.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ call.num_params (), type.num_params ());
+ return;
+ }
+ }
+ else
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ call.num_params (), type.num_params ());
+ return;
+ }
}
size_t i = 0;
call.iterate_params ([&] (HIR::Expr *param) mutable -> bool {
- auto fnparam = type.param_at (i);
auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param, false);
if (argument_expr_tyty == nullptr)
{
@@ -2072,12 +2084,19 @@ TypeCheckCallExpr::visit (FnType &type)
return false;
}
- auto resolved_argument_type = fnparam.second->unify (argument_expr_tyty);
- if (resolved_argument_type == nullptr)
+ auto resolved_argument_type = argument_expr_tyty;
+
+ // it might be a varadic function
+ if (i < type.num_params ())
{
- rust_error_at (param->get_locus_slow (),
- "Type Resolution failure on parameter");
- return false;
+ auto fnparam = type.param_at (i);
+ resolved_argument_type = fnparam.second->unify (argument_expr_tyty);
+ if (resolved_argument_type == nullptr)
+ {
+ rust_error_at (param->get_locus_slow (),
+ "Type Resolution failure on parameter");
+ return false;
+ }
}
context->insert_type (param->get_mappings (), resolved_argument_type);
@@ -2086,7 +2105,7 @@ TypeCheckCallExpr::visit (FnType &type)
return true;
});
- if (i != call.num_params ())
+ if (i < call.num_params ())
{
rust_error_at (call.get_locus (),
"unexpected number of arguments %lu expected %lu", i,
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index cecf69ad0f5d..336d42b15f93 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -970,14 +970,19 @@ class ADTType : public BaseType, public SubstitutionRef
class FnType : public BaseType, public SubstitutionRef
{
public:
- FnType (HirId ref, DefId id, std::string identifier, bool is_method,
+#define FNTYPE_DEFAULT_FLAGS 0x00
+#define FNTYPE_IS_METHOD_FLAG 0x01
+#define FNTYPE_IS_EXTERN_FLAG 0x02
+#define FNTYPE_IS_VARADIC_FLAG 0X04
+
+ FnType (HirId ref, DefId id, std::string identifier, uint8_t flags,
std::vector > params,
BaseType *type, std::vector subst_refs,
std::set refs = std::set ())
: BaseType (ref, ref, TypeKind::FNDEF, refs),
SubstitutionRef (std::move (subst_refs),
SubstitutionArgumentMappings::error ()),
- params (std::move (params)), type (type), is_method_flag (is_method),
+ params (std::move (params)), type (type), flags (flags),
identifier (identifier), id (id)
{
LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK;
@@ -985,15 +990,15 @@ class FnType : public BaseType, public SubstitutionRef
}
FnType (HirId ref, HirId ty_ref, DefId id, std::string identifier,
- bool is_method,
+ uint8_t flags,
std::vector > params,
BaseType *type, std::vector subst_refs,
std::set refs = std::set ())
: BaseType (ref, ty_ref, TypeKind::FNDEF, refs),
SubstitutionRef (std::move (subst_refs),
SubstitutionArgumentMappings::error ()),
- params (params), type (type), is_method_flag (is_method),
- identifier (identifier), id (id)
+ params (params), type (type), flags (flags), identifier (identifier),
+ id (id)
{
LocalDefId local_def_id = id & DEF_ID_LOCAL_DEF_MASK;
rust_assert (local_def_id != UNKNOWN_LOCAL_DEFID);
@@ -1022,9 +1027,13 @@ class FnType : public BaseType, public SubstitutionRef
if (num_params () == 0)
return false;
- return is_method_flag;
+ return (flags & FNTYPE_IS_METHOD_FLAG) != 0;
}
+ bool is_extern () const { return (flags & FNTYPE_IS_EXTERN_FLAG) != 0; }
+
+ bool is_varadic () const { return (flags & FNTYPE_IS_VARADIC_FLAG) != 0; }
+
DefId get_id () const { return id; }
// get the Self type for the method
@@ -1077,7 +1086,7 @@ class FnType : public BaseType, public SubstitutionRef
private:
std::vector > params;
BaseType *type;
- bool is_method_flag;
+ uint8_t flags;
std::string identifier;
DefId id;
};
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 40b5167f0257..69fbe250b7e2 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -283,6 +283,30 @@ Mappings::lookup_hir_trait_item (CrateNum crateNum, HirId id)
return iy->second;
}
+void
+Mappings::insert_hir_extern_item (CrateNum crateNum, HirId id,
+ HIR::ExternalItem *item)
+{
+ rust_assert (lookup_hir_extern_item (crateNum, id) == nullptr);
+
+ hirExternItemMappings[crateNum][id] = item;
+ nodeIdToHirMappings[crateNum][item->get_mappings ().get_nodeid ()] = id;
+}
+
+HIR::ExternalItem *
+Mappings::lookup_hir_extern_item (CrateNum crateNum, HirId id)
+{
+ auto it = hirExternItemMappings.find (crateNum);
+ if (it == hirExternItemMappings.end ())
+ return nullptr;
+
+ auto iy = it->second.find (id);
+ if (iy == it->second.end ())
+ return nullptr;
+
+ return iy->second;
+}
+
void
Mappings::insert_hir_impl_block (CrateNum crateNum, HirId id,
HIR::ImplBlock *item)
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 3789b57ab695..7e5449c70140 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -132,6 +132,10 @@ class Mappings
HIR::TraitItem *item);
HIR::TraitItem *lookup_hir_trait_item (CrateNum crateNum, HirId id);
+ void insert_hir_extern_item (CrateNum crateNum, HirId id,
+ HIR::ExternalItem *item);
+ HIR::ExternalItem *lookup_hir_extern_item (CrateNum crateNum, HirId id);
+
void insert_hir_impl_block (CrateNum crateNum, HirId id,
HIR::ImplBlock *item);
HIR::ImplBlock *lookup_hir_impl_block (CrateNum crateNum, HirId id);
@@ -239,6 +243,8 @@ class Mappings
std::map hirImplItemsToImplMappings;
std::map > hirImplBlockMappings;
std::map > hirTraitItemMappings;
+ std::map >
+ hirExternItemMappings;
// location info
std::map > locations;
diff --git a/gcc/testsuite/rust/execute/torture/helloworld1.rs b/gcc/testsuite/rust/execute/torture/helloworld1.rs
new file mode 100644
index 000000000000..d416efa33af6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/helloworld1.rs
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World" }*/
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ unsafe {
+ let a = "Hello World";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ puts(c);
+ }
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/helloworld2.rs b/gcc/testsuite/rust/execute/torture/helloworld2.rs
new file mode 100644
index 000000000000..cc05f3798fac
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/helloworld2.rs
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+ unsafe {
+ let a = "Hello World %i\n";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 123);
+ }
+ 0
+}