From 0df3b41630119f3b2dc3db27bf5ace942f210871 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 26 Mar 2019 19:53:04 +0100 Subject: [PATCH] Skip ZST arguments Fixes #413 and increases compatibility with cg_llvm --- example/mini_core_hello_world.rs | 2 + src/abi.rs | 138 ++++++++++--------------------- src/base.rs | 3 +- src/pretty_clif.rs | 2 +- 4 files changed, 49 insertions(+), 96 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 4dea94e3687..e69c509b763 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -206,4 +206,6 @@ fn main() { } unsafe { assert_eq!(ABC as usize, 0); } + + &mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>; } diff --git a/src/abi.rs b/src/abi.rs index 45c2c6d3719..79bdfcc1240 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -1,7 +1,5 @@ use std::borrow::Cow; -use std::iter; -use rustc::hir; use rustc::ty::layout::{FloatTy, Integer, Primitive, Scalar}; use rustc_target::spec::abi::Abi; @@ -44,26 +42,16 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type { fn get_pass_mode<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, - is_return: bool, ) -> PassMode { let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); assert!(!layout.is_unsized()); - if layout.size.bytes() == 0 { - if is_return { - PassMode::NoPass - } else { - PassMode::ByRef - } + if layout.is_zst() { + // WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer + PassMode::NoPass } else { match &layout.abi { - layout::Abi::Uninhabited => { - if is_return { - PassMode::NoPass - } else { - PassMode::ByRef - } - } + layout::Abi::Uninhabited => PassMode::NoPass, layout::Abi::Scalar(scalar) => { PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())) } @@ -80,11 +68,11 @@ fn get_pass_mode<'a, 'tcx: 'a>( fn adjust_arg_for_abi<'a, 'tcx: 'a>( fx: &mut FunctionCx<'a, 'tcx, impl Backend>, arg: CValue<'tcx>, -) -> Value { - match get_pass_mode(fx.tcx, arg.layout().ty, false) { - PassMode::NoPass => unimplemented!("pass mode nopass"), - PassMode::ByVal(_) => arg.load_scalar(fx), - PassMode::ByRef => arg.force_stack(fx), +) -> Option { + match get_pass_mode(fx.tcx, arg.layout().ty) { + PassMode::NoPass => None, + PassMode::ByVal(_) => Some(arg.load_scalar(fx)), + PassMode::ByRef => Some(arg.force_stack(fx)), } } @@ -109,13 +97,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t let inputs = inputs .into_iter() - .filter_map(|ty| match get_pass_mode(tcx, ty, false) { + .filter_map(|ty| match get_pass_mode(tcx, ty) { + PassMode::NoPass => None, PassMode::ByVal(clif_ty) => Some(clif_ty), - PassMode::NoPass => unimplemented!("pass mode nopass"), PassMode::ByRef => Some(pointer_ty(tcx)), }); - let (params, returns) = match get_pass_mode(tcx, output, true) { + let (params, returns) = match get_pass_mode(tcx, output) { PassMode::NoPass => (inputs.map(AbiParam::new).collect(), vec![]), PassMode::ByVal(ret_ty) => ( inputs.map(AbiParam::new).collect(), @@ -140,59 +128,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t } } -pub fn ty_fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> ty::FnSig<'tcx> { - let sig = match ty.sty { - ty::FnDef(..) | - // Shims currently have type TyFnPtr. Not sure this should remain. - ty::FnPtr(_) => ty.fn_sig(tcx), - ty::Closure(def_id, substs) => { - let sig = substs.closure_sig(def_id, tcx); - - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.c_variadic, - sig.unsafety, - sig.abi - )) - } - ty::Generator(def_id, substs, _) => { - let sig = substs.poly_sig(def_id, tcx); - - let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - - sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[ - sig.yield_ty.into(), - sig.return_ty.into(), - ]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - - tcx.mk_fn_sig(iter::once(env_ty), - ret_ty, - false, - hir::Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} to ty_fn_sig", ty) - }; - tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &sig) -} - pub fn get_function_name_and_sig<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, inst: Instance<'tcx>, support_vararg: bool, ) -> (String, Signature) { assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types()); - let fn_ty = inst.ty(tcx); - let fn_sig = ty_fn_sig(tcx, fn_ty); + let fn_sig = tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &inst.fn_sig(tcx)); if fn_sig.c_variadic && !support_vararg { unimpl!("Variadic function definitions are not yet supported"); } @@ -293,7 +235,7 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> { } fn self_sig(&self) -> FnSig<'tcx> { - ty_fn_sig(self.tcx, self.instance.ty(self.tcx)) + self.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &self.instance.fn_sig(self.tcx)) } fn return_type(&self) -> Ty<'tcx> { @@ -405,9 +347,14 @@ fn cvalue_for_param<'a, 'tcx: 'a>( local_field: Option, arg_ty: Ty<'tcx>, ssa_flags: crate::analyze::Flags, -) -> CValue<'tcx> { +) -> Option> { let layout = fx.layout_of(arg_ty); - let pass_mode = get_pass_mode(fx.tcx, arg_ty, false); + let pass_mode = get_pass_mode(fx.tcx, arg_ty); + + if let PassMode::NoPass = pass_mode { + return None; + } + let clif_type = pass_mode.get_param_ty(fx); let ebb_param = fx.bcx.append_ebb_param(start_ebb, clif_type); @@ -424,9 +371,9 @@ fn cvalue_for_param<'a, 'tcx: 'a>( ); match pass_mode { - PassMode::NoPass => unimplemented!("pass mode nopass"), - PassMode::ByVal(_) => CValue::ByVal(ebb_param, layout), - PassMode::ByRef => CValue::ByRef(ebb_param, layout), + PassMode::NoPass => unreachable!(), + PassMode::ByVal(_) => Some(CValue::ByVal(ebb_param, layout)), + PassMode::ByRef => Some(CValue::ByRef(ebb_param, layout)), } } @@ -440,7 +387,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>( fx.add_global_comment(format!("ssa {:?}", ssa_analyzed)); let ret_layout = fx.layout_of(fx.return_type()); - let output_pass_mode = get_pass_mode(fx.tcx, fx.return_type(), true); + let output_pass_mode = get_pass_mode(fx.tcx, fx.return_type()); let ret_param = match output_pass_mode { PassMode::NoPass => None, PassMode::ByVal(_) => None, @@ -462,9 +409,10 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>( ); } + // None means pass_mode == NoPass enum ArgKind<'tcx> { - Normal(CValue<'tcx>), - Spread(Vec>), + Normal(Option>), + Spread(Vec>>), } let func_params = fx @@ -542,13 +490,17 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>( match arg_kind { ArgKind::Normal(param) => { - place.write_cvalue(fx, param); + if let Some(param) = param { + place.write_cvalue(fx, param); + } } ArgKind::Spread(params) => { for (i, param) in params.into_iter().enumerate() { - place - .place_field(fx, mir::Field::new(i)) - .write_cvalue(fx, param); + if let Some(param) = param { + place + .place_field(fx, mir::Field::new(i)) + .write_cvalue(fx, param); + } } } } @@ -578,7 +530,7 @@ pub fn codegen_terminator_call<'a, 'tcx: 'a>( destination: &Option<(Place<'tcx>, BasicBlock)>, ) { let fn_ty = fx.monomorphize(&func.ty(fx.mir, fx.tcx)); - let sig = ty_fn_sig(fx.tcx, fn_ty); + let sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx)); // Unpack arguments tuple for closures let args = if sig.abi == Abi::RustCall { @@ -649,11 +601,11 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>( args: Vec>, ret_place: Option>, ) { - let fn_sig = ty_fn_sig(fx.tcx, fn_ty); + let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx)); let ret_layout = fx.layout_of(fn_sig.output()); - let output_pass_mode = get_pass_mode(fx.tcx, fn_sig.output(), true); + let output_pass_mode = get_pass_mode(fx.tcx, fn_sig.output()); let return_ptr = match output_pass_mode { PassMode::NoPass => None, PassMode::ByRef => match ret_place { @@ -683,7 +635,7 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>( } // Normal call - Some(_) => (None, args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg))), + Some(_) => (None, args.get(0).and_then(|arg| adjust_arg_for_abi(fx, *arg))), // Indirect call None => { @@ -691,7 +643,7 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>( .load_scalar(fx); ( Some(func), - args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg)), + args.get(0).and_then(|arg| adjust_arg_for_abi(fx, *arg)), ) } }; @@ -702,7 +654,7 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>( .chain( args.into_iter() .skip(1) - .map(|arg| adjust_arg_for_abi(fx, arg)), + .filter_map(|arg| adjust_arg_for_abi(fx, arg)), ) .collect::>(); @@ -756,9 +708,9 @@ pub fn codegen_drop<'a, 'tcx: 'a>( let (ptr, vtable) = drop_place.to_addr_maybe_unsized(fx); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap()); - let fn_sig = ty_fn_sig(fx.tcx, drop_fn_ty); + let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &drop_fn_ty.fn_sig(fx.tcx)); - match get_pass_mode(fx.tcx, fn_sig.output(), true) { + match get_pass_mode(fx.tcx, fn_sig.output()) { PassMode::NoPass => {} _ => unreachable!(), }; @@ -770,7 +722,7 @@ pub fn codegen_drop<'a, 'tcx: 'a>( } pub fn codegen_return(fx: &mut FunctionCx) { - match get_pass_mode(fx.tcx, fx.return_type(), true) { + match get_pass_mode(fx.tcx, fx.return_type()) { PassMode::NoPass | PassMode::ByRef => { fx.bcx.ins().return_(&[]); } diff --git a/src/base.rs b/src/base.rs index b36e673854e..ec057dd81d4 100644 --- a/src/base.rs +++ b/src/base.rs @@ -69,8 +69,7 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>( // FIXME implement u128 and i128 support // Step 2a. Check sig for u128 and i128 - let fn_ty = instance.ty(tcx); - let fn_sig = crate::abi::ty_fn_sig(tcx, fn_ty); + let fn_sig = tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx)); struct UI128Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>, bool); diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 31ca4168d24..ee16c68214b 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -75,7 +75,7 @@ impl CommentWriter { global_comments: vec![ format!("symbol {}", tcx.symbol_name(instance).as_str()), format!("instance {:?}", instance), - format!("sig {:?}", crate::abi::ty_fn_sig(tcx, instance.ty(tcx))), + format!("sig {:?}", tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx))), String::new(), ], entity_comments: HashMap::new(),