aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-09-13 16:12:45 +0000
committerGitHub <noreply@github.com>2021-09-13 16:12:45 +0000
commitc644ee4c4351e3590f5396e94ec24ad7b828a954 (patch)
treeb1bcaa2f68d4fc74e4e90ff6d608613e4f11a8a7 /gcc
parente3b7eb58844c446d097ddee00ecd455d5537c6b2 (diff)
parent9464066111c715a63e632b1dc60f3230e8c48bb1 (diff)
downloadgcc-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.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;
+}