Skip to content

Commit 0df3b41

Browse files
committed
Skip ZST arguments
Fixes #413 and increases compatibility with cg_llvm
1 parent 47b1ef2 commit 0df3b41

File tree

4 files changed

+49
-96
lines changed

4 files changed

+49
-96
lines changed

example/mini_core_hello_world.rs

+2
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,6 @@ fn main() {
206206
}
207207

208208
unsafe { assert_eq!(ABC as usize, 0); }
209+
210+
&mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>;
209211
}

src/abi.rs

+45-93
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::borrow::Cow;
2-
use std::iter;
32

4-
use rustc::hir;
53
use rustc::ty::layout::{FloatTy, Integer, Primitive, Scalar};
64
use rustc_target::spec::abi::Abi;
75

@@ -44,26 +42,16 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
4442
fn get_pass_mode<'a, 'tcx: 'a>(
4543
tcx: TyCtxt<'a, 'tcx, 'tcx>,
4644
ty: Ty<'tcx>,
47-
is_return: bool,
4845
) -> PassMode {
4946
let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
5047
assert!(!layout.is_unsized());
5148

52-
if layout.size.bytes() == 0 {
53-
if is_return {
54-
PassMode::NoPass
55-
} else {
56-
PassMode::ByRef
57-
}
49+
if layout.is_zst() {
50+
// WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer
51+
PassMode::NoPass
5852
} else {
5953
match &layout.abi {
60-
layout::Abi::Uninhabited => {
61-
if is_return {
62-
PassMode::NoPass
63-
} else {
64-
PassMode::ByRef
65-
}
66-
}
54+
layout::Abi::Uninhabited => PassMode::NoPass,
6755
layout::Abi::Scalar(scalar) => {
6856
PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone()))
6957
}
@@ -80,11 +68,11 @@ fn get_pass_mode<'a, 'tcx: 'a>(
8068
fn adjust_arg_for_abi<'a, 'tcx: 'a>(
8169
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
8270
arg: CValue<'tcx>,
83-
) -> Value {
84-
match get_pass_mode(fx.tcx, arg.layout().ty, false) {
85-
PassMode::NoPass => unimplemented!("pass mode nopass"),
86-
PassMode::ByVal(_) => arg.load_scalar(fx),
87-
PassMode::ByRef => arg.force_stack(fx),
71+
) -> Option<Value> {
72+
match get_pass_mode(fx.tcx, arg.layout().ty) {
73+
PassMode::NoPass => None,
74+
PassMode::ByVal(_) => Some(arg.load_scalar(fx)),
75+
PassMode::ByRef => Some(arg.force_stack(fx)),
8876
}
8977
}
9078

@@ -109,13 +97,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t
10997

11098
let inputs = inputs
11199
.into_iter()
112-
.filter_map(|ty| match get_pass_mode(tcx, ty, false) {
100+
.filter_map(|ty| match get_pass_mode(tcx, ty) {
101+
PassMode::NoPass => None,
113102
PassMode::ByVal(clif_ty) => Some(clif_ty),
114-
PassMode::NoPass => unimplemented!("pass mode nopass"),
115103
PassMode::ByRef => Some(pointer_ty(tcx)),
116104
});
117105

118-
let (params, returns) = match get_pass_mode(tcx, output, true) {
106+
let (params, returns) = match get_pass_mode(tcx, output) {
119107
PassMode::NoPass => (inputs.map(AbiParam::new).collect(), vec![]),
120108
PassMode::ByVal(ret_ty) => (
121109
inputs.map(AbiParam::new).collect(),
@@ -140,59 +128,13 @@ fn clif_sig_from_fn_sig<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sig: FnSig<'t
140128
}
141129
}
142130

143-
pub fn ty_fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> ty::FnSig<'tcx> {
144-
let sig = match ty.sty {
145-
ty::FnDef(..) |
146-
// Shims currently have type TyFnPtr. Not sure this should remain.
147-
ty::FnPtr(_) => ty.fn_sig(tcx),
148-
ty::Closure(def_id, substs) => {
149-
let sig = substs.closure_sig(def_id, tcx);
150-
151-
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
152-
sig.map_bound(|sig| tcx.mk_fn_sig(
153-
iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
154-
sig.output(),
155-
sig.c_variadic,
156-
sig.unsafety,
157-
sig.abi
158-
))
159-
}
160-
ty::Generator(def_id, substs, _) => {
161-
let sig = substs.poly_sig(def_id, tcx);
162-
163-
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
164-
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
165-
166-
sig.map_bound(|sig| {
167-
let state_did = tcx.lang_items().gen_state().unwrap();
168-
let state_adt_ref = tcx.adt_def(state_did);
169-
let state_substs = tcx.intern_substs(&[
170-
sig.yield_ty.into(),
171-
sig.return_ty.into(),
172-
]);
173-
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
174-
175-
tcx.mk_fn_sig(iter::once(env_ty),
176-
ret_ty,
177-
false,
178-
hir::Unsafety::Normal,
179-
Abi::Rust
180-
)
181-
})
182-
}
183-
_ => bug!("unexpected type {:?} to ty_fn_sig", ty)
184-
};
185-
tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &sig)
186-
}
187-
188131
pub fn get_function_name_and_sig<'a, 'tcx>(
189132
tcx: TyCtxt<'a, 'tcx, 'tcx>,
190133
inst: Instance<'tcx>,
191134
support_vararg: bool,
192135
) -> (String, Signature) {
193136
assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types());
194-
let fn_ty = inst.ty(tcx);
195-
let fn_sig = ty_fn_sig(tcx, fn_ty);
137+
let fn_sig = tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &inst.fn_sig(tcx));
196138
if fn_sig.c_variadic && !support_vararg {
197139
unimpl!("Variadic function definitions are not yet supported");
198140
}
@@ -293,7 +235,7 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> {
293235
}
294236

295237
fn self_sig(&self) -> FnSig<'tcx> {
296-
ty_fn_sig(self.tcx, self.instance.ty(self.tcx))
238+
self.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &self.instance.fn_sig(self.tcx))
297239
}
298240

299241
fn return_type(&self) -> Ty<'tcx> {
@@ -405,9 +347,14 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
405347
local_field: Option<usize>,
406348
arg_ty: Ty<'tcx>,
407349
ssa_flags: crate::analyze::Flags,
408-
) -> CValue<'tcx> {
350+
) -> Option<CValue<'tcx>> {
409351
let layout = fx.layout_of(arg_ty);
410-
let pass_mode = get_pass_mode(fx.tcx, arg_ty, false);
352+
let pass_mode = get_pass_mode(fx.tcx, arg_ty);
353+
354+
if let PassMode::NoPass = pass_mode {
355+
return None;
356+
}
357+
411358
let clif_type = pass_mode.get_param_ty(fx);
412359
let ebb_param = fx.bcx.append_ebb_param(start_ebb, clif_type);
413360

@@ -424,9 +371,9 @@ fn cvalue_for_param<'a, 'tcx: 'a>(
424371
);
425372

426373
match pass_mode {
427-
PassMode::NoPass => unimplemented!("pass mode nopass"),
428-
PassMode::ByVal(_) => CValue::ByVal(ebb_param, layout),
429-
PassMode::ByRef => CValue::ByRef(ebb_param, layout),
374+
PassMode::NoPass => unreachable!(),
375+
PassMode::ByVal(_) => Some(CValue::ByVal(ebb_param, layout)),
376+
PassMode::ByRef => Some(CValue::ByRef(ebb_param, layout)),
430377
}
431378
}
432379

@@ -440,7 +387,7 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
440387
fx.add_global_comment(format!("ssa {:?}", ssa_analyzed));
441388

442389
let ret_layout = fx.layout_of(fx.return_type());
443-
let output_pass_mode = get_pass_mode(fx.tcx, fx.return_type(), true);
390+
let output_pass_mode = get_pass_mode(fx.tcx, fx.return_type());
444391
let ret_param = match output_pass_mode {
445392
PassMode::NoPass => None,
446393
PassMode::ByVal(_) => None,
@@ -462,9 +409,10 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
462409
);
463410
}
464411

412+
// None means pass_mode == NoPass
465413
enum ArgKind<'tcx> {
466-
Normal(CValue<'tcx>),
467-
Spread(Vec<CValue<'tcx>>),
414+
Normal(Option<CValue<'tcx>>),
415+
Spread(Vec<Option<CValue<'tcx>>>),
468416
}
469417

470418
let func_params = fx
@@ -542,13 +490,17 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(
542490

543491
match arg_kind {
544492
ArgKind::Normal(param) => {
545-
place.write_cvalue(fx, param);
493+
if let Some(param) = param {
494+
place.write_cvalue(fx, param);
495+
}
546496
}
547497
ArgKind::Spread(params) => {
548498
for (i, param) in params.into_iter().enumerate() {
549-
place
550-
.place_field(fx, mir::Field::new(i))
551-
.write_cvalue(fx, param);
499+
if let Some(param) = param {
500+
place
501+
.place_field(fx, mir::Field::new(i))
502+
.write_cvalue(fx, param);
503+
}
552504
}
553505
}
554506
}
@@ -578,7 +530,7 @@ pub fn codegen_terminator_call<'a, 'tcx: 'a>(
578530
destination: &Option<(Place<'tcx>, BasicBlock)>,
579531
) {
580532
let fn_ty = fx.monomorphize(&func.ty(fx.mir, fx.tcx));
581-
let sig = ty_fn_sig(fx.tcx, fn_ty);
533+
let sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
582534

583535
// Unpack arguments tuple for closures
584536
let args = if sig.abi == Abi::RustCall {
@@ -649,11 +601,11 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
649601
args: Vec<CValue<'tcx>>,
650602
ret_place: Option<CPlace<'tcx>>,
651603
) {
652-
let fn_sig = ty_fn_sig(fx.tcx, fn_ty);
604+
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
653605

654606
let ret_layout = fx.layout_of(fn_sig.output());
655607

656-
let output_pass_mode = get_pass_mode(fx.tcx, fn_sig.output(), true);
608+
let output_pass_mode = get_pass_mode(fx.tcx, fn_sig.output());
657609
let return_ptr = match output_pass_mode {
658610
PassMode::NoPass => None,
659611
PassMode::ByRef => match ret_place {
@@ -683,15 +635,15 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
683635
}
684636

685637
// Normal call
686-
Some(_) => (None, args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg))),
638+
Some(_) => (None, args.get(0).and_then(|arg| adjust_arg_for_abi(fx, *arg))),
687639

688640
// Indirect call
689641
None => {
690642
let func = trans_operand(fx, func.expect("indirect call without func Operand"))
691643
.load_scalar(fx);
692644
(
693645
Some(func),
694-
args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg)),
646+
args.get(0).and_then(|arg| adjust_arg_for_abi(fx, *arg)),
695647
)
696648
}
697649
};
@@ -702,7 +654,7 @@ pub fn codegen_call_inner<'a, 'tcx: 'a>(
702654
.chain(
703655
args.into_iter()
704656
.skip(1)
705-
.map(|arg| adjust_arg_for_abi(fx, arg)),
657+
.filter_map(|arg| adjust_arg_for_abi(fx, arg)),
706658
)
707659
.collect::<Vec<_>>();
708660

@@ -756,9 +708,9 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
756708
let (ptr, vtable) = drop_place.to_addr_maybe_unsized(fx);
757709
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
758710

759-
let fn_sig = ty_fn_sig(fx.tcx, drop_fn_ty);
711+
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &drop_fn_ty.fn_sig(fx.tcx));
760712

761-
match get_pass_mode(fx.tcx, fn_sig.output(), true) {
713+
match get_pass_mode(fx.tcx, fn_sig.output()) {
762714
PassMode::NoPass => {}
763715
_ => unreachable!(),
764716
};
@@ -770,7 +722,7 @@ pub fn codegen_drop<'a, 'tcx: 'a>(
770722
}
771723

772724
pub fn codegen_return(fx: &mut FunctionCx<impl Backend>) {
773-
match get_pass_mode(fx.tcx, fx.return_type(), true) {
725+
match get_pass_mode(fx.tcx, fx.return_type()) {
774726
PassMode::NoPass | PassMode::ByRef => {
775727
fx.bcx.ins().return_(&[]);
776728
}

src/base.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>(
6969
// FIXME implement u128 and i128 support
7070

7171
// Step 2a. Check sig for u128 and i128
72-
let fn_ty = instance.ty(tcx);
73-
let fn_sig = crate::abi::ty_fn_sig(tcx, fn_ty);
72+
let fn_sig = tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx));
7473

7574
struct UI128Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>, bool);
7675

src/pretty_clif.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl CommentWriter {
7575
global_comments: vec![
7676
format!("symbol {}", tcx.symbol_name(instance).as_str()),
7777
format!("instance {:?}", instance),
78-
format!("sig {:?}", crate::abi::ty_fn_sig(tcx, instance.ty(tcx))),
78+
format!("sig {:?}", tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx))),
7979
String::new(),
8080
],
8181
entity_comments: HashMap::new(),

0 commit comments

Comments
 (0)