Skip to content

Commit

Permalink
Rollup merge of rust-lang#110782 - matthiaskrgr:revert_panic_oom, r=A…
Browse files Browse the repository at this point in the history
…manieu

Revert panic oom

This temporarily reverts rust-lang#109507 until rust-lang#110771 is addressed

r? `@Amanieu`
  • Loading branch information
matthiaskrgr authored Apr 25, 2023
2 parents 2212354 + 23a3638 commit 2d72abc
Show file tree
Hide file tree
Showing 58 changed files with 878 additions and 138 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_builtin_macros/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ builtin_macros_requires_cfg_pattern =
builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
.label = boolean expression required
Expand Down
97 changes: 97 additions & 0 deletions compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use crate::errors;
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, ThinVec};

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();

// 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) =
if let Annotatable::Item(item) = &item
&& let ItemKind::Fn(fn_kind) = &item.kind
{
(item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
} else if let Annotatable::Stmt(stmt) = &item
&& let StmtKind::Item(item) = &stmt.kind
&& let ItemKind::Fn(fn_kind) = &item.kind
{
(item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
} else {
ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocErrorMustBeFn {span: item.span() });
return vec![orig_item];
};

// 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 = thin_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(ThinVec::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,
thin_vec![cx.expr_ident(span, size), cx.expr_ident(span, align)],
);

let call = cx.expr_call_ident(sig_span, handler, thin_vec![layout]);

let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never));
let params = thin_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 attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];

let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
cx.stmt_item(sig_span, item)
}
7 changes: 7 additions & 0 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ pub(crate) struct OneCfgPattern {
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_alloc_error_must_be_fn)]
pub(crate) struct AllocErrorMustBeFn {
#[primary_span]
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_assert_requires_boolean)]
pub(crate) struct AssertRequiresBoolean {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use rustc_expand::proc_macro::BangProcMacro;
use rustc_fluent_macro::fluent_messages;
use rustc_span::symbol::sym;

mod alloc_error_handler;
mod assert;
mod cfg;
mod cfg_accessible;
Expand Down Expand Up @@ -103,6 +104,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
}

register_attr! {
alloc_error_handler: alloc_error_handler::expand,
bench: test::expand_bench,
cfg_accessible: cfg_accessible::Expander,
cfg_eval: cfg_eval::expand,
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_codegen_cranelift/example/alloc_example.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(start, core_intrinsics)]
#![feature(start, core_intrinsics, alloc_error_handler)]
#![no_std]

extern crate alloc;
Expand All @@ -22,6 +22,11 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
core::intrinsics::abort();
}

#[alloc_error_handler]
fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
core::intrinsics::abort();
}

#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
let world: Box<&str> = Box::new("Hello World!\0");
Expand Down
23 changes: 22 additions & 1 deletion compiler/rustc_codegen_cranelift/src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::prelude::*;
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
use rustc_session::config::OomStrategy;
use rustc_span::symbol::sym;

/// Returns whether an allocator shim was created
pub(crate) fn codegen(
Expand All @@ -14,14 +15,21 @@ pub(crate) fn codegen(
unwind_context: &mut UnwindContext,
) -> bool {
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
codegen_inner(module, unwind_context, kind, tcx.sess.opts.unstable_opts.oom);
codegen_inner(
module,
unwind_context,
kind,
tcx.alloc_error_handler_kind(()).unwrap(),
tcx.sess.opts.unstable_opts.oom,
);
true
}

fn codegen_inner(
module: &mut impl Module,
unwind_context: &mut UnwindContext,
kind: AllocatorKind,
alloc_error_handler_kind: AllocatorKind,
oom_strategy: OomStrategy,
) {
let usize_ty = module.target_config().pointer_type();
Expand Down Expand Up @@ -63,6 +71,19 @@ fn codegen_inner(
);
}

let sig = Signature {
call_conv: module.target_config().default_call_conv,
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
returns: vec![],
};
crate::common::create_wrapper_function(
module,
unwind_context,
sig,
"__rust_alloc_error_handler",
&alloc_error_handler_kind.fn_name(sym::oom),
);

let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
let mut data_ctx = DataContext::new();
data_ctx.set_align(1);
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_codegen_gcc/example/alloc_example.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(start, core_intrinsics, lang_items)]
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
#![no_std]

extern crate alloc;
Expand All @@ -21,6 +21,11 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! {
core::intrinsics::abort();
}

#[alloc_error_handler]
fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
core::intrinsics::abort();
}

#[lang = "eh_personality"]
fn eh_personality() -> ! {
loop {}
Expand Down
34 changes: 33 additions & 1 deletion compiler/rustc_codegen_gcc/src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::OomStrategy;
use rustc_span::symbol::sym;

use crate::GccContext;

pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind) {
pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) {
let context = &mods.context;
let usize =
match tcx.sess.target.pointer_width {
Expand Down Expand Up @@ -86,6 +87,37 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
// as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643
}

let types = [usize, usize];
let name = "__rust_alloc_error_handler".to_string();
let args: Vec<_> = types.iter().enumerate()
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
.collect();
let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);

if tcx.sess.target.default_hidden_visibility {
#[cfg(feature="master")]
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
}

let callee = alloc_error_handler_kind.fn_name(sym::oom);
let args: Vec<_> = types.iter().enumerate()
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
.collect();
let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false);
#[cfg(feature="master")]
callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));

let block = func.new_block("entry");

let args = args
.iter()
.enumerate()
.map(|(i, _)| func.get_param(i as i32).to_rvalue())
.collect::<Vec<_>>();
let _ret = context.new_call(None, callee, &args);
//llvm::LLVMSetTailCall(ret, True);
block.end_with_void_return(None);

let name = OomStrategy::SYMBOL.to_string();
let global = context.new_global(None, GlobalKind::Exported, i8, name);
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,11 @@ impl CodegenBackend for GccCodegenBackend {
}

impl ExtraBackendMethods for GccCodegenBackend {
fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind) -> Self::Module {
fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
let mut mods = GccContext {
context: Context::default(),
};
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind); }
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
mods
}

Expand Down
48 changes: 48 additions & 0 deletions compiler/rustc_codegen_llvm/src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{DebugInfo, OomStrategy};
use rustc_span::symbol::sym;

use crate::debuginfo;
use crate::llvm::{self, False, True};
Expand All @@ -14,6 +15,7 @@ pub(crate) unsafe fn codegen(
module_llvm: &mut ModuleLlvm,
module_name: &str,
kind: AllocatorKind,
alloc_error_handler_kind: AllocatorKind,
) {
let llcx = &*module_llvm.llcx;
let llmod = module_llvm.llmod();
Expand Down Expand Up @@ -98,6 +100,52 @@ pub(crate) unsafe fn codegen(
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 = "__rust_alloc_error_handler";
let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
// -> ! DIFlagNoReturn
let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx);
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);

if tcx.sess.target.default_hidden_visibility {
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
}
if tcx.sess.must_emit_unwind_tables() {
let uwtable = attributes::uwtable_attr(llcx);
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
}

let callee = alloc_error_handler_kind.fn_name(sym::oom);
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);

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,
ty,
callee,
args.as_ptr(),
args.len() as c_uint,
[].as_ptr(),
0 as c_uint,
);
llvm::LLVMSetTailCall(ret, True);
llvm::LLVMBuildRetVoid(llbuilder);
llvm::LLVMDisposeBuilder(llbuilder);

// __rust_alloc_error_handler_should_panic
let name = OomStrategy::SYMBOL;
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
tcx: TyCtxt<'tcx>,
module_name: &str,
kind: AllocatorKind,
alloc_error_handler_kind: AllocatorKind,
) -> ModuleLlvm {
let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
unsafe {
allocator::codegen(tcx, &mut module_llvm, module_name, kind);
allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind);
}
module_llvm
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ fn exported_symbols_provider_local(
for symbol_name in ALLOCATOR_METHODS
.iter()
.map(|method| format!("__rust_{}", method.name))
.chain([OomStrategy::SYMBOL.to_string()])
.chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()])
{
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));

Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,9 +635,16 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
if let Some(kind) = allocator_kind_for_codegen(tcx) {
let llmod_id =
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
let module_llvm = tcx
.sess
.time("write_allocator_module", || backend.codegen_allocator(tcx, &llmod_id, kind));
let module_llvm = tcx.sess.time("write_allocator_module", || {
backend.codegen_allocator(
tcx,
&llmod_id,
kind,
// If allocator_kind is Some then alloc_error_handler_kind must
// also be Some.
tcx.alloc_error_handler_kind(()).unwrap(),
)
});

ongoing_codegen.submit_pre_codegened_module_to_llvm(
tcx,
Expand Down
Loading

0 comments on commit 2d72abc

Please sign in to comment.