|  | //! Allocator shim | 
|  | // Adapted from rustc | 
|  |  | 
|  | use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; | 
|  | use rustc_ast::expand::allocator::{ | 
|  | ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, | 
|  | alloc_error_handler_name, default_fn_name, global_fn_name, | 
|  | }; | 
|  | use rustc_codegen_ssa::base::allocator_kind_for_codegen; | 
|  | use rustc_session::config::OomStrategy; | 
|  | use rustc_symbol_mangling::mangle_internal_symbol; | 
|  |  | 
|  | use crate::prelude::*; | 
|  |  | 
|  | /// Returns whether an allocator shim was created | 
|  | pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { | 
|  | let Some(kind) = allocator_kind_for_codegen(tcx) else { return false }; | 
|  | codegen_inner( | 
|  | tcx, | 
|  | module, | 
|  | kind, | 
|  | tcx.alloc_error_handler_kind(()).unwrap(), | 
|  | tcx.sess.opts.unstable_opts.oom, | 
|  | ); | 
|  | true | 
|  | } | 
|  |  | 
|  | fn codegen_inner( | 
|  | tcx: TyCtxt<'_>, | 
|  | module: &mut dyn Module, | 
|  | kind: AllocatorKind, | 
|  | alloc_error_handler_kind: AllocatorKind, | 
|  | oom_strategy: OomStrategy, | 
|  | ) { | 
|  | let usize_ty = module.target_config().pointer_type(); | 
|  |  | 
|  | if kind == AllocatorKind::Default { | 
|  | for method in ALLOCATOR_METHODS { | 
|  | let mut arg_tys = Vec::with_capacity(method.inputs.len()); | 
|  | for input in method.inputs.iter() { | 
|  | match input.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"), | 
|  | } | 
|  | } | 
|  | let output = match method.output { | 
|  | AllocatorTy::ResultPtr => Some(usize_ty), | 
|  | AllocatorTy::Unit => None, | 
|  |  | 
|  | 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, | 
|  | sig, | 
|  | &mangle_internal_symbol(tcx, &global_fn_name(method.name)), | 
|  | &mangle_internal_symbol(tcx, &default_fn_name(method.name)), | 
|  | ); | 
|  | } | 
|  | } | 
|  |  | 
|  | 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, | 
|  | sig, | 
|  | &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), | 
|  | &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), | 
|  | ); | 
|  |  | 
|  | { | 
|  | let sig = Signature { | 
|  | call_conv: module.target_config().default_call_conv, | 
|  | params: vec![], | 
|  | returns: vec![AbiParam::new(types::I8)], | 
|  | }; | 
|  | let func_id = module | 
|  | .declare_function( | 
|  | &mangle_internal_symbol(tcx, OomStrategy::SYMBOL), | 
|  | Linkage::Export, | 
|  | &sig, | 
|  | ) | 
|  | .unwrap(); | 
|  | let mut ctx = Context::new(); | 
|  | ctx.func.signature = sig; | 
|  | { | 
|  | let mut func_ctx = FunctionBuilderContext::new(); | 
|  | let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); | 
|  |  | 
|  | let block = bcx.create_block(); | 
|  | bcx.switch_to_block(block); | 
|  | let value = bcx.ins().iconst(types::I8, oom_strategy.should_panic() as i64); | 
|  | bcx.ins().return_(&[value]); | 
|  | bcx.seal_all_blocks(); | 
|  | bcx.finalize(); | 
|  | } | 
|  | module.define_function(func_id, &mut ctx).unwrap(); | 
|  | } | 
|  |  | 
|  | { | 
|  | let sig = Signature { | 
|  | call_conv: module.target_config().default_call_conv, | 
|  | params: vec![], | 
|  | returns: vec![], | 
|  | }; | 
|  | let func_id = module | 
|  | .declare_function( | 
|  | &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), | 
|  | Linkage::Export, | 
|  | &sig, | 
|  | ) | 
|  | .unwrap(); | 
|  |  | 
|  | let mut ctx = Context::new(); | 
|  | ctx.func.signature = sig; | 
|  | let mut func_ctx = FunctionBuilderContext::new(); | 
|  | let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); | 
|  |  | 
|  | let block = bcx.create_block(); | 
|  | bcx.switch_to_block(block); | 
|  | bcx.ins().return_(&[]); | 
|  | bcx.seal_all_blocks(); | 
|  | bcx.finalize(); | 
|  |  | 
|  | module.define_function(func_id, &mut ctx).unwrap(); | 
|  | } | 
|  | } |