Implement Make handle_alloc_error
default to panic (for no_std + liballoc)
Related: https://github.com/rust-lang/rust/issues/66741 Guarded with `#![feature(default_alloc_error_handler)]` a default `alloc_error_handler` is called, if a custom allocator is used and no other custom `#[alloc_error_handler]` is defined. The panic message does not contain the size anymore, because it would pull in the fmt machinery, which would blow up the code size significantly.
This commit is contained in:
parent
f283d3f02c
commit
cadd12b5f0
12 changed files with 292 additions and 7 deletions
|
@ -3,11 +3,17 @@ use libc::c_uint;
|
|||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use crate::llvm::{self, False, True};
|
||||
use crate::ModuleLlvm;
|
||||
|
||||
pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: AllocatorKind) {
|
||||
pub(crate) unsafe fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
mods: &mut ModuleLlvm,
|
||||
kind: AllocatorKind,
|
||||
has_alloc_error_handler: bool,
|
||||
) {
|
||||
let llcx = &*mods.llcx;
|
||||
let llmod = mods.llmod();
|
||||
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
|
||||
|
@ -82,4 +88,41 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
|
|||
}
|
||||
llvm::LLVMDisposeBuilder(llbuilder);
|
||||
}
|
||||
|
||||
// rust alloc error handler
|
||||
let args = [usize, usize]; // size, align
|
||||
|
||||
let ty = llvm::LLVMFunctionType(void, args.as_ptr(), args.len() as c_uint, False);
|
||||
let name = format!("__rust_alloc_error_handler");
|
||||
let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
|
||||
// -> ! DIFlagNoReturn
|
||||
llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn);
|
||||
|
||||
if tcx.sess.target.target.options.default_hidden_visibility {
|
||||
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
|
||||
}
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
attributes::emit_uwtable(llfn, true);
|
||||
}
|
||||
|
||||
let kind = if has_alloc_error_handler { AllocatorKind::Global } else { AllocatorKind::Default };
|
||||
let callee = kind.fn_name(sym::oom);
|
||||
let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
|
||||
// -> ! DIFlagNoReturn
|
||||
llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, callee);
|
||||
llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
|
||||
|
||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
||||
let args = args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
|
||||
.collect::<Vec<_>>();
|
||||
let ret = llvm::LLVMRustBuildCall(llbuilder, callee, args.as_ptr(), args.len() as c_uint, None);
|
||||
llvm::LLVMSetTailCall(ret, True);
|
||||
llvm::LLVMBuildRetVoid(llbuilder);
|
||||
llvm::LLVMDisposeBuilder(llbuilder);
|
||||
}
|
||||
|
|
|
@ -95,8 +95,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
mods: &mut ModuleLlvm,
|
||||
kind: AllocatorKind,
|
||||
has_alloc_error_handler: bool,
|
||||
) {
|
||||
unsafe { allocator::codegen(tcx, mods, kind) }
|
||||
unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) }
|
||||
}
|
||||
fn compile_codegen_unit(
|
||||
&self,
|
||||
|
|
|
@ -538,8 +538,9 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
let llmod_id =
|
||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
||||
let mut modules = backend.new_metadata(tcx, &llmod_id);
|
||||
tcx.sess
|
||||
.time("write_allocator_module", || backend.codegen_allocator(tcx, &mut modules, kind));
|
||||
tcx.sess.time("write_allocator_module", || {
|
||||
backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some())
|
||||
});
|
||||
|
||||
Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator })
|
||||
} else {
|
||||
|
|
|
@ -109,6 +109,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
|
|||
tcx: TyCtxt<'tcx>,
|
||||
mods: &mut Self::Module,
|
||||
kind: AllocatorKind,
|
||||
has_alloc_error_handler: bool,
|
||||
);
|
||||
/// This generates the codegen unit and returns it along with
|
||||
/// a `u64` giving an estimate of the unit's processing cost.
|
||||
|
|
|
@ -593,6 +593,9 @@ declare_features! (
|
|||
/// Allows to use the `#[cmse_nonsecure_entry]` attribute.
|
||||
(active, cmse_nonsecure_entry, "1.48.0", Some(75835), None),
|
||||
|
||||
/// Allows rustc to inject a default alloc_error_handler
|
||||
(active, default_alloc_error_handler, "1.48.0", Some(66741), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
@ -64,7 +64,10 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
|
|||
if item == LangItem::PanicImpl {
|
||||
tcx.sess.err("`#[panic_handler]` function required, but not found");
|
||||
} else if item == LangItem::Oom {
|
||||
tcx.sess.err("`#[alloc_error_handler]` function required, but not found");
|
||||
if !tcx.features().default_alloc_error_handler {
|
||||
tcx.sess.err("`#[alloc_error_handler]` function required, but not found.");
|
||||
tcx.sess.note_without_error("Use `#![feature(default_alloc_error_handler)]` for a default error handler.");
|
||||
}
|
||||
} else {
|
||||
tcx.sess.err(&format!("language item required, but not found: `{}`", name));
|
||||
}
|
||||
|
|
|
@ -415,6 +415,7 @@ symbols! {
|
|||
decl_macro,
|
||||
declare_lint_pass,
|
||||
decode,
|
||||
default_alloc_error_handler,
|
||||
default_lib_allocator,
|
||||
default_type_parameter_fallback,
|
||||
default_type_params,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue