ty::layout: replicate layout_of setup for fn_abi_of_{fn_ptr,instance}.

This commit is contained in:
Eduard-Mihai Burtescu 2021-09-02 00:09:34 +03:00
parent 319dec89e7
commit e9b68304ef
17 changed files with 277 additions and 157 deletions

View File

@ -5,7 +5,7 @@ mod pass_mode;
mod returning;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_target::abi::call::{Conv, FnAbi};
use rustc_target::spec::abi::Abi;
@ -53,7 +53,7 @@ pub(crate) fn get_function_sig<'tcx>(
inst: Instance<'tcx>,
) -> Signature {
assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[]))
clif_sig_from_fn_abi(tcx, triple, &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, &[]))
}
/// Instance must be monomorphized
@ -355,9 +355,9 @@ pub(crate) fn codegen_terminator_call<'tcx>(
.map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))
.collect::<Vec<_>>();
let fn_abi = if let Some(instance) = instance {
FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args)
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, &extra_args)
} else {
FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args)
RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), &extra_args)
};
let is_cold = instance
@ -525,7 +525,7 @@ pub(crate) fn codegen_drop<'tcx>(
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
substs: drop_instance.substs,
};
let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), virtual_drop, &[]);
let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, &[]);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
let sig = fx.bcx.import_signature(sig);
@ -534,7 +534,7 @@ pub(crate) fn codegen_drop<'tcx>(
_ => {
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), drop_instance, &[]);
let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, &[]);
let arg_value = drop_place.place_ref(
fx,

View File

@ -3,8 +3,7 @@
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_index::vec::IndexVec;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::layout::FnAbiExt;
use rustc_target::abi::call::FnAbi;
use rustc_middle::ty::layout::FnAbiOf;
use crate::constant::ConstantCx;
use crate::prelude::*;
@ -62,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>(
instance,
symbol_name,
mir,
fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, &[])),
bcx,
block_map,

View File

@ -1,5 +1,7 @@
use rustc_index::vec::IndexVec;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers};
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
};
use rustc_middle::ty::SymbolName;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{Integer, Primitive};
@ -266,6 +268,20 @@ impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
}
}
impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
#[inline]
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>,
) -> ! {
RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request)
}
}
impl<'tcx> layout::HasTyCtxt<'tcx> for FunctionCx<'_, '_, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.tcx
@ -378,6 +394,43 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
}
}
impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
#[inline]
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>,
) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.0.sess.span_fatal(span, &err.to_string())
} else {
match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => {
span_bug!(
span,
"`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
sig,
extra_args,
err
);
}
FnAbiRequest::OfInstance { instance, extra_args } => {
span_bug!(
span,
"`fn_abi_of_instance({}, {:?})` failed: {}",
instance,
extra_args,
err
);
}
}
}
}
}
impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.0

View File

@ -129,9 +129,7 @@ pub(crate) fn codegen_constant<'tcx>(
};
let const_val = match const_.val {
ConstKind::Value(const_val) => const_val,
ConstKind::Unevaluated(uv)
if fx.tcx.is_static(uv.def.did) =>
{
ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => {
assert!(uv.substs(fx.tcx).is_empty());
assert!(uv.promoted.is_none());

View File

@ -61,9 +61,8 @@ use cranelift_codegen::{
write::{FuncWriter, PlainWriter},
};
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_session::config::OutputType;
use rustc_target::abi::call::FnAbi;
use crate::prelude::*;
@ -81,7 +80,7 @@ impl CommentWriter {
vec![
format!("symbol {}", tcx.symbol_name(instance).name),
format!("instance {:?}", instance),
format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
format!("abi {:?}", RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, &[])),
String::new(),
]
} else {

View File

@ -15,10 +15,12 @@ use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
use rustc_target::abi::{self, Align, Size, WrappingRange};
use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
use rustc_target::spec::{HasTargetSpec, Target};
use std::borrow::Cow;
use std::ffi::CStr;
@ -97,6 +99,20 @@ impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
}
}
impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
#[inline]
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>,
) -> ! {
self.cx.handle_fn_abi_err(err, span, fn_abi_request)
}
}
impl Deref for Builder<'_, 'll, 'tcx> {
type Target = CodegenCx<'ll, 'tcx>;

View File

@ -4,7 +4,7 @@
//! and methods are represented as just a fn ptr and not a full
//! closure.
use crate::abi::{FnAbi, FnAbiLlvmExt};
use crate::abi::FnAbiLlvmExt;
use crate::attributes;
use crate::context::CodegenCx;
use crate::llvm;
@ -12,7 +12,7 @@ use crate::value::Value;
use rustc_codegen_ssa::traits::*;
use tracing::debug;
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_middle::ty::{self, Instance, TypeFoldable};
/// Codegens a reference to a fn/method item, monomorphizing and
@ -42,7 +42,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
sym
);
let fn_abi = FnAbi::of_instance(cx, instance, &[]);
let fn_abi = cx.fn_abi_of_instance(instance, &[]);
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
// Create a fn pointer with the new signature.

View File

@ -15,14 +15,19 @@ use rustc_data_structures::base_n;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
TyAndLayout,
};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
use rustc_session::Session;
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::abi::{
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
};
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
use smallvec::SmallVec;
@ -853,3 +858,40 @@ impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
}
}
}
impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
#[inline]
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>,
) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.sess().span_fatal(span, &err.to_string())
} else {
match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => {
span_bug!(
span,
"`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
sig,
extra_args,
err
);
}
FnAbiRequest::OfInstance { instance, extra_args } => {
span_bug!(
span,
"`fn_abi_of_instance({}, {:?})` failed: {}",
instance,
extra_args,
err
);
}
}
}
}
}

View File

@ -1,6 +1,6 @@
use crate::llvm;
use crate::abi::{Abi, FnAbi};
use crate::abi::Abi;
use crate::builder::Builder;
use crate::common::CodegenCx;
@ -20,7 +20,7 @@ use rustc_middle::mir::coverage::{
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
};
use rustc_middle::ty;
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::Instance;
@ -200,8 +200,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
let llfn = cx.declare_fn(
&tcx.symbol_name(instance).name,
&FnAbi::of_fn_ptr(
cx,
&cx.fn_abi_of_fn_ptr(
ty::Binder::dummy(tcx.mk_fn_sig(
iter::once(tcx.mk_unit()),
tcx.mk_unit(),

View File

@ -3,12 +3,11 @@ use super::utils::DIB;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;
use crate::abi::FnAbi;
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::{DILocation, DIScope};
use rustc_middle::mir::{Body, SourceScope};
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo;
@ -94,7 +93,7 @@ fn make_mir_scope(
ty::ParamEnv::reveal_all(),
callee,
);
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
let callee_fn_abi = cx.fn_abi_of_instance(callee, &[]);
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
}
None => unsafe {

View File

@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_hir as hir;
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
use rustc_middle::ty::{self, Ty};
use rustc_middle::{bug, span_bug};
use rustc_span::{sym, symbol::kw, Span, Symbol};
@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>(
rust_fn_sig: ty::PolyFnSig<'tcx>,
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
) -> (&'ll Type, &'ll Value) {
let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, &[]);
let llty = fn_abi.llvm_type(cx);
let llfn = cx.declare_fn(name, &fn_abi);
cx.set_frame_pointer_type(llfn);

View File

@ -1,4 +1,3 @@
use crate::abi::FnAbi;
use crate::attributes;
use crate::base;
use crate::context::CodegenCx;
@ -8,7 +7,7 @@ use rustc_codegen_ssa::traits::*;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
pub use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_session::config::CrateType;
use rustc_target::spec::RelocModel;
@ -53,7 +52,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
) {
assert!(!instance.substs.needs_infer());
let fn_abi = FnAbi::of_instance(self, instance, &[]);
let fn_abi = self.fn_abi_of_instance(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());

View File

@ -1,10 +1,9 @@
use crate::abi::FnAbi;
use crate::common::*;
use crate::context::TypeLowering;
use crate::type_::Type;
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
@ -231,7 +230,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
ty::Adt(def, _) if def.is_box() => {
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
}
ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])),
ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, &[])),
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
};
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);

