Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
50 changes: 50 additions & 0 deletions compiler/rustc_builtin_macros/src/extern_allocator_crate.rs
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_llvm/src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down Expand Up @@ -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());

Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,14 +620,20 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// 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 =
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/metadata.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
40 changes: 40 additions & 0 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading