diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-11-16 13:54:43 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-11-16 14:09:23 +0000 |
commit | c47d5cbdee9b701fb7753b44530fcb51f80b20fa (patch) | |
tree | 2cd74fceb2f9cc92ae47988507fdf424fb3d3682 /gcc/rust/backend/rust-compile.cc | |
parent | 89e02f52d86c7120046236e654e49749c4b4ecb3 (diff) | |
download | gcc-c47d5cbdee9b701fb7753b44530fcb51f80b20fa.zip gcc-c47d5cbdee9b701fb7753b44530fcb51f80b20fa.tar.gz gcc-c47d5cbdee9b701fb7753b44530fcb51f80b20fa.tar.bz2 |
Initial support operator overloading on [lang = "add"]
This change incorporates a few changes.
1. Create new gcc/rust/backend/rust-compile-expr.cc to split out
implementation code
2. Create new type check context api calls:
- TypeCheckContext::lookup_operator_overload
- TypeCheckContext::insert_operator_overload
3. Update type checking for ArithmeticOrLogicalExpr to look for any
operator overloading
When we are looking for operator overloads we must look up the associated
lang item type for this paticular operation, to resolve the operation to
any known lang_items by looking up the specified lang_item to DefId. Then
we must probe for the lang_item candidate for this paticular lang_item
DefID to see if we can resolve it to a method call. Then based on the
autoderef rules in a MethodCallExpr we must verify that we don't end up
in a recursive operator overload by checking that the current context
is not the same as the actual operator overload for this type. Finally
we mark this expression as operator overload and setup everything as a
resolved MethodCallExpr.
Fixes #249
Diffstat (limited to 'gcc/rust/backend/rust-compile.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 219 |
1 files changed, 10 insertions, 209 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index e9aca2c..e53993a 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -242,220 +242,21 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) const TyTy::DynamicObjectType *dyn = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ()); - size_t offs = 0; - const Resolver::TraitItemReference *ref = nullptr; - for (auto &bound : dyn->get_object_items ()) - { - const Resolver::TraitItemReference *item = bound.first; - auto t = item->get_tyty (); - rust_assert (t->get_kind () == TyTy::TypeKind::FNDEF); - auto ft = static_cast<TyTy::FnType *> (t); - - if (ft->get_id () == fntype->get_id ()) - { - ref = item; - break; - } - offs++; - } - - if (ref == nullptr) - { - translated = ctx->get_backend ()->error_expression (); - return; - } - - // get any indirection sorted out - auto receiver_ref = self; - if (receiver->get_kind () == TyTy::TypeKind::REF) - { - TyTy::ReferenceType *r - = static_cast<TyTy::ReferenceType *> (receiver); - auto indirect_ty = r->get_base (); - Btype *indrect_compiled_tyty - = TyTyResolveCompile::compile (ctx, indirect_ty); - - Bexpression *indirect - = ctx->get_backend ()->indirect_expression (indrect_compiled_tyty, - receiver_ref, true, - expr.get_locus ()); - receiver_ref = indirect; - } + std::vector<HIR::Expr *> arguments; + for (auto &arg : expr.get_arguments ()) + arguments.push_back (arg.get ()); - // access the offs + 1 for the fnptr and offs=0 for the reciever obj - Bexpression *self_argument - = ctx->get_backend ()->struct_field_expression (receiver_ref, 0, - expr.get_locus ()); - - // access the vtable for the fn - Bexpression *fn_vtable_access - = ctx->get_backend ()->struct_field_expression (receiver_ref, offs + 1, - expr.get_locus ()); - - // cast it to the correct fntype - Btype *expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true); - Bexpression *fn_convert_expr - = ctx->get_backend ()->convert_expression (expected_fntype, - fn_vtable_access, - expr.get_locus ()); - - fncontext fnctx = ctx->peek_fn (); - Bblock *enclosing_scope = ctx->peek_enclosing_scope (); - bool is_address_taken = false; - Bstatement *ret_var_stmt = nullptr; - - Bvariable *fn_convert_expr_tmp = ctx->get_backend ()->temporary_variable ( - fnctx.fndecl, enclosing_scope, expected_fntype, fn_convert_expr, - is_address_taken, expr.get_locus (), &ret_var_stmt); - ctx->add_statement (ret_var_stmt); - - std::vector<Bexpression *> args; - args.push_back (self_argument); - for (auto &argument : expr.get_arguments ()) - { - Bexpression *compiled_expr - = CompileExpr::Compile (argument.get (), ctx); - args.push_back (compiled_expr); - } - - Bexpression *fn_expr - = ctx->get_backend ()->var_expression (fn_convert_expr_tmp, - expr.get_locus ()); - - translated - = ctx->get_backend ()->call_expression (fnctx.fndecl, fn_expr, args, - nullptr, expr.get_locus ()); + translated = compile_dyn_dispatch_call (dyn, receiver, fntype, self, + arguments, expr.get_locus ()); return; } - // address of compiled function - Bexpression *fn_expr = ctx->get_backend ()->error_expression (); - // lookup compiled functions since it may have already been compiled - Bfunction *fn = nullptr; - if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) - { - fn_expr - = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); - } - else - { - // Now we can try and resolve the address since this might be a forward - // declared function, generic function which has not be compiled yet or - // its an not yet trait bound function - HIR::ImplItem *resolved_item = ctx->get_mappings ()->lookup_hir_implitem ( - expr.get_mappings ().get_crate_num (), ref, nullptr); - if (resolved_item == nullptr) - { - // it might be resolved to a trait item - HIR::TraitItem *trait_item - = ctx->get_mappings ()->lookup_hir_trait_item ( - expr.get_mappings ().get_crate_num (), ref); - HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping ( - trait_item->get_mappings ().get_hirid ()); - - Resolver::TraitReference *trait_ref - = &Resolver::TraitReference::error_node (); - bool ok = ctx->get_tyctx ()->lookup_trait_reference ( - trait->get_mappings ().get_defid (), &trait_ref); - rust_assert (ok); - - // the type resolver can only resolve type bounds to their trait - // item so its up to us to figure out if this path should resolve - // to an trait-impl-block-item or if it can be defaulted to the - // trait-impl-item's definition - - auto root = receiver->get_root (); - std::vector<Resolver::PathProbeCandidate> candidates - = Resolver::PathProbeType::Probe ( - root, expr.get_method_name ().get_segment (), true, false, true); - - if (candidates.size () == 0) - { - // this means we are defaulting back to the trait_item if - // possible - Resolver::TraitItemReference *trait_item_ref = nullptr; - bool ok = trait_ref->lookup_hir_trait_item (*trait_item, - &trait_item_ref); - rust_assert (ok); // found - rust_assert (trait_item_ref->is_optional ()); // has definition - - // FIXME Optional means it has a definition and an associated - // block which can be a default implementation, if it does not - // contain an implementation we should actually return - // error_mark_node - - TyTy::BaseType *self_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver ()->get_mappings ().get_hirid (), - &self_type)) - { - rust_error_at (expr.get_locus (), - "failed to resolve type for self param"); - return; - } - - fn_expr = CompileTraitItem::Compile ( - self_type, trait_item_ref->get_hir_trait_item (), ctx, fntype, - true, expr.get_locus ()); - } - else - { - std::vector<Resolver::Adjustment> adjustments; - Resolver::PathProbeCandidate *candidate - = Resolver::MethodResolution::Select (candidates, root, - adjustments); - - // FIXME this will be a case to return error_mark_node, there is - // an error scenario where a Trait Foo has a method Bar, but this - // receiver does not implement this trait or has an incompatible - // implementation and we should just return error_mark_node - rust_assert (candidate != nullptr); - rust_assert (candidate->is_impl_candidate ()); - - HIR::ImplItem *impl_item = candidate->item.impl.impl_item; - - TyTy::BaseType *self_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver ()->get_mappings ().get_hirid (), - &self_type)) - { - rust_error_at (expr.get_locus (), - "failed to resolve type for self param"); - return; - } - - if (!fntype->has_subsititions_defined ()) - fn_expr - = CompileInherentImplItem::Compile (self_type, impl_item, ctx, - true); - else - fn_expr - = CompileInherentImplItem::Compile (self_type, impl_item, ctx, - true, fntype); - } - } - else - { - TyTy::BaseType *self_type = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver ()->get_mappings ().get_hirid (), &self_type)) - { - rust_error_at (expr.get_locus (), - "failed to resolve type for self param"); - return; - } - - if (!fntype->has_subsititions_defined ()) - fn_expr - = CompileInherentImplItem::Compile (self_type, resolved_item, ctx, - true); - else - fn_expr - = CompileInherentImplItem::Compile (self_type, resolved_item, ctx, - true, fntype); - } - } + HIR::PathExprSegment method_name = expr.get_method_name (); + HIR::PathIdentSegment segment_name = method_name.get_segment (); + 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; |