diff options
Diffstat (limited to 'tests/ui/abi/extern')
20 files changed, 521 insertions, 0 deletions
diff --git a/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs b/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs new file mode 100644 index 000000000..9c61518b9 --- /dev/null +++ b/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs @@ -0,0 +1,28 @@ +#![crate_name = "externcallback"] +#![crate_type = "lib"] +#![feature(rustc_private)] + +extern crate libc; + +pub mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +pub fn fact(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { fact(data - 1) * data } +} diff --git a/tests/ui/abi/extern/extern-call-deep.rs b/tests/ui/abi/extern/extern-call-deep.rs new file mode 100644 index 000000000..db5f2ca65 --- /dev/null +++ b/tests/ui/abi/extern/extern-call-deep.rs @@ -0,0 +1,36 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with +// ignore-emscripten blows the JS stack + +#![feature(rustc_private)] + +extern crate libc; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { count(data - 1) + 1 } +} + +fn count(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + let result = count(1000); + println!("result = {}", result); + assert_eq!(result, 1000); +} diff --git a/tests/ui/abi/extern/extern-call-deep2.rs b/tests/ui/abi/extern/extern-call-deep2.rs new file mode 100644 index 000000000..60e8db159 --- /dev/null +++ b/tests/ui/abi/extern/extern-call-deep2.rs @@ -0,0 +1,41 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +#![feature(rustc_private)] + +extern crate libc; +use std::thread; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { count(data - 1) + 1 } +} + +fn count(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + // Make sure we're on a thread with small Rust stacks (main currently + // has a large stack) + thread::spawn(move || { + let result = count(1000); + println!("result = {}", result); + assert_eq!(result, 1000); + }) + .join(); +} diff --git a/tests/ui/abi/extern/extern-call-direct.rs b/tests/ui/abi/extern/extern-call-direct.rs new file mode 100644 index 000000000..19b901d49 --- /dev/null +++ b/tests/ui/abi/extern/extern-call-direct.rs @@ -0,0 +1,10 @@ +// run-pass +// Test direct calls to extern fns. + + +extern "C" fn f(x: usize) -> usize { x * 2 } + +pub fn main() { + let x = f(22); + assert_eq!(x, 44); +} diff --git a/tests/ui/abi/extern/extern-call-indirect.rs b/tests/ui/abi/extern/extern-call-indirect.rs new file mode 100644 index 000000000..886e8f6be --- /dev/null +++ b/tests/ui/abi/extern/extern-call-indirect.rs @@ -0,0 +1,35 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate libc; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { fact(data - 1) * data } +} + +fn fact(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + let result = fact(10); + println!("result = {}", result); + assert_eq!(result, 3628800); +} diff --git a/tests/ui/abi/extern/extern-call-scrub.rs b/tests/ui/abi/extern/extern-call-scrub.rs new file mode 100644 index 000000000..ff33cf31a --- /dev/null +++ b/tests/ui/abi/extern/extern-call-scrub.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(unused_must_use)] +// This time we're testing repeatedly going up and down both stacks to +// make sure the stack pointers are maintained properly in both +// directions + +// ignore-emscripten no threads support +#![feature(rustc_private)] + +extern crate libc; +use std::thread; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { count(data - 1) + count(data - 1) } +} + +fn count(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + // Make sure we're on a thread with small Rust stacks (main currently + // has a large stack) + thread::spawn(move || { + let result = count(12); + println!("result = {}", result); + assert_eq!(result, 2048); + }) + .join(); +} diff --git a/tests/ui/abi/extern/extern-crosscrate.rs b/tests/ui/abi/extern/extern-crosscrate.rs new file mode 100644 index 000000000..123ce20ca --- /dev/null +++ b/tests/ui/abi/extern/extern-crosscrate.rs @@ -0,0 +1,21 @@ +// run-pass +// aux-build:extern-crosscrate-source.rs +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate externcallback; +extern crate libc; + +fn fact(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + externcallback::rustrt::rust_dbg_call(externcallback::cb, n) + } +} + +pub fn main() { + let result = fact(10); + println!("result = {}", result); + assert_eq!(result, 3628800); +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU16s.rs b/tests/ui/abi/extern/extern-pass-TwoU16s.rs new file mode 100644 index 000000000..cff25511c --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU16s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU16s { + one: u16, + two: u16, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; +} + +pub fn main() { + unsafe { + let x = TwoU16s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU16s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU32s.rs b/tests/ui/abi/extern/extern-pass-TwoU32s.rs new file mode 100644 index 000000000..03a8ecf24 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU32s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU32s { + one: u32, + two: u32, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; +} + +pub fn main() { + unsafe { + let x = TwoU32s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU32s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU64s.rs b/tests/ui/abi/extern/extern-pass-TwoU64s.rs new file mode 100644 index 000000000..8bbc987c8 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU64s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU64s { + one: u64, + two: u64, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s; +} + +pub fn main() { + unsafe { + let x = TwoU64s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU64s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU8s.rs b/tests/ui/abi/extern/extern-pass-TwoU8s.rs new file mode 100644 index 000000000..55a53c250 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU8s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU8s { + one: u8, + two: u8, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; +} + +pub fn main() { + unsafe { + let x = TwoU8s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU8s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-char.rs b/tests/ui/abi/extern/extern-pass-char.rs new file mode 100644 index 000000000..2b10d26d1 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-char.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +// Test a function that takes/returns a u8. + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u8(v: u8) -> u8; +} + +pub fn main() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u8(22)); + } +} diff --git a/tests/ui/abi/extern/extern-pass-double.rs b/tests/ui/abi/extern/extern-pass-double.rs new file mode 100644 index 000000000..0b556c99e --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-double.rs @@ -0,0 +1,13 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_double(v: f64) -> f64; +} + +pub fn main() { + unsafe { + assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64)); + } +} diff --git a/tests/ui/abi/extern/extern-pass-empty.rs b/tests/ui/abi/extern/extern-pass-empty.rs new file mode 100644 index 000000000..ee974f6db --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-empty.rs @@ -0,0 +1,55 @@ +// run-pass +#![allow(improper_ctypes)] // FIXME: this test is inherently not FFI-safe. + +// Test a foreign function that accepts empty struct. + +// pretty-expanded FIXME #23616 +// ignore-msvc +// ignore-emscripten emcc asserts on an empty struct as an argument + +#[repr(C)] +struct TwoU8s { + one: u8, + two: u8, +} + +#[repr(C)] +struct ManyInts { + arg1: i8, + arg2: i16, + arg3: i32, + arg4: i16, + arg5: i8, + arg6: TwoU8s, +} + +#[repr(C)] +struct Empty; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts); +} + +pub fn main() { + unsafe { + let x = ManyInts { + arg1: 2, + arg2: 3, + arg3: 4, + arg4: 5, + arg5: 6, + arg6: TwoU8s { one: 7, two: 8 }, + }; + let y = ManyInts { + arg1: 1, + arg2: 2, + arg3: 3, + arg4: 4, + arg5: 5, + arg6: TwoU8s { one: 6, two: 7 }, + }; + let empty = Empty; + rust_dbg_extern_empty_struct(x, empty, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-u32.rs b/tests/ui/abi/extern/extern-pass-u32.rs new file mode 100644 index 000000000..c9b8d52cf --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-u32.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +// Test a function that takes/returns a u32. + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; +} + +pub fn main() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u32(22)); + } +} diff --git a/tests/ui/abi/extern/extern-pass-u64.rs b/tests/ui/abi/extern/extern-pass-u64.rs new file mode 100644 index 000000000..5103129ab --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-u64.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +// Test a call to a function that takes/returns a u64. + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; +} + +pub fn main() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u64(22)); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU16s.rs b/tests/ui/abi/extern/extern-return-TwoU16s.rs new file mode 100644 index 000000000..2551c93a7 --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU16s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU16s { + one: u16, + two: u16, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU16s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU32s.rs b/tests/ui/abi/extern/extern-return-TwoU32s.rs new file mode 100644 index 000000000..70a42895d --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU32s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU32s { + one: u32, + two: u32, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU32s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU64s.rs b/tests/ui/abi/extern/extern-return-TwoU64s.rs new file mode 100644 index 000000000..dd264fb9c --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU64s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU64s { + one: u64, + two: u64, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU64s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU8s.rs b/tests/ui/abi/extern/extern-return-TwoU8s.rs new file mode 100644 index 000000000..b60387aed --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU8s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU8s { + one: u8, + two: u8, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU8s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} |