[Rust,front-end,v2,06/37] gccrs: Add execution test cases

Message ID 20220824115956.737931-7-philip.herron@embecosm.com
State New, archived
Headers
Series [Rust,front-end,v2,01/37] Use DW_ATE_UTF for the Rust 'char' type |

Commit Message

herron.philip@googlemail.com Aug. 24, 2022, 11:59 a.m. UTC
  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
  

Patch

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![];
+}