From 552ea447e48264036f7e67159358dec855e9c9ba Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 28 Oct 2019 21:16:41 +0200 Subject: [PATCH 01/20] rustc: combine Instance::fn_sig_noadjust and Instance::fn_sig. --- src/librustc/ty/instance.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 777db38850fec..856be6f3c7791 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -62,12 +62,24 @@ impl<'tcx> Instance<'tcx> { ) } - fn fn_sig_noadjust(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { + pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { let ty = self.ty(tcx); match ty.kind { ty::FnDef(..) | // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => ty.fn_sig(tcx), + ty::FnPtr(_) => { + let mut sig = ty.fn_sig(tcx); + if let InstanceDef::VtableShim(..) = self.def { + // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. + sig = sig.map_bound(|mut sig| { + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + sig + }); + } + sig + } ty::Closure(def_id, substs) => { let sig = substs.as_closure().sig(def_id, tcx); @@ -108,22 +120,8 @@ impl<'tcx> Instance<'tcx> { ) }) } - _ => bug!("unexpected type {:?} in Instance::fn_sig_noadjust", ty) - } - } - - pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let mut fn_sig = self.fn_sig_noadjust(tcx); - if let InstanceDef::VtableShim(..) = self.def { - // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. - fn_sig = fn_sig.map_bound(|mut fn_sig| { - let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); - inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); - fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); - fn_sig - }); + _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) } - fn_sig } } From 4810cf1d1b27377e9c3633e4c1e820e197b270ac Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 3 Dec 2019 12:54:47 +0200 Subject: [PATCH 02/20] rustc_mir: don't hardcode InstanceDef::VtableShim behavior to Adjustment::DerefMove. --- src/librustc_mir/shim.rs | 42 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 680f75eb84e2c..fc606db98be0c 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -35,7 +35,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx ty::InstanceDef::VtableShim(def_id) => { build_call_shim( tcx, - def_id, + instance, Adjustment::DerefMove, CallKind::Direct(def_id), None, @@ -60,7 +60,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx build_call_shim( tcx, - def_id, + instance, adjustment, CallKind::Indirect, Some(arg_tys) @@ -74,13 +74,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx ty::InstanceDef::ReifyShim(def_id) => { build_call_shim( tcx, - def_id, + instance, Adjustment::Identity, CallKind::Direct(def_id), None ) } - ty::InstanceDef::ClosureOnceShim { call_once } => { + ty::InstanceDef::ClosureOnceShim { call_once: _ } => { let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); let call_mut = tcx .associated_items(fn_mut) @@ -89,7 +89,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx build_call_shim( tcx, - call_once, + instance, Adjustment::RefMut, CallKind::Direct(call_mut), None @@ -697,7 +697,7 @@ impl CloneShimBuilder<'tcx> { } } -/// Builds a "call" shim for `def_id`. The shim calls the +/// Builds a "call" shim for `instance`. The shim calls the /// function specified by `call_kind`, first adjusting its first /// argument according to `rcvr_adjustment`. /// @@ -705,17 +705,30 @@ impl CloneShimBuilder<'tcx> { /// function will be untupled as these types. fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + instance: ty::InstanceDef<'tcx>, rcvr_adjustment: Adjustment, call_kind: CallKind, untuple_args: Option<&[Ty<'tcx>]>, ) -> BodyCache<'tcx> { - debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \ + debug!("build_call_shim(instance={:?}, rcvr_adjustment={:?}, \ call_kind={:?}, untuple_args={:?})", - def_id, rcvr_adjustment, call_kind, untuple_args); + instance, rcvr_adjustment, call_kind, untuple_args); + let def_id = instance.def_id(); let sig = tcx.fn_sig(def_id); - let sig = tcx.erase_late_bound_regions(&sig); + let mut sig = tcx.erase_late_bound_regions(&sig); + + // FIXME(eddyb) avoid having this snippet both here and in + // `Instance::fn_sig` (introduce `InstanceDef::fn_sig`?). + if let ty::InstanceDef::VtableShim(..) = instance { + // Modify fn(self, ...) to fn(self: *mut Self, ...) + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + let self_arg = &mut inputs_and_output[0]; + debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param); + *self_arg = tcx.mk_mut_ptr(*self_arg); + sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + } + let span = tcx.def_span(def_id); debug!("build_call_shim: sig={:?}", sig); @@ -730,14 +743,7 @@ fn build_call_shim<'tcx>( let rcvr = match rcvr_adjustment { Adjustment::Identity => Operand::Move(rcvr_l), Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)), - Adjustment::DerefMove => { - // fn(Self, ...) -> fn(*mut Self, ...) - let arg_ty = local_decls[rcvr_arg].ty; - debug_assert!(tcx.generics_of(def_id).has_self && arg_ty == tcx.types.self_param); - local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty); - - Operand::Move(tcx.mk_place_deref(rcvr_l)) - } + Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_l)), Adjustment::RefMut => { // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push(temp_decl( From a57aea88d4620008ff06ed8e23f093a2e88b33f9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 3 Dec 2019 12:55:58 +0200 Subject: [PATCH 03/20] rustc: expose the mir::Body reference lifetime from mir::ReadOnlyBodyCache (#64736 fallout). --- src/librustc/mir/cache.rs | 12 ++------ src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 4 +-- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 ++-- .../borrow_check/conflict_errors.rs | 10 +++---- .../borrow_check/error_reporting.rs | 6 ++-- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/move_errors.rs | 8 +++--- .../borrow_check/mutability_errors.rs | 8 +++--- .../borrow_check/nll/type_check/mod.rs | 28 +++++++++---------- src/librustc_mir/borrow_check/prefixes.rs | 2 +- .../transform/check_consts/qualifs.rs | 6 ++-- .../transform/check_consts/resolver.rs | 2 +- .../transform/check_consts/validation.rs | 16 +++++------ src/librustc_mir/transform/promote_consts.rs | 18 ++++++------ 16 files changed, 62 insertions(+), 70 deletions(-) diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index b8ef4f753f368..95e9f098da3fb 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -279,18 +279,10 @@ impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for ReadOnlyBodyCache<'a, 'tcx> { impl Deref for ReadOnlyBodyCache<'a, 'tcx> { - type Target = Body<'tcx>; + type Target = &'a Body<'tcx>; fn deref(&self) -> &Self::Target { - self.body - } -} - -impl Index for ReadOnlyBodyCache<'a, 'tcx> { - type Output = BasicBlockData<'tcx>; - - fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { - &self.body[index] + &self.body } } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index f15456e0ff841..6c627085b2ed8 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -131,7 +131,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, &*self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, *self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 23a5b0cf32ac2..1b0663e0d24dc 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -324,7 +324,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(&*self.mir, bx.tcx()).ty; + let ty = location.ty(*self.mir, bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); @@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let extra_args = &args[sig.inputs().len()..]; let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(&*self.mir, bx.tcx()); + let op_ty = op_arg.ty(*self.mir, bx.tcx()); self.monomorphize(&op_ty) }).collect::>(); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 9dd4d0ec22f23..e2507394ce681 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -594,7 +594,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let place_ty = mir::Place::ty_from( place_ref.base, place_ref.projection, - &*self.mir, + *self.mir, tcx, ); self.monomorphize(&place_ty.ty) diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 3bae027e7634d..488ae8dbf9036 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(&*self.mir, bx.tcx()); + let discr_ty = rvalue.ty(*self.mir, bx.tcx()); let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { @@ -513,7 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(&*self.mir, self.cx.tcx()); + let ty = rvalue.ty(*self.mir, self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -710,7 +710,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(&*self.mir, self.cx.tcx()); + let ty = rvalue.ty(*self.mir, self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 73a9fd81c9b4f..b1e327cdb0ef3 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -208,7 +208,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from( used_place.base, used_place.projection, - &*self.body, + *self.body, self.infcx.tcx ).ty; let needs_note = match ty.kind { @@ -225,7 +225,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mpi = self.move_data.moves[move_out_indices[0]].path; let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(&*self.body, self.infcx.tcx).ty; + let ty = place.ty(*self.body, self.infcx.tcx).ty; let opt_name = self.describe_place_with_options(place.as_ref(), IncludingDowncast(true)); let note_msg = match opt_name { @@ -625,7 +625,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from( place_base, place_projection, - &*self.body, + *self.body, self.infcx.tcx ).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) @@ -1635,7 +1635,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Place::ty_from( &place.base, proj_base, - &*self.body, + *self.body, tcx ).ty.is_box(), "Drop of value behind a reference or raw pointer" @@ -1648,7 +1648,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( &place.base, proj_base, - &*self.body, + *self.body, tcx ).ty; match base_ty.kind { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index cc15d236b2325..9953d2807437a 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -372,7 +372,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( place.base, place.projection, - &*self.body, + *self.body, self.infcx.tcx).ty; self.describe_field_from_ty(&base_ty, field, Some(*variant_index)) } @@ -502,7 +502,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }) = bbd.terminator { if let Some(source) = BorrowedContentSource::from_call( - func.ty(&*self.body, tcx), + func.ty(*self.body, tcx), tcx ) { return source; @@ -519,7 +519,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let base_ty = Place::ty_from( deref_base.base, deref_base.projection, - &*self.body, + *self.body, tcx ).ty; if base_ty.is_unsafe_ptr() { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index da08de7690ab2..bacff0b3e54d2 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -646,7 +646,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx let tcx = self.infcx.tcx; // Compute the type with accurate region information. - let drop_place_ty = drop_place.ty(&*self.body, self.infcx.tcx); + let drop_place_ty = drop_place.ty(*self.body, self.infcx.tcx); // Erase the regions. let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty; diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 388a8abd5fc1f..fd779767d7a89 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. - let ty = deref_target_place.ty(&*self.body, self.infcx.tcx).ty; + let ty = deref_target_place.ty(*self.body, self.infcx.tcx).ty; let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); @@ -411,7 +411,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let move_ty = format!( "{:?}", - move_place.ty(&*self.body, self.infcx.tcx).ty, + move_place.ty(*self.body, self.infcx.tcx).ty, ); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { let is_option = move_ty.starts_with("std::option::Option"); @@ -454,7 +454,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.is_empty() { - let place_ty = move_from.ty(&*self.body, self.infcx.tcx).ty; + let place_ty = move_from.ty(*self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), @@ -482,7 +482,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // No binding. Nothing to suggest. GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => { let span = use_spans.var_or_use(); - let place_ty = original_path.ty(&*self.body, self.infcx.tcx).ty; + let place_ty = original_path.ty(*self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { Some(desc) => format!("`{}`", desc), None => format!("value"), diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index e135f8d1be98d..98a7b101d56f7 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Place::ty_from( &the_place_err.base, proj_base, - &*self.body, + *self.body, self.infcx.tcx ).ty)); @@ -115,7 +115,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Place::ty_from( the_place_err.base, the_place_err.projection, - &*self.body, + *self.body, self.infcx.tcx ) .ty @@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((span, message)) = annotate_struct_field( self.infcx.tcx, - Place::ty_from(base, proj_base, &*self.body, self.infcx.tcx).ty, + Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty, field, ) { err.span_suggestion( @@ -304,7 +304,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { debug_assert!(is_closure_or_generator( - Place::ty_from(base, proj_base, &*self.body, self.infcx.tcx).ty + Place::ty_from(base, proj_base, *self.body, self.infcx.tcx).ty )); err.span_label(span, format!("cannot {ACT}", ACT = act)); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a554867389e12..de304202a0840 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1413,9 +1413,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { _ => ConstraintCategory::Assignment, }; - let place_ty = place.ty(&*body, tcx).ty; + let place_ty = place.ty(*body, tcx).ty; let place_ty = self.normalize(place_ty, location); - let rv_ty = rv.ty(&*body, tcx); + let rv_ty = rv.ty(*body, tcx); let rv_ty = self.normalize(rv_ty, location); if let Err(terr) = self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category) @@ -1467,7 +1467,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ref place, variant_index, } => { - let place_type = place.ty(&*body, tcx).ty; + let place_type = place.ty(*body, tcx).ty; let adt = match place_type.kind { ty::Adt(adt, _) if adt.is_enum() => adt, _ => { @@ -1489,7 +1489,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; } StatementKind::AscribeUserType(box(ref place, ref projection), variance) => { - let place_ty = place.ty(&*body, tcx).ty; + let place_ty = place.ty(*body, tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, variance, @@ -2010,7 +2010,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // While this is located in `nll::typeck` this error is not an NLL error, it's // a required check to make sure that repeated elements implement `Copy`. let span = body.source_info(location).span; - let ty = operand.ty(&*body, tcx); + let ty = operand.ty(*body, tcx); if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { // To determine if `const_in_array_repeat_expressions` feature gate should // be mentioned, need to check if the rvalue is promotable. @@ -2064,7 +2064,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Cast(cast_kind, op, ty) => { match cast_kind { CastKind::Pointer(PointerCast::ReifyFnPointer) => { - let fn_sig = op.ty(&*body, tcx).fn_sig(tcx); + let fn_sig = op.ty(*body, tcx).fn_sig(tcx); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a @@ -2093,7 +2093,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { - let sig = match op.ty(&*body, tcx).kind { + let sig = match op.ty(*body, tcx).kind { ty::Closure(def_id, substs) => { substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx) } @@ -2119,7 +2119,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::UnsafeFnPointer) => { - let fn_sig = op.ty(&*body, tcx).fn_sig(tcx); + let fn_sig = op.ty(*body, tcx).fn_sig(tcx); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a @@ -2151,7 +2151,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let &ty = ty; let trait_ref = ty::TraitRef { def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), - substs: tcx.mk_substs_trait(op.ty(&*body, tcx), &[ty.into()]), + substs: tcx.mk_substs_trait(op.ty(*body, tcx), &[ty.into()]), }; self.prove_trait_ref( @@ -2162,7 +2162,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::MutToConstPointer) => { - let ty_from = match op.ty(&*body, tcx).kind { + let ty_from = match op.ty(*body, tcx).kind { ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mutable, @@ -2210,7 +2210,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ArrayToPointer) => { - let ty_from = op.ty(&*body, tcx); + let ty_from = op.ty(*body, tcx); let opt_ty_elem = match ty_from.kind { ty::RawPtr( @@ -2272,7 +2272,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Misc => { - let ty_from = op.ty(&*body, tcx); + let ty_from = op.ty(*body, tcx); let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(ty); match (cast_ty_from, cast_ty_to) { @@ -2339,9 +2339,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::BinaryOp(BinOp::Le, left, right) | Rvalue::BinaryOp(BinOp::Gt, left, right) | Rvalue::BinaryOp(BinOp::Ge, left, right) => { - let ty_left = left.ty(&*body, tcx); + let ty_left = left.ty(*body, tcx); if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.kind { - let ty_right = right.ty(&*body, tcx); + let ty_right = right.ty(*body, tcx); let common_ty = self.infcx.next_ty_var( TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 06b9d4dbde003..b58bf737a3575 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -143,7 +143,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // derefs, except we stop at the deref of a shared // reference. - let ty = Place::ty_from(cursor.base, proj_base, &*self.body, self.tcx).ty; + let ty = Place::ty_from(cursor.base, proj_base, *self.body, self.tcx).ty; match ty.kind { ty::RawPtr(_) | ty::Ref( diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 62b4a4ccc9894..223a5f8d605fc 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -51,7 +51,7 @@ pub trait Qualif { }); let qualif = base_qualif && Self::in_any_value_of_ty( cx, - Place::ty_from(place.base, proj_base, &*cx.body, cx.tcx) + Place::ty_from(place.base, proj_base, *cx.body, cx.tcx) .projection_ty(cx.tcx, elem) .ty, ); @@ -155,7 +155,7 @@ pub trait Qualif { // Special-case reborrows to be more like a copy of the reference. if let &[ref proj_base @ .., elem] = place.projection.as_ref() { if ProjectionElem::Deref == elem { - let base_ty = Place::ty_from(&place.base, proj_base, &*cx.body, cx.tcx).ty; + let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; if let ty::Ref(..) = base_ty.kind { return Self::in_place(cx, per_local, PlaceRef { base: &place.base, @@ -221,7 +221,7 @@ impl Qualif for HasMutInterior { Rvalue::Aggregate(ref kind, _) => { if let AggregateKind::Adt(def, ..) = **kind { if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() { - let ty = rvalue.ty(&*cx.body, cx.tcx); + let ty = rvalue.ty(*cx.body, cx.tcx); assert_eq!(Self::in_any_value_of_ty(cx, ty), true); return true; } diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index 9004c5be987fd..cb542484be633 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -77,7 +77,7 @@ where args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ) { - let return_ty = return_place.ty(&*self.item.body, self.item.tcx).ty; + let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty; let qualif = Q::in_call( self.item, &|l| self.qualifs_per_local.contains(l), diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 9d477bfbae81f..663a5243e8fe2 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -304,7 +304,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // Special-case reborrows to be more like a copy of a reference. if let Rvalue::Ref(_, kind, ref place) = *rvalue { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, &*self.body, place) { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { let ctx = match kind { BorrowKind::Shared => PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow, @@ -342,7 +342,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { | Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place) | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => { - let ty = place.ty(&*self.body, self.tcx).ty; + let ty = place.ty(*self.body, self.tcx).ty; let is_allowed = match ty.kind { // Inside a `static mut`, `&mut [...]` is allowed. ty::Array(..) | ty::Slice(_) if self.const_kind() == ConstKind::StaticMut @@ -390,7 +390,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { - let operand_ty = operand.ty(&*self.body, self.tcx); + let operand_ty = operand.ty(*self.body, self.tcx); let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); @@ -401,7 +401,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(&*self.body, self.tcx).kind { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(*self.body, self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -475,7 +475,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(place_base, proj_base, &*self.body, self.tcx).ty; + let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty; if let ty::RawPtr(_) = base_ty.kind { if proj_base.is_empty() { if let (PlaceBase::Local(local), []) = (place_base, proj_base) { @@ -499,7 +499,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { ProjectionElem::Subslice {..} | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - let base_ty = Place::ty_from(place_base, proj_base, &*self.body, self.tcx).ty; + let base_ty = Place::ty_from(place_base, proj_base, *self.body, self.tcx).ty; match base_ty.ty_adt_def() { Some(def) if def.is_union() => { self.check_op(ops::UnionAccess); @@ -548,7 +548,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match kind { TerminatorKind::Call { func, .. } => { - let fn_ty = func.ty(&*self.body, self.tcx); + let fn_ty = func.ty(*self.body, self.tcx); let def_id = match fn_ty.kind { ty::FnDef(def_id, _) => def_id, @@ -609,7 +609,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { // Check to see if the type of this place can ever have a drop impl. If not, this // `Drop` terminator is frivolous. let ty_needs_drop = dropped_place - .ty(&*self.body, self.tcx) + .ty(*self.body, self.tcx) .ty .needs_drop(self.tcx, self.param_env); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index c99824bd35647..c758ccfd11d91 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -350,7 +350,7 @@ impl<'tcx> Validator<'_, 'tcx> { let ty = Place::ty_from( &place.base, proj_base, - &*self.body, + *self.body, self.tcx ) .projection_ty(self.tcx, elem) @@ -373,7 +373,7 @@ impl<'tcx> Validator<'_, 'tcx> { } if let BorrowKind::Mut { .. } = kind { - let ty = place.ty(&*self.body, self.tcx).ty; + let ty = place.ty(*self.body, self.tcx).ty; // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] @@ -522,7 +522,7 @@ impl<'tcx> Validator<'_, 'tcx> { ProjectionElem::Field(..) => { if self.const_kind.is_none() { let base_ty = - Place::ty_from(place.base, proj_base, &*self.body, self.tcx).ty; + Place::ty_from(place.base, proj_base, *self.body, self.tcx).ty; if let Some(def) = base_ty.ty_adt_def() { // No promotion of union field accesses. if def.is_union() { @@ -571,7 +571,7 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { match *rvalue { Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.const_kind.is_none() => { - let operand_ty = operand.ty(&*self.body, self.tcx); + let operand_ty = operand.ty(*self.body, self.tcx); let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); match (cast_in, cast_out) { @@ -585,7 +585,7 @@ impl<'tcx> Validator<'_, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) if self.const_kind.is_none() => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(&*self.body, self.tcx).kind { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(*self.body, self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -620,7 +620,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::Ref(_, kind, place) => { if let BorrowKind::Mut { .. } = kind { - let ty = place.ty(&*self.body, self.tcx).ty; + let ty = place.ty(*self.body, self.tcx).ty; // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] @@ -647,7 +647,7 @@ impl<'tcx> Validator<'_, 'tcx> { let mut place = place.as_ref(); if let [proj_base @ .., ProjectionElem::Deref] = &place.projection { let base_ty = - Place::ty_from(&place.base, proj_base, &*self.body, self.tcx).ty; + Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.kind { place = PlaceRef { base: &place.base, @@ -673,7 +673,7 @@ impl<'tcx> Validator<'_, 'tcx> { while let [proj_base @ .., elem] = place_projection { // FIXME(eddyb) this is probably excessive, with // the exception of `union` member accesses. - let ty = Place::ty_from(place.base, proj_base, &*self.body, self.tcx) + let ty = Place::ty_from(place.base, proj_base, *self.body, self.tcx) .projection_ty(self.tcx, elem) .ty; if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) { @@ -706,7 +706,7 @@ impl<'tcx> Validator<'_, 'tcx> { callee: &Operand<'tcx>, args: &[Operand<'tcx>], ) -> Result<(), Unpromotable> { - let fn_ty = callee.ty(&*self.body, self.tcx); + let fn_ty = callee.ty(*self.body, self.tcx); if !self.explicit && self.const_kind.is_none() { if let ty::FnDef(def_id, _) = fn_ty.kind { From a7094f7ce3fbf7fd44e0c81cfdd00ec6d2a59cc1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 16:24:25 +0200 Subject: [PATCH 04/20] rustc_codegen_ssa: use &'tcx mir::Body<'tcx> instead of &'a ... for the MIR body. --- src/librustc_codegen_ssa/mir/block.rs | 43 ++++++++++++++------------- src/librustc_codegen_ssa/mir/mod.rs | 14 ++++----- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 1b0663e0d24dc..c8881ca5f9506 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -24,13 +24,14 @@ use super::operand::OperandValue::{Pair, Ref, Immediate}; /// Used by `FunctionCx::codegen_terminator` for emitting common patterns /// e.g., creating a basic block, calling a function, etc. -struct TerminatorCodegenHelper<'a, 'tcx> { - bb: &'a mir::BasicBlock, - terminator: &'a mir::Terminator<'tcx>, +struct TerminatorCodegenHelper<'tcx> { + bb: mir::BasicBlock, + terminator: &'tcx mir::Terminator<'tcx>, funclet_bb: Option, } -impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { +// FIXME(eddyb) clean up the lifetimes in this impl. +impl<'tcx> TerminatorCodegenHelper<'tcx> { /// Returns the associated funclet from `FunctionCx::funclets` for the /// `funclet_bb` member if it is not `None`. fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( @@ -132,7 +133,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } else { let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, llret); - if fx.mir[*self.bb].is_cleanup { + if fx.mir[self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested // struct, there are "symmetry" issues that cause @@ -151,15 +152,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { // Generate sideeffect intrinsic if jumping to any of the targets can form // a loop. - fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( + fn maybe_sideeffect<'b, Bx: BuilderMethods<'b, 'tcx>>( &self, - mir: mir::ReadOnlyBodyCache<'b, 'tcx>, + mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, bx: &mut Bx, targets: &[mir::BasicBlock], ) { if bx.tcx().sess.opts.debugging_opts.insert_sideeffect { - if targets.iter().any(|target| { - *target <= *self.bb + if targets.iter().any(|&target| { + target <= self.bb && target .start_location() .is_predecessor_of(self.bb.start_location(), mir) @@ -173,9 +174,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Codegen implementations for some terminator variants. impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Generates code for a `Resume` terminator. - fn codegen_resume_terminator<'b>( + fn codegen_resume_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, ) { if let Some(funclet) = helper.funclet(self) { @@ -201,9 +202,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - fn codegen_switchint_terminator<'b>( + fn codegen_switchint_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, discr: &mir::Operand<'tcx>, switch_ty: Ty<'tcx>, @@ -316,9 +317,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } - fn codegen_drop_terminator<'b>( + fn codegen_drop_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, location: &mir::Place<'tcx>, target: mir::BasicBlock, @@ -367,9 +368,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { unwind); } - fn codegen_assert_terminator<'b>( + fn codegen_assert_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, cond: &mir::Operand<'tcx>, @@ -446,9 +447,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); } - fn codegen_call_terminator<'b>( + fn codegen_call_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, @@ -807,14 +808,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, mut bx: Bx, bb: mir::BasicBlock, - terminator: &mir::Terminator<'tcx> + terminator: &'tcx mir::Terminator<'tcx> ) { debug!("codegen_terminator: {:?}", terminator); // Create the cleanup bundle, if needed. let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb); let helper = TerminatorCodegenHelper { - bb: &bb, terminator, funclet_bb + bb, terminator, funclet_bb }; self.set_debug_loc(&mut bx, terminator.source_info); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 8b60904081e66..600bdced4edd2 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -1,6 +1,6 @@ use rustc::ty::{self, Ty, TypeFoldable, Instance}; use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt}; -use rustc::mir::{self, Body, ReadOnlyBodyCache}; +use rustc::mir; use rustc_target::abi::call::{FnAbi, PassMode}; use crate::base; use crate::traits::*; @@ -21,7 +21,7 @@ use self::operand::{OperandRef, OperandValue}; pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: mir::ReadOnlyBodyCache<'a, 'tcx>, + mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, debug_context: Option>, @@ -76,7 +76,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// All `VarDebuginfo` from the MIR body, partitioned by `Local`. /// This is `None` if no variable debuginfo/names are needed. - per_local_var_debug_info: Option>>>, + per_local_var_debug_info: Option>>>, } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -122,7 +122,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, llfn: Bx::Function, - mir: ReadOnlyBodyCache<'a, 'tcx>, + mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, ) { @@ -156,7 +156,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }).collect(); let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); - let mir_body: &Body<'_> = mir.body(); + let mir_body: &mir::Body<'_> = mir.body(); let mut fx = FunctionCx { instance, mir, @@ -248,8 +248,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -fn create_funclets<'a, 'b, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - mir: &'b Body<'tcx>, +fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + mir: &'tcx mir::Body<'tcx>, bx: &mut Bx, cleanup_kinds: &IndexVec, block_bxs: &IndexVec, From fce40a22569d31dcb20b4bc9505d835f12278d98 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 16:26:25 +0200 Subject: [PATCH 05/20] rustc_codegen_ssa: make codegen_instance a simple wrapper for codegen_mir. --- src/librustc_codegen_ssa/base.rs | 8 +------- src/librustc_codegen_ssa/mir/mod.rs | 9 ++++++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index e460a4a2e8c97..af340008cd9c6 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -368,13 +368,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( // release builds. info!("codegen_instance({})", instance); - let sig = instance.fn_sig(cx.tcx()); - let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - - let lldecl = cx.get_fn(instance); - - let mir = cx.tcx().instance_mir(instance.def); - mir::codegen_mir::(cx, lldecl, mir, instance, sig); + mir::codegen_mir::(cx, instance); } /// Creates the `main` function which will initialize the rust runtime and call diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 600bdced4edd2..f2f0f36824c83 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -121,13 +121,16 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, - llfn: Bx::Function, - mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, ) { assert!(!instance.substs.needs_infer()); + let llfn = cx.get_fn(instance); + + let mir = cx.tcx().instance_mir(instance.def); + + let sig = instance.fn_sig(cx.tcx()); + let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let fn_abi = FnAbi::new(cx, sig, &[]); debug!("fn_abi: {:?}", fn_abi); From 6a75768b33b10fde649f0dcab6ff72a7dd62b561 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 18:11:11 +0200 Subject: [PATCH 06/20] rustc_codegen_ssa: clean up lifetimes on TerminatorCodegenHelper's methods. --- src/librustc_codegen_ssa/mir/block.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index c8881ca5f9506..370c172f97fd1 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -30,23 +30,22 @@ struct TerminatorCodegenHelper<'tcx> { funclet_bb: Option, } -// FIXME(eddyb) clean up the lifetimes in this impl. -impl<'tcx> TerminatorCodegenHelper<'tcx> { +impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { /// Returns the associated funclet from `FunctionCx::funclets` for the /// `funclet_bb` member if it is not `None`. - fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - ) -> Option<&'c Bx::Funclet> { + fx: &'b mut FunctionCx<'a, 'tcx, Bx>, + ) -> Option<&'b Bx::Funclet> { match self.funclet_bb { Some(funcl) => fx.funclets[funcl].as_ref(), None => None, } } - fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( + fn lltarget>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; @@ -64,9 +63,9 @@ impl<'tcx> TerminatorCodegenHelper<'tcx> { } /// Create a basic block. - fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn llblock>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, ) -> Bx::BasicBlock { let (lltarget, is_cleanupret) = self.lltarget(fx, target); @@ -84,9 +83,9 @@ impl<'tcx> TerminatorCodegenHelper<'tcx> { } } - fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet_br>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, target: mir::BasicBlock, ) { @@ -102,9 +101,9 @@ impl<'tcx> TerminatorCodegenHelper<'tcx> { /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional /// return destination `destination` and the cleanup function `cleanup`. - fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn do_call>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, fn_abi: FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, @@ -152,7 +151,7 @@ impl<'tcx> TerminatorCodegenHelper<'tcx> { // Generate sideeffect intrinsic if jumping to any of the targets can form // a loop. - fn maybe_sideeffect<'b, Bx: BuilderMethods<'b, 'tcx>>( + fn maybe_sideeffect>( &self, mir: mir::ReadOnlyBodyCache<'tcx, 'tcx>, bx: &mut Bx, From db477af9ade518d5d756daf20c647095a1f4af23 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 18:39:54 +0200 Subject: [PATCH 07/20] rustc_codegen_ssa: remove define_fn and define_internal_fn. --- src/librustc_codegen_llvm/declare.rs | 22 ---------------------- src/librustc_codegen_llvm/intrinsic.rs | 4 +++- src/librustc_codegen_ssa/traits/declare.rs | 14 -------------- 3 files changed, 3 insertions(+), 37 deletions(-) diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 46cdd2aaa9614..61c1e0dffe677 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -130,28 +130,6 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } - fn define_fn( - &self, - name: &str, - fn_sig: PolyFnSig<'tcx>, - ) -> &'ll Value { - if self.get_defined_value(name).is_some() { - self.sess().fatal(&format!("symbol `{}` already defined", name)) - } else { - self.declare_fn(name, fn_sig) - } - } - - fn define_internal_fn( - &self, - name: &str, - fn_sig: PolyFnSig<'tcx>, - ) -> &'ll Value { - let llfn = self.define_fn(name, fn_sig); - unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; - llfn - } - fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); let namebuf = SmallCStr::new(name); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index aa55f3a19e2be..26f3b4bbe2910 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1013,7 +1013,9 @@ fn gen_fn<'ll, 'tcx>( hir::Unsafety::Unsafe, Abi::Rust )); - let llfn = cx.define_internal_fn(name, rust_fn_sig); + let llfn = cx.declare_fn(name, rust_fn_sig); + // FIXME(eddyb) find a nicer way to do this. + unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; attributes::from_fn_attrs(cx, llfn, None, rust_fn_sig); let bx = Builder::new_block(cx, llfn, "entry-block"); codegen(bx); diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index cd42044e48df8..e6cb82c8229f3 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -38,20 +38,6 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// Use this function when you intend to define a global without a name. fn define_private_global(&self, ty: Self::Type) -> Self::Value; - /// Declare a Rust function with an intention to define it. - /// - /// Use this function when you intend to define a function. This function will - /// return panic if the name already has a definition associated with it. This - /// can happen with #[no_mangle] or #[export_name], for example. - fn define_fn(&self, name: &str, fn_sig: ty::PolyFnSig<'tcx>) -> Self::Value; - - /// Declare a Rust function with an intention to define it. - /// - /// Use this function when you intend to define a function. This function will - /// return panic if the name already has a definition associated with it. This - /// can happen with #[no_mangle] or #[export_name], for example. - fn define_internal_fn(&self, name: &str, fn_sig: ty::PolyFnSig<'tcx>) -> Self::Value; - /// Gets declared value by name. fn get_declared_value(&self, name: &str) -> Option; From 95b944210f8964f24a64dbb7d723b622eb3b0a4e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 18:34:50 +0200 Subject: [PATCH 08/20] rustc_codegen_ssa: take a FnAbi instead of a FnSig in declare_fn. --- src/librustc_codegen_llvm/attributes.rs | 7 +++---- src/librustc_codegen_llvm/callee.rs | 22 ++++++++++++---------- src/librustc_codegen_llvm/context.rs | 10 ++++++---- src/librustc_codegen_llvm/declare.rs | 13 +++++-------- src/librustc_codegen_llvm/intrinsic.rs | 11 +++++------ src/librustc_codegen_llvm/mono_item.rs | 16 +++++++++++----- src/librustc_codegen_ssa/traits/declare.rs | 5 +++-- 7 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 6f4e7d0f0caf5..a295f2b240291 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -6,7 +6,7 @@ use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::{Sanitizer, OptLevel}; -use rustc::ty::{self, TyCtxt, PolyFnSig}; +use rustc::ty::TyCtxt; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc_data_structures::small_c_str::SmallCStr; @@ -203,7 +203,7 @@ pub fn from_fn_attrs( cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, id: Option, - sig: PolyFnSig<'tcx>, + abi: Abi, ) { let codegen_fn_attrs = id.map(|id| cx.tcx.codegen_fn_attrs(id)) .unwrap_or_else(|| CodegenFnAttrs::new()); @@ -276,8 +276,7 @@ pub fn from_fn_attrs( // Special attribute for allocator functions, which can't unwind. false } else { - let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - if sig.abi == Abi::Rust || sig.abi == Abi::RustCall { + if abi == Abi::Rust || abi == Abi::RustCall { // Any Rust method (or `extern "Rust" fn` or `extern // "rust-call" fn`) is explicitly allowed to unwind // (unless it has no-unwind attribute, handled above). diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 08fa23f2a7c9e..b8e41b1f3dbfb 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -4,14 +4,15 @@ //! and methods are represented as just a fn ptr and not a full //! closure. +use crate::abi::FnAbi; use crate::attributes; use crate::llvm; use crate::context::CodegenCx; use crate::value::Value; use rustc_codegen_ssa::traits::*; -use rustc::ty::{TypeFoldable, Instance}; -use rustc::ty::layout::{LayoutOf, HasTyCtxt}; +use rustc::ty::{self, TypeFoldable, Instance}; +use rustc::ty::layout::{FnAbiExt, LayoutOf, HasTyCtxt}; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. @@ -32,19 +33,19 @@ pub fn get_fn( assert!(!instance.substs.has_escaping_bound_vars()); assert!(!instance.substs.has_param_types()); - let sig = instance.fn_sig(cx.tcx()); if let Some(&llfn) = cx.instances.borrow().get(&instance) { return llfn; } + let sig = instance.fn_sig(cx.tcx()); let sym = tcx.symbol_name(instance).name.as_str(); debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); - // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(sig); - let llptrty = cx.backend_type(cx.layout_of(fn_ptr_ty)); - let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { + // Create a fn pointer with the substituted signature. + let fn_ptr_ty = tcx.mk_fn_ptr(sig); + let llptrty = cx.backend_type(cx.layout_of(fn_ptr_ty)); + // This is subtle and surprising, but sometimes we have to bitcast // the resulting fn pointer. The reason has to do with external // functions. If you have two crates that both bind the same C @@ -76,14 +77,15 @@ pub fn get_fn( llfn } } else { - let llfn = cx.declare_fn(&sym, sig); - assert_eq!(cx.val_ty(llfn), llptrty); + let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); + let fn_abi = FnAbi::new(cx, sig, &[]); + let llfn = cx.declare_fn(&sym, &fn_abi); debug!("get_fn: not casting pointer!"); if instance.def.is_inline(tcx) { attributes::inline(cx, llfn, attributes::InlineAttr::Hint); } - attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig); + attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig.abi); let instance_def_id = instance.def_id(); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 4a40349cb73e8..89e3195342ce8 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -1,3 +1,4 @@ +use crate::abi::FnAbi; use crate::attributes; use crate::llvm; use crate::llvm_util; @@ -15,7 +16,7 @@ use rustc::mir::mono::CodegenUnit; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; use rustc::ty::layout::{ - LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv + FnAbiExt, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv }; use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::util::nodemap::FxHashMap; @@ -412,15 +413,16 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { return llfn; } - let sig = ty::Binder::bind(tcx.mk_fn_sig( + let sig = tcx.mk_fn_sig( iter::once(tcx.mk_mut_ptr(tcx.types.u8)), tcx.types.never, false, hir::Unsafety::Unsafe, Abi::C - )); + ); - let llfn = self.declare_fn("rust_eh_unwind_resume", sig); + let fn_abi = FnAbi::new(self, sig, &[]); + let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi); attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); llfn diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 61c1e0dffe677..772377617e2e1 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -18,8 +18,7 @@ use crate::attributes; use crate::context::CodegenCx; use crate::type_::Type; use crate::value::Value; -use rustc::ty::{self, PolyFnSig}; -use rustc::ty::layout::{FnAbiExt, LayoutOf}; +use rustc::ty::Ty; use rustc::session::config::Sanitizer; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::traits::*; @@ -94,16 +93,14 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn declare_fn( &self, name: &str, - sig: PolyFnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll Value { - debug!("declare_rust_fn(name={:?}, sig={:?})", name, sig); - let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - debug!("declare_rust_fn (after region erasure) sig={:?}", sig); + debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi); - let fn_abi = FnAbi::new(self, sig, &[]); let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self)); - if self.layout_of(sig.output()).abi.is_uninhabited() { + // FIXME(eddyb) move into `FnAbi::apply_attrs_llfn`. + if fn_abi.ret.layout.abi.is_uninhabited() { llvm::Attribute::NoReturn.apply_llfn(Function, llfn); } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 26f3b4bbe2910..999fc857c15a2 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1,4 +1,3 @@ -use crate::attributes; use crate::llvm; use crate::llvm_util; use crate::abi::{Abi, FnAbi, LlvmType, PassMode}; @@ -14,7 +13,7 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::glue; use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types}; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; +use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive}; use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; @@ -1006,17 +1005,17 @@ fn gen_fn<'ll, 'tcx>( output: Ty<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> &'ll Value { - let rust_fn_sig = ty::Binder::bind(cx.tcx.mk_fn_sig( + let rust_fn_sig = cx.tcx.mk_fn_sig( inputs.into_iter(), output, false, hir::Unsafety::Unsafe, Abi::Rust - )); - let llfn = cx.declare_fn(name, rust_fn_sig); + ); + let fn_abi = FnAbi::new(cx, rust_fn_sig, &[]); + let llfn = cx.declare_fn(name, &fn_abi); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; - attributes::from_fn_attrs(cx, llfn, None, rust_fn_sig); let bx = Builder::new_block(cx, llfn, "entry-block"); codegen(bx); llfn diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index c1703ffd0c753..f9df0a00475d0 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -1,3 +1,4 @@ +use crate::abi::FnAbi; use crate::attributes; use crate::base; use crate::context::CodegenCx; @@ -5,8 +6,8 @@ use crate::llvm; use crate::type_of::LayoutLlvmExt; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::ty::{TypeFoldable, Instance}; -use rustc::ty::layout::{LayoutOf, HasTyCtxt}; +use rustc::ty::{self, TypeFoldable, Instance}; +use rustc::ty::layout::{FnAbiExt, LayoutOf, HasTyCtxt}; use rustc_codegen_ssa::traits::*; pub use rustc::mir::mono::MonoItem; @@ -43,9 +44,14 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { !instance.substs.has_param_types()); let mono_sig = instance.fn_sig(self.tcx()); - let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - let lldecl = self.declare_fn(symbol_name, mono_sig); + let mono_sig = self.tcx().normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &mono_sig, + ); + let fn_abi = FnAbi::new(self, mono_sig, &[]); + let lldecl = self.declare_fn(symbol_name, &fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; + let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); base::set_link_section(lldecl, &attrs); if linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR { @@ -75,7 +81,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { self, lldecl, Some(instance.def.def_id()), - mono_sig, + mono_sig.abi, ); self.instances.borrow_mut().insert(instance, lldecl); diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index e6cb82c8229f3..1dd2c74dd4fa2 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -1,7 +1,8 @@ use super::BackendTypes; use rustc::hir::def_id::DefId; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::ty::{self, Instance}; +use rustc::ty::{Instance, Ty}; +use rustc_target::abi::call::FnAbi; pub trait DeclareMethods<'tcx>: BackendTypes { /// Declare a global value. @@ -23,7 +24,7 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Function; + fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function; /// Declare a global with an intention to define it. /// From 5b7d0f389f1ae4177f675a5ac535226ef92027a3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 19:46:18 +0200 Subject: [PATCH 09/20] rustc_codegen_llvm: move NoReturn attribute to apply_attrs_llfn. --- src/librustc_codegen_llvm/abi.rs | 5 +++++ src/librustc_codegen_llvm/declare.rs | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 804a7af41f39a..4ad58b9a9f7a6 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -388,6 +388,11 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) { + // FIXME(eddyb) can this also be applied to callsites? + if self.ret.layout.abi.is_uninhabited() { + llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn); + } + let mut i = 0; let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| { attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty); diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 772377617e2e1..8b6fedc87db96 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -98,14 +98,7 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi); let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self)); - - // FIXME(eddyb) move into `FnAbi::apply_attrs_llfn`. - if fn_abi.ret.layout.abi.is_uninhabited() { - llvm::Attribute::NoReturn.apply_llfn(Function, llfn); - } - fn_abi.apply_attrs_llfn(self, llfn); - llfn } From 4b68afe257603a61aa2eb8b8eaa394c5e7a246fe Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 20:01:31 +0200 Subject: [PATCH 10/20] rustc_codegen_ssa: use FnAbi::of_instance wherever possible. --- src/librustc_codegen_llvm/callee.rs | 23 ++++++++++---------- src/librustc_codegen_llvm/debuginfo/mod.rs | 13 ++++++++--- src/librustc_codegen_llvm/mono_item.rs | 16 ++++++-------- src/librustc_codegen_ssa/mir/mod.rs | 7 ++---- src/librustc_codegen_ssa/traits/debuginfo.rs | 5 +++-- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index b8e41b1f3dbfb..b6a3bf2f8789e 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -4,15 +4,15 @@ //! and methods are represented as just a fn ptr and not a full //! closure. -use crate::abi::FnAbi; +use crate::abi::{FnAbi, FnAbiLlvmExt}; use crate::attributes; use crate::llvm; use crate::context::CodegenCx; use crate::value::Value; use rustc_codegen_ssa::traits::*; -use rustc::ty::{self, TypeFoldable, Instance}; -use rustc::ty::layout::{FnAbiExt, LayoutOf, HasTyCtxt}; +use rustc::ty::{TypeFoldable, Instance}; +use rustc::ty::layout::{FnAbiExt, HasTyCtxt}; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. @@ -37,14 +37,14 @@ pub fn get_fn( return llfn; } - let sig = instance.fn_sig(cx.tcx()); let sym = tcx.symbol_name(instance).name.as_str(); - debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); + debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx()), sym); + + let fn_abi = FnAbi::of_instance(cx, instance); let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { - // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(sig); - let llptrty = cx.backend_type(cx.layout_of(fn_ptr_ty)); + // Create a fn pointer with the new signature. + let llptrty = fn_abi.ptr_to_llvm_type(cx); // This is subtle and surprising, but sometimes we have to bitcast // the resulting fn pointer. The reason has to do with external @@ -77,15 +77,16 @@ pub fn get_fn( llfn } } else { - let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - let fn_abi = FnAbi::new(cx, sig, &[]); let llfn = cx.declare_fn(&sym, &fn_abi); debug!("get_fn: not casting pointer!"); if instance.def.is_inline(tcx) { attributes::inline(cx, llfn, attributes::InlineAttr::Hint); } - attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig.abi); + // FIXME(eddyb) avoid this `Instance::fn_sig` call. + // Perhaps store the relevant information in `FnAbi`? + let sig_abi = instance.fn_sig(cx.tcx()).abi(); + attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig_abi); let instance_def_id = instance.def_id(); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 7713fe47004b9..f8aeaa20475d1 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -16,7 +16,7 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ty::subst::{SubstsRef, GenericArgKind}; -use crate::abi::Abi; +use crate::abi::{Abi, FnAbi}; use crate::common::CodegenCx; use crate::builder::Builder; use crate::value::Value; @@ -280,7 +280,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn create_function_debug_context( &self, instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: &'ll Value, mir: &mir::Body<'_>, ) -> Option> { @@ -308,6 +308,12 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let file_metadata = file_metadata(self, &loc.file.name, def_id.krate); let function_type_metadata = unsafe { + // FIXME(eddyb) avoid this `Instance::fn_sig` call, by + // rewriting `get_function_signature` to use `fn_abi` instead. + let sig = self.tcx().normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &instance.fn_sig(self.tcx()), + ); let fn_signature = get_function_signature(self, sig); llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature) }; @@ -338,7 +344,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let mut flags = DIFlags::FlagPrototyped; - if self.layout_of(sig.output()).abi.is_uninhabited() { + if fn_abi.ret.layout.abi.is_uninhabited() { flags |= DIFlags::FlagNoReturn; } @@ -390,6 +396,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { return Some(fn_debug_context); + // FIXME(eddyb) rewrite this to be based on `FnAbi` instead of `FnSig`. fn get_function_signature<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index f9df0a00475d0..3d2f6efb072ee 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -6,7 +6,7 @@ use crate::llvm; use crate::type_of::LayoutLlvmExt; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::ty::{self, TypeFoldable, Instance}; +use rustc::ty::{TypeFoldable, Instance}; use rustc::ty::layout::{FnAbiExt, LayoutOf, HasTyCtxt}; use rustc_codegen_ssa::traits::*; @@ -43,12 +43,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types()); - let mono_sig = instance.fn_sig(self.tcx()); - let mono_sig = self.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &mono_sig, - ); - let fn_abi = FnAbi::new(self, mono_sig, &[]); + let fn_abi = FnAbi::of_instance(self, instance); let lldecl = self.declare_fn(symbol_name, &fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); @@ -73,15 +68,18 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } - debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance); + debug!("predefine_fn: instance = {:?}", instance); if instance.def.is_inline(self.tcx) { attributes::inline(self, lldecl, attributes::InlineAttr::Hint); } + // FIXME(eddyb) avoid this `Instance::fn_sig` call. + // Perhaps store the relevant information in `FnAbi`? + let mono_sig_abi = instance.fn_sig(self.tcx()).abi(); attributes::from_fn_attrs( self, lldecl, Some(instance.def.def_id()), - mono_sig.abi, + mono_sig_abi, ); self.instances.borrow_mut().insert(instance, lldecl); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index f2f0f36824c83..04b102879517f 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -129,13 +129,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mir = cx.tcx().instance_mir(instance.def); - let sig = instance.fn_sig(cx.tcx()); - let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - let fn_abi = FnAbi::new(cx, sig, &[]); + let fn_abi = FnAbi::of_instance(cx, instance); debug!("fn_abi: {:?}", fn_abi); - let debug_context = - cx.create_function_debug_context(instance, sig, llfn, &mir); + let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); let mut bx = Bx::new_block(cx, llfn, "start"); diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index 802eaaa357ac0..e67201b710698 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -2,8 +2,9 @@ use super::BackendTypes; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind}; use rustc::hir::def_id::CrateNum; use rustc::mir; -use rustc::ty::{self, Ty, Instance}; +use rustc::ty::{Ty, Instance}; use rustc::ty::layout::Size; +use rustc_target::abi::call::FnAbi; use syntax::ast::Name; use syntax_pos::{SourceFile, Span}; @@ -17,7 +18,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { fn create_function_debug_context( &self, instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Function, mir: &mir::Body<'_>, ) -> Option>; From 39e50e2f289a58a46f46044d8e9d296b9e7ac7e6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 20:56:21 +0200 Subject: [PATCH 11/20] rustc: use ReifyShim for reifying Virtual call instances. --- src/librustc/ty/instance.rs | 32 ++++++++++++++-------- src/librustc_mir/monomorphize/collector.rs | 16 +++++------ src/librustc_mir/shim.rs | 11 +++++--- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 856be6f3c7791..06fc168bd5740 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -29,10 +29,15 @@ pub enum InstanceDef<'tcx> { /// `fn()` pointer where the function itself cannot be turned into a pointer. /// - /// One example in the compiler today is functions annotated with `#[track_caller]`, which - /// must have their implicit caller location argument populated for a call. Because this is a - /// required part of the function's ABI but can't be tracked as a property of the function - /// pointer, we create a single "caller location" at the site where the function is reified. + /// One example is `::fn`, where the shim contains + /// a virtual call, which codegen supports only via a direct call to the + /// `::fn` instance (an `InstanceDef::Virtual`). + /// + /// Another example is functions annotated with `#[track_caller]`, which + /// must have their implicit caller location argument populated for a call. + /// Because this is a required part of the function's ABI but can't be tracked + /// as a property of the function pointer, we use a single "caller location" + /// (the definition of the function itself). ReifyShim(DefId), /// `::call_*` @@ -194,7 +199,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { write!(f, " - intrinsic") } InstanceDef::Virtual(_, num) => { - write!(f, " - shim(#{})", num) + write!(f, " - virtual#{}", num) } InstanceDef::FnPtrShim(_, ty) => { write!(f, " - shim({:?})", ty) @@ -309,20 +314,23 @@ impl<'tcx> Instance<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { + Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| { let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags .contains(CodegenFnAttrFlags::TRACK_CALLER); match resolved.def { InstanceDef::Item(def_id) if has_track_caller(def_id) => { debug!(" => fn pointer created for function with #[track_caller]"); - Instance { - def: InstanceDef::ReifyShim(def_id), - substs, - } - }, - _ => resolved, + resolved.def = InstanceDef::ReifyShim(def_id); + } + InstanceDef::Virtual(def_id, _) => { + debug!(" => fn pointer created for virtual call"); + resolved.def = InstanceDef::ReifyShim(def_id); + } + _ => {} } + + resolved }) } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 4fe53cf35e511..93a76712b2869 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -741,23 +741,21 @@ fn visit_instance_use<'tcx>( } match instance.def { - ty::InstanceDef::Intrinsic(def_id) => { + ty::InstanceDef::Virtual(..) | + ty::InstanceDef::Intrinsic(_) => { if !is_direct_call { - bug!("intrinsic {:?} being reified", def_id); + bug!("{:?} being reified", instance); } } - ty::InstanceDef::VtableShim(..) | - ty::InstanceDef::ReifyShim(..) | - ty::InstanceDef::Virtual(..) | ty::InstanceDef::DropGlue(_, None) => { - // Don't need to emit shim if we are calling directly. + // Don't need to emit noop drop glue if we are calling directly. if !is_direct_call { output.push(create_fn_mono_item(instance)); } } - ty::InstanceDef::DropGlue(_, Some(_)) => { - output.push(create_fn_mono_item(instance)); - } + ty::InstanceDef::DropGlue(_, Some(_)) | + ty::InstanceDef::VtableShim(..) | + ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index fc606db98be0c..5b208dd858763 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -67,10 +67,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx ) } // We are generating a call back to our def-id, which the - // codegen backend knows to turn to an actual virtual call. - ty::InstanceDef::Virtual(def_id, _) | - // ...or we are generating a direct call to a function for which indirect calls must be - // codegen'd differently than direct ones (example: #[track_caller]) + // codegen backend knows to turn to an actual call, be it + // a virtual call, or a direct call to a function for which + // indirect calls must be codegen'd differently than direct ones + // (such as `#[track_caller]`). ty::InstanceDef::ReifyShim(def_id) => { build_call_shim( tcx, @@ -109,6 +109,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx bug!("builtin clone shim {:?} not supported", instance) } } + ty::InstanceDef::Virtual(..) => { + bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) + } ty::InstanceDef::Intrinsic(_) => { bug!("creating shims from intrinsics ({:?}) is unsupported", instance) } From 052d0edbc1c2572ba735ef911a5ab7e9c2a703bc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 21:46:25 +0200 Subject: [PATCH 12/20] rustc: compute FnAbi's for virtual calls through FnAbi::of_instance. --- src/librustc/ty/layout.rs | 20 +++++------ src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/mono_item.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 46 ++++++++++++++------------ src/librustc_codegen_ssa/mir/mod.rs | 2 +- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c67e6a0a13e63..52f0bb220ad1f 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2347,9 +2347,8 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self; fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn new_internal( cx: &C, sig: ty::FnSig<'tcx>, @@ -2367,25 +2366,22 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self { + fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty))) + } + + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { let sig = instance.fn_sig(cx.tcx()); let sig = cx .tcx() .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - call::FnAbi::new(cx, sig, &[]) - } - - fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty))) - } - fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - FnAbiExt::new_internal(cx, sig, extra_args, |ty, arg_idx| { + call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| { let mut layout = cx.layout_of(ty); // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen - if arg_idx == Some(0) { + if let (ty::InstanceDef::Virtual(..), Some(0)) = (&instance.def, arg_idx) { let fat_pointer_ty = if layout.is_unsized() { // unsized `self` is passed as a pointer to `self` // FIXME (mikeyhew) change this to use &own if it is ever added to the language diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index b6a3bf2f8789e..74f4970333c86 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -40,7 +40,7 @@ pub fn get_fn( let sym = tcx.symbol_name(instance).name.as_str(); debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx()), sym); - let fn_abi = FnAbi::of_instance(cx, instance); + let fn_abi = FnAbi::of_instance(cx, instance, &[]); let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { // Create a fn pointer with the new signature. diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index 3d2f6efb072ee..75a4a96669483 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -43,7 +43,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types()); - let fn_abi = FnAbi::of_instance(self, instance); + let fn_abi = FnAbi::of_instance(self, instance, &[]); let lldecl = self.declare_fn(symbol_name, &fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 370c172f97fd1..3ef6caec2f2cf 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -345,20 +345,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &args1[..] }; let (drop_fn, fn_abi) = match ty.kind { + // FIXME(eddyb) perhaps move some of this logic into + // `Instance::resolve_drop_in_place`? ty::Dynamic(..) => { - let sig = drop_fn.fn_sig(self.cx.tcx()); - let sig = self.cx.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let fn_abi = FnAbi::new_vtable(&bx, sig, &[]); + let virtual_drop = Instance { + def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), + substs: drop_fn.substs, + }; + let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]); let vtable = args[1]; args = &args[..1]; (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi) } _ => { (bx.get_fn_addr(drop_fn), - FnAbi::of_instance(&bx, drop_fn)) + FnAbi::of_instance(&bx, drop_fn, &[])) } }; helper.maybe_sideeffect(self.mir, &mut bx, &[target]); @@ -439,7 +440,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance); + let fn_abi = FnAbi::of_instance(&bx, instance, &[]); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -474,6 +475,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} is not callable", callee.layout.ty), }; let def = instance.map(|i| i.def); + + if let Some(ty::InstanceDef::DropGlue(_, None)) = def { + // Empty drop glue; a no-op. + let &(_, target) = destination.as_ref().unwrap(); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + return; + } + + // FIXME(eddyb) avoid computing this if possible, when `instance` is + // available - right now `sig` is only needed for getting the `abi` + // and figuring out how many extra args were passed to a C-variadic `fn`. let sig = callee.layout.ty.fn_sig(bx.tcx()); let sig = bx.tcx().normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), @@ -514,18 +527,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.monomorphize(&op_ty) }).collect::>(); - let fn_abi = match def { - Some(ty::InstanceDef::Virtual(..)) => { - FnAbi::new_vtable(&bx, sig, &extra_args) - } - Some(ty::InstanceDef::DropGlue(_, None)) => { - // Empty drop glue; a no-op. - let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - return; - } - _ => FnAbi::new(&bx, sig, &extra_args) + let fn_abi = match instance { + Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), + None => FnAbi::new(&bx, sig, &extra_args) }; // For normal codegen, this Miri-specific intrinsic is just a NOP. @@ -549,7 +553,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance); + let fn_abi = FnAbi::of_instance(&bx, instance, &[]); let llfn = bx.get_fn_addr(instance); if let Some((_, target)) = destination.as_ref() { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 04b102879517f..3a157ca24a470 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -129,7 +129,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mir = cx.tcx().instance_mir(instance.def); - let fn_abi = FnAbi::of_instance(cx, instance); + let fn_abi = FnAbi::of_instance(cx, instance, &[]); debug!("fn_abi: {:?}", fn_abi); let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); From 2b921d51d750cdb2892fff1cf0681481f4e5e3f6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 21:57:45 +0200 Subject: [PATCH 13/20] rustc: rename FnAbi::new to FnAbi::of_fn_ptr. --- src/librustc/ty/layout.rs | 4 ++-- src/librustc_codegen_llvm/context.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 2 +- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 52f0bb220ad1f..c8800d6f140e1 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2347,7 +2347,7 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn of_fn_ptr(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn new_internal( cx: &C, @@ -2366,7 +2366,7 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + fn of_fn_ptr(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty))) } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 89e3195342ce8..223aa7595d8fe 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -421,7 +421,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { Abi::C ); - let fn_abi = FnAbi::new(self, sig, &[]); + let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]); let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi); attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 999fc857c15a2..c26b1ed8793cc 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1012,7 +1012,7 @@ fn gen_fn<'ll, 'tcx>( hir::Unsafety::Unsafe, Abi::Rust ); - let fn_abi = FnAbi::new(cx, rust_fn_sig, &[]); + let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); let llfn = cx.declare_fn(name, &fn_abi); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index c21e62e7562e3..aa060e474fa5b 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -239,7 +239,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { ty::ParamEnv::reveal_all(), &sig, ); - cx.fn_ptr_backend_type(&FnAbi::new(cx, sig, &[])) + cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])) } _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO) }; diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 3ef6caec2f2cf..1f63568807179 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -529,7 +529,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_abi = match instance { Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), - None => FnAbi::new(&bx, sig, &extra_args) + None => FnAbi::of_fn_ptr(&bx, sig, &extra_args) }; // For normal codegen, this Miri-specific intrinsic is just a NOP. From 902433b5bf4f42714ed8d5b6bbf0d574d83a4f0f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 22:08:50 +0200 Subject: [PATCH 14/20] rustc: take a PolyFnSig instead of an FnSig in FnAbi::of_fn_ptr. --- src/librustc/ty/layout.rs | 15 +++++++------ src/librustc_codegen_llvm/context.rs | 4 ++-- src/librustc_codegen_llvm/intrinsic.rs | 4 ++-- src/librustc_codegen_llvm/type_of.rs | 4 ---- src/librustc_codegen_ssa/mir/block.rs | 30 +++++++++++--------------- 5 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index c8800d6f140e1..d34ad7fb26a27 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2347,11 +2347,11 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_fn_ptr(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn new_internal( cx: &C, - sig: ty::FnSig<'tcx>, + sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgAbi<'tcx, Ty<'tcx>>, ) -> Self; @@ -2366,15 +2366,12 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_fn_ptr(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { call::FnAbi::new_internal(cx, sig, extra_args, |ty, _| ArgAbi::new(cx.layout_of(ty))) } fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { let sig = instance.fn_sig(cx.tcx()); - let sig = cx - .tcx() - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| { let mut layout = cx.layout_of(ty); @@ -2432,12 +2429,16 @@ where fn new_internal( cx: &C, - sig: ty::FnSig<'tcx>, + sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgAbi<'tcx, Ty<'tcx>>, ) -> Self { debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); + let sig = cx + .tcx() + .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); + use rustc_target::spec::abi::Abi::*; let conv = match cx.tcx().sess.target.target.adjust_abi(sig.abi) { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::C, diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 223aa7595d8fe..39ea1f6f5dccf 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -413,13 +413,13 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { return llfn; } - let sig = tcx.mk_fn_sig( + let sig = ty::Binder::bind(tcx.mk_fn_sig( iter::once(tcx.mk_mut_ptr(tcx.types.u8)), tcx.types.never, false, hir::Unsafety::Unsafe, Abi::C - ); + )); let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]); let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index c26b1ed8793cc..3201767c86015 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1005,13 +1005,13 @@ fn gen_fn<'ll, 'tcx>( output: Ty<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> &'ll Value { - let rust_fn_sig = cx.tcx.mk_fn_sig( + let rust_fn_sig = ty::Binder::bind(cx.tcx.mk_fn_sig( inputs.into_iter(), output, false, hir::Unsafety::Unsafe, Abi::Rust - ); + )); let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); let llfn = cx.declare_fn(name, &fn_abi); // FIXME(eddyb) find a nicer way to do this. diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index aa060e474fa5b..d77bbb279216a 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -235,10 +235,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) } ty::FnPtr(sig) => { - let sig = cx.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])) } _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 1f63568807179..6dccf329c9f64 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -488,11 +488,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // available - right now `sig` is only needed for getting the `abi` // and figuring out how many extra args were passed to a C-variadic `fn`. let sig = callee.layout.ty.fn_sig(bx.tcx()); - let sig = bx.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let abi = sig.abi; + let abi = sig.abi(); // Handle intrinsics old codegen wants Expr's for, ourselves. let intrinsic = match def { @@ -502,6 +498,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let intrinsic = intrinsic.as_ref().map(|s| &s[..]); + let extra_args = &args[sig.inputs().skip_binder().len()..]; + let extra_args = extra_args.iter().map(|op_arg| { + let op_ty = op_arg.ty(*self.mir, bx.tcx()); + self.monomorphize(&op_ty) + }).collect::>(); + + let fn_abi = match instance { + Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), + None => FnAbi::of_fn_ptr(&bx, sig, &extra_args) + }; + if intrinsic == Some("transmute") { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; @@ -515,23 +522,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // we can do what we like. Here, we declare that transmuting // into an uninhabited type is impossible, so anything following // it must be unreachable. - assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited); + assert_eq!(fn_abi.ret.layout.abi, layout::Abi::Uninhabited); bx.unreachable(); } return; } - let extra_args = &args[sig.inputs().len()..]; - let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(*self.mir, bx.tcx()); - self.monomorphize(&op_ty) - }).collect::>(); - - let fn_abi = match instance { - Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), - None => FnAbi::of_fn_ptr(&bx, sig, &extra_args) - }; - // For normal codegen, this Miri-specific intrinsic is just a NOP. if intrinsic == Some("miri_start_panic") { let target = destination.as_ref().unwrap().1; From 8a8749b29780d18f57b81cf25f91b7960ccc64d3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Oct 2019 20:01:31 +0200 Subject: [PATCH 15/20] rustc_codegen_llvm: rewrite debuginfo::get_function_signature to use FnAbi. --- src/librustc_codegen_llvm/debuginfo/mod.rs | 45 ++++++---------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index f8aeaa20475d1..c2359a2fe6d94 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -16,7 +16,7 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ty::subst::{SubstsRef, GenericArgKind}; -use crate::abi::{Abi, FnAbi}; +use crate::abi::FnAbi; use crate::common::CodegenCx; use crate::builder::Builder; use crate::value::Value; @@ -308,13 +308,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let file_metadata = file_metadata(self, &loc.file.name, def_id.krate); let function_type_metadata = unsafe { - // FIXME(eddyb) avoid this `Instance::fn_sig` call, by - // rewriting `get_function_signature` to use `fn_abi` instead. - let sig = self.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &instance.fn_sig(self.tcx()), - ); - let fn_signature = get_function_signature(self, sig); + let fn_signature = get_function_signature(self, fn_abi); llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature) }; @@ -396,28 +390,22 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { return Some(fn_debug_context); - // FIXME(eddyb) rewrite this to be based on `FnAbi` instead of `FnSig`. fn get_function_signature<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - sig: ty::FnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll DIArray { if cx.sess().opts.debuginfo == DebugInfo::Limited { return create_DIArray(DIB(cx), &[]); } - let mut signature = Vec::with_capacity(sig.inputs().len() + 1); + let mut signature = Vec::with_capacity(fn_abi.args.len() + 1); // Return type -- llvm::DIBuilder wants this at index 0 - signature.push(match sig.output().kind { - ty::Tuple(ref tys) if tys.is_empty() => None, - _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)) - }); - - let inputs = if sig.abi == Abi::RustCall { - &sig.inputs()[..sig.inputs().len() - 1] + signature.push(if fn_abi.ret.is_ignore() { + None } else { - sig.inputs() - }; + Some(type_metadata(cx, fn_abi.ret.layout.ty, syntax_pos::DUMMY_SP)) + }); // Arguments types if cx.sess().target.target.options.is_like_msvc { @@ -431,7 +419,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`. // This transformed type is wrong, but these function types are // already inaccurate due to ABI adjustments (see #42800). - signature.extend(inputs.iter().map(|&t| { + signature.extend(fn_abi.args.iter().map(|arg| { + let t = arg.layout.ty; let t = match t.kind { ty::Array(ct, _) if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => { @@ -442,21 +431,11 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) })); } else { - signature.extend(inputs.iter().map(|t| { - Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) + signature.extend(fn_abi.args.iter().map(|arg| { + Some(type_metadata(cx, arg.layout.ty, syntax_pos::DUMMY_SP)) })); } - if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].kind { - signature.extend( - args.iter().map(|argument_type| { - Some(type_metadata(cx, argument_type.expect_ty(), syntax_pos::DUMMY_SP)) - }) - ); - } - } - create_DIArray(DIB(cx), &signature[..]) } From cd3c324b0714ed744220da1419d91a6d9efefc04 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 27 Nov 2019 12:53:19 +0200 Subject: [PATCH 16/20] rustc_codegen_llvm: take an Instance in attributes::from_fn_attrs. --- src/librustc_codegen_llvm/attributes.rs | 36 ++++++++++++++----------- src/librustc_codegen_llvm/callee.rs | 8 +----- src/librustc_codegen_llvm/mono_item.rs | 16 +++-------- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index a295f2b240291..cee2e56ef7590 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -2,11 +2,11 @@ use std::ffi::CString; -use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::{Sanitizer, OptLevel}; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc_data_structures::small_c_str::SmallCStr; @@ -202,11 +202,9 @@ pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) { pub fn from_fn_attrs( cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, - id: Option, - abi: Abi, + instance: ty::Instance<'tcx>, ) { - let codegen_fn_attrs = id.map(|id| cx.tcx.codegen_fn_attrs(id)) - .unwrap_or_else(|| CodegenFnAttrs::new()); + let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); match codegen_fn_attrs.optimize { OptimizeAttr::None => { @@ -224,6 +222,11 @@ pub fn from_fn_attrs( } } + // FIXME(eddyb) consolidate these two `inline` calls (and avoid overwrites). + if instance.def.is_inline(cx.tcx) { + inline(cx, llfn, attributes::InlineAttr::Hint); + } + inline(cx, llfn, codegen_fn_attrs.inline); // The `uwtable` attribute according to LLVM is: @@ -276,6 +279,9 @@ pub fn from_fn_attrs( // Special attribute for allocator functions, which can't unwind. false } else { + // FIXME(eddyb) avoid this `Instance::fn_sig` call. + // Perhaps store the relevant information in `FnAbi`? + let abi = instance.fn_sig(cx.tcx()).abi(); if abi == Abi::Rust || abi == Abi::RustCall { // Any Rust method (or `extern "Rust" fn` or `extern // "rust-call" fn`) is explicitly allowed to unwind @@ -330,16 +336,14 @@ pub fn from_fn_attrs( // Note that currently the `wasm-import-module` doesn't do anything, but // eventually LLVM 7 should read this and ferry the appropriate import // module to the output file. - if let Some(id) = id { - if cx.tcx.sess.target.target.arch == "wasm32" { - if let Some(module) = wasm_import_module(cx.tcx, id) { - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - const_cstr!("wasm-import-module"), - &module, - ); - } + if cx.tcx.sess.target.target.arch == "wasm32" { + if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + const_cstr!("wasm-import-module"), + &module, + ); } } } diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 74f4970333c86..727cbbb8c1433 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -80,13 +80,7 @@ pub fn get_fn( let llfn = cx.declare_fn(&sym, &fn_abi); debug!("get_fn: not casting pointer!"); - if instance.def.is_inline(tcx) { - attributes::inline(cx, llfn, attributes::InlineAttr::Hint); - } - // FIXME(eddyb) avoid this `Instance::fn_sig` call. - // Perhaps store the relevant information in `FnAbi`? - let sig_abi = instance.fn_sig(cx.tcx()).abi(); - attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig_abi); + attributes::from_fn_attrs(cx, llfn, instance); let instance_def_id = instance.def_id(); diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index 75a4a96669483..2270b59b6822c 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -7,7 +7,7 @@ use crate::type_of::LayoutLlvmExt; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::{TypeFoldable, Instance}; -use rustc::ty::layout::{FnAbiExt, LayoutOf, HasTyCtxt}; +use rustc::ty::layout::{FnAbiExt, LayoutOf}; use rustc_codegen_ssa::traits::*; pub use rustc::mir::mono::MonoItem; @@ -69,18 +69,8 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { } debug!("predefine_fn: instance = {:?}", instance); - if instance.def.is_inline(self.tcx) { - attributes::inline(self, lldecl, attributes::InlineAttr::Hint); - } - // FIXME(eddyb) avoid this `Instance::fn_sig` call. - // Perhaps store the relevant information in `FnAbi`? - let mono_sig_abi = instance.fn_sig(self.tcx()).abi(); - attributes::from_fn_attrs( - self, - lldecl, - Some(instance.def.def_id()), - mono_sig_abi, - ); + + attributes::from_fn_attrs(self, lldecl, instance); self.instances.borrow_mut().insert(instance, lldecl); } From e93aa104abaafe35af93d3c5e47ac8bca2f2ff02 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 27 Nov 2019 12:55:33 +0200 Subject: [PATCH 17/20] rustc_codegen_llvm: privatize as much of attributes::* as possible. --- src/librustc_codegen_llvm/attributes.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index cee2e56ef7590..22ff0379624dc 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -26,7 +26,7 @@ use crate::value::Value; /// Mark LLVM function to use provided inline heuristic. #[inline] -pub fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { +fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), @@ -58,7 +58,7 @@ fn unwind(val: &'ll Value, can_unwind: bool) { /// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue. #[inline] -pub fn naked(val: &'ll Value, is_naked: bool) { +fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } @@ -72,7 +72,7 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) /// Tell LLVM what instrument function to insert. #[inline] -pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().instrument_mcount() { // Similar to `clang -pg` behavior. Handled by the // `post-inline-ee-instrument` LLVM pass. @@ -88,7 +88,7 @@ pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } } -pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Only use stack probes if the target specification indicates that we // should be using stack probes if !cx.sess().target.target.options.stack_probes { From 79d908b301c4ad8b0778331af4b0c6ad46970ef1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 27 Nov 2019 13:23:30 +0200 Subject: [PATCH 18/20] rustc_target: add abi::call::Conv::Rust distinct from Conv::C. --- src/librustc/ty/layout.rs | 2 +- src/librustc_codegen_llvm/abi.rs | 2 +- src/librustc_codegen_llvm/attributes.rs | 11 +++++------ src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/mono_item.rs | 2 +- src/librustc_target/abi/call/mod.rs | 5 +++++ 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index d34ad7fb26a27..1662776adf50f 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2441,7 +2441,7 @@ where use rustc_target::spec::abi::Abi::*; let conv = match cx.tcx().sess.target.target.adjust_abi(sig.abi) { - RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::C, + RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust, // It's the ABI's job to select this, not ours. System => bug!("system abi should be selected elsewhere"), diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 4ad58b9a9f7a6..1f3c8e1953e4f 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -372,7 +372,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn llvm_cconv(&self) -> llvm::CallConv { match self.conv { - Conv::C => llvm::CCallConv, + Conv::C | Conv::Rust => llvm::CCallConv, Conv::AmdGpuKernel => llvm::AmdGpuKernel, Conv::ArmAapcs => llvm::ArmAapcsCallConv, Conv::Msp430Intr => llvm::Msp430Intr, diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 22ff0379624dc..33dc2513de584 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -6,15 +6,16 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::{Sanitizer, OptLevel}; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, Ty}; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::fx::FxHashMap; +use rustc_target::abi::call::Conv; use rustc_target::spec::PanicStrategy; use rustc_codegen_ssa::traits::*; -use crate::abi::Abi; +use crate::abi::FnAbi; use crate::attributes; use crate::llvm::{self, Attribute}; use crate::llvm::AttributePlace::Function; @@ -203,6 +204,7 @@ pub fn from_fn_attrs( cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::Instance<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); @@ -279,10 +281,7 @@ pub fn from_fn_attrs( // Special attribute for allocator functions, which can't unwind. false } else { - // FIXME(eddyb) avoid this `Instance::fn_sig` call. - // Perhaps store the relevant information in `FnAbi`? - let abi = instance.fn_sig(cx.tcx()).abi(); - if abi == Abi::Rust || abi == Abi::RustCall { + if fn_abi.conv == Conv::Rust { // Any Rust method (or `extern "Rust" fn` or `extern // "rust-call" fn`) is explicitly allowed to unwind // (unless it has no-unwind attribute, handled above). diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 727cbbb8c1433..e0db7cae99e1a 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -80,7 +80,7 @@ pub fn get_fn( let llfn = cx.declare_fn(&sym, &fn_abi); debug!("get_fn: not casting pointer!"); - attributes::from_fn_attrs(cx, llfn, instance); + attributes::from_fn_attrs(cx, llfn, instance, &fn_abi); let instance_def_id = instance.def_id(); diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index 2270b59b6822c..cbc8af4fd2710 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -70,7 +70,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { debug!("predefine_fn: instance = {:?}", instance); - attributes::from_fn_attrs(self, lldecl, instance); + attributes::from_fn_attrs(self, lldecl, instance, &fn_abi); self.instances.borrow_mut().insert(instance, lldecl); } diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 3a3ad763790ba..6f53577b45055 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -492,7 +492,12 @@ impl<'a, Ty> ArgAbi<'a, Ty> { #[derive(Copy, Clone, PartialEq, Debug)] pub enum Conv { + // General language calling conventions, for which every target + // should have its own backend (e.g. LLVM) support. C, + Rust, + + // Target-specific calling conventions. ArmAapcs, From 9da14a82c6d2b69eb191c13776f2974d292168e9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 27 Nov 2019 13:44:20 +0200 Subject: [PATCH 19/20] rustc: move Instance::fn_sig to ty::layout and privatize it. --- src/librustc/ty/instance.rs | 66 +--------------------------------- src/librustc/ty/layout.rs | 72 ++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 66 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 06fc168bd5740..f270d3d3a2a59 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,8 +1,7 @@ use crate::hir::CodegenFnAttrFlags; -use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; -use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; +use crate::ty::{self, Ty, TypeFoldable, SubstsRef, TyCtxt}; use crate::ty::print::{FmtPrinter, Printer}; use crate::traits; use crate::middle::lang_items::DropInPlaceFnLangItem; @@ -10,7 +9,6 @@ use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; use std::fmt; -use std::iter; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(HashStable, Lift)] @@ -66,68 +64,6 @@ impl<'tcx> Instance<'tcx> { &ty, ) } - - pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - let ty = self.ty(tcx); - match ty.kind { - ty::FnDef(..) | - // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => { - let mut sig = ty.fn_sig(tcx); - if let InstanceDef::VtableShim(..) = self.def { - // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. - sig = sig.map_bound(|mut sig| { - let mut inputs_and_output = sig.inputs_and_output.to_vec(); - inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); - sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); - sig - }); - } - sig - } - ty::Closure(def_id, substs) => { - let sig = substs.as_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.as_generator().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); - - let pin_did = tcx.lang_items().pin_type().unwrap(); - let pin_adt_ref = tcx.adt_def(pin_did); - let pin_substs = tcx.intern_substs(&[env_ty.into()]); - let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); - - 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, - Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) - } - } } impl<'tcx> InstanceDef<'tcx> { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 1662776adf50f..4d48c7841451f 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2339,6 +2339,76 @@ impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { } } + +impl<'tcx> ty::Instance<'tcx> { + // NOTE(eddyb) this is private to avoid using it from outside of + // `FnAbi::of_instance` - any other uses are either too high-level + // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), + // or should go through `FnAbi` instead, to avoid losing any + // adjustments `FnAbi::of_instance` might be performing. + fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + let ty = self.ty(tcx); + match ty.kind { + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => { + let mut sig = ty.fn_sig(tcx); + if let ty::InstanceDef::VtableShim(..) = self.def { + // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. + sig = sig.map_bound(|mut sig| { + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + sig + }); + } + sig + } + ty::Closure(def_id, substs) => { + let sig = substs.as_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.as_generator().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); + + let pin_did = tcx.lang_items().pin_type().unwrap(); + let pin_adt_ref = tcx.adt_def(pin_did); + let pin_substs = tcx.intern_substs(&[env_ty.into()]); + let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); + + 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, + rustc_target::spec::abi::Abi::Rust + ) + }) + } + _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) + } + } +} + pub trait FnAbiExt<'tcx, C> where C: LayoutOf, TyLayout = TyLayout<'tcx>> @@ -2371,7 +2441,7 @@ where } fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - let sig = instance.fn_sig(cx.tcx()); + let sig = instance.fn_sig_for_fn_abi(cx.tcx()); call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| { let mut layout = cx.layout_of(ty); From c2f4c57296f0d929618baed0b0d6eb594abf01eb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 27 Nov 2019 13:59:59 +0200 Subject: [PATCH 20/20] rustc: add docs to FnAbi::{of_fn_ptr,of_instance} and InstanceDef::Virtual. --- src/librustc/ty/instance.rs | 6 +++++- src/librustc/ty/layout.rs | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index f270d3d3a2a59..801dfa81ef178 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -42,7 +42,11 @@ pub enum InstanceDef<'tcx> { /// `DefId` is `FnTrait::call_*`. FnPtrShim(DefId, Ty<'tcx>), - /// `::fn` + /// `::fn`, "direct calls" of which are implicitly + /// codegen'd as virtual calls. + /// + /// NB: if this is reified to a `fn` pointer, a `ReifyShim` is used + /// (see `ReifyShim` above for more details on that). Virtual(DefId, usize), /// `<[mut closure] as FnOnce>::call_once` diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 4d48c7841451f..7f93e8c91e9d9 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2417,8 +2417,19 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` + /// instead, where the instance is a `InstanceDef::Virtual`. fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to a `InstanceDef::Virtual` instance (of `::fn`). fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn new_internal( cx: &C, sig: ty::PolyFnSig<'tcx>,