From 79fa6ce7a140efb47c67567f80e59a4f19b452a6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 10 Sep 2022 10:55:02 +0000 Subject: [PATCH 01/14] Inline AllocFnFactory kind field --- compiler/rustc_builtin_macros/src/global_allocator.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 866cc5adbf3b1..1dd6a700e6581 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -40,8 +40,7 @@ pub fn expand( // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); - let f = - AllocFnFactory { span, ty_span, kind: AllocatorKind::Global, global: item.ident, cx: ecx }; + let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx }; // Generate item statements for the allocator methods. let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect(); @@ -63,7 +62,6 @@ pub fn expand( struct AllocFnFactory<'a, 'b> { span: Span, ty_span: Span, - kind: AllocatorKind, global: Ident, cx: &'b ExtCtxt<'a>, } @@ -92,7 +90,7 @@ impl AllocFnFactory<'_, '_> { })); let item = self.cx.item( self.span, - Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span), + Ident::from_str_and_span(&AllocatorKind::Global.fn_name(method.name), self.span), self.attrs(), kind, ); From 4ce20663f767c7d1610411b21ed31db3e9af21f4 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 3 Jul 2021 16:46:41 +0200 Subject: [PATCH 02/14] Don't use an allocator shim for `#[global_allocator]` This makes it possible to use liballoc/libstd in combination with `--emit obj` if you use `#[global_allocator]`. Making it work for the default libstd allocator would require weak functions, which are not well supported on all systems. --- compiler/rustc_ast/src/expand/allocator.rs | 11 +- .../rustc_codegen_cranelift/src/allocator.rs | 71 ++++----- compiler/rustc_codegen_gcc/src/allocator.rs | 119 +++++++-------- compiler/rustc_codegen_llvm/src/allocator.rs | 136 +++++++++--------- 4 files changed, 177 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index 3593949634898..c7ca66bc841b6 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -1,6 +1,6 @@ use rustc_span::symbol::{sym, Symbol}; -#[derive(Clone, Debug, Copy, HashStable_Generic)] +#[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)] pub enum AllocatorKind { Global, Default, @@ -9,12 +9,19 @@ pub enum AllocatorKind { impl AllocatorKind { pub fn fn_name(&self, base: Symbol) -> String { match *self { - AllocatorKind::Global => format!("__rg_{base}"), + AllocatorKind::Global => format!("__rust_{base}"), AllocatorKind::Default => format!("__rdl_{base}"), } } } +pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str { + match alloc_error_handler_kind { + AllocatorKind::Global => "__rg_oom", + AllocatorKind::Default => "__rdl_oom", + } +} + pub enum AllocatorTy { Layout, Ptr, diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 2c246ceb37d54..ef69d3f7800cb 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -3,10 +3,11 @@ use crate::prelude::*; -use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use rustc_ast::expand::allocator::{ + alloc_error_handler_name, 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( @@ -34,41 +35,43 @@ fn codegen_inner( ) { let usize_ty = module.target_config().pointer_type(); - for method in ALLOCATOR_METHODS { - let mut arg_tys = Vec::with_capacity(method.inputs.len()); - for ty in method.inputs.iter() { - match *ty { - AllocatorTy::Layout => { - arg_tys.push(usize_ty); // size - arg_tys.push(usize_ty); // align - } - AllocatorTy::Ptr => arg_tys.push(usize_ty), - AllocatorTy::Usize => arg_tys.push(usize_ty), + if kind == AllocatorKind::Default { + for method in ALLOCATOR_METHODS { + let mut arg_tys = Vec::with_capacity(method.inputs.len()); + for ty in method.inputs.iter() { + match *ty { + AllocatorTy::Layout => { + arg_tys.push(usize_ty); // size + arg_tys.push(usize_ty); // align + } + AllocatorTy::Ptr => arg_tys.push(usize_ty), + AllocatorTy::Usize => arg_tys.push(usize_ty), - AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), + AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), + } } - } - let output = match method.output { - AllocatorTy::ResultPtr => Some(usize_ty), - AllocatorTy::Unit => None, + let output = match method.output { + AllocatorTy::ResultPtr => Some(usize_ty), + AllocatorTy::Unit => None, - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { - panic!("invalid allocator output") - } - }; + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; - let sig = Signature { - call_conv: module.target_config().default_call_conv, - params: arg_tys.iter().cloned().map(AbiParam::new).collect(), - returns: output.into_iter().map(AbiParam::new).collect(), - }; - crate::common::create_wrapper_function( - module, - unwind_context, - sig, - &format!("__rust_{}", method.name), - &kind.fn_name(method.name), - ); + let sig = Signature { + call_conv: module.target_config().default_call_conv, + params: arg_tys.iter().cloned().map(AbiParam::new).collect(), + returns: output.into_iter().map(AbiParam::new).collect(), + }; + crate::common::create_wrapper_function( + module, + unwind_context, + sig, + &format!("__rust_{}", method.name), + &AllocatorKind::Default.fn_name(method.name), + ); + } } let sig = Signature { @@ -81,7 +84,7 @@ fn codegen_inner( unwind_context, sig, "__rust_alloc_error_handler", - &alloc_error_handler_kind.fn_name(sym::oom), + &alloc_error_handler_name(alloc_error_handler_kind), ); let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap(); diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index 4bad33ee879ee..f4105b91e9848 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -1,11 +1,12 @@ #[cfg(feature="master")] use gccjit::FnAttribute; use gccjit::{FunctionType, GlobalKind, ToRValue}; -use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use rustc_ast::expand::allocator::{ + alloc_error_handler_name, 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; @@ -22,69 +23,71 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam let i8p = i8.make_pointer(); let void = context.new_type::<()>(); - for method in ALLOCATOR_METHODS { - let mut types = Vec::with_capacity(method.inputs.len()); - for ty in method.inputs.iter() { - match *ty { - AllocatorTy::Layout => { - types.push(usize); - types.push(usize); + if kind == AllocatorKind::Default { + for method in ALLOCATOR_METHODS { + let mut types = Vec::with_capacity(method.inputs.len()); + for ty in method.inputs.iter() { + match *ty { + AllocatorTy::Layout => { + types.push(usize); + types.push(usize); + } + AllocatorTy::Ptr => types.push(i8p), + AllocatorTy::Usize => types.push(usize), + + AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), } - AllocatorTy::Ptr => types.push(i8p), - AllocatorTy::Usize => types.push(usize), - - AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), } - } - let output = match method.output { - AllocatorTy::ResultPtr => Some(i8p), - AllocatorTy::Unit => None, + let output = match method.output { + AllocatorTy::ResultPtr => Some(i8p), + AllocatorTy::Unit => None, - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { - panic!("invalid allocator output") - } - }; - let name = format!("__rust_{}", method.name); + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; + let name = format!("__rust_{}", method.name); + + 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, output.unwrap_or(void), &args, name, false); - 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, output.unwrap_or(void), &args, name, false); + if tcx.sess.target.options.default_hidden_visibility { + #[cfg(feature="master")] + func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + } + if tcx.sess.must_emit_unwind_tables() { + // TODO(antoyo): emit unwind tables. + } - if tcx.sess.target.options.default_hidden_visibility { + let callee = AllocatorKind::Default.fn_name(method.name); + 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, output.unwrap_or(void), &args, callee, false); #[cfg(feature="master")] - func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - } - if tcx.sess.must_emit_unwind_tables() { - // TODO(antoyo): emit unwind tables. - } + 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::>(); + let ret = context.new_call(None, callee, &args); + //llvm::LLVMSetTailCall(ret, True); + if output.is_some() { + block.end_with_return(None, ret); + } + else { + block.end_with_void_return(None); + } - let callee = kind.fn_name(method.name); - 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, output.unwrap_or(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::>(); - let ret = context.new_call(None, callee, &args); - //llvm::LLVMSetTailCall(ret, True); - if output.is_some() { - block.end_with_return(None, ret); - } - else { - block.end_with_void_return(None); + // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances + // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643 } - - // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances - // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643 } let types = [usize, usize]; @@ -99,7 +102,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } - let callee = alloc_error_handler_kind.fn_name(sym::oom); + let callee = alloc_error_handler_name(alloc_error_handler_kind); let args: Vec<_> = types.iter().enumerate() .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) .collect(); diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 668d929270530..acf44f3276d27 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,10 +1,11 @@ use crate::attributes; use libc::c_uint; -use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use rustc_ast::expand::allocator::{ + alloc_error_handler_name, 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}; @@ -29,75 +30,78 @@ pub(crate) unsafe fn codegen( let i8p = llvm::LLVMPointerType(i8, 0); let void = llvm::LLVMVoidTypeInContext(llcx); - for method in ALLOCATOR_METHODS { - let mut args = Vec::with_capacity(method.inputs.len()); - for ty in method.inputs.iter() { - match *ty { - AllocatorTy::Layout => { - args.push(usize); // size - args.push(usize); // align + if kind == AllocatorKind::Default { + for method in ALLOCATOR_METHODS { + let mut args = Vec::with_capacity(method.inputs.len()); + for ty in method.inputs.iter() { + match *ty { + AllocatorTy::Layout => { + args.push(usize); // size + args.push(usize); // align + } + AllocatorTy::Ptr => args.push(i8p), + AllocatorTy::Usize => args.push(usize), + + AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), } - AllocatorTy::Ptr => args.push(i8p), - AllocatorTy::Usize => args.push(usize), - - AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), } - } - let output = match method.output { - AllocatorTy::ResultPtr => Some(i8p), - AllocatorTy::Unit => None, + let output = match method.output { + AllocatorTy::ResultPtr => Some(i8p), + AllocatorTy::Unit => None, - AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { - panic!("invalid allocator output") + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; + let ty = llvm::LLVMFunctionType( + output.unwrap_or(void), + args.as_ptr(), + args.len() as c_uint, + False, + ); + let name = format!("__rust_{}", method.name); + let llfn = + llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); + + 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 ty = llvm::LLVMFunctionType( - output.unwrap_or(void), - args.as_ptr(), - args.len() as c_uint, - False, - ); - let name = format!("__rust_{}", method.name); - let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); - - 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 = kind.fn_name(method.name); - let callee = - llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); - 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::>(); - 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); - if output.is_some() { - llvm::LLVMBuildRet(llbuilder, ret); - } else { - llvm::LLVMBuildRetVoid(llbuilder); + let callee = AllocatorKind::Default.fn_name(method.name); + let callee = + llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); + 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::>(); + 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); + if output.is_some() { + llvm::LLVMBuildRet(llbuilder, ret); + } else { + llvm::LLVMBuildRetVoid(llbuilder); + } + llvm::LLVMDisposeBuilder(llbuilder); } - llvm::LLVMDisposeBuilder(llbuilder); } // rust alloc error handler @@ -118,7 +122,7 @@ pub(crate) unsafe fn codegen( attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]); } - let callee = alloc_error_handler_kind.fn_name(sym::oom); + let callee = alloc_error_handler_name(alloc_error_handler_kind); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); // -> ! DIFlagNoReturn attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); From 6ba7c5db079132b5d85112083691d4203a6b761c Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 3 Jul 2021 17:50:53 +0200 Subject: [PATCH 03/14] Split AllocatorKind::fn_name in global_fn_name and default_fn_name --- compiler/rustc_ast/src/expand/allocator.rs | 13 ++++++------- .../rustc_builtin_macros/src/global_allocator.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/allocator.rs | 4 ++-- compiler/rustc_codegen_gcc/src/allocator.rs | 4 ++-- compiler/rustc_codegen_llvm/src/allocator.rs | 4 ++-- compiler/rustc_metadata/src/creader.rs | 6 +++--- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index c7ca66bc841b6..73e79d4441c91 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -6,13 +6,12 @@ pub enum AllocatorKind { Default, } -impl AllocatorKind { - pub fn fn_name(&self, base: Symbol) -> String { - match *self { - AllocatorKind::Global => format!("__rust_{base}"), - AllocatorKind::Default => format!("__rdl_{base}"), - } - } +pub fn global_fn_name(base: Symbol) -> String { + format!("__rust_{base}") +} + +pub fn default_fn_name(base: Symbol) -> String { + format!("__rdl_{base}") } pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str { diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 1dd6a700e6581..f0d378d12f712 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -1,7 +1,7 @@ use crate::util::check_builtin_macro_attribute; use rustc_ast::expand::allocator::{ - AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS, + global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS, }; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind}; @@ -90,7 +90,7 @@ impl AllocFnFactory<'_, '_> { })); let item = self.cx.item( self.span, - Ident::from_str_and_span(&AllocatorKind::Global.fn_name(method.name), self.span), + Ident::from_str_and_span(&global_fn_name(method.name), self.span), self.attrs(), kind, ); diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index ef69d3f7800cb..3b74050250b20 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -4,7 +4,7 @@ use crate::prelude::*; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + alloc_error_handler_name, default_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; @@ -69,7 +69,7 @@ fn codegen_inner( unwind_context, sig, &format!("__rust_{}", method.name), - &AllocatorKind::Default.fn_name(method.name), + &default_fn_name(method.name), ); } } diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index f4105b91e9848..fe143aaad5fe7 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -2,7 +2,7 @@ use gccjit::FnAttribute; use gccjit::{FunctionType, GlobalKind, ToRValue}; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + alloc_error_handler_name, default_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -61,7 +61,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam // TODO(antoyo): emit unwind tables. } - let callee = AllocatorKind::Default.fn_name(method.name); + let callee = default_fn_name(method.name); let args: Vec<_> = types.iter().enumerate() .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) .collect(); diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index acf44f3276d27..c248468107239 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,7 +1,7 @@ use crate::attributes; use libc::c_uint; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + alloc_error_handler_name, default_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -71,7 +71,7 @@ pub(crate) unsafe fn codegen( attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]); } - let callee = AllocatorKind::Default.fn_name(method.name); + let callee = default_fn_name(method.name); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index e6e7d25773e67..07a9593fee833 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -4,7 +4,7 @@ use crate::errors; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind}; use rustc_ast::{self as ast, *}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; @@ -1044,7 +1044,7 @@ fn global_allocator_spans(krate: &ast::Crate) -> Vec { } } - let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc)); + let name = Symbol::intern(&global_fn_name(sym::alloc)); let mut f = Finder { name, spans: Vec::new() }; visit::walk_crate(&mut f, krate); f.spans @@ -1066,7 +1066,7 @@ fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec { } } - let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom)); + let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)); let mut f = Finder { name, spans: Vec::new() }; visit::walk_crate(&mut f, krate); f.spans From 145b0574efd63603f35beda4d6b69933c8a01c1f Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 6 Jul 2021 18:56:01 +0200 Subject: [PATCH 04/14] Use global_fn_name instead of format! --- compiler/rustc_codegen_cranelift/src/allocator.rs | 5 +++-- compiler/rustc_codegen_gcc/src/allocator.rs | 5 +++-- compiler/rustc_codegen_llvm/src/allocator.rs | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 3b74050250b20..c27971897a039 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -4,7 +4,8 @@ use crate::prelude::*; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, default_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, + ALLOCATOR_METHODS, }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; @@ -68,7 +69,7 @@ fn codegen_inner( module, unwind_context, sig, - &format!("__rust_{}", method.name), + &global_fn_name(method.name), &default_fn_name(method.name), ); } diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index fe143aaad5fe7..ff68de8c8f1dd 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -2,7 +2,8 @@ use gccjit::FnAttribute; use gccjit::{FunctionType, GlobalKind, ToRValue}; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, default_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, + ALLOCATOR_METHODS, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -46,7 +47,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam panic!("invalid allocator output") } }; - let name = format!("__rust_{}", method.name); + let name = global_fn_name(method.name); let args: Vec<_> = types.iter().enumerate() .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index c248468107239..564e996cdf3b3 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,7 +1,8 @@ use crate::attributes; use libc::c_uint; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, default_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, + ALLOCATOR_METHODS, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -59,7 +60,7 @@ pub(crate) unsafe fn codegen( args.len() as c_uint, False, ); - let name = format!("__rust_{}", method.name); + let name = global_fn_name(method.name); let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty); From 66982a383b6f7d3a933fc6896202632bee7161a4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 10 Sep 2022 11:33:44 +0000 Subject: [PATCH 05/14] Prevent insta-stable no alloc shim support You will need to add the following as replacement for the old __rust_* definitions when not using the alloc shim. #[no_mangle] static __rust_no_alloc_shim_is_unstable: u8 = 0; --- compiler/rustc_ast/src/expand/allocator.rs | 2 ++ compiler/rustc_codegen_cranelift/src/allocator.rs | 9 ++++++++- compiler/rustc_codegen_gcc/src/allocator.rs | 7 ++++++- compiler/rustc_codegen_llvm/src/allocator.rs | 10 +++++++++- .../rustc_codegen_ssa/src/back/symbol_export.rs | 13 ++++++++++++- library/alloc/src/alloc.rs | 12 +++++++++++- tests/codegen/alloc-optimisation.rs | 3 ++- tests/codegen/vec-optimizes-away.rs | 3 ++- 8 files changed, 52 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index 73e79d4441c91..e87f6e820a1fc 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -21,6 +21,8 @@ pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'st } } +pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable"; + pub enum AllocatorTy { Layout, Ptr, diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index c27971897a039..d4b1ae2b61383 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -5,7 +5,7 @@ use crate::prelude::*; use rustc_ast::expand::allocator::{ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, - ALLOCATOR_METHODS, + ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; @@ -94,4 +94,11 @@ fn codegen_inner( let val = oom_strategy.should_panic(); data_ctx.define(Box::new([val])); module.define_data(data_id, &data_ctx).unwrap(); + + let data_id = + module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap(); + let mut data_ctx = DataContext::new(); + data_ctx.set_align(1); + data_ctx.define(Box::new([0])); + module.define_data(data_id, &data_ctx).unwrap(); } diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index ff68de8c8f1dd..13f88192bbc90 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -3,7 +3,7 @@ use gccjit::FnAttribute; use gccjit::{FunctionType, GlobalKind, ToRValue}; use rustc_ast::expand::allocator::{ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, - ALLOCATOR_METHODS, + ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -127,4 +127,9 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam let value = tcx.sess.opts.unstable_opts.oom.should_panic(); let value = context.new_rvalue_from_int(i8, value as i32); global.global_set_initializer_rvalue(value); + + let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string(); + let global = context.new_global(None, GlobalKind::Exported, i8, name); + let value = context.new_rvalue_from_int(i8, 0); + global.global_set_initializer_rvalue(value); } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 564e996cdf3b3..a57508815d6f8 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -2,7 +2,7 @@ use crate::attributes; use libc::c_uint; use rustc_ast::expand::allocator::{ alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, - ALLOCATOR_METHODS, + ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -161,6 +161,14 @@ pub(crate) unsafe fn codegen( let llval = llvm::LLVMConstInt(i8, val as u64, False); llvm::LLVMSetInitializer(ll_g, llval); + let name = NO_ALLOC_SHIM_IS_UNSTABLE; + let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); + if tcx.sess.target.default_hidden_visibility { + llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); + } + let llval = llvm::LLVMConstInt(i8, 0, False); + llvm::LLVMSetInitializer(ll_g, llval); + if tcx.sess.opts.debuginfo != DebugInfo::None { let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod); debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 8f2f829c17c1c..23c531a22663e 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -2,7 +2,7 @@ use crate::base::allocator_kind_for_codegen; use std::collections::hash_map::Entry::*; -use rustc_ast::expand::allocator::ALLOCATOR_METHODS; +use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; @@ -241,6 +241,17 @@ fn exported_symbols_provider_local( used: false, }, )); + + let exported_symbol = + ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)); + symbols.push(( + exported_symbol, + SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Data, + used: false, + }, + )) } if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 6f2ba957bcda0..01d1fdc9b2a55 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -37,6 +37,9 @@ extern "Rust" { #[rustc_allocator_zeroed] #[rustc_nounwind] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + + #[cfg(not(bootstrap))] + static __rust_no_alloc_shim_is_unstable: u8; } /// The global memory allocator. @@ -90,7 +93,14 @@ pub use std::alloc::Global; #[must_use = "losing the pointer will leak memory"] #[inline] pub unsafe fn alloc(layout: Layout) -> *mut u8 { - unsafe { __rust_alloc(layout.size(), layout.align()) } + unsafe { + // Make sure we don't accidentally allow omitting the allocator shim in + // stable code until it is actually stabilized. + #[cfg(not(bootstrap))] + core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); + + __rust_alloc(layout.size(), layout.align()) + } } /// Deallocate memory with the global allocator. diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs index c3ffaeb9547b3..f88d695d87e1e 100644 --- a/tests/codegen/alloc-optimisation.rs +++ b/tests/codegen/alloc-optimisation.rs @@ -1,12 +1,13 @@ // // no-system-llvm // compile-flags: -O -#![crate_type="lib"] +#![crate_type = "lib"] #[no_mangle] pub fn alloc_test(data: u32) { // CHECK-LABEL: @alloc_test // CHECK-NEXT: start: + // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1 // CHECK-NEXT: ret void let x = Box::new(data); drop(x); diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs index 9143fad234087..6f477a796b65d 100644 --- a/tests/codegen/vec-optimizes-away.rs +++ b/tests/codegen/vec-optimizes-away.rs @@ -1,12 +1,13 @@ // ignore-debug: the debug assertions get in the way // no-system-llvm // compile-flags: -O -#![crate_type="lib"] +#![crate_type = "lib"] #[no_mangle] pub fn sum_me() -> i32 { // CHECK-LABEL: @sum_me // CHECK-NEXT: {{^.*:$}} + // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1 // CHECK-NEXT: ret i32 6 vec![1, 2, 3].iter().sum::() } From 8ea28a41326591852453730723cf06dbba7d73e1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 11 Sep 2022 14:01:03 +0000 Subject: [PATCH 06/14] Add test --- .../run-make-fulldeps/no-alloc-shim/Makefile | 21 +++++++++ tests/run-make-fulldeps/no-alloc-shim/foo.rs | 44 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 tests/run-make-fulldeps/no-alloc-shim/Makefile create mode 100644 tests/run-make-fulldeps/no-alloc-shim/foo.rs diff --git a/tests/run-make-fulldeps/no-alloc-shim/Makefile b/tests/run-make-fulldeps/no-alloc-shim/Makefile new file mode 100644 index 0000000000000..03679fb604e63 --- /dev/null +++ b/tests/run-make-fulldeps/no-alloc-shim/Makefile @@ -0,0 +1,21 @@ +include ../tools.mk + +TARGET_LIBDIR = $$($(RUSTC) --print target-libdir) + +all: + $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort +ifdef IS_MSVC + $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib $(call OUT_EXE,foo) + $(call OUT_EXE,foo) +else + $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) + $(call RUN_BINFILE,foo) +endif + + # Check that linking without __rust_no_alloc_shim_is_unstable defined fails + $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort --cfg check_feature_gate +ifdef IS_MSVC + $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib $(call OUT_EXE,foo) || exit 0 && exit 1 +else + $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) || exit 0 && exit 1 +endif diff --git a/tests/run-make-fulldeps/no-alloc-shim/foo.rs b/tests/run-make-fulldeps/no-alloc-shim/foo.rs new file mode 100644 index 0000000000000..a3daec3db391a --- /dev/null +++ b/tests/run-make-fulldeps/no-alloc-shim/foo.rs @@ -0,0 +1,44 @@ +#![feature(default_alloc_error_handler)] +#![no_std] +#![no_main] + +extern crate alloc; + +use alloc::alloc::{GlobalAlloc, Layout}; + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn rust_eh_personality() { + loop {} +} + +#[global_allocator] +static ALLOC: Alloc = Alloc; + +struct Alloc; + +unsafe impl GlobalAlloc for Alloc { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { + core::ptr::null_mut() + } + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { + todo!() + } +} + +#[cfg(not(check_feature_gate))] +#[no_mangle] +static __rust_no_alloc_shim_is_unstable: u8 = 0; + +#[no_mangle] +extern "C" fn main(_argc: usize, _argv: *const *const i8) -> i32 { + unsafe { + assert_eq!(alloc::alloc::alloc(Layout::new::<()>()), core::ptr::null_mut()); + } + + 0 +} From 9506011d32a55941dcda1c4e588ff7c0954648a5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 12 Feb 2023 12:01:18 +0000 Subject: [PATCH 07/14] Fix allocator shim handling in miri --- src/tools/miri/src/machine.rs | 4 ++ src/tools/miri/src/shims/foreign_items.rs | 59 +++++++++++------------ 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 21c5a9c1b7029..f95a0a981c2e3 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -635,6 +635,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { /// Sets up the "extern statics" for this machine. fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + // "__rust_no_alloc_shim_is_unstable" + let val = ImmTy::from_int(0, this.machine.layouts.u8); + Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?; + match this.tcx.sess.target.os.as_ref() { "linux" => { // "environ" diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 44bca3796f9af..cc2d4cd640a90 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -347,7 +347,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Emulates calling the internal __rust_* allocator functions fn emulate_allocator( &mut self, - symbol: Symbol, default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>, ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); @@ -359,11 +358,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match allocator_kind { AllocatorKind::Global => { - let (body, instance) = this - .lookup_exported_symbol(symbol)? - .expect("symbol should be present if there is a global allocator"); - - Ok(EmulateByNameResult::MirBody(body, instance)) + // `__rust_*` is defined by `#[global_allocator]` if `#[global_allocator]` is used + return Ok(EmulateByNameResult::NotSupported); } AllocatorKind::Default => { default(this)?; @@ -558,11 +554,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Rust allocation "__rust_alloc" | "miri_alloc" => { - let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; - let size = this.read_target_usize(size)?; - let align = this.read_target_usize(align)?; - let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { + let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; + let size = this.read_target_usize(size)?; + let align = this.read_target_usize(align)?; + Self::check_alloc_request(size, align)?; let memory_kind = match link_name.as_str() { @@ -581,8 +577,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; match link_name.as_str() { - "__rust_alloc" => - return this.emulate_allocator(Symbol::intern("__rg_alloc"), default), + "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; return Ok(EmulateByNameResult::NeedsJumping); @@ -591,11 +586,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } "__rust_alloc_zeroed" => { - let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; - let size = this.read_target_usize(size)?; - let align = this.read_target_usize(align)?; + return this.emulate_allocator(|this| { + let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; + let size = this.read_target_usize(size)?; + let align = this.read_target_usize(align)?; - return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| { Self::check_alloc_request(size, align)?; let ptr = this.allocate_ptr( @@ -614,12 +609,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }); } "__rust_dealloc" | "miri_dealloc" => { - let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; - let ptr = this.read_pointer(ptr)?; - let old_size = this.read_target_usize(old_size)?; - let align = this.read_target_usize(align)?; - let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { + let [ptr, old_size, align] = + this.check_shim(abi, Abi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let old_size = this.read_target_usize(old_size)?; + let align = this.read_target_usize(align)?; + let memory_kind = match link_name.as_str() { "__rust_dealloc" => MiriMemoryKind::Rust, "miri_dealloc" => MiriMemoryKind::Miri, @@ -635,8 +631,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; match link_name.as_str() { - "__rust_dealloc" => - return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default), + "__rust_dealloc" => { + return this.emulate_allocator(default); + } "miri_dealloc" => { default(this)?; return Ok(EmulateByNameResult::NeedsJumping); @@ -645,15 +642,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } "__rust_realloc" => { - let [ptr, old_size, align, new_size] = - this.check_shim(abi, Abi::Rust, link_name, args)?; - let ptr = this.read_pointer(ptr)?; - let old_size = this.read_target_usize(old_size)?; - let align = this.read_target_usize(align)?; - let new_size = this.read_target_usize(new_size)?; - // No need to check old_size; we anyway check that they match the allocation. + return this.emulate_allocator(|this| { + let [ptr, old_size, align, new_size] = + this.check_shim(abi, Abi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let old_size = this.read_target_usize(old_size)?; + let align = this.read_target_usize(align)?; + let new_size = this.read_target_usize(new_size)?; + // No need to check old_size; we anyway check that they match the allocation. - return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| { Self::check_alloc_request(new_size, align)?; let align = Align::from_bytes(align).unwrap(); From efb9c30ed2bef28812f47914dea3ae4f703e6870 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 12 Feb 2023 12:01:28 +0000 Subject: [PATCH 08/14] Fix fs miri test on AArch64 --- src/tools/miri/tests/pass/shims/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index af245aa89aa36..3258a2be460b0 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -31,7 +31,7 @@ fn main() { } fn host_to_target_path(path: String) -> PathBuf { - use std::ffi::{CStr, CString}; + use std::ffi::{c_char, CStr, CString}; let path = CString::new(path).unwrap(); let mut out = Vec::with_capacity(1024); From 568deb7ece889ed2871fa023100cb69c5c086967 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:14:28 +0000 Subject: [PATCH 09/14] Improve miri comments --- src/tools/miri/src/shims/foreign_items.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index cc2d4cd640a90..167370ef4a8b6 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -358,7 +358,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match allocator_kind { AllocatorKind::Global => { - // `__rust_*` is defined by `#[global_allocator]` if `#[global_allocator]` is used + // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion + // of this attribute rather than generated by the allocator shim. As such we have + // to call the definition produced by `#[global_allocator]` instead of the shim like + // in the case of `#[global_allocator]` not existing. Somewhat unintuitively doing + // so is done by returning `NotSupported`. return Ok(EmulateByNameResult::NotSupported); } AllocatorKind::Default => { @@ -555,6 +559,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Rust allocation "__rust_alloc" | "miri_alloc" => { let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { + // Only call `check_shim` when `#[global_allocator]` isn't used. The macro + // expansion of `#[global_allocator]` defines this symbol and `check_shim` + // checks that there exists no definition of a shim. let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let size = this.read_target_usize(size)?; let align = this.read_target_usize(align)?; @@ -587,6 +594,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "__rust_alloc_zeroed" => { return this.emulate_allocator(|this| { + // See the comment for `__rust_alloc` why `check_shim` is only called in the + // default case. let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let size = this.read_target_usize(size)?; let align = this.read_target_usize(align)?; @@ -610,6 +619,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "__rust_dealloc" | "miri_dealloc" => { let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { + // See the comment for `__rust_alloc` why `check_shim` is only called in the + // default case. let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; @@ -643,6 +654,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "__rust_realloc" => { return this.emulate_allocator(|this| { + // See the comment for `__rust_alloc` why `check_shim` is only called in the + // default case. let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; From ffd8cb87bf342488b56fe8e0238b0e556e813601 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 14 Feb 2023 00:12:25 +0100 Subject: [PATCH 10/14] Fix review comments Co-authored-by: Ralf Jung --- src/tools/miri/src/shims/foreign_items.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 167370ef4a8b6..57fce448b606a 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -359,10 +359,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { match allocator_kind { AllocatorKind::Global => { // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion - // of this attribute rather than generated by the allocator shim. As such we have - // to call the definition produced by `#[global_allocator]` instead of the shim like - // in the case of `#[global_allocator]` not existing. Somewhat unintuitively doing - // so is done by returning `NotSupported`. + // of this attribute. As such we have to call an exported Rust function, + // and not execute any Miri shim. Somewhat unintuitively doing so is done + // by returning `NotSupported`, which triggers the `lookup_exported_symbol` + // fallback case in `emulate_foreign_item`. return Ok(EmulateByNameResult::NotSupported); } AllocatorKind::Default => { @@ -559,9 +559,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Rust allocation "__rust_alloc" | "miri_alloc" => { let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { - // Only call `check_shim` when `#[global_allocator]` isn't used. The macro - // expansion of `#[global_allocator]` defines this symbol and `check_shim` - // checks that there exists no definition of a shim. + // Only call `check_shim` when `#[global_allocator]` isn't used. When that + // macro is used, we act like no shim exists, so that the exported function can run. let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let size = this.read_target_usize(size)?; let align = this.read_target_usize(align)?; From 34f6a83b28cd88a9f4e6cf790d3f270a489f1bf2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 9 Mar 2023 11:51:18 +0000 Subject: [PATCH 11/14] Fix test --- tests/codegen/debug-vtable.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs index d82b737de0b41..e52392b260bd4 100644 --- a/tests/codegen/debug-vtable.rs +++ b/tests/codegen/debug-vtable.rs @@ -11,8 +11,6 @@ // Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled. // This helps debuggers more reliably map from dyn pointer to concrete type. -// CHECK: @vtable.0 = private constant <{ -// CHECK: @vtable.1 = private constant <{ // CHECK: @vtable.2 = private constant <{ // CHECK: @vtable.3 = private constant <{ // CHECK: @vtable.4 = private constant <{ From 8ace03e152957b8ce8ccbc8d0f9cbd19db4937a8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 9 Mar 2023 19:41:44 +0000 Subject: [PATCH 12/14] Fix no-alloc-shim test on MSVC --- tests/run-make-fulldeps/no-alloc-shim/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run-make-fulldeps/no-alloc-shim/Makefile b/tests/run-make-fulldeps/no-alloc-shim/Makefile index 03679fb604e63..f3dbbf1fd63e6 100644 --- a/tests/run-make-fulldeps/no-alloc-shim/Makefile +++ b/tests/run-make-fulldeps/no-alloc-shim/Makefile @@ -5,7 +5,7 @@ TARGET_LIBDIR = $$($(RUSTC) --print target-libdir) all: $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort ifdef IS_MSVC - $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib $(call OUT_EXE,foo) + $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib $(call OUT_EXE,foo) else $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) @@ -15,7 +15,7 @@ endif # Check that linking without __rust_no_alloc_shim_is_unstable defined fails $(RUSTC) foo.rs --crate-type bin --emit obj -Cpanic=abort --cfg check_feature_gate ifdef IS_MSVC - $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib $(call OUT_EXE,foo) || exit 0 && exit 1 + $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(call OUT_EXE,foo) /link $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib || exit 0 && exit 1 else $(CC) $(CFLAGS) $(TMPDIR)/foo.o $(TARGET_LIBDIR)/liballoc-*.rlib $(TARGET_LIBDIR)/libcore-*.rlib $(TARGET_LIBDIR)/libcompiler_builtins-*.rlib -o $(call RUN_BINFILE,foo) || exit 0 && exit 1 endif From 3082865e6c65e16fbb892ef74ff3a67a0bfc243b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 May 2023 14:47:56 +0000 Subject: [PATCH 13/14] Ignore test on MSVC for now I can't figure out how to link with the MSVC toolchain --- tests/{run-make-fulldeps => run-make}/no-alloc-shim/Makefile | 3 +++ tests/{run-make-fulldeps => run-make}/no-alloc-shim/foo.rs | 0 2 files changed, 3 insertions(+) rename tests/{run-make-fulldeps => run-make}/no-alloc-shim/Makefile (91%) rename tests/{run-make-fulldeps => run-make}/no-alloc-shim/foo.rs (100%) diff --git a/tests/run-make-fulldeps/no-alloc-shim/Makefile b/tests/run-make/no-alloc-shim/Makefile similarity index 91% rename from tests/run-make-fulldeps/no-alloc-shim/Makefile rename to tests/run-make/no-alloc-shim/Makefile index f3dbbf1fd63e6..568e3f9ba1d68 100644 --- a/tests/run-make-fulldeps/no-alloc-shim/Makefile +++ b/tests/run-make/no-alloc-shim/Makefile @@ -1,5 +1,8 @@ include ../tools.mk +# ignore-cross-compile +# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain + TARGET_LIBDIR = $$($(RUSTC) --print target-libdir) all: diff --git a/tests/run-make-fulldeps/no-alloc-shim/foo.rs b/tests/run-make/no-alloc-shim/foo.rs similarity index 100% rename from tests/run-make-fulldeps/no-alloc-shim/foo.rs rename to tests/run-make/no-alloc-shim/foo.rs From 33d9b5880885862fdf4ec5bf70f45bf0e503a7fc Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 May 2023 16:23:45 +0000 Subject: [PATCH 14/14] Bless miri tests --- src/tools/miri/tests/fail/memleak.stderr | 4 ++-- src/tools/miri/tests/fail/memleak_rc.32bit.stderr | 4 ++-- src/tools/miri/tests/fail/memleak_rc.64bit.stderr | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/tests/fail/memleak.stderr b/src/tools/miri/tests/fail/memleak.stderr index 6d9b664c8f483..12bb944b07677 100644 --- a/src/tools/miri/tests/fail/memleak.stderr +++ b/src/tools/miri/tests/fail/memleak.stderr @@ -1,8 +1,8 @@ error: memory leaked: ALLOC (Rust heap, size: 4, align: 4), allocated here: --> RUSTLIB/alloc/src/alloc.rs:LL:CC | -LL | unsafe { __rust_alloc(layout.size(), layout.align()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | __rust_alloc(layout.size(), layout.align()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC diff --git a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr index 0e1146cf4ad93..87c5f466bc4be 100644 --- a/src/tools/miri/tests/fail/memleak_rc.32bit.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.32bit.stderr @@ -1,8 +1,8 @@ error: memory leaked: ALLOC (Rust heap, size: 16, align: 4), allocated here: --> RUSTLIB/alloc/src/alloc.rs:LL:CC | -LL | unsafe { __rust_alloc(layout.size(), layout.align()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | __rust_alloc(layout.size(), layout.align()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC diff --git a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr index 4979588f370ff..ec5f5f5bed368 100644 --- a/src/tools/miri/tests/fail/memleak_rc.64bit.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.64bit.stderr @@ -1,8 +1,8 @@ error: memory leaked: ALLOC (Rust heap, size: 32, align: 8), allocated here: --> RUSTLIB/alloc/src/alloc.rs:LL:CC | -LL | unsafe { __rust_alloc(layout.size(), layout.align()) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | __rust_alloc(layout.size(), layout.align()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: inside `std::alloc::alloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `std::alloc::Global::alloc_impl` at RUSTLIB/alloc/src/alloc.rs:LL:CC