]> git.lizzy.rs Git - rust.git/commitdiff
End-to-end regression test for 97463.
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Mon, 6 Jun 2022 16:39:58 +0000 (12:39 -0400)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Wed, 6 Jul 2022 14:53:28 +0000 (10:53 -0400)
incorporated review feedback, with comment explaining why this is calling CC
instead of COMPILE_OBJ or NATIVE_STATICLIB. As drive-by, removed some other
unnecessary commands from the recipe.

src/test/run-make-fulldeps/issue-97463-abi-param-passing/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/issue-97463-abi-param-passing/bad.c [new file with mode: 0644]
src/test/run-make-fulldeps/issue-97463-abi-param-passing/param_passing.rs [new file with mode: 0644]

diff --git a/src/test/run-make-fulldeps/issue-97463-abi-param-passing/Makefile b/src/test/run-make-fulldeps/issue-97463-abi-param-passing/Makefile
new file mode 100644 (file)
index 0000000..b3db6bc
--- /dev/null
@@ -0,0 +1,12 @@
+-include ../tools.mk
+
+# The issue exercised by this test, rust-lang/rust#97463, explicitly needs `-O`
+# flags (like `-O3`) to reproduce. Thus, we call $(CC) instead of nicer
+# alternatives provided by tools.mk like using `COMPILE_OBJ` or using a
+# `NATIVE_STATICLIB` dependency.
+
+all:
+       $(CC) -c -O3 -o $(TMPDIR)/bad.o bad.c
+       $(AR) rcs $(TMPDIR)/libbad.a $(TMPDIR)/bad.o
+       $(RUSTC) param_passing.rs -L$(TMPDIR) -lbad -C opt-level=3
+       $(call RUN,param_passing)
diff --git a/src/test/run-make-fulldeps/issue-97463-abi-param-passing/bad.c b/src/test/run-make-fulldeps/issue-97463-abi-param-passing/bad.c
new file mode 100644 (file)
index 0000000..013314a
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+
+
+struct bloc {
+    uint16_t a;
+    uint16_t b;
+    uint16_t c;
+};
+
+uint16_t c_read_value(uint32_t a, uint32_t b, uint32_t c) {
+    struct bloc *data = malloc(sizeof(struct bloc));
+
+    data->a = a & 0xFFFF;
+    data->b = b & 0xFFFF;
+    data->c = c & 0xFFFF;
+
+    printf("C struct: a = %u, b = %u, c = %u\n",
+        (unsigned) data->a, (unsigned) data->b, (unsigned) data->c);
+    printf("C function returns %u\n", (unsigned) data->b);
+
+    return data->b; /* leak data */
+}
diff --git a/src/test/run-make-fulldeps/issue-97463-abi-param-passing/param_passing.rs b/src/test/run-make-fulldeps/issue-97463-abi-param-passing/param_passing.rs
new file mode 100644 (file)
index 0000000..b4744a3
--- /dev/null
@@ -0,0 +1,38 @@
+// NOTE: Exposing the bug encoded in this test is sensitive to
+// LLVM optimization choices. See additional note below for an
+// example.
+
+#[link(name = "bad")]
+extern "C" {
+    pub fn c_read_value(a: u32, b: u32, c: u32) -> u16;
+}
+
+fn main() {
+    const C1: usize = 0x327b23c6;
+    const C2: usize = C1 & 0xFFFF;
+
+    let r1: usize = 0x0;
+    let r2: usize = C1;
+    let r3: usize = 0x0;
+    let value: u16 = unsafe { c_read_value(r1 as u32, r2 as u32, r3 as u32) };
+
+    // NOTE: as an example of the sensitivity of this test to optimization choices,
+    // uncommenting this block of code makes the bug go away on pnkfeix's machine.
+    // (But observing via `dbg!` doesn't hide the bug. At least sometimes.)
+    /*
+    println!("{}", value);
+    println!("{}", value as usize);
+    println!("{}", usize::from(value));
+    println!("{}", (value as usize) & 0xFFFF);
+     */
+
+    let d1 = value;
+    let d2 = value as usize;
+    let d3 = usize::from(value);
+    let d4 = (value as usize) & 0xFFFF;
+
+    let d = (&d1, &d2, &d3, &d4);
+    let d_ = (d1, d2, d3, d4);
+
+    assert_eq!(((&(C2 as u16), &C2, &C2, &C2), (C2 as u16, C2, C2, C2)), (d, d_));
+}