diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-11-08 01:36:59 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-11-16 14:19:22 +0000 |
commit | a7fb60bb626f7b936bf117636db777a5f0df30c9 (patch) | |
tree | 300c1dac1d15aff0eec5cd1e0a0f549e6fd20e78 /gcc/rust/backend/rust-compile-expr.cc | |
parent | 432add899f4e436d0d30b89ef87fe19e71b36955 (diff) | |
download | gcc-a7fb60bb626f7b936bf117636db777a5f0df30c9.zip gcc-a7fb60bb626f7b936bf117636db777a5f0df30c9.tar.gz gcc-a7fb60bb626f7b936bf117636db777a5f0df30c9.tar.bz2 |
Add support compound assignment operator overloads
Fixes #249
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index c7941bc2..4fc69d3 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -135,6 +135,121 @@ CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) nullptr, expr.get_locus ()); } +void +CompileExpr::visit (HIR::CompoundAssignmentExpr &expr) +{ + fncontext fn = ctx->peek_fn (); + + auto op = expr.get_expr_type (); + auto lhs = CompileExpr::Compile (expr.get_left_expr ().get (), ctx); + auto rhs = CompileExpr::Compile (expr.get_right_expr ().get (), ctx); + + // this might be an operator overload situation lets check + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + if (!is_op_overload) + { + auto operator_expr + = ctx->get_backend ()->arithmetic_or_logical_expression ( + op, lhs, rhs, expr.get_locus ()); + Bstatement *assignment + = ctx->get_backend ()->assignment_statement (fn.fndecl, lhs, + operator_expr, + expr.get_locus ()); + ctx->add_statement (assignment); + return; + } + + // lookup the resolved name + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at (expr.get_locus (), "failed to lookup resolved MethodCall"); + return; + } + + // reverse lookup + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + TyTy::BaseType *receiver = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_receiver (expr.get_mappings ().get_hirid (), + &receiver); + rust_assert (ok); + + bool is_dyn_dispatch + = receiver->get_root ()->get_kind () == TyTy::TypeKind::DYNAMIC; + bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM; + if (is_generic_receiver) + { + TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver); + receiver = p->resolve (); + } + + if (is_dyn_dispatch) + { + const TyTy::DynamicObjectType *dyn + = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ()); + + std::vector<HIR::Expr *> arguments; + arguments.push_back (expr.get_right_expr ().get ()); + + translated = compile_dyn_dispatch_call (dyn, receiver, fntype, lhs, + arguments, expr.get_locus ()); + return; + } + + // lookup compiled functions since it may have already been compiled + HIR::PathIdentSegment segment_name ("add_assign"); + Bexpression *fn_expr + = resolve_method_address (fntype, ref, receiver, segment_name, + expr.get_mappings (), expr.get_locus ()); + + // lookup the autoderef mappings + std::vector<Resolver::Adjustment> *adjustments = nullptr; + ok = ctx->get_tyctx ()->lookup_autoderef_mappings ( + expr.get_mappings ().get_hirid (), &adjustments); + rust_assert (ok); + + Bexpression *self = lhs; + for (auto &adjustment : *adjustments) + { + switch (adjustment.get_type ()) + { + case Resolver::Adjustment::AdjustmentType::IMM_REF: + case Resolver::Adjustment::AdjustmentType::MUT_REF: + self = ctx->get_backend ()->address_expression ( + self, expr.get_left_expr ()->get_locus ()); + break; + + case Resolver::Adjustment::AdjustmentType::DEREF_REF: + Btype *expected_type + = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); + self = ctx->get_backend ()->indirect_expression ( + expected_type, self, true, /* known_valid*/ + expr.get_left_expr ()->get_locus ()); + break; + } + } + + std::vector<Bexpression *> args; + args.push_back (self); // adjusted self + args.push_back (rhs); + + auto fncontext = ctx->peek_fn (); + translated + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args, + nullptr, expr.get_locus ()); +} + Bexpression * CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, TyTy::BaseType *receiver, |