From: Enes Cevik <[email protected]>
This patch implements the 'unsafe_cell' lang item to the compilers.
Since, gccrs currently lacks niche-filling optimizations, this patch
does not include any changes related to type layout sizes.
gcc/rust/ChangeLog:
* backend/rust-compile-type.cc
(TyTyResolveCompile::visit): If type contains unsafe_cell type,
do not mark it as const.
* typecheck/rust-tyty.cc (ADTType::contains_unsafe_cell): New
function.
(TupleType::contains_unsafe_cell): Likewise.
(ArrayType::contains_unsafe_cell): Likewise.
(SliceType::contains_unsafe_cell): Likewise.
* typecheck/rust-tyty.h (contains_unsafe_cell): New declaration.
* util/rust-lang-item.cc (Rust::LangItem::lang_items): Add
unsafe_cell to the BiMap.
* util/rust-lang-item.h (class LangItem): Add UNSAFE_CELL to the
Kind enum.
gcc/testsuite/ChangeLog:
* rust/compile/unsafe_cell.rs: New test.
Signed-off-by: Enes Cevik <[email protected]>
---
gcc/rust/backend/rust-compile-type.cc | 12 ++++++-
gcc/rust/typecheck/rust-tyty.cc | 38 +++++++++++++++++++++++
gcc/rust/typecheck/rust-tyty.h | 10 ++++++
gcc/rust/util/rust-lang-item.cc | 2 ++
gcc/rust/util/rust-lang-item.h | 2 ++
gcc/testsuite/rust/compile/unsafe_cell.rs | 16 ++++++++++
6 files changed, 79 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/rust/compile/unsafe_cell.rs
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index f0c2d1bf1e0..eed8fd734c9 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -773,7 +773,17 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
}
else
{
- auto base = Backend::immutable_type (base_compiled_type);
+ // https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html
+ // If you have a reference &T, then normally in Rust the compiler performs
+ // optimizations based on the knowledge that &T points to immutable data.
+ // Mutating that data, for example through an alias or by transmuting a &T
+ // into a &mut T, is considered undefined behavior. UnsafeCell<T> opts-out
+ // of the immutability guarantee for &T: a shared reference &UnsafeCell<T>
+ // may point to data that is being mutated. This is called “interior
+ // mutability”.
+ auto base = type.get_base ()->contains_unsafe_cell ()
+ ? base_compiled_type
+ : Backend::immutable_type (base_compiled_type);
translated = Backend::reference_type (base);
}
}
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index bc26692058a..af43b1c122a 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -2053,6 +2053,23 @@ ADTType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
return adt;
}
+bool
+ADTType::contains_unsafe_cell () const
+{
+ if (auto unsafe_cell
+ = mappings.lookup_lang_item (LangItem::Kind::UNSAFE_CELL))
+ {
+ if (get_id () == *unsafe_cell)
+ return true;
+
+ for (auto &variant : get_variants ())
+ for (auto &field : variant->get_fields ())
+ if (field->get_field_type ()->contains_unsafe_cell ())
+ return true;
+ }
+ return false;
+}
+
// TupleType
TupleType::TupleType (HirId ref, location_t locus, std::vector<TyVar> fields,
@@ -2206,6 +2223,15 @@ TupleType::handle_substitions (SubstitutionArgumentMappings &mappings)
return tuple;
}
+bool
+TupleType::contains_unsafe_cell () const
+{
+ for (auto &field : get_fields ())
+ if (field.get_tyty ()->contains_unsafe_cell ())
+ return true;
+ return false;
+}
+
void
FnType::accept_vis (TyVisitor &vis)
{
@@ -2670,6 +2696,12 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings)
return ref;
}
+bool
+ArrayType::contains_unsafe_cell () const
+{
+ return get_element_type ()->contains_unsafe_cell ();
+}
+
void
SliceType::accept_vis (TyVisitor &vis)
{
@@ -2737,6 +2769,12 @@ SliceType::handle_substitions (SubstitutionArgumentMappings &mappings)
return ref;
}
+bool
+SliceType::contains_unsafe_cell () const
+{
+ return get_element_type ()->contains_unsafe_cell ();
+}
+
// BoolType
BoolType::BoolType (HirId ref, std::set<HirId> refs)
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index ec9b71123ba..3eaf23a3ce8 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -356,6 +356,8 @@ public:
virtual BaseConstType *as_const_type () { return nullptr; }
virtual const BaseConstType *as_const_type () const { return nullptr; }
+ virtual bool contains_unsafe_cell () const { return false; }
+
protected:
BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
std::set<HirId> refs = std::set<HirId> ());
@@ -793,6 +795,8 @@ public:
TupleType *handle_substitions (SubstitutionArgumentMappings &mappings);
+ bool contains_unsafe_cell () const override;
+
private:
std::vector<TyVar> fields;
};
@@ -1035,6 +1039,8 @@ public:
ADTType *
handle_substitions (SubstitutionArgumentMappings &mappings) override final;
+ bool contains_unsafe_cell () const override;
+
private:
DefId id;
std::string identifier;
@@ -1395,6 +1401,8 @@ public:
ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
+ bool contains_unsafe_cell () const override;
+
private:
TyVar element_type;
TyVar capacity;
@@ -1435,6 +1443,8 @@ public:
SliceType *handle_substitions (SubstitutionArgumentMappings &mappings);
+ bool contains_unsafe_cell () const override;
+
private:
TyVar element_type;
};
diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index c58ab401fd1..e7bcc8f8e48 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -133,6 +133,8 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
{"box_free", Kind::BOX_FREE},
{"maybe_uninit", Kind::MAYBE_UNINIT},
+ {"unsafe_cell", Kind::UNSAFE_CELL},
+
{"future_trait", Kind::FUTURE_TRAIT},
{"poll", Kind::POLL},
{"Ready", Kind::READY},
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index d6bea1a8e43..c1fd45d043d 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -169,6 +169,8 @@ public:
BOX_FREE,
MAYBE_UNINIT,
+ UNSAFE_CELL,
+
FUTURE_TRAIT,
POLL,
READY,
diff --git a/gcc/testsuite/rust/compile/unsafe_cell.rs b/gcc/testsuite/rust/compile/unsafe_cell.rs
new file mode 100644
index 00000000000..0df31080f83
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe_cell.rs
@@ -0,0 +1,16 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "unsafe_cell"]
+pub struct UnsafeCell<T> { _v: T }
+
+pub fn normal_ref(_a: &i32) {}
+
+pub fn unsafe_ref(_b: &UnsafeCell<i32>) {}
+
+// { dg-final { scan-tree-dump "normal_ref \\(const i32 & const _a\\)" "gimple" } }
+// { dg-final { scan-tree-dump "unsafe_ref \\(struct unsafe_cell::UnsafeCell<i32> & const _b\\)" "gimple" } }
--
2.50.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.