diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index c7a599a5749b7..fdd6a761dfa1a 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -174,8 +174,10 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB // UWP apps have API restrictions enforced during Store submissions. // To comply with the Windows App Certification Kit, // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). + // Similarly, apps targeting the Games API partition need to link to the OneCore versions of + // the runtime to ensure they don't use functions that are unavailable in that partition. let t = &sess.target.target; - if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" { + if flavor == LinkerFlavor::Msvc && (t.target_vendor == "uwp" || t.target_vendor == "games") { if let Some(ref tool) = msvc_tool { let original_path = tool.path(); if let Some(ref root_lib_path) = original_path.ancestors().skip(4).next() { @@ -187,7 +189,19 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB }; if let Some(ref a) = arch { let mut arg = OsString::from("/LIBPATH:"); - arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a.to_string())); + if t.target_vendor == "uwp" { + arg.push(format!( + "{}\\lib\\{}\\store", + root_lib_path.display(), + a.to_string() + )); + } else { + arg.push(format!( + "{}\\lib\\onecore\\{}", + root_lib_path.display(), + a.to_string() + )); + } cmd.arg(&arg); } else { warn!("arch is not supported"); diff --git a/src/librustc_target/spec/aarch64_games_windows_msvc.rs b/src/librustc_target/spec/aarch64_games_windows_msvc.rs new file mode 100644 index 0000000000000..5f57c6504773f --- /dev/null +++ b/src/librustc_target/spec/aarch64_games_windows_msvc.rs @@ -0,0 +1,25 @@ +use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_games_msvc_base::opts(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + base.features = "+neon,+fp-armv8".to_string(); + + // FIXME: this shouldn't be panic=abort, it should be panic=unwind + base.panic_strategy = PanicStrategy::Abort; + + Ok(Target { + llvm_target: "aarch64-games-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "games".to_string(), + linker_flavor: LinkerFlavor::Msvc, + options: base, + }) +} diff --git a/src/librustc_target/spec/i686_games_windows_msvc.rs b/src/librustc_target/spec/i686_games_windows_msvc.rs new file mode 100644 index 0000000000000..d6b3ee949ac3d --- /dev/null +++ b/src/librustc_target/spec/i686_games_windows_msvc.rs @@ -0,0 +1,31 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_games_msvc_base::opts(); + base.cpu = "pentium4".to_string(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + // Mark all dynamic libraries and executables as compatible with the larger 4GiB address + // space available to x86 Windows binaries on x86_64. + base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/LARGEADDRESSAWARE".to_string()); + + // Ensure the linker will only produce an image if it can also produce a table of + // the image's safe exception handlers. + // https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers + base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/SAFESEH".to_string()); + + Ok(Target { + llvm_target: "i686-games-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(), + arch: "x86".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "games".to_string(), + linker_flavor: LinkerFlavor::Msvc, + options: base, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index f08634cc770e0..c65d5aa382dee 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -70,6 +70,7 @@ mod uefi_base; mod vxworks_base; mod wasm32_base; mod windows_base; +mod windows_games_msvc_base; mod windows_msvc_base; mod windows_uwp_base; mod windows_uwp_msvc_base; @@ -452,10 +453,13 @@ supported_targets! { ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc), + ("aarch64-games-windows-msvc", aarch64_games_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc), + ("x86_64-games-windows-msvc", x86_64_games_windows_msvc), ("i686-pc-windows-msvc", i686_pc_windows_msvc), ("i686-uwp-windows-msvc", i686_uwp_windows_msvc), + ("i686-games-windows-msvc", i686_games_windows_msvc), ("i586-pc-windows-msvc", i586_pc_windows_msvc), ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc), diff --git a/src/librustc_target/spec/windows_games_msvc_base.rs b/src/librustc_target/spec/windows_games_msvc_base.rs new file mode 100644 index 0000000000000..1153d87d2f8cf --- /dev/null +++ b/src/librustc_target/spec/windows_games_msvc_base.rs @@ -0,0 +1,36 @@ +use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert( + LinkerFlavor::Msvc, + vec!["/NOLOGO".to_string(), "/NXCOMPAT".to_string(), "onecore.lib".to_string()], + ); + + TargetOptions { + function_sections: true, + dynamic_linking: true, + executables: true, + dll_prefix: String::new(), + dll_suffix: ".dll".to_string(), + exe_suffix: ".exe".to_string(), + staticlib_prefix: String::new(), + staticlib_suffix: ".lib".to_string(), + target_family: Some("windows".to_string()), + is_like_windows: true, + is_like_msvc: true, + // set VSLANG to 1033 can prevent link.exe from using + // language packs, and avoid generating Non-UTF-8 error + // messages if a link error occurred. + link_env: vec![("VSLANG".to_string(), "1033".to_string())], + pre_link_args: args, + crt_static_allows_dylibs: true, + crt_static_respected: true, + abi_return_struct_as_int: true, + emit_debug_gdb_scripts: false, + requires_uwtable: true, + + ..Default::default() + } +} diff --git a/src/librustc_target/spec/x86_64_games_windows_msvc.rs b/src/librustc_target/spec/x86_64_games_windows_msvc.rs new file mode 100644 index 0000000000000..fbce8719540bf --- /dev/null +++ b/src/librustc_target/spec/x86_64_games_windows_msvc.rs @@ -0,0 +1,22 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_games_msvc_base::opts(); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + Ok(Target { + llvm_target: "x86_64-games-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "games".to_string(), + linker_flavor: LinkerFlavor::Msvc, + options: base, + }) +} diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 4d377341be30f..79d30456612e6 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -151,9 +151,6 @@ pub const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003; pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001; pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; -pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; -pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; - // Note that these are not actually HANDLEs, just values to pass to GetStdHandle pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; @@ -638,6 +635,34 @@ if #[cfg(not(target_vendor = "uwp"))] { pub type PVECTORED_EXCEPTION_HANDLER = extern "system" fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; + pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; + + extern "system" { + pub fn SetHandleInformation(hObject: HANDLE, + dwMask: DWORD, + dwFlags: DWORD) -> BOOL; + pub fn AddVectoredExceptionHandler(FirstHandler: ULONG, + VectoredHandler: PVECTORED_EXCEPTION_HANDLER) + -> LPVOID; + pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, + lpTargetFileName: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES) + -> BOOL; + } +} +} + +// Functions forbidden when targeting the Games API partition +cfg_if::cfg_if! { +if #[cfg(not(target_vendor = "games"))] { + pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; + pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; +} +} + +// Functions forbidden when targeting UWP or the Games API partition +cfg_if::cfg_if! { +if #[cfg(not(any(target_vendor = "uwp", target_vendor = "games")))] { #[repr(C)] #[derive(Copy, Clone)] pub struct CONSOLE_READCONSOLE_CONTROL { @@ -666,8 +691,6 @@ if #[cfg(not(target_vendor = "uwp"))] { pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; pub type LPCVOID = *const c_void; - pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; - pub const TOKEN_READ: DWORD = 0x20008; extern "system" { @@ -688,33 +711,24 @@ if #[cfg(not(target_vendor = "uwp"))] { pub fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; - // Allowed but unused by UWP + // Allowed but unused by UWP and Games pub fn OpenProcessToken(ProcessHandle: HANDLE, DesiredAccess: DWORD, TokenHandle: *mut HANDLE) -> BOOL; pub fn GetUserProfileDirectoryW(hToken: HANDLE, lpProfileDir: LPWSTR, lpcchSize: *mut DWORD) -> BOOL; + // Allowed but unused by Games pub fn GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) -> BOOL; - pub fn SetHandleInformation(hObject: HANDLE, - dwMask: DWORD, - dwFlags: DWORD) -> BOOL; - pub fn AddVectoredExceptionHandler(FirstHandler: ULONG, - VectoredHandler: PVECTORED_EXCEPTION_HANDLER) - -> LPVOID; - pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, - lpTargetFileName: LPCWSTR, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES) - -> BOOL; } } } -// UWP specific functions & types +// UWP and Games specific functions & types cfg_if::cfg_if! { -if #[cfg(target_vendor = "uwp")] { +if #[cfg(any(target_vendor = "uwp", target_vendor = "games"))] { pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; #[repr(C)] @@ -732,7 +746,7 @@ if #[cfg(target_vendor = "uwp")] { lpFileInformation: LPVOID, dwBufferSize: DWORD) -> BOOL; pub fn BCryptGenRandom(hAlgorithm: LPVOID, pBuffer: *mut u8, - cbBuffer: ULONG, dwFlags: ULONG) -> LONG; + cbBuffer: ULONG, dwFlags: ULONG) -> LONG; } } } @@ -1019,6 +1033,7 @@ extern "system" { compat_fn! { kernel32: + #[cfg(not(target_vendor = "games"))] pub fn CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, _lpTargetFileName: LPCWSTR, _dwFlags: DWORD) -> BOOLEAN { diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index e9c84c4e7c9cb..eda677b53ccc6 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -322,7 +322,7 @@ impl File { Ok(()) } - #[cfg(not(target_vendor = "uwp"))] + #[cfg(not(any(target_vendor = "uwp", target_vendor = "games")))] pub fn file_attr(&self) -> io::Result { unsafe { let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed(); @@ -350,7 +350,7 @@ impl File { } } - #[cfg(target_vendor = "uwp")] + #[cfg(any(target_vendor = "uwp", target_vendor = "games"))] pub fn file_attr(&self) -> io::Result { unsafe { let mut info: c::FILE_BASIC_INFO = mem::zeroed(); @@ -753,6 +753,7 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { symlink_inner(src, dst, false) } +#[cfg(not(target_vendor = "games"))] pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { let src = to_u16s(src)?; let dst = to_u16s(dst)?; @@ -780,6 +781,14 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { Ok(()) } +#[cfg(target_vendor = "games")] +pub fn symlink_inner(_: &Path, _: &Path, _: bool) -> io::Result<()> { + return Err(io::Error::new( + io::ErrorKind::Other, + "symbolic links are not supported on the Games API partition", + )); +} + #[cfg(not(target_vendor = "uwp"))] pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = to_u16s(src)?; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index b004cd19020f8..fb5fec8f90ce0 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -38,14 +38,18 @@ pub mod thread; pub mod thread_local; pub mod time; cfg_if::cfg_if! { - if #[cfg(not(target_vendor = "uwp"))] { - pub mod stdio; - pub mod stack_overflow; - } else { + if #[cfg(target_vendor = "uwp")] { pub mod stdio_uwp; pub mod stack_overflow_uwp; pub use self::stdio_uwp as stdio; pub use self::stack_overflow_uwp as stack_overflow; + } else if #[cfg(target_vendor = "games")] { + pub mod stdio_uwp; + pub mod stack_overflow; + pub use self::stdio_uwp as stdio; + } else { + pub mod stdio; + pub mod stack_overflow; } } diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index e7fa61dd0f6b9..74c337eefc70a 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -284,7 +284,7 @@ pub fn temp_dir() -> PathBuf { super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap() } -#[cfg(not(target_vendor = "uwp"))] +#[cfg(not(any(target_vendor = "uwp", target_vendor = "games")))] fn home_dir_crt() -> Option { unsafe { use crate::sys::handle::Handle; @@ -309,7 +309,7 @@ fn home_dir_crt() -> Option { } } -#[cfg(target_vendor = "uwp")] +#[cfg(any(target_vendor = "uwp", target_vendor = "games"))] fn home_dir_crt() -> Option { None } diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs index 87ea416bf675a..917cb11376fcb 100644 --- a/src/libstd/sys/windows/rand.rs +++ b/src/libstd/sys/windows/rand.rs @@ -2,7 +2,7 @@ use crate::io; use crate::mem; use crate::sys::c; -#[cfg(not(target_vendor = "uwp"))] +#[cfg(not(any(target_vendor = "uwp", target_vendor = "games")))] pub fn hashmap_random_keys() -> (u64, u64) { let mut v = (0, 0); let ret = @@ -13,7 +13,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { v } -#[cfg(target_vendor = "uwp")] +#[cfg(any(target_vendor = "uwp", target_vendor = "games"))] pub fn hashmap_random_keys() -> (u64, u64) { use crate::ptr;