From 95f7416decca57ba9b80481aade905371636bbf9 Mon Sep 17 00:00:00 2001 From: ricci009 Date: Sat, 25 Jan 2025 12:15:04 -0500 Subject: [PATCH 01/13] modified minicore.rs and implemented core-ffi-typecheck-clang rmake test --- tests/auxiliary/minicore.rs | 125 +++++++++++++ .../core-ffi-typecheck-clang/rmake.rs | 164 ++++++++++++++++++ .../core-ffi-typecheck-clang/tests.rs | 93 ++++++++++ 3 files changed, 382 insertions(+) create mode 100644 tests/run-make/core-ffi-typecheck-clang/rmake.rs create mode 100644 tests/run-make/core-ffi-typecheck-clang/tests.rs diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index a68552175c318..e60411fa12c3b 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -17,6 +17,7 @@ #![feature(no_core, lang_items, rustc_attrs, decl_macro, naked_functions, f16, f128)] #![allow(unused, improper_ctypes_definitions, internal_features)] #![feature(asm_experimental_arch)] +#![feature(intrinsics)] #![no_std] #![no_core] @@ -108,3 +109,127 @@ macro_rules! stringify { /* compiler built-in */ }; } + +macro_rules! cfg_if { + // match if/else chains with a final `else` + ( + $( + if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* } + ) else+ + else { $( $e_tokens:tt )* } + ) => { + cfg_if! { + @__items () ; + $( + (( $i_meta ) ( $( $i_tokens )* )) , + )+ + (() ( $( $e_tokens )* )) , + } + }; + + // Internal and recursive macro to emit all the items + // + // Collects all the previous cfgs in a list at the beginning, so they can be + // negated. After the semicolon is all the remaining items. + (@__items ( $( $_:meta , )* ) ; ) => {}; + ( + @__items ( $( $no:meta , )* ) ; + (( $( $yes:meta )? ) ( $( $tokens:tt )* )) , + $( $rest:tt , )* + ) => { + // Emit all items within one block, applying an appropriate #[cfg]. The + // #[cfg] will require all `$yes` matchers specified and must also negate + // all previous matchers. + #[cfg(all( + $( $yes , )? + not(any( $( $no ),* )) + ))] + cfg_if! { @__identity $( $tokens )* } + + // Recurse to emit all other items in `$rest`, and when we do so add all + // our `$yes` matchers to the list of `$no` matchers as future emissions + // will have to negate everything we just matched as well. + cfg_if! { + @__items ( $( $no , )* $( $yes , )? ) ; + $( $rest , )* + } + }; + + // Internal macro to make __apply work out right for different match types, + // because of how macros match/expand stuff. + (@__identity $( $tokens:tt )* ) => { + $( $tokens )* + }; +} + +#[macro_export] +macro_rules! panic { + ($msg:literal) => { + $crate::panic(&$msg) + }; +} + +#[rustc_intrinsic] +#[rustc_intrinsic_const_stable_indirect] +#[rustc_intrinsic_must_be_overridden] +pub const fn size_of() -> usize { + loop {} +} + +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +pub const fn abort() -> ! { + loop {} +} + +#[lang = "panic"] +#[rustc_const_panic_str] +const fn panic(_expr: &&'static str) -> ! { + abort(); +} + +#[lang = "eq"] +pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +impl PartialEq for usize { + fn eq(&self, other: &usize) -> bool { + (*self) == (*other) + } +} + +impl PartialEq for bool { + fn eq(&self, other: &bool) -> bool { + (*self) == (*other) + } +} + +#[lang = "bitxor"] +pub trait BitXor { + type Output; + fn bitxor(self, rhs: Rhs) -> Self::Output; +} + +impl BitXor for bool { + type Output = bool; + fn bitxor(self, rhs: bool) -> bool { + (self || rhs) && !(self && rhs) + } +} + +#[lang = "not"] +pub trait Not { + type Output; + fn not(self) -> Self::Output; +} + +impl Not for bool { + type Output = bool; + fn not(self) -> Self { + !self + } +} diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs new file mode 100644 index 0000000000000..7b6240de5f849 --- /dev/null +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -0,0 +1,164 @@ +//@ needs-force-clang-based-tests + +use run_make_support::{clang, regex, rfs, rustc}; + +const SKIPPED_TARGETS: &[&str] = &[ + "riscv", //error: unknown target triple 'riscv32e-unknown-none-elf' + "wasm", //error: unknown target triple 'wasm32v1-none' + "xtensa", //error: unknown target triple 'xtensa-esp32-espidf' +]; + +fn main() { + let targets = get_target_list(); + + let minicore_path = run_make_support::source_root().join("tests/auxiliary/minicore.rs"); + + regex_mod(); + + for target in targets.lines() { + if SKIPPED_TARGETS.iter().any(|prefix| target.starts_with(prefix)) { + continue; + } + + let clang_output = + clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", target]).run(); + + let defines = String::from_utf8(clang_output.stdout()).expect("Invalid UTF-8"); + + let minicore_content = rfs::read_to_string(&minicore_path); + let mut rmake_content = format!( + r#" + #![no_std] + #![no_core] + #![feature(link_cfg)] + #![allow(unused)] + #![crate_type = "rlib"] + {} + #[path = "processed_mod.rs"] + mod ffi; + #[path = "tests.rs"] + mod tests; + "#, + minicore_content + ); + + rmake_content.push_str(&format!( + " + const CLANG_C_CHAR_SIZE: usize = {}; + const CLANG_C_CHAR_SIGNED: bool = {}; + const CLANG_C_SHORT_SIZE: usize = {}; + const CLANG_C_INT_SIZE: usize = {}; + const CLANG_C_LONG_SIZE: usize = {}; + const CLANG_C_LONGLONG_SIZE: usize = {}; + const CLANG_C_FLOAT_SIZE: usize = {}; + const CLANG_C_DOUBLE_SIZE: usize = {}; + ", + parse_size(&defines, "CHAR"), + parse_signed(&defines, "CHAR"), + parse_size(&defines, "SHORT"), + parse_size(&defines, "INT"), + parse_size(&defines, "LONG"), + parse_size(&defines, "LONG_LONG"), + parse_size(&defines, "FLOAT"), + parse_size(&defines, "DOUBLE"), + )); + + // Write to target-specific rmake file + let mut file_name = format!("{}_rmake.rs", target.replace("-", "_")); + + if target.starts_with("thumbv8m") { + file_name = String::from("thumbv8m_rmake.rs"); + } + + rfs::create_file(&file_name); + rfs::write(&file_name, rmake_content); + let rustc_output = rustc() + .arg("-Zunstable-options") + .arg("--emit=metadata") + .arg("--target") + .arg(target) + .arg(&file_name) + .run(); + rfs::remove_file(&file_name); + if !rustc_output.status().success() { + panic!("Failed for target {}", target); + } + } + + // Cleanup + rfs::remove_file("processed_mod.rs"); +} + +fn get_target_list() -> String { + let completed_process = rustc().arg("--print").arg("target-list").run(); + String::from_utf8(completed_process.stdout()).expect("error not a string") +} + +// Helper to parse size from clang defines +fn parse_size(defines: &str, type_name: &str) -> usize { + let search_pattern = format!("__SIZEOF_{}__ ", type_name.to_uppercase()); + for line in defines.lines() { + if line.contains(&search_pattern) { + if let Some(size_str) = line.split_whitespace().last() { + return size_str.parse().unwrap_or(0); + } + } + } + + // Only allow CHAR to default to 1 + if type_name.to_uppercase() == "CHAR" { + return 1; + } + + panic!("Could not find size definition for type: {}", type_name); +} + +// Helper to parse signedness from clang defines +fn parse_signed(defines: &str, type_name: &str) -> bool { + match type_name.to_uppercase().as_str() { + "CHAR" => { + // Check if char is explicitly unsigned + !defines.lines().any(|line| line.contains("__CHAR_UNSIGNED__")) + } + _ => true, + } +} + +// Parse core/ffi/mod.rs to retrieve only necessary macros and type defines +fn regex_mod() { + let mod_path = run_make_support::source_root().join("library/core/src/ffi/mod.rs"); + let mut content = rfs::read_to_string(&mod_path); + + //remove stability features #![unstable] + let mut re = regex::Regex::new(r"#!?\[(un)?stable[^]]*?\]").unwrap(); + content = re.replace_all(&content, "").to_string(); + + //remove doc features #[doc...] + re = regex::Regex::new(r"#\[doc[^]]*?\]").unwrap(); + content = re.replace_all(&content, "").to_string(); + + //remove lang feature #[lang...] + re = regex::Regex::new(r"#\[lang[^]]*?\]").unwrap(); + content = re.replace_all(&content, "").to_string(); + + //remove non inline modules + re = regex::Regex::new(r".*mod.*;").unwrap(); + content = re.replace_all(&content, "").to_string(); + + //remove use + re = regex::Regex::new(r".*use.*;").unwrap(); + content = re.replace_all(&content, "").to_string(); + + //remove fn fmt {...} + re = regex::Regex::new(r"(?s)fn fmt.*?\{.*?\}").unwrap(); + content = re.replace_all(&content, "").to_string(); + + //rmv impl fmt {...} + re = regex::Regex::new(r"(?s)impl fmt::Debug for.*?\{.*?\}").unwrap(); + content = re.replace_all(&content, "").to_string(); + + let file_name = format!("processed_mod.rs"); + + rfs::create_file(&file_name); + rfs::write(&file_name, content); +} diff --git a/tests/run-make/core-ffi-typecheck-clang/tests.rs b/tests/run-make/core-ffi-typecheck-clang/tests.rs new file mode 100644 index 0000000000000..10577f02f7a3a --- /dev/null +++ b/tests/run-make/core-ffi-typecheck-clang/tests.rs @@ -0,0 +1,93 @@ +// tests.rs + +use super::*; // `super` will include everything from `smallcore` once glued together + +cfg_if! { + if #[cfg(all(target_arch = "aarch64", target_abi = "ilp32"))] { + // FIXME: long is not long enough on aarch64 ilp32, should be 8, defaulting to 4 + const XFAIL_C_LONG_SIZE: usize = 4; + pub const TEST_C_LONG_SIZE: () = if size_of::() != XFAIL_C_LONG_SIZE { + panic!("wrong c_long size test ilp32"); + }; + } + else { + // Default test + pub const TEST_C_LONG_SIZE: () = if size_of::() != CLANG_C_LONG_SIZE { + panic!("wrong c_long size"); + }; + } +} + +cfg_if! { + if #[cfg(target_arch = "csky")] { + // FIXME: c_char signedness misallignment on csky, should be signed on CLANG + const XFAIL_C_CHAR_SIGNED: bool = false; + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED ^ XFAIL_C_CHAR_SIGNED { + panic!("mismatched c_char signed, target_arch: csky"); + }; + } + else if #[cfg(target_arch = "msp430")] { + // FIXME: c_char signedness misallignment on msp430, should be signed on CLANG + const XFAIL_C_CHAR_SIGNED: bool = false; // Change to true for darwin + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED ^ XFAIL_C_CHAR_SIGNED { + panic!("mismatched c_char signed, target_arch: msp430"); + }; + } + else { + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED ^ CLANG_C_CHAR_SIGNED { + panic!("mismatched c_char sign"); + }; + } +} + +cfg_if! { + if #[cfg(target_arch = "avr")] { + // FIXME: double is not short enough on avr-unknown-gnu-atmega328 (should be 4 bytes) + const XFAIL_C_DOUBLE_SIZE: usize = 8; + pub const TEST_C_DOUBLE_SIZE: () = if size_of::() != XFAIL_C_DOUBLE_SIZE { + panic!("wrong c_double size, target_arch: avr"); + }; + } + else { + pub const TEST_C_DOUBLE_SIZE: () = if size_of::() != CLANG_C_DOUBLE_SIZE { + panic!("wrong c_double size"); + }; + } +} + +trait Signed { + const SIGNED: bool; +} + +impl Signed for i8 { + const SIGNED: bool = true; +} + +impl Signed for u8 { + const SIGNED: bool = false; +} + +//c_char size +pub const TEST_C_CHAR_SIZE: () = if size_of::() != CLANG_C_CHAR_SIZE { + panic!("wrong c_char size"); +}; + +//c_int size +pub const TEST_C_INT_SIZE: () = if size_of::() != CLANG_C_INT_SIZE { + panic!("mismatched c_int size"); +}; + +//c_short size +pub const TEST_C_SHORT_SIZE: () = if size_of::() != CLANG_C_SHORT_SIZE { + panic!("wrong c_short size"); +}; + +//c_longlong size +pub const TEST_C_LONGLONG_SIZE: () = if size_of::() != CLANG_C_LONGLONG_SIZE { + panic!("wrong c_longlong size"); +}; + +//c_float size +pub const TEST_C_FLOAT_SIZE: () = if size_of::() != CLANG_C_FLOAT_SIZE { + panic!("wrong c_float size"); +}; From 4b8291f36a89d57a6715b05df78d0348d6ff130c Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 16:05:52 -0500 Subject: [PATCH 02/13] styling fixes, skipped_targets clearly defined, bitXor removed, clang status check --- tests/auxiliary/minicore.rs | 120 ++++++++---------- .../core-ffi-typecheck-clang/rmake.rs | 95 ++++++++++---- .../core-ffi-typecheck-clang/tests.rs | 24 ++-- 3 files changed, 138 insertions(+), 101 deletions(-) diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index e60411fa12c3b..663c0abaae80c 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -21,6 +21,60 @@ #![no_std] #![no_core] +/// Vendored from the 'cfg_if' crate + +macro_rules! cfg_if { + // match if/else chains with a final `else` + ( + $( + if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* } + ) else+ + else { $( $e_tokens:tt )* } + ) => { + cfg_if! { + @__items () ; + $( + (( $i_meta ) ( $( $i_tokens )* )) , + )+ + (() ( $( $e_tokens )* )) , + } + }; + + // Internal and recursive macro to emit all the items + // + // Collects all the previous cfgs in a list at the beginning, so they can be + // negated. After the semicolon is all the remaining items. + (@__items ( $( $_:meta , )* ) ; ) => {}; + ( + @__items ( $( $no:meta , )* ) ; + (( $( $yes:meta )? ) ( $( $tokens:tt )* )) , + $( $rest:tt , )* + ) => { + // Emit all items within one block, applying an appropriate #[cfg]. The + // #[cfg] will require all `$yes` matchers specified and must also negate + // all previous matchers. + #[cfg(all( + $( $yes , )? + not(any( $( $no ),* )) + ))] + cfg_if! { @__identity $( $tokens )* } + + // Recurse to emit all other items in `$rest`, and when we do so add all + // our `$yes` matchers to the list of `$no` matchers as future emissions + // will have to negate everything we just matched as well. + cfg_if! { + @__items ( $( $no , )* $( $yes , )? ) ; + $( $rest , )* + } + }; + + // Internal macro to make __apply work out right for different match types, + // because of how macros match/expand stuff. + (@__identity $( $tokens:tt )* ) => { + $( $tokens )* + }; +} + // `core` has some exotic `marker_impls!` macro for handling the with-generics cases, but for our // purposes, just use a simple macro_rules macro. macro_rules! impl_marker_trait { @@ -102,6 +156,7 @@ macro_rules! concat { /* compiler built-in */ }; } + #[rustc_builtin_macro] #[macro_export] macro_rules! stringify { @@ -110,58 +165,6 @@ macro_rules! stringify { }; } -macro_rules! cfg_if { - // match if/else chains with a final `else` - ( - $( - if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* } - ) else+ - else { $( $e_tokens:tt )* } - ) => { - cfg_if! { - @__items () ; - $( - (( $i_meta ) ( $( $i_tokens )* )) , - )+ - (() ( $( $e_tokens )* )) , - } - }; - - // Internal and recursive macro to emit all the items - // - // Collects all the previous cfgs in a list at the beginning, so they can be - // negated. After the semicolon is all the remaining items. - (@__items ( $( $_:meta , )* ) ; ) => {}; - ( - @__items ( $( $no:meta , )* ) ; - (( $( $yes:meta )? ) ( $( $tokens:tt )* )) , - $( $rest:tt , )* - ) => { - // Emit all items within one block, applying an appropriate #[cfg]. The - // #[cfg] will require all `$yes` matchers specified and must also negate - // all previous matchers. - #[cfg(all( - $( $yes , )? - not(any( $( $no ),* )) - ))] - cfg_if! { @__identity $( $tokens )* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$yes` matchers to the list of `$no` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { - @__items ( $( $no , )* $( $yes , )? ) ; - $( $rest , )* - } - }; - - // Internal macro to make __apply work out right for different match types, - // because of how macros match/expand stuff. - (@__identity $( $tokens:tt )* ) => { - $( $tokens )* - }; -} - #[macro_export] macro_rules! panic { ($msg:literal) => { @@ -208,19 +211,6 @@ impl PartialEq for bool { } } -#[lang = "bitxor"] -pub trait BitXor { - type Output; - fn bitxor(self, rhs: Rhs) -> Self::Output; -} - -impl BitXor for bool { - type Output = bool; - fn bitxor(self, rhs: bool) -> bool { - (self || rhs) && !(self && rhs) - } -} - #[lang = "not"] pub trait Not { type Output; diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 7b6240de5f849..a70ca144564a1 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -1,11 +1,52 @@ //@ needs-force-clang-based-tests +// This test checks that the clang defines for each target allign with the core ffi types defined in +// mod.rs. Therefore each rust target is queried and the clang defines for each target are read and +// compared to the core sizes to verify all types and sizes allign at buildtime. +// +// If this test fails because Rust adds a target that Clang does not support, this target should be +// added to SKIPPED_TARGETS. use run_make_support::{clang, regex, rfs, rustc}; +// It is not possible to run the Rust test-suite on these targets. const SKIPPED_TARGETS: &[&str] = &[ - "riscv", //error: unknown target triple 'riscv32e-unknown-none-elf' - "wasm", //error: unknown target triple 'wasm32v1-none' - "xtensa", //error: unknown target triple 'xtensa-esp32-espidf' + "riscv32gc-unknown-linux-gnu", + "riscv32gc-unknown-linux-musl", + "riscv32im-risc0-zkvm-elf", + "riscv32imac-esp-espidf", + "riscv32imafc-esp-espidf", + "riscv32imafc-unknown-nuttx-elf", + "riscv32imc-esp-espidf", + "riscv32imac-unknown-nuttx-elf", + "riscv32imac-unknown-xous-elf", + "riscv32imc-unknown-nuttx-elf", + "riscv32e-unknown-none-elf", + "riscv32em-unknown-none-elf", + "riscv32emc-unknown-none-elf", + "riscv32i-unknown-none-elf", + "riscv32im-unknown-none-elf", + "riscv32imc-unknown-none-elf", + "riscv32ima-unknown-none-elf", + "riscv32imac-unknown-none-elf", + "riscv32imafc-unknown-none-elf", + "riscv64gc-unknown-freebsd", + "riscv64gc-unknown-fuchsia", + "riscv64gc-unknown-hermit", + "riscv64gc-unknown-linux-gnu", + "riscv64gc-unknown-linux-musl", + "riscv64gc-unknown-netbsd", + "riscv64gc-unknown-none-elf", + "riscv64gc-unknown-nuttx-elf", + "riscv64gc-unknown-openbsd", + "riscv64imac-unknown-none-elf", + "riscv64imac-unknown-nuttx-elf", + "wasm32v1-none", + "xtensa-esp32-espidf", + "xtensa-esp32-none-elf", + "xtensa-esp32s2-espidf", + "xtensa-esp32s2-none-elf", + "xtensa-esp32s3-espidf", + "xtensa-esp32s3-none-elf", ]; fn main() { @@ -16,13 +57,18 @@ fn main() { regex_mod(); for target in targets.lines() { - if SKIPPED_TARGETS.iter().any(|prefix| target.starts_with(prefix)) { + if SKIPPED_TARGETS.iter().any(|&to_skip_target| target == to_skip_target) { continue; } + // Run Clang's preprocessor for the relevant target, printing default macro definitions. let clang_output = clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", target]).run(); + if !clang_output.status().success() { + continue; + } + let defines = String::from_utf8(clang_output.stdout()).expect("Invalid UTF-8"); let minicore_content = rfs::read_to_string(&minicore_path); @@ -33,13 +79,16 @@ fn main() { #![feature(link_cfg)] #![allow(unused)] #![crate_type = "rlib"] - {} + + /* begin minicore content */ + {minicore_content} + /* end minicore content */ + #[path = "processed_mod.rs"] mod ffi; #[path = "tests.rs"] mod tests; - "#, - minicore_content + "# ); rmake_content.push_str(&format!( @@ -54,7 +103,7 @@ fn main() { const CLANG_C_DOUBLE_SIZE: usize = {}; ", parse_size(&defines, "CHAR"), - parse_signed(&defines, "CHAR"), + char_is_signed(&defines), parse_size(&defines, "SHORT"), parse_size(&defines, "INT"), parse_size(&defines, "LONG"), @@ -63,20 +112,20 @@ fn main() { parse_size(&defines, "DOUBLE"), )); - // Write to target-specific rmake file - let mut file_name = format!("{}_rmake.rs", target.replace("-", "_")); + // Generate a target-specific rmake file. + // If type misalignments occur, use the generated rmake file name to identify the failing target. + // Replace dots (.) and hyphens (-) in the target name with underscores to ensure valid filenames. + let file_name = format!("{}_rmake.rs", target.replace("-", "_").replace(".", "_")); - if target.starts_with("thumbv8m") { - file_name = String::from("thumbv8m_rmake.rs"); - } - - rfs::create_file(&file_name); + // Attempt to build the test file for the relevant target. Tests use constant evaluation, + // so running is not necessary. rfs::write(&file_name, rmake_content); let rustc_output = rustc() .arg("-Zunstable-options") .arg("--emit=metadata") .arg("--target") .arg(target) + .arg("-o-") .arg(&file_name) .run(); rfs::remove_file(&file_name); @@ -89,6 +138,7 @@ fn main() { rfs::remove_file("processed_mod.rs"); } +/// Get a list of available targets for 'rustc'. fn get_target_list() -> String { let completed_process = rustc().arg("--print").arg("target-list").run(); String::from_utf8(completed_process.stdout()).expect("error not a string") @@ -113,18 +163,11 @@ fn parse_size(defines: &str, type_name: &str) -> usize { panic!("Could not find size definition for type: {}", type_name); } -// Helper to parse signedness from clang defines -fn parse_signed(defines: &str, type_name: &str) -> bool { - match type_name.to_uppercase().as_str() { - "CHAR" => { - // Check if char is explicitly unsigned - !defines.lines().any(|line| line.contains("__CHAR_UNSIGNED__")) - } - _ => true, - } +fn char_is_signed(defines: &str) -> bool { + !defines.lines().any(|line| line.contains("__CHAR_UNSIGNED__")) } -// Parse core/ffi/mod.rs to retrieve only necessary macros and type defines +/// Parse core/ffi/mod.rs to retrieve only necessary macros and type defines fn regex_mod() { let mod_path = run_make_support::source_root().join("library/core/src/ffi/mod.rs"); let mut content = rfs::read_to_string(&mod_path); @@ -157,7 +200,7 @@ fn regex_mod() { re = regex::Regex::new(r"(?s)impl fmt::Debug for.*?\{.*?\}").unwrap(); content = re.replace_all(&content, "").to_string(); - let file_name = format!("processed_mod.rs"); + let file_name = "processed_mod.rs"; rfs::create_file(&file_name); rfs::write(&file_name, content); diff --git a/tests/run-make/core-ffi-typecheck-clang/tests.rs b/tests/run-make/core-ffi-typecheck-clang/tests.rs index 10577f02f7a3a..2949827aa5c8e 100644 --- a/tests/run-make/core-ffi-typecheck-clang/tests.rs +++ b/tests/run-make/core-ffi-typecheck-clang/tests.rs @@ -1,7 +1,13 @@ -// tests.rs +/// This file compares the size and signedness of Rust `c_*` types to those from Clang, +/// based on the `CLANG_C_*` constants. Comparisons are done at compile time so this +/// does not need to be executed. +use super::*; // `super` will include everything from the common template -use super::*; // `super` will include everything from `smallcore` once glued together +trait Signed { + const SIGNED: bool; +} +// Verify Rust's 'c_long' is correct. cfg_if! { if #[cfg(all(target_arch = "aarch64", target_abi = "ilp32"))] { // FIXME: long is not long enough on aarch64 ilp32, should be 8, defaulting to 4 @@ -18,28 +24,30 @@ cfg_if! { } } +// Verify Rust's 'c_char' has correct sign. cfg_if! { if #[cfg(target_arch = "csky")] { // FIXME: c_char signedness misallignment on csky, should be signed on CLANG const XFAIL_C_CHAR_SIGNED: bool = false; - pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED ^ XFAIL_C_CHAR_SIGNED { + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != XFAIL_C_CHAR_SIGNED { panic!("mismatched c_char signed, target_arch: csky"); }; } else if #[cfg(target_arch = "msp430")] { // FIXME: c_char signedness misallignment on msp430, should be signed on CLANG - const XFAIL_C_CHAR_SIGNED: bool = false; // Change to true for darwin - pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED ^ XFAIL_C_CHAR_SIGNED { + const XFAIL_C_CHAR_SIGNED: bool = false; + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != XFAIL_C_CHAR_SIGNED { panic!("mismatched c_char signed, target_arch: msp430"); }; } else { - pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED ^ CLANG_C_CHAR_SIGNED { + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != CLANG_C_CHAR_SIGNED { panic!("mismatched c_char sign"); }; } } +// Verify Rust's 'c_double' is correct. cfg_if! { if #[cfg(target_arch = "avr")] { // FIXME: double is not short enough on avr-unknown-gnu-atmega328 (should be 4 bytes) @@ -55,10 +63,6 @@ cfg_if! { } } -trait Signed { - const SIGNED: bool; -} - impl Signed for i8 { const SIGNED: bool = true; } From 98ae709dfc6f37ac87316e3dba52a027b1e11f2a Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 16:08:06 -0500 Subject: [PATCH 03/13] styling fixes, skipped_targets clearly defined, bitXor removed, clang status check --- tests/run-make/core-ffi-typecheck-clang/rmake.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index a70ca144564a1..38c2d0f07063e 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -113,12 +113,12 @@ fn main() { )); // Generate a target-specific rmake file. - // If type misalignments occur, use the generated rmake file name to identify the failing target. - // Replace dots (.) and hyphens (-) in the target name with underscores to ensure valid filenames. + // If type misalignments occur, + // generated rmake file name used to identify the failing target. let file_name = format!("{}_rmake.rs", target.replace("-", "_").replace(".", "_")); - // Attempt to build the test file for the relevant target. Tests use constant evaluation, - // so running is not necessary. + // Attempt to build the test file for the relevant target. + // Tests use constant evaluation, so running is not necessary. rfs::write(&file_name, rmake_content); let rustc_output = rustc() .arg("-Zunstable-options") From 1a427d731681b689819828610afb01f3834ee5c8 Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 18:41:44 -0500 Subject: [PATCH 04/13] implemented checks for size_t, ssize_t, ptrdiff_t, & schar_t --- .../core-ffi-typecheck-clang/rmake.rs | 5 +- .../core-ffi-typecheck-clang/tests.rs | 73 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 38c2d0f07063e..0a0b4cfc8c1de 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -1,4 +1,3 @@ -//@ needs-force-clang-based-tests // This test checks that the clang defines for each target allign with the core ffi types defined in // mod.rs. Therefore each rust target is queried and the clang defines for each target are read and // compared to the core sizes to verify all types and sizes allign at buildtime. @@ -101,6 +100,8 @@ fn main() { const CLANG_C_LONGLONG_SIZE: usize = {}; const CLANG_C_FLOAT_SIZE: usize = {}; const CLANG_C_DOUBLE_SIZE: usize = {}; + const CLANG_C_SIZE_T_SIZE: usize = {}; + const CLANG_C_PTRDIFF_T_SIZE: usize = {}; ", parse_size(&defines, "CHAR"), char_is_signed(&defines), @@ -110,6 +111,8 @@ fn main() { parse_size(&defines, "LONG_LONG"), parse_size(&defines, "FLOAT"), parse_size(&defines, "DOUBLE"), + parse_size(&defines, "SIZE_T"), + parse_size(&defines, "PTRDIFF_T"), )); // Generate a target-specific rmake file. diff --git a/tests/run-make/core-ffi-typecheck-clang/tests.rs b/tests/run-make/core-ffi-typecheck-clang/tests.rs index 2949827aa5c8e..97688db3442ea 100644 --- a/tests/run-make/core-ffi-typecheck-clang/tests.rs +++ b/tests/run-make/core-ffi-typecheck-clang/tests.rs @@ -63,6 +63,54 @@ cfg_if! { } } +// Verify Rust's 'c_size_t' is correct +cfg_if! { + if #[cfg(all(target_arch = "aarch64", target_abi = "ilp32"))] { + // FIXME: size_t is not short enough on aarch64 ilp32, should be 4, defaulting to 8 + const XFAIL_C_SIZE_T_SIZE: usize = 4; + pub const TEST_C_SIZE_T_SIZE: () = if size_of::() != XFAIL_C_SIZE_T_SIZE { + panic!("wrong c_size_t size, target_arch: aarch64, target_abi: ilp32"); + }; + } + else { + pub const TEST_C_SIZE_T_SIZE: () = if size_of::() != CLANG_C_SIZE_T_SIZE { + panic!("wrong c_size_t size"); + }; + } +} + +// Verify Rust's 'c_ssize_t' is correct +cfg_if! { + if #[cfg(all(target_arch = "aarch64", target_abi = "ilp32"))] { + // FIXME: ssize_t is not short enough on aarch64 ilp32, should be 4, defaulting to 8 + const XFAIL_C_SSIZE_T_SIZE: usize = 4; + pub const TEST_C_SSIZE_T_SIZE: () = if size_of::() != XFAIL_C_SSIZE_T_SIZE { + panic!("wrong c_ssize_t size, target_arch: aarch64, target_abi: ilp32"); + }; + } + else { + pub const TEST_C_SSIZE_T_SIZE: () = if size_of::() != CLANG_C_SIZE_T_SIZE { + panic!("wrong c_size_t size"); + }; + } +} + +// Verify Rust's 'c_ptrdiff_t' is correct +cfg_if! { + if #[cfg(all(target_arch = "aarch64", target_abi = "ilp32"))] { + // FIXME: c_ptrdiff_t is not short enough on aarch64 ilp32, should be 4, defaulting to 8 + const XFAIL_C_PTRDIFF_T_SIZE: usize = 4; + pub const TEST_C_PTRDIFF_T_SIZE: () = if size_of::() != XFAIL_C_PTRDIFF_T_SIZE { + panic!("wrong c_ssize_t size, target_arch: aarch64, target_abi: ilp32"); + }; + } + else { + pub const TEST_C_PTRDIFF_T_SIZE: () = if size_of::() != CLANG_C_PTRDIFF_T_SIZE { + panic!("wrong c_size_t size"); + }; + } +} + impl Signed for i8 { const SIGNED: bool = true; } @@ -95,3 +143,28 @@ pub const TEST_C_LONGLONG_SIZE: () = if size_of::() != CLANG_C_ pub const TEST_C_FLOAT_SIZE: () = if size_of::() != CLANG_C_FLOAT_SIZE { panic!("wrong c_float size"); }; + +//c_schar size +pub const TEST_C_SCHAR_SIZE: () = if size_of::() != CLANG_C_CHAR_SIZE { + panic!("wrong c_schar size"); +}; + +//c_uchar size +pub const TEST_C_UCHAR_SIZE: () = if size_of::() != CLANG_C_CHAR_SIZE { + panic!("wrong c_uchar size"); +}; + +//c_uint size +pub const TEST_C_UINT_SIZE: () = if size_of::() != CLANG_C_INT_SIZE { + panic!("mismatched c_uint size"); +}; + +//c_ushort size +pub const TEST_C_USHORT_SIZE: () = if size_of::() != CLANG_C_SHORT_SIZE { + panic!("wrong c_ushort size"); +}; + +//c_ulonglong size +pub const TEST_C_ULONGLONG_SIZE: () = if size_of::() != CLANG_C_LONGLONG_SIZE { + panic!("wrong c_ulonglong size"); +}; From 4e0c7cbd3fb8d313b0dbd90f3a655944718ac554 Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 18:43:21 -0500 Subject: [PATCH 05/13] tidy up --- tests/run-make/core-ffi-typecheck-clang/tests.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/tests.rs b/tests/run-make/core-ffi-typecheck-clang/tests.rs index 97688db3442ea..d5353cb39cf06 100644 --- a/tests/run-make/core-ffi-typecheck-clang/tests.rs +++ b/tests/run-make/core-ffi-typecheck-clang/tests.rs @@ -100,12 +100,14 @@ cfg_if! { if #[cfg(all(target_arch = "aarch64", target_abi = "ilp32"))] { // FIXME: c_ptrdiff_t is not short enough on aarch64 ilp32, should be 4, defaulting to 8 const XFAIL_C_PTRDIFF_T_SIZE: usize = 4; - pub const TEST_C_PTRDIFF_T_SIZE: () = if size_of::() != XFAIL_C_PTRDIFF_T_SIZE { + pub const TEST_C_PTRDIFF_T_SIZE: () = + if size_of::() != XFAIL_C_PTRDIFF_T_SIZE { panic!("wrong c_ssize_t size, target_arch: aarch64, target_abi: ilp32"); }; } else { - pub const TEST_C_PTRDIFF_T_SIZE: () = if size_of::() != CLANG_C_PTRDIFF_T_SIZE { + pub const TEST_C_PTRDIFF_T_SIZE: () = + if size_of::() != CLANG_C_PTRDIFF_T_SIZE { panic!("wrong c_size_t size"); }; } From 16cc9a04ed7a0bdad17b7d01b35be60f220bac79 Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 18:46:31 -0500 Subject: [PATCH 06/13] add comment: needs force clang based tests --- tests/run-make/core-ffi-typecheck-clang/rmake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 0a0b4cfc8c1de..4c12d457a3b6f 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-force-clang-based-tests // This test checks that the clang defines for each target allign with the core ffi types defined in // mod.rs. Therefore each rust target is queried and the clang defines for each target are read and // compared to the core sizes to verify all types and sizes allign at buildtime. @@ -205,6 +206,5 @@ fn regex_mod() { let file_name = "processed_mod.rs"; - rfs::create_file(&file_name); rfs::write(&file_name, content); } From ea35da9951bf6ebdf66970d2a56d19d80e39998e Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 18:55:24 -0500 Subject: [PATCH 07/13] map rust target to clang target if not the same --- .../core-ffi-typecheck-clang/rmake.rs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 4c12d457a3b6f..6b91cbe45a5a5 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -49,6 +49,15 @@ const SKIPPED_TARGETS: &[&str] = &[ "xtensa-esp32s3-none-elf", ]; +/// Map from a Rust target to the Clang target if they are not the same. +const MAPPED_TARGETS: &[(&str, &str)] = &[ + ("aarch64-apple-ios-sim", "aarch64-apple-ios"), + ("aarch64-apple-tvos-sim", "aarch64-apple-tvos"), + ("aarch64-apple-visionos-sim", "aarch64-apple-visionos"), + ("aarch64-apple-watchos-sim", "aarch64-apple-watchos"), + ("x86_64-apple-watchos-sim", "x86_64-apple-watchos"), +]; + fn main() { let targets = get_target_list(); @@ -61,13 +70,15 @@ fn main() { continue; } + // Map the Rust target string to a Clang target string if needed. + let ctarget = match MAPPED_TARGETS.iter().find(|(rtarget, _ctarget)| rtarget == &target) { + Some((_rtarget, ctarget)) => ctarget, + None => target, + }; + // Run Clang's preprocessor for the relevant target, printing default macro definitions. let clang_output = - clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", target]).run(); - - if !clang_output.status().success() { - continue; - } + clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", ctarget]).run(); let defines = String::from_utf8(clang_output.stdout()).expect("Invalid UTF-8"); From 1b49dbfa4579c9f03405b1ea57af626c5ec38321 Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 27 Jan 2025 21:14:43 -0500 Subject: [PATCH 08/13] clang target specific handling (rscv) --- .../core-ffi-typecheck-clang/rmake.rs | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 6b91cbe45a5a5..7e9ccbfdc827a 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -6,40 +6,10 @@ // If this test fails because Rust adds a target that Clang does not support, this target should be // added to SKIPPED_TARGETS. -use run_make_support::{clang, regex, rfs, rustc}; +use run_make_support::{clang, llvm_components_contain, regex, rfs, rustc}; // It is not possible to run the Rust test-suite on these targets. const SKIPPED_TARGETS: &[&str] = &[ - "riscv32gc-unknown-linux-gnu", - "riscv32gc-unknown-linux-musl", - "riscv32im-risc0-zkvm-elf", - "riscv32imac-esp-espidf", - "riscv32imafc-esp-espidf", - "riscv32imafc-unknown-nuttx-elf", - "riscv32imc-esp-espidf", - "riscv32imac-unknown-nuttx-elf", - "riscv32imac-unknown-xous-elf", - "riscv32imc-unknown-nuttx-elf", - "riscv32e-unknown-none-elf", - "riscv32em-unknown-none-elf", - "riscv32emc-unknown-none-elf", - "riscv32i-unknown-none-elf", - "riscv32im-unknown-none-elf", - "riscv32imc-unknown-none-elf", - "riscv32ima-unknown-none-elf", - "riscv32imac-unknown-none-elf", - "riscv32imafc-unknown-none-elf", - "riscv64gc-unknown-freebsd", - "riscv64gc-unknown-fuchsia", - "riscv64gc-unknown-hermit", - "riscv64gc-unknown-linux-gnu", - "riscv64gc-unknown-linux-musl", - "riscv64gc-unknown-netbsd", - "riscv64gc-unknown-none-elf", - "riscv64gc-unknown-nuttx-elf", - "riscv64gc-unknown-openbsd", - "riscv64imac-unknown-none-elf", - "riscv64imac-unknown-nuttx-elf", "wasm32v1-none", "xtensa-esp32-espidf", "xtensa-esp32-none-elf", @@ -70,15 +40,34 @@ fn main() { continue; } - // Map the Rust target string to a Clang target string if needed. - let ctarget = match MAPPED_TARGETS.iter().find(|(rtarget, _ctarget)| rtarget == &target) { - Some((_rtarget, ctarget)) => ctarget, - None => target, - }; + // Map the Rust target string to a Clang target string if needed + // Also replace riscv with necessary replacements to match clang + // If neither just use target string + let ctarget = MAPPED_TARGETS + .iter() + .find(|(rtarget, _)| *rtarget == target) + .map(|(_, ctarget)| ctarget.to_string()) + .unwrap_or_else(|| { + if target.starts_with("riscv") { + target + .replace("imac", "") + .replace("gc", "") + .replace("imafc", "") + .replace("imc", "") + .replace("ima", "") + .replace("im", "") + .replace("emc", "") + .replace("em", "") + .replace("e-", "-") + .replace("i-", "-") + } else { + target.to_string() + } + }); // Run Clang's preprocessor for the relevant target, printing default macro definitions. let clang_output = - clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", ctarget]).run(); + clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", &ctarget]).run(); let defines = String::from_utf8(clang_output.stdout()).expect("Invalid UTF-8"); From 7edcddda84dbf9a9136192a9f0330f241b40bec0 Mon Sep 17 00:00:00 2001 From: ricci009 Date: Tue, 28 Jan 2025 22:44:33 -0500 Subject: [PATCH 09/13] added additional unsupported targets on clang and refactored a func name and replace portion --- .../core-ffi-typecheck-clang/rmake.rs | 48 +++++++++++++++---- .../core-ffi-typecheck-clang/tests.rs | 9 +--- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 7e9ccbfdc827a..41658893ae4e2 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -17,6 +17,8 @@ const SKIPPED_TARGETS: &[&str] = &[ "xtensa-esp32s2-none-elf", "xtensa-esp32s3-espidf", "xtensa-esp32s3-none-elf", + "csky-unknown-linux-gnuabiv2", + "csky-unknown-linux-gnuabiv2hf", ]; /// Map from a Rust target to the Clang target if they are not the same. @@ -26,6 +28,32 @@ const MAPPED_TARGETS: &[(&str, &str)] = &[ ("aarch64-apple-visionos-sim", "aarch64-apple-visionos"), ("aarch64-apple-watchos-sim", "aarch64-apple-watchos"), ("x86_64-apple-watchos-sim", "x86_64-apple-watchos"), + ("aarch64-pc-windows-gnullvm", "aarch64-pc-windows-gnu"), + ("aarch64-unknown-linux-gnu_ilp32", "aarch64-unknown-linux-gnu"), + ("aarch64-unknown-none-softfloat", "aarch64-unknown-none"), + ("aarch64-unknown-nto-qnx700", "aarch64-unknown-nto-700"), + ("aarch64-unknown-nto-qnx710", "aarch64-unknown-nto-710"), + ("aarch64-unknown-uefi", "aarch64-unknown"), + ("aarch64_be-unknown-linux-gnu_ilp32", "aarch64_be-unknown-linux-gnu"), + ("armv5te-unknown-linux-uclibceabi", "armv5te-unknown-linux"), + ("armv7-sony-vita-newlibeabihf", "armv7-sony-vita"), + ("armv7-unknown-linux-uclibceabi", "armv7-unknown-linux"), + ("armv7-unknown-linux-uclibceabihf", "armv7-unknown-linux"), + ("avr-unknown-gnu-atmega328", "avr-unknown-gnu"), + ("csky-unknown-linux-gnuabiv2", "csky-unknown-linux-gnu"), + ("i586-pc-nto-qnx700", "i586-pc-nto-700"), + ("i686-pc-windows-gnullvm", "i686-pc-windows-gnu"), + ("i686-unknown-uefi", "i686-unknown"), + ("loongarch64-unknown-none-softfloat", "loongarch64-unknown-none"), + ("mips-unknown-linux-uclibc", "mips-unknown-linux"), + ("mipsel-unknown-linux-uclibc", "mipsel-unknown-linux"), + ("powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu"), + ("powerpc-unknown-linux-muslspe", "powerpc-unknown-linux-musl"), + ("powerpc-wrs-vxworks-spe", "powerpc-wrs-vxworks"), + ("x86_64-fortanix-unknown-sgx", "x86_64-fortanix-unknown"), + ("x86_64-pc-nto-qnx710", "x86_64-pc-nto-710"), + ("x86_64-pc-windows-gnullvm", "x86_64-pc-windows-gnu"), + ("x86_64-unknown-l4re-uclibc", "x86_64-unknown-l4re"), ]; fn main() { @@ -33,7 +61,7 @@ fn main() { let minicore_path = run_make_support::source_root().join("tests/auxiliary/minicore.rs"); - regex_mod(); + preprocess_core_ffi(); for target in targets.lines() { if SKIPPED_TARGETS.iter().any(|&to_skip_target| target == to_skip_target) { @@ -50,14 +78,14 @@ fn main() { .unwrap_or_else(|| { if target.starts_with("riscv") { target - .replace("imac", "") - .replace("gc", "") - .replace("imafc", "") - .replace("imc", "") - .replace("ima", "") - .replace("im", "") - .replace("emc", "") - .replace("em", "") + .replace("imac-", "-") + .replace("gc-", "-") + .replace("imafc-", "-") + .replace("imc-", "-") + .replace("ima-", "-") + .replace("im-", "-") + .replace("emc-", "-") + .replace("em-", "-") .replace("e-", "-") .replace("i-", "-") } else { @@ -172,7 +200,7 @@ fn char_is_signed(defines: &str) -> bool { } /// Parse core/ffi/mod.rs to retrieve only necessary macros and type defines -fn regex_mod() { +fn preprocess_core_ffi() { let mod_path = run_make_support::source_root().join("library/core/src/ffi/mod.rs"); let mut content = rfs::read_to_string(&mod_path); diff --git a/tests/run-make/core-ffi-typecheck-clang/tests.rs b/tests/run-make/core-ffi-typecheck-clang/tests.rs index d5353cb39cf06..6ce30f3025866 100644 --- a/tests/run-make/core-ffi-typecheck-clang/tests.rs +++ b/tests/run-make/core-ffi-typecheck-clang/tests.rs @@ -26,14 +26,7 @@ cfg_if! { // Verify Rust's 'c_char' has correct sign. cfg_if! { - if #[cfg(target_arch = "csky")] { - // FIXME: c_char signedness misallignment on csky, should be signed on CLANG - const XFAIL_C_CHAR_SIGNED: bool = false; - pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != XFAIL_C_CHAR_SIGNED { - panic!("mismatched c_char signed, target_arch: csky"); - }; - } - else if #[cfg(target_arch = "msp430")] { + if #[cfg(target_arch = "msp430")] { // FIXME: c_char signedness misallignment on msp430, should be signed on CLANG const XFAIL_C_CHAR_SIGNED: bool = false; pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != XFAIL_C_CHAR_SIGNED { From cedd098b4ff9ffba69ecdb268a3f6afe72753ffe Mon Sep 17 00:00:00 2001 From: ricci009 Date: Wed, 29 Jan 2025 18:00:25 -0500 Subject: [PATCH 10/13] llvm-target use and additional misallignment catches --- .../core-ffi-typecheck-clang/rmake.rs | 77 +++---------------- .../core-ffi-typecheck-clang/tests.rs | 26 ++++++- 2 files changed, 37 insertions(+), 66 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 41658893ae4e2..0f50f431c946e 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -6,7 +6,8 @@ // If this test fails because Rust adds a target that Clang does not support, this target should be // added to SKIPPED_TARGETS. -use run_make_support::{clang, llvm_components_contain, regex, rfs, rustc}; +use run_make_support::{clang, regex, rfs, rustc, serde_json}; +use serde_json::Value; // It is not possible to run the Rust test-suite on these targets. const SKIPPED_TARGETS: &[&str] = &[ @@ -21,81 +22,27 @@ const SKIPPED_TARGETS: &[&str] = &[ "csky-unknown-linux-gnuabiv2hf", ]; -/// Map from a Rust target to the Clang target if they are not the same. -const MAPPED_TARGETS: &[(&str, &str)] = &[ - ("aarch64-apple-ios-sim", "aarch64-apple-ios"), - ("aarch64-apple-tvos-sim", "aarch64-apple-tvos"), - ("aarch64-apple-visionos-sim", "aarch64-apple-visionos"), - ("aarch64-apple-watchos-sim", "aarch64-apple-watchos"), - ("x86_64-apple-watchos-sim", "x86_64-apple-watchos"), - ("aarch64-pc-windows-gnullvm", "aarch64-pc-windows-gnu"), - ("aarch64-unknown-linux-gnu_ilp32", "aarch64-unknown-linux-gnu"), - ("aarch64-unknown-none-softfloat", "aarch64-unknown-none"), - ("aarch64-unknown-nto-qnx700", "aarch64-unknown-nto-700"), - ("aarch64-unknown-nto-qnx710", "aarch64-unknown-nto-710"), - ("aarch64-unknown-uefi", "aarch64-unknown"), - ("aarch64_be-unknown-linux-gnu_ilp32", "aarch64_be-unknown-linux-gnu"), - ("armv5te-unknown-linux-uclibceabi", "armv5te-unknown-linux"), - ("armv7-sony-vita-newlibeabihf", "armv7-sony-vita"), - ("armv7-unknown-linux-uclibceabi", "armv7-unknown-linux"), - ("armv7-unknown-linux-uclibceabihf", "armv7-unknown-linux"), - ("avr-unknown-gnu-atmega328", "avr-unknown-gnu"), - ("csky-unknown-linux-gnuabiv2", "csky-unknown-linux-gnu"), - ("i586-pc-nto-qnx700", "i586-pc-nto-700"), - ("i686-pc-windows-gnullvm", "i686-pc-windows-gnu"), - ("i686-unknown-uefi", "i686-unknown"), - ("loongarch64-unknown-none-softfloat", "loongarch64-unknown-none"), - ("mips-unknown-linux-uclibc", "mips-unknown-linux"), - ("mipsel-unknown-linux-uclibc", "mipsel-unknown-linux"), - ("powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu"), - ("powerpc-unknown-linux-muslspe", "powerpc-unknown-linux-musl"), - ("powerpc-wrs-vxworks-spe", "powerpc-wrs-vxworks"), - ("x86_64-fortanix-unknown-sgx", "x86_64-fortanix-unknown"), - ("x86_64-pc-nto-qnx710", "x86_64-pc-nto-710"), - ("x86_64-pc-windows-gnullvm", "x86_64-pc-windows-gnu"), - ("x86_64-unknown-l4re-uclibc", "x86_64-unknown-l4re"), -]; - fn main() { - let targets = get_target_list(); - let minicore_path = run_make_support::source_root().join("tests/auxiliary/minicore.rs"); preprocess_core_ffi(); - for target in targets.lines() { + let targets_json = + rustc().arg("--print").arg("all-target-specs-json").arg("-Z").arg("unstable-options").run(); + let targets_json_str = + String::from_utf8(targets_json.stdout().to_vec()).expect("error not a string"); + + let j: Value = serde_json::from_str(&targets_json_str).unwrap(); + for (target, v) in j.as_object().unwrap() { + let llvm_target = &v["llvm-target"].as_str().unwrap(); + if SKIPPED_TARGETS.iter().any(|&to_skip_target| target == to_skip_target) { continue; } - // Map the Rust target string to a Clang target string if needed - // Also replace riscv with necessary replacements to match clang - // If neither just use target string - let ctarget = MAPPED_TARGETS - .iter() - .find(|(rtarget, _)| *rtarget == target) - .map(|(_, ctarget)| ctarget.to_string()) - .unwrap_or_else(|| { - if target.starts_with("riscv") { - target - .replace("imac-", "-") - .replace("gc-", "-") - .replace("imafc-", "-") - .replace("imc-", "-") - .replace("ima-", "-") - .replace("im-", "-") - .replace("emc-", "-") - .replace("em-", "-") - .replace("e-", "-") - .replace("i-", "-") - } else { - target.to_string() - } - }); - // Run Clang's preprocessor for the relevant target, printing default macro definitions. let clang_output = - clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", &ctarget]).run(); + clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", &llvm_target]).run(); let defines = String::from_utf8(clang_output.stdout()).expect("Invalid UTF-8"); diff --git a/tests/run-make/core-ffi-typecheck-clang/tests.rs b/tests/run-make/core-ffi-typecheck-clang/tests.rs index 6ce30f3025866..9dc44201ac766 100644 --- a/tests/run-make/core-ffi-typecheck-clang/tests.rs +++ b/tests/run-make/core-ffi-typecheck-clang/tests.rs @@ -13,7 +13,23 @@ cfg_if! { // FIXME: long is not long enough on aarch64 ilp32, should be 8, defaulting to 4 const XFAIL_C_LONG_SIZE: usize = 4; pub const TEST_C_LONG_SIZE: () = if size_of::() != XFAIL_C_LONG_SIZE { - panic!("wrong c_long size test ilp32"); + panic!("mismatched c_long size, target_abi: ilp32"); + }; + } + else if #[cfg(all(target_arch = "aarch64", target_os = "uefi"))] { + // FIXME: c_long misallignment llvm target is aarch64-unknown-windows, + // discrepencies between Rust target configuration and LLVM alias. + const XFAIL_C_LONG_SIZE: usize = 8; + pub const TEST_C_LONG_SIZE: () = if size_of::() != XFAIL_C_LONG_SIZE { + panic!("mismatched c_long size, target_os: uefi"); + }; + } + else if #[cfg(all(target_arch = "x86_64", target_os = "uefi"))] { + // FIXME: c_long misallignment llvm target is x86_64-unknown-windows, + // discrepencies between Rust target configuration and LLVM alias. + const XFAIL_C_LONG_SIZE: usize = 8; + pub const TEST_C_LONG_SIZE: () = if size_of::() != XFAIL_C_LONG_SIZE { + panic!("mismatched c_long size, target_os: uefi"); }; } else { @@ -33,6 +49,14 @@ cfg_if! { panic!("mismatched c_char signed, target_arch: msp430"); }; } + else if #[cfg(all(target_arch = "aarch64", target_os = "uefi"))] { + // FIXME: c_char signedness misallignment llvm target is aarch64-unknown-windows, + // discrepencies between Rust target configuration and LLVM alias. + const XFAIL_C_CHAR_SIGNED: bool = false; + pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != XFAIL_C_CHAR_SIGNED { + panic!("mismatched c_char signed, target_os: uefi"); + }; + } else { pub const TEST_C_CHAR_UNSIGNED: () = if ffi::c_char::SIGNED != CLANG_C_CHAR_SIGNED { panic!("mismatched c_char sign"); From 8fbd055e2b39ffca07c6cabab15fa5ae2910247b Mon Sep 17 00:00:00 2001 From: ricci009 Date: Wed, 29 Jan 2025 18:11:20 -0500 Subject: [PATCH 11/13] rmake cleanup and addition of additional targets --- tests/run-make/core-ffi-typecheck-clang/rmake.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 0f50f431c946e..7448a501f1873 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -11,7 +11,6 @@ use serde_json::Value; // It is not possible to run the Rust test-suite on these targets. const SKIPPED_TARGETS: &[&str] = &[ - "wasm32v1-none", "xtensa-esp32-espidf", "xtensa-esp32-none-elf", "xtensa-esp32s2-espidf", @@ -117,12 +116,6 @@ fn main() { rfs::remove_file("processed_mod.rs"); } -/// Get a list of available targets for 'rustc'. -fn get_target_list() -> String { - let completed_process = rustc().arg("--print").arg("target-list").run(); - String::from_utf8(completed_process.stdout()).expect("error not a string") -} - // Helper to parse size from clang defines fn parse_size(defines: &str, type_name: &str) -> usize { let search_pattern = format!("__SIZEOF_{}__ ", type_name.to_uppercase()); From 46a68d106e80ecfba04a00d50e3555bb8ed2d245 Mon Sep 17 00:00:00 2001 From: Riccardo Date: Thu, 30 Jan 2025 11:47:37 -0500 Subject: [PATCH 12/13] added matching for unsupported clang targets --- .../core-ffi-typecheck-clang/rmake.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 7448a501f1873..7f63ebd4cabd6 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -21,6 +21,15 @@ const SKIPPED_TARGETS: &[&str] = &[ "csky-unknown-linux-gnuabiv2hf", ]; +const MAPPED_TARGETS: &[(&str, &str)] = &[ + ("armv5te-unknown-linux-uclibcgnueabi", "armv5te-unknown-linux"), + ("mips-unknown-linux-uclibc", "mips-unknown-linux"), + ("mipsel-unknown-linux-uclibc", "mips-unknown-linux"), + ("powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnu"), + ("powerpc-unknown-linux-muslspe", "powerpc-unknown-linux-musl"), + ("x86_64-unknown-l4re-uclibc", "x86_64-unknown-l4re"), +]; + fn main() { let minicore_path = run_make_support::source_root().join("tests/auxiliary/minicore.rs"); @@ -39,9 +48,17 @@ fn main() { continue; } + // Create a new variable to hold either the mapped target or original llvm_target + let target_to_use = MAPPED_TARGETS + .iter() + .find(|&&(from, _)| from == *llvm_target) + .map(|&(_, to)| to) + .unwrap_or(llvm_target); + + // Run Clang's preprocessor for the relevant target, printing default macro definitions. let clang_output = - clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", &llvm_target]).run(); + clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", &target_to_use]).run(); let defines = String::from_utf8(clang_output.stdout()).expect("Invalid UTF-8"); From a88bcbe74c46f87a59ec194a71ce586a91022487 Mon Sep 17 00:00:00 2001 From: Riccardo Date: Thu, 30 Jan 2025 13:14:27 -0500 Subject: [PATCH 13/13] formatting fix --- tests/run-make/core-ffi-typecheck-clang/rmake.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/run-make/core-ffi-typecheck-clang/rmake.rs b/tests/run-make/core-ffi-typecheck-clang/rmake.rs index 7f63ebd4cabd6..b0d500b1bb0fd 100644 --- a/tests/run-make/core-ffi-typecheck-clang/rmake.rs +++ b/tests/run-make/core-ffi-typecheck-clang/rmake.rs @@ -55,7 +55,6 @@ fn main() { .map(|&(_, to)| to) .unwrap_or(llvm_target); - // Run Clang's preprocessor for the relevant target, printing default macro definitions. let clang_output = clang().args(&["-E", "-dM", "-x", "c", "/dev/null", "-target", &target_to_use]).run();