diff --git a/bootstrap.rust9x.gnu.toml b/bootstrap.rust9x.gnu.toml new file mode 100644 index 0000000000000..05be202921b15 --- /dev/null +++ b/bootstrap.rust9x.gnu.toml @@ -0,0 +1,74 @@ +# See bootstrap.example.toml for documentation of available options +# +change-id = 148795 + +[llvm] +# Will download LLVM from CI if available on your platform. +download-ci-llvm = true +# NOTE: if you set ↑ to false, disable other LLVM targets to save lots of build time! +# targets = "X86" +# experimental-targets = "" + +[build] +build = "x86_64-unknown-linux-gnu" +target = [ + "x86_64-unknown-linux-gnu", + "x86_64-pc-windows-gnu", + "x86_64-rust9x-windows-gnu", + "i686-pc-windows-gnu", + "i686-rust9x-windows-gnu", + "i586-rust9x-windows-gnu", +] + +docs = false + +# extended = true +# tools = [ +# # "cargo", +# # "clippy", +# "rustdoc", +# # "rustfmt", +# # "rust-analyzer", +# # "rust-analyzer-proc-macro-srv", +# # "analysis", +# "src", +# # "wasm-component-ld", +# # "miri", "cargo-miri" # for dev/nightly channels +# ] + +[target.x86_64-pc-windows-gnu] +cc = "x86_64-w64-mingw32-gcc" +cxx = "x86_64-w64-mingw32-g++" + +[target.x86_64-rust9x-windows-gnu] +cc = "x86_64-w64-mingw32-gcc" +cxx = "x86_64-w64-mingw32-g++" + +[target.i686-pc-windows-gnu] +cc = "i686-w64-mingw32-gcc" +cxx = "i686-w64-mingw32-g++" + +[target.i686-rust9x-windows-gnu] +cc = "i686-w64-mingw32-gcc" +cxx = "i686-w64-mingw32-g++" + +[target.i586-rust9x-windows-gnu] +cc = "i686-w64-mingw32-gcc" +cxx = "i686-w64-mingw32-g++" + +[install] +# for creating a downloadable package: python x.py install, then create and archive this +prefix = "../dist/rust9x-gnu" +sysconfdir = "." + +[rust] +# enable rust-lld.exe so we don't need editbin.exe +lld = true +dist-src = false + +# you can override this with -i/--incremental +# incremental = false +# incremental = true + +[dist] +src-tarball = false diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 5c165b1cb6a9b..0de5855d59392 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1614,9 +1614,12 @@ supported_targets! { ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu), ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu), + ("x86_64-rust9x-windows-gnu", x86_64_rust9x_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), ("i686-uwp-windows-gnu", i686_uwp_windows_gnu), ("i686-win7-windows-gnu", i686_win7_windows_gnu), + ("i686-rust9x-windows-gnu", i686_rust9x_windows_gnu), + ("i586-rust9x-windows-gnu", i586_rust9x_windows_gnu), ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm), ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm), diff --git a/compiler/rustc_target/src/spec/targets/i586_rust9x_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i586_rust9x_windows_gnu.rs new file mode 100644 index 0000000000000..f22773059deb2 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/i586_rust9x_windows_gnu.rs @@ -0,0 +1,10 @@ +use crate::spec::Target; + +pub(crate) fn target() -> Target { + let mut base = super::i686_rust9x_windows_gnu::target(); + base.cpu = "i586".into(); + base.llvm_target = "i586-pc-windows-gnu".into(); + // go back to x87 FPU ABI spec + base.rustc_abi = None; + base +} diff --git a/compiler/rustc_target/src/spec/targets/i686_rust9x_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_rust9x_windows_gnu.rs new file mode 100644 index 0000000000000..bb8fab0572ee8 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/i686_rust9x_windows_gnu.rs @@ -0,0 +1,15 @@ +use crate::spec::{Target, cvs}; + +pub(crate) fn target() -> Target { + let mut base = super::i686_pc_windows_gnu::target(); + base.families = cvs!["windows", "rust9x"]; + + base.metadata = crate::spec::TargetMetadata { + description: Some("64-bit GNU rust9x (Windows XP 64-bit+)".into()), + tier: Some(4), + host_tools: Some(false), + std: Some(true), + }; + + base +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_rust9x_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_rust9x_windows_gnu.rs new file mode 100644 index 0000000000000..2af3c4a9fdbb2 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_rust9x_windows_gnu.rs @@ -0,0 +1,15 @@ +use crate::spec::{Target, cvs}; + +pub(crate) fn target() -> Target { + let mut base = super::x86_64_pc_windows_gnu::target(); + base.families = cvs!["windows", "rust9x"]; + + base.metadata = crate::spec::TargetMetadata { + description: Some("32-bit GNU rust9x (Windows 98/NT4+)".into()), + tier: Some(4), + host_tools: Some(false), + std: Some(true), + }; + + base +} diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 5c06e3aa5ef59..5f2557804be22 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -29,7 +29,7 @@ pub const EXIT_FAILURE: u32 = 1; pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() }; #[cfg(any(target_vendor = "win7", target_family = "rust9x"))] pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() }; -#[cfg(not(target_thread_local))] +#[cfg(all(not(target_thread_local), not(target_family = "rust9x")))] pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() }; // Some windows_sys types have different signs than the types we use. diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index a5b790a1db42c..64f3e54ad035c 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -161,10 +161,8 @@ pub fn fill_bytes(bytes: &mut [u8]) { getrandom(bytes, false); } -pub fn hashmap_random_keys() -> (u64, u64) { +pub fn hashmap_random_keys() -> [u8; 16] { let mut bytes = [0; 16]; getrandom(&mut bytes, true); - let k1 = u64::from_ne_bytes(bytes[..8].try_into().unwrap()); - let k2 = u64::from_ne_bytes(bytes[8..].try_into().unwrap()); - (k1, k2) + bytes } diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs index 2ff0fd1196e12..95a5f9a30c53e 100644 --- a/library/std/src/sys/thread_local/key/windows.rs +++ b/library/std/src/sys/thread_local/key/windows.rs @@ -24,10 +24,15 @@ // FIXME: investigate using a fixed-size array instead, as the maximum number // of keys is [limited to 1088](https://learn.microsoft.com/en-us/windows/win32/ProcThread/thread-local-storage). +#[cfg(not(target_family = "rust9x"))] use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release}; use crate::sync::atomic::{Atomic, AtomicPtr, AtomicU32}; +#[cfg(target_family = "rust9x")] +use crate::sync::atomic::AtomicBool; +#[cfg(target_family = "rust9x")] +use crate::sync::nonpoison::Mutex; use crate::sys::c; use crate::sys::thread_local::guard; @@ -44,7 +49,12 @@ pub struct LazyKey { /// Currently, destructors cannot be unregistered, so we cannot use racy /// initialization for keys. Instead, we need synchronize initialization. /// Use the Windows-provided `Once` since it does not require TLS. + #[cfg(not(target_family = "rust9x"))] once: UnsafeCell, + #[cfg(target_family = "rust9x")] + pending: AtomicBool, + #[cfg(target_family = "rust9x")] + initing: Mutex<()>, } impl LazyKey { @@ -54,7 +64,12 @@ impl LazyKey { key: AtomicU32::new(0), dtor, next: AtomicPtr::new(ptr::null_mut()), + #[cfg(not(target_family = "rust9x"))] once: UnsafeCell::new(c::INIT_ONCE_STATIC_INIT), + #[cfg(target_family = "rust9x")] + pending: AtomicBool::new(true), + #[cfg(target_family = "rust9x")] + initing: Mutex::new(()), } } @@ -67,6 +82,7 @@ impl LazyKey { } #[cold] + #[cfg(not(target_family = "rust9x"))] unsafe fn init(&'static self) -> Key { if self.dtor.is_some() { let mut pending = c::FALSE; @@ -123,6 +139,73 @@ impl LazyKey { } } } + + #[cold] + #[cfg(target_family = "rust9x")] + unsafe fn init(&'static self) -> Key { + if self.dtor.is_some() { + let pending = self.pending.load(Acquire); + if pending == false { + // Some other thread initialized the key, load it. + // We can use Relaxed here because pending will ensure + // key has been initialized. + self.key.load(Relaxed) - 1 + } else { + let _lock_guard = self.initing.lock(); + + // Multiple threads may have seen pending as true and + // tried to initialize it. We have the lock now, + // but we may not have the first to get it. + // Check if it was already initialized. + let pending2 = self.pending.load(Acquire); + if pending2 == false { + return self.key.load(Relaxed) - 1; + } + + let key = unsafe { c::TlsAlloc() }; + if key == c::TLS_OUT_OF_INDEXES { + // Since we abort the process, there is no need to wake up + // the waiting threads. If this were a panic, the wakeup + // would need to occur first in order to avoid deadlock. + rtabort!("out of TLS indexes"); + } + + unsafe { + register_dtor(self); + } + + // Store key with a Release to ensure loaders have + // access to our destructor. + self.key.store(key + 1, Release); + + // Store pending with a release to ensure any pending + // loads see the key store value. This ensures we won't + // ever hit a situation of finding pending false and + // the key uninitialized. + self.pending.store(false, Release); + + key + } + } else { + // If there is no destructor to clean up, we can use racy initialization. + + let key = unsafe { c::TlsAlloc() }; + if key == c::TLS_OUT_OF_INDEXES { + rtabort!("out of TLS indexes"); + } + + match self.key.compare_exchange(0, key + 1, AcqRel, Acquire) { + Ok(_) => key, + Err(new) => unsafe { + // Some other thread completed initialization first, so destroy + // our key and use theirs. + let r = c::TlsFree(key); + debug_assert_eq!(r, c::TRUE); + new - 1 + }, + } + } + } } unsafe impl Send for LazyKey {} diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 46d05b9d5d2f7..5fab906a1096f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -930,7 +930,13 @@ impl Step for StartupObjects { let src_file = &src_dir.join(file.to_string() + ".rs"); let dst_file = &dst_dir.join(file.to_string() + ".o"); if !up_to_date(src_file, dst_file) { - let mut cmd = command(&builder.initial_rustc); + let mut cmd = if target.contains("-rust9x-windows-gnu") { + // stage0 doesn't know about Rust9x targets, use a compiler + // we've built ourselves + builder.rustc_cmd(for_compiler) + } else { + command(&builder.initial_rustc) + }; cmd.env("RUSTC_BOOTSTRAP", "1"); if !builder.local_rebuild { // a local_rebuild compiler already has stage1 features diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 2e291f7c2c320..401d20b03fb6d 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -211,9 +211,12 @@ fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_ let (bin_path, lib_path) = get_cc_search_dirs(target, builder); - let compiler = if target == "i686-pc-windows-gnu" { + let compiler = if target == "i686-pc-windows-gnu" || + target == "i686-rust9x-windows-gnu" || + target == "i586-rust9x-windows-gnu" { "i686-w64-mingw32-gcc.exe" - } else if target == "x86_64-pc-windows-gnu" { + } else if target == "x86_64-pc-windows-gnu" || + target == "x86_64-rust9x-windows-gnu" { "x86_64-w64-mingw32-gcc.exe" } else { "gcc.exe" @@ -434,14 +437,14 @@ impl Step for Mingw { fn run(self, builder: &Builder<'_>) -> Option { let target = self.target; - if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker { + if !target.contains("windows-gnu") || !builder.config.dist_include_mingw_linker { return None; } let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple); tarball.set_product_name("Rust MinGW"); - if target.ends_with("pc-windows-gnu") { + if target.ends_with("windows-gnu") { make_win_dist(tarball.image_dir(), target, builder); } else if target.ends_with("pc-windows-gnullvm") { make_win_llvm_dist(tarball.image_dir(), target, builder); @@ -506,7 +509,7 @@ impl Step for Rustc { // anything requiring us to distribute a license, but it's likely the // install will *also* include the rust-mingw package, which also needs // licenses, so to be safe we just include it here in all MinGW packages. - if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker { + if target.contains("windows-gnu") && builder.config.dist_include_mingw_linker { runtime_dll_dist(tarball.image_dir(), target, builder); tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc"); } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index a98b701521273..edc88ed55c73b 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -50,8 +50,11 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ "aarch64v8r-unknown-none-softfloat", "s390x-unknown-none-softfloat", "i586-rust9x-windows-msvc", + "i586-rust9x-windows-gnu", "i686-rust9x-windows-msvc", + "i686-rust9x-windows-gnu", "x86_64-rust9x-windows-msvc", + "x86_64-rust9x-windows-gnu", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index b9a914f53cec1..a539544b0392f 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1299,7 +1299,10 @@ impl Build { // Work around an apparently bad MinGW / GCC optimization, // See: https://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936 - if &*target.triple == "i686-pc-windows-gnu" { + if &*target.triple == "i686-pc-windows-gnu" || + &*target.triple == "i586-rust9x-windows-gnu" || + &*target.triple == "i686-rust9x-windows-gnu" + { base.push("-fno-omit-frame-pointer".into()); } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index afe87614e8c8c..fc90d6de6c3be 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -288,14 +288,12 @@ impl Builder { } // so is rust-mingw if it's available for the target PkgType::RustMingw => { - if host.contains("pc-windows-gnu") { + if host.contains("windows-gnu") { components.push(host_component(pkg)); extensions.extend( TARGETS .iter() - .filter(|&&target| { - target.contains("pc-windows-gnu") && target != host - }) + .filter(|&&target| target.contains("windows-gnu") && target != host) .map(|target| Component::from_pkg(pkg, target)), ); }