aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile.cc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-10-05 14:50:29 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-10-05 15:09:09 +0100
commitf6a04f38d51f6ca4319219f101e3f58660b128dc (patch)
tree755b5bebd0b063be0464510d00bef0886a9aa03c /gcc/rust/backend/rust-compile.cc
parent591b43e42e7f63841ce46fdd4f2760e47b6a7b0d (diff)
downloadgcc-f6a04f38d51f6ca4319219f101e3f58660b128dc.zip
gcc-f6a04f38d51f6ca4319219f101e3f58660b128dc.tar.gz
gcc-f6a04f38d51f6ca4319219f101e3f58660b128dc.tar.bz2
Ensure we emit the code for coercion sites on CallExpr and MethodCallExpr
When we coerce the types of arguments to the parameters of functions for example we must store the actual type of the argument at that HIR ID not the coerced ones. This gives the backend a chance to then figure out when to actually implement any coercion site code. such as computing the dynamic objects. Fixes: #700
Diffstat (limited to 'gcc/rust/backend/rust-compile.cc')
-rw-r--r--gcc/rust/backend/rust-compile.cc111
1 files changed, 96 insertions, 15 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index d1fd064..23a035f 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -69,39 +69,120 @@ CompileExpr::visit (HIR::CallExpr &expr)
|| tyty->get_kind () == TyTy::TypeKind::FNPTR;
if (!is_fn)
{
- Btype *type = TyTyResolveCompile::compile (ctx, tyty);
+ rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
+ Btype *compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);
// this assumes all fields are in order from type resolution and if a
// base struct was specified those fields are filed via accesors
std::vector<Bexpression *> vals;
- for (auto &argument : expr.get_arguments ())
+ for (size_t i = 0; i < expr.get_arguments ().size (); i++)
{
- Bexpression *e = CompileExpr::Compile (argument.get (), ctx);
- vals.push_back (e);
+ auto &argument = expr.get_arguments ().at (i);
+ auto rvalue = CompileExpr::Compile (argument.get (), ctx);
+
+ // assignments are coercion sites so lets convert the rvalue if
+ // necessary
+ auto respective_field = adt->get_field (i);
+ auto expected = respective_field->get_field_type ();
+
+ TyTy::BaseType *actual = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ argument->get_mappings ().get_hirid (), &actual);
+ rust_assert (ok);
+
+ // coerce it if required
+ rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+
+ // add it to the list
+ vals.push_back (rvalue);
}
translated
- = ctx->get_backend ()->constructor_expression (type, vals, -1,
- expr.get_locus ());
+ = ctx->get_backend ()->constructor_expression (compiled_adt_type, vals,
+ -1, expr.get_locus ());
}
else
{
- // must be a call to a function
- Bexpression *fn = CompileExpr::Compile (expr.get_fnexpr (), ctx);
- rust_assert (fn != nullptr);
+ auto get_parameter_tyty_at_index
+ = [] (const TyTy::BaseType *base, size_t index,
+ TyTy::BaseType **result) -> bool {
+ bool is_fn = base->get_kind () == TyTy::TypeKind::FNDEF
+ || base->get_kind () == TyTy::TypeKind::FNPTR;
+ rust_assert (is_fn);
+
+ if (base->get_kind () == TyTy::TypeKind::FNPTR)
+ {
+ const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (base);
+ *result = fn->param_at (index);
+
+ return true;
+ }
+
+ const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (base);
+ auto param = fn->param_at (index);
+ *result = param.second;
+
+ return true;
+ };
+
+ bool is_varadic = false;
+ if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (tyty);
+ is_varadic = fn->is_varadic ();
+ }
+
+ size_t required_num_args;
+ if (tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (tyty);
+ required_num_args = fn->num_params ();
+ }
+ else
+ {
+ const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (tyty);
+ required_num_args = fn->num_params ();
+ }
std::vector<Bexpression *> args;
- for (auto &argument : expr.get_arguments ())
+ for (size_t i = 0; i < expr.get_arguments ().size (); i++)
{
- Bexpression *compiled_expr
- = CompileExpr::Compile (argument.get (), ctx);
- args.push_back (compiled_expr);
+ auto &argument = expr.get_arguments ().at (i);
+ auto rvalue = CompileExpr::Compile (argument.get (), ctx);
+
+ if (is_varadic && i >= required_num_args)
+ {
+ args.push_back (rvalue);
+ continue;
+ }
+
+ // assignments are coercion sites so lets convert the rvalue if
+ // necessary
+ bool ok;
+ TyTy::BaseType *expected = nullptr;
+ ok = get_parameter_tyty_at_index (tyty, i, &expected);
+ rust_assert (ok);
+
+ TyTy::BaseType *actual = nullptr;
+ ok = ctx->get_tyctx ()->lookup_type (
+ argument->get_mappings ().get_hirid (), &actual);
+ rust_assert (ok);
+
+ // coerce it if required
+ rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+
+ // add it to the list
+ args.push_back (rvalue);
}
+ // must be a call to a function
+ auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
auto fncontext = ctx->peek_fn ();
translated
- = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args,
- nullptr, expr.get_locus ());
+ = ctx->get_backend ()->call_expression (fncontext.fndecl, fn_address,
+ args, nullptr,
+ expr.get_locus ());
}
}