aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile-expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.cc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc187
1 files changed, 110 insertions, 77 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 7c8aa29..fa88e48 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -168,19 +168,36 @@ CompileExpr::visit (HIR::CallExpr &expr)
// must be a tuple constructor
bool is_fn = tyty->get_kind () == TyTy::TypeKind::FNDEF
|| tyty->get_kind () == TyTy::TypeKind::FNPTR;
- if (!is_fn)
+ bool is_adt_ctor = !is_fn;
+ if (is_adt_ctor)
{
rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty);
tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty);
- rust_assert (!adt->is_enum ());
- rust_assert (adt->number_of_variants () == 1);
- auto variant = adt->get_variants ().at (0);
+ // what variant is it?
+ int union_disriminator = -1;
+ TyTy::VariantDef *variant = nullptr;
+ if (!adt->is_enum ())
+ {
+ rust_assert (adt->number_of_variants () == 1);
+ variant = adt->get_variants ().at (0);
+ }
+ else
+ {
+ HirId variant_id;
+ bool ok = ctx->get_tyctx ()->lookup_variant_definition (
+ expr.get_fnexpr ()->get_mappings ().get_hirid (), &variant_id);
+ rust_assert (ok);
+
+ ok = adt->lookup_variant_by_id (variant_id, &variant,
+ &union_disriminator);
+ rust_assert (ok);
+ }
// 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<tree> vals;
+ std::vector<tree> arguments;
for (size_t i = 0; i < expr.get_arguments ().size (); i++)
{
auto &argument = expr.get_arguments ().at (i);
@@ -200,95 +217,111 @@ CompileExpr::visit (HIR::CallExpr &expr)
rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
// add it to the list
- vals.push_back (rvalue);
+ arguments.push_back (rvalue);
}
- translated
- = ctx->get_backend ()->constructor_expression (compiled_adt_type, vals,
- -1, expr.get_locus ());
- }
- else
- {
- 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);
+ // the constructor depends on whether this is actually an enum or not if
+ // its an enum we need to setup the discriminator
+ std::vector<tree> ctor_arguments;
+ if (adt->is_enum ())
+ {
+ HirId variant_id = variant->get_id ();
+ mpz_t val;
+ mpz_init_set_ui (val, variant_id);
+
+ tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
+ tree qualifier
+ = double_int_to_tree (t, mpz_get_double_int (t, val, true));
+ ctor_arguments.push_back (qualifier);
+ }
+ for (auto &arg : arguments)
+ ctor_arguments.push_back (arg);
- return true;
- }
+ translated = ctx->get_backend ()->constructor_expression (
+ compiled_adt_type, adt->is_enum (), ctor_arguments, union_disriminator,
+ expr.get_locus ());
- const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (base);
- auto param = fn->param_at (index);
- *result = param.second;
+ return;
+ }
- return true;
- };
+ 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);
- 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 ();
- }
+ if (base->get_kind () == TyTy::TypeKind::FNPTR)
+ {
+ const TyTy::FnPtr *fn = static_cast<const TyTy::FnPtr *> (base);
+ *result = fn->param_at (index);
- 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 ();
- }
+ return true;
+ }
- std::vector<tree> args;
- for (size_t i = 0; i < expr.get_arguments ().size (); i++)
- {
- auto &argument = expr.get_arguments ().at (i);
- auto rvalue = CompileExpr::Compile (argument.get (), ctx);
+ const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (base);
+ auto param = fn->param_at (index);
+ *result = param.second;
- if (is_varadic && i >= required_num_args)
- {
- args.push_back (rvalue);
- continue;
- }
+ return true;
+ };
- // 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);
+ 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 ();
+ }
- TyTy::BaseType *actual = nullptr;
- ok = ctx->get_tyctx ()->lookup_type (
- argument->get_mappings ().get_hirid (), &actual);
- rust_assert (ok);
+ 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 ();
+ }
- // coerce it if required
- rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+ std::vector<tree> args;
+ for (size_t i = 0; i < expr.get_arguments ().size (); i++)
+ {
+ auto &argument = expr.get_arguments ().at (i);
+ auto rvalue = CompileExpr::Compile (argument.get (), ctx);
- // add it to the list
+ if (is_varadic && i >= required_num_args)
+ {
args.push_back (rvalue);
+ continue;
}
- // 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_address,
- args, nullptr,
- expr.get_locus ());
+ // 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_address, args,
+ nullptr, expr.get_locus ());
}
void