-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #103061 - Amanieu:rewrite_alloc_error_handler, r=bjorn3
Rewrite implementation of `#[alloc_error_handler]` The new implementation doesn't use weak lang items and instead changes `#[alloc_error_handler]` to an attribute macro just like `#[global_allocator]`. The attribute will generate the `__rg_oom` function which is called by the compiler-generated `__rust_alloc_error_handler`. If no `__rg_oom` function is defined in any crate then the compiler shim will call `__rdl_oom` in the alloc crate which will simply panic. This also fixes link errors with `-C link-dead-code` with `default_alloc_error_handler`: `__rg_oom` was previously defined in the alloc crate and would attempt to reference the `oom` lang item, even if it didn't exist. This worked as long as `__rg_oom` was excluded from linking since it was not called. This is a prerequisite for the stabilization of `default_alloc_error_handler` (#102318).
- Loading branch information
Showing
40 changed files
with
441 additions
and
166 deletions.
There are no files selected for viewing
104 changes: 104 additions & 0 deletions
104
compiler/rustc_builtin_macros/src/alloc_error_handler.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use crate::util::check_builtin_macro_attribute; | ||
|
||
use rustc_ast::ptr::P; | ||
use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind}; | ||
use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe}; | ||
use rustc_expand::base::{Annotatable, ExtCtxt}; | ||
use rustc_span::symbol::{kw, sym, Ident}; | ||
use rustc_span::Span; | ||
use thin_vec::thin_vec; | ||
|
||
pub fn expand( | ||
ecx: &mut ExtCtxt<'_>, | ||
_span: Span, | ||
meta_item: &ast::MetaItem, | ||
item: Annotatable, | ||
) -> Vec<Annotatable> { | ||
check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler); | ||
|
||
let orig_item = item.clone(); | ||
let not_function = || { | ||
ecx.sess | ||
.parse_sess | ||
.span_diagnostic | ||
.span_err(item.span(), "alloc_error_handler must be a function"); | ||
vec![orig_item.clone()] | ||
}; | ||
|
||
// Allow using `#[alloc_error_handler]` on an item statement | ||
// FIXME - if we get deref patterns, use them to reduce duplication here | ||
let (item, is_stmt, sig_span) = match &item { | ||
Annotatable::Item(item) => match item.kind { | ||
ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)), | ||
_ => return not_function(), | ||
}, | ||
Annotatable::Stmt(stmt) => match &stmt.kind { | ||
StmtKind::Item(item_) => match item_.kind { | ||
ItemKind::Fn(ref fn_kind) => { | ||
(item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) | ||
} | ||
_ => return not_function(), | ||
}, | ||
_ => return not_function(), | ||
}, | ||
_ => return not_function(), | ||
}; | ||
|
||
// Generate a bunch of new items using the AllocFnFactory | ||
let span = ecx.with_def_site_ctxt(item.span); | ||
|
||
// Generate item statements for the allocator methods. | ||
let stmts = vec![generate_handler(ecx, item.ident, span, sig_span)]; | ||
|
||
// Generate anonymous constant serving as container for the allocator methods. | ||
let const_ty = ecx.ty(sig_span, TyKind::Tup(Vec::new())); | ||
let const_body = ecx.expr_block(ecx.block(span, stmts)); | ||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); | ||
let const_item = if is_stmt { | ||
Annotatable::Stmt(P(ecx.stmt_item(span, const_item))) | ||
} else { | ||
Annotatable::Item(const_item) | ||
}; | ||
|
||
// Return the original item and the new methods. | ||
vec![orig_item, const_item] | ||
} | ||
|
||
// #[rustc_std_internal_symbol] | ||
// unsafe fn __rg_oom(size: usize, align: usize) -> ! { | ||
// handler(core::alloc::Layout::from_size_align_unchecked(size, align)) | ||
// } | ||
fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt { | ||
let usize = cx.path_ident(span, Ident::new(sym::usize, span)); | ||
let ty_usize = cx.ty_path(usize); | ||
let size = Ident::from_str_and_span("size", span); | ||
let align = Ident::from_str_and_span("align", span); | ||
|
||
let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]); | ||
let layout_new = cx.expr_path(cx.path(span, layout_new)); | ||
let layout = | ||
cx.expr_call(span, layout_new, vec![cx.expr_ident(span, size), cx.expr_ident(span, align)]); | ||
|
||
let call = cx.expr_call_ident(sig_span, handler, vec![layout]); | ||
|
||
let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never)); | ||
let params = vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)]; | ||
let decl = cx.fn_decl(params, never); | ||
let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() }; | ||
let sig = FnSig { decl, header, span: span }; | ||
|
||
let body = Some(cx.block_expr(call)); | ||
let kind = ItemKind::Fn(Box::new(Fn { | ||
defaultness: ast::Defaultness::Final, | ||
sig, | ||
generics: Generics::default(), | ||
body, | ||
})); | ||
|
||
let special = sym::rustc_std_internal_symbol; | ||
let special = cx.meta_word(span, special); | ||
let attrs = thin_vec![cx.attribute(special)]; | ||
|
||
let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind); | ||
cx.stmt_item(sig_span, item) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.