Skip to content

Commit 3031705

Browse files
committed
some more refactor of FnType. Things build now
1 parent 11426a4 commit 3031705

File tree

4 files changed

+409
-84
lines changed

4 files changed

+409
-84
lines changed

src/librustc/ty/layout.rs

+110-76
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1919
StableHasherResult};
2020

2121
pub use rustc_target::abi::*;
22-
use rustc_target::spec::HasTargetSpec;
22+
use rustc_target::spec::{HasTargetSpec, abi::Abi as SpecAbi};
2323
use rustc_target::abi::call::{
24-
ArgAttribute, ArgAttributes, ArgType, Conv, FnType, IgnoreMode, PassMode
24+
ArgAttribute, ArgAttributes, ArgType, Conv, FnType, IgnoreMode, PassMode, Reg, RegKind
2525
};
2626

2727

@@ -2266,81 +2266,48 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LayoutError<'gcx>
22662266
}
22672267
}
22682268

2269-
pub trait FnTypeExt<'tcx, C> {
2270-
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self
2271-
where
2272-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2273-
+ HasDataLayout
2274-
+ HasTargetSpec
2275-
+ HasTyCtxt<'tcx>
2276-
+ HasParamEnv<'tcx>;
2277-
fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self
2278-
where
2279-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2280-
+ HasDataLayout
2281-
+ HasTargetSpec
2282-
+ HasTyCtxt<'tcx>
2283-
+ HasParamEnv<'tcx>;
2284-
fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self
2285-
where
2286-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2287-
+ HasDataLayout
2288-
+ HasTargetSpec
2289-
+ HasTyCtxt<'tcx>
2290-
+ HasParamEnv<'tcx>;
2269+
pub trait FnTypeExt<'tcx, C>
2270+
where
2271+
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2272+
+ HasDataLayout
2273+
+ HasTargetSpec
2274+
+ HasTyCtxt<'tcx>
2275+
+ HasParamEnv<'tcx>,
2276+
{
2277+
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self;
2278+
fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
2279+
fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
22912280
fn new_internal(
22922281
cx: &C,
22932282
sig: ty::FnSig<'tcx>,
22942283
extra_args: &[Ty<'tcx>],
22952284
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
2296-
) -> Self
2297-
where
2298-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2299-
+ HasDataLayout
2300-
+ HasTargetSpec
2301-
+ HasTyCtxt<'tcx>
2302-
+ HasParamEnv<'tcx>;
2285+
) -> Self;
2286+
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
23032287
}
23042288

2305-
2306-
impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
2307-
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self
2308-
where
2309-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2310-
+ HasDataLayout
2311-
+ HasTargetSpec
2312-
+ HasTargetSpec
2313-
+ HasTyCtxt<'tcx>
2314-
+ HasParamEnv<'tcx>,
2315-
{
2289+
impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>>
2290+
where
2291+
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2292+
+ HasDataLayout
2293+
+ HasTargetSpec
2294+
+ HasTyCtxt<'tcx>
2295+
+ HasParamEnv<'tcx>,
2296+
{
2297+
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self {
23162298
let sig = instance.fn_sig(cx.tcx());
23172299
let sig = cx
23182300
.tcx()
23192301
.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
23202302
call::FnType::new(cx, sig, &[])
23212303
}
23222304

2323-
fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self
2324-
where
2325-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2326-
+ HasDataLayout
2327-
+ HasTargetSpec
2328-
+ HasTyCtxt<'tcx>
2329-
+ HasParamEnv<'tcx>,
2330-
{
2305+
fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
23312306
call::FnType::new_internal(cx, sig, extra_args, |ty, _| ArgType::new(cx.layout_of(ty)))
23322307
}
23332308

2334-
2335-
fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self
2336-
where
2337-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2338-
+ HasDataLayout
2339-
+ HasTargetSpec
2340-
+ HasTyCtxt<'tcx>
2341-
+ HasParamEnv<'tcx>,
2342-
{
2343-
FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
2309+
fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
2310+
FnTypeExt::new_internal(cx, sig, extra_args, |ty, arg_idx| {
23442311
let mut layout = cx.layout_of(ty);
23452312
// Don't pass the vtable, it's not an argument of the virtual fn.
23462313
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2395,19 +2362,11 @@ impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
23952362
}
23962363

23972364
fn new_internal(
2398-
cx: &C,
2399-
sig: ty::FnSig<'tcx>,
2400-
extra_args: &[Ty<'tcx>],
2401-
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
2402-
) -> Self
2403-
where
2404-
C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
2405-
+ HasDataLayout
2406-
+ HasTargetSpec
2407-
+ HasTargetSpec
2408-
+ HasTyCtxt<'tcx>
2409-
+ HasParamEnv<'tcx>,
2410-
{
2365+
cx: &C,
2366+
sig: ty::FnSig<'tcx>,
2367+
extra_args: &[Ty<'tcx>],
2368+
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
2369+
) -> Self {
24112370
debug!("FnType::new_internal({:?}, {:?})", sig, extra_args);
24122371

24132372
use rustc_target::spec::abi::Abi::*;
@@ -2591,7 +2550,7 @@ impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
25912550
arg
25922551
};
25932552

2594-
let fn_ty = FnType {
2553+
let mut fn_ty = FnType {
25952554
ret: arg_of(sig.output(), None),
25962555
args: inputs
25972556
.iter()
@@ -2603,8 +2562,83 @@ impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
26032562
c_variadic: sig.c_variadic,
26042563
conv,
26052564
};
2606-
// FIXME: uncomment this after figuring out wwhere should adjust_for_abi reside.
2607-
//fn_ty.adjust_for_abi(cx, sig.abi);
2565+
fn_ty.adjust_for_abi(cx, sig.abi);
26082566
fn_ty
26092567
}
2568+
2569+
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
2570+
if abi == SpecAbi::Unadjusted {
2571+
return;
2572+
}
2573+
2574+
if abi == SpecAbi::Rust
2575+
|| abi == SpecAbi::RustCall
2576+
|| abi == SpecAbi::RustIntrinsic
2577+
|| abi == SpecAbi::PlatformIntrinsic
2578+
{
2579+
let fixup = |arg: &mut ArgType<'tcx, Ty<'tcx>>| {
2580+
if arg.is_ignore() {
2581+
return;
2582+
}
2583+
2584+
match arg.layout.abi {
2585+
Abi::Aggregate { .. } => {}
2586+
2587+
// This is a fun case! The gist of what this is doing is
2588+
// that we want callers and callees to always agree on the
2589+
// ABI of how they pass SIMD arguments. If we were to *not*
2590+
// make these arguments indirect then they'd be immediates
2591+
// in LLVM, which means that they'd used whatever the
2592+
// appropriate ABI is for the callee and the caller. That
2593+
// means, for example, if the caller doesn't have AVX
2594+
// enabled but the callee does, then passing an AVX argument
2595+
// across this boundary would cause corrupt data to show up.
2596+
//
2597+
// This problem is fixed by unconditionally passing SIMD
2598+
// arguments through memory between callers and callees
2599+
// which should get them all to agree on ABI regardless of
2600+
// target feature sets. Some more information about this
2601+
// issue can be found in #44367.
2602+
//
2603+
// Note that the platform intrinsic ABI is exempt here as
2604+
// that's how we connect up to LLVM and it's unstable
2605+
// anyway, we control all calls to it in libstd.
2606+
Abi::Vector { .. }
2607+
if abi != SpecAbi::PlatformIntrinsic
2608+
&& cx.tcx().sess.target.target.options.simd_types_indirect =>
2609+
{
2610+
arg.make_indirect();
2611+
return;
2612+
}
2613+
2614+
_ => return,
2615+
}
2616+
2617+
let size = arg.layout.size;
2618+
if arg.layout.is_unsized() || size > Pointer.size(cx) {
2619+
arg.make_indirect();
2620+
} else {
2621+
// We want to pass small aggregates as immediates, but using
2622+
// a LLVM aggregate type for this leads to bad optimizations,
2623+
// so we pick an appropriately sized integer type instead.
2624+
arg.cast_to(Reg {
2625+
kind: RegKind::Integer,
2626+
size,
2627+
});
2628+
}
2629+
};
2630+
fixup(&mut self.ret);
2631+
for arg in &mut self.args {
2632+
fixup(arg);
2633+
}
2634+
if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
2635+
attrs.set(ArgAttribute::StructRet);
2636+
}
2637+
return;
2638+
}
2639+
2640+
if let Err(msg) = self.adjust_for_cabi(cx, abi) {
2641+
cx.tcx().sess.fatal(&msg);
2642+
}
2643+
}
26102644
}

0 commit comments

Comments
 (0)