diff options
Diffstat (limited to 'tests/run-make/raw-dylib-alt-calling-convention')
6 files changed, 378 insertions, 0 deletions
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/Makefile b/tests/run-make/raw-dylib-alt-calling-convention/Makefile new file mode 100644 index 000000000..03f8778d2 --- /dev/null +++ b/tests/run-make/raw-dylib-alt-calling-convention/Makefile @@ -0,0 +1,32 @@ +# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions. + +# only-x86 +# only-windows + +include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs + $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)" + $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c) +ifdef IS_MSVC + $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib +else + $(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll +endif + + "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.txt output.txt +else + $(DIFF) output.txt "$(TMPDIR)"/output.txt +endif + +ifdef IS_MSVC + "$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.msvc.txt output.msvc.txt +else + $(DIFF) output.msvc.txt "$(TMPDIR)"/output.msvc.txt +endif +endif diff --git a/tests/run-make/raw-dylib-alt-calling-convention/driver.rs b/tests/run-make/raw-dylib-alt-calling-convention/driver.rs new file mode 100644 index 000000000..b7f372c6b --- /dev/null +++ b/tests/run-make/raw-dylib-alt-calling-convention/driver.rs @@ -0,0 +1,8 @@ +extern crate raw_dylib_alt_calling_convention_test; + +fn main() { + raw_dylib_alt_calling_convention_test::library_function( + std::env::args().skip(1).next().map_or( + false, + |s| std::str::FromStr::from_str(&s).unwrap())); +} diff --git a/tests/run-make/raw-dylib-alt-calling-convention/extern.c b/tests/run-make/raw-dylib-alt-calling-convention/extern.c new file mode 100644 index 000000000..344d4a6bf --- /dev/null +++ b/tests/run-make/raw-dylib-alt-calling-convention/extern.c @@ -0,0 +1,193 @@ +#include <stdio.h> +#include <stdint.h> + +struct S { + uint8_t x; + int32_t y; +}; + +struct S2 { + int32_t x; + uint8_t y; +}; + +struct S3 { + uint8_t x[5]; +}; + +__declspec(dllexport) void __stdcall stdcall_fn_1(int i) { + printf("stdcall_fn_1(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) { + printf("stdcall_fn_2(%d, %.1f)\n", i, f); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_3(double d) { + printf("stdcall_fn_3(%.1f)\n", d); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) { + printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) { + printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +// Test that stdcall support works correctly with the nullable pointer optimization. +__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) { + if (s) { + printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y); + } else { + printf("stdcall_fn_6(null)\n"); + } + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) { + printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +// Verify that we compute the correct amount of space in the argument list for a 5-byte struct. +__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) { + printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n", + s.x[0], s.x[1], s.x[2], s.x[3], s.x[4], + t.x[0], t.x[1], t.x[2], t.x[3], t.x[4] + ); + fflush(stdout); +} + +// test whether f64/double values are aligned on 4-byte or 8-byte boundaries. +__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) { + printf("stdcall_fn_9(%d, %.1f)\n", x, y); + fflush(stdout); +} + +__declspec(dllexport) void __stdcall stdcall_fn_10(int i) { + printf("stdcall_fn_10(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_1(int i) { + printf("fastcall_fn_1(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) { + printf("fastcall_fn_2(%d, %.1f)\n", i, f); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_3(double d) { + printf("fastcall_fn_3(%.1f)\n", d); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) { + printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) { + printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) { + if (s) { + printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y); + } else { + printf("fastcall_fn_6(null)\n"); + } + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) { + printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) { + printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n", + s.x[0], s.x[1], s.x[2], s.x[3], s.x[4], + t.x[0], t.x[1], t.x[2], t.x[3], t.x[4] + ); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) { + printf("fastcall_fn_9(%d, %.1f)\n", x, y); + fflush(stdout); +} + +__declspec(dllexport) void __fastcall fastcall_fn_10(int i) { + printf("fastcall_fn_10(%d)\n", i); + fflush(stdout); +} + +// GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 +#ifdef _MSC_VER +__declspec(dllexport) void __vectorcall vectorcall_fn_1(int i) { + printf("vectorcall_fn_1(%d)\n", i); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_2(uint8_t i, float f) { + printf("vectorcall_fn_2(%d, %.1f)\n", i, f); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_3(double d) { + printf("vectorcall_fn_3(%.1f)\n", d); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_4(uint8_t i, uint8_t j, float f) { + printf("vectorcall_fn_4(%d, %d, %.1f)\n", i, j, f); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_5(struct S s, int i) { + printf("vectorcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_6(struct S* s) { + if (s) { + printf("vectorcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y); + } else { + printf("vectorcall_fn_6(null)\n"); + } + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_7(struct S2 s, int i) { + printf("vectorcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_8(struct S3 s, struct S3 t) { + printf("vectorcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n", + s.x[0], s.x[1], s.x[2], s.x[3], s.x[4], + t.x[0], t.x[1], t.x[2], t.x[3], t.x[4] + ); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_9(uint8_t x, double y) { + printf("vectorcall_fn_9(%d, %.1f)\n", x, y); + fflush(stdout); +} + +__declspec(dllexport) void __vectorcall vectorcall_fn_10(int i) { + printf("vectorcall_fn_10(%d)\n", i); + fflush(stdout); +} +#endif diff --git a/tests/run-make/raw-dylib-alt-calling-convention/lib.rs b/tests/run-make/raw-dylib-alt-calling-convention/lib.rs new file mode 100644 index 000000000..22f222c12 --- /dev/null +++ b/tests/run-make/raw-dylib-alt-calling-convention/lib.rs @@ -0,0 +1,115 @@ +#![feature(abi_vectorcall)] +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[repr(C)] +#[derive(Clone)] +struct S { + x: u8, + y: i32, +} + +#[repr(C)] +#[derive(Clone)] +struct S2 { + x: i32, + y: u8, +} + +#[repr(C)] +#[derive(Clone)] +struct S3 { + x: [u8; 5], +} + +#[link(name = "extern", kind = "raw-dylib")] +extern "stdcall" { + fn stdcall_fn_1(i: i32); + fn stdcall_fn_2(c: u8, f: f32); + fn stdcall_fn_3(d: f64); + fn stdcall_fn_4(i: u8, j: u8, f: f32); + fn stdcall_fn_5(a: S, b: i32); + fn stdcall_fn_6(a: Option<&S>); + fn stdcall_fn_7(a: S2, b: i32); + fn stdcall_fn_8(a: S3, b: S3); + fn stdcall_fn_9(x: u8, y: f64); + #[link_name = "stdcall_fn_10"] + fn stdcall_fn_10_renamed(i: i32); +} + +#[link(name = "extern", kind = "raw-dylib")] +extern "fastcall" { + fn fastcall_fn_1(i: i32); + fn fastcall_fn_2(c: u8, f: f32); + fn fastcall_fn_3(d: f64); + fn fastcall_fn_4(i: u8, j: u8, f: f32); + fn fastcall_fn_5(a: S, b: i32); + fn fastcall_fn_6(a: Option<&S>); + fn fastcall_fn_7(a: S2, b: i32); + fn fastcall_fn_8(a: S3, b: S3); + fn fastcall_fn_9(x: u8, y: f64); + #[link_name = "fastcall_fn_10"] + fn fastcall_fn_10_renamed(i: i32); +} + +#[cfg(target_env = "msvc")] +#[link(name = "extern", kind = "raw-dylib")] +extern "vectorcall" { + fn vectorcall_fn_1(i: i32); + fn vectorcall_fn_2(c: u8, f: f32); + fn vectorcall_fn_3(d: f64); + fn vectorcall_fn_4(i: u8, j: u8, f: f32); + fn vectorcall_fn_5(a: S, b: i32); + fn vectorcall_fn_6(a: Option<&S>); + fn vectorcall_fn_7(a: S2, b: i32); + fn vectorcall_fn_8(a: S3, b: S3); + fn vectorcall_fn_9(x: u8, y: f64); + #[link_name = "vectorcall_fn_10"] + fn vectorcall_fn_10_renamed(i: i32); +} + +pub fn library_function(run_msvc_only: bool) { + unsafe { + if !run_msvc_only { + stdcall_fn_1(14); + stdcall_fn_2(16, 3.5); + stdcall_fn_3(3.5); + stdcall_fn_4(1, 2, 3.0); + stdcall_fn_5(S { x: 1, y: 2 }, 16); + stdcall_fn_6(Some(&S { x: 10, y: 12 })); + stdcall_fn_7(S2 { x: 15, y: 16 }, 3); + stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + stdcall_fn_9(1, 3.0); + stdcall_fn_10_renamed(19); + + fastcall_fn_1(14); + fastcall_fn_2(16, 3.5); + fastcall_fn_3(3.5); + fastcall_fn_4(1, 2, 3.0); + fastcall_fn_6(Some(&S { x: 10, y: 12 })); + fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + fastcall_fn_9(1, 3.0); + fastcall_fn_10_renamed(19); + } else { + // FIXME: 91167 + // rustc generates incorrect code for the calls to fastcall_fn_5 and fastcall_fn_7 + // on i686-pc-windows-gnu; disabling these until the indicated issue is fixed. + fastcall_fn_5(S { x: 1, y: 2 }, 16); + fastcall_fn_7(S2 { x: 15, y: 16 }, 3); + + // GCC doesn't support vectorcall: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 + #[cfg(target_env = "msvc")] + { + vectorcall_fn_1(14); + vectorcall_fn_2(16, 3.5); + vectorcall_fn_3(3.5); + vectorcall_fn_4(1, 2, 3.0); + vectorcall_fn_5(S { x: 1, y: 2 }, 16); + vectorcall_fn_6(Some(&S { x: 10, y: 12 })); + vectorcall_fn_7(S2 { x: 15, y: 16 }, 3); + vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }); + vectorcall_fn_9(1, 3.0); + vectorcall_fn_10_renamed(19); + } + } + } +} diff --git a/tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt b/tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt new file mode 100644 index 000000000..a216835c4 --- /dev/null +++ b/tests/run-make/raw-dylib-alt-calling-convention/output.msvc.txt @@ -0,0 +1,12 @@ +fastcall_fn_5(S { x: 1, y: 2 }, 16) +fastcall_fn_7(S2 { x: 15, y: 16 }, 3) +vectorcall_fn_1(14) +vectorcall_fn_2(16, 3.5) +vectorcall_fn_3(3.5) +vectorcall_fn_4(1, 2, 3.0) +vectorcall_fn_5(S { x: 1, y: 2 }, 16) +vectorcall_fn_6(S { x: 10, y: 12 }) +vectorcall_fn_7(S2 { x: 15, y: 16 }, 3) +vectorcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }) +vectorcall_fn_9(1, 3.0) +vectorcall_fn_10(19) diff --git a/tests/run-make/raw-dylib-alt-calling-convention/output.txt b/tests/run-make/raw-dylib-alt-calling-convention/output.txt new file mode 100644 index 000000000..7622d3161 --- /dev/null +++ b/tests/run-make/raw-dylib-alt-calling-convention/output.txt @@ -0,0 +1,18 @@ +stdcall_fn_1(14) +stdcall_fn_2(16, 3.5) +stdcall_fn_3(3.5) +stdcall_fn_4(1, 2, 3.0) +stdcall_fn_5(S { x: 1, y: 2 }, 16) +stdcall_fn_6(S { x: 10, y: 12 }) +stdcall_fn_7(S2 { x: 15, y: 16 }, 3) +stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }) +stdcall_fn_9(1, 3.0) +stdcall_fn_10(19) +fastcall_fn_1(14) +fastcall_fn_2(16, 3.5) +fastcall_fn_3(3.5) +fastcall_fn_4(1, 2, 3.0) +fastcall_fn_6(S { x: 10, y: 12 }) +fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] }) +fastcall_fn_9(1, 3.0) +fastcall_fn_10(19) |