From 48c6ae0611ec6fb4094a24610982ddefde16e20f Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sun, 18 Dec 2022 09:54:54 +0530 Subject: Add Minimal Std implementation for UEFI Implemented modules: 1. alloc 2. os_str 3. env 4. math Tracking Issue: https://github.com/rust-lang/rust/issues/100499 API Change Proposal: https://github.com/rust-lang/libs-team/issues/87 This was originally part of https://github.com/rust-lang/rust/pull/100316. Since that PR was becoming too unwieldy and cluttered, and with suggestion from @dvdhrm, I have extracted a minimal std implementation to this PR. Signed-off-by: Ayush Singh --- compiler/rustc_codegen_ssa/src/base.rs | 35 +++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index cd19885faa0..4753f125540 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -420,9 +420,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( rust_main_def_id: DefId, entry_type: EntryFnType, ) -> Bx::Function { - // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, - // depending on whether the target needs `argc` and `argv` to be passed in. - let llfty = if cx.sess().target.main_needs_argc_argv { + // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or + // `Status efi_main(Handle hd, SystemTable *st)` depending on the target. + let llfty = if cx.sess().target.os.contains("uefi") { + cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize()) + } else if cx.sess().target.main_needs_argc_argv { cx.type_func(&[cx.type_int(), cx.type_ptr()], cx.type_int()) } else { cx.type_func(&[], cx.type_int()) @@ -485,8 +487,12 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; let result = bx.call(start_ty, None, None, start_fn, &args, None); - let cast = bx.intcast(result, cx.type_int(), true); - bx.ret(cast); + if cx.sess().target.os.contains("uefi") { + bx.ret(result); + } else { + let cast = bx.intcast(result, cx.type_int(), true); + bx.ret(cast); + } llfn } @@ -497,7 +503,18 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, bx: &mut Bx, ) -> (Bx::Value, Bx::Value) { - if cx.sess().target.main_needs_argc_argv { + if cx.sess().target.os.contains("uefi") { + // Params for UEFI + let param_handle = bx.get_param(0); + let param_system_table = bx.get_param(1); + let arg_argc = bx.const_int(cx.type_isize(), 2); + let arg_argv = bx.alloca(cx.type_array(cx.type_i8p(), 2), Align::ONE); + bx.store(param_handle, arg_argv, Align::ONE); + let arg_argv_el1 = + bx.gep(cx.type_ptr_to(cx.type_i8()), arg_argv, &[bx.const_int(cx.type_int(), 1)]); + bx.store(param_system_table, arg_argv_el1, Align::ONE); + (arg_argc, arg_argv) + } else if cx.sess().target.main_needs_argc_argv { // Params from native `main()` used as args for rust start function let param_argc = bx.get_param(0); let param_argv = bx.get_param(1); @@ -549,7 +566,11 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option { use rustc_middle::middle::dependency_format::Linkage; list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); - if any_dynamic_crate { None } else { tcx.allocator_kind(()) } + if any_dynamic_crate { + None + } else { + tcx.allocator_kind(()) + } } pub fn codegen_crate( -- cgit 1.4.1-3-g733a5 From c7e5f3ca085c3adfd285a6d41080ff65a6299bc9 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sun, 21 May 2023 14:26:59 +0530 Subject: Rebase to master - Update Example - Add thread_parking to sys::uefi - Fix unsafe in unsafe errors - Improve docs - Improve os/exit - Some asserts - Switch back to atomics Signed-off-by: Ayush Singh --- compiler/rustc_codegen_ssa/src/base.rs | 13 ++---- library/panic_abort/src/lib.rs | 2 +- library/std/build.rs | 1 - library/std/src/lib.rs | 1 + library/std/src/os/mod.rs | 1 - library/std/src/os/uefi/env.rs | 54 +++++++++++++--------- library/std/src/sys/uefi/helpers.rs | 14 +++--- library/std/src/sys/uefi/mod.rs | 36 +++++++++++---- library/std/src/sys/uefi/os.rs | 42 +++++++++++++---- src/doc/rustc/src/platform-support/unknown-uefi.md | 10 ++-- 10 files changed, 111 insertions(+), 63 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 4753f125540..6c51dffedbf 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -421,7 +421,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( entry_type: EntryFnType, ) -> Bx::Function { // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or - // `Status efi_main(Handle hd, SystemTable *st)` depending on the target. + // `usize efi_main(void *handle, void *system_table)` depending on the target. let llfty = if cx.sess().target.os.contains("uefi") { cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize()) } else if cx.sess().target.main_needs_argc_argv { @@ -508,10 +508,9 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let param_handle = bx.get_param(0); let param_system_table = bx.get_param(1); let arg_argc = bx.const_int(cx.type_isize(), 2); - let arg_argv = bx.alloca(cx.type_array(cx.type_i8p(), 2), Align::ONE); + let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE); bx.store(param_handle, arg_argv, Align::ONE); - let arg_argv_el1 = - bx.gep(cx.type_ptr_to(cx.type_i8()), arg_argv, &[bx.const_int(cx.type_int(), 1)]); + let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]); bx.store(param_system_table, arg_argv_el1, Align::ONE); (arg_argc, arg_argv) } else if cx.sess().target.main_needs_argc_argv { @@ -566,11 +565,7 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option { use rustc_middle::middle::dependency_format::Linkage; list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); - if any_dynamic_crate { - None - } else { - tcx.allocator_kind(()) - } + if any_dynamic_crate { None } else { tcx.allocator_kind(()) } } pub fn codegen_crate( diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index bc0d7287be5..6e097e2caf2 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -44,7 +44,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { } } else if #[cfg(any(target_os = "hermit", all(target_vendor = "fortanix", target_env = "sgx"), - target_os = "xous" + target_os = "xous", target_os = "uefi", ))] { unsafe fn abort() -> ! { diff --git a/library/std/build.rs b/library/std/build.rs index 1c32b425650..36516978b7a 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -52,7 +52,6 @@ fn main() { // - mipsel-sony-psp // - nvptx64-nvidia-cuda // - arch=avr - // - tvos (aarch64-apple-tvos, x86_64-apple-tvos) // - JSON targets // - Any new targets that have not been explicitly added above. println!("cargo:rustc-cfg=feature=\"restricted-std\""); diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b572347019c..5e3249655b8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -263,6 +263,7 @@ #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] // // Language features: +// tidy-alphabetical-start #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index d1a73503899..41aa0472f52 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -142,7 +142,6 @@ pub mod solid; #[cfg(target_os = "tvos")] #[path = "ios/mod.rs"] pub(crate) mod tvos; -#[cfg(target_os = "uefi")] #[cfg(any(target_os = "uefi", doc))] pub mod uefi; #[cfg(target_os = "vita")] diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs index 4dd090e22c6..5d082e7c113 100644 --- a/library/std/src/os/uefi/env.rs +++ b/library/std/src/os/uefi/env.rs @@ -2,23 +2,22 @@ #![unstable(feature = "uefi_std", issue = "100499")] -use crate::{cell::Cell, ffi::c_void, ptr::NonNull}; +use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; +use crate::{ffi::c_void, ptr::NonNull}; -// Since UEFI is single-threaded, making the global variables thread local should be safe. -thread_local! { - // Flag to check if BootServices are still valid. - // Start with assuming that they are not available - static BOOT_SERVICES_FLAG: Cell = Cell::new(false); - // Position 0 = SystemTable - // Position 1 = ImageHandle - static GLOBALS: Cell, NonNull)>> = Cell::new(None); -} +static SYSTEM_TABLE: AtomicPtr = AtomicPtr::new(crate::ptr::null_mut()); +static IMAGE_HANDLE: AtomicPtr = AtomicPtr::new(crate::ptr::null_mut()); +// Flag to check if BootServices are still valid. +// Start with assuming that they are not available +static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false); /// Initializes the global System Table and Image Handle pointers. /// /// The standard library requires access to the UEFI System Table and the Application Image Handle /// to operate. Those are provided to UEFI Applications via their application entry point. By /// calling `init_globals()`, those pointers are retained by the standard library for future use. +/// Thus this function must be called before any of the standard library services are used. +/// /// The pointers are never exposed to any entity outside of this application and it is guaranteed /// that, once the application exited, these pointers are never dereferenced again. /// @@ -26,9 +25,26 @@ thread_local! { /// application. In particular, UEFI Boot Services must not be exited while an application with the /// standard library is loaded. /// -/// This function must not be called more than once. -pub unsafe fn init_globals(handle: NonNull, system_table: NonNull) { - GLOBALS.set(Some((system_table, handle))); +/// # SAFETY +/// Calling this function more than once will panic +pub(crate) unsafe fn init_globals(handle: NonNull, system_table: NonNull) { + IMAGE_HANDLE + .compare_exchange( + crate::ptr::null_mut(), + handle.as_ptr(), + Ordering::Release, + Ordering::Acquire, + ) + .unwrap(); + SYSTEM_TABLE + .compare_exchange( + crate::ptr::null_mut(), + system_table.as_ptr(), + Ordering::Release, + Ordering::Acquire, + ) + .unwrap(); + BOOT_SERVICES_FLAG.store(true, Ordering::Release) } /// Get the SystemTable Pointer. @@ -50,7 +66,7 @@ pub fn image_handle() -> NonNull { /// Get the BootServices Pointer. /// This function also checks if `ExitBootServices` has already been called. pub fn boot_services() -> Option> { - if BOOT_SERVICES_FLAG.get() { + if BOOT_SERVICES_FLAG.load(Ordering::Acquire) { let system_table: NonNull = try_system_table()?.cast(); let boot_services = unsafe { (*system_table.as_ptr()).boot_services }; NonNull::new(boot_services).map(|x| x.cast()) @@ -62,19 +78,15 @@ pub fn boot_services() -> Option> { /// Get the SystemTable Pointer. /// This function is mostly intended for places where panic is not an option pub(crate) fn try_system_table() -> Option> { - GLOBALS.get().map(|x| x.0) + NonNull::new(SYSTEM_TABLE.load(Ordering::Acquire)) } /// Get the SystemHandle Pointer. /// This function is mostly intended for places where panicking is not an option pub(crate) fn try_image_handle() -> Option> { - GLOBALS.get().map(|x| x.1) -} - -pub(crate) fn enable_boot_services() { - BOOT_SERVICES_FLAG.set(true); + NonNull::new(IMAGE_HANDLE.load(Ordering::Acquire)) } pub(crate) fn disable_boot_services() { - BOOT_SERVICES_FLAG.set(false); + BOOT_SERVICES_FLAG.store(false, Ordering::Release) } diff --git a/library/std/src/sys/uefi/helpers.rs b/library/std/src/sys/uefi/helpers.rs index 2e1bcb36944..126661bfc96 100644 --- a/library/std/src/sys/uefi/helpers.rs +++ b/library/std/src/sys/uefi/helpers.rs @@ -60,13 +60,14 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result = - Vec::with_capacity(buf_len / size_of::()); + assert_eq!(buf_len % size_of::(), 0); + let num_of_handles = buf_len / size_of::(); + let mut buf: Vec = Vec::with_capacity(num_of_handles); match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) { Ok(()) => { // This is safe because the call will succeed only if buf_len >= required length. // Also, on success, the `buf_len` is updated with the size of bufferv (in bytes) written - unsafe { buf.set_len(buf_len / size_of::()) }; + unsafe { buf.set_len(num_of_handles) }; Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect()) } Err(e) => Err(e), @@ -114,16 +115,15 @@ pub(crate) fn create_event( ) -> io::Result> { let boot_services: NonNull = boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let mut exit_boot_service_event: r_efi::efi::Event = crate::ptr::null_mut(); + let mut event: r_efi::efi::Event = crate::ptr::null_mut(); let r = unsafe { let create_event = (*boot_services.as_ptr()).create_event; - (create_event)(signal, tpl, handler, context, &mut exit_boot_service_event) + (create_event)(signal, tpl, handler, context, &mut event) }; if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { - NonNull::new(exit_boot_service_event) - .ok_or(const_io_error!(io::ErrorKind::Other, "null protocol")) + NonNull::new(event).ok_or(const_io_error!(io::ErrorKind::Other, "null protocol")) } } diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs index 85d00caf149..9a10395af8e 100644 --- a/library/std/src/sys/uefi/mod.rs +++ b/library/std/src/sys/uefi/mod.rs @@ -12,7 +12,6 @@ //! [`OsStr`]: crate::ffi::OsStr //! [`OsString`]: crate::ffi::OsString -#![deny(unsafe_op_in_unsafe_fn)] pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; @@ -43,6 +42,8 @@ pub mod stdio; pub mod thread; #[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; +#[path = "../unsupported/thread_parking.rs"] +pub mod thread_parking; #[path = "../unsupported/time.rs"] pub mod time; @@ -53,18 +54,17 @@ mod tests; pub type RawOsError = usize; -use crate::cell::Cell; use crate::io as std_io; use crate::os::uefi; use crate::ptr::NonNull; +use crate::sync::atomic::{AtomicPtr, Ordering}; pub mod memchr { pub use core::slice::memchr::{memchr, memrchr}; } -thread_local! { - static EXIT_BOOT_SERVICE_EVENT: Cell>> = Cell::new(None); -} +static EXIT_BOOT_SERVICE_EVENT: AtomicPtr = + AtomicPtr::new(crate::ptr::null_mut()); /// # SAFETY /// - must be called only once during runtime initialization. @@ -75,8 +75,6 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { let image_handle = unsafe { NonNull::new(*argv as *mut crate::ffi::c_void).unwrap() }; let system_table = unsafe { NonNull::new(*argv.add(1) as *mut crate::ffi::c_void).unwrap() }; unsafe { uefi::env::init_globals(image_handle, system_table) }; - // Enable boot services once GLOBALS are initialized - uefi::env::enable_boot_services(); // Register exit boot services handler match helpers::create_event( @@ -86,7 +84,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { crate::ptr::null_mut(), ) { Ok(x) => { - EXIT_BOOT_SERVICE_EVENT.set(Some(x)); + if EXIT_BOOT_SERVICE_EVENT + .compare_exchange( + crate::ptr::null_mut(), + x.as_ptr(), + Ordering::Release, + Ordering::Acquire, + ) + .is_err() + { + abort_internal(); + }; } Err(_) => abort_internal(), } @@ -96,7 +104,9 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { /// this is not guaranteed to run, for example when the program aborts. /// - must be called only once during runtime cleanup. pub unsafe fn cleanup() { - if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() { + if let Some(exit_boot_service_event) = + NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire)) + { let _ = unsafe { helpers::close_event(exit_boot_service_event) }; } } @@ -159,7 +169,9 @@ pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind { } pub fn abort_internal() -> ! { - if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() { + if let Some(exit_boot_service_event) = + NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire)) + { let _ = unsafe { helpers::close_event(exit_boot_service_event) }; } @@ -226,3 +238,7 @@ fn get_random() -> Option<(u64, u64)> { extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) { uefi::env::disable_boot_services(); } + +pub fn is_interrupted(_code: RawOsError) -> bool { + false +} diff --git a/library/std/src/sys/uefi/os.rs b/library/std/src/sys/uefi/os.rs index cd489d8f7f9..e6693db68e6 100644 --- a/library/std/src/sys/uefi/os.rs +++ b/library/std/src/sys/uefi/os.rs @@ -4,15 +4,16 @@ use crate::ffi::{OsStr, OsString}; use crate::fmt; use crate::io; use crate::marker::PhantomData; +use crate::os::uefi; use crate::path::{self, PathBuf}; +use crate::ptr::NonNull; +use r_efi::efi::Status; pub fn errno() -> RawOsError { 0 } pub fn error_string(errno: RawOsError) -> String { - use r_efi::efi::Status; - // Keep the List in Alphabetical Order // The Messages are taken from UEFI Specification Appendix D - Status Codes match r_efi::efi::Status::from_usize(errno) { @@ -160,12 +161,7 @@ impl fmt::Display for JoinPathsError { } } -impl StdError for JoinPathsError { - #[allow(deprecated)] - fn description(&self) -> &str { - "not supported on this platform yet" - } -} +impl StdError for JoinPathsError {} pub fn current_exe() -> io::Result { unsupported() @@ -173,6 +169,14 @@ pub fn current_exe() -> io::Result { pub struct Env(!); +impl Env { + // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self(inner) = self; + match *inner {} + } +} + impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { @@ -180,6 +184,13 @@ impl Iterator for Env { } } +impl fmt::Debug for Env { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self(inner) = self; + match *inner {} + } +} + pub fn env() -> Env { panic!("not supported on this platform") } @@ -204,7 +215,20 @@ pub fn home_dir() -> Option { None } -pub fn exit(_code: i32) -> ! { +pub fn exit(code: i32) -> ! { + if let (Some(boot_services), Some(handle)) = + (uefi::env::boot_services(), uefi::env::try_image_handle()) + { + let boot_services: NonNull = boot_services.cast(); + let _ = unsafe { + ((*boot_services.as_ptr()).exit)( + handle.as_ptr(), + Status::from_usize(code as usize), + 0, + crate::ptr::null_mut(), + ) + }; + } crate::intrinsics::abort() } diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 019f030eb1c..68cd7fae319 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -277,7 +277,9 @@ cargo +custom build --target x86_64-unknown-uefi ``` ```rust,ignore (platform-specific) -use r_efi::efi; +#![feature(uefi_std)] + +use r_efi::{efi, protocols::simple_text_output}; use std::{ ffi::OsString, os::uefi::{env, ffi::OsStrExt} @@ -290,7 +292,7 @@ pub fn main() { let r = unsafe { let con_out: *mut simple_text_output::Protocol = (*st).con_out; - let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) = (*con_out).output_string; + let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) -> efi::Status = (*con_out).output_string; output_string(con_out, s.as_ptr() as *mut efi::Char16) }; assert!(!r.is_error()) @@ -298,6 +300,6 @@ pub fn main() { ``` ### BootServices -The current implementation of std make `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses. +The current implementation of std makes `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses. -Note: It should be noted that it is upto the user to drop all allocated memory before `ExitBootServices` is called. +Note: It should be noted that it is up to the user to drop all allocated memory before `ExitBootServices` is called. -- cgit 1.4.1-3-g733a5 From 699240567446ba9d794b7e4883831ae13aadac59 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 19 Sep 2023 19:20:22 +0000 Subject: Tolerate non-ptr indirect scalars in codegen. --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 9205acc527e..63de6a72072 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -156,7 +156,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - let val = read_scalar(Size::ZERO, size, s, bx.type_ptr()); + let val = read_scalar(Size::ZERO, size, s, bx.backend_type(layout)); OperandRef { val: OperandValue::Immediate(val), layout } } Abi::ScalarPair( -- cgit 1.4.1-3-g733a5 From ac0683b78310bba9c3c601cfd81bbda4a10be322 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 23 Sep 2023 09:35:44 +0000 Subject: Use correct offset when codegening mir::Const::Indirect. --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 63de6a72072..0ab2b7ecd9c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -135,15 +135,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { assert_eq!(alloc_align, layout.align.abi); let read_scalar = |start, size, s: abi::Scalar, ty| { - let val = alloc - .0 - .read_scalar( - bx, - alloc_range(start, size), - /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), - ) - .unwrap(); - bx.scalar_to_backend(val, s, ty) + match alloc.0.read_scalar( + bx, + alloc_range(start, size), + /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), + ) { + Ok(val) => bx.scalar_to_backend(val, s, ty), + Err(_) => bx.const_poison(ty), + } }; // It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point. @@ -156,7 +155,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - let val = read_scalar(Size::ZERO, size, s, bx.backend_type(layout)); + let val = read_scalar(offset, size, s, bx.backend_type(layout)); OperandRef { val: OperandValue::Immediate(val), layout } } Abi::ScalarPair( @@ -164,10 +163,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { b @ abi::Scalar::Initialized { .. }, ) => { let (a_size, b_size) = (a.size(bx), b.size(bx)); - let b_offset = a_size.align_to(b.align(bx).abi); + let b_offset = (offset + a_size).align_to(b.align(bx).abi); assert!(b_offset.bytes() > 0); let a_val = read_scalar( - Size::ZERO, + offset, a_size, a, bx.scalar_pair_element_backend_type(layout, 0, true), -- cgit 1.4.1-3-g733a5 From 91544e6a937b4c2c7181578533e6d10991559c14 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Sat, 9 Sep 2023 14:00:24 +0200 Subject: Pass name of object file to LLVM so it can correctly emit S_OBJNAME --- .../src/back/owned_target_machine.rs | 2 ++ compiler/rustc_codegen_llvm/src/back/write.rs | 19 ++++++++++++++----- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_codegen_ssa/src/back/write.rs | 9 ++++++++- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 4 ++++ 5 files changed, 29 insertions(+), 6 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index 707af1046bd..36484c3c3fc 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -37,6 +37,7 @@ impl OwnedTargetMachine { relax_elf_relocations: bool, use_init_array: bool, split_dwarf_file: &CStr, + output_obj_file: &CStr, debug_info_compression: &CStr, force_emulated_tls: bool, args_cstr_buff: &[u8], @@ -68,6 +69,7 @@ impl OwnedTargetMachine { relax_elf_relocations, use_init_array, split_dwarf_file.as_ptr(), + output_obj_file.as_ptr(), debug_info_compression.as_ptr(), force_emulated_tls, args_cstr_buff.as_ptr() as *const c_char, diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 9fb20c02c6b..c778a6e017f 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -100,7 +100,7 @@ pub fn write_output_file<'ll>( } pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine { - let config = TargetMachineFactoryConfig { split_dwarf_file: None }; + let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None }; // Can't use query system here quite yet because this function is invoked before the query // system/tcx is set up. let features = llvm_util::global_llvm_features(sess, false); @@ -118,7 +118,11 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMach } else { None }; - let config = TargetMachineFactoryConfig { split_dwarf_file }; + + let output_obj_file = + Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(mod_name))); + let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }; + target_machine_factory( &tcx.sess, tcx.backend_optimization_level(()), @@ -256,9 +260,13 @@ pub fn target_machine_factory( let debuginfo_compression = SmallCStr::new(&debuginfo_compression); Arc::new(move |config: TargetMachineFactoryConfig| { - let split_dwarf_file = - path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0; - let split_dwarf_file = CString::new(split_dwarf_file.to_str().unwrap()).unwrap(); + let path_to_cstring_helper = |path: Option| -> CString { + let path = path_mapping.map_prefix(path.unwrap_or_default()).0; + CString::new(path.to_str().unwrap()).unwrap() + }; + + let split_dwarf_file = path_to_cstring_helper(config.split_dwarf_file); + let output_obj_file = path_to_cstring_helper(config.output_obj_file); OwnedTargetMachine::new( &triple, @@ -279,6 +287,7 @@ pub fn target_machine_factory( relax_elf_relocations, use_init_array, &split_dwarf_file, + &output_obj_file, &debuginfo_compression, force_emulated_tls, &args_cstr_buff, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 36303b08107..a038b3af03d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2133,6 +2133,7 @@ extern "C" { RelaxELFRelocations: bool, UseInitArray: bool, SplitDwarfFile: *const c_char, + OutputObjFile: *const c_char, DebugInfoCompression: *const c_char, ForceEmulatedTls: bool, ArgsCstrBuff: *const c_char, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 3bf98c46dea..f192747c8ab 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -286,6 +286,10 @@ pub struct TargetMachineFactoryConfig { /// so the path to the dwarf object has to be provided when we create the target machine. /// This can be ignored by backends which do not need it for their Split DWARF support. pub split_dwarf_file: Option, + + /// The name of the output object file. Used for setting OutputFilenames in target options + /// so that LLVM can emit the CodeView S_OBJNAME record in pdb files + pub output_obj_file: Option, } impl TargetMachineFactoryConfig { @@ -302,7 +306,10 @@ impl TargetMachineFactoryConfig { } else { None }; - TargetMachineFactoryConfig { split_dwarf_file } + + let output_obj_file = + Some(cgcx.output_filenames.temp_path(OutputType::Object, Some(module_name))); + TargetMachineFactoryConfig { split_dwarf_file, output_obj_file } } } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 461b5290e69..b729c40228b 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -416,6 +416,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool RelaxELFRelocations, bool UseInitArray, const char *SplitDwarfFile, + const char *OutputObjFile, const char *DebugInfoCompression, bool ForceEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { @@ -448,6 +449,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( if (SplitDwarfFile) { Options.MCOptions.SplitDwarfFile = SplitDwarfFile; } + if (OutputObjFile) { + Options.ObjectFilenameForDebug = OutputObjFile; + } #if LLVM_VERSION_GE(16, 0) if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { Options.CompressDebugSections = DebugCompressionType::Zlib; -- cgit 1.4.1-3-g733a5 From 3c52a3e280a5fd1e8e4b48a5ec349aa00dcd859c Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 25 Sep 2023 15:46:38 +0200 Subject: subst -> instantiate --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../rustc_borrowck/src/diagnostics/region_name.rs | 4 ++-- compiler/rustc_borrowck/src/region_infer/mod.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_borrowck/src/universal_regions.rs | 5 ++--- .../scripts/filter_profile.rs | 6 +++--- compiler/rustc_codegen_cranelift/src/common.rs | 2 +- .../src/debuginfo/create_scope_map.rs | 2 +- compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 +- .../rustc_const_eval/src/interpret/eval_context.rs | 2 +- compiler/rustc_const_eval/src/interpret/util.rs | 5 +++-- .../rustc_const_eval/src/transform/validate.rs | 4 ++-- .../rustc_error_codes/src/error_codes/E0038.md | 7 +++---- compiler/rustc_hir_analysis/src/astconv/bounds.rs | 2 +- .../rustc_hir_analysis/src/astconv/generics.rs | 17 +++++++-------- compiler/rustc_hir_analysis/src/astconv/mod.rs | 4 ++-- compiler/rustc_middle/src/ty/instance.rs | 12 +++++------ .../src/ty/normalize_erasing_regions.rs | 24 ++++++---------------- compiler/rustc_mir_transform/src/inline.rs | 21 +++++++++++-------- compiler/rustc_mir_transform/src/inline/cycle.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_monomorphize/src/partitioning.rs | 2 +- compiler/rustc_monomorphize/src/util.rs | 4 ++-- .../src/methods/unnecessary_to_owned.rs | 4 ++-- 25 files changed, 66 insertions(+), 75 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5b172b863ab..85ab5e7223b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1664,7 +1664,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime.ident, )); - // Now make an arg that we can use for the substs of the opaque tykind. + // Now make an arg that we can use for the generic params of the opaque tykind. let id = self.next_node_id(); let lifetime_arg = self.new_named_lifetime_with_res(id, lifetime.ident, res); let duplicated_lifetime_def_id = self.local_def_id(duplicated_lifetime_node_id); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 30b47d076e2..dc304cd7605 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -27,7 +27,7 @@ pub(crate) struct RegionName { /// This helps to print the right kinds of diagnostics. #[derive(Debug, Clone)] pub(crate) enum RegionNameSource { - /// A bound (not free) region that was substituted at the def site (not an HRTB). + /// A bound (not free) region that was instantiated at the def site (not an HRTB). NamedEarlyBoundRegion(Span), /// A free region that the user has a name (`'a`) for. NamedFreeRegion(Span), @@ -619,7 +619,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // programs, so we need to use delay_span_bug here. See #82126. self.infcx.tcx.sess.delay_span_bug( hir_arg.span(), - format!("unmatched subst and hir arg: found {kind:?} vs {hir_arg:?}"), + format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"), ); } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 1049e7a8bbe..852935676b6 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2250,7 +2250,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { // Query canonicalization can create local superuniverses (for example in - // `InferCtx::query_response_substitution_guess`), but they don't have an associated + // `InferCtx::query_response_instantiation_guess`), but they don't have an associated // `UniverseInfo` explaining why they were created. // This can cause ICEs if these causes are accessed in diagnostics, for example in issue // #114907 where this happens via liveness and dropck outlives results. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index aa750dd0169..9b952f3fe36 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } pub(super) fn register_predefined_opaques_in_new_solver(&mut self) { - // OK to use the identity substitutions for each opaque type key, since + // OK to use the identity arguments for each opaque type key, since // we remap opaques from HIR typeck back to their definition params. let opaques: Vec<_> = self .infcx diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index e00299bad66..af437f36b9f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -639,10 +639,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); - let subst_mapping = - iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); + let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); - UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static } + UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static } } fn compute_inputs_and_output( diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index f782671fe36..03912b18ea5 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs @@ -100,9 +100,9 @@ fn main() -> Result<(), Box> { stack = &stack[..index + ENCODE_METADATA.len()]; } - const SUBST_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::::subst_and_normalize_erasing_regions"; - if let Some(index) = stack.find(SUBST_AND_NORMALIZE_ERASING_REGIONS) { - stack = &stack[..index + SUBST_AND_NORMALIZE_ERASING_REGIONS.len()]; + const INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::::instantiate_and_normalize_erasing_regions"; + if let Some(index) = stack.find(INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS) { + stack = &stack[..index + INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS.len()]; } const NORMALIZE_ERASING_LATE_BOUND_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::::normalize_erasing_late_bound_regions"; diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index ec2da39398b..359b430b4e5 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -359,7 +359,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { where T: TypeFoldable> + Copy, { - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 5ca2942ac4e..aff764f0224 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -90,7 +90,7 @@ fn make_mir_scope<'ll, 'tcx>( Some((callee, _)) => { // FIXME(eddyb) this would be `self.monomorphize(&callee)` // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. - let callee = cx.tcx.subst_and_normalize_erasing_regions( + let callee = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(callee), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index c862acdc7de..30cc9ea9b82 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -529,7 +529,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if let Some(impl_def_id) = cx.tcx.impl_of_method(instance.def_id()) { // If the method does *not* belong to a trait, proceed if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { - let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions( + let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), cx.tcx.type_of(impl_def_id), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 1e905a7c78e..a61018f9870 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { T: Copy + TypeFoldable>, { debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.cx.tcx(), ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 7c743a21d93..94a5cc67d31 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -569,7 +569,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> Result { frame .instance - .try_subst_mir_and_normalize_erasing_regions( + .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, self.param_env, ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index b3319442388..eb639ded70f 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::{ }; use std::ops::ControlFlow; -/// Checks whether a type contains generic parameters which require substitution. +/// Checks whether a type contains generic parameters which must be instantiated. /// /// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization /// types may be "concrete enough" even though they still contain generic parameters in @@ -43,7 +43,8 @@ where .try_into() .expect("more generic parameters than can fit into a `u32`"); // Only recurse when generic parameters in fns, closures and generators - // are used and require substitution. + // are used and have to be instantiated. + // // Just in case there are closures or generators within this subst, // recurse. if unused_params.is_used(index) && subst.has_param() { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 2f5f2ad6534..0d8733070a4 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -558,8 +558,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } -/// A faster version of the validation pass that only checks those things which may break when apply -/// generic substitutions. +/// A faster version of the validation pass that only checks those things which may break when +/// instantiating any generic parameters. pub fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, mir_phase: MirPhase, diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index 584b78554ef..8f8eabb1519 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -162,14 +162,13 @@ fn foo(x: T) { ``` The machine code for `foo::()`, `foo::()`, `foo::()`, or any -other type substitution is different. Hence the compiler generates the +other instantiation is different. Hence the compiler generates the implementation on-demand. If you call `foo()` with a `bool` parameter, the compiler will only generate code for `foo::()`. When we have additional type parameters, the number of monomorphized implementations the compiler generates does not grow drastically, since the compiler will only generate an -implementation if the function is called with unparameterized substitutions -(i.e., substitutions where none of the substituted types are themselves -parameterized). +implementation if the function is called with fully concrete arguments +(i.e., arguments which do not contain any generic parameters). However, with trait objects we have to make a table containing _every_ object that implements the trait. Now, if it has type parameters, we need to add diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index ba152cd48de..21611e9c586 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -427,7 +427,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let bound_vars = tcx.late_bound_vars(binding.hir_id); ty::Binder::bind_with_vars(subst_output, bound_vars) } else { - // Include substitutions for generic parameters of associated types + // Append the generic arguments of the associated type to the `trait_ref`. candidate.map_bound(|trait_ref| { let ident = Ident::new(assoc_item.name, binding.item_name.span); let item_segment = hir::PathSegment { diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 1372cc896be..e3621ef933a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -139,22 +139,22 @@ fn generic_arg_mismatch_err( err.emit() } -/// Creates the relevant generic argument substitutions +/// Creates the relevant generic arguments /// corresponding to a set of generic parameters. This is a /// rather complex function. Let us try to explain the role /// of each of its parameters: /// -/// To start, we are given the `def_id` of the thing we are -/// creating the substitutions for, and a partial set of -/// substitutions `parent_args`. In general, the substitutions -/// for an item begin with substitutions for all the "parents" of +/// To start, we are given the `def_id` of the thing whose generic +/// parameters we are instantiating, and a partial set of +/// arguments `parent_args`. In general, the generic arguments +/// for an item begin with arguments for all the "parents" of /// that item -- e.g., for a method it might include the /// parameters from the impl. /// /// Therefore, the method begins by walking down these parents, /// starting with the outermost parent and proceed inwards until /// it reaches `def_id`. For each parent `P`, it will check `parent_args` -/// first to see if the parent's substitutions are listed in there. If so, +/// first to see if the parent's arguments are listed in there. If so, /// we can append those and move on. Otherwise, it invokes the /// three callback functions: /// @@ -188,7 +188,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( stack.push((def_id, parent_defs)); } - // We manually build up the substitution, rather than using convenience + // We manually build up the generic arguments, rather than using convenience // methods in `subst.rs`, so that we can iterate over the arguments and // parameters in lock-step linearly, instead of trying to match each pair. let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); @@ -196,7 +196,8 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( while let Some((def_id, defs)) = stack.pop() { let mut params = defs.params.iter().peekable(); - // If we have already computed substitutions for parents, we can use those directly. + // If we have already computed the generic arguments for parents, + // we can use those directly. while let Some(¶m) = params.peek() { if let Some(&kind) = parent_args.get(param.index as usize) { args.push(kind); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 106cd223d30..bb2e4447d4d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -289,7 +289,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`, - /// returns an appropriate set of substitutions for this particular reference to `I`. + /// returns an appropriate set of generic arguments for this particular reference to `I`. pub fn ast_path_args_for_ty( &self, span: Span, @@ -315,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference), returns the complete - /// set of substitutions. This may involve applying defaulted type parameters. + /// set of generic arguments. This may involve applying defaulted type parameters. /// Constraints on associated types are created from `create_assoc_bindings_for_generic_args`. /// /// Example: diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 2b75f6c4e8f..0b0a708e42b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -118,7 +118,7 @@ impl<'tcx> Instance<'tcx> { /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -580,7 +580,7 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn subst_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T + pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T where T: TypeFoldable> + Copy, { @@ -593,7 +593,7 @@ impl<'tcx> Instance<'tcx> { } #[inline(always)] - pub fn subst_mir_and_normalize_erasing_regions( + pub fn instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -603,14 +603,14 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.subst_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.normalize_erasing_regions(param_env, v.skip_binder()) } } #[inline(always)] - pub fn try_subst_mir_and_normalize_erasing_regions( + pub fn try_instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -620,7 +620,7 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.try_subst_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.try_normalize_erasing_regions(param_env, v.skip_binder()) } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 2415d50b278..fd125af2074 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -134,8 +134,9 @@ impl<'tcx> TyCtxt<'tcx> { /// in-scope substitutions and then normalizing any associated /// types. /// Panics if normalization fails. In case normalization might fail - /// use `try_subst_and_normalize_erasing_regions` instead. - pub fn subst_and_normalize_erasing_regions( + /// use `try_instantiate_and_normalize_erasing_regions` instead. + #[instrument(level = "debug", skip(self))] + pub fn instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -144,22 +145,16 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.normalize_erasing_regions(param_env, substituted) } /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then trying to normalize any associated - /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// types. Contrary to `instantiate_and_normalize_erasing_regions` this does /// not assume that normalization succeeds. - pub fn try_subst_and_normalize_erasing_regions( + #[instrument(level = "debug", skip(self))] + pub fn try_instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -168,13 +163,6 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.try_normalize_erasing_regions(param_env, substituted) } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 1d9c89477cb..ebd61f8ad95 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -193,7 +193,7 @@ impl<'tcx> Inliner<'tcx> { return Err("optimization fuel exhausted"); } - let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions( + let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, self.param_env, ty::EarlyBinder::bind(callee_body.clone()), @@ -481,9 +481,10 @@ impl<'tcx> Inliner<'tcx> { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. - let ty = callsite - .callee - .subst_mir(self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty)); + let ty = callsite.callee.instantiate_mir( + self.tcx, + ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind { work_list.push(unwind); } @@ -650,7 +651,7 @@ impl<'tcx> Inliner<'tcx> { // Copy only unevaluated constants from the callee_body into the caller_body. // Although we are only pushing `ConstKind::Unevaluated` consts to // `required_consts`, here we may not only have `ConstKind::Unevaluated` - // because we are calling `subst_and_normalize_erasing_regions`. + // because we are calling `instantiate_and_normalize_erasing_regions`. caller_body.required_consts.extend( callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ { Const::Ty(_) => { @@ -811,9 +812,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { match terminator.kind { TerminatorKind::Drop { ref place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. - let ty = self - .instance - .subst_mir(tcx, ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty)); + let ty = self.instance.instantiate_mir( + tcx, + ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.param_env) { self.cost += CALL_PENALTY; if let UnwindAction::Cleanup(_) = unwind { @@ -824,7 +826,8 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } } TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => { - let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty())); + let fn_ty = + self.instance.instantiate_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty())); self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) { // Don't give intrinsics the extra penalty for calls INSTR_COST diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 822634129fc..d30e0bad813 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -44,7 +44,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( ) -> bool { trace!(%caller); for &(callee, args) in tcx.mir_inliner_callees(caller.def) { - let Ok(args) = caller.try_subst_mir_and_normalize_erasing_regions( + let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions( tcx, param_env, ty::EarlyBinder::bind(args), diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4afa4e597f7..1a9f0e8352e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -606,7 +606,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { T: TypeFoldable>, { debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index c993e64477b..1d8cbe0e21b 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -647,7 +647,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( // parameters, but the self-type of their impl block do will fail to normalize. if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() { // This is a method within an impl, find out what the self-type is: - let impl_self_ty = tcx.subst_and_normalize_erasing_regions( + let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), tcx.type_of(impl_def_id), diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index a3433d3d13d..e25c5c9f27c 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -26,12 +26,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = typeck_results.closure_size_eval[&closure_def_id]; - let before_feature_tys = tcx.subst_and_normalize_erasing_regions( + let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, param_env, ty::EarlyBinder::bind(before_feature_tys), ); - let after_feature_tys = tcx.subst_and_normalize_erasing_regions( + let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, param_env, ty::EarlyBinder::bind(after_feature_tys), diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 5c5ee262052..50d6f3b7e55 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -401,7 +401,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< = get_callee_generic_args_and_args(cx, parent_expr) { // FIXME: the `instantiate_identity()` below seems incorrect, since we eventually - // call `tcx.try_subst_and_normalize_erasing_regions` further down + // call `tcx.try_instantiate_and_normalize_erasing_regions` further down // (i.e., we are explicitly not in the identity context). let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder(); if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id) @@ -452,7 +452,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let output_ty = fn_sig.output(); if output_ty.contains(*param_ty) { - if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions( + if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, cx.param_env, EarlyBinder::bind(output_ty)) { expr = parent_expr; ty = new_ty; -- cgit 1.4.1-3-g733a5