diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-10-05 14:50:29 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-10-05 15:09:09 +0100 |
commit | f6a04f38d51f6ca4319219f101e3f58660b128dc (patch) | |
tree | 755b5bebd0b063be0464510d00bef0886a9aa03c /gcc/rust/backend/rust-compile.cc | |
parent | 591b43e42e7f63841ce46fdd4f2760e47b6a7b0d (diff) | |
download | gcc-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.cc | 111 |
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 ()); } } |