View File

@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::{self, SwitchTargets};
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_span::source_map::Span;
@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
substs: drop_fn.substs,
};
let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]);
let fn_abi = bx.fn_abi_of_instance(virtual_drop, &[]);
let vtable = args[1];
args = &args[..1];
(
@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn_abi,
)
}
_ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])),
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, &[])),
};
helper.do_call(
self,
@ -433,7 +433,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 = bx.fn_abi_of_instance(instance, &[]);
let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call.
@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let def_id =
common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_abi = FnAbi::of_instance(bx, instance, &[]);
let fn_abi = bx.fn_abi_of_instance(instance, &[]);
let llfn = bx.get_fn_addr(instance);
// Codegen the actual panic invoke/call.
@ -579,8 +579,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
.collect::<Vec<_>>();
let fn_abi = match instance {
Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args),
None => FnAbi::of_fn_ptr(&bx, sig, &extra_args),
Some(instance) => bx.fn_abi_of_instance(instance, &extra_args),
None => bx.fn_abi_of_fn_ptr(sig, &extra_args),
};
if intrinsic == Some(sym::transmute) {

View File

@ -2,7 +2,7 @@ use crate::traits::*;
use rustc_errors::ErrorReported;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_target::abi::call::{FnAbi, PassMode};
@ -139,7 +139,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 = cx.fn_abi_of_instance(instance, &[]);
debug!("fn_abi: {:?}", fn_abi);
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);

View File

@ -8,14 +8,15 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_session::{
config::{self, OutputFilenames, PrintRequest},
Session,
};
use rustc_span::symbol::Symbol;
use rustc_target::abi::call::FnAbi;
use rustc_target::spec::Target;
pub use rustc_data_structures::sync::MetadataRef;
@ -38,12 +39,19 @@ pub trait BackendTypes {
}
pub trait Backend<'tcx>:
Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
Sized
+ BackendTypes
+ HasTyCtxt<'tcx>
+ LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+ FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
{
}
impl<'tcx, T> Backend<'tcx> for T where
Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
Self: BackendTypes
+ HasTyCtxt<'tcx>
+ LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+ FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
{
}

View File

@ -2035,6 +2035,12 @@ impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
}
}
impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
fn target_spec(&self) -> &Target {
&self.sess.target
}
}
impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
@ -2142,10 +2148,10 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
#[inline]
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
let tcx = self.tcx().at(span);
MaybeResult::from(
self.tcx()
.at(span)
.layout_of(self.param_env().and(ty))
tcx.layout_of(self.param_env().and(ty))
.map_err(|err| self.handle_layout_err(err, span, ty)),
)
}
@ -2545,10 +2551,10 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> 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
// `fn_abi_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.
// adjustments `fn_abi_of_instance` might be performing.
fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
// FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function.
let ty = self.ty(tcx, ty::ParamEnv::reveal_all());
@ -2801,7 +2807,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
}
/// Error produced by attempting to compute or adjust a `FnAbi`.
enum FnAbiError<'tcx> {
pub enum FnAbiError<'tcx> {
/// Error produced by a `layout_of` call, while computing `FnAbi` initially.
Layout(LayoutError<'tcx>),
@ -2830,125 +2836,124 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
}
}
pub trait FnAbiExt<'tcx, C>
where
C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>,
{
// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
// just for error handling.
#[derive(Debug)]
pub enum FnAbiRequest<'a, 'tcx> {
OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'a [Ty<'tcx>] },
OfInstance { instance: ty::Instance<'tcx>, extra_args: &'a [Ty<'tcx>] },
}
/// Trait for contexts that want to be able to compute `FnAbi`s.
/// This automatically gives access to `FnAbiOf`, through a blanket `impl`.
pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
/// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be
/// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`).
type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>;
/// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a
/// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`).
///
/// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`,
/// but this hook allows e.g. codegen to return only `&FnABi` from its
/// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with
/// (and any `FnAbiError`s are turned into fatal errors or ICEs).
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
span: Span,
fn_abi_request: FnAbiRequest<'_, 'tcx>,
) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error;
}
/// Blanket extension trait for contexts that can compute `FnAbi`s.
pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'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`
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
/// instead, where the instance is an `InstanceDef::Virtual`.
fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self;
#[inline]
fn fn_abi_of_fn_ptr(
&self,
sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here.
let span = self.layout_tcx_at_span();
let cx = LayoutCx { tcx: self.tcx().at(span), param_env: self.param_env() };
MaybeResult::from(
cx.fn_abi_new_internal(sig, extra_args, None, CodegenFnAttrFlags::empty(), false)
.map_err(|err| {
self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args })
}),
)
}
/// 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 an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self;
}
#[inline]
fn fn_abi_of_instance(
&self,
instance: ty::Instance<'tcx>,
extra_args: &[Ty<'tcx>],
) -> Self::FnAbiOfResult {
// FIXME(eddyb) get a better `span` here.
let span = self.layout_tcx_at_span();
let cx = LayoutCx { tcx: self.tcx().at(span), param_env: self.param_env() };
impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
where
C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>,
{
fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self {
call::FnAbi::new_internal(
&LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() },
sig,
extra_args,
None,
CodegenFnAttrFlags::empty(),
false,
)
.unwrap_or_else(|err| {
// FIXME(eddyb) get a better `span` here.
let span = DUMMY_SP;
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
cx.tcx().sess.span_fatal(span, &err.to_string())
} else {
span_bug!(span, "`FnAbi::of_fn_ptr({}, {:?})` failed: {}", sig, extra_args, err);
}
})
}
fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> &'tcx Self {
let sig = instance.fn_sig_for_fn_abi(cx.tcx());
let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
Some(cx.tcx().caller_location_ty())
Some(cx.tcx.caller_location_ty())
} else {
None
};
let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
let attrs = cx.tcx.codegen_fn_attrs(instance.def_id()).flags;
call::FnAbi::new_internal(
&LayoutCx { tcx: cx.tcx(), param_env: cx.param_env() },
sig,
extra_args,
caller_location,
attrs,
matches!(instance.def, ty::InstanceDef::Virtual(..)),
MaybeResult::from(
cx.fn_abi_new_internal(
sig,
extra_args,
caller_location,
attrs,
matches!(instance.def, ty::InstanceDef::Virtual(..)),
)
.map_err(|err| {
// HACK(eddyb) at least for definitions of/calls to `Instance`s,
// we can get some kind of span even if one wasn't provided.
// However, we don't do this early in order to avoid calling
// `def_span` unconditionally (which may have a perf penalty).
let span = if !span.is_dummy() { span } else { cx.tcx.def_span(instance.def_id()) };
self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
}),
)
.unwrap_or_else(|err| {
// FIXME(eddyb) get a better `span` here.
let span = cx.tcx().def_span(instance.def_id());
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
cx.tcx().sess.span_fatal(span, &err.to_string())
} else {
span_bug!(
span,
"`FnAbi::of_instance({}, {:?})` failed: {}",
instance,
extra_args,
err
);
}
})
}
}
/// Implementation detail of computing `FnAbi`s, shouldn't be exported.
// FIXME(eddyb) move this off of being generic on `C: LayoutOf`, and
// explicitly take `LayoutCx` *or* `TyCtxt` and `ParamEnvAnd<...>`.
trait FnAbiInternalExt<'tcx, C>
where
C: LayoutOf<'tcx, LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>>
+ HasTargetSpec,
{
impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
impl<'tcx> LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
// arguments of this method, into a separate `struct`.
fn new_internal(
cx: &C,
fn fn_abi_new_internal(
&self,
sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
// FIXME(eddyb) replace this with something typed, like an `enum`.
make_self_ptr_thin: bool,
) -> Result<&'tcx Self, FnAbiError<'tcx>>;
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>>;
}
impl<'tcx, C> FnAbiInternalExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
where
C: LayoutOf<'tcx, LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>>
+ HasTargetSpec,
{
fn new_internal(
cx: &C,
sig: ty::PolyFnSig<'tcx>,
extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>,
codegen_fn_attr_flags: CodegenFnAttrFlags,
force_thin_self_ptr: bool,
) -> Result<&'tcx Self, FnAbiError<'tcx>> {
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
let sig = cx.tcx().normalize_erasing_late_bound_regions(cx.param_env(), sig);
let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig);
let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
let conv = conv_from_spec_abi(self.tcx(), sig.abi);
let mut inputs = sig.inputs();
let extra_args = if sig.abi == RustCall {
@ -2975,7 +2980,7 @@ where
extra_args.to_vec()
};
let target = &cx.tcx().sess.target;
let target = &self.tcx.sess.target;
let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl");
let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
let linux_s390x_gnu_like =
@ -3008,7 +3013,7 @@ where
attrs.set(ArgAttribute::NonNull);
}
if let Some(pointee) = layout.pointee_info_at(cx, offset) {
if let Some(pointee) = layout.pointee_info_at(self, offset) {
if let Some(kind) = pointee.safe {
attrs.pointee_align = Some(pointee.align);
@ -3055,17 +3060,17 @@ where
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
let is_return = arg_idx.is_none();
let layout = cx.layout_of(ty)?;
let layout = self.layout_of(ty)?;
let layout = if force_thin_self_ptr && arg_idx == Some(0) {
// 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
make_thin_self_ptr(cx, layout)
make_thin_self_ptr(self, layout)
} else {
layout
};
let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| {
let mut attrs = ArgAttributes::new();
adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
attrs
@ -3102,14 +3107,18 @@ where
c_variadic: sig.c_variadic,
fixed_count: inputs.len(),
conv,
can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi),
can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi),
};
fn_abi.adjust_for_abi(cx, sig.abi)?;
self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
debug!("FnAbi::new_internal = {:?}", fn_abi);
Ok(cx.tcx().intern_fn_abi(fn_abi))
Ok(self.tcx.intern_fn_abi(fn_abi))
}
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) -> Result<(), FnAbiError<'tcx>> {
fn fn_abi_adjust_for_abi(
&self,
fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
abi: SpecAbi,
) -> Result<(), FnAbiError<'tcx>> {
if abi == SpecAbi::Unadjusted {
return Ok(());
}
@ -3148,7 +3157,7 @@ where
// anyway, we control all calls to it in libstd.
Abi::Vector { .. }
if abi != SpecAbi::PlatformIntrinsic
&& cx.tcx().sess.target.simd_types_indirect =>
&& self.tcx.sess.target.simd_types_indirect =>
{
arg.make_indirect();
return;
@ -3159,7 +3168,7 @@ where
// Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`.
// LLVM will usually pass these in 2 registers, which is more efficient than by-ref.
let max_by_val_size = Pointer.size(cx) * 2;
let max_by_val_size = Pointer.size(self) * 2;
let size = arg.layout.size;
if arg.layout.is_unsized() || size > max_by_val_size {
@ -3171,12 +3180,12 @@ where
arg.cast_to(Reg { kind: RegKind::Integer, size });
}
};
fixup(&mut self.ret);
for arg in &mut self.args {
fixup(&mut fn_abi.ret);
for arg in &mut fn_abi.args {
fixup(arg);
}
} else {
self.adjust_for_foreign_abi(cx, abi)?;
fn_abi.adjust_for_foreign_abi(self, abi)?;
}
Ok(())