summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_gcc/tests
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_gcc/tests')
-rw-r--r--compiler/rustc_codegen_gcc/tests/lang_tests_common.rs68
-rw-r--r--compiler/rustc_codegen_gcc/tests/lang_tests_debug.rs5
-rw-r--r--compiler/rustc_codegen_gcc/tests/lang_tests_release.rs5
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/abort1.rs51
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/abort2.rs53
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/array.rs229
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/asm.rs172
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/assign.rs153
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/closure.rs230
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/condition.rs320
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/empty_main.rs39
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/exit.rs49
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/exit_code.rs39
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs223
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int.rs340
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int_overflow.rs140
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/mut_ref.rs165
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/operations.rs221
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs222
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/return-tuple.rs72
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/slice.rs128
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/static.rs112
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/structs.rs70
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/tuple.rs51
24 files changed, 3157 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
new file mode 100644
index 000000000..8e378177e
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
@@ -0,0 +1,68 @@
+//! The common code for `tests/lang_tests_*.rs`
+use std::{
+ env::{self, current_dir},
+ path::PathBuf,
+ process::Command,
+};
+
+use lang_tester::LangTester;
+use tempfile::TempDir;
+
+/// Controls the compile options (e.g., optimization level) used to compile
+/// test code.
+#[allow(dead_code)] // Each test crate picks one variant
+pub enum Profile {
+ Debug,
+ Release,
+}
+
+pub fn main_inner(profile: Profile) {
+ let tempdir = TempDir::new().expect("temp dir");
+ let current_dir = current_dir().expect("current dir");
+ let current_dir = current_dir.to_str().expect("current dir").to_string();
+ let gcc_path = include_str!("../gcc_path");
+ let gcc_path = gcc_path.trim();
+ env::set_var("LD_LIBRARY_PATH", gcc_path);
+ LangTester::new()
+ .test_dir("tests/run")
+ .test_file_filter(|path| path.extension().expect("extension").to_str().expect("to_str") == "rs")
+ .test_extract(|source| {
+ let lines =
+ source.lines()
+ .skip_while(|l| !l.starts_with("//"))
+ .take_while(|l| l.starts_with("//"))
+ .map(|l| &l[2..])
+ .collect::<Vec<_>>()
+ .join("\n");
+ Some(lines)
+ })
+ .test_cmds(move |path| {
+ // Test command 1: Compile `x.rs` into `tempdir/x`.
+ let mut exe = PathBuf::new();
+ exe.push(&tempdir);
+ exe.push(path.file_stem().expect("file_stem"));
+ let mut compiler = Command::new("rustc");
+ compiler.args(&[
+ &format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir),
+ "--sysroot", &format!("{}/build_sysroot/sysroot/", current_dir),
+ "-Zno-parallel-llvm",
+ "-C", "panic=abort",
+ "-C", "link-arg=-lc",
+ "-o", exe.to_str().expect("to_str"),
+ path.to_str().expect("to_str"),
+ ]);
+ match profile {
+ Profile::Debug => {}
+ Profile::Release => {
+ compiler.args(&[
+ "-C", "opt-level=3",
+ "-C", "lto=no",
+ ]);
+ }
+ }
+ // Test command 2: run `tempdir/x`.
+ let runtime = Command::new(exe);
+ vec![("Compiler", compiler), ("Run-time", runtime)]
+ })
+ .run();
+}
diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests_debug.rs b/compiler/rustc_codegen_gcc/tests/lang_tests_debug.rs
new file mode 100644
index 000000000..96bd74883
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/lang_tests_debug.rs
@@ -0,0 +1,5 @@
+mod lang_tests_common;
+
+fn main() {
+ lang_tests_common::main_inner(lang_tests_common::Profile::Debug);
+}
diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests_release.rs b/compiler/rustc_codegen_gcc/tests/lang_tests_release.rs
new file mode 100644
index 000000000..35d5d60c3
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/lang_tests_release.rs
@@ -0,0 +1,5 @@
+mod lang_tests_common;
+
+fn main() {
+ lang_tests_common::main_inner(lang_tests_common::Profile::Release);
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
new file mode 100644
index 000000000..291af5993
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
@@ -0,0 +1,51 @@
+// Compiler:
+//
+// Run-time:
+// status: signal
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod intrinsics {
+ use super::Sized;
+
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+/*
+ * Code
+ */
+
+fn test_fail() -> ! {
+ unsafe { intrinsics::abort() };
+}
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ test_fail();
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
new file mode 100644
index 000000000..3c87c5678
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
@@ -0,0 +1,53 @@
+// Compiler:
+//
+// Run-time:
+// status: signal
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod intrinsics {
+ use super::Sized;
+
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+/*
+ * Code
+ */
+
+fn fail() -> i32 {
+ unsafe { intrinsics::abort() };
+ 0
+}
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ fail();
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs
new file mode 100644
index 000000000..8b621d8a3
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/array.rs
@@ -0,0 +1,229 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 42
+// 7
+// 5
+// 10
+
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for usize {}
+impl Copy for i32 {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+impl Copy for i16 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ pub fn puts(s: *const u8) -> i32;
+ }
+}
+
+#[lang = "index"]
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> Index<usize> for [T; 3] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+impl<T> Index<usize> for [T] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+#[lang = "panic_bounds_check"]
+#[track_caller]
+#[no_mangle]
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+ unsafe {
+ libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
+ intrinsics::abort();
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+
+impl Sub for usize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for isize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for u8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i16 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+
+/*
+ * Code
+ */
+
+static mut ONE: usize = 1;
+
+fn make_array() -> [u8; 3] {
+ [42, 10, 5]
+}
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+ let array = [42, 7, 5];
+ let array2 = make_array();
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, array[ONE - 1]);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, array[ONE]);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, array[ONE + 1]);
+
+ libc::printf(b"%d\n\0" as *const u8 as *const i8, array2[argc as usize] as u32);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs
new file mode 100644
index 000000000..46abbb553
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs
@@ -0,0 +1,172 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+global_asm!("
+ .global add_asm
+add_asm:
+ mov rax, rdi
+ add rax, rsi
+ ret"
+);
+
+extern "C" {
+ fn add_asm(a: i64, b: i64) -> i64;
+}
+
+pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
+ asm!(
+ "rep movsb",
+ inout("rdi") dst => _,
+ inout("rsi") src => _,
+ inout("rcx") len => _,
+ options(preserves_flags, nostack)
+ );
+}
+
+fn main() {
+ unsafe {
+ asm!("nop");
+ }
+
+ let x: u64;
+ unsafe {
+ asm!("mov $5, {}",
+ out(reg) x,
+ options(att_syntax)
+ );
+ }
+ assert_eq!(x, 5);
+
+ let x: u64;
+ let input: u64 = 42;
+ unsafe {
+ asm!("mov {input}, {output}",
+ "add $1, {output}",
+ input = in(reg) input,
+ output = out(reg) x,
+ options(att_syntax)
+ );
+ }
+ assert_eq!(x, 43);
+
+ let x: u64;
+ unsafe {
+ asm!("mov {}, 6",
+ out(reg) x,
+ );
+ }
+ assert_eq!(x, 6);
+
+ let x: u64;
+ let input: u64 = 42;
+ unsafe {
+ asm!("mov {output}, {input}",
+ "add {output}, 1",
+ input = in(reg) input,
+ output = out(reg) x,
+ );
+ }
+ assert_eq!(x, 43);
+
+ // check inout(reg_class) x
+ let mut x: u64 = 42;
+ unsafe {
+ asm!("add {0}, {0}",
+ inout(reg) x
+ );
+ }
+ assert_eq!(x, 84);
+
+ // check inout("reg") x
+ let mut x: u64 = 42;
+ unsafe {
+ asm!("add r11, r11",
+ inout("r11") x
+ );
+ }
+ assert_eq!(x, 84);
+
+ // check a mix of
+ // in("reg")
+ // inout(class) x => y
+ // inout (class) x
+ let x: u64 = 702;
+ let y: u64 = 100;
+ let res: u64;
+ let mut rem: u64 = 0;
+ unsafe {
+ asm!("div r11",
+ in("r11") y,
+ inout("eax") x => res,
+ inout("edx") rem,
+ );
+ }
+ assert_eq!(res, 7);
+ assert_eq!(rem, 2);
+
+ // check const
+ let mut x: u64 = 42;
+ unsafe {
+ asm!("add {}, {}",
+ inout(reg) x,
+ const 1
+ );
+ }
+ assert_eq!(x, 43);
+
+ // check const (ATT syntax)
+ let mut x: u64 = 42;
+ unsafe {
+ asm!("add {}, {}",
+ const 1,
+ inout(reg) x,
+ options(att_syntax)
+ );
+ }
+ assert_eq!(x, 43);
+
+ // check sym fn
+ extern "C" fn foo() -> u64 { 42 }
+ let x: u64;
+ unsafe {
+ asm!("call {}", sym foo, lateout("rax") x);
+ }
+ assert_eq!(x, 42);
+
+ // check sym fn (ATT syntax)
+ let x: u64;
+ unsafe {
+ asm!("call {}", sym foo, lateout("rax") x, options(att_syntax));
+ }
+ assert_eq!(x, 42);
+
+ // check sym static
+ static FOO: u64 = 42;
+ let x: u64;
+ unsafe {
+ asm!("mov {1}, qword ptr [rip + {0}]", sym FOO, lateout(reg) x);
+ }
+ assert_eq!(x, 42);
+
+ // check sym static (ATT syntax)
+ let x: u64;
+ unsafe {
+ asm!("movq {0}(%rip), {1}", sym FOO, lateout(reg) x, options(att_syntax));
+ }
+ assert_eq!(x, 42);
+
+ assert_eq!(unsafe { add_asm(40, 2) }, 42);
+
+ let array1 = [1u8, 2, 3];
+ let mut array2 = [0u8, 0, 0];
+ unsafe {
+ mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3);
+ }
+ assert_eq!(array1, array2);
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs
new file mode 100644
index 000000000..eb38a8a38
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs
@@ -0,0 +1,153 @@
+// Compiler:
+//
+// Run-time:
+// stdout: 2
+// 7 8
+// 10
+
+#![allow(unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for *mut i32 {}
+impl Copy for usize {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+impl Copy for i32 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn puts(s: *const u8) -> i32;
+ pub fn fflush(stream: *mut i32) -> i32;
+ pub fn printf(format: *const i8, ...) -> i32;
+
+ pub static stdout: *mut i32;
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ libc::fflush(libc::stdout);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+/*
+ * Code
+ */
+
+fn inc_ref(num: &mut isize) -> isize {
+ *num = *num + 5;
+ *num + 1
+}
+
+fn inc(num: isize) -> isize {
+ num + 1
+}
+
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ argc = inc(argc);
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);
+ }
+
+ let b = inc_ref(&mut argc);
+ unsafe {
+ libc::printf(b"%ld %ld\n\0" as *const u8 as *const i8, argc, b);
+ }
+
+ argc = 10;
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs
new file mode 100644
index 000000000..7121a5f0d
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs
@@ -0,0 +1,230 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: Arg: 1
+// Argument: 1
+// String arg: 1
+// Int argument: 2
+// Both args: 11
+
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics,
+ unboxed_closures)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for usize {}
+impl Copy for i32 {}
+impl Copy for u32 {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn puts(s: *const u8) -> i32;
+ pub fn printf(format: *const i8, ...) -> i32;
+ }
+}
+
+#[lang = "index"]
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> Index<usize> for [T; 3] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+impl<T> Index<usize> for [T] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+#[lang = "panic_bounds_check"]
+#[track_caller]
+#[no_mangle]
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+ unsafe {
+ libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
+ intrinsics::abort();
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "unsize"]
+pub trait Unsize<T: ?Sized> {}
+
+#[lang = "coerce_unsized"]
+pub trait CoerceUnsized<T> {}
+
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
+
+#[lang = "fn_once"]
+#[rustc_paren_sugar]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_mut"]
+#[rustc_paren_sugar]
+pub trait FnMut<Args>: FnOnce<Args> {
+ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ intrinsics::abort();
+ }
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ let string = "Arg: %d\n\0";
+ let mut closure = || {
+ unsafe {
+ libc::printf(string as *const str as *const i8, argc);
+ }
+ };
+ closure();
+
+ let mut closure = || {
+ unsafe {
+ libc::printf("Argument: %d\n\0" as *const str as *const i8, argc);
+ }
+ };
+ closure();
+
+ let mut closure = |string| {
+ unsafe {
+ libc::printf(string as *const str as *const i8, argc);
+ }
+ };
+ closure("String arg: %d\n\0");
+
+ let mut closure = |arg: isize| {
+ unsafe {
+ libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg);
+ }
+ };
+ closure(argc + 1);
+
+ let mut closure = |string, arg: isize| {
+ unsafe {
+ libc::printf(string as *const str as *const i8, arg);
+ }
+ };
+ closure("Both args: %d\n\0", argc + 10);
+
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs
new file mode 100644
index 000000000..6a2e2d5bb
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs
@@ -0,0 +1,320 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: true
+// 1
+
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for usize {}
+impl Copy for u64 {}
+impl Copy for i32 {}
+impl Copy for u32 {}
+impl Copy for bool {}
+impl Copy for u16 {}
+impl Copy for i16 {}
+impl Copy for char {}
+impl Copy for i8 {}
+impl Copy for u8 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ pub fn puts(s: *const u8) -> i32;
+ }
+}
+
+#[lang = "index"]
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> Index<usize> for [T; 3] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+impl<T> Index<usize> for [T] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+#[lang = "panic_bounds_check"]
+#[track_caller]
+#[no_mangle]
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+ unsafe {
+ libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
+ intrinsics::abort();
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+
+impl Sub for usize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for isize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for u8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i16 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+ fn ne(&self, other: &Rhs) -> bool;
+}
+
+impl PartialEq for u8 {
+ fn eq(&self, other: &u8) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &u8) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for u16 {
+ fn eq(&self, other: &u16) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &u16) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for u32 {
+ fn eq(&self, other: &u32) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &u32) -> bool {
+ (*self) != (*other)
+ }
+}
+
+
+impl PartialEq for u64 {
+ fn eq(&self, other: &u64) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &u64) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for usize {
+ fn eq(&self, other: &usize) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &usize) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for i8 {
+ fn eq(&self, other: &i8) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &i8) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &i32) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &i32) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for isize {
+ fn eq(&self, other: &isize) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &isize) -> bool {
+ (*self) != (*other)
+ }
+}
+
+impl PartialEq for char {
+ fn eq(&self, other: &char) -> bool {
+ (*self) == (*other)
+ }
+ fn ne(&self, other: &char) -> bool {
+ (*self) != (*other)
+ }
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+ unsafe {
+ if argc == 1 {
+ libc::printf(b"true\n\0" as *const u8 as *const i8);
+ }
+
+ let string =
+ match argc {
+ 1 => b"1\n\0",
+ 2 => b"2\n\0",
+ 3 => b"3\n\0",
+ 4 => b"4\n\0",
+ 5 => b"5\n\0",
+ _ => b"_\n\0",
+ };
+ libc::printf(string as *const u8 as *const i8);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
new file mode 100644
index 000000000..c02cfd2a8
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs
@@ -0,0 +1,39 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+
+#![feature(auto_traits, lang_items, no_core, start)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/exit.rs b/compiler/rustc_codegen_gcc/tests/run/exit.rs
new file mode 100644
index 000000000..956e53dd4
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/exit.rs
@@ -0,0 +1,49 @@
+// Compiler:
+//
+// Run-time:
+// status: 2
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn exit(status: i32);
+ }
+}
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ unsafe {
+ libc::exit(2);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
new file mode 100644
index 000000000..eeab35209
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs
@@ -0,0 +1,39 @@
+// Compiler:
+//
+// Run-time:
+// status: 1
+
+#![feature(auto_traits, lang_items, no_core, start)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ 1
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
new file mode 100644
index 000000000..a226fff79
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
@@ -0,0 +1,223 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 1
+
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for usize {}
+impl Copy for i32 {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+impl Copy for i16 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ pub fn puts(s: *const u8) -> i32;
+ }
+}
+
+#[lang = "index"]
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> Index<usize> for [T; 3] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+impl<T> Index<usize> for [T] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+#[lang = "panic_bounds_check"]
+#[track_caller]
+#[no_mangle]
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+ unsafe {
+ libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
+ intrinsics::abort();
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+
+impl Sub for usize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for isize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for u8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i16 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+
+/*
+ * Code
+ */
+
+fn i16_as_i8(a: i16) -> i8 {
+ a as i8
+}
+
+fn call_func(func: fn(i16) -> i8, param: i16) -> i8 {
+ func(param)
+}
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+ unsafe {
+ let result = call_func(i16_as_i8, argc as i16) as isize;
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, result);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
new file mode 100644
index 000000000..2b90e4ae8
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -0,0 +1,340 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+
+#![feature(bench_black_box, const_black_box, core_intrinsics, start)]
+
+#![no_std]
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+ core::intrinsics::abort();
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ use core::hint::black_box;
+
+ macro_rules! check {
+ ($ty:ty, $expr:expr) => {
+ {
+ const EXPECTED: $ty = $expr;
+ assert_eq!($expr, EXPECTED);
+ }
+ };
+ }
+
+ check!(u32, (2220326408_u32 + black_box(1)) >> (32 - 6));
+
+ /// Generate `check!` tests for integer types at least as wide as 128 bits.
+ macro_rules! check_ops128 {
+ () => {
+ check_ops64!();
+
+ // Shifts.
+ check!(T, VAL1 << black_box(64));
+ check!(T, VAL1 << black_box(81));
+ check!(T, VAL3 << black_box(63));
+ check!(T, VAL3 << black_box(64));
+
+ check!(T, VAL1 >> black_box(64));
+ check!(T, VAL2 >> black_box(64));
+ check!(T, VAL3 >> black_box(64));
+ check!(T, VAL3 >> black_box(81));
+ };
+ }
+
+ /// Generate `check!` tests for integer types at least as wide as 64 bits.
+ macro_rules! check_ops64 {
+ () => {
+ check_ops32!();
+
+ // Shifts.
+ check!(T, VAL2 << black_box(33));
+ check!(T, VAL2 << black_box(49));
+ check!(T, VAL2 << black_box(61));
+ check!(T, VAL2 << black_box(63));
+
+ check!(T, VAL3 << black_box(33));
+ check!(T, VAL3 << black_box(49));
+ check!(T, VAL3 << black_box(61));
+
+ check!(T, VAL1 >> black_box(33));
+ check!(T, VAL1 >> black_box(49));
+ check!(T, VAL1 >> black_box(61));
+ check!(T, VAL1 >> black_box(63));
+
+ check!(T, VAL2 >> black_box(33));
+ check!(T, VAL2 >> black_box(49));
+ check!(T, VAL2 >> black_box(61));
+ check!(T, VAL2 >> black_box(63));
+
+ check!(T, VAL3 >> black_box(33));
+ check!(T, VAL3 >> black_box(49));
+ check!(T, VAL3 >> black_box(61));
+ check!(T, VAL3 >> black_box(63));
+ };
+ }
+
+ /// Generate `check!` tests for integer types at least as wide as 32 bits.
+ macro_rules! check_ops32 {
+ () => {
+ // Shifts.
+ check!(T, VAL2 << black_box(1));
+ check!(T, VAL2 << black_box(0));
+
+ check!(T, VAL3 << black_box(1));
+ check!(T, VAL3 << black_box(0));
+
+ check!(T, VAL1.wrapping_shl(black_box(0)));
+ check!(T, VAL1.wrapping_shl(black_box(1)));
+ check!(T, VAL1.wrapping_shl(black_box(33)));
+ check!(T, VAL1.wrapping_shl(black_box(49)));
+ check!(T, VAL1.wrapping_shl(black_box(61)));
+ check!(T, VAL1.wrapping_shl(black_box(63)));
+ check!(T, VAL1.wrapping_shl(black_box(64)));
+ check!(T, VAL1.wrapping_shl(black_box(81)));
+
+ check!(Option<T>, VAL1.checked_shl(black_box(0)));
+ check!(Option<T>, VAL1.checked_shl(black_box(1)));
+ check!(Option<T>, VAL1.checked_shl(black_box(33)));
+ check!(Option<T>, VAL1.checked_shl(black_box(49)));
+ check!(Option<T>, VAL1.checked_shl(black_box(61)));
+ check!(Option<T>, VAL1.checked_shl(black_box(63)));
+ check!(Option<T>, VAL1.checked_shl(black_box(64)));
+ check!(Option<T>, VAL1.checked_shl(black_box(81)));
+
+ check!(T, VAL1 >> black_box(0));
+ check!(T, VAL1 >> black_box(1));
+
+ check!(T, VAL2 >> black_box(1));
+ check!(T, VAL2 >> black_box(0));
+
+ check!(T, VAL3 >> black_box(0));
+ check!(T, VAL3 >> black_box(1));
+
+ check!(T, VAL1.wrapping_shr(black_box(0)));
+ check!(T, VAL1.wrapping_shr(black_box(1)));
+ check!(T, VAL1.wrapping_shr(black_box(33)));
+ check!(T, VAL1.wrapping_shr(black_box(49)));
+ check!(T, VAL1.wrapping_shr(black_box(61)));
+ check!(T, VAL1.wrapping_shr(black_box(63)));
+ check!(T, VAL1.wrapping_shr(black_box(64)));
+ check!(T, VAL1.wrapping_shr(black_box(81)));
+
+ check!(Option<T>, VAL1.checked_shr(black_box(0)));
+ check!(Option<T>, VAL1.checked_shr(black_box(1)));
+ check!(Option<T>, VAL1.checked_shr(black_box(33)));
+ check!(Option<T>, VAL1.checked_shr(black_box(49)));
+ check!(Option<T>, VAL1.checked_shr(black_box(61)));
+ check!(Option<T>, VAL1.checked_shr(black_box(63)));
+ check!(Option<T>, VAL1.checked_shr(black_box(64)));
+ check!(Option<T>, VAL1.checked_shr(black_box(81)));
+
+ // Casts
+ check!(u64, (VAL1 >> black_box(1)) as u64);
+
+ // Addition.
+ check!(T, VAL1 + black_box(1));
+ check!(T, VAL2 + black_box(1));
+ check!(T, VAL2 + (VAL2 + black_box(1)));
+ check!(T, VAL3 + black_box(1));
+
+ check!(Option<T>, VAL1.checked_add(black_box(1)));
+ check!(Option<T>, VAL2.checked_add(black_box(1)));
+ check!(Option<T>, VAL2.checked_add(VAL2 + black_box(1)));
+ check!(Option<T>, VAL3.checked_add(T::MAX));
+ check!(Option<T>, VAL3.checked_add(T::MIN));
+
+ check!(T, VAL1.wrapping_add(black_box(1)));
+ check!(T, VAL2.wrapping_add(black_box(1)));
+ check!(T, VAL2.wrapping_add(VAL2 + black_box(1)));
+ check!(T, VAL3.wrapping_add(T::MAX));
+ check!(T, VAL3.wrapping_add(T::MIN));
+
+ check!((T, bool), VAL1.overflowing_add(black_box(1)));
+ check!((T, bool), VAL2.overflowing_add(black_box(1)));
+ check!((T, bool), VAL2.overflowing_add(VAL2 + black_box(1)));
+ check!((T, bool), VAL3.overflowing_add(T::MAX));
+ check!((T, bool), VAL3.overflowing_add(T::MIN));
+
+ check!(T, VAL1.saturating_add(black_box(1)));
+ check!(T, VAL2.saturating_add(black_box(1)));
+ check!(T, VAL2.saturating_add(VAL2 + black_box(1)));
+ check!(T, VAL3.saturating_add(T::MAX));
+ check!(T, VAL3.saturating_add(T::MIN));
+
+ // Subtraction
+ check!(T, VAL1 - black_box(1));
+ check!(T, VAL2 - black_box(1));
+ check!(T, VAL3 - black_box(1));
+
+ check!(Option<T>, VAL1.checked_sub(black_box(1)));
+ check!(Option<T>, VAL2.checked_sub(black_box(1)));
+ check!(Option<T>, VAL2.checked_sub(VAL2 + black_box(1)));
+ check!(Option<T>, VAL3.checked_sub(T::MAX));
+ check!(Option<T>, VAL3.checked_sub(T::MIN));
+
+ check!(T, VAL1.wrapping_sub(black_box(1)));
+ check!(T, VAL2.wrapping_sub(black_box(1)));
+ check!(T, VAL2.wrapping_sub(VAL2 + black_box(1)));
+ check!(T, VAL3.wrapping_sub(T::MAX));
+ check!(T, VAL3.wrapping_sub(T::MIN));
+
+ check!((T, bool), VAL1.overflowing_sub(black_box(1)));
+ check!((T, bool), VAL2.overflowing_sub(black_box(1)));
+ check!((T, bool), VAL2.overflowing_sub(VAL2 + black_box(1)));
+ check!((T, bool), VAL3.overflowing_sub(T::MAX));
+ check!((T, bool), VAL3.overflowing_sub(T::MIN));
+
+ check!(T, VAL1.saturating_sub(black_box(1)));
+ check!(T, VAL2.saturating_sub(black_box(1)));
+ check!(T, VAL2.saturating_sub(VAL2 + black_box(1)));
+ check!(T, VAL3.saturating_sub(T::MAX));
+ check!(T, VAL3.saturating_sub(T::MIN));
+
+ // Multiplication
+ check!(T, VAL1 * black_box(2));
+ check!(T, VAL1 * (black_box(1) + VAL2));
+ check!(T, VAL2 * black_box(2));
+ check!(T, VAL2 * (black_box(1) + VAL2));
+ check!(T, VAL3 * black_box(1));
+ check!(T, VAL4 * black_box(2));
+ check!(T, VAL5 * black_box(2));
+
+ check!(Option<T>, VAL1.checked_mul(black_box(2)));
+ check!(Option<T>, VAL1.checked_mul(black_box(1) + VAL2));
+ check!(Option<T>, VAL3.checked_mul(VAL3));
+ check!(Option<T>, VAL4.checked_mul(black_box(2)));
+ check!(Option<T>, VAL5.checked_mul(black_box(2)));
+
+ check!(T, VAL1.wrapping_mul(black_box(2)));
+ check!(T, VAL1.wrapping_mul((black_box(1) + VAL2)));
+ check!(T, VAL3.wrapping_mul(VAL3));
+ check!(T, VAL4.wrapping_mul(black_box(2)));
+ check!(T, VAL5.wrapping_mul(black_box(2)));
+
+ check!((T, bool), VAL1.overflowing_mul(black_box(2)));
+ check!((T, bool), VAL1.overflowing_mul(black_box(1) + VAL2));
+ check!((T, bool), VAL3.overflowing_mul(VAL3));
+ check!((T, bool), VAL4.overflowing_mul(black_box(2)));
+ check!((T, bool), VAL5.overflowing_mul(black_box(2)));
+
+ check!(T, VAL1.saturating_mul(black_box(2)));
+ check!(T, VAL1.saturating_mul(black_box(1) + VAL2));
+ check!(T, VAL3.saturating_mul(VAL3));
+ check!(T, VAL4.saturating_mul(black_box(2)));
+ check!(T, VAL5.saturating_mul(black_box(2)));
+
+ // Division.
+ check!(T, VAL1 / black_box(2));
+ check!(T, VAL1 / black_box(3));
+
+ check!(T, VAL2 / black_box(2));
+ check!(T, VAL2 / black_box(3));
+
+ check!(T, VAL3 / black_box(2));
+ check!(T, VAL3 / black_box(3));
+ check!(T, VAL3 / (black_box(1) + VAL4));
+ check!(T, VAL3 / (black_box(1) + VAL2));
+
+ check!(T, VAL4 / black_box(2));
+ check!(T, VAL4 / black_box(3));
+
+ check!(Option<T>, VAL1.checked_div(black_box(2)));
+ check!(Option<T>, VAL1.checked_div(black_box(1) + VAL2));
+ check!(Option<T>, VAL3.checked_div(VAL3));
+ check!(Option<T>, VAL4.checked_div(black_box(2)));
+ check!(Option<T>, VAL5.checked_div(black_box(2)));
+ check!(Option<T>, (T::MIN).checked_div(black_box(0 as T).wrapping_sub(1)));
+ check!(Option<T>, VAL5.checked_div(black_box(0))); // var5 / 0
+
+ check!(T, VAL1.wrapping_div(black_box(2)));
+ check!(T, VAL1.wrapping_div(black_box(1) + VAL2));
+ check!(T, VAL3.wrapping_div(VAL3));
+ check!(T, VAL4.wrapping_div(black_box(2)));
+ check!(T, VAL5.wrapping_div(black_box(2)));
+ check!(T, (T::MIN).wrapping_div(black_box(0 as T).wrapping_sub(1)));
+
+ check!((T, bool), VAL1.overflowing_div(black_box(2)));
+ check!((T, bool), VAL1.overflowing_div(black_box(1) + VAL2));
+ check!((T, bool), VAL3.overflowing_div(VAL3));
+ check!((T, bool), VAL4.overflowing_div(black_box(2)));
+ check!((T, bool), VAL5.overflowing_div(black_box(2)));
+ check!((T, bool), (T::MIN).overflowing_div(black_box(0 as T).wrapping_sub(1)));
+
+ check!(T, VAL1.saturating_div(black_box(2)));
+ check!(T, VAL1.saturating_div((black_box(1) + VAL2)));
+ check!(T, VAL3.saturating_div(VAL3));
+ check!(T, VAL4.saturating_div(black_box(2)));
+ check!(T, VAL5.saturating_div(black_box(2)));
+ check!(T, (T::MIN).saturating_div((0 as T).wrapping_sub(black_box(1))));
+ };
+ }
+
+ {
+ type T = u32;
+ const VAL1: T = 14162_u32;
+ const VAL2: T = 14556_u32;
+ const VAL3: T = 323656954_u32;
+ const VAL4: T = 2023651954_u32;
+ const VAL5: T = 1323651954_u32;
+ check_ops32!();
+ }
+
+ {
+ type T = i32;
+ const VAL1: T = 13456_i32;
+ const VAL2: T = 10475_i32;
+ const VAL3: T = 923653954_i32;
+ const VAL4: T = 993198738_i32;
+ const VAL5: T = 1023653954_i32;
+ check_ops32!();
+ }
+
+ {
+ type T = u64;
+ const VAL1: T = 134217856_u64;
+ const VAL2: T = 104753732_u64;
+ const VAL3: T = 12323651988970863954_u64;
+ const VAL4: T = 7323651988970863954_u64;
+ const VAL5: T = 8323651988970863954_u64;
+ check_ops64!();
+ }
+
+ {
+ type T = i64;
+ const VAL1: T = 134217856_i64;
+ const VAL2: T = 104753732_i64;
+ const VAL3: T = 6323651988970863954_i64;
+ const VAL4: T = 2323651988970863954_i64;
+ const VAL5: T = 3323651988970863954_i64;
+ check_ops64!();
+ }
+
+ {
+ type T = u128;
+ const VAL1: T = 134217856_u128;
+ const VAL2: T = 10475372733397991552_u128;
+ const VAL3: T = 193236519889708027473620326106273939584_u128;
+ const VAL4: T = 123236519889708027473620326106273939584_u128;
+ const VAL5: T = 153236519889708027473620326106273939584_u128;
+ check_ops128!();
+ }
+ {
+ type T = i128;
+ const VAL1: T = 134217856_i128;
+ const VAL2: T = 10475372733397991552_i128;
+ const VAL3: T = 83236519889708027473620326106273939584_i128;
+ const VAL4: T = 63236519889708027473620326106273939584_i128;
+ const VAL5: T = 73236519889708027473620326106273939584_i128;
+ check_ops128!();
+ }
+
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
new file mode 100644
index 000000000..ea2c5add9
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
@@ -0,0 +1,140 @@
+// Compiler:
+//
+// Run-time:
+// stdout: Success
+// status: signal
+
+#![allow(unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for *mut i32 {}
+impl Copy for usize {}
+impl Copy for i32 {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn puts(s: *const u8) -> i32;
+ pub fn fflush(stream: *mut i32) -> i32;
+
+ pub static stdout: *mut i32;
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ // Panicking is expected iff overflow checking is enabled.
+ #[cfg(debug_assertions)]
+ libc::puts("Success\0" as *const str as *const u8);
+ libc::fflush(libc::stdout);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ let int = 9223372036854775807isize;
+ let int = int + argc; // overflow
+
+ // If overflow checking is disabled, we should reach here.
+ #[cfg(not(debug_assertions))]
+ unsafe {
+ libc::puts("Success\0" as *const str as *const u8);
+ libc::fflush(libc::stdout);
+ intrinsics::abort();
+ }
+
+ int
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
new file mode 100644
index 000000000..52de20021
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
@@ -0,0 +1,165 @@
+
+// Compiler:
+//
+// Run-time:
+// stdout: 2
+// 7
+// 6
+// 11
+
+#![allow(unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for *mut i32 {}
+impl Copy for usize {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+impl Copy for i32 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn puts(s: *const u8) -> i32;
+ pub fn fflush(stream: *mut i32) -> i32;
+ pub fn printf(format: *const i8, ...) -> i32;
+
+ pub static stdout: *mut i32;
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ libc::fflush(libc::stdout);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+/*
+ * Code
+ */
+
+struct Test {
+ field: isize,
+}
+
+fn test(num: isize) -> Test {
+ Test {
+ field: num + 1,
+ }
+}
+
+fn update_num(num: &mut isize) {
+ *num = *num + 5;
+}
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ let mut test = test(argc);
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
+ }
+ update_num(&mut test.field);
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
+ }
+
+ update_num(&mut argc);
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);
+ }
+
+ let refe = &mut argc;
+ *refe = *refe + 5;
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);
+ }
+
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs
new file mode 100644
index 000000000..e078b37b4
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs
@@ -0,0 +1,221 @@
+// Compiler:
+//
+// Run-time:
+// stdout: 41
+// 39
+// 10
+
+#![allow(unused_attributes)]
+#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for *mut i32 {}
+impl Copy for usize {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target: ?Sized;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ pub fn puts(s: *const u8) -> i32;
+ pub fn fflush(stream: *mut i32) -> i32;
+
+ pub static stdout: *mut i32;
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ libc::fflush(libc::stdout);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+
+impl Sub for usize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for isize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for u8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i16 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+#[lang = "mul"]
+pub trait Mul<RHS = Self> {
+ type Output;
+
+ #[must_use]
+ fn mul(self, rhs: RHS) -> Self::Output;
+}
+
+impl Mul for u8 {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self::Output {
+ self * rhs
+ }
+}
+
+impl Mul for usize {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self::Output {
+ self * rhs
+ }
+}
+
+impl Mul for isize {
+ type Output = Self;
+
+ fn mul(self, rhs: Self) -> Self::Output {
+ self * rhs
+ }
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, 10 * argc);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
new file mode 100644
index 000000000..6ac099ea1
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
@@ -0,0 +1,222 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 1
+
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for usize {}
+impl Copy for i32 {}
+impl Copy for u8 {}
+impl Copy for i8 {}
+impl Copy for i16 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ pub fn puts(s: *const u8) -> i32;
+ }
+}
+
+#[lang = "index"]
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> Index<usize> for [T; 3] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+impl<T> Index<usize> for [T] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+#[lang = "panic"]
+#[track_caller]
+#[no_mangle]
+pub fn panic(_msg: &str) -> ! {
+ unsafe {
+ libc::puts("Panicking\0" as *const str as *const u8);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+#[lang = "panic_bounds_check"]
+#[track_caller]
+#[no_mangle]
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+ unsafe {
+ libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
+ intrinsics::abort();
+ }
+}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+#[lang = "add"]
+trait Add<RHS = Self> {
+ type Output;
+
+ fn add(self, rhs: RHS) -> Self::Output;
+}
+
+impl Add for u8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i8 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for i32 {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for usize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+impl Add for isize {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self {
+ self + rhs
+ }
+}
+
+#[lang = "sub"]
+pub trait Sub<RHS = Self> {
+ type Output;
+
+ fn sub(self, rhs: RHS) -> Self::Output;
+}
+
+impl Sub for usize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for isize {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for u8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i8 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+impl Sub for i16 {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self {
+ self - rhs
+ }
+}
+
+
+/*
+ * Code
+ */
+
+static mut ONE: usize = 1;
+
+fn make_array() -> [u8; 3] {
+ [42, 10, 5]
+}
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+ unsafe {
+ let ptr = ONE as *mut usize;
+ let value = ptr as usize;
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, value);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
new file mode 100644
index 000000000..6fa10dca0
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs
@@ -0,0 +1,72 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 10
+// 10
+// 42
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+#[lang = "copy"]
+pub unsafe trait Copy {}
+
+unsafe impl Copy for bool {}
+unsafe impl Copy for u8 {}
+unsafe impl Copy for u16 {}
+unsafe impl Copy for u32 {}
+unsafe impl Copy for u64 {}
+unsafe impl Copy for usize {}
+unsafe impl Copy for i8 {}
+unsafe impl Copy for i16 {}
+unsafe impl Copy for i32 {}
+unsafe impl Copy for isize {}
+unsafe impl Copy for f32 {}
+unsafe impl Copy for char {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ }
+}
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+/*
+ * Code
+ */
+
+fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) {
+ (
+ a as u8, a as u16, a as u32, a as usize, a as i8, a as i16, a as i32, a as isize, b as u8,
+ b as u32,
+ )
+}
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+ let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
+ unsafe {
+ libc::printf(b"%d\n\0" as *const u8 as *const i8, c);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, d);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, j);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs
new file mode 100644
index 000000000..ad9258ed0
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs
@@ -0,0 +1,128 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 5
+
+#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+impl Copy for usize {}
+impl Copy for i32 {}
+impl Copy for u32 {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ }
+}
+
+#[lang = "index"]
+pub trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> Index<usize> for [T; 3] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+impl<T> Index<usize> for [T] {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self[index]
+ }
+}
+
+#[lang = "unsize"]
+pub trait Unsize<T: ?Sized> {}
+
+#[lang = "coerce_unsized"]
+pub trait CoerceUnsized<T> {}
+
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+#[lang = "panic_location"]
+struct PanicLocation {
+ file: &'static str,
+ line: u32,
+ column: u32,
+}
+
+#[lang = "panic_bounds_check"]
+#[track_caller]
+#[no_mangle]
+fn panic_bounds_check(index: usize, len: usize) -> ! {
+ unsafe {
+ libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
+ intrinsics::abort();
+ }
+}
+
+mod intrinsics {
+ use super::Sized;
+
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+/*
+ * Code
+ */
+
+static mut TWO: usize = 2;
+
+fn index_slice(s: &[u32]) -> u32 {
+ unsafe {
+ s[TWO]
+ }
+}
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ let array = [42, 7, 5];
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array));
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs
new file mode 100644
index 000000000..294add968
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/static.rs
@@ -0,0 +1,112 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 10
+// 14
+// 1
+// 12
+// 12
+// 1
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "destruct"]
+pub trait Destruct {}
+
+#[lang = "drop"]
+pub trait Drop {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod intrinsics {
+ use super::Sized;
+
+ extern "rust-intrinsic" {
+ pub fn abort() -> !;
+ }
+}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ }
+}
+
+#[lang = "structural_peq"]
+pub trait StructuralPartialEq {}
+
+#[lang = "structural_teq"]
+pub trait StructuralEq {}
+
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ drop_in_place(to_drop);
+}
+
+/*
+ * Code
+ */
+
+struct Test {
+ field: isize,
+}
+
+struct WithRef {
+ refe: &'static Test,
+}
+
+static mut CONSTANT: isize = 10;
+
+static mut TEST: Test = Test {
+ field: 12,
+};
+
+static mut TEST2: Test = Test {
+ field: 14,
+};
+
+static mut WITH_REF: WithRef = WithRef {
+ refe: unsafe { &TEST },
+};
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);
+ TEST2.field = argc;
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, WITH_REF.refe.field);
+ WITH_REF.refe = &TEST2;
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST.field);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, WITH_REF.refe.field);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs
new file mode 100644
index 000000000..6c8884855
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs
@@ -0,0 +1,70 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 1
+// 2
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ }
+}
+
+/*
+ * Code
+ */
+
+struct Test {
+ field: isize,
+}
+
+struct Two {
+ two: isize,
+}
+
+fn one() -> isize {
+ 1
+}
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ let test = Test {
+ field: one(),
+ };
+ let two = Two {
+ two: 2,
+ };
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two);
+ }
+ 0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/tuple.rs b/compiler/rustc_codegen_gcc/tests/run/tuple.rs
new file mode 100644
index 000000000..0b670bf26
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/tuple.rs
@@ -0,0 +1,51 @@
+// Compiler:
+//
+// Run-time:
+// status: 0
+// stdout: 3
+
+#![feature(auto_traits, lang_items, no_core, start, intrinsics)]
+
+#![no_std]
+#![no_core]
+
+/*
+ * Core
+ */
+
+// Because we don't have core yet.
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {
+}
+
+impl Copy for isize {}
+
+#[lang = "receiver"]
+trait Receiver {
+}
+
+#[lang = "freeze"]
+pub(crate) unsafe auto trait Freeze {}
+
+mod libc {
+ #[link(name = "c")]
+ extern "C" {
+ pub fn printf(format: *const i8, ...) -> i32;
+ }
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(mut argc: isize, _argv: *const *const u8) -> isize {
+ let test: (isize, isize, isize) = (3, 1, 4);
+ unsafe {
+ libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0);
+ }
+ 0
+}