diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-05-03 12:45:45 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-05-04 13:13:12 +0100 |
commit | 74f4ee8d38f5aa58e4722725f3016f6420d4654b (patch) | |
tree | be164dafb951987e1e8a25ac3be87c9555d0b6b3 /gcc/rust/backend/rust-compile-expr.cc | |
parent | 21b9e1226cfbc4137a881a71c5e6f904fc5b364e (diff) | |
download | gcc-74f4ee8d38f5aa58e4722725f3016f6420d4654b.zip gcc-74f4ee8d38f5aa58e4722725f3016f6420d4654b.tar.gz gcc-74f4ee8d38f5aa58e4722725f3016f6420d4654b.tar.bz2 |
Take advantage of OBJ_TYPE_REF'S in dyn calls
OBJ_TYPE_REF's are the gcc nodes that signify that this is a virtual call
which gives a hint to the optimizers for devirtualization.
Fixes #996
Fixes #854
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 103 |
1 files changed, 54 insertions, 49 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index eb7b0df..41f8c0a 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -573,6 +573,7 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) receiver = p->resolve (); } + tree fn_expr = error_mark_node; if (is_dyn_dispatch) { const TyTy::DynamicObjectType *dyn @@ -582,17 +583,20 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) for (auto &arg : expr.get_arguments ()) arguments.push_back (arg.get ()); - translated = compile_dyn_dispatch_call (dyn, receiver, fntype, self, - arguments, expr.get_locus ()); - return; + fn_expr + = get_fn_addr_from_dyn (dyn, receiver, fntype, self, expr.get_locus ()); + self = get_receiver_from_dyn (dyn, receiver, fntype, self, + expr.get_locus ()); + } + else + { + // lookup compiled functions since it may have already been compiled + HIR::PathExprSegment method_name = expr.get_method_name (); + HIR::PathIdentSegment segment_name = method_name.get_segment (); + fn_expr + = resolve_method_address (fntype, ref, receiver, segment_name, + expr.get_mappings (), expr.get_locus ()); } - - // lookup compiled functions since it may have already been compiled - HIR::PathExprSegment method_name = expr.get_method_name (); - HIR::PathIdentSegment segment_name = method_name.get_segment (); - tree 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; @@ -639,11 +643,10 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) } tree -CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, - TyTy::BaseType *receiver, - TyTy::FnType *fntype, tree receiver_ref, - std::vector<HIR::Expr *> &arguments, - Location expr_locus) +CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn, + TyTy::BaseType *receiver, + TyTy::FnType *fntype, tree receiver_ref, + Location expr_locus) { size_t offs = 0; const Resolver::TraitItemReference *ref = nullptr; @@ -680,32 +683,49 @@ CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, receiver_ref = indirect; } - // access the offs + 1 for the fnptr and offs=0 for the reciever obj - tree self_argument - = ctx->get_backend ()->struct_field_expression (receiver_ref, 0, - expr_locus); + // cast it to the correct fntype + tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true); + tree idx = build_int_cst (size_type_node, offs); - // access the vtable for the fn - tree fn_vtable_access - = ctx->get_backend ()->struct_field_expression (receiver_ref, offs + 1, + tree vtable_ptr + = ctx->get_backend ()->struct_field_expression (receiver_ref, 1, expr_locus); + tree vtable_array_access = build4_loc (expr_locus.gcc_location (), ARRAY_REF, + TREE_TYPE (TREE_TYPE (vtable_ptr)), + vtable_ptr, idx, NULL_TREE, NULL_TREE); - // cast it to the correct fntype - tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true); - tree fn_convert_expr - = ctx->get_backend ()->convert_expression (expected_fntype, - fn_vtable_access, expr_locus); + tree vcall + = build3_loc (expr_locus.gcc_location (), OBJ_TYPE_REF, expected_fntype, + vtable_array_access, receiver_ref, idx); + + return vcall; +} + +tree +CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn, + TyTy::BaseType *receiver, + TyTy::FnType *fntype, tree receiver_ref, + Location expr_locus) +{ + // get any indirection sorted out + if (receiver->get_kind () == TyTy::TypeKind::REF) - std::vector<tree> args; - args.push_back (self_argument); - for (auto &argument : arguments) { - tree compiled_expr = CompileExpr::Compile (argument, ctx); - args.push_back (compiled_expr); + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); + auto indirect_ty = r->get_base (); + tree indrect_compiled_tyty + = TyTyResolveCompile::compile (ctx, indirect_ty); + + tree indirect + = ctx->get_backend ()->indirect_expression (indrect_compiled_tyty, + receiver_ref, true, + expr_locus); + receiver_ref = indirect; } - return ctx->get_backend ()->call_expression (fn_convert_expr, args, nullptr, - expr_locus); + // access the offs + 1 for the fnptr and offs=0 for the reciever obj + return ctx->get_backend ()->struct_field_expression (receiver_ref, 0, + expr_locus); } tree @@ -832,8 +852,6 @@ CompileExpr::resolve_operator_overload ( &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) { @@ -841,19 +859,6 @@ CompileExpr::resolve_operator_overload ( receiver = p->resolve (); } - if (is_dyn_dispatch) - { - const TyTy::DynamicObjectType *dyn - = static_cast<const TyTy::DynamicObjectType *> (receiver->get_root ()); - - std::vector<HIR::Expr *> arguments; - if (rhs_expr != nullptr) // can be null for negation_expr (unary ones) - arguments.push_back (rhs_expr); - - return compile_dyn_dispatch_call (dyn, receiver, fntype, lhs, arguments, - expr.get_locus ()); - } - // lookup compiled functions since it may have already been compiled HIR::PathIdentSegment segment_name ( Analysis::RustLangItem::ToString (lang_item_type)); |