From: Philip Herron <[email protected]>

GCC makes this stuff really straight forward which is nice.

Fixes Rust-GCC/gccrs#4794

gcc/rust/ChangeLog:

        * backend/rust-compile-type.cc (TyTyResolveCompile::visit): make vector
        * rust-gcc.cc (struct_field_expression): we use bit field acces for 
lanes
        (constructor_expression): special case VECTOR
        (convert_tree): likewise for canonical main variant

gcc/testsuite/ChangeLog:

        * rust/compile/issue-4794.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/af4b290158f953c4a2c338207bfa78728204e49b

The commit has been mentioned in the following issue(s):
 - Rust-GCC/gccrs#4794: https://github.com/Rust-GCC/gccrs/issues/4794

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4795

 gcc/rust/backend/rust-compile-type.cc    |  8 ++++-
 gcc/rust/rust-gcc.cc                     | 40 +++++++++++++++++++++++-
 gcc/testsuite/rust/compile/issue-4794.rs | 35 +++++++++++++++++++++
 3 files changed, 81 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-4794.rs

diff --git a/gcc/rust/backend/rust-compile-type.cc 
b/gcc/rust/backend/rust-compile-type.cc
index c3fb34260..1a815b9ff 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -334,8 +334,14 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
            }
        }
     }
+  else if (repr.repr_kind == TyTy::ADTType::ReprKind::SIMD)
+    {
+      TyTy::VariantDef &variant = *type.get_variants ().at (0);
+      auto element = variant.get_fields ().at (0)->get_field_type ();
+      auto inner_type = compile (ctx, element);
 
-  // compilation of non-transparent ADTs below
+      type_record = build_vector_type (inner_type, variant.num_fields ());
+    }
   else if (!type.is_enum ())
     {
       rust_assert (type.number_of_variants () == 1);
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 00f356381..ada66a2c7 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -888,6 +888,18 @@ struct_field_expression (tree struct_tree, size_t index, 
location_t location)
 {
   if (error_operand_p (struct_tree))
     return error_mark_node;
+
+  if (VECTOR_TYPE_P (TREE_TYPE (struct_tree)))
+    {
+      tree vec_type = TREE_TYPE (struct_tree);
+      tree element_type = TREE_TYPE (vec_type);
+      tree part_width = TYPE_SIZE (element_type);
+      tree bit_offset = bitsize_int (index * tree_to_uhwi (part_width));
+
+      return fold_build3_loc (location, BIT_FIELD_REF, element_type,
+                             struct_tree, part_width, bit_offset);
+    }
+
   gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE
              || TREE_CODE (TREE_TYPE (struct_tree)) == UNION_TYPE);
   tree field = TYPE_FIELDS (TREE_TYPE (struct_tree));
@@ -1277,6 +1289,32 @@ constructor_expression (tree type_tree, bool is_variant,
   vec<constructor_elt, va_gc> *init;
   vec_alloc (init, union_index != -1 ? 1 : vals.size ());
 
+  if (VECTOR_TYPE_P (type_tree))
+    {
+      tree element_type = TREE_TYPE (type_tree);
+      bool is_constant = true;
+      for (size_t i = 0; i < vals.size (); ++i)
+       {
+         tree val = vals[i];
+         if (error_operand_p (val))
+           return error_mark_node;
+
+         constructor_elt empty = {NULL, NULL};
+         constructor_elt *elt = init->quick_push (empty);
+         elt->index = size_int (i);
+         elt->value = convert_tree (element_type, val, location);
+
+         if (!TREE_CONSTANT (elt->value))
+           is_constant = false;
+       }
+
+      tree ret = build_constructor (type_tree, init);
+      if (is_constant)
+       TREE_CONSTANT (ret) = 1;
+
+      return ret;
+    }
+
   tree sink = NULL_TREE;
   bool is_constant = true;
   tree field = TYPE_FIELDS (type_tree);
@@ -1951,7 +1989,7 @@ convert_tree (tree type_tree, tree expr_tree, location_t 
location)
     return fold_convert_loc (location, type_tree, expr_tree);
   else if (TREE_CODE (type_tree) == RECORD_TYPE
           || TREE_CODE (type_tree) == UNION_TYPE
-          || TREE_CODE (type_tree) == ARRAY_TYPE)
+          || TREE_CODE (type_tree) == ARRAY_TYPE || VECTOR_TYPE_P (type_tree))
     {
       gcc_assert (int_size_in_bytes (type_tree)
                  == int_size_in_bytes (TREE_TYPE (expr_tree)));
diff --git a/gcc/testsuite/rust/compile/issue-4794.rs 
b/gcc/testsuite/rust/compile/issue-4794.rs
new file mode 100644
index 000000000..a42523a32
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4794.rs
@@ -0,0 +1,35 @@
+#![feature(no_core, lang_items, repr_simd)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[repr(simd)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+pub fn make_u32x4(a: u32, b: u32, c: u32, d: u32) -> u32x4 {
+    u32x4(a, b, c, d)
+}
+
+pub fn make_i32x4(a: i32, b: i32, c: i32, d: i32) -> i32x4 {
+    i32x4(a, b, c, d)
+}
+
+pub fn pass_u32x4(v: u32x4) -> u32x4 {
+    v
+}
+
+pub fn first_u32x4(v: u32x4) -> u32 {
+    v.0
+}
+
+pub fn third_i32x4(v: i32x4) -> i32 {
+    v.2
+}
+
+pub fn constructed_second_u32x4(a: u32, b: u32, c: u32, d: u32) -> u32 {
+    make_u32x4(a, b, c, d).1
+}

base-commit: a263235e4f9da943366e08ebc4ecb799c50738bd
-- 
2.54.0

Reply via email to