aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2023-05-08 14:10:57 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-16 18:37:15 +0100
commitc9600aa54d7412f5bbff97be2046c8054e201c3c (patch)
tree3291eb32d16f0c1e15ee99ae4f10910fcf4df5d9
parente857a3b67905628c97360df77f8f2c8456e4e7b9 (diff)
downloadgcc-c9600aa54d7412f5bbff97be2046c8054e201c3c.zip
gcc-c9600aa54d7412f5bbff97be2046c8054e201c3c.tar.gz
gcc-c9600aa54d7412f5bbff97be2046c8054e201c3c.tar.bz2
gccrs: unify how we handle DST's
DST's are not truely reference types they are "unsized types" so the exact size of them is not known at compile time. We actually achieve this by pretending they are a reference but really its struct we pass around. Fixes #2180 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): refactr (CompileExpr::get_fn_addr_from_dyn): likewise (CompileExpr::get_receiver_from_dyn): likewise (CompileExpr::type_cast_expression): likewise * backend/rust-compile-type.cc (TyTyResolveCompile::visit): likewise (TyTyResolveCompile::create_dyn_obj_record): likewise (TyTyResolveCompile::create_slice_type_record): likewise (TyTyResolveCompile::create_str_type_record): likewise * backend/rust-compile-type.h: likewise * backend/rust-compile.cc (HIRCompileBase::coercion_site1): likewise (HIRCompileBase::coerce_to_dyn_object): refactor * backend/rust-tree.h (SLICE_FLAG): removed (SLICE_TYPE_P): removed (RS_DST_FLAG): new flag (RS_DST_FLAG_P): new predicate * typecheck/rust-tyty.cc (ReferenceType::is_dyn_object): new helper (ReferenceType::is_dyn_obj_type): likewise (PointerType::is_dyn_object): likewise (PointerType::is_dyn_obj_type): likewise * typecheck/rust-tyty.h (class DynamicObjectType): moved up gcc/testsuite/ChangeLog: * rust/execute/torture/issue-2180.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc27
-rw-r--r--gcc/rust/backend/rust-compile-type.cc47
-rw-r--r--gcc/rust/backend/rust-compile-type.h1
-rw-r--r--gcc/rust/backend/rust-compile.cc14
-rw-r--r--gcc/rust/backend/rust-tree.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc30
-rw-r--r--gcc/rust/typecheck/rust-tyty.h62
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-2180.rs34
8 files changed, 157 insertions, 62 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 07e5d79..59afc01 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -29,6 +29,7 @@
#include "fold-const.h"
#include "realmpfr.h"
#include "convert.h"
+#include "print-tree.h"
namespace Rust {
namespace Compile {
@@ -791,7 +792,7 @@ void
CompileExpr::visit (HIR::BorrowExpr &expr)
{
tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
- if (SLICE_TYPE_P (TREE_TYPE (main_expr)))
+ if (RS_DST_FLAG_P (TREE_TYPE (main_expr)))
{
translated = main_expr;
return;
@@ -836,7 +837,7 @@ CompileExpr::visit (HIR::DereferenceExpr &expr)
}
tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
- if (SLICE_TYPE_P (TREE_TYPE (main_expr)) && SLICE_TYPE_P (expected_type))
+ if (RS_DST_FLAG_P (TREE_TYPE (main_expr)) && RS_DST_FLAG_P (expected_type))
{
translated = main_expr;
return;
@@ -908,6 +909,10 @@ CompileExpr::visit (HIR::AssignmentExpr &expr)
expected, expr.get_lhs ()->get_locus (),
expr.get_rhs ()->get_locus ());
+ // rust_debug_loc (expr.get_locus (), "XXXXXX assignment");
+ // debug_tree (rvalue);
+ // debug_tree (lvalue);
+
tree assignment
= ctx->get_backend ()->assignment_statement (lvalue, rvalue,
expr.get_locus ());
@@ -1810,13 +1815,6 @@ CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn,
if (ref == nullptr)
return error_mark_node;
- // get any indirection sorted out
- if (receiver->get_kind () == TyTy::TypeKind::REF)
- {
- tree indirect = indirect_expression (receiver_ref, expr_locus);
- receiver_ref = indirect;
- }
-
// cast it to the correct fntype
tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true);
tree idx = build_int_cst (size_type_node, offs);
@@ -1841,13 +1839,6 @@ CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn,
TyTy::FnType *fntype, tree receiver_ref,
Location expr_locus)
{
- // get any indirection sorted out
- if (receiver->get_kind () == TyTy::TypeKind::REF)
- {
- tree indirect = indirect_expression (receiver_ref, expr_locus);
- receiver_ref = indirect;
- }
-
// 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);
@@ -2130,7 +2121,7 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
type_to_cast_to, expr_tree);
}
else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
- && SLICE_TYPE_P (TREE_TYPE (expr_tree)))
+ && RS_DST_FLAG (TREE_TYPE (expr_tree)))
{
// returning a raw cast using NOP_EXPR seems to resut in an ICE:
//
@@ -2327,7 +2318,7 @@ HIRCompileBase::resolve_adjustements (
case Resolver::Adjustment::AdjustmentType::IMM_REF:
case Resolver::Adjustment::AdjustmentType::MUT_REF: {
- if (!SLICE_TYPE_P (TREE_TYPE (e)))
+ if (!RS_DST_FLAG (TREE_TYPE (e)))
{
e = address_expression (e, locus);
}
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 29f7cca..76b38c5 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -576,6 +576,7 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
{
const TyTy::SliceType *slice = nullptr;
const TyTy::StrType *str = nullptr;
+ const TyTy::DynamicObjectType *dyn = nullptr;
if (type.is_dyn_slice_type (&slice))
{
tree type_record = create_slice_type_record (*slice);
@@ -601,6 +602,18 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
return;
}
+ else if (type.is_dyn_obj_type (&dyn))
+ {
+ tree type_record = create_dyn_obj_record (*dyn);
+ std::string dyn_str_type_str
+ = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
+
+ translated
+ = ctx->get_backend ()->named_type (dyn_str_type_str, type_record,
+ dyn->get_locus ());
+
+ return;
+ }
tree base_compiled_type
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
@@ -620,6 +633,7 @@ TyTyResolveCompile::visit (const TyTy::PointerType &type)
{
const TyTy::SliceType *slice = nullptr;
const TyTy::StrType *str = nullptr;
+ const TyTy::DynamicObjectType *dyn = nullptr;
if (type.is_dyn_slice_type (&slice))
{
tree type_record = create_slice_type_record (*slice);
@@ -645,6 +659,19 @@ TyTyResolveCompile::visit (const TyTy::PointerType &type)
return;
}
+ else if (type.is_dyn_obj_type (&dyn))
+ {
+ tree type_record = create_dyn_obj_record (*dyn);
+ std::string dyn_str_type_str
+ = std::string (type.is_mutable () ? "*mut " : "*const ")
+ + dyn->get_name ();
+
+ translated
+ = ctx->get_backend ()->named_type (dyn_str_type_str, type_record,
+ dyn->get_locus ());
+
+ return;
+ }
tree base_compiled_type
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
@@ -684,6 +711,14 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
return;
}
+ tree type_record = create_dyn_obj_record (type);
+ translated = ctx->get_backend ()->named_type (type.get_name (), type_record,
+ type.get_ident ().locus);
+}
+
+tree
+TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
+{
// create implicit struct
auto items = type.get_object_items ();
std::vector<Backend::typed_identifier> fields;
@@ -704,9 +739,11 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
type.get_ty_ref ()));
fields.push_back (std::move (vtf));
- tree type_record = ctx->get_backend ()->struct_type (fields);
- translated = ctx->get_backend ()->named_type (type.get_name (), type_record,
- type.get_ident ().locus);
+ tree record = ctx->get_backend ()->struct_type (fields);
+ RS_DST_FLAG (record) = 1;
+ TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
+
+ return record;
}
tree
@@ -727,7 +764,7 @@ TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
tree record = ctx->get_backend ()->struct_type ({data_field, len_field});
- SLICE_FLAG (record) = 1;
+ RS_DST_FLAG (record) = 1;
TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
return record;
@@ -753,7 +790,7 @@ TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
tree record = ctx->get_backend ()->struct_type ({data_field, len_field});
- SLICE_FLAG (record) = 1;
+ RS_DST_FLAG (record) = 1;
TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
return record;
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index ce13795..44bd218 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -65,6 +65,7 @@ public:
protected:
tree create_slice_type_record (const TyTy::SliceType &type);
tree create_str_type_record (const TyTy::StrType &type);
+ tree create_dyn_obj_record (const TyTy::DynamicObjectType &type);
private:
TyTyResolveCompile (Context *ctx, bool trait_object_mode);
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index ea7cc15..a5d6abb 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -78,7 +78,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval,
if (expected->get_kind () == TyTy::TypeKind::REF)
{
// this is a dyn object
- if (SLICE_TYPE_P (TREE_TYPE (rvalue)))
+ if (RS_DST_FLAG_P (TREE_TYPE (rvalue)))
{
return rvalue;
}
@@ -96,7 +96,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval,
tree coerced
= coercion_site1 (deref_rvalue, act->get_base (), exp->get_base (),
lvalue_locus, rvalue_locus);
- if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced)))
+ if (exp->is_dyn_object () && RS_DST_FLAG_P (TREE_TYPE (coerced)))
return coerced;
return address_expression (coerced, rvalue_locus);
@@ -104,7 +104,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval,
else if (expected->get_kind () == TyTy::TypeKind::POINTER)
{
// this is a dyn object
- if (SLICE_TYPE_P (TREE_TYPE (rvalue)))
+ if (RS_DST_FLAG_P (TREE_TYPE (rvalue)))
{
return rvalue;
}
@@ -140,7 +140,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval,
= coercion_site1 (deref_rvalue, actual_base, exp->get_base (),
lvalue_locus, rvalue_locus);
- if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced)))
+ if (exp->is_dyn_object () && RS_DST_FLAG_P (TREE_TYPE (coerced)))
return coerced;
return address_expression (coerced, rvalue_locus);
@@ -183,7 +183,11 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref,
const TyTy::DynamicObjectType *ty,
Location locus)
{
- tree dynamic_object = TyTyResolveCompile::compile (ctx, ty);
+ // DST's get wrapped in a pseudo reference that doesnt exist...
+ const TyTy::ReferenceType r (ctx->get_mappings ()->get_next_hir_id (),
+ TyTy::TyVar (ty->get_ref ()), Mutability::Imm);
+
+ tree dynamic_object = TyTyResolveCompile::compile (ctx, &r);
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);
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 1f0e12f..b4c058f 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -78,8 +78,8 @@
// this is a helper to differentiate RECORD types between actual records and
// slices
-#define SLICE_FLAG TREE_LANG_FLAG_0
-#define SLICE_TYPE_P(TYPE) \
+#define RS_DST_FLAG TREE_LANG_FLAG_0
+#define RS_DST_FLAG_P(TYPE) \
(TREE_CODE (TYPE) == RECORD_TYPE && TREE_LANG_FLAG_0 (TYPE))
// lambda?
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 1c67318..5e9af52 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -2961,7 +2961,7 @@ ReferenceType::is_mutable () const
bool
ReferenceType::is_dyn_object () const
{
- return is_dyn_slice_type () || is_dyn_str_type ();
+ return is_dyn_slice_type () || is_dyn_str_type () || is_dyn_obj_type ();
}
bool
@@ -2990,6 +2990,19 @@ ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const
return true;
}
+bool
+ReferenceType::is_dyn_obj_type (const TyTy::DynamicObjectType **dyn) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::DYNAMIC)
+ return false;
+ if (dyn == nullptr)
+ return true;
+
+ *dyn = static_cast<const TyTy::DynamicObjectType *> (element);
+ return true;
+}
+
void
ReferenceType::accept_vis (TyVisitor &vis)
{
@@ -3112,7 +3125,7 @@ PointerType::is_const () const
bool
PointerType::is_dyn_object () const
{
- return is_dyn_slice_type () || is_dyn_str_type ();
+ return is_dyn_slice_type () || is_dyn_str_type () || is_dyn_obj_type ();
}
bool
@@ -3141,6 +3154,19 @@ PointerType::is_dyn_str_type (const TyTy::StrType **str) const
return true;
}
+bool
+PointerType::is_dyn_obj_type (const TyTy::DynamicObjectType **dyn) const
+{
+ const TyTy::BaseType *element = get_base ()->destructure ();
+ if (element->get_kind () != TyTy::TypeKind::DYNAMIC)
+ return false;
+ if (dyn == nullptr)
+ return true;
+
+ *dyn = static_cast<const TyTy::DynamicObjectType *> (element);
+ return true;
+}
+
void
PointerType::accept_vis (TyVisitor &vis)
{
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index cd6be34..a6a373a 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1147,6 +1147,36 @@ public:
BaseType *clone () const final override;
};
+class DynamicObjectType : public BaseType
+{
+public:
+ DynamicObjectType (HirId ref, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ BaseType *clone () const final override;
+
+ std::string get_name () const override final;
+
+ // this returns a flat list of items including super trait bounds
+ const std::vector<
+ std::pair<const Resolver::TraitItemReference *, const TypeBoundPredicate *>>
+ get_object_items () const;
+};
+
class ReferenceType : public BaseType
{
public:
@@ -1179,6 +1209,7 @@ public:
bool is_dyn_object () const;
bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
+ bool is_dyn_obj_type (const TyTy::DynamicObjectType **dyn = nullptr) const;
private:
TyVar base;
@@ -1216,6 +1247,7 @@ public:
bool is_dyn_object () const;
bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const;
bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const;
+ bool is_dyn_obj_type (const TyTy::DynamicObjectType **dyn = nullptr) const;
private:
TyVar base;
@@ -1328,36 +1360,6 @@ private:
DefId item;
};
-class DynamicObjectType : public BaseType
-{
-public:
- DynamicObjectType (HirId ref, RustIdent ident,
- std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ());
-
- DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
- std::vector<TypeBoundPredicate> specified_bounds,
- std::set<HirId> refs = std::set<HirId> ());
-
- void accept_vis (TyVisitor &vis) override;
- void accept_vis (TyConstVisitor &vis) const override;
-
- std::string as_string () const override;
-
- bool can_eq (const BaseType *other, bool emit_errors) const override final;
-
- bool is_equal (const BaseType &other) const override;
-
- BaseType *clone () const final override;
-
- std::string get_name () const override final;
-
- // this returns a flat list of items including super trait bounds
- const std::vector<
- std::pair<const Resolver::TraitItemReference *, const TypeBoundPredicate *>>
- get_object_items () const;
-};
-
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/testsuite/rust/execute/torture/issue-2180.rs b/gcc/testsuite/rust/execute/torture/issue-2180.rs
new file mode 100644
index 0000000..3a7ea10
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-2180.rs
@@ -0,0 +1,34 @@
+// { dg-output "123\n" }
+trait A {
+ fn get_int(&self) -> i32;
+}
+
+impl A for i32 {
+ fn get_int(&self) -> i32 {
+ *self
+ }
+}
+
+fn get_dyn_a(x: &i32) -> &dyn A {
+ x as &dyn A
+}
+
+fn clobber_stack() {
+ let _z: [usize; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...) -> i32;
+}
+
+fn main() -> i32 {
+ let x = 123;
+ let y = get_dyn_a(&x);
+ clobber_stack();
+ let value = y.get_int();
+ let fmt_string = "%d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(fmt_string, value);
+ }
+ return 0;
+}