public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
From: arthur.cohen@embecosm.com
To: gcc-patches@gcc.gnu.org
Cc: gcc-rust@gcc.gnu.org
Subject: [PATCH Rust front-end v3 06/46] gccrs: Add execution test cases
Date: Wed, 26 Oct 2022 10:17:31 +0200	[thread overview]
Message-ID: <20221026081811.602573-7-arthur.cohen@embecosm.com> (raw)
In-Reply-To: <20221026081811.602573-1-arthur.cohen@embecosm.com>

From: Philip Herron <philip.herron@embecosm.com>

This is similar to the compile/torture/*.rs test cases but all of these are
dg-execute testcases so they get compiled, linked and executed by default,
all the while being compiled with the matrix of torture options.

The only caveat here is that currently gccrs does not currently support
the main shim yet so we have a C-style main function here returning zero
which is not supported in Rustc.

Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Co-authored-by: Thomas Schwinge <thomas@codesourcery.com>
Co-authored-by: Mark Wielaard <mark@klomp.org>
Co-authored-by: Marc Poulhiès <dkm@kataplop.net>
---
 .../rust/execute/torture/block_expr1.rs       |   8 +
 .../rust/execute/torture/builtin_macro_cfg.rs |  32 ++++
 .../execute/torture/builtin_macro_concat.rs   |  29 +++
 .../rust/execute/torture/builtin_macro_env.rs |  31 ++++
 .../torture/builtin_macro_include_bytes.rs    |  46 +++++
 .../torture/builtin_macro_include_str.rs      |  27 +++
 .../execute/torture/builtin_macro_line.rs     |  25 +++
 .../rust/execute/torture/builtin_macros1.rs   |  21 +++
 .../rust/execute/torture/builtin_macros3.rs   |  28 +++
 gcc/testsuite/rust/execute/torture/cfg1.rs    |  32 ++++
 gcc/testsuite/rust/execute/torture/cfg2.rs    |  31 ++++
 gcc/testsuite/rust/execute/torture/cfg3.rs    |  37 ++++
 gcc/testsuite/rust/execute/torture/cfg4.rs    |  38 ++++
 gcc/testsuite/rust/execute/torture/cfg5.rs    |  13 ++
 .../rust/execute/torture/coercion1.rs         |  41 +++++
 .../rust/execute/torture/coercion2.rs         |  39 ++++
 .../rust/execute/torture/const_fold1.rs       |  13 ++
 .../rust/execute/torture/const_fold2.rs       |  16 ++
 .../execute/torture/copy_nonoverlapping1.rs   |  17 ++
 .../rust/execute/torture/empty_main.rs        |   3 +
 .../rust/execute/torture/execute.exp          |  33 ++++
 .../rust/execute/torture/exit_error.rs        |   5 +
 .../rust/execute/torture/extern_mod4.rs       |  19 ++
 gcc/testsuite/rust/execute/torture/func1.rs   |   5 +
 .../rust/execute/torture/helloworld1.rs       |  15 ++
 .../rust/execute/torture/helloworld2.rs       |  15 ++
 .../rust/execute/torture/include.txt          |   1 +
 gcc/testsuite/rust/execute/torture/index1.rs  |  28 +++
 .../rust/execute/torture/issue-1120.rs        | 123 +++++++++++++
 .../rust/execute/torture/issue-1133.rs        | 146 +++++++++++++++
 .../rust/execute/torture/issue-1198.rs        |  75 ++++++++
 .../rust/execute/torture/issue-1231.rs        |  36 ++++
 .../rust/execute/torture/issue-1232.rs        | 159 ++++++++++++++++
 .../rust/execute/torture/issue-1249.rs        |  39 ++++
 .../rust/execute/torture/issue-1436.rs        | 172 ++++++++++++++++++
 .../rust/execute/torture/issue-1496.rs        |  75 ++++++++
 .../rust/execute/torture/issue-647.rs         |  33 ++++
 .../rust/execute/torture/issue-845.rs         |  47 +++++
 .../rust/execute/torture/issue-851.rs         |  35 ++++
 .../rust/execute/torture/issue-858.rs         |  32 ++++
 .../rust/execute/torture/issue-976.rs         |  14 ++
 .../rust/execute/torture/issue-995.rs         |   9 +
 gcc/testsuite/rust/execute/torture/macros1.rs |  13 ++
 .../rust/execute/torture/macros10.rs          |  22 +++
 .../rust/execute/torture/macros11.rs          |  25 +++
 .../rust/execute/torture/macros12.rs          |  22 +++
 .../rust/execute/torture/macros13.rs          |  22 +++
 .../rust/execute/torture/macros14.rs          |  22 +++
 .../rust/execute/torture/macros16.rs          |  14 ++
 .../rust/execute/torture/macros17.rs          |  17 ++
 .../rust/execute/torture/macros18.rs          |  14 ++
 .../rust/execute/torture/macros19.rs          |  14 ++
 gcc/testsuite/rust/execute/torture/macros2.rs |  40 ++++
 .../rust/execute/torture/macros20.rs          |  14 ++
 .../rust/execute/torture/macros21.rs          |  15 ++
 .../rust/execute/torture/macros22.rs          |  27 +++
 .../rust/execute/torture/macros23.rs          |  19 ++
 .../rust/execute/torture/macros24.rs          |   9 +
 .../rust/execute/torture/macros25.rs          |  13 ++
 .../rust/execute/torture/macros26.rs          |  12 ++
 .../rust/execute/torture/macros27.rs          |  24 +++
 .../rust/execute/torture/macros28.rs          |  13 ++
 .../rust/execute/torture/macros29.rs          |  24 +++
 gcc/testsuite/rust/execute/torture/macros3.rs |  61 +++++++
 .../rust/execute/torture/macros30.rs          |  25 +++
 .../rust/execute/torture/macros31.rs          |  32 ++++
 gcc/testsuite/rust/execute/torture/macros4.rs |  15 ++
 gcc/testsuite/rust/execute/torture/macros5.rs |  13 ++
 gcc/testsuite/rust/execute/torture/macros6.rs |  12 ++
 gcc/testsuite/rust/execute/torture/macros7.rs |  28 +++
 gcc/testsuite/rust/execute/torture/macros8.rs |  27 +++
 gcc/testsuite/rust/execute/torture/macros9.rs |  28 +++
 gcc/testsuite/rust/execute/torture/match1.rs  |  58 ++++++
 gcc/testsuite/rust/execute/torture/match2.rs  |  41 +++++
 gcc/testsuite/rust/execute/torture/match3.rs  |  51 ++++++
 .../rust/execute/torture/match_bool1.rs       |  49 +++++
 .../rust/execute/torture/match_byte1.rs       |  56 ++++++
 .../rust/execute/torture/match_char1.rs       |  56 ++++++
 .../rust/execute/torture/match_int1.rs        | 109 +++++++++++
 .../rust/execute/torture/match_loop1.rs       |  56 ++++++
 .../rust/execute/torture/match_range1.rs      |  37 ++++
 .../rust/execute/torture/match_range2.rs      |  45 +++++
 .../rust/execute/torture/match_tuple1.rs      |  45 +++++
 gcc/testsuite/rust/execute/torture/method1.rs |  27 +++
 gcc/testsuite/rust/execute/torture/method2.rs |  76 ++++++++
 gcc/testsuite/rust/execute/torture/method3.rs |  78 ++++++++
 gcc/testsuite/rust/execute/torture/method4.rs |  78 ++++++++
 gcc/testsuite/rust/execute/torture/mod1.rs    |  21 +++
 .../rust/execute/torture/modules/mod.rs       |   3 +
 .../execute/torture/operator_overload_1.rs    |  36 ++++
 .../execute/torture/operator_overload_10.rs   |  75 ++++++++
 .../execute/torture/operator_overload_11.rs   |  37 ++++
 .../execute/torture/operator_overload_12.rs   |  31 ++++
 .../execute/torture/operator_overload_2.rs    |  38 ++++
 .../execute/torture/operator_overload_3.rs    |  55 ++++++
 .../execute/torture/operator_overload_4.rs    |  33 ++++
 .../execute/torture/operator_overload_5.rs    |  33 ++++
 .../execute/torture/operator_overload_6.rs    |  37 ++++
 .../execute/torture/operator_overload_7.rs    |  42 +++++
 .../execute/torture/operator_overload_8.rs    |  58 ++++++
 .../execute/torture/operator_overload_9.rs    |  58 ++++++
 .../rust/execute/torture/slice-magic.rs       | 106 +++++++++++
 .../rust/execute/torture/slice-magic2.rs      | 106 +++++++++++
 gcc/testsuite/rust/execute/torture/slice1.rs  |  27 +++
 .../rust/execute/torture/str-layout1.rs       |  57 ++++++
 .../rust/execute/torture/str-zero.rs          |  26 +++
 gcc/testsuite/rust/execute/torture/trait1.rs  |  52 ++++++
 gcc/testsuite/rust/execute/torture/trait10.rs |  41 +++++
 gcc/testsuite/rust/execute/torture/trait11.rs |  38 ++++
 gcc/testsuite/rust/execute/torture/trait12.rs |  38 ++++
 gcc/testsuite/rust/execute/torture/trait13.rs |  48 +++++
 gcc/testsuite/rust/execute/torture/trait2.rs  |  37 ++++
 gcc/testsuite/rust/execute/torture/trait3.rs  |  43 +++++
 gcc/testsuite/rust/execute/torture/trait4.rs  |  34 ++++
 gcc/testsuite/rust/execute/torture/trait5.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait6.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait7.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait8.rs  |  39 ++++
 gcc/testsuite/rust/execute/torture/trait9.rs  |  35 ++++
 .../rust/execute/torture/transmute1.rs        |  23 +++
 .../rust/execute/torture/wrapping_op1.rs      |  14 ++
 .../rust/execute/torture/wrapping_op2.rs      |  20 ++
 gcc/testsuite/rust/execute/xfail/macro1.rs    |  32 ++++
 123 files changed, 4631 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/torture/block_expr1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macros1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/builtin_macros3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/cfg5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/coercion1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/coercion2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/const_fold1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/const_fold2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/empty_main.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/execute.exp
 create mode 100644 gcc/testsuite/rust/execute/torture/exit_error.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/extern_mod4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/func1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/helloworld1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/helloworld2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/include.txt
 create mode 100644 gcc/testsuite/rust/execute/torture/index1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1120.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1133.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1198.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1231.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1232.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1249.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1436.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1496.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-647.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-845.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-851.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-858.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-976.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-995.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros10.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros11.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros12.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros13.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros14.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros16.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros17.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros18.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros19.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros20.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros21.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros22.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros23.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros24.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros25.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros26.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros27.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros28.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros29.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros30.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros31.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros6.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros8.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/macros9.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_bool1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_byte1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_char1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_int1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_loop1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_range1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_range2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/match_tuple1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/method4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/mod1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/modules/mod.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_10.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_11.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_12.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_6.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_8.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/operator_overload_9.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/slice-magic.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/slice-magic2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/slice1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/str-layout1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/str-zero.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait10.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait11.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait12.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait13.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait2.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait3.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait4.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait5.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait6.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait7.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait8.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/trait9.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/transmute1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/wrapping_op1.rs
 create mode 100644 gcc/testsuite/rust/execute/torture/wrapping_op2.rs
 create mode 100644 gcc/testsuite/rust/execute/xfail/macro1.rs

diff --git a/gcc/testsuite/rust/execute/torture/block_expr1.rs b/gcc/testsuite/rust/execute/torture/block_expr1.rs
new file mode 100644
index 00000000000..d561f8cab59
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/block_expr1.rs
@@ -0,0 +1,8 @@
+fn main() -> i32 {
+    let ret = {
+        1;
+        2;
+        0
+    };
+    ret
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
new file mode 100644
index 00000000000..fad2daef6bc
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_cfg.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "A\n" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let cfg = cfg!(A);
+    if cfg {
+        print("A");
+    }
+    let cfg = cfg!(B);
+    if cfg {
+        print("B");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
new file mode 100644
index 00000000000..9b33924f5a1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_concat.rs
@@ -0,0 +1,29 @@
+// { dg-output "\ntest10btrue2.15\ntest10bfalse2.151\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let a = concat!();
+    let b = concat!("test", 10, 'b', true, 2.15);
+    let c = concat!("test", 10, 'b', false, 2.15, 1u64);
+    print(a);
+    print(b);
+    print(c);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
new file mode 100644
index 00000000000..a5c80b25728
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_env.rs
@@ -0,0 +1,31 @@
+// { dg-output "VALUE\nVALUE\n" }
+// { dg-set-compiler-env-var ENV_MACRO_TEST "VALUE" }
+#[rustc_builtin_macro]
+macro_rules! env {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let val0 = env!("ENV_MACRO_TEST");
+
+    print(val0);
+
+    let val1 = env!("ENV_MACRO_TEST",);
+
+    print(val1);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
new file mode 100644
index 00000000000..087f0220de5
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_include_bytes.rs
@@ -0,0 +1,46 @@
+// { dg-output "104\n33\n1\n" }
+#[rustc_builtin_macro]
+macro_rules! include_bytes {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+fn main() -> i32 {
+    let bytes = include_bytes!("include.txt");
+
+    print_int(bytes[0] as i32);
+    print_int(bytes[14] as i32);
+
+    let the_bytes = b"hello, include!\n";
+
+    let x = bytes[0] == the_bytes[0]
+        && bytes[1] == the_bytes[1]
+        && bytes[2] == the_bytes[2]
+        && bytes[3] == the_bytes[3]
+        && bytes[4] == the_bytes[4]
+        && bytes[5] == the_bytes[5]
+        && bytes[6] == the_bytes[6]
+        && bytes[7] == the_bytes[7]
+        && bytes[8] == the_bytes[8]
+        && bytes[9] == the_bytes[9]
+        && bytes[10] == the_bytes[10]
+        && bytes[11] == the_bytes[11]
+        && bytes[12] == the_bytes[12]
+        && bytes[13] == the_bytes[13]
+        && bytes[14] == the_bytes[14]
+        && bytes[15] == the_bytes[15];
+
+    print_int(x as i32);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
new file mode 100644
index 00000000000..6f9871d379c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_include_str.rs
@@ -0,0 +1,27 @@
+// { dg-output "hello, include!\n" }
+#[rustc_builtin_macro]
+macro_rules! include_str {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    // include_str! (and include_bytes!) allow for an optional trailing comma.
+    let my_str = include_str!("include.txt",);
+
+    print(my_str);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs b/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
new file mode 100644
index 00000000000..02541ed52e2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macro_line.rs
@@ -0,0 +1,25 @@
+// { dg-output "18\n21\n" }
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+#[rustc_builtin_macro]
+macro_rules! line {
+    () => {{}};
+}
+
+fn main() -> i32 {
+    let a = line!();
+    print(a);
+
+    let b = line!();
+    print(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
new file mode 100644
index 00000000000..5976478e426
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
@@ -0,0 +1,21 @@
+// { dg-output "rust/execute/torture/builtin_macros1.rs" }
+#[rustc_builtin_macro]
+macro_rules! file {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf("%s\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    print(file!());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros3.rs b/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
new file mode 100644
index 00000000000..24555cbdb8a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros3.rs
@@ -0,0 +1,28 @@
+// { dg-output "14\n42\n" }
+#[rustc_builtin_macro]
+macro_rules! column {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    let c0 = column!();
+
+    print(c0);
+
+    let c1 =                             column!();
+
+    print(c1);
+
+    0
+}
+
diff --git a/gcc/testsuite/rust/execute/torture/cfg1.rs b/gcc/testsuite/rust/execute/torture/cfg1.rs
new file mode 100644
index 00000000000..d3c56295503
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg1.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[cfg(A)]
+fn test() {
+    unsafe {
+        let a = "test1\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+#[cfg(B)]
+fn test() {
+    unsafe {
+        let a = "test2\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+fn main() -> i32 {
+    test();
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg2.rs b/gcc/testsuite/rust/execute/torture/cfg2.rs
new file mode 100644
index 00000000000..5048bcb2791
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg2.rs
@@ -0,0 +1,31 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn test() {
+    #[cfg(A)]
+    unsafe {
+        let a = "test1\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+
+    #[cfg(B)]
+    unsafe {
+        let a = "test2\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c);
+    }
+}
+
+fn main() -> i32 {
+    test();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg3.rs b/gcc/testsuite/rust/execute/torture/cfg3.rs
new file mode 100644
index 00000000000..89312344b23
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg3.rs
@@ -0,0 +1,37 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    #[cfg(A)]
+    fn test(&self) {
+        unsafe {
+            let a = "test1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+
+    #[cfg(B)]
+    fn test(&self) {
+        unsafe {
+            let a = "test2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.test();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg4.rs b/gcc/testsuite/rust/execute/torture/cfg4.rs
new file mode 100644
index 00000000000..d1c2a22a0ff
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg4.rs
@@ -0,0 +1,38 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\ntest2\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    #[cfg(A)]
+    fn test(&self) {
+        unsafe {
+            let a = "test1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+
+    #[cfg(not(B))]
+    fn test2(&self) {
+        unsafe {
+            let a = "test2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.test();
+    a.test2();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/cfg5.rs b/gcc/testsuite/rust/execute/torture/cfg5.rs
new file mode 100644
index 00000000000..581a29bb89d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/cfg5.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+
+fn main() -> i32 {
+    let mut a = 0;
+
+    #[cfg(A)]
+    a = 3;
+
+    #[cfg(B)]
+    a = 40;
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/coercion1.rs b/gcc/testsuite/rust/execute/torture/coercion1.rs
new file mode 100644
index 00000000000..2cdb9bbca38
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/coercion1.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(123);
+    static_dispatch(&a);
+
+    let b: &dyn Bar;
+    b = &a;
+    dynamic_dispatch(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/coercion2.rs b/gcc/testsuite/rust/execute/torture/coercion2.rs
new file mode 100644
index 00000000000..12dd68ff5f7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/coercion2.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a;
+    a = &Foo(123);
+
+    static_dispatch(a);
+    dynamic_dispatch(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/const_fold1.rs b/gcc/testsuite/rust/execute/torture/const_fold1.rs
new file mode 100644
index 00000000000..3cd6c0c77b5
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_fold1.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w" }
+const fn const_fn() -> usize {
+    4
+}
+
+const FN_TEST: usize = const_fn();
+
+const TEST: usize = 2 + FN_TEST;
+
+fn main() -> i32 {
+    let a: [_; 12] = [5; TEST * 2];
+    a[6] - 5
+}
diff --git a/gcc/testsuite/rust/execute/torture/const_fold2.rs b/gcc/testsuite/rust/execute/torture/const_fold2.rs
new file mode 100644
index 00000000000..c525648fe0b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_fold2.rs
@@ -0,0 +1,16 @@
+// { dg-additional-options "-w" }
+const A: i32 = 1;
+const B: i32 = { A + 2 };
+
+const fn test() -> i32 {
+    B
+}
+
+const C: i32 = {
+    const a: i32 = 4;
+    test() + a
+};
+
+fn main() -> i32 {
+    C - 7
+}
diff --git a/gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs b/gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs
new file mode 100644
index 00000000000..2ae7a0869e3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/copy_nonoverlapping1.rs
@@ -0,0 +1,17 @@
+extern "rust-intrinsic" {
+    pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+}
+
+fn main() -> i32 {
+    let i = 15;
+    let mut i_copy = 16;
+
+    let i = &i as *const i32;
+    let i_copy = &mut i_copy as *mut i32;
+
+    unsafe {
+        copy_nonoverlapping(i, i_copy, 1);
+
+        *i_copy - *i
+    }
+}
\ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/torture/empty_main.rs b/gcc/testsuite/rust/execute/torture/empty_main.rs
new file mode 100644
index 00000000000..6442e1e4e83
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/empty_main.rs
@@ -0,0 +1,3 @@
+fn main() -> i32 {
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/execute.exp b/gcc/testsuite/rust/execute/torture/execute.exp
new file mode 100644
index 00000000000..6dfb6d2b446
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/execute.exp
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Execute tests, torture testing.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "run"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/execute/torture/exit_error.rs b/gcc/testsuite/rust/execute/torture/exit_error.rs
new file mode 100644
index 00000000000..c3d0d9f2480
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/exit_error.rs
@@ -0,0 +1,5 @@
+// { dg-xfail-run-if "" { *-*-* } }
+
+fn main() -> i32 {
+    1
+}
diff --git a/gcc/testsuite/rust/execute/torture/extern_mod4.rs b/gcc/testsuite/rust/execute/torture/extern_mod4.rs
new file mode 100644
index 00000000000..99b6fb5c9ba
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/extern_mod4.rs
@@ -0,0 +1,19 @@
+// { dg-additional-options "-w" }
+// { dg-output "12" }
+mod modules;
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+    unsafe {
+        let fmt_s = "%d\n\0";
+        let fmt_p = fmt_s as *const str;
+        let fmt_i8 = fmt_p as *const i8;
+
+        printf(fmt_i8, modules::return_12());
+    }
+
+    return 0;
+}
diff --git a/gcc/testsuite/rust/execute/torture/func1.rs b/gcc/testsuite/rust/execute/torture/func1.rs
new file mode 100644
index 00000000000..0a093d88587
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/func1.rs
@@ -0,0 +1,5 @@
+fn main() -> i32 {
+    1;
+    2;
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/helloworld1.rs b/gcc/testsuite/rust/execute/torture/helloworld1.rs
new file mode 100644
index 00000000000..d416efa33af
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/helloworld1.rs
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World" }*/
+extern "C" {
+    fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+    unsafe {
+        let a = "Hello World";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        puts(c);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/helloworld2.rs b/gcc/testsuite/rust/execute/torture/helloworld2.rs
new file mode 100644
index 00000000000..cc05f3798fa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/helloworld2.rs
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+    unsafe {
+        let a = "Hello World %i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, 123);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/include.txt b/gcc/testsuite/rust/execute/torture/include.txt
new file mode 100644
index 00000000000..12c368778e1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/include.txt
@@ -0,0 +1 @@
+hello, include!
diff --git a/gcc/testsuite/rust/execute/torture/index1.rs b/gcc/testsuite/rust/execute/torture/index1.rs
new file mode 100644
index 00000000000..4682978bdd0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/index1.rs
@@ -0,0 +1,28 @@
+// { dg-additional-options "-w" }
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+struct Foo(i32, i32);
+impl Index<isize> for Foo {
+    type Output = i32;
+
+    fn index(&self, index: isize) -> &i32 {
+        if index == 0 {
+            &self.0
+        } else {
+            &self.1
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(1, 2);
+    let b = a[0];
+    let c = a[1];
+
+    c - b - 1
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1120.rs b/gcc/testsuite/rust/execute/torture/issue-1120.rs
new file mode 100644
index 00000000000..242c94b5cb6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1120.rs
@@ -0,0 +1,123 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end
+        /* || self.end > slice.len() */
+        {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1133.rs b/gcc/testsuite/rust/execute/torture/issue-1133.rs
new file mode 100644
index 00000000000..f2080a6e072
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1133.rs
@@ -0,0 +1,146 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+    type Output = T;
+
+    fn get(self, slice: &[T]) -> Option<&T> {
+        unsafe { Option::Some(&*self.get_unchecked(slice)) }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        // SAFETY: the caller guarantees that `slice` is not dangling, so it
+        // cannot be longer than `isize::MAX`. They also guarantee that
+        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+        // so the call to `add` is safe.
+        unsafe { slice.as_ptr().add(self) }
+    }
+
+    fn index(self, slice: &[T]) -> &T {
+        // N.B., use intrinsic indexing
+        // &(*slice)[self]
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end
+        /* || self.end > slice.len() */
+        {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+    let c = b[1];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1198.rs b/gcc/testsuite/rust/execute/torture/issue-1198.rs
new file mode 100644
index 00000000000..fce44ad1994
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1198.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo: Foo<i32> = Foo(123);
+    let bar: &i32 = &foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1231.rs b/gcc/testsuite/rust/execute/torture/issue-1231.rs
new file mode 100644
index 00000000000..970e86f917a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1231.rs
@@ -0,0 +1,36 @@
+// { dg-additional-options "-w" }
+// { dg-output "outer\ninner\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn machin() {
+    unsafe {
+        let a = "outer\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, 123);
+    }
+}
+
+fn bidule() {
+    fn machin() {
+        unsafe {
+            let a = "inner\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, 123);
+        }
+    }
+
+    self::machin();
+    machin();
+}
+
+fn main() -> i32 {
+    bidule();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1232.rs b/gcc/testsuite/rust/execute/torture/issue-1232.rs
new file mode 100644
index 00000000000..c56d5c18695
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1232.rs
@@ -0,0 +1,159 @@
+// { dg-additional-options "-w" }
+// { dg-output "slice_access=3\n" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+    type Output = T;
+
+    fn get(self, slice: &[T]) -> Option<&T> {
+        unsafe { Option::Some(&*self.get_unchecked(slice)) }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        // SAFETY: the caller guarantees that `slice` is not dangling, so it
+        // cannot be longer than `isize::MAX`. They also guarantee that
+        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+        // so the call to `add` is safe.
+        unsafe { slice.as_ptr().add(self) }
+    }
+
+    fn index(self, slice: &[T]) -> &T {
+        // N.B., use intrinsic indexing
+        // &(*slice)[self]
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end
+        /* || self.end > slice.len() */
+        {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let array = [1, 2, 3, 4, 5];
+    let slice = &array[1..3];
+    let slice_access = slice[1];
+
+    unsafe {
+        let a = "slice_access=%i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, slice_access);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1249.rs b/gcc/testsuite/rust/execute/torture/issue-1249.rs
new file mode 100644
index 00000000000..072204ea877
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1249.rs
@@ -0,0 +1,39 @@
+// { dg-options "-w" }
+// { dg-output "1\n2\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait T {
+    fn foo(&self);
+}
+
+impl dyn T {
+    fn bar(&self) {
+        unsafe {
+            let a = "1\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            printf(c);
+        }
+        self.foo()
+    }
+}
+
+struct S;
+impl T for S {
+    fn foo(&self) {
+        unsafe {
+            let a = "2\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            printf(c);
+        }
+    }
+}
+
+pub fn main() -> i32 {
+    <dyn T>::bar(&S);
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1436.rs b/gcc/testsuite/rust/execute/torture/issue-1436.rs
new file mode 100644
index 00000000000..5c079a61f07
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1436.rs
@@ -0,0 +1,172 @@
+// { dg-options "-w" }
+// { dg-output "" }
+mod intrinsics {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+        pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+    }
+}
+
+mod mem {
+    extern "rust-intrinsic" {
+        fn size_of<T>() -> usize;
+    }
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { intrinsics::offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> [T] {
+    pub const fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    pub const fn len(&self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    fn get(self, slice: &T) -> Option<&Self::Output>;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+    type Output = T;
+
+    fn get(self, slice: &[T]) -> Option<&T> {
+        unsafe { Option::Some(&*self.get_unchecked(slice)) }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+        // SAFETY: the caller guarantees that `slice` is not dangling, so it
+        // cannot be longer than `isize::MAX`. They also guarantee that
+        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+        // so the call to `add` is safe.
+        unsafe { slice.as_ptr().add(self) }
+    }
+
+    fn index(self, slice: &[T]) -> &T {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        if self.start > self.end || self.end > slice.len() {
+            Option::None
+        } else {
+            unsafe { Option::Some(&*self.get_unchecked(slice)) }
+        }
+    }
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        unsafe {
+            let a = "slice-index\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = a[1];
+
+    b - 2
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1496.rs b/gcc/testsuite/rust/execute/torture/issue-1496.rs
new file mode 100644
index 00000000000..9f08b2ae98a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1496.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo = Foo(123);
+    let bar = &foo as &i32;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-647.rs b/gcc/testsuite/rust/execute/torture/issue-647.rs
new file mode 100644
index 00000000000..3f427ccb785
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-647.rs
@@ -0,0 +1,33 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo<T>(T);
+
+struct Bar<T> {
+    a: Foo<T>,
+    b: bool,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn test<T>(a: Bar<T>) -> Foo<T> {
+    a.a
+}
+
+fn main() -> i32 {
+    let a: Bar<i32> = Bar::<i32> {
+        a: Foo::<i32>(123),
+        b: true,
+    };
+    let result: Foo<i32> = test(a);
+
+    unsafe {
+        let a = "Hello World %i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, result.0);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-845.rs b/gcc/testsuite/rust/execute/torture/issue-845.rs
new file mode 100644
index 00000000000..4c689e3b6c8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-845.rs
@@ -0,0 +1,47 @@
+// { dg-output "Foo::bar\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo {}
+
+trait Bar {
+    fn bar(&self) {
+        unsafe {
+            let _a = "Bar::bar\n\0";
+            let _b = _a as *const str;
+            let _c = _b as *const i8;
+            printf(_c);
+        }
+    }
+}
+
+impl Foo {
+    fn bar(&self) {
+        unsafe {
+            let _a = "Foo::bar\n\0";
+            let _b = _a as *const str;
+            let _c = _b as *const i8;
+            printf(_c);
+        }
+    }
+}
+
+impl Bar for Foo {
+    fn bar(&self) {
+        unsafe {
+            let _a = "<Bar as Foo>::bar\n\0";
+            let _b = _a as *const str;
+            let _c = _b as *const i8;
+            printf(_c);
+        }
+    }
+}
+
+pub fn main() -> i32 {
+    let mut f = Foo {};
+    f.bar();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-851.rs b/gcc/testsuite/rust/execute/torture/issue-851.rs
new file mode 100644
index 00000000000..3881c7a2ada
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-851.rs
@@ -0,0 +1,35 @@
+/* { dg-output "Result: 123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo<T> {
+    A,
+    B(T),
+}
+
+fn inspect(a: Foo<i32>) {
+    match a {
+        Foo::A => unsafe {
+            let a = "A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::B(x) => unsafe {
+            let a = "Result: %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x);
+        },
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::B(123);
+    inspect(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-858.rs b/gcc/testsuite/rust/execute/torture/issue-858.rs
new file mode 100644
index 00000000000..5a43f3e1b1a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-858.rs
@@ -0,0 +1,32 @@
+/* { dg-output "Result: 123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo<T> {
+    A,
+    B(T),
+}
+
+fn main() -> i32 {
+    let result = Foo::B(123);
+
+    match result {
+        Foo::A => unsafe {
+            let a = "A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::B(x) => unsafe {
+            let a = "Result: %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x);
+        },
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-976.rs b/gcc/testsuite/rust/execute/torture/issue-976.rs
new file mode 100644
index 00000000000..42cf596fb7d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-976.rs
@@ -0,0 +1,14 @@
+/* { dg-output "hi" } */
+fn main() -> i32 {
+    {
+        extern "C" {
+            fn puts(s: *const i8);
+        }
+
+        unsafe {
+            puts("hi\0" as *const str as *const i8);
+        }
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-995.rs b/gcc/testsuite/rust/execute/torture/issue-995.rs
new file mode 100644
index 00000000000..42570e33f74
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-995.rs
@@ -0,0 +1,9 @@
+struct Pattern(i32);
+
+fn pattern_as_arg(Pattern(value): Pattern) -> i32 {
+    value
+}
+
+fn main() -> i32 {
+    pattern_as_arg(Pattern(15)) - 15
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros1.rs b/gcc/testsuite/rust/execute/torture/macros1.rs
new file mode 100644
index 00000000000..652d2d8fe5b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros1.rs
@@ -0,0 +1,13 @@
+macro_rules! add {
+    ($a:expr,$b:expr) => {
+        $a + $b
+    };
+}
+
+fn test() -> i32 {
+    add!(1 + 2, 3)
+}
+
+fn main() -> i32 {
+    test() - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros10.rs b/gcc/testsuite/rust/execute/torture/macros10.rs
new file mode 100644
index 00000000000..155a440ee04
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros10.rs
@@ -0,0 +1,22 @@
+// { dg-output "18\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)*) => (0 $(+ $e)*)
+}
+
+fn main() -> i32 {
+    // 1 + 2 + 15 => 18
+    print_int(add_exprs!(1 2 15));
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros11.rs b/gcc/testsuite/rust/execute/torture/macros11.rs
new file mode 100644
index 00000000000..5bde97d3dd4
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros11.rs
@@ -0,0 +1,25 @@
+// { dg-output "2" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0";
+    let s_p = s as *const str;
+    let c_p = s_p as *const i8;
+    unsafe {
+        printf(c_p, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)?) => (0 $(+ $e)?)
+}
+
+fn main() -> i32 {
+    // 2
+    let a = add_exprs!(2);
+    print_int(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros12.rs b/gcc/testsuite/rust/execute/torture/macros12.rs
new file mode 100644
index 00000000000..d310dff9ba8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros12.rs
@@ -0,0 +1,22 @@
+// { dg-output "0\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)?) => (0 $(+ $e)?)
+}
+
+fn main() -> i32 {
+    // 0
+    print_int(add_exprs!());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros13.rs b/gcc/testsuite/rust/execute/torture/macros13.rs
new file mode 100644
index 00000000000..afb20264625
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros13.rs
@@ -0,0 +1,22 @@
+// { dg-output "18\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)+) => (0 $(+ $e)+)
+}
+
+fn main() -> i32 {
+    // 1 + 2 + 15 => 18
+    print_int(add_exprs!(1 2 15));
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros14.rs b/gcc/testsuite/rust/execute/torture/macros14.rs
new file mode 100644
index 00000000000..00656546d4c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros14.rs
@@ -0,0 +1,22 @@
+// { dg-output "15\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+    let s = "%d\n\0" as *const str as *const i8;
+    unsafe {
+        printf(s, value);
+    }
+}
+
+macro_rules! add_exprs {
+    ($($e:expr)*) => (15 $(+ $e)*)
+}
+
+fn main() -> i32 {
+    // 15
+    print_int(add_exprs!());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros16.rs b/gcc/testsuite/rust/execute/torture/macros16.rs
new file mode 100644
index 00000000000..47ab2411c0d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros16.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:literal) => {
+        0 + $e
+    };
+    ($e:literal $($es:literal)*) => {
+        $e + add!($($es)*)
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(1 2 3 10); // 16
+
+    a - 16
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros17.rs b/gcc/testsuite/rust/execute/torture/macros17.rs
new file mode 100644
index 00000000000..390352ec47f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros17.rs
@@ -0,0 +1,17 @@
+macro_rules! two {
+    (2) => {
+        3
+    };
+}
+
+macro_rules! one {
+    (1) => {{
+        two!(2)
+    }};
+}
+
+fn main() -> i32 {
+    let a = one!(1);
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros18.rs b/gcc/testsuite/rust/execute/torture/macros18.rs
new file mode 100644
index 00000000000..61df17e9da5
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros18.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:literal) => {
+        0 + $e
+    };
+    ($e:literal $($es:literal)*) => {
+        $e + add!($($es)*)
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(3 4); // 7
+
+    a - 7
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros19.rs b/gcc/testsuite/rust/execute/torture/macros19.rs
new file mode 100644
index 00000000000..4732545410e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros19.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:expr, $($es:expr),*) => {
+        $e + add!($($es),*)
+    };
+    ($e:expr) => {
+        $e
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(15, 2, 9); // 26
+
+    a - 26
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros2.rs b/gcc/testsuite/rust/execute/torture/macros2.rs
new file mode 100644
index 00000000000..ba5098710ea
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros2.rs
@@ -0,0 +1,40 @@
+// { dg-output "arg\narg\narg\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    unsafe {
+        let r_s = "arg\n\0";
+        let s_p = r_s as *const str;
+        let c_p = s_p as *const i8;
+
+        printf(c_p);
+    }
+}
+
+macro_rules! kw0 {
+    (keyword) => {
+        f();
+    };
+}
+
+macro_rules! kw1 {
+    (fn) => {
+        f();
+    };
+}
+
+macro_rules! kw2 {
+    (kw0 kw1 kw3) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    kw0!(keyword);
+    kw1!(fn);
+    kw2!(kw0 kw1 kw3);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros20.rs b/gcc/testsuite/rust/execute/torture/macros20.rs
new file mode 100644
index 00000000000..97317a0879e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros20.rs
@@ -0,0 +1,14 @@
+macro_rules! add {
+    ($e:expr , $($es:expr) , *) => {
+        $e + add!($($es) , *)
+    };
+    ($e:expr) => {
+        $e
+    };
+}
+
+fn main() -> i32 {
+    let a = add!(15, 2, 9); // 26
+
+    a - 26
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros21.rs b/gcc/testsuite/rust/execute/torture/macros21.rs
new file mode 100644
index 00000000000..2508be1a6fd
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros21.rs
@@ -0,0 +1,15 @@
+macro_rules! add_parens {
+    ($($rep:ident ( ) )*) => {
+        { 0 $(+ $rep ( ))* }
+    };
+}
+
+fn f() -> i32 {
+    1
+}
+
+fn main() -> i32 {
+    let a = add_parens!(f() f() f());
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros22.rs b/gcc/testsuite/rust/execute/torture/macros22.rs
new file mode 100644
index 00000000000..3f291ace98e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros22.rs
@@ -0,0 +1,27 @@
+// { dg-output "1\n2\nNaN\n3\n" }
+
+macro_rules! print_num {
+    ($l:literal) => {{
+        unsafe {
+            printf("%d\n\0" as *const str as *const i8, $l);
+        }
+    }};
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+// Check to make sure that expanding macros does not break the flow of calls
+fn main() -> i32 {
+    print_num!(1);
+    print_num!(2);
+
+    unsafe {
+        printf("NaN\n\0" as *const str as *const i8);
+    }
+
+    print_num!(3);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros23.rs b/gcc/testsuite/rust/execute/torture/macros23.rs
new file mode 100644
index 00000000000..846352d0487
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros23.rs
@@ -0,0 +1,19 @@
+trait Valuable {
+    const VALUE: i32;
+}
+
+struct Something;
+
+macro_rules! implement {
+    () => {
+        const VALUE: i32 = 18;
+    };
+}
+
+impl Valuable for Something {
+    implement!();
+}
+
+fn main() -> i32 {
+    Something::VALUE - 18
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros24.rs b/gcc/testsuite/rust/execute/torture/macros24.rs
new file mode 100644
index 00000000000..f838a83af66
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros24.rs
@@ -0,0 +1,9 @@
+macro_rules! repeat {
+    ( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
+}
+
+fn main() -> i32 {
+    let t = repeat!(1, 1; 2, 2);
+
+    t.0 .0 + t.0 .1 + t.1 .0 + t.1 .1 - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros25.rs b/gcc/testsuite/rust/execute/torture/macros25.rs
new file mode 100644
index 00000000000..c2658721bdf
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros25.rs
@@ -0,0 +1,13 @@
+macro_rules! t {
+    ($t:tt) => {
+        $t
+    };
+}
+
+fn frob() -> i32 {
+    t!(15) + t!((14))
+}
+
+fn main() -> i32 {
+    frob() - 29
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros26.rs b/gcc/testsuite/rust/execute/torture/macros26.rs
new file mode 100644
index 00000000000..30f0beef0d9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros26.rs
@@ -0,0 +1,12 @@
+macro_rules! count_tt {
+    ($t:tt) => { 1 };
+    ($t:tt $($ts:tt)*) => { 1 + count_tt!($($ts)*) };
+}
+
+fn main() -> i32 {
+    let count = count_tt!(1 2 let a = 15) + count_tt!(1 2 (let a = 15));
+    //                    ^ ^ ^^^ ^ ^ ^^              ^ ^ ^^^^^^^^^^^^
+    //                    6 token-trees               3 token-trees
+
+    count - 9
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros27.rs b/gcc/testsuite/rust/execute/torture/macros27.rs
new file mode 100644
index 00000000000..d515bb278a0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros27.rs
@@ -0,0 +1,24 @@
+// { dg-additional-options "-frust-cfg=A" }
+
+macro_rules! attr {
+    (#[$attr:meta] $s:stmt) => {
+        #[$attr]
+        $s;
+    };
+}
+
+fn main() -> i32 {
+    let mut a = 0;
+
+    attr! {
+    #[cfg(A)]
+        a = 3
+    };
+
+    attr! {
+    #[cfg(B)]
+        a = 40
+    };
+
+    a - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros28.rs b/gcc/testsuite/rust/execute/torture/macros28.rs
new file mode 100644
index 00000000000..b011f924149
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros28.rs
@@ -0,0 +1,13 @@
+macro_rules! t {
+    () => {
+        i32
+    };
+}
+
+fn id<T>(arg: T) -> T {
+    arg
+}
+
+fn main() -> i32 {
+    id::<t!()>(15) - 15
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros29.rs b/gcc/testsuite/rust/execute/torture/macros29.rs
new file mode 100644
index 00000000000..306979b9b5b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros29.rs
@@ -0,0 +1,24 @@
+// { dg-output "1\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    let res = concat!("test2") == "test3";
+    if !res {
+        print(1);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros3.rs b/gcc/testsuite/rust/execute/torture/macros3.rs
new file mode 100644
index 00000000000..00f6d253f50
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros3.rs
@@ -0,0 +1,61 @@
+// { dg-output "invok\ninvok\ninvok\ninvok\ninvok\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    unsafe {
+        let r_s = "invok\n\0";
+        let s_p = r_s as *const str;
+        let c_p = s_p as *const i8;
+
+        printf(c_p);
+    }
+}
+
+macro_rules! invocation0 {
+    (valid) => {
+        f();
+    };
+    () => {};
+}
+
+macro_rules! invocation1 {
+    (valid) => {};
+    () => {
+        f();
+    };
+}
+
+macro_rules! invocation2 {
+    (valid) => {
+        f();
+    };
+    (invalid) => {};
+}
+
+macro_rules! invocation3 {
+    (this is a valid invocation) => {
+        f();
+    };
+    (not this one) => {};
+}
+
+macro_rules! invocation4 {
+    (fn f() {}) => {
+        f();
+    };
+    (not a keyword) => {};
+}
+
+fn main() -> i32 {
+    invocation0!(valid);
+    invocation1!();
+    invocation2!(valid);
+    invocation3!(this is a valid invocation);
+    invocation4!(
+        fn f() {}
+    );
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros30.rs b/gcc/testsuite/rust/execute/torture/macros30.rs
new file mode 100644
index 00000000000..ab36f5e78af
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros30.rs
@@ -0,0 +1,25 @@
+// { dg-output "1\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+    unsafe {
+        printf("%u\n\0" as *const str as *const i8, s);
+    }
+}
+
+fn main() -> i32 {
+    let mut x = concat!("x");
+    x = concat!("y");
+    if x == "y" {
+        print(1);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros31.rs b/gcc/testsuite/rust/execute/torture/macros31.rs
new file mode 100644
index 00000000000..483f897a92b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros31.rs
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "A\nB\n" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+    () => {{}};
+}
+
+extern "C" {
+    fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+    unsafe {
+        printf(
+            "%s\n" as *const str as *const i8,
+            s as *const str as *const i8,
+        );
+    }
+}
+
+fn main() -> i32 {
+    let cfg = cfg!(A) || cfg!(B);
+    if cfg {
+        print("A");
+    }
+    let cfg = cfg!(A) && cfg!(B);
+    if !cfg {
+        print("B");
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros4.rs b/gcc/testsuite/rust/execute/torture/macros4.rs
new file mode 100644
index 00000000000..3303bfa58aa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros4.rs
@@ -0,0 +1,15 @@
+macro_rules! add {
+    ($a:expr,$b:expr) => {
+        $a + $b
+    };
+    ($a:expr) => {
+        $a
+    };
+}
+
+fn main() -> i32 {
+    let mut x = add!(1);
+    x += add!(2, 3);
+
+    x - 6
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros5.rs b/gcc/testsuite/rust/execute/torture/macros5.rs
new file mode 100644
index 00000000000..822665494a4
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros5.rs
@@ -0,0 +1,13 @@
+macro_rules! add {
+    ($a:expr,$b:expr) => {{
+        $a + $b
+    }};
+}
+
+fn test() -> i32 {
+    add!(1, 2)
+}
+
+fn main() -> i32 {
+    test() - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros6.rs b/gcc/testsuite/rust/execute/torture/macros6.rs
new file mode 100644
index 00000000000..652a765d5a8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros6.rs
@@ -0,0 +1,12 @@
+macro_rules! Test {
+    ($a:ident, $b:ty) => {
+        struct $a($b);
+    };
+}
+
+Test!(Foo, i32);
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.0 - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros7.rs b/gcc/testsuite/rust/execute/torture/macros7.rs
new file mode 100644
index 00000000000..ed1f922f581
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros7.rs
@@ -0,0 +1,28 @@
+// { dg-output "any\nany\nany\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "any\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    unsafe {
+        printf(c_p);
+    }
+}
+
+macro_rules! any {
+    ($($a:expr)*) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    any!();
+    any!(a + b);
+    any!(a + b    14 "gcc");
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros8.rs b/gcc/testsuite/rust/execute/torture/macros8.rs
new file mode 100644
index 00000000000..a12aca4910e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros8.rs
@@ -0,0 +1,27 @@
+// { dg-output "zo1\nzo1\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "zo1\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    unsafe {
+        printf(c_p);
+    }
+}
+
+macro_rules! zero_or_one {
+    ($($a:expr)?) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    zero_or_one!();
+    zero_or_one!(f());
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros9.rs b/gcc/testsuite/rust/execute/torture/macros9.rs
new file mode 100644
index 00000000000..0e3fd24e8a9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros9.rs
@@ -0,0 +1,28 @@
+// { dg-output "oom\noom\noom\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "oom\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    unsafe {
+        printf(c_p);
+    }
+}
+
+macro_rules! one_or_more {
+    ($($a:expr)+) => {
+        f();
+    };
+}
+
+fn main() -> i32 {
+    one_or_more!(f());
+    one_or_more!(f() f());
+    one_or_more!(f() f() 15 + 12);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match1.rs b/gcc/testsuite/rust/execute/torture/match1.rs
new file mode 100644
index 00000000000..e5af512f15d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match1.rs
@@ -0,0 +1,58 @@
+// { dg-output "Foo::A\nFoo::B\nFoo::C x\nFoo::D 20 80\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => unsafe {
+            let a = "Foo::A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::B => unsafe {
+            let a = "Foo::B\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::C(x) => unsafe {
+            let a = "Foo::C %c\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x);
+        },
+        Foo::D { x, y } => unsafe {
+            let a = "Foo::D %i %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x, y);
+        },
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::A;
+    let b = Foo::B;
+    let c = Foo::C('x');
+    let d = Foo::D { x: 20, y: 80 };
+
+    inspect(a);
+    inspect(b);
+    inspect(c);
+    inspect(d);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match2.rs b/gcc/testsuite/rust/execute/torture/match2.rs
new file mode 100644
index 00000000000..02cedf29b3c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match2.rs
@@ -0,0 +1,41 @@
+// { dg-output "123\n80\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    C(i32),
+    D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) -> i32 {
+    match f {
+        Foo::C(x) => x,
+        Foo::D { x, y } => y,
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::C(123);
+    let b = Foo::D { x: 20, y: 80 };
+
+    let result = inspect(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, result);
+    }
+
+    let result = inspect(b);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, result);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match3.rs b/gcc/testsuite/rust/execute/torture/match3.rs
new file mode 100644
index 00000000000..8cded3044df
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match3.rs
@@ -0,0 +1,51 @@
+// { dg-output "Foo::A\nwildcard\nwildcard\nFoo::D 20 80\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    A,
+    B,
+    C(char),
+    D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) {
+    match f {
+        Foo::A => unsafe {
+            let a = "Foo::A\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+        Foo::D { x, y } => unsafe {
+            let a = "Foo::D %i %i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, x, y);
+        },
+        _ => unsafe {
+            let a = "wildcard\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        },
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo::A;
+    let b = Foo::B;
+    let c = Foo::C('x');
+    let d = Foo::D { x: 20, y: 80 };
+
+    inspect(a);
+    inspect(b);
+    inspect(c);
+    inspect(d);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_bool1.rs b/gcc/testsuite/rust/execute/torture/match_bool1.rs
new file mode 100644
index 00000000000..101dbb58571
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_bool1.rs
@@ -0,0 +1,49 @@
+// { dg-output "182 is more than 100\n55 is less than 100\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo(x: bool) -> i32 {
+    match x {
+        true => {
+            return 182;
+        }
+        false => {
+            return 55;
+        }
+    }
+}
+
+fn bar(y: i32) {
+    match y < 100 {
+        true => {
+            let a = "%i is less than 100\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            unsafe {
+                printf(c, y);
+            }
+        }
+        _ => {
+            let a = "%i is more than 100\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            unsafe {
+                printf(c, y);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = foo(true);
+    let b = foo(false);
+
+    bar(a);
+    bar(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_byte1.rs b/gcc/testsuite/rust/execute/torture/match_byte1.rs
new file mode 100644
index 00000000000..3546cfb9d8b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_byte1.rs
@@ -0,0 +1,56 @@
+// { dg-output "a\nseven\nquote\nelse" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo(x: u8) {
+    match x {
+        b'a' => {
+            let a = "a\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        b'\x07' => {
+            let a = "seven\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        b'\'' => {
+            let a = "quote\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "else\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let x: u8 = 7;
+
+    foo(b'a');
+    foo(x);
+    foo(b'\'');
+    foo(b'\\');
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_char1.rs b/gcc/testsuite/rust/execute/torture/match_char1.rs
new file mode 100644
index 00000000000..fa65876a907
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_char1.rs
@@ -0,0 +1,56 @@
+// { dg-output "amazing\nwildcard\ncompiler\nproductivity\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo(x: char) {
+    match x {
+        'a' => {
+            let a = "amazing\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        'c' => {
+            let a = "compiler\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        'p' => {
+            let a = "productivity\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "wildcard\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let p = 'p';
+
+    foo('a');
+    foo('b');
+    foo('c');
+    foo(p);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_int1.rs b/gcc/testsuite/rust/execute/torture/match_int1.rs
new file mode 100644
index 00000000000..209429added
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_int1.rs
@@ -0,0 +1,109 @@
+// { dg-output "other!\nother!\nother!\nfifteen!\nfifteen!\nother!\nother!\nfifteen!\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn foo_i32(x: i32) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn foo_isize(x: isize) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn foo_u32(x: u32) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn foo_usize(x: usize) {
+    match x {
+        15 => {
+            let a = "fifteen!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "other!\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let x = -2;
+    foo_i32(x);
+    foo_i32(334);
+    foo_isize(-4768);
+    foo_isize(15);
+
+    let y = 127;
+    foo_u32(15);
+    foo_u32(y);
+    foo_usize(2394);
+    foo_usize(15);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_loop1.rs b/gcc/testsuite/rust/execute/torture/match_loop1.rs
new file mode 100644
index 00000000000..bb6aee946f6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_loop1.rs
@@ -0,0 +1,56 @@
+// { dg-output "E::One\nE::Two\nbreak!\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum E {
+    One,
+    Two,
+    Other,
+}
+
+fn foo() {
+    let mut x = E::One;
+
+    loop {
+        match x {
+            E::One => {
+                let a = "E::One\n\0";
+                let b = a as *const str;
+                let c = b as *const i8;
+                unsafe {
+                    printf(c);
+                }
+
+                x = E::Two;
+            }
+            E::Two => {
+                let a = "E::Two\n\0";
+                let b = a as *const str;
+                let c = b as *const i8;
+                unsafe {
+                    printf(c);
+                }
+
+                x = E::Other;
+            }
+            _ => {
+                let a = "break!\n\0";
+                let b = a as *const str;
+                let c = b as *const i8;
+                unsafe {
+                    printf(c);
+                }
+
+                break;
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    foo();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_range1.rs b/gcc/testsuite/rust/execute/torture/match_range1.rs
new file mode 100644
index 00000000000..82e9e34a989
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_range1.rs
@@ -0,0 +1,37 @@
+// { dg-output "zero to END_RANGE\nzero to END_RANGE\nelse\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+const END_RANGE: i32 = 15;
+
+fn foo(x: i32) {
+    match x {
+        0..=END_RANGE => {
+            let a = "zero to END_RANGE\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+
+        _ => {
+            let a = "else\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    foo(11);
+    foo(15);
+    foo(21);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_range2.rs b/gcc/testsuite/rust/execute/torture/match_range2.rs
new file mode 100644
index 00000000000..8153f9e1c7e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_range2.rs
@@ -0,0 +1,45 @@
+// { dg-output "lowercase\nuppercase\nother\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+const BIG_A: char = 'A';
+const BIG_Z: char = 'Z';
+
+fn bar(x: char) {
+    match x {
+        'a'..='z' => {
+            let a = "lowercase\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+        BIG_A..=BIG_Z => {
+            let a = "uppercase\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+        _ => {
+            let a = "other\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+            unsafe {
+                printf(c);
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    bar('b');
+    bar('X');
+    bar('!');
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/match_tuple1.rs b/gcc/testsuite/rust/execute/torture/match_tuple1.rs
new file mode 100644
index 00000000000..cb61cc0847c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match_tuple1.rs
@@ -0,0 +1,45 @@
+// { dg-output "x:15\ny:20\n" }
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+    A,
+    B,
+}
+
+fn inspect(f: Foo, g: u8) -> i32 {
+    match (f, g) {
+        (Foo::A, 1) => {
+            return 5;
+        }
+
+        (Foo::A, 2) => {
+            return 10;
+        }
+
+        (Foo::B, 2) => {
+            return 15;
+        }
+
+        _ => {
+            return 20;
+        }
+    }
+    return 25;
+}
+
+fn main() -> i32 {
+    let x = inspect(Foo::B, 2);
+    let y = inspect(Foo::B, 1);
+
+    unsafe {
+        printf("x:%d\n" as *const str as *const i8, x);
+    }
+    unsafe {
+        printf("y:%d\n" as *const str as *const i8, y);
+    }
+
+    y - x - 5
+}
diff --git a/gcc/testsuite/rust/execute/torture/method1.rs b/gcc/testsuite/rust/execute/torture/method1.rs
new file mode 100644
index 00000000000..6af6133939b
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method1.rs
@@ -0,0 +1,27 @@
+/* { dg-output "124\n458" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+    fn bar(&self, i: i32) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0 + i);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = Foo(123);
+    a.bar(1);
+
+    let b = &Foo(456);
+    b.bar(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/method2.rs b/gcc/testsuite/rust/execute/torture/method2.rs
new file mode 100644
index 00000000000..f532b4488c6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method2.rs
@@ -0,0 +1,76 @@
+// { dg-additional-options "-w" }
+// { dg-output "foo_deref\nimm_deref\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Bar(i32);
+impl Bar {
+    fn foobar(self) -> i32 {
+        self.0
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+pub fn main() -> i32 {
+    let bar = Bar(123);
+    let foo: Foo<&Bar> = Foo(&bar);
+    let foobar: i32 = foo.foobar();
+
+    foobar - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/method3.rs b/gcc/testsuite/rust/execute/torture/method3.rs
new file mode 100644
index 00000000000..0e9e8ff42a0
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method3.rs
@@ -0,0 +1,78 @@
+// { dg-additional-options "-w" }
+// { dg-output "mut_deref\nfoobar: 123\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+    fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+pub struct Bar(i32);
+impl Bar {
+    pub fn foobar(&mut self) -> i32 {
+        self.0
+    }
+}
+
+pub struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for Foo<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &mut self.0
+    }
+}
+
+pub fn main() -> i32 {
+    let bar = Bar(123);
+    let mut foo: Foo<Bar> = Foo(bar);
+    let foobar = foo.foobar();
+
+    unsafe {
+        let a = "foobar: %i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, foobar);
+    }
+
+    foobar - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/method4.rs b/gcc/testsuite/rust/execute/torture/method4.rs
new file mode 100644
index 00000000000..5c6fdfe02c3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/method4.rs
@@ -0,0 +1,78 @@
+// { dg-additional-options "-w" }
+// { dg-output "mut_deref\nfoobar: 123\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+    fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+pub struct Bar(i32);
+impl Bar {
+    pub fn foobar(&mut self) -> i32 {
+        self.0
+    }
+}
+
+pub struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for Foo<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &mut self.0
+    }
+}
+
+pub fn main() -> i32 {
+    let mut bar = Bar(123);
+    let mut foo: Foo<&mut Bar> = Foo(&mut bar);
+    let foobar = foo.foobar();
+
+    unsafe {
+        let a = "foobar: %i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, foobar);
+    }
+
+    foobar - 123
+}
diff --git a/gcc/testsuite/rust/execute/torture/mod1.rs b/gcc/testsuite/rust/execute/torture/mod1.rs
new file mode 100644
index 00000000000..700393850af
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/mod1.rs
@@ -0,0 +1,21 @@
+mod A {
+    pub mod B {
+        pub mod C {
+            pub struct Foo {
+                pub f: i32,
+            }
+            impl Foo {
+                pub fn new() -> Self {
+                    Foo { f: 23i32 }
+                }
+            }
+        }
+    }
+}
+
+fn main() -> i32 {
+    let a = A::B::C::Foo::new();
+    let b = A::B::C::Foo { f: -23i32 };
+
+    a.f + b.f
+}
diff --git a/gcc/testsuite/rust/execute/torture/modules/mod.rs b/gcc/testsuite/rust/execute/torture/modules/mod.rs
new file mode 100644
index 00000000000..9020aaf4bb8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/modules/mod.rs
@@ -0,0 +1,3 @@
+fn return_12() -> i32 {
+    12
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_1.rs b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
new file mode 100644
index 00000000000..5a28c5f4e93
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_1.rs
@@ -0,0 +1,36 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Add for i32 {
+    type Output = i32;
+
+    fn add(self, other: i32) -> i32 {
+        let res = self + other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = 1 + 2;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_10.rs b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
new file mode 100644
index 00000000000..f5d45db5338
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo: Foo<i32> = Foo(123);
+    let bar: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_11.rs b/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
new file mode 100644
index 00000000000..1919941c486
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_11.rs
@@ -0,0 +1,37 @@
+// { dg-output "1\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "bitand"]
+pub trait BitAnd<Rhs = Self> {
+    type Output;
+
+    fn bitand(self, rhs: Rhs) -> Self::Output;
+}
+
+impl BitAnd for i32 {
+    type Output = i32;
+
+    fn bitand(self, other: i32) -> i32 {
+        let res = self & other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = 1 & 1;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_12.rs b/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
new file mode 100644
index 00000000000..7433330fa31
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_12.rs
@@ -0,0 +1,31 @@
+// { dg-output "1\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "bitand_assign"]
+pub trait BitAndAssign<Rhs = Self> {
+    fn bitand_assign(&mut self, rhs: Rhs);
+}
+
+impl BitAndAssign for i32 {
+    fn bitand_assign(&mut self, other: i32) {
+        *self &= other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, *self);
+        }
+    }
+}
+
+fn main() -> i32 {
+    let mut a = 1;
+    a &= 1;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_2.rs b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
new file mode 100644
index 00000000000..a577718451d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_2.rs
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+struct Foo(i32);
+
+impl Add for Foo {
+    type Output = Foo;
+
+    fn add(self, other: Foo) -> Foo {
+        let res = Foo(self.0 + other.0);
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res.0);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(1) + Foo(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_3.rs b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
new file mode 100644
index 00000000000..57f58076c3e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_3.rs
@@ -0,0 +1,55 @@
+/* { dg-output "3\n3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+    type Output;
+
+    fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Add for i32 {
+    type Output = i32;
+
+    fn add(self, other: i32) -> i32 {
+        let res = self + other;
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res);
+        }
+
+        res
+    }
+}
+
+struct Foo(i32);
+impl Add for Foo {
+    type Output = Foo;
+
+    fn add(self, other: Foo) -> Foo {
+        let res = Foo(self.0 + other.0);
+
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, res.0);
+        }
+
+        res
+    }
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(1) + Foo(2);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_4.rs b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
new file mode 100644
index 00000000000..ce9887b2ead
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_4.rs
@@ -0,0 +1,33 @@
+/* { dg-output "neg\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "neg"]
+pub trait Neg {
+    type Output;
+
+    fn neg(self) -> Self::Output;
+}
+
+impl Neg for i32 {
+    type Output = i32;
+
+    fn neg(self) -> i32 {
+        unsafe {
+            let a = "neg\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        -self
+    }
+}
+
+fn main() -> i32 {
+    let a: i32 = 1;
+    let _b = -a;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_5.rs b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
new file mode 100644
index 00000000000..a525f743680
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_5.rs
@@ -0,0 +1,33 @@
+/* { dg-output "not\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "not"]
+pub trait Not {
+    type Output;
+
+    fn not(self) -> Self::Output;
+}
+
+impl Not for i32 {
+    type Output = i32;
+
+    fn not(self) -> i32 {
+        unsafe {
+            let a = "not\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        !self
+    }
+}
+
+fn main() -> i32 {
+    let a: i32 = 1;
+    let _b = !a;
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_6.rs b/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
new file mode 100644
index 00000000000..fbd2a8fa9d3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_6.rs
@@ -0,0 +1,37 @@
+/* { dg-output "add_assign\n3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "add_assign"]
+pub trait AddAssign<Rhs = Self> {
+    fn add_assign(&mut self, rhs: Rhs);
+}
+
+impl AddAssign for i32 {
+    fn add_assign(&mut self, other: i32) {
+        unsafe {
+            let a = "add_assign\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+        *self += other
+    }
+}
+
+fn main() -> i32 {
+    let mut res = 1;
+    res += 2;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_7.rs b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
new file mode 100644
index 00000000000..886a7010efc
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs
@@ -0,0 +1,42 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+fn main() -> i32 {
+    let foo: &i32 = &123;
+    let res: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_8.rs b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
new file mode 100644
index 00000000000..862e29a4bc6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs
@@ -0,0 +1,58 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+fn main() -> i32 {
+    let foo: &i32 = &123;
+    let res: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
new file mode 100644
index 00000000000..fd972e28ab3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
@@ -0,0 +1,58 @@
+/* { dg-output "mut_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+fn main() -> i32 {
+    let foo = &mut 123;
+    let res: i32 = *foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, res);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice-magic.rs b/gcc/testsuite/rust/execute/torture/slice-magic.rs
new file mode 100644
index 00000000000..d1132989ddb
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice-magic.rs
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<A> *const [A] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const A {
+        self as *const A
+    }
+}
+
+#[lang = "const_ptr"]
+impl<B> *const B {
+    pub const unsafe fn offset(self, count: isize) -> *const B {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const B {
+        self as *const B
+    }
+}
+
+const fn slice_from_raw_parts<C>(data: *const C, len: usize) -> *const [C] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<X> {
+    type Output;
+
+    unsafe fn get_unchecked(self, slice: *const X) -> *const Self::Output;
+
+    fn index(self, slice: &X) -> &Self::Output;
+}
+
+unsafe impl<Y> SliceIndex<[Y]> for Range<usize> {
+    type Output = [Y];
+
+    unsafe fn get_unchecked(self, slice: *const [Y]) -> *const [Y] {
+        unsafe {
+            let a: *const Y = slice.as_ptr();
+            let b: *const Y = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[Y]) -> &[Y] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice-magic2.rs b/gcc/testsuite/rust/execute/torture/slice-magic2.rs
new file mode 100644
index 00000000000..64a566185fa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice-magic2.rs
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+    pub start: Idx,
+    pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+    pub const fn len(self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) }
+    }
+
+    pub const unsafe fn add(self, count: usize) -> Self {
+        unsafe { self.offset(count as isize) }
+    }
+
+    pub const fn as_ptr(self) -> *const T {
+        self as *const T
+    }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
+    }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+    type Output;
+
+    fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+    type Output;
+
+    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+    fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+    type Output = [T];
+
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        unsafe {
+            let a: *const T = slice.as_ptr();
+            let b: *const T = a.add(self.start);
+            slice_from_raw_parts(b, self.end - self.start)
+        }
+    }
+
+    fn index(self, slice: &[T]) -> &[T] {
+        unsafe { &*self.get_unchecked(slice) }
+    }
+}
+
+impl<T, I> Index<I> for [T]
+where
+    I: SliceIndex<[T]>,
+{
+    type Output = I::Output;
+
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self)
+    }
+}
+
+fn main() -> i32 {
+    let a = [1, 2, 3, 4, 5];
+    let b = &a[1..3];
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/slice1.rs b/gcc/testsuite/rust/execute/torture/slice1.rs
new file mode 100644
index 00000000000..a0488b3912c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/slice1.rs
@@ -0,0 +1,27 @@
+// { dg-additional-options "-w" }
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+    unsafe {
+        let a = FatPtr { data, len };
+        let b = Repr { raw: a };
+        b.rust
+    }
+}
+
+fn main() -> i32 {
+    let a = 123;
+    let b: *const i32 = &a;
+    let c = slice_from_raw_parts(b, 1);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/str-layout1.rs b/gcc/testsuite/rust/execute/torture/str-layout1.rs
new file mode 100644
index 00000000000..80bdc2a9c9f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/str-layout1.rs
@@ -0,0 +1,57 @@
+// { dg-additional-options "-w" }
+// { dg-output "t1sz=5 t2sz=10" }
+mod mem {
+    extern "rust-intrinsic" {
+        #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+        fn transmute<T, U>(_: T) -> U;
+    }
+}
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+    data: *const T,
+    len: usize,
+}
+
+pub union Repr<T> {
+    rust: *const [T],
+    rust_mut: *mut [T],
+    raw: FatPtr<T>,
+}
+
+impl<T> [T] {
+    pub const fn len(&self) -> usize {
+        unsafe { Repr { rust: self }.raw.len }
+    }
+}
+
+impl str {
+    pub const fn len(&self) -> usize {
+        self.as_bytes().len()
+    }
+
+    pub const fn as_bytes(&self) -> &[u8] {
+        unsafe { mem::transmute(self) }
+    }
+}
+
+fn main() -> i32 {
+    let t1: &str = "TEST1";
+    let t2: &str = &"TEST_12345";
+
+    let t1sz = t1.len();
+    let t2sz = t2.len();
+
+    unsafe {
+        let a = "t1sz=%i t2sz=%i\n";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, t1sz as i32, t2sz as i32);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/str-zero.rs b/gcc/testsuite/rust/execute/torture/str-zero.rs
new file mode 100644
index 00000000000..e7fba0d1372
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/str-zero.rs
@@ -0,0 +1,26 @@
+/* { dg-output "bar foo baz foobar\n" } */
+extern "C"
+{
+  fn printf(s: *const i8, ...);
+  fn memchr(s: *const i8, c: u8, n: usize) -> *const i8;
+}
+
+pub fn main () -> i32
+{
+  let f = "%s %s %s %s\n\0";
+  let s = "bar\0\
+           foo\
+           \x00\
+           baz\u{0000}\
+           foobar\0";
+  let cf = f as *const str as *const i8;
+  let cs = s as *const str as *const i8;
+  unsafe
+    {
+      let cs2 = memchr (cs, b'f', 5);
+      let cs3 = memchr (cs2, b'b', 5);
+      let cs4 = memchr (cs3, b'f', 5);
+      printf (cf, cs, cs2, cs3, cs4);
+    }
+  0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait1.rs b/gcc/testsuite/rust/execute/torture/trait1.rs
new file mode 100644
index 00000000000..dc3cc471c33
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait1.rs
@@ -0,0 +1,52 @@
+/* { dg-output "S::f\nT1::f\nT2::f\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct S;
+
+impl S {
+    fn f() {
+        unsafe {
+            let a = "S::f\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+
+trait T1 {
+    fn f() {
+        unsafe {
+            let a = "T1::f\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+impl T1 for S {}
+
+trait T2 {
+    fn f() {
+        unsafe {
+            let a = "T2::f\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+    }
+}
+impl T2 for S {}
+
+fn main() -> i32 {
+    S::f();
+    <S as T1>::f();
+    <S as T2>::f();
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait10.rs b/gcc/testsuite/rust/execute/torture/trait10.rs
new file mode 100644
index 00000000000..e581e324bbf
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait10.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+struct S;
+impl S {
+    fn dynamic_dispatch(self, t: &dyn Bar) {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        t.baz();
+    }
+}
+
+pub fn main() -> i32 {
+    let a;
+    a = &Foo(123);
+
+    let b;
+    b = S;
+
+    b.dynamic_dispatch(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait11.rs b/gcc/testsuite/rust/execute/torture/trait11.rs
new file mode 100644
index 00000000000..283c9ecd0ed
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait11.rs
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+    fn call(&self, arg: A) -> R;
+}
+
+struct S;
+impl<'a, T> FnLike<&'a T, &'a T> for S {
+    fn call(&self, arg: &'a T) -> &'a T {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        arg
+    }
+}
+
+fn indirect<F>(f: F)
+where
+    F: for<'a> FnLike<&'a isize, &'a isize>,
+{
+    let x = 3;
+    let y = f.call(&x);
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *y);
+    }
+}
+
+fn main() -> i32 {
+    indirect(S);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait12.rs b/gcc/testsuite/rust/execute/torture/trait12.rs
new file mode 100644
index 00000000000..68b0a4014ad
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait12.rs
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+    fn call(&self, arg: A) -> R;
+}
+
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
+
+struct Identity;
+
+impl<'a, T> FnLike<&'a T, &'a T> for Identity {
+    fn call(&self, arg: &'a T) -> &'a T {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        arg
+    }
+}
+
+fn call_repeatedly(f: &FnObject) {
+    let x = 3;
+    let y = f.call(&x);
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *y);
+    }
+}
+
+fn main() -> i32 {
+    call_repeatedly(&Identity);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait13.rs b/gcc/testsuite/rust/execute/torture/trait13.rs
new file mode 100644
index 00000000000..3071da27a6a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait13.rs
@@ -0,0 +1,48 @@
+/* { dg-output "123\n456\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+
+    fn qux(&self) {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, 456);
+        }
+    }
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+    t.qux();
+}
+
+fn main() -> i32 {
+    let a;
+    a = Foo(123);
+
+    let b: &dyn Bar;
+    b = &a;
+    dynamic_dispatch(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait2.rs b/gcc/testsuite/rust/execute/torture/trait2.rs
new file mode 100644
index 00000000000..c96615fa891
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait2.rs
@@ -0,0 +1,37 @@
+/* { dg-output "Bar::A = 456\n<Foo as Bar>::A = 456\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait Foo {
+    const A: i32 = 123;
+}
+
+struct Bar;
+impl Foo for Bar {
+    const A: i32 = 456;
+}
+
+fn main() -> i32 {
+    let a;
+    a = Bar::A;
+
+    unsafe {
+        let _a = "Bar::A = %i\n\0";
+        let _b = _a as *const str;
+        let _c = _b as *const i8;
+        printf(_c, a);
+    }
+
+    let b;
+    b = <Bar as Foo>::A;
+
+    unsafe {
+        let _a = "<Foo as Bar>::A = %i\n\0";
+        let _b = _a as *const str;
+        let _c = _b as *const i8;
+        printf(_c, b);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait3.rs b/gcc/testsuite/rust/execute/torture/trait3.rs
new file mode 100644
index 00000000000..accfa9d0a36
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait3.rs
@@ -0,0 +1,43 @@
+/* { dg-output "123, 777" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait A {
+    fn a() -> i32 {
+        123
+    }
+}
+
+trait B: A {
+    fn b() -> i32 {
+        <T as A>::a() + 456
+    }
+}
+
+struct T;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl A for T {
+    fn a() -> i32 {
+        321
+    }
+}
+
+struct S;
+impl A for S {}
+impl B for S {}
+
+fn main() -> i32 {
+    let aa = S::a();
+    let bb = S::b();
+
+    unsafe {
+        let a = "%i, %i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, aa, bb);
+    }
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait4.rs b/gcc/testsuite/rust/execute/torture/trait4.rs
new file mode 100644
index 00000000000..8c0d257cd7e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait4.rs
@@ -0,0 +1,34 @@
+/* { dg-output "123\n" }*/
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn type_bound<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a;
+
+    a = &Foo(123);
+    type_bound(a);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait5.rs b/gcc/testsuite/rust/execute/torture/trait5.rs
new file mode 100644
index 00000000000..49f11a6085a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait5.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+    fn baz(&self);
+}
+
+impl Bar for Foo {
+    fn baz(&self) {
+        unsafe {
+            let a = "%i\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c, self.0);
+        }
+    }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+    t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+    t.baz();
+}
+
+fn main() -> i32 {
+    let a = &Foo(123);
+    static_dispatch(a);
+
+    let b: &dyn Bar = a;
+    dynamic_dispatch(b);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait6.rs b/gcc/testsuite/rust/execute/torture/trait6.rs
new file mode 100644
index 00000000000..c83d6666c87
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait6.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(self) -> Self::A {
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar::<S>(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait7.rs b/gcc/testsuite/rust/execute/torture/trait7.rs
new file mode 100644
index 00000000000..064f88d5de9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait7.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(self) -> Self::A {
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait8.rs b/gcc/testsuite/rust/execute/torture/trait8.rs
new file mode 100644
index 00000000000..14392ff0cca
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait8.rs
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(&self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(&self) -> Self::A {
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar(a);
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, bar);
+    }
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait9.rs b/gcc/testsuite/rust/execute/torture/trait9.rs
new file mode 100644
index 00000000000..c0e6d36f183
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait9.rs
@@ -0,0 +1,35 @@
+/* { dg-output "3\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+    fn call(&self, arg: A) -> R;
+}
+
+struct S;
+impl<T> FnLike<&T, &T> for S {
+    fn call(&self, arg: &T) -> &T {
+        // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+        arg
+    }
+}
+
+fn indirect<F: FnLike<&isize, &isize>>(f: F) {
+    let x = 3;
+    let y = f.call(&x);
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *y);
+    }
+}
+
+fn main() -> i32 {
+    indirect(S);
+
+    0
+}
diff --git a/gcc/testsuite/rust/execute/torture/transmute1.rs b/gcc/testsuite/rust/execute/torture/transmute1.rs
new file mode 100644
index 00000000000..b9ec38ca618
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/transmute1.rs
@@ -0,0 +1,23 @@
+// { dg-additional-options "-w" }
+
+extern "rust-intrinsic" {
+    fn transmute<T, U>(value: T) -> U;
+}
+
+struct WrapI {
+    inner: i32,
+}
+
+struct WrapF {
+    inner: f32,
+}
+
+fn main() -> i32 {
+    let f = 15.4f32;
+    let f_wrap = WrapF { inner: f };
+
+    let fst = unsafe { transmute::<f32, i32>(f) };
+    let snd = unsafe { transmute::<WrapF, WrapI>(f_wrap) };
+
+    fst - snd.inner
+}
diff --git a/gcc/testsuite/rust/execute/torture/wrapping_op1.rs b/gcc/testsuite/rust/execute/torture/wrapping_op1.rs
new file mode 100644
index 00000000000..64b37085ab7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/wrapping_op1.rs
@@ -0,0 +1,14 @@
+extern "rust-intrinsic" {
+    pub fn wrapping_add<T>(l: T, r: T) -> T;
+}
+
+fn five() -> u8 {
+    5
+}
+
+fn main() -> u8 {
+    let l = 255;
+    let r = five();
+
+    unsafe { wrapping_add(l, r) - 4 }
+}
diff --git a/gcc/testsuite/rust/execute/torture/wrapping_op2.rs b/gcc/testsuite/rust/execute/torture/wrapping_op2.rs
new file mode 100644
index 00000000000..f9990157894
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/wrapping_op2.rs
@@ -0,0 +1,20 @@
+extern "rust-intrinsic" {
+    pub fn wrapping_add<T>(l: T, r: T) -> T;
+    pub fn wrapping_sub<T>(l: T, r: T) -> T;
+    pub fn wrapping_mul<T>(l: T, r: T) -> T;
+}
+
+fn five() -> u8 {
+    5
+}
+
+fn main() -> u8 {
+    let l = 255;
+    let r = five();
+
+    let ret0 = unsafe { wrapping_add(l, r) - 4 }; // 4
+    let ret1 = unsafe { wrapping_sub(r, l) - 6 }; // 6
+    let ret2 = unsafe { wrapping_mul(r, l) - 251 }; // 251
+
+    ret0 + ret1 + ret2
+}
diff --git a/gcc/testsuite/rust/execute/xfail/macro1.rs b/gcc/testsuite/rust/execute/xfail/macro1.rs
new file mode 100644
index 00000000000..eab5a0285cf
--- /dev/null
+++ b/gcc/testsuite/rust/execute/xfail/macro1.rs
@@ -0,0 +1,32 @@
+// { dg-output "macro\nmacro\nmacro\nmacro\n" }
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn f() {
+    let r_s = "macro\n\0";
+    let s_p = r_s as *const str;
+    let c_p = s_p as *const i8;
+
+    printf(c_p);
+}
+
+macro_rules! empty0 {
+    () => ( f() );
+}
+
+macro_rules! empty1 {
+    {} => { f() };
+}
+
+macro_rules! empty2 {
+    [] => [ f() ];
+}
+
+// using multiple parens/brackets/curlies variants allows us to make sure we
+// parse everything properly
+fn main() {
+    empty0!();
+    empty1!{};
+    empty2![];
+}
-- 
2.37.2


  parent reply	other threads:[~2022-10-26  8:15 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-26  8:17 Rust frontend patches v3 arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 01/46] Use DW_ATE_UTF for the Rust 'char' type arthur.cohen
2022-10-26  8:39   ` Jakub Jelinek
2022-10-30 15:22     ` Mark Wielaard
2022-10-30 17:25       ` Jakub Jelinek
2022-10-31 14:19       ` Tom Tromey
2022-11-15 20:37       ` Marc Poulhiès
2022-10-26  8:17 ` [PATCH Rust front-end v3 02/46] gccrs: Add nessecary hooks for a Rust front-end testsuite arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 03/46] gccrs: Add Debug info testsuite arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 04/46] gccrs: Add link cases testsuite arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 05/46] gccrs: Add general compilation test cases arthur.cohen
2022-10-26  8:17 ` arthur.cohen [this message]
2022-10-26  8:17 ` [PATCH Rust front-end v3 07/46] gccrs: Add gcc-check-target check-rust arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 08/46] gccrs: Add Rust front-end base AST data structures arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 09/46] gccrs: Add definitions of Rust Items in " arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 10/46] gccrs: Add full definitions of Rust " arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 11/46] gccrs: Add Rust AST visitors arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 12/46] gccrs: Add Lexer for Rust front-end arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 13/46] gccrs: Add Parser for Rust front-end pt.1 arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 14/46] gccrs: Add Parser for Rust front-end pt.2 arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 15/46] gccrs: Add expansion pass for the Rust front-end arthur.cohen
2022-11-10 10:49   ` Richard Biener
2022-11-15 11:35     ` Arthur Cohen
2022-11-16 15:49       ` Richard Biener
2022-11-17 14:22         ` Arthur Cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 16/46] gccrs: Add name resolution pass to " arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 17/46] gccrs: Add declarations for Rust HIR arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 18/46] gccrs: Add HIR definitions and visitor framework arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 19/46] gccrs: Add AST to HIR lowering pass arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 20/46] gccrs: Add wrapper for make_unique arthur.cohen
2022-10-26 20:56   ` David Malcolm
2022-10-26  8:17 ` [PATCH Rust front-end v3 21/46] gccrs: Add port of FNV hash used during legacy symbol mangling arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 22/46] gccrs: Add Rust ABI enum helpers arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 23/46] gccrs: Add Base62 implementation arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 24/46] gccrs: Add implementation of Optional arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 25/46] gccrs: Add attributes checker arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 26/46] gccrs: Add helpers mappings canonical path and lang items arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 27/46] gccrs: Add type resolution and trait solving pass arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 28/46] gccrs: Add Rust type information arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 29/46] gccrs: Add remaining type system transformations arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 30/46] gccrs: Add unsafe checks for Rust arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 31/46] gccrs: Add const checker arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 32/46] gccrs: Add privacy checks arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 33/46] gccrs: Add dead code scan on HIR arthur.cohen
2022-10-26  8:17 ` [PATCH Rust front-end v3 34/46] gccrs: Add unused variable scan arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 35/46] gccrs: Add metadata ouptput pass arthur.cohen
2022-10-26 21:04   ` David Malcolm
2022-10-27  8:09     ` Arthur Cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 36/46] gccrs: Add base for HIR to GCC GENERIC lowering arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 37/46] gccrs: Add HIR to GCC GENERIC lowering for all nodes arthur.cohen
2022-11-09 18:07   ` Richard Biener
2022-11-15 12:32     ` Arthur Cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 38/46] gccrs: Add HIR to GCC GENERIC lowering entry point arthur.cohen
2022-11-09 13:53   ` Richard Biener
2022-11-15 13:49     ` Arthur Cohen
2022-11-18 13:02       ` Richard Biener
2022-11-29 18:13         ` Arthur Cohen
2022-11-30  7:53           ` Richard Biener
2022-11-21  9:03     ` Thomas Schwinge
2022-10-26  8:18 ` [PATCH Rust front-end v3 39/46] gccrs: These are wrappers ported from reusing gccgo arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 40/46] gccrs: Add GCC Rust front-end Make-lang.in arthur.cohen
2022-10-27  8:14   ` Arthur Cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 41/46] gccrs: Add config-lang.in arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 42/46] gccrs: Add lang-spec.h arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 43/46] gccrs: Add lang.opt arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 44/46] gccrs: Add compiler driver arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 45/46] gccrs: Compiler proper interface kicks off the pipeline arthur.cohen
2022-10-26  8:18 ` [PATCH Rust front-end v3 46/46] gccrs: Add README, CONTRIBUTING and compiler logo arthur.cohen
2022-10-26 21:15 ` Rust frontend patches v3 David Malcolm
2022-10-28 11:48   ` Arthur Cohen
2022-10-28 12:31     ` Richard Biener
2022-10-28 13:06     ` David Malcolm
2022-10-28 15:20       ` Arthur Cohen
2022-10-28 16:29         ` David Malcolm
2022-11-10 10:52 ` Richard Biener
2022-11-15 10:12   ` Arthur Cohen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221026081811.602573-7-arthur.cohen@embecosm.com \
    --to=arthur.cohen@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gcc-rust@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).