diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-09-13 16:12:45 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-13 16:12:45 +0000 |
commit | c644ee4c4351e3590f5396e94ec24ad7b828a954 (patch) | |
tree | b1bcaa2f68d4fc74e4e90ff6d608613e4f11a8a7 /gcc | |
parent | e3b7eb58844c446d097ddee00ecd455d5537c6b2 (diff) | |
parent | 9464066111c715a63e632b1dc60f3230e8c48bb1 (diff) | |
download | gcc-c644ee4c4351e3590f5396e94ec24ad7b828a954.zip gcc-c644ee4c4351e3590f5396e94ec24ad7b828a954.tar.gz gcc-c644ee4c4351e3590f5396e94ec24ad7b828a954.tar.bz2 |
Merge #671
671: Support indirection for struct and tuple field access r=philberty a=philberty
This allows for fat pointers to be used for tuple or struct field access by
supporting the GCC indirect references by binding the type to the reference.
This might get updated when we support the autoderef mechanism and if the
type supports the deref trait.
Addresses #241
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 51 | ||||
-rw-r--r-- | gcc/rust/lint/rust-lint-marklive.cc | 20 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 17 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/autoderef1.rs | 15 |
4 files changed, 92 insertions, 11 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index ac33ccd..d0c0b74 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -46,6 +46,26 @@ public: TupleIndex index = expr.get_tuple_index (); Bexpression *receiver_ref = CompileExpr::Compile (tuple_expr, ctx); + + TyTy::BaseType *tuple_expr_ty = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + tuple_expr->get_mappings ().get_hirid (), &tuple_expr_ty); + rust_assert (ok); + + // do we need to add an indirect reference + if (tuple_expr_ty->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r + = static_cast<TyTy::ReferenceType *> (tuple_expr_ty); + TyTy::BaseType *tuple_type = r->get_base (); + Btype *tuple_tyty = TyTyResolveCompile::compile (ctx, tuple_type); + + Bexpression *indirect + = ctx->get_backend ()->indirect_expression (tuple_tyty, receiver_ref, + true, expr.get_locus ()); + receiver_ref = indirect; + } + translated = ctx->get_backend ()->struct_field_expression (receiver_ref, index, expr.get_locus ()); @@ -606,6 +626,9 @@ public: void visit (HIR::FieldAccessExpr &expr) override { + Bexpression *receiver_ref + = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); + // resolve the receiver back to ADT type TyTy::BaseType *receiver = nullptr; if (!ctx->get_tyctx ()->lookup_type ( @@ -615,17 +638,31 @@ public: "unresolved type for receiver"); return; } - rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT); - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); - size_t index = 0; - adt->get_field (expr.get_field_name (), &index); + size_t field_index = 0; + if (receiver->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); + adt->get_field (expr.get_field_name (), &field_index); + } + else if (receiver->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); + TyTy::BaseType *b = r->get_base (); + rust_assert (b->get_kind () == TyTy::TypeKind::ADT); - Bexpression *struct_ref - = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (b); + adt->get_field (expr.get_field_name (), &field_index); + Btype *adt_tyty = TyTyResolveCompile::compile (ctx, adt); + + Bexpression *indirect + = ctx->get_backend ()->indirect_expression (adt_tyty, receiver_ref, + true, expr.get_locus ()); + receiver_ref = indirect; + } translated - = ctx->get_backend ()->struct_field_expression (struct_ref, index, + = ctx->get_backend ()->struct_field_expression (receiver_ref, field_index, expr.get_locus ()); } diff --git a/gcc/rust/lint/rust-lint-marklive.cc b/gcc/rust/lint/rust-lint-marklive.cc index f383d48..0871291 100644 --- a/gcc/rust/lint/rust-lint-marklive.cc +++ b/gcc/rust/lint/rust-lint-marklive.cc @@ -214,9 +214,22 @@ MarkLive::visit (HIR::FieldAccessExpr &expr) rust_error_at (expr.get_receiver_expr ()->get_locus (), "unresolved type for receiver"); } - bool ok = receiver->get_kind () == TyTy::TypeKind::ADT; - rust_assert (ok); - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); + + TyTy::ADTType *adt = nullptr; + if (receiver->get_kind () == TyTy::TypeKind::ADT) + { + adt = static_cast<TyTy::ADTType *> (receiver); + } + else if (receiver->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); + TyTy::BaseType *b = r->get_base (); + rust_assert (b->get_kind () == TyTy::TypeKind::ADT); + + adt = static_cast<TyTy::ADTType *> (b); + } + + rust_assert (adt != nullptr); // get the field index size_t index = 0; @@ -228,6 +241,7 @@ MarkLive::visit (HIR::FieldAccessExpr &expr) adt->get_name ().c_str (), index); return; } + // get the field hir id HirId field_id = adt->get_field (index)->get_ref (); mark_hir_id (field_id); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 2744516..31c8909 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -64,13 +64,20 @@ public: { auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get (), inside_loop); - if (resolved == nullptr) + if (resolved->get_kind () == TyTy::TypeKind::ERROR) { rust_error_at (expr.get_tuple_expr ()->get_locus (), "failed to resolve TupleIndexExpr receiver"); return; } + // FIXME does this require autoderef here? + if (resolved->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (resolved); + resolved = r->get_base (); + } + bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT || resolved->get_kind () == TyTy::TypeKind::TUPLE; if (!is_valid_type) @@ -902,6 +909,14 @@ public: auto struct_base = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get (), false); + // FIXME does this require autoderef here? + if (struct_base->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r + = static_cast<TyTy::ReferenceType *> (struct_base); + struct_base = r->get_base (); + } + bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; if (!is_valid_type) { diff --git a/gcc/testsuite/rust/compile/torture/autoderef1.rs b/gcc/testsuite/rust/compile/torture/autoderef1.rs new file mode 100644 index 0000000..0cf070f --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/autoderef1.rs @@ -0,0 +1,15 @@ +struct Foo(i32, bool); +struct Bar { + a: i32, + b: bool, +} + +fn main() { + let a = &Foo(123, false); + let _b: i32 = a.0; + let _c: bool = a.1; + + let a = &Bar { a: 456, b: false }; + let _b: i32 = a.a; + let _c: bool = a.b; +} |