Auto merge of #88575 - eddyb:fn-abi-queries, r=nagisa
Querify `FnAbi::of_{fn_ptr,instance}` as `fn_abi_of_{fn_ptr,instance}`. *Note: opening this PR as draft because it's based on #88499* This more or less replicates the `LayoutOf::layout_of` setup from #88499, to replace `FnAbi::of_{fn_ptr,instance}` with `FnAbiOf::fn_abi_of_{fn_ptr,instance}`, and also route them through queries (which `layout_of` has used for a while). The two changes at the use sites (other than the names) are: * return type is now wrapped in `&'tcx` * the value *is* interned, which may affect performance * the `extra_args` list is now an interned `&'tcx ty::List<Ty<'tcx>>` * should be cheap (it's empty for anything other than C variadics) Theoretically, a `FnAbiOfHelpers` implementer could choose to keep the `Result<...>` instead of eagerly erroring, but the only existing users of these APIs are codegen backends, so they don't (want to) take advantage of this. At least miri could make use of this, since it prefers propagating errors (it "just" doesn't use `FnAbi` yet - cc `@RalfJung).` The way this is done is probably less efficient than what is possible, because the queries handle the correctness-oriented API (i.e. the split into `fn` pointers vs instances), whereas a lower-level query could end up with more reuse between different instances with identical signatures. r? `@nagisa` cc `@oli-obk` `@bjorn3`
This commit is contained in:
commit
91198820d7
23 changed files with 508 additions and 244 deletions
|
@ -5,7 +5,7 @@ mod pass_mode;
|
||||||
mod returning;
|
mod returning;
|
||||||
|
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
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::abi::call::{Conv, FnAbi};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
|
@ -53,7 +53,11 @@ pub(crate) fn get_function_sig<'tcx>(
|
||||||
inst: Instance<'tcx>,
|
inst: Instance<'tcx>,
|
||||||
) -> Signature {
|
) -> Signature {
|
||||||
assert!(!inst.substs.needs_infer());
|
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, ty::List::empty()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instance must be monomorphized
|
/// Instance must be monomorphized
|
||||||
|
@ -350,14 +354,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let extra_args = &args[fn_sig.inputs().len()..];
|
let extra_args = &args[fn_sig.inputs().len()..];
|
||||||
let extra_args = extra_args
|
let extra_args = fx
|
||||||
.iter()
|
.tcx
|
||||||
.map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))
|
.mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let fn_abi = if let Some(instance) = instance {
|
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 {
|
} 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
|
let is_cold = instance
|
||||||
|
@ -525,7 +528,8 @@ pub(crate) fn codegen_drop<'tcx>(
|
||||||
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
|
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
|
||||||
substs: drop_instance.substs,
|
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, ty::List::empty());
|
||||||
|
|
||||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
|
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
|
||||||
let sig = fx.bcx.import_signature(sig);
|
let sig = fx.bcx.import_signature(sig);
|
||||||
|
@ -534,7 +538,8 @@ pub(crate) fn codegen_drop<'tcx>(
|
||||||
_ => {
|
_ => {
|
||||||
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
|
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, ty::List::empty());
|
||||||
|
|
||||||
let arg_value = drop_place.place_ref(
|
let arg_value = drop_place.place_ref(
|
||||||
fx,
|
fx,
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
|
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::ty::adjustment::PointerCast;
|
use rustc_middle::ty::adjustment::PointerCast;
|
||||||
use rustc_middle::ty::layout::FnAbiExt;
|
use rustc_middle::ty::layout::FnAbiOf;
|
||||||
use rustc_target::abi::call::FnAbi;
|
|
||||||
|
|
||||||
use crate::constant::ConstantCx;
|
use crate::constant::ConstantCx;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -62,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>(
|
||||||
instance,
|
instance,
|
||||||
symbol_name,
|
symbol_name,
|
||||||
mir,
|
mir,
|
||||||
fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
|
fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())),
|
||||||
|
|
||||||
bcx,
|
bcx,
|
||||||
block_map,
|
block_map,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use rustc_index::vec::IndexVec;
|
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_middle::ty::SymbolName;
|
||||||
use rustc_target::abi::call::FnAbi;
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::abi::{Integer, Primitive};
|
use rustc_target::abi::{Integer, Primitive};
|
||||||
|
@ -239,7 +241,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
||||||
pub(crate) instance: Instance<'tcx>,
|
pub(crate) instance: Instance<'tcx>,
|
||||||
pub(crate) symbol_name: SymbolName<'tcx>,
|
pub(crate) symbol_name: SymbolName<'tcx>,
|
||||||
pub(crate) mir: &'tcx Body<'tcx>,
|
pub(crate) mir: &'tcx Body<'tcx>,
|
||||||
pub(crate) fn_abi: Option<FnAbi<'tcx, Ty<'tcx>>>,
|
pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
|
||||||
|
|
||||||
pub(crate) bcx: FunctionBuilder<'clif>,
|
pub(crate) bcx: FunctionBuilder<'clif>,
|
||||||
pub(crate) block_map: IndexVec<BasicBlock, Block>,
|
pub(crate) block_map: IndexVec<BasicBlock, Block>,
|
||||||
|
@ -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> {
|
impl<'tcx> layout::HasTyCtxt<'tcx> for FunctionCx<'_, '_, 'tcx> {
|
||||||
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
||||||
self.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> {
|
impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> {
|
||||||
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
||||||
self.0
|
self.0
|
||||||
|
|
|
@ -129,9 +129,7 @@ pub(crate) fn codegen_constant<'tcx>(
|
||||||
};
|
};
|
||||||
let const_val = match const_.val {
|
let const_val = match const_.val {
|
||||||
ConstKind::Value(const_val) => const_val,
|
ConstKind::Value(const_val) => const_val,
|
||||||
ConstKind::Unevaluated(uv)
|
ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => {
|
||||||
if fx.tcx.is_static(uv.def.did) =>
|
|
||||||
{
|
|
||||||
assert!(uv.substs(fx.tcx).is_empty());
|
assert!(uv.substs(fx.tcx).is_empty());
|
||||||
assert!(uv.promoted.is_none());
|
assert!(uv.promoted.is_none());
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,8 @@ use cranelift_codegen::{
|
||||||
write::{FuncWriter, PlainWriter},
|
write::{FuncWriter, PlainWriter},
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustc_middle::ty::layout::FnAbiExt;
|
use rustc_middle::ty::layout::FnAbiOf;
|
||||||
use rustc_session::config::OutputType;
|
use rustc_session::config::OutputType;
|
||||||
use rustc_target::abi::call::FnAbi;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -81,7 +80,10 @@ impl CommentWriter {
|
||||||
vec![
|
vec![
|
||||||
format!("symbol {}", tcx.symbol_name(instance).name),
|
format!("symbol {}", tcx.symbol_name(instance).name),
|
||||||
format!("instance {:?}", instance),
|
format!("instance {:?}", instance),
|
||||||
format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
|
format!(
|
||||||
|
"abi {:?}",
|
||||||
|
RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())
|
||||||
|
),
|
||||||
String::new(),
|
String::new(),
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,10 +15,12 @@ use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::MemFlags;
|
use rustc_codegen_ssa::MemFlags;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_hir::def_id::DefId;
|
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_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
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 rustc_target::spec::{HasTargetSpec, Target};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ffi::CStr;
|
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> {
|
impl Deref for Builder<'_, 'll, 'tcx> {
|
||||||
type Target = CodegenCx<'ll, 'tcx>;
|
type Target = CodegenCx<'ll, 'tcx>;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//! and methods are represented as just a fn ptr and not a full
|
//! and methods are represented as just a fn ptr and not a full
|
||||||
//! closure.
|
//! closure.
|
||||||
|
|
||||||
use crate::abi::{FnAbi, FnAbiLlvmExt};
|
use crate::abi::FnAbiLlvmExt;
|
||||||
use crate::attributes;
|
use crate::attributes;
|
||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
|
@ -12,7 +12,7 @@ use crate::value::Value;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||||
|
|
||||||
/// Codegens a reference to a fn/method item, monomorphizing and
|
/// 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
|
sym
|
||||||
);
|
);
|
||||||
|
|
||||||
let fn_abi = FnAbi::of_instance(cx, instance, &[]);
|
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||||
|
|
||||||
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
|
let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
|
||||||
// Create a fn pointer with the new signature.
|
// Create a fn pointer with the new signature.
|
||||||
|
|
|
@ -15,14 +15,19 @@ use rustc_data_structures::base_n;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_middle::mir::mono::CodegenUnit;
|
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::ty::{self, Instance, Ty, TyCtxt};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
|
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::symbol::Symbol;
|
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 rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -835,6 +840,12 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
|
ty::ParamEnv::reveal_all()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
|
impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
type LayoutOfResult = TyAndLayout<'tcx>;
|
type LayoutOfResult = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
|
@ -848,8 +859,39 @@ impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
|
impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
|
||||||
ty::ParamEnv::reveal_all()
|
|
||||||
|
#[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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
|
|
||||||
use crate::abi::{Abi, FnAbi};
|
use crate::abi::Abi;
|
||||||
use crate::builder::Builder;
|
use crate::builder::Builder;
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ use rustc_middle::mir::coverage::{
|
||||||
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
|
CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty;
|
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::subst::InternalSubsts;
|
||||||
use rustc_middle::ty::Instance;
|
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(
|
let llfn = cx.declare_fn(
|
||||||
&tcx.symbol_name(instance).name,
|
&tcx.symbol_name(instance).name,
|
||||||
&FnAbi::of_fn_ptr(
|
&cx.fn_abi_of_fn_ptr(
|
||||||
cx,
|
|
||||||
ty::Binder::dummy(tcx.mk_fn_sig(
|
ty::Binder::dummy(tcx.mk_fn_sig(
|
||||||
iter::once(tcx.mk_unit()),
|
iter::once(tcx.mk_unit()),
|
||||||
tcx.mk_unit(),
|
tcx.mk_unit(),
|
||||||
|
@ -209,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
|
||||||
hir::Unsafety::Unsafe,
|
hir::Unsafety::Unsafe,
|
||||||
Abi::Rust,
|
Abi::Rust,
|
||||||
)),
|
)),
|
||||||
&[],
|
ty::List::empty(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,11 @@ use super::utils::DIB;
|
||||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
|
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
|
|
||||||
use crate::abi::FnAbi;
|
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
use crate::llvm::debuginfo::{DILocation, DIScope};
|
use crate::llvm::debuginfo::{DILocation, DIScope};
|
||||||
use rustc_middle::mir::{Body, SourceScope};
|
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_middle::ty::{self, Instance};
|
||||||
use rustc_session::config::DebugInfo;
|
use rustc_session::config::DebugInfo;
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ fn make_mir_scope(
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
callee,
|
callee,
|
||||||
);
|
);
|
||||||
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
|
let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
|
||||||
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
|
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
|
||||||
}
|
}
|
||||||
None => unsafe {
|
None => unsafe {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::operand::OperandRef;
|
||||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_hir as hir;
|
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::ty::{self, Ty};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::{sym, symbol::kw, Span, Symbol};
|
use rustc_span::{sym, symbol::kw, Span, Symbol};
|
||||||
|
@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>(
|
||||||
rust_fn_sig: ty::PolyFnSig<'tcx>,
|
rust_fn_sig: ty::PolyFnSig<'tcx>,
|
||||||
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
|
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
|
||||||
) -> (&'ll Type, &'ll Value) {
|
) -> (&'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, ty::List::empty());
|
||||||
let llty = fn_abi.llvm_type(cx);
|
let llty = fn_abi.llvm_type(cx);
|
||||||
let llfn = cx.declare_fn(name, &fn_abi);
|
let llfn = cx.declare_fn(name, &fn_abi);
|
||||||
cx.set_frame_pointer_type(llfn);
|
cx.set_frame_pointer_type(llfn);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::abi::FnAbi;
|
|
||||||
use crate::attributes;
|
use crate::attributes;
|
||||||
use crate::base;
|
use crate::base;
|
||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
|
@ -8,7 +7,7 @@ use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
pub use rustc_middle::mir::mono::MonoItem;
|
pub use rustc_middle::mir::mono::MonoItem;
|
||||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
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_middle::ty::{self, Instance, TypeFoldable};
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
use rustc_target::spec::RelocModel;
|
use rustc_target::spec::RelocModel;
|
||||||
|
@ -53,7 +52,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
) {
|
) {
|
||||||
assert!(!instance.substs.needs_infer());
|
assert!(!instance.substs.needs_infer());
|
||||||
|
|
||||||
let fn_abi = FnAbi::of_instance(self, instance, &[]);
|
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||||
let lldecl = self.declare_fn(symbol_name, &fn_abi);
|
let lldecl = self.declare_fn(symbol_name, &fn_abi);
|
||||||
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
|
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
|
||||||
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use crate::abi::FnAbi;
|
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::context::TypeLowering;
|
use crate::context::TypeLowering;
|
||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_middle::bug;
|
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::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
||||||
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
|
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
|
||||||
|
@ -231,7 +230,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
ty::Adt(def, _) if def.is_box() => {
|
ty::Adt(def, _) if def.is_box() => {
|
||||||
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
|
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, ty::List::empty()))
|
||||||
|
}
|
||||||
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
|
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
|
||||||
};
|
};
|
||||||
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
|
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir::AssertKind;
|
use rustc_middle::mir::AssertKind;
|
||||||
use rustc_middle::mir::{self, SwitchTargets};
|
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::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
@ -124,7 +124,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
fx: &mut FunctionCx<'a, 'tcx, Bx>,
|
fx: &mut FunctionCx<'a, 'tcx, Bx>,
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
fn_abi: FnAbi<'tcx, Ty<'tcx>>,
|
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
|
||||||
fn_ptr: Bx::Value,
|
fn_ptr: Bx::Value,
|
||||||
llargs: &[Bx::Value],
|
llargs: &[Bx::Value],
|
||||||
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
|
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
|
||||||
|
@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
|
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
|
||||||
substs: drop_fn.substs,
|
substs: drop_fn.substs,
|
||||||
};
|
};
|
||||||
let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]);
|
let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||||
let vtable = args[1];
|
let vtable = args[1];
|
||||||
args = &args[..1];
|
args = &args[..1];
|
||||||
(
|
(
|
||||||
|
@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
fn_abi,
|
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, ty::List::empty())),
|
||||||
};
|
};
|
||||||
helper.do_call(
|
helper.do_call(
|
||||||
self,
|
self,
|
||||||
|
@ -433,7 +433,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
// Obtain the panic entry point.
|
// Obtain the panic entry point.
|
||||||
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
|
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
|
||||||
let instance = ty::Instance::mono(bx.tcx(), def_id);
|
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, ty::List::empty());
|
||||||
let llfn = bx.get_fn_addr(instance);
|
let llfn = bx.get_fn_addr(instance);
|
||||||
|
|
||||||
// Codegen the actual panic invoke/call.
|
// Codegen the actual panic invoke/call.
|
||||||
|
@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
let def_id =
|
let def_id =
|
||||||
common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
|
common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
|
||||||
let instance = ty::Instance::mono(bx.tcx(), def_id);
|
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, ty::List::empty());
|
||||||
let llfn = bx.get_fn_addr(instance);
|
let llfn = bx.get_fn_addr(instance);
|
||||||
|
|
||||||
// Codegen the actual panic invoke/call.
|
// Codegen the actual panic invoke/call.
|
||||||
|
@ -570,17 +570,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let extra_args = &args[sig.inputs().skip_binder().len()..];
|
let extra_args = &args[sig.inputs().skip_binder().len()..];
|
||||||
let extra_args = extra_args
|
let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| {
|
||||||
.iter()
|
let op_ty = op_arg.ty(self.mir, bx.tcx());
|
||||||
.map(|op_arg| {
|
self.monomorphize(op_ty)
|
||||||
let op_ty = op_arg.ty(self.mir, bx.tcx());
|
}));
|
||||||
self.monomorphize(op_ty)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let fn_abi = match instance {
|
let fn_abi = match instance {
|
||||||
Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args),
|
Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
|
||||||
None => FnAbi::of_fn_ptr(&bx, sig, &extra_args),
|
None => bx.fn_abi_of_fn_ptr(sig, extra_args),
|
||||||
};
|
};
|
||||||
|
|
||||||
if intrinsic == Some(sym::transmute) {
|
if intrinsic == Some(sym::transmute) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::traits::*;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
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_middle::ty::{self, Instance, Ty, TypeFoldable};
|
||||||
use rustc_target::abi::call::{FnAbi, PassMode};
|
use rustc_target::abi::call::{FnAbi, PassMode};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||||
|
|
||||||
cx: &'a Bx::CodegenCx,
|
cx: &'a Bx::CodegenCx,
|
||||||
|
|
||||||
fn_abi: FnAbi<'tcx, Ty<'tcx>>,
|
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
|
||||||
|
|
||||||
/// When unwinding is initiated, we have to store this personality
|
/// When unwinding is initiated, we have to store this personality
|
||||||
/// value somewhere so that we can load it and re-use it in the
|
/// value somewhere so that we can load it and re-use it in the
|
||||||
|
@ -139,7 +139,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
|
|
||||||
let mir = cx.tcx().instance_mir(instance.def);
|
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, ty::List::empty());
|
||||||
debug!("fn_abi: {:?}", fn_abi);
|
debug!("fn_abi: {:?}", fn_abi);
|
||||||
|
|
||||||
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
|
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
|
||||||
|
|
|
@ -8,14 +8,15 @@ use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
|
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::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_session::{
|
use rustc_session::{
|
||||||
config::{self, OutputFilenames, PrintRequest},
|
config::{self, OutputFilenames, PrintRequest},
|
||||||
Session,
|
Session,
|
||||||
};
|
};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
|
|
||||||
pub use rustc_data_structures::sync::MetadataRef;
|
pub use rustc_data_structures::sync::MetadataRef;
|
||||||
|
@ -38,12 +39,19 @@ pub trait BackendTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Backend<'tcx>:
|
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
|
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>>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
macro_rules! arena_types {
|
macro_rules! arena_types {
|
||||||
($macro:path, $tcx:lifetime) => (
|
($macro:path, $tcx:lifetime) => (
|
||||||
$macro!([
|
$macro!([
|
||||||
[] layouts: rustc_target::abi::Layout,
|
[] layout: rustc_target::abi::Layout,
|
||||||
|
[] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>,
|
||||||
// AdtDef are interned and compared by address
|
// AdtDef are interned and compared by address
|
||||||
[] adt_def: rustc_middle::ty::AdtDef,
|
[] adt_def: rustc_middle::ty::AdtDef,
|
||||||
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<$tcx>>,
|
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<$tcx>>,
|
||||||
|
|
|
@ -1128,6 +1128,27 @@ rustc_queries! {
|
||||||
desc { "computing layout of `{}`", key.value }
|
desc { "computing layout of `{}`", key.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
|
||||||
|
///
|
||||||
|
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
|
||||||
|
/// instead, where the instance is an `InstanceDef::Virtual`.
|
||||||
|
query fn_abi_of_fn_ptr(
|
||||||
|
key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
|
||||||
|
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
|
||||||
|
desc { "computing call ABI of `{}` function pointers", key.value.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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`).
|
||||||
|
query fn_abi_of_instance(
|
||||||
|
key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
|
||||||
|
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
|
||||||
|
desc { "computing call ABI of `{}`", key.value.0 }
|
||||||
|
}
|
||||||
|
|
||||||
query dylib_dependency_formats(_: CrateNum)
|
query dylib_dependency_formats(_: CrateNum)
|
||||||
-> &'tcx [(CrateNum, LinkagePreference)] {
|
-> &'tcx [(CrateNum, LinkagePreference)] {
|
||||||
desc { "dylib dependency formats of crate" }
|
desc { "dylib dependency formats of crate" }
|
||||||
|
|
|
@ -102,8 +102,8 @@ pub struct CtxtInterners<'tcx> {
|
||||||
/// The arena that types, regions, etc. are allocated from.
|
/// The arena that types, regions, etc. are allocated from.
|
||||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||||
|
|
||||||
/// Specifically use a speedy hash algorithm for these hash sets, since
|
// Specifically use a speedy hash algorithm for these hash sets, since
|
||||||
/// they're accessed quite often.
|
// they're accessed quite often.
|
||||||
type_: InternedSet<'tcx, TyS<'tcx>>,
|
type_: InternedSet<'tcx, TyS<'tcx>>,
|
||||||
type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
|
type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
|
||||||
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
|
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
|
||||||
|
@ -116,9 +116,9 @@ pub struct CtxtInterners<'tcx> {
|
||||||
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
||||||
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
|
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
|
||||||
const_: InternedSet<'tcx, Const<'tcx>>,
|
const_: InternedSet<'tcx, Const<'tcx>>,
|
||||||
/// Const allocations.
|
const_allocation: InternedSet<'tcx, Allocation>,
|
||||||
allocation: InternedSet<'tcx, Allocation>,
|
|
||||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||||
|
layout: InternedSet<'tcx, Layout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CtxtInterners<'tcx> {
|
impl<'tcx> CtxtInterners<'tcx> {
|
||||||
|
@ -136,8 +136,9 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||||
projs: Default::default(),
|
projs: Default::default(),
|
||||||
place_elems: Default::default(),
|
place_elems: Default::default(),
|
||||||
const_: Default::default(),
|
const_: Default::default(),
|
||||||
allocation: Default::default(),
|
const_allocation: Default::default(),
|
||||||
bound_variable_kinds: Default::default(),
|
bound_variable_kinds: Default::default(),
|
||||||
|
layout: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,10 +1047,9 @@ pub struct GlobalCtxt<'tcx> {
|
||||||
/// Stores memory for globals (statics/consts).
|
/// Stores memory for globals (statics/consts).
|
||||||
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
|
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
|
||||||
|
|
||||||
layout_interner: ShardedHashMap<&'tcx Layout, ()>,
|
|
||||||
|
|
||||||
output_filenames: Arc<OutputFilenames>,
|
output_filenames: Arc<OutputFilenames>,
|
||||||
|
|
||||||
|
// FIXME(eddyb) this doesn't belong here and should be using a query.
|
||||||
pub(super) vtables_cache:
|
pub(super) vtables_cache:
|
||||||
Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
|
Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
|
||||||
}
|
}
|
||||||
|
@ -1091,13 +1091,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr))
|
self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation {
|
|
||||||
self.interners
|
|
||||||
.allocation
|
|
||||||
.intern(alloc, |alloc| Interned(self.interners.arena.alloc(alloc)))
|
|
||||||
.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocates a read-only byte or string literal for `mir::interpret`.
|
/// Allocates a read-only byte or string literal for `mir::interpret`.
|
||||||
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
|
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
|
||||||
// Create an allocation that just contains these bytes.
|
// Create an allocation that just contains these bytes.
|
||||||
|
@ -1106,20 +1099,19 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.create_memory_alloc(alloc)
|
self.create_memory_alloc(alloc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(eddyb) move to `direct_interners!`.
|
||||||
pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {
|
pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {
|
||||||
self.stability_interner.intern(stab, |stab| self.arena.alloc(stab))
|
self.stability_interner.intern(stab, |stab| self.arena.alloc(stab))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(eddyb) move to `direct_interners!`.
|
||||||
pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability {
|
pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability {
|
||||||
self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab))
|
self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_layout(self, layout: Layout) -> &'tcx Layout {
|
|
||||||
self.layout_interner.intern(layout, |layout| self.arena.alloc(layout))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a range of the start/end indices specified with the
|
/// Returns a range of the start/end indices specified with the
|
||||||
/// `rustc_layout_scalar_valid_range` attribute.
|
/// `rustc_layout_scalar_valid_range` attribute.
|
||||||
|
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
|
||||||
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
|
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
|
||||||
let attrs = self.get_attrs(def_id);
|
let attrs = self.get_attrs(def_id);
|
||||||
let get = |name| {
|
let get = |name| {
|
||||||
|
@ -1194,7 +1186,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
evaluation_cache: Default::default(),
|
evaluation_cache: Default::default(),
|
||||||
crate_name: Symbol::intern(crate_name),
|
crate_name: Symbol::intern(crate_name),
|
||||||
data_layout,
|
data_layout,
|
||||||
layout_interner: Default::default(),
|
|
||||||
stability_interner: Default::default(),
|
stability_interner: Default::default(),
|
||||||
const_stability_interner: Default::default(),
|
const_stability_interner: Default::default(),
|
||||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||||
|
@ -1665,7 +1656,7 @@ macro_rules! nop_list_lift {
|
||||||
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
|
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
|
||||||
nop_lift! {region; Region<'a> => Region<'tcx>}
|
nop_lift! {region; Region<'a> => Region<'tcx>}
|
||||||
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
|
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
|
||||||
nop_lift! {allocation; &'a Allocation => &'tcx Allocation}
|
nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation}
|
||||||
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
|
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
|
||||||
|
|
||||||
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
|
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
|
||||||
|
@ -1957,8 +1948,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
"Const Stability interner: #{}",
|
"Const Stability interner: #{}",
|
||||||
self.0.const_stability_interner.len()
|
self.0.const_stability_interner.len()
|
||||||
)?;
|
)?;
|
||||||
writeln!(fmt, "Allocation interner: #{}", self.0.interners.allocation.len())?;
|
writeln!(
|
||||||
writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?;
|
fmt,
|
||||||
|
"Const Allocation interner: #{}",
|
||||||
|
self.0.interners.const_allocation.len()
|
||||||
|
)?;
|
||||||
|
writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -2046,38 +2041,6 @@ impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List<T>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
|
|
||||||
fn borrow(&self) -> &RegionKind {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Borrow<Const<'tcx>> for Interned<'tcx, Const<'tcx>> {
|
|
||||||
fn borrow<'a>(&'a self) -> &'a Const<'tcx> {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Borrow<Allocation> for Interned<'tcx, Allocation> {
|
|
||||||
fn borrow<'a>(&'a self) -> &'a Allocation {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> PartialEq for Interned<'tcx, Allocation> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.0 == other.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Eq for Interned<'tcx, Allocation> {}
|
|
||||||
|
|
||||||
impl<'tcx> Hash for Interned<'tcx, Allocation> {
|
|
||||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
|
||||||
self.0.hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! direct_interners {
|
macro_rules! direct_interners {
|
||||||
($($name:ident: $method:ident($ty:ty),)+) => {
|
($($name:ident: $method:ident($ty:ty),)+) => {
|
||||||
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
|
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
|
||||||
|
@ -2094,9 +2057,15 @@ macro_rules! direct_interners {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> {
|
||||||
|
fn borrow<'a>(&'a self) -> &'a $ty {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn $method(self, v: $ty) -> &'tcx $ty {
|
pub fn $method(self, v: $ty) -> &'tcx $ty {
|
||||||
self.interners.$name.intern_ref(&v, || {
|
self.interners.$name.intern(v, |v| {
|
||||||
Interned(self.interners.arena.alloc(v))
|
Interned(self.interners.arena.alloc(v))
|
||||||
}).0
|
}).0
|
||||||
}
|
}
|
||||||
|
@ -2107,6 +2076,8 @@ macro_rules! direct_interners {
|
||||||
direct_interners! {
|
direct_interners! {
|
||||||
region: mk_region(RegionKind),
|
region: mk_region(RegionKind),
|
||||||
const_: mk_const(Const<'tcx>),
|
const_: mk_const(Const<'tcx>),
|
||||||
|
const_allocation: intern_const_alloc(Allocation),
|
||||||
|
layout: intern_layout(Layout),
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! slice_interners {
|
macro_rules! slice_interners {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::ich::StableHashingContext;
|
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
|
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
|
||||||
use crate::ty::subst::Subst;
|
use crate::ty::subst::Subst;
|
||||||
|
@ -6,7 +5,6 @@ use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
|
@ -18,15 +16,19 @@ use rustc_target::abi::call::{
|
||||||
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
|
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
|
||||||
};
|
};
|
||||||
use rustc_target::abi::*;
|
use rustc_target::abi::*;
|
||||||
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy};
|
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::mem;
|
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::ops::Bound;
|
use std::ops::Bound;
|
||||||
|
|
||||||
|
pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
|
*providers =
|
||||||
|
ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
|
||||||
|
}
|
||||||
|
|
||||||
pub trait IntegerExt {
|
pub trait IntegerExt {
|
||||||
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
|
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
|
||||||
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
|
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
|
||||||
|
@ -191,7 +193,7 @@ pub const FAT_PTR_EXTRA: usize = 1;
|
||||||
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
|
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
|
||||||
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
|
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)]
|
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
|
||||||
pub enum LayoutError<'tcx> {
|
pub enum LayoutError<'tcx> {
|
||||||
Unknown(Ty<'tcx>),
|
Unknown(Ty<'tcx>),
|
||||||
SizeOverflow(Ty<'tcx>),
|
SizeOverflow(Ty<'tcx>),
|
||||||
|
@ -248,10 +250,6 @@ fn layout_of<'tcx>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut ty::query::Providers) {
|
|
||||||
*providers = ty::query::Providers { layout_of, ..*providers };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LayoutCx<'tcx, C> {
|
pub struct LayoutCx<'tcx, C> {
|
||||||
pub tcx: C,
|
pub tcx: C,
|
||||||
pub param_env: ty::ParamEnv<'tcx>,
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
|
@ -2015,6 +2013,12 @@ impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> HasTargetSpec for TyCtxt<'tcx> {
|
||||||
|
fn target_spec(&self) -> &Target {
|
||||||
|
&self.sess.target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
|
impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
|
@ -2029,6 +2033,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> {
|
impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
|
@ -2048,6 +2058,12 @@ impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> {
|
||||||
|
fn target_spec(&self) -> &Target {
|
||||||
|
self.tcx.target_spec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> {
|
impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx.tcx()
|
self.tcx.tcx()
|
||||||
|
@ -2130,10 +2146,10 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
|
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 span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
|
||||||
|
let tcx = self.tcx().at(span);
|
||||||
|
|
||||||
MaybeResult::from(
|
MaybeResult::from(
|
||||||
self.tcx()
|
tcx.layout_of(self.param_env().and(ty))
|
||||||
.at(span)
|
|
||||||
.layout_of(self.param_env().and(ty))
|
|
||||||
.map_err(|err| self.handle_layout_err(err, span, ty)),
|
.map_err(|err| self.handle_layout_err(err, span, ty)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2519,24 +2535,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
|
|
||||||
#[inline]
|
|
||||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
|
||||||
use crate::ty::layout::LayoutError::*;
|
|
||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
Unknown(t) | SizeOverflow(t) => t.hash_stable(hcx, hasher),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> ty::Instance<'tcx> {
|
impl<'tcx> ty::Instance<'tcx> {
|
||||||
// NOTE(eddyb) this is private to avoid using it from outside of
|
// 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),
|
// for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
|
||||||
// or should go through `FnAbi` instead, to avoid losing any
|
// 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> {
|
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.
|
// FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function.
|
||||||
let ty = self.ty(tcx, ty::ParamEnv::reveal_all());
|
let ty = self.ty(tcx, ty::ParamEnv::reveal_all());
|
||||||
|
@ -2633,34 +2637,6 @@ impl<'tcx> ty::Instance<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FnAbiExt<'tcx, C>
|
|
||||||
where
|
|
||||||
C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
|
|
||||||
{
|
|
||||||
/// 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 an `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 an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
|
|
||||||
fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
|
|
||||||
|
|
||||||
fn new_internal(
|
|
||||||
cx: &C,
|
|
||||||
sig: ty::PolyFnSig<'tcx>,
|
|
||||||
extra_args: &[Ty<'tcx>],
|
|
||||||
caller_location: Option<Ty<'tcx>>,
|
|
||||||
codegen_fn_attr_flags: CodegenFnAttrFlags,
|
|
||||||
make_self_ptr_thin: bool,
|
|
||||||
) -> Self;
|
|
||||||
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculates whether a function's ABI can unwind or not.
|
/// Calculates whether a function's ABI can unwind or not.
|
||||||
///
|
///
|
||||||
/// This takes two primary parameters:
|
/// This takes two primary parameters:
|
||||||
|
@ -2816,48 +2792,175 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
|
/// Error produced by attempting to compute or adjust a `FnAbi`.
|
||||||
where
|
#[derive(Clone, Debug, HashStable)]
|
||||||
C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
|
pub enum FnAbiError<'tcx> {
|
||||||
{
|
/// Error produced by a `layout_of` call, while computing `FnAbi` initially.
|
||||||
fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
|
Layout(LayoutError<'tcx>),
|
||||||
call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false)
|
|
||||||
|
/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
|
||||||
|
AdjustForForeignAbi(call::AdjustForForeignAbiError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LayoutError<'tcx>> for FnAbiError<'tcx> {
|
||||||
|
fn from(err: LayoutError<'tcx>) -> Self {
|
||||||
|
Self::Layout(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
|
||||||
|
fn from(err: call::AdjustForForeignAbiError) -> Self {
|
||||||
|
Self::AdjustForForeignAbi(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> fmt::Display for FnAbiError<'tcx> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Layout(err) => err.fmt(f),
|
||||||
|
Self::AdjustForForeignAbi(err) => err.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
|
||||||
|
// just for error handling.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum FnAbiRequest<'tcx> {
|
||||||
|
OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
|
||||||
|
OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<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 `fn_abi_of_instance`
|
||||||
|
/// instead, where the instance is an `InstanceDef::Virtual`.
|
||||||
|
#[inline]
|
||||||
|
fn fn_abi_of_fn_ptr(
|
||||||
|
&self,
|
||||||
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
|
extra_args: &'tcx ty::List<Ty<'tcx>>,
|
||||||
|
) -> Self::FnAbiOfResult {
|
||||||
|
// FIXME(eddyb) get a better `span` here.
|
||||||
|
let span = self.layout_tcx_at_span();
|
||||||
|
let tcx = self.tcx().at(span);
|
||||||
|
|
||||||
|
MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
|
||||||
|
|err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
|
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
|
||||||
let sig = instance.fn_sig_for_fn_abi(cx.tcx());
|
/// 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`).
|
||||||
|
#[inline]
|
||||||
|
fn fn_abi_of_instance(
|
||||||
|
&self,
|
||||||
|
instance: ty::Instance<'tcx>,
|
||||||
|
extra_args: &'tcx ty::List<Ty<'tcx>>,
|
||||||
|
) -> Self::FnAbiOfResult {
|
||||||
|
// FIXME(eddyb) get a better `span` here.
|
||||||
|
let span = self.layout_tcx_at_span();
|
||||||
|
let tcx = self.tcx().at(span);
|
||||||
|
|
||||||
let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
|
MaybeResult::from(
|
||||||
Some(cx.tcx().caller_location_ty())
|
tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
|
||||||
} else {
|
// HACK(eddyb) at least for definitions of/calls to `Instance`s,
|
||||||
None
|
// 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 attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
|
let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
|
||||||
|
self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
|
||||||
call::FnAbi::new_internal(
|
}),
|
||||||
cx,
|
|
||||||
sig,
|
|
||||||
extra_args,
|
|
||||||
caller_location,
|
|
||||||
attrs,
|
|
||||||
matches!(instance.def, ty::InstanceDef::Virtual(..)),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn new_internal(
|
impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
|
||||||
cx: &C,
|
|
||||||
|
fn fn_abi_of_fn_ptr<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
|
||||||
|
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
|
||||||
|
let (param_env, (sig, extra_args)) = query.into_parts();
|
||||||
|
|
||||||
|
LayoutCx { tcx, param_env }.fn_abi_new_uncached(
|
||||||
|
sig,
|
||||||
|
extra_args,
|
||||||
|
None,
|
||||||
|
CodegenFnAttrFlags::empty(),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_abi_of_instance<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
|
||||||
|
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
|
||||||
|
let (param_env, (instance, extra_args)) = query.into_parts();
|
||||||
|
|
||||||
|
let sig = instance.fn_sig_for_fn_abi(tcx);
|
||||||
|
|
||||||
|
let caller_location = if instance.def.requires_caller_location(tcx) {
|
||||||
|
Some(tcx.caller_location_ty())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags;
|
||||||
|
|
||||||
|
LayoutCx { tcx, param_env }.fn_abi_new_uncached(
|
||||||
|
sig,
|
||||||
|
extra_args,
|
||||||
|
caller_location,
|
||||||
|
attrs,
|
||||||
|
matches!(instance.def, ty::InstanceDef::Virtual(..)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
|
||||||
|
// arguments of this method, into a separate `struct`.
|
||||||
|
fn fn_abi_new_uncached(
|
||||||
|
&self,
|
||||||
sig: ty::PolyFnSig<'tcx>,
|
sig: ty::PolyFnSig<'tcx>,
|
||||||
extra_args: &[Ty<'tcx>],
|
extra_args: &[Ty<'tcx>],
|
||||||
caller_location: Option<Ty<'tcx>>,
|
caller_location: Option<Ty<'tcx>>,
|
||||||
codegen_fn_attr_flags: CodegenFnAttrFlags,
|
codegen_fn_attr_flags: CodegenFnAttrFlags,
|
||||||
|
// FIXME(eddyb) replace this with something typed, like an `enum`.
|
||||||
force_thin_self_ptr: bool,
|
force_thin_self_ptr: bool,
|
||||||
) -> Self {
|
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
|
||||||
debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
|
debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args);
|
||||||
|
|
||||||
let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), 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 mut inputs = sig.inputs();
|
||||||
let extra_args = if sig.abi == RustCall {
|
let extra_args = if sig.abi == RustCall {
|
||||||
|
@ -2884,7 +2987,7 @@ where
|
||||||
extra_args.to_vec()
|
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 target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl");
|
||||||
let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
|
let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
|
||||||
let linux_s390x_gnu_like =
|
let linux_s390x_gnu_like =
|
||||||
|
@ -2917,7 +3020,7 @@ where
|
||||||
attrs.set(ArgAttribute::NonNull);
|
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 {
|
if let Some(kind) = pointee.safe {
|
||||||
attrs.pointee_align = Some(pointee.align);
|
attrs.pointee_align = Some(pointee.align);
|
||||||
|
|
||||||
|
@ -2961,20 +3064,20 @@ where
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
|
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
|
||||||
let is_return = arg_idx.is_none();
|
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) {
|
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.
|
// 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`
|
// 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
|
// 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 {
|
} else {
|
||||||
layout
|
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();
|
let mut attrs = ArgAttributes::new();
|
||||||
adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
|
adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
|
||||||
attrs
|
attrs
|
||||||
|
@ -2995,11 +3098,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arg
|
Ok(arg)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut fn_abi = FnAbi {
|
let mut fn_abi = FnAbi {
|
||||||
ret: arg_of(sig.output(), None),
|
ret: arg_of(sig.output(), None)?,
|
||||||
args: inputs
|
args: inputs
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -3007,20 +3110,24 @@ where
|
||||||
.chain(caller_location)
|
.chain(caller_location)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, ty)| arg_of(ty, Some(i)))
|
.map(|(i, ty)| arg_of(ty, Some(i)))
|
||||||
.collect(),
|
.collect::<Result<_, _>>()?,
|
||||||
c_variadic: sig.c_variadic,
|
c_variadic: sig.c_variadic,
|
||||||
fixed_count: inputs.len(),
|
fixed_count: inputs.len(),
|
||||||
conv,
|
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);
|
debug!("fn_abi_new_uncached = {:?}", fn_abi);
|
||||||
fn_abi
|
Ok(self.tcx.arena.alloc(fn_abi))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
|
fn fn_abi_adjust_for_abi(
|
||||||
|
&self,
|
||||||
|
fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
|
||||||
|
abi: SpecAbi,
|
||||||
|
) -> Result<(), FnAbiError<'tcx>> {
|
||||||
if abi == SpecAbi::Unadjusted {
|
if abi == SpecAbi::Unadjusted {
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if abi == SpecAbi::Rust
|
if abi == SpecAbi::Rust
|
||||||
|
@ -3057,7 +3164,7 @@ where
|
||||||
// anyway, we control all calls to it in libstd.
|
// anyway, we control all calls to it in libstd.
|
||||||
Abi::Vector { .. }
|
Abi::Vector { .. }
|
||||||
if abi != SpecAbi::PlatformIntrinsic
|
if abi != SpecAbi::PlatformIntrinsic
|
||||||
&& cx.tcx().sess.target.simd_types_indirect =>
|
&& self.tcx.sess.target.simd_types_indirect =>
|
||||||
{
|
{
|
||||||
arg.make_indirect();
|
arg.make_indirect();
|
||||||
return;
|
return;
|
||||||
|
@ -3068,7 +3175,7 @@ where
|
||||||
|
|
||||||
// Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`.
|
// 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.
|
// 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;
|
let size = arg.layout.size;
|
||||||
|
|
||||||
if arg.layout.is_unsized() || size > max_by_val_size {
|
if arg.layout.is_unsized() || size > max_by_val_size {
|
||||||
|
@ -3080,16 +3187,15 @@ where
|
||||||
arg.cast_to(Reg { kind: RegKind::Integer, size });
|
arg.cast_to(Reg { kind: RegKind::Integer, size });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fixup(&mut self.ret);
|
fixup(&mut fn_abi.ret);
|
||||||
for arg in &mut self.args {
|
for arg in &mut fn_abi.args {
|
||||||
fixup(arg);
|
fixup(arg);
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
|
fn_abi.adjust_for_foreign_abi(self, abi)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(msg) = self.adjust_for_cabi(cx, abi) {
|
Ok(())
|
||||||
cx.tcx().sess.fatal(&msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
|
||||||
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||||
use rustc_session::utils::NativeLibKind;
|
use rustc_session::utils::NativeLibKind;
|
||||||
use rustc_session::Limits;
|
use rustc_session::Limits;
|
||||||
|
use rustc_target::abi;
|
||||||
use rustc_target::spec::PanicStrategy;
|
use rustc_target::spec::PanicStrategy;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
|
|
|
@ -449,3 +449,25 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
|
||||||
DUMMY_SP
|
DUMMY_SP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
|
||||||
|
#[inline(always)]
|
||||||
|
fn query_crate_is_local(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_span(&self, _: TyCtxt<'_>) -> Span {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
|
||||||
|
#[inline(always)]
|
||||||
|
fn query_crate_is_local(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||||
|
self.0.default_span(tcx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::abi::{self, Abi, Align, FieldsShape, Size};
|
use crate::abi::{self, Abi, Align, FieldsShape, Size};
|
||||||
use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
|
use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
|
||||||
use crate::spec::{self, HasTargetSpec};
|
use crate::spec::{self, HasTargetSpec};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
mod aarch64;
|
mod aarch64;
|
||||||
mod amdgpu;
|
mod amdgpu;
|
||||||
|
@ -24,7 +25,7 @@ mod x86;
|
||||||
mod x86_64;
|
mod x86_64;
|
||||||
mod x86_win64;
|
mod x86_win64;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub enum PassMode {
|
pub enum PassMode {
|
||||||
/// Ignore the argument.
|
/// Ignore the argument.
|
||||||
///
|
///
|
||||||
|
@ -59,7 +60,7 @@ pub use attr_impl::ArgAttribute;
|
||||||
mod attr_impl {
|
mod attr_impl {
|
||||||
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
|
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
#[derive(Default)]
|
#[derive(Default, HashStable_Generic)]
|
||||||
pub struct ArgAttribute: u16 {
|
pub struct ArgAttribute: u16 {
|
||||||
const NoAlias = 1 << 1;
|
const NoAlias = 1 << 1;
|
||||||
const NoCapture = 1 << 2;
|
const NoCapture = 1 << 2;
|
||||||
|
@ -76,7 +77,7 @@ mod attr_impl {
|
||||||
/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
|
/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
|
||||||
/// defines if this extension should be zero-extension or sign-extension when necessary. When it is
|
/// defines if this extension should be zero-extension or sign-extension when necessary. When it is
|
||||||
/// not necessary to extend the argument, this enum is ignored.
|
/// not necessary to extend the argument, this enum is ignored.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub enum ArgExtension {
|
pub enum ArgExtension {
|
||||||
None,
|
None,
|
||||||
Zext,
|
Zext,
|
||||||
|
@ -85,7 +86,7 @@ pub enum ArgExtension {
|
||||||
|
|
||||||
/// A compact representation of LLVM attributes (at least those relevant for this module)
|
/// A compact representation of LLVM attributes (at least those relevant for this module)
|
||||||
/// that can be manipulated without interacting with LLVM's Attribute machinery.
|
/// that can be manipulated without interacting with LLVM's Attribute machinery.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct ArgAttributes {
|
pub struct ArgAttributes {
|
||||||
pub regular: ArgAttribute,
|
pub regular: ArgAttribute,
|
||||||
pub arg_ext: ArgExtension,
|
pub arg_ext: ArgExtension,
|
||||||
|
@ -126,14 +127,14 @@ impl ArgAttributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub enum RegKind {
|
pub enum RegKind {
|
||||||
Integer,
|
Integer,
|
||||||
Float,
|
Float,
|
||||||
Vector,
|
Vector,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct Reg {
|
pub struct Reg {
|
||||||
pub kind: RegKind,
|
pub kind: RegKind,
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
|
@ -183,7 +184,7 @@ impl Reg {
|
||||||
|
|
||||||
/// An argument passed entirely registers with the
|
/// An argument passed entirely registers with the
|
||||||
/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
|
/// same kind (e.g., HFA / HVA on PPC64 and AArch64).
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct Uniform {
|
pub struct Uniform {
|
||||||
pub unit: Reg,
|
pub unit: Reg,
|
||||||
|
|
||||||
|
@ -208,7 +209,7 @@ impl Uniform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct CastTarget {
|
pub struct CastTarget {
|
||||||
pub prefix: [Option<RegKind>; 8],
|
pub prefix: [Option<RegKind>; 8],
|
||||||
pub prefix_chunk_size: Size,
|
pub prefix_chunk_size: Size,
|
||||||
|
@ -436,7 +437,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
|
|
||||||
/// Information about how to pass an argument to,
|
/// Information about how to pass an argument to,
|
||||||
/// or return a value from, a function, under some ABI.
|
/// or return a value from, a function, under some ABI.
|
||||||
#[derive(Debug)]
|
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct ArgAbi<'a, Ty> {
|
pub struct ArgAbi<'a, Ty> {
|
||||||
pub layout: TyAndLayout<'a, Ty>,
|
pub layout: TyAndLayout<'a, Ty>,
|
||||||
|
|
||||||
|
@ -544,7 +545,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub enum Conv {
|
pub enum Conv {
|
||||||
// General language calling conventions, for which every target
|
// General language calling conventions, for which every target
|
||||||
// should have its own backend (e.g. LLVM) support.
|
// should have its own backend (e.g. LLVM) support.
|
||||||
|
@ -578,7 +579,7 @@ pub enum Conv {
|
||||||
///
|
///
|
||||||
/// I will do my best to describe this structure, but these
|
/// I will do my best to describe this structure, but these
|
||||||
/// comments are reverse-engineered and may be inaccurate. -NDM
|
/// comments are reverse-engineered and may be inaccurate. -NDM
|
||||||
#[derive(Debug)]
|
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub struct FnAbi<'a, Ty> {
|
pub struct FnAbi<'a, Ty> {
|
||||||
/// The LLVM types of each argument.
|
/// The LLVM types of each argument.
|
||||||
pub args: Vec<ArgAbi<'a, Ty>>,
|
pub args: Vec<ArgAbi<'a, Ty>>,
|
||||||
|
@ -599,8 +600,29 @@ pub struct FnAbi<'a, Ty> {
|
||||||
pub can_unwind: bool,
|
pub can_unwind: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
|
||||||
|
#[derive(Clone, Debug, HashStable_Generic)]
|
||||||
|
pub enum AdjustForForeignAbiError {
|
||||||
|
/// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs.
|
||||||
|
Unsupported { arch: String, abi: spec::abi::Abi },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AdjustForForeignAbiError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Unsupported { arch, abi } => {
|
||||||
|
write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, Ty> FnAbi<'a, Ty> {
|
impl<'a, Ty> FnAbi<'a, Ty> {
|
||||||
pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
|
pub fn adjust_for_foreign_abi<C>(
|
||||||
|
&mut self,
|
||||||
|
cx: &C,
|
||||||
|
abi: spec::abi::Abi,
|
||||||
|
) -> Result<(), AdjustForForeignAbiError>
|
||||||
where
|
where
|
||||||
Ty: TyAbiInterface<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: HasDataLayout + HasTargetSpec,
|
C: HasDataLayout + HasTargetSpec,
|
||||||
|
@ -655,7 +677,9 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
||||||
}
|
}
|
||||||
"asmjs" => wasm::compute_c_abi_info(cx, self),
|
"asmjs" => wasm::compute_c_abi_info(cx, self),
|
||||||
"bpf" => bpf::compute_abi_info(self),
|
"bpf" => bpf::compute_abi_info(self),
|
||||||
a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
|
arch => {
|
||||||
|
return Err(AdjustForForeignAbiError::Unsupported { arch: arch.to_string(), abi });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue