aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-09-13 16:31:18 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-09-13 16:33:58 +0100
commit9464066111c715a63e632b1dc60f3230e8c48bb1 (patch)
treeb1bcaa2f68d4fc74e4e90ff6d608613e4f11a8a7 /gcc
parente3b7eb58844c446d097ddee00ecd455d5537c6b2 (diff)
downloadgcc-9464066111c715a63e632b1dc60f3230e8c48bb1.zip
gcc-9464066111c715a63e632b1dc60f3230e8c48bb1.tar.gz
gcc-9464066111c715a63e632b1dc60f3230e8c48bb1.tar.bz2
Support indirection for struct and tuple field access
When we have a fat pointer to a structure the GCC needs to know the RECORD or UNION type of the type before it can access fields, this can be supported by C'stye indirection such as '->'. This might get updated when we support the autoderef mechanism and if the type supports the deref trait. Addresses #241
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.h51
-rw-r--r--gcc/rust/lint/rust-lint-marklive.cc20
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h17
-rw-r--r--gcc/testsuite/rust/compile/torture/autoderef1.rs15
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;
+}