diff --git a/Cargo.lock b/Cargo.lock index 705210e44b24c..d8370d5663747 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,6 +65,18 @@ dependencies = [ "rand_xorshift", ] +[[package]] +name = "alloc_error_handler" +version = "0.0.0" +dependencies = [ + "alloc", + "compiler_builtins", + "core", + "panic_abort", + "panic_unwind", + "std", +] + [[package]] name = "ammonia" version = "3.2.0" @@ -1830,6 +1842,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "global_allocator" +version = "0.0.0" +dependencies = [ + "panic_abort", + "panic_unwind", + "std", +] + [[package]] name = "globset" version = "0.4.9" @@ -2930,6 +2951,16 @@ dependencies = [ "libc", ] +[[package]] +name = "panic_handler" +version = "0.0.0" +dependencies = [ + "core", + "panic_abort", + "panic_unwind", + "std", +] + [[package]] name = "panic_unwind" version = "0.0.0" @@ -5533,11 +5564,14 @@ dependencies = [ name = "test" version = "0.0.0" dependencies = [ + "alloc_error_handler", "cfg-if", "core", "getopts", + "global_allocator", "libc", "panic_abort", + "panic_handler", "panic_unwind", "proc_macro", "std", diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index e21c9b6604440..3bd3347e60d62 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -30,7 +30,8 @@ fn main() { // See the comment at the top of this file for an explanation of this. #[cfg(feature = "jemalloc-sys")] { - use std::os::raw::{c_int, c_void}; + use core::ffi::c_void; + use std::os::raw::c_int; #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; diff --git a/compiler/rustc_builtin_macros/src/extern_allocator_crate.rs b/compiler/rustc_builtin_macros/src/extern_allocator_crate.rs new file mode 100644 index 0000000000000..ca173129ab624 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/extern_allocator_crate.rs @@ -0,0 +1,50 @@ +// Code that injects an extern statement pointing to the `global_allocator` or +// `alloc_error_handler` sysroot crates. Should +// only be used when the `incomplete_dylib` compiler feature is enabled, an allocator is needed, +// and a global allocator or alloc error handler is not already found in the crate graph. + +// mattmatt could/should this be fully generic and used for other pre-existing extern imports as +// well or what + +use rustc_ast as ast; +use rustc_expand::base::{ExtCtxt, ResolverExpand}; +use rustc_expand::expand::{AstFragment, ExpansionConfig}; +use rustc_session::Session; +use rustc_span::edition::Edition::Edition2018; +use rustc_span::hygiene::AstPass; +use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::DUMMY_SP; +use smallvec::smallvec; +use thin_vec::thin_vec; + +pub fn inject( + sess: &Session, + resolver: &mut dyn ResolverExpand, + krate: &mut ast::Crate, + sym_name: Symbol, +) { + let ecfg = ExpansionConfig::default("allocator_crate_injection".to_string()); + let mut cx = ExtCtxt::new(sess, ecfg, resolver, None); + + let expn_id = cx.resolver.expansion_for_ast_pass(DUMMY_SP, AstPass::AllocatorCrates, &[], None); + + // mattmatt i am guessing i want to inject extern definitions for the allocator functions. we + // codegen the allocator in, say, the bin, but the definitions are found in the + // global_allocator.so (or .rlib) + + let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); + let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id()); + let ident = if sess.parse_sess.edition >= Edition2018 { + Ident::new(sym_name, span) + } else { + Ident::new(sym_name, call_site) + }; + + let extern_stmt = cx.item(span, ident, thin_vec![], ast::ItemKind::ExternCrate(None)); + let fragment = AstFragment::Items(smallvec![extern_stmt]); + let expanded_fragment = + cx.monotonic_expander().fully_expand_fragment(fragment).make_items().pop().unwrap(); + + println!("mattmatt injecting {}", sym_name); + krate.items.insert(0, expanded_fragment); // mattmatt 0 may be wrong +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 75cfac7238485..2f8407b1fcc7d 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -50,6 +50,7 @@ mod util; pub mod asm; pub mod cmdline_attrs; +pub mod extern_allocator_crate; pub mod proc_macro_harness; pub mod standard_library_imports; pub mod test_harness; diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 668d929270530..be4c2f9b73014 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -71,7 +71,8 @@ pub(crate) unsafe fn codegen( let callee = kind.fn_name(method.name); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); - llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); + // mattmatt originally hidden + llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Default); let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); @@ -122,7 +123,7 @@ pub(crate) unsafe fn codegen( let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); // -> ! DIFlagNoReturn attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); - llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); + llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Default); // mattmatt originally hidden let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 02b502d948c2c..222244d46f4f0 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -620,14 +620,20 @@ pub fn codegen_crate( // If the crate doesn't have an `allocator_kind` set then there's definitely // no shim to generate. Otherwise we also check our dependency graph for all // our output crate types. If anything there looks like its a `Dynamic` - // linkage, then it's already got an allocator shim and we'll be using that + // linkage, then it's already got an allocator shim* and we'll be using that // one instead. If nothing exists then it's our job to generate the // allocator! + // + // *If `-Z incomplete_dylibs` is enabled, we can't assume that. Regular dylibs won't have the + // allocator shim but Cdylibs will. If your dependency graph contains a Cdylib (uncommon?) then + // you will get a duplicated allocator shim. If `-Z unified_sysroot_injection` becomes default + // and we make `#[global_allocator]` generate __rust_* directly, we can fully delete the + // codegen including this edge case / assumption. mattmatt let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| { use rustc_middle::middle::dependency_format::Linkage; list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); - let allocator_module = if any_dynamic_crate { + let allocator_module = if any_dynamic_crate && !tcx.sess.opts.unstable_opts.incomplete_dylibs { None } else if let Some(kind) = tcx.allocator_kind(()) { let llmod_id = diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 79b8b41725704..b8d9c96d0e105 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -148,6 +148,13 @@ metadata_profiler_builtins_needs_core = metadata_not_profiler_runtime = the crate `{$crate_name}` is not a profiler runtime +metadata_no_multiple_panic_handlers = + cannot define multiple panic handlers + .label = cannot define a new panic handler + +metadata_prev_panic_handlers = + previous panic handler defined here + metadata_no_multiple_global_alloc = cannot define multiple global allocators .label = cannot define a new global allocator @@ -162,6 +169,9 @@ metadata_no_multiple_alloc_error_handler = metadata_prev_alloc_error_handler = previous allocation error handler defined here +metadata_conflicting_panic_handler = + the `#[panic_handler]` in {$other_crate_name} conflicts with panic handler in: {$crate_name} + metadata_conflicting_global_alloc = the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 323f5a368fc09..1b16bf5a8ea8a 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -213,6 +213,8 @@ declare_features! ( (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), /// Allows using the `#[linkage = ".."]` attribute. (active, linkage, "1.0.0", Some(29603), None), + /// Allows declaring with `#![needs_panic_handler]` that a panic handler is needed. + (active, needs_panic_handler, "1.69.0", None, None), // mattmatt needs tracking issue /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. (active, needs_panic_runtime, "1.10.0", Some(32837), None), /// Allows using the `#![panic_runtime]` attribute. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index af56a0b245987..c7e80061f9e1b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -566,6 +566,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ needs_panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(needs_panic_runtime) ), + gated!(needs_panic_handler, Normal, template!(Word), WarnFollowing, experimental!(needs_panic_handler)), gated!( compiler_builtins, Normal, template!(Word), WarnFollowing, "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2a373ebc1324d..00877911cfc09 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -403,6 +403,46 @@ pub fn configure_and_expand( }); } + if sess.opts.unstable_opts.unified_sysroot_injection { + sess.time("maybe_inject_allocator_crates", || { + println!("mattmatt maybe injecting allocators"); + let allocator_crates = resolver.crate_loader().find_allocator_crates(&krate); + if let Some((global_allocator, alloc_error_handler)) = allocator_crates { + if !global_allocator.is_some() { + rustc_builtin_macros::extern_allocator_crate::inject( + sess, + resolver, + &mut krate, + sym::global_allocator, + ) + } + if !alloc_error_handler.is_some() { + rustc_builtin_macros::extern_allocator_crate::inject( + sess, + resolver, + &mut krate, + sym::alloc_error_handler, + ) + } + } + }); + + sess.time("maybe_inject_panic_handler", || { + let panic_handler = resolver.crate_loader().find_panic_handler(&krate); + if let Some(panic_handler) = panic_handler { + if !panic_handler.is_some() { + // mattmatt no reason this needs to be allocator-specific + rustc_builtin_macros::extern_allocator_crate::inject( + sess, + resolver, + &mut krate, + sym::panic_handler, + ) + } + } + }); + } + // Done with macro expansion! if sess.opts.unstable_opts.input_stats { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 21652063b4716..c4080ef31d1ad 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -700,9 +700,59 @@ impl<'a> CrateLoader<'a> { Ok(unsafe { **sym }) } + pub fn find_panic_handler(&self, krate: &ast::Crate) -> Option> { + let needs_panic_handler_predicate = if self.sess.opts.unstable_opts.incomplete_dylibs { + |ct: &CrateType| !matches!(*ct, CrateType::Rlib) && !matches!(*ct, CrateType::Dylib) + } else { + |ct: &CrateType| !matches!(*ct, CrateType::Rlib) + }; + let mut needs_panic_handler = + self.sess.crate_types().iter().any(needs_panic_handler_predicate); + if !needs_panic_handler { + return None; + } + + needs_panic_handler = self.sess.contains_name(&krate.attrs, sym::needs_panic_handler); + for (_, data) in self.cstore.iter_crate_data() { + if data.needs_panic_handler() {} + needs_panic_handler = needs_panic_handler || data.needs_panic_handler(); + } + + if !needs_panic_handler { + return None; + } + + let has_panic_handler = match &*panic_handler_spans(&self.sess, krate) { + [span1, span2, ..] => { + self.sess + .emit_err(errors::NoMultiplePanicHandlers { span2: *span2, span1: *span1 }); + true + } + spans => !spans.is_empty(), + }; + + let mut panic_handler = has_panic_handler.then(|| Symbol::intern("this crate")); + for (_, data) in self.cstore.iter_crate_data() { + if data.has_panic_handler() { + match panic_handler { + Some(other_crate) => { + self.sess.emit_err(errors::ConflictingPanicHandler { + crate_name: data.name(), + other_crate_name: other_crate, + }); + } + None => panic_handler = Some(data.name()), + } + } + } + + Some(panic_handler) + } + fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. + // mattmatt this probably wants the incomplete dylibs logic let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib); if !any_non_rlib { info!("panic runtime injection skipped, only generating rlib"); @@ -800,7 +850,13 @@ impl<'a> CrateLoader<'a> { } } - fn inject_allocator_crate(&mut self, krate: &ast::Crate) { + pub fn find_allocator_crates( + &mut self, + krate: &ast::Crate, + ) -> Option<(Option, Option)> { + // First we check if the local crate defines a global allocator or allocator error handler. + // mattmatt I extracted this logic to a separate function but don't want to get rid of this + // side effect. Not sure if new behavior needs it, but old behavior had it self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { [span1, span2, ..] => { self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); @@ -823,21 +879,31 @@ impl<'a> CrateLoader<'a> { if !self.sess.contains_name(&krate.attrs, sym::needs_allocator) && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) { - return; + return None; } // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); - if all_rlib { - return; + let needs_allocator_predicate = if self.sess.opts.unstable_opts.incomplete_dylibs { + |ct: &CrateType| !matches!(*ct, CrateType::Rlib) && !matches!(*ct, CrateType::Dylib) + } else { + |ct: &CrateType| !matches!(*ct, CrateType::Rlib) + }; + let needs_allocator = self.sess.crate_types().iter().any(needs_allocator_predicate); + if !needs_allocator { + return None; + } + + // When this flag is enabled, we always use a global allocator. Either one is + // provided by the user, or we inject a dependency on the `global_allocator` sysroot crate. + // If the `#[global_allocator]` attribute is made to generate `__rustc_*` symbols directly, + // this can be removed. + if self.sess.opts.unstable_opts.unified_sysroot_injection { + self.cstore.allocator_kind = Some(AllocatorKind::Global); + self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); } - // Ok, we need an allocator. Not only that but we're actually going to - // create an artifact that needs one linked in. Let's go find the one - // that we're going to link in. - // // First up we check for global allocators. Look at the crate graph here // and see what's a global allocator, including if we ourselves are a // global allocator. @@ -872,27 +938,39 @@ impl<'a> CrateLoader<'a> { } } - if global_allocator.is_some() { - self.cstore.allocator_kind = Some(AllocatorKind::Global); - } else { - // Ok we haven't found a global allocator but we still need an - // allocator. At this point our allocator request is typically fulfilled - // by the standard library, denoted by the `#![default_lib_allocator]` - // attribute. - if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) - && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) - { - self.sess.emit_err(errors::GlobalAllocRequired); + Some((global_allocator, alloc_error_handler)) + } + + /// Determines whether an allocator shim is required and, if so, what type. The shim will be + /// generated later during codegen and included in linked output. This does not run if the + /// `-Z unified_sysroot_injection` flag is enabled. + fn inject_allocator_crate(&mut self, krate: &ast::Crate) { + if let Some((global_allocator, alloc_error_handler)) = self.find_allocator_crates(krate) { + if global_allocator.is_some() { + self.cstore.allocator_kind = Some(AllocatorKind::Global); + } else { + // Ok we haven't found a global allocator but we still need an + // allocator. At this point our allocator request is typically fulfilled + // by the standard library, denoted by the `#![default_lib_allocator]` + // attribute. + if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) + && !self + .cstore + .iter_crate_data() + .any(|(_, data)| data.has_default_lib_allocator()) + { + self.sess.emit_err(errors::GlobalAllocRequired); + } + self.cstore.allocator_kind = Some(AllocatorKind::Default); } - self.cstore.allocator_kind = Some(AllocatorKind::Default); - } - if alloc_error_handler.is_some() { - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); - } else { - // The alloc crate provides a default allocation error handler if - // one isn't specified. - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default); + if alloc_error_handler.is_some() { + self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); + } else { + // The alloc crate provides a default allocation error handler if + // one isn't specified. + self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default); + } } } @@ -974,7 +1052,15 @@ impl<'a> CrateLoader<'a> { pub fn postprocess(&mut self, krate: &ast::Crate) { self.inject_profiler_runtime(krate); - self.inject_allocator_crate(krate); + + // When this flag is enabled, these injections happen during AST expansion alongside + // injections of std/core, test, and proc_macro. + if !self.sess.opts.unstable_opts.unified_sysroot_injection { + self.inject_allocator_crate(krate); + // self.inject_panic_runtime(krate); + } + + // inject a panic runtime dependency into a panic handler if necessary self.inject_panic_runtime(krate); self.report_unused_deps(krate); @@ -1046,6 +1132,25 @@ impl<'a> CrateLoader<'a> { } } +fn panic_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec { + struct Finder<'a> { + sess: &'a Session, + spans: Vec, + } + impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> { + fn visit_item(&mut self, item: &'ast ast::Item) { + if self.sess.contains_name(&item.attrs, sym::panic_handler) { + self.spans.push(item.span); + } + visit::walk_item(self, item) + } + } + + let mut f = Finder { sess, spans: Vec::new() }; + visit::walk_crate(&mut f, krate); + f.spans +} + fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec { struct Finder<'a> { sess: &'a Session, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 02c03114eb67f..fe3f8109800cf 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -341,6 +341,16 @@ pub struct NotProfilerRuntime { pub crate_name: Symbol, } +#[derive(Diagnostic)] +#[diag(metadata_no_multiple_panic_handlers)] +pub struct NoMultiplePanicHandlers { + #[primary_span] + #[label] + pub span2: Span, + #[label(metadata_prev_panic_handlers)] + pub span1: Span, +} + #[derive(Diagnostic)] #[diag(metadata_no_multiple_global_alloc)] pub struct NoMultipleGlobalAlloc { @@ -361,6 +371,13 @@ pub struct NoMultipleAllocErrorHandler { pub span1: Span, } +#[derive(Diagnostic)] +#[diag(metadata_conflicting_panic_handler)] +pub struct ConflictingPanicHandler { + pub crate_name: Symbol, + pub other_crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_conflicting_global_alloc)] pub struct ConflictingGlobalAlloc { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index bb2dd290c6d5d..f64106dcf635e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1697,6 +1697,14 @@ impl CrateMetadata { self.root.required_panic_strategy } + pub(crate) fn needs_panic_handler(&self) -> bool { + self.root.needs_panic_handler + } + + pub(crate) fn has_panic_handler(&self) -> bool { + self.root.has_panic_handler + } + pub(crate) fn needs_panic_runtime(&self) -> bool { self.root.needs_panic_runtime } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 9d8f14058f681..ed0de2492c660 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -679,6 +679,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debugger_visualizers, compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins), needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator), + needs_panic_handler: tcx.sess.contains_name(&attrs, sym::needs_panic_handler), needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime), no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 37af9e64e9a3d..b6fb2aec7007e 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -257,6 +257,7 @@ pub(crate) struct CrateRoot { compiler_builtins: bool, needs_allocator: bool, + needs_panic_handler: bool, needs_panic_runtime: bool, no_builtins: bool, panic_runtime: bool, diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index fc6372cf99ee8..24532be804062 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -42,15 +42,26 @@ pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) { fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { // We only need to check for the presence of weak lang items if we're - // emitting something that's not an rlib. - let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind { - CrateType::Dylib - | CrateType::ProcMacro - | CrateType::Cdylib - | CrateType::Executable - | CrateType::Staticlib => true, - CrateType::Rlib => false, - }); + // emitting something that's not an rlib. If `-Z incomplete_dylibs` is enabled, we also don't + // need to check dylibs. + let needs_check = if !tcx.sess.opts.unstable_opts.incomplete_dylibs { + tcx.sess.crate_types().iter().any(|kind| match *kind { + CrateType::Dylib + | CrateType::ProcMacro + | CrateType::Cdylib + | CrateType::Executable + | CrateType::Staticlib => true, + CrateType::Rlib => false, + }) + } else { + tcx.sess.crate_types().iter().any(|kind| match *kind { + CrateType::ProcMacro + | CrateType::Cdylib + | CrateType::Executable + | CrateType::Staticlib => true, + CrateType::Rlib | CrateType::Dylib => false, + }) + }; if !needs_check { return; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0db4d85ff4b67..d379b3b71480a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1364,6 +1364,8 @@ options! { "generate human-readable, predictable names for codegen units (default: no)"), identify_regions: bool = (false, parse_bool, [UNTRACKED], "display unnamed regions as `'`, using a non-ident unique id (default: no)"), + incomplete_dylibs: bool = (true, parse_bool, [TRACKED], + "build dylib crates (not cdylib) without injecting allocator and panic implementations, mirroring rlib"), incremental_ignore_spans: bool = (false, parse_bool, [TRACKED], "ignore spans during ICH computation -- used for testing (default: no)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], @@ -1650,6 +1652,8 @@ options! { "select processor to schedule for (`rustc --print target-cpus` for details)"), ui_testing: bool = (false, parse_bool, [UNTRACKED], "emit compiler diagnostics in a form suitable for UI testing (default: no)"), + unified_sysroot_injection: bool = (true, parse_bool, [TRACKED], + "inject allocator and panic dependencies into the AST rather than ad-hoc"), uninit_const_chunk_threshold: usize = (16, parse_number, [TRACKED], "allow generating const initializers with mixed init/uninit chunks, \ and set the maximum number of chunks for which this is allowed (default: 16)"), diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index dee823eefde68..9333a391258e0 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1118,6 +1118,7 @@ impl MacroKind { #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] pub enum AstPass { StdImports, + AllocatorCrates, TestHarness, ProcMacroHarness, } @@ -1126,6 +1127,7 @@ impl AstPass { pub fn descr(self) -> &'static str { match self { AstPass::StdImports => "standard library imports", + AstPass::AllocatorCrates => "injected allocator crates", AstPass::TestHarness => "test harness", AstPass::ProcMacroHarness => "proc macro harness", } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f1119214be44d..21bbe03c981ad 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -973,6 +973,7 @@ symbols! { nearbyintf64, needs_allocator, needs_drop, + needs_panic_handler, needs_panic_runtime, neg, negate_unsigned, diff --git a/library/alloc_error_handler/Cargo.toml b/library/alloc_error_handler/Cargo.toml new file mode 100644 index 0000000000000..f7588ed3eb2f8 --- /dev/null +++ b/library/alloc_error_handler/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "alloc_error_handler" +version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust Standard Library - Default alloc error handler" +edition = "2021" + +[lib] +crate-type = ["rlib", "dylib"] + +[dependencies] +# we want this to be no_std, but we need to build with std while bootstrapping. +# after bootstrapping, with no_std on, std will not be externed/used even with a dep +std = { path = "../std" } + +# panic stuff is just a silly dance i have to do in this prototype +panic_unwind = { path = "../panic_unwind", optional = true } +panic_abort = { path = "../panic_abort" } + +alloc = { path = "../alloc" } +compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } +core = { path = "../core" } + +[features] +default = ["unified-sysroot-injection"] + +compiler-builtins-mem = ['compiler_builtins/mem'] +compiler-builtins-c = ["compiler_builtins/c"] +compiler-builtins-no-asm = ["compiler_builtins/no-asm"] +compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"] + +unified-sysroot-injection = [] +panic-unwind = ["panic_unwind"] diff --git a/library/alloc_error_handler/build.rs b/library/alloc_error_handler/build.rs new file mode 100644 index 0000000000000..8b1a06ee750fb --- /dev/null +++ b/library/alloc_error_handler/build.rs @@ -0,0 +1,52 @@ +use std::env; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + let target = env::var("TARGET").expect("TARGET was not set"); + if target.contains("freebsd") { + if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() { + println!("cargo:rustc-cfg=freebsd12"); + } + } else if target.contains("linux") + || target.contains("netbsd") + || target.contains("dragonfly") + || target.contains("openbsd") + || target.contains("solaris") + || target.contains("illumos") + || target.contains("apple-darwin") + || target.contains("apple-ios") + || target.contains("apple-watchos") + || target.contains("uwp") + || target.contains("windows") + || target.contains("fuchsia") + || (target.contains("sgx") && target.contains("fortanix")) + || target.contains("hermit") + || target.contains("l4re") + || target.contains("redox") + || target.contains("haiku") + || target.contains("vxworks") + || target.contains("wasm32") + || target.contains("wasm64") + || target.contains("asmjs") + || target.contains("espidf") + || target.contains("solid") + || target.contains("nintendo-3ds") + { + // These platforms don't have any special requirements. + } else { + // This is for Cargo's build-std support, to mark std as unstable for + // typically no_std platforms. + // This covers: + // - os=none ("bare metal" targets) + // - mipsel-sony-psp + // - nvptx64-nvidia-cuda + // - arch=avr + // - tvos (aarch64-apple-tvos, x86_64-apple-tvos) + // - uefi (x86_64-unknown-uefi, i686-unknown-uefi) + // - JSON targets + // - Any new targets that have not been explicitly added above. + println!("cargo:rustc-cfg=feature=\"restricted-std\""); + } + println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); + println!("cargo:rustc-cfg=backtrace_in_libstd"); +} diff --git a/library/alloc_error_handler/src/lib.rs b/library/alloc_error_handler/src/lib.rs new file mode 100644 index 0000000000000..88bda4691314a --- /dev/null +++ b/library/alloc_error_handler/src/lib.rs @@ -0,0 +1,44 @@ +#![feature(alloc_error_handler)] +#![feature(core_panic)] +// we can't even build an empty crate as no_std dylib until after bootstrapping; +// it'll be missing eh_personality and the compiler doesn't know that's okay +// mattmatt maaaaybe we don't actually need no_std at all +// #![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), no_std)] + +// depending on std, but need to get core::panicking::panic_nounwind_fmt +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +extern crate core; + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use std::alloc::Layout; + +// if we need no_std use below +//#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +//use alloc::alloc::Layout; + +// mattmatt below is __rdl_oom() which i guess is just for no_std crates? +// library/std/src/alloc.rs has a #[alloc_error_handler] impl which has runtime hooks +// +// probably would need to supply normal crates with the hook behavior, but would need to supply the +// __rdl_oom impl to no_std crates. either keep the bad codegen shim or inject a different extern +// statement depending on whether local crate is no_std + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +#[cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), alloc_error_handler)] +pub unsafe fn on_oom(layout: Layout) -> ! { + extern "Rust" { + // This symbol is emitted by rustc next to __rust_alloc_error_handler. + // Its value depends on the -Zoom={panic,abort} compiler option. + static __rust_alloc_error_handler_should_panic: u8; + } + + #[allow(unused_unsafe)] + if unsafe { __rust_alloc_error_handler_should_panic != 0 } { + panic!("memory allocation of {} bytes failed", layout.size()) + } else { + core::panicking::panic_nounwind_fmt(format_args!( + "memory allocation of {} bytes failed", + layout.size() + )) + } +} diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 3dc8c84e0bfde..1d4541a5f7235 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -11,6 +11,8 @@ autobenches = false edition = "2021" [lib] +#crate-type = ["rlib"] # uncomment this when using downloaded stage0 +crate-type = ["dylib", "rlib"] # copy stage1 to another dir, use it as stage0, and uncomment this test = false bench = false @@ -33,3 +35,4 @@ panic_immediate_abort = [] # Make `RefCell` store additional debugging information, which is printed out when # a borrow error occurs debug_refcell = [] +unified-sysroot-injection = [] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dc0702c467a4e..29d851cd018e9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -180,6 +180,18 @@ #![feature(const_is_char_boundary)] #![feature(const_cstr_methods)] #![feature(is_ascii_octdigit)] +#![cfg_attr( + all(not(bootstrap), feature = "unified-sysroot-injection"), + feature(needs_panic_handler) +)] +#![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), needs_panic_handler)] +// core is built as a dylib, meaning std will no longer generate an allocator shim during +// bootstrap as something in its crate graph has shared linkage. so, during bootstrap, make core +// generate a default allocator shim as a hack, and then build the new hookups in stage1 +// #![cfg_attr(all(bootstrap, feature = "unified-sysroot-injection"), needs_allocator)] +// #![cfg_attr(all(bootstrap, feature = "unified-sysroot-injection"), feature(allocator_internals))] +// #![cfg_attr(all(bootstrap, feature = "unified-sysroot-injection"), default_lib_allocator)] + // // Language features: #![feature(abi_unadjusted)] diff --git a/library/global_allocator/Cargo.toml b/library/global_allocator/Cargo.toml new file mode 100644 index 0000000000000..e7d1d503b5692 --- /dev/null +++ b/library/global_allocator/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "global_allocator" +version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust Standard Library - Default global allocator" +edition = "2021" + +[lib] +crate-type = ["rlib", "dylib"] + +[dependencies] +std = { path = "../std" } +panic_unwind = { path = "../panic_unwind", optional = true } +panic_abort = { path = "../panic_abort" } + +[features] +default = ["unified-sysroot-injection"] +unified-sysroot-injection = [] +panic-unwind = ["panic_unwind"] diff --git a/library/global_allocator/build.rs b/library/global_allocator/build.rs new file mode 100644 index 0000000000000..8b1a06ee750fb --- /dev/null +++ b/library/global_allocator/build.rs @@ -0,0 +1,52 @@ +use std::env; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + let target = env::var("TARGET").expect("TARGET was not set"); + if target.contains("freebsd") { + if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() { + println!("cargo:rustc-cfg=freebsd12"); + } + } else if target.contains("linux") + || target.contains("netbsd") + || target.contains("dragonfly") + || target.contains("openbsd") + || target.contains("solaris") + || target.contains("illumos") + || target.contains("apple-darwin") + || target.contains("apple-ios") + || target.contains("apple-watchos") + || target.contains("uwp") + || target.contains("windows") + || target.contains("fuchsia") + || (target.contains("sgx") && target.contains("fortanix")) + || target.contains("hermit") + || target.contains("l4re") + || target.contains("redox") + || target.contains("haiku") + || target.contains("vxworks") + || target.contains("wasm32") + || target.contains("wasm64") + || target.contains("asmjs") + || target.contains("espidf") + || target.contains("solid") + || target.contains("nintendo-3ds") + { + // These platforms don't have any special requirements. + } else { + // This is for Cargo's build-std support, to mark std as unstable for + // typically no_std platforms. + // This covers: + // - os=none ("bare metal" targets) + // - mipsel-sony-psp + // - nvptx64-nvidia-cuda + // - arch=avr + // - tvos (aarch64-apple-tvos, x86_64-apple-tvos) + // - uefi (x86_64-unknown-uefi, i686-unknown-uefi) + // - JSON targets + // - Any new targets that have not been explicitly added above. + println!("cargo:rustc-cfg=feature=\"restricted-std\""); + } + println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); + println!("cargo:rustc-cfg=backtrace_in_libstd"); +} diff --git a/library/global_allocator/src/lib.rs b/library/global_allocator/src/lib.rs new file mode 100644 index 0000000000000..6c0098d6e2682 --- /dev/null +++ b/library/global_allocator/src/lib.rs @@ -0,0 +1,20 @@ +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use std::alloc::{GlobalAlloc, Layout, System}; + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +struct DefaultAllocator; + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +unsafe impl GlobalAlloc for DefaultAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + System.alloc(layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + System.dealloc(ptr, layout) + } +} + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +#[global_allocator] +static GLOBAL: DefaultAllocator = DefaultAllocator; diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index a3cebf99c5342..e98b658d3d6ac 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -23,12 +23,14 @@ use core::panic::BoxMeUp; #[rustc_std_internal_symbol] #[allow(improper_ctypes_definitions)] +#[no_mangle] pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) { unreachable!() } // "Leak" the payload and shim to the relevant abort on the platform in question. #[rustc_std_internal_symbol] +#[no_mangle] pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // Android has the ability to attach a message as part of the abort. #[cfg(target_os = "android")] diff --git a/library/panic_handler/Cargo.toml b/library/panic_handler/Cargo.toml new file mode 100644 index 0000000000000..b776d31178133 --- /dev/null +++ b/library/panic_handler/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "panic_handler" +version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust Standard Library - Default panic handler" +edition = "2021" + +[lib] +crate-type = ["rlib", "dylib"] + +[dependencies] +std = { path = "../std" } +core = { path = "../core" } +panic_unwind = { path = "../panic_unwind", optional = true } +panic_abort = { path = "../panic_abort" } + +[features] +default = ["unified-sysroot-injection"] +unified-sysroot-injection = [] +panic-unwind = ["panic_unwind"] diff --git a/library/panic_handler/build.rs b/library/panic_handler/build.rs new file mode 100644 index 0000000000000..8b1a06ee750fb --- /dev/null +++ b/library/panic_handler/build.rs @@ -0,0 +1,52 @@ +use std::env; + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + let target = env::var("TARGET").expect("TARGET was not set"); + if target.contains("freebsd") { + if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() { + println!("cargo:rustc-cfg=freebsd12"); + } + } else if target.contains("linux") + || target.contains("netbsd") + || target.contains("dragonfly") + || target.contains("openbsd") + || target.contains("solaris") + || target.contains("illumos") + || target.contains("apple-darwin") + || target.contains("apple-ios") + || target.contains("apple-watchos") + || target.contains("uwp") + || target.contains("windows") + || target.contains("fuchsia") + || (target.contains("sgx") && target.contains("fortanix")) + || target.contains("hermit") + || target.contains("l4re") + || target.contains("redox") + || target.contains("haiku") + || target.contains("vxworks") + || target.contains("wasm32") + || target.contains("wasm64") + || target.contains("asmjs") + || target.contains("espidf") + || target.contains("solid") + || target.contains("nintendo-3ds") + { + // These platforms don't have any special requirements. + } else { + // This is for Cargo's build-std support, to mark std as unstable for + // typically no_std platforms. + // This covers: + // - os=none ("bare metal" targets) + // - mipsel-sony-psp + // - nvptx64-nvidia-cuda + // - arch=avr + // - tvos (aarch64-apple-tvos, x86_64-apple-tvos) + // - uefi (x86_64-unknown-uefi, i686-unknown-uefi) + // - JSON targets + // - Any new targets that have not been explicitly added above. + println!("cargo:rustc-cfg=feature=\"restricted-std\""); + } + println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); + println!("cargo:rustc-cfg=backtrace_in_libstd"); +} diff --git a/library/panic_handler/src/lib.rs b/library/panic_handler/src/lib.rs new file mode 100644 index 0000000000000..4639b2b9a6f64 --- /dev/null +++ b/library/panic_handler/src/lib.rs @@ -0,0 +1,102 @@ +#![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), feature(panic_can_unwind))] +#![cfg_attr( + all(not(bootstrap), feature = "unified-sysroot-injection"), + feature(panic_info_message) +)] +#![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), feature(std_internals))] +#![cfg_attr( + all(not(bootstrap), feature = "unified-sysroot-injection"), + feature(needs_panic_runtime) +)] +#![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), needs_panic_runtime)] +// Library features (unwind): +#![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), feature(panic_unwind))] + +// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind` +// This is present in std but I get an unknown lint error here +// #![cfg_attr(all(not(bootstrap), feature = "unified-sysroot-injection"), deny(ffi_unwind_calls))] + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use core::mem; +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use core::panic::{BoxMeUp, PanicInfo}; +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use std::rust_panic_with_hook; + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use std::any::Any; + +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +use std::fmt; + +/// Entry point of panics from the core crate (`panic_impl` lang item). +#[cfg(not(test))] +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +#[panic_handler] +pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { + struct PanicPayload<'a> { + inner: &'a fmt::Arguments<'a>, + string: Option, + } + + impl<'a> PanicPayload<'a> { + fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> { + PanicPayload { inner, string: None } + } + + fn fill(&mut self) -> &mut String { + use std::fmt::Write; + + let inner = self.inner; + // Lazily, the first time this gets called, run the actual string formatting. + self.string.get_or_insert_with(|| { + let mut s = String::new(); + drop(s.write_fmt(*inner)); + s + }) + } + } + + unsafe impl<'a> BoxMeUp for PanicPayload<'a> { + fn take_box(&mut self) -> *mut (dyn Any + Send) { + // We do two allocations here, unfortunately. But (a) they're required with the current + // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in + // begin_panic below). + let contents = mem::take(self.fill()); + Box::into_raw(Box::new(contents)) + } + + fn get(&mut self) -> &(dyn Any + Send) { + self.fill() + } + } + + struct StrPanicPayload(&'static str); + + unsafe impl BoxMeUp for StrPanicPayload { + fn take_box(&mut self) -> *mut (dyn Any + Send) { + Box::into_raw(Box::new(self.0)) + } + + fn get(&mut self) -> &(dyn Any + Send) { + &self.0 + } + } + + let loc = info.location().unwrap(); // The current implementation always returns Some + let msg = info.message().unwrap(); // The current implementation always returns Some + std::__rust_end_short_backtrace(move || { + // mattmatt + // std::sys_common::backtrace::__rust_end_short_backtrace + if let Some(msg) = msg.as_str() { + rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind()); + } else { + rust_panic_with_hook( + &mut PanicPayload::new(msg), + info.message(), + loc, + info.can_unwind(), + ); + } + }) +} diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index ea3c9a7a663c2..32d0157706983 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -92,6 +92,7 @@ extern "C" { #[rustc_std_internal_symbol] #[allow(improper_ctypes_definitions)] +#[no_mangle] pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { Box::into_raw(imp::cleanup(payload)) } @@ -99,6 +100,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any // Entry point for raising an exception, just delegates to the platform-specific // implementation. #[rustc_std_internal_symbol] +#[no_mangle] pub unsafe fn __rust_start_panic(payload: *mut &mut dyn BoxMeUp) -> u32 { let payload = Box::from_raw((*payload).take_box()); diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index adf521d9b94a1..a695a88078ec1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -6,6 +6,9 @@ repository = "https://github.com/rust-lang/rust.git" description = "The Rust Standard Library" edition = "2021" +# [build] +# rustflags = ["-C", "prefer-dynamic"] # mattmatt probably bad + [lib] crate-type = ["dylib", "rlib"] @@ -74,6 +77,7 @@ panic_immediate_abort = ["core/panic_immediate_abort"] std_detect_file_io = ["std_detect/std_detect_file_io"] std_detect_dlsym_getauxval = ["std_detect/std_detect_dlsym_getauxval"] std_detect_env_override = ["std_detect/std_detect_env_override"] +unified-sysroot-injection = ["core/unified-sysroot-injection"] [package.metadata.fortanix-sgx] # Maximum possible number of threads when testing diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c5a5991cc81c4..f4b3ffa74104d 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -345,6 +345,7 @@ fn default_alloc_error_hook(layout: Layout) { } #[cfg(not(test))] +#[cfg(any(bootstrap, not(feature = "unified-sysroot-injection")))] #[doc(hidden)] #[alloc_error_handler] #[unstable(feature = "alloc_internals", issue = "none")] @@ -357,6 +358,7 @@ pub fn rust_oom(layout: Layout) -> ! { } #[cfg(not(test))] +#[cfg(any(bootstrap, not(feature = "unified-sysroot-injection")))] #[doc(hidden)] #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 762f7a7c9a1a0..841bea7a6ef31 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -359,8 +359,7 @@ #![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(thread_local_internals)] -// -#![default_lib_allocator] +#![cfg_attr(any(bootstrap, not(feature = "unified-sysroot-injection")), default_lib_allocator)] // Explicitly import the prelude. The compiler uses this same unstable attribute // to import the prelude implicitly when building crates that depend on std. @@ -590,12 +589,22 @@ pub use std_detect::is_x86_feature_detected; mod sys; mod sys_common; +// mattmatt +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +#[stable(feature = "panic_hooks", since = "1.10.0")] // mattmatt cheating +pub use sys_common::backtrace::__rust_end_short_backtrace; + pub mod alloc; // Private support modules mod panicking; mod personality; +// mattmatt +#[cfg(all(not(bootstrap), feature = "unified-sysroot-injection"))] +#[stable(feature = "panic_hooks", since = "1.10.0")] // mattmatt cheating +pub use panicking::rust_panic_with_hook; + #[path = "../../backtrace/src/lib.rs"] #[allow(dead_code, unused_attributes, fuzzy_provenance_casts)] mod backtrace_rs; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b0db3112e22fd..4c62f4ad47522 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -519,6 +519,7 @@ pub fn panicking() -> bool { /// Entry point of panics from the core crate (`panic_impl` lang item). #[cfg(not(test))] +#[cfg(any(bootstrap, not(feature = "unified-sysroot-injection")))] #[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { struct PanicPayload<'a> { @@ -646,7 +647,8 @@ pub const fn begin_panic(msg: M) -> ! { /// Executes the primary logic for a panic, including checking for recursive /// panics, panic hooks, and finally dispatching to the panic runtime to either /// abort or unwind. -fn rust_panic_with_hook( +#[stable(feature = "panic_hooks", since = "1.10.0")] // mattmatt cheating +pub fn rust_panic_with_hook( payload: &mut dyn BoxMeUp, message: Option<&fmt::Arguments<'_>>, location: &Location<'_>, diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index f1d804ef40c0e..344509cb1b116 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -130,6 +130,7 @@ where /// this is only inline(never) when backtraces in std are enabled, otherwise /// it's fine to optimize away. #[cfg_attr(feature = "backtrace", inline(never))] +#[stable(feature = "panic_hooks", since = "1.10.0")] // mattmatt cheating pub fn __rust_end_short_backtrace(f: F) -> T where F: FnOnce() -> T, diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 61b6f33bce020..a247a7c52a523 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -15,12 +15,15 @@ libc = { version = "0.2", default-features = false } panic_unwind = { path = "../panic_unwind" } panic_abort = { path = "../panic_abort" } -# not actually used but needed to always have proc_macro in the sysroot +# not actually used but needed to always have these in the sysroot proc_macro = { path = "../proc_macro" } +global_allocator = { path = "../global_allocator", optional = true } +alloc_error_handler = { path = "../alloc_error_handler", optional = true } +panic_handler = { path = "../panic_handler", optional = true } # Forward features to the `std` crate as necessary [features] -default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] +default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind", "unified-sysroot-injection"] backtrace = ["std/backtrace"] compiler-builtins-c = ["std/compiler-builtins-c"] compiler-builtins-mem = ["std/compiler-builtins-mem"] @@ -28,9 +31,10 @@ compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"] compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"] llvm-libunwind = ["std/llvm-libunwind"] system-llvm-libunwind = ["std/system-llvm-libunwind"] -panic-unwind = ["std/panic_unwind"] +panic-unwind = ["std/panic_unwind", "panic_handler?/panic-unwind", "global_allocator?/panic-unwind", "alloc_error_handler?/panic-unwind"] panic_immediate_abort = ["std/panic_immediate_abort"] profiler = ["std/profiler"] std_detect_file_io = ["std/std_detect_file_io"] std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] std_detect_env_override = ["std/std_detect_env_override"] +unified-sysroot-injection = ["dep:global_allocator", "dep:alloc_error_handler", "dep:panic_handler", "std/unified-sysroot-injection"]