1
Fork 0

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:
bors 2021-09-19 21:39:47 +00:00
commit 91198820d7
23 changed files with 508 additions and 244 deletions

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, ty::List::empty());
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;
@ -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> {
type LayoutOfResult = TyAndLayout<'tcx>;
@ -848,8 +859,39 @@ impl LayoutOfHelpers<'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 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(),
@ -209,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
hir::Unsafety::Unsafe,
Abi::Rust,
)),
&[],
ty::List::empty(),
),
);

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, ty::List::empty());
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, ty::List::empty());
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, ty::List::empty());
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,9 @@ 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, ty::List::empty()))
}
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
};
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);