aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-05-23 14:57:55 +0000
committerGitHub <noreply@github.com>2022-05-23 14:57:55 +0000
commitbf6d540b1043bb944450dfe9da4c91124cdf31d3 (patch)
tree6edb9359d5ac9d9b63938019e0fd9b336c1dd43e /gcc/rust/backend
parent63762cc243c643c10aca7e07dfd6abe9b78748f8 (diff)
parentcd39861da5e1113207193bb8b3e6fb3dde92895f (diff)
downloadgcc-bf6d540b1043bb944450dfe9da4c91124cdf31d3.zip
gcc-bf6d540b1043bb944450dfe9da4c91124cdf31d3.tar.gz
gcc-bf6d540b1043bb944450dfe9da4c91124cdf31d3.tar.bz2
Merge #1268
1268: Fix Slice Type Layout r=philberty a=philberty Slices in Rust are represented by TypePaths such as '[i32]'. Though if you actually try to use this explicit type-path you will hit errors such as this type has an unknown size at compile time. This is because this is actually what Rust calls a dynamically sized type. This means when you use types such as: '&[i32]' it is not actually a reference type to a slice. Its a slice in its entirety this means for lack of a better word when you use '*const [i32]' or '&mut [i32]' we end up actually passing around a struct by value _not_ at pointer/reference to it. This patch changes the type-layout so that we handle this layout change properly. This patch will also need to be applied to str types which I believe have a similar layout for safety. The patch also sets up TYPE_MAIN_VARIANT so that we can avoid unnessecary view_convert_expressions between *const [i32] and &mut [i32] which will have the same layout. Reference: https://doc.rust-lang.org/reference/dynamically-sized-types.html https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=672adac002939a2dab43b8d231adc1dc Fixes #1232 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-compile-context.h12
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc56
-rw-r--r--gcc/rust/backend/rust-compile-type.cc82
-rw-r--r--gcc/rust/backend/rust-compile-type.h8
-rw-r--r--gcc/rust/backend/rust-compile.cc19
-rw-r--r--gcc/rust/backend/rust-tree.h6
6 files changed, 156 insertions, 27 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 8378554..096b65f 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -67,6 +67,17 @@ public:
return type;
}
+ tree insert_main_variant (tree type)
+ {
+ hashval_t h = type_hasher (type);
+ auto it = main_variants.find (h);
+ if (it != main_variants.end ())
+ return it->second;
+
+ main_variants.insert ({h, type});
+ return type;
+ }
+
::Backend *get_backend () { return backend; }
Resolver::Resolver *get_resolver () { return resolver; }
Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
@@ -314,6 +325,7 @@ private:
std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>>
mono_fns;
std::map<HirId, tree> implicit_pattern_bindings;
+ std::map<hashval_t, tree> main_variants;
// To GCC middle-end
std::vector<tree> type_decls;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 824d6d3..b176ed2 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -123,6 +123,11 @@ void
CompileExpr::visit (HIR::BorrowExpr &expr)
{
tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx);
+ if (SLICE_TYPE_P (TREE_TYPE (main_expr)))
+ {
+ translated = main_expr;
+ return;
+ }
TyTy::BaseType *tyty = nullptr;
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
@@ -164,6 +169,12 @@ 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))
+ {
+ translated = main_expr;
+ return;
+ }
+
bool known_valid = true;
translated
= ctx->get_backend ()->indirect_expression (expected_type, main_expr,
@@ -1092,6 +1103,32 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
return fold_build1_loc (location.gcc_location (), VIEW_CONVERT_EXPR,
type_to_cast_to, expr_tree);
}
+ else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE
+ && SLICE_TYPE_P (TREE_TYPE (expr_tree)))
+ {
+ // returning a raw cast using NOP_EXPR seems to resut in an ICE:
+ //
+ // Analyzing compilation unit
+ // Performing interprocedural optimizations
+ // <*free_lang_data> {heap 2644k} <visibility> {heap 2644k}
+ // <build_ssa_passes> {heap 2644k} <opt_local_passes> {heap 2644k}during
+ // GIMPLE pass: cddce
+ // In function ‘*T::as_ptr<i32>’:
+ // rust1: internal compiler error: in propagate_necessity, at
+ // tree-ssa-dce.cc:984 0x1d5b43e propagate_necessity
+ // ../../gccrs/gcc/tree-ssa-dce.cc:984
+ // 0x1d5e180 perform_tree_ssa_dce
+ // ../../gccrs/gcc/tree-ssa-dce.cc:1876
+ // 0x1d5e2c8 tree_ssa_cd_dce
+ // ../../gccrs/gcc/tree-ssa-dce.cc:1920
+ // 0x1d5e49a execute
+ // ../../gccrs/gcc/tree-ssa-dce.cc:1992
+
+ // this is returning the direct raw pointer of the slice an assumes a very
+ // specific layout
+ return ctx->get_backend ()->struct_field_expression (expr_tree, 0,
+ location);
+ }
return fold_convert_loc (location.gcc_location (), type_to_cast_to,
expr_tree);
@@ -1261,9 +1298,13 @@ HIRCompileBase::resolve_adjustements (
case Resolver::Adjustment::AdjustmentType::IMM_REF:
case Resolver::Adjustment::AdjustmentType::MUT_REF: {
- tree ptrtype
- = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
- e = address_expression (e, ptrtype, locus);
+ if (!SLICE_TYPE_P (TREE_TYPE (e)))
+ {
+ tree ptrtype
+ = TyTyResolveCompile::compile (ctx,
+ adjustment.get_expected ());
+ e = address_expression (e, ptrtype, locus);
+ }
}
break;
@@ -1619,6 +1660,15 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr)
index, expr.get_array_expr (),
expr.get_index_expr ());
+ tree actual_type = TREE_TYPE (operator_overload_call);
+ bool can_indirect = TYPE_PTR_P (actual_type) || TYPE_REF_P (actual_type);
+ if (!can_indirect)
+ {
+ // nothing to do
+ translated = operator_overload_call;
+ return;
+ }
+
// lookup the expected type for this expression
TyTy::BaseType *tyty = nullptr;
bool ok
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 102bc0a..707b2af 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -25,6 +25,13 @@
namespace Rust {
namespace Compile {
+static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
+
+TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
+ : ctx (ctx), trait_object_mode (trait_object_mode),
+ translated (error_mark_node), recurisve_ops (0)
+{}
+
tree
TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
bool trait_object_mode)
@@ -42,8 +49,6 @@ TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
return compiler.translated;
}
-static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
-
// see: gcc/c/c-decl.cc:8230-8241
// https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
tree
@@ -375,24 +380,7 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
void
TyTyResolveCompile::visit (const TyTy::SliceType &type)
{
- std::vector<Backend::typed_identifier> fields;
-
- tree element_type
- = TyTyResolveCompile::compile (ctx, type.get_element_type ());
- tree data_field_ty = build_pointer_type (element_type);
- Backend::typed_identifier data_field ("data", data_field_ty, Location ());
- fields.push_back (std::move (data_field));
-
- // lookup usize
- TyTy::BaseType *usize = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
- rust_assert (ok);
-
- tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
- Backend::typed_identifier len_field ("len", len_field_ty, Location ());
- fields.push_back (std::move (len_field));
-
- tree type_record = ctx->get_backend ()->struct_type (fields);
+ tree type_record = create_slice_type_record (type);
std::string named_struct_str
= std::string ("[") + type.get_element_type ()->get_name () + "]";
@@ -536,6 +524,21 @@ TyTyResolveCompile::visit (const TyTy::CharType &type)
void
TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
{
+ const TyTy::SliceType *slice = nullptr;
+ if (type.is_dyn_slice_type (&slice))
+ {
+ tree type_record = create_slice_type_record (*slice);
+ std::string dyn_slice_type_str
+ = std::string (type.is_mutable () ? "&mut " : "&") + "["
+ + slice->get_element_type ()->get_name () + "]";
+
+ translated
+ = ctx->get_backend ()->named_type (dyn_slice_type_str, type_record,
+ slice->get_locus ());
+
+ return;
+ }
+
tree base_compiled_type
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
if (type.is_mutable ())
@@ -552,6 +555,21 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
void
TyTyResolveCompile::visit (const TyTy::PointerType &type)
{
+ const TyTy::SliceType *slice = nullptr;
+ if (type.is_dyn_slice_type (&slice))
+ {
+ tree type_record = create_slice_type_record (*slice);
+ std::string dyn_slice_type_str
+ = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
+ + slice->get_element_type ()->get_name () + "]";
+
+ translated
+ = ctx->get_backend ()->named_type (dyn_slice_type_str, type_record,
+ slice->get_locus ());
+
+ return;
+ }
+
tree base_compiled_type
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
if (type.is_mutable ())
@@ -615,5 +633,29 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
type.get_ident ().locus);
}
+tree
+TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
+{
+ // lookup usize
+ TyTy::BaseType *usize = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
+ rust_assert (ok);
+
+ tree element_type
+ = TyTyResolveCompile::compile (ctx, type.get_element_type ());
+ tree data_field_ty = build_pointer_type (element_type);
+ Backend::typed_identifier data_field ("data", data_field_ty,
+ type.get_locus ());
+
+ tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
+ 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;
+ TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
+
+ return record;
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index 262b8fc..aefacea 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -60,11 +60,11 @@ public:
public:
static hashval_t type_hasher (tree type);
+protected:
+ tree create_slice_type_record (const TyTy::SliceType &type);
+
private:
- TyTyResolveCompile (Context *ctx, bool trait_object_mode)
- : ctx (ctx), trait_object_mode (trait_object_mode),
- translated (error_mark_node), recurisve_ops (0)
- {}
+ TyTyResolveCompile (Context *ctx, bool trait_object_mode);
Context *ctx;
bool trait_object_mode;
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index d9349d5..18a2df6 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -218,6 +218,11 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
= static_cast<const TyTy::ReferenceType *> (expected);
const TyTy::ReferenceType *act
= static_cast<const TyTy::ReferenceType *> (actual);
+ if (act->is_dyn_slice_type ())
+ {
+ // nothing to do
+ return rvalue;
+ }
tree expected_type = TyTyResolveCompile::compile (ctx, act->get_base ());
tree deref_rvalue
@@ -227,6 +232,8 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
tree coerced
= coercion_site (deref_rvalue, act->get_base (), exp->get_base (),
lvalue_locus, rvalue_locus);
+ if (exp->is_dyn_slice_type () && SLICE_TYPE_P (TREE_TYPE (coerced)))
+ return coerced;
return address_expression (coerced,
build_reference_type (TREE_TYPE (coerced)),
@@ -249,6 +256,12 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
{
const TyTy::ReferenceType *act
= static_cast<const TyTy::ReferenceType *> (actual);
+ if (act->is_dyn_slice_type ())
+ {
+ // nothing to do
+ return rvalue;
+ }
+
actual_base = act->get_base ();
expected_type = TyTyResolveCompile::compile (ctx, act->get_base ());
}
@@ -256,6 +269,12 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
{
const TyTy::PointerType *act
= static_cast<const TyTy::PointerType *> (actual);
+ if (act->is_dyn_slice_type ())
+ {
+ // nothing to do
+ return rvalue;
+ }
+
actual_base = act->get_base ();
expected_type = TyTyResolveCompile::compile (ctx, act->get_base ());
}
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index c50e090..2b480ad 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -74,6 +74,12 @@
(INDIRECT_REF_P (NODE) && TREE_TYPE (TREE_OPERAND (NODE, 0)) \
&& TYPE_REF_P (TREE_TYPE (TREE_OPERAND ((NODE), 0))))
+// 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) \
+ (TREE_CODE (TYPE) == RECORD_TYPE && TREE_LANG_FLAG_0 (TYPE))
+
namespace Rust {
// forked from gcc/cp/cvt.cc convert_to_void