diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 103 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 12 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-type.cc | 22 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 18 |
4 files changed, 83 insertions, 72 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)); diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 8aeb703..bb81d4e 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -789,11 +789,13 @@ public: void visit (HIR::AsyncBlockExpr &) override {} protected: - tree 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); + tree get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn, + TyTy::BaseType *receiver, TyTy::FnType *fntype, + tree receiver_ref, Location expr_locus); + + tree get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn, + TyTy::BaseType *receiver, TyTy::FnType *fntype, + tree receiver_ref, Location expr_locus); tree resolve_method_address (TyTy::FnType *fntype, HirId ref, TyTy::BaseType *receiver, diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 16029ba..03c2ca4 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -532,25 +532,19 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) tree uint = ctx->get_backend ()->integer_type ( true, ctx->get_backend ()->get_pointer_size ()); - tree uintptr_ty = ctx->get_backend ()->pointer_type (uint); + tree uintptr_ty = build_pointer_type (uint); - Backend::typed_identifier f ("__receiver_trait_obj_ptr", uintptr_ty, + Backend::typed_identifier f ("pointer", uintptr_ty, ctx->get_mappings ()->lookup_location ( type.get_ty_ref ())); fields.push_back (std::move (f)); - for (size_t i = 0; i < items.size (); i++) - { - // mrustc seems to make a vtable consisting of uintptr's - tree uint = ctx->get_backend ()->integer_type ( - true, ctx->get_backend ()->get_pointer_size ()); - tree uintptr_ty = ctx->get_backend ()->pointer_type (uint); - - Backend::typed_identifier f ("__" + std::to_string (i), uintptr_ty, - ctx->get_mappings ()->lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); - } + tree vtable_size = build_int_cst (size_type_node, items.size ()); + tree vtable_type = ctx->get_backend ()->array_type (uintptr_ty, vtable_size); + Backend::typed_identifier vtf ("vtable", vtable_type, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + fields.push_back (std::move (vtf)); tree type_record = ctx->get_backend ()->struct_type (fields); tree named_struct diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index db22227..49155d2 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -312,6 +312,9 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, Location locus) { tree dynamic_object = TyTyResolveCompile::compile (ctx, ty); + tree dynamic_object_fields = TYPE_FIELDS (dynamic_object); + tree vtable_field = DECL_CHAIN (dynamic_object_fields); + rust_assert (TREE_CODE (TREE_TYPE (vtable_field)) == ARRAY_TYPE); //' this assumes ordering and current the structure is // __trait_object_ptr @@ -326,8 +329,10 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, = address_expression (compiled_ref, build_pointer_type (TREE_TYPE (compiled_ref)), locus); - std::vector<tree> vals; - vals.push_back (address_of_compiled_ref); + + std::vector<tree> vtable_ctor_elems; + std::vector<unsigned long> vtable_ctor_idx; + unsigned long i = 0; for (auto &bound : ty->get_object_items ()) { const Resolver::TraitItemReference *item = bound.first; @@ -336,11 +341,16 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, auto address = compute_address_for_trait_item (item, predicate, probed_bounds_for_receiver, actual, actual, locus); - vals.push_back (address); + vtable_ctor_elems.push_back (address); + vtable_ctor_idx.push_back (i++); } + tree vtable_ctor = ctx->get_backend ()->array_constructor_expression ( + TREE_TYPE (vtable_field), vtable_ctor_idx, vtable_ctor_elems, locus); + + std::vector<tree> dyn_ctor = {address_of_compiled_ref, vtable_ctor}; return ctx->get_backend ()->constructor_expression (dynamic_object, false, - vals, -1, locus); + dyn_ctor, -1, locus); } tree |