Skip to content

Commit 32cb5b8

Browse files
committed
Move discriminant get and set to discriminant.rs
1 parent 883894a commit 32cb5b8

File tree

4 files changed

+145
-135
lines changed

4 files changed

+145
-135
lines changed

src/base.rs

Lines changed: 3 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -246,55 +246,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
246246
variant_index,
247247
} => {
248248
let place = trans_place(fx, place);
249-
let layout = place.layout();
250-
if layout.for_variant(&*fx, *variant_index).abi == layout::Abi::Uninhabited {
251-
return;
252-
}
253-
match layout.variants {
254-
layout::Variants::Single { index } => {
255-
assert_eq!(index, *variant_index);
256-
}
257-
layout::Variants::Multiple {
258-
discr: _,
259-
discr_index,
260-
discr_kind: layout::DiscriminantKind::Tag,
261-
variants: _,
262-
} => {
263-
let ptr = place.place_field(fx, mir::Field::new(discr_index));
264-
let to = layout
265-
.ty
266-
.discriminant_for_variant(fx.tcx, *variant_index)
267-
.unwrap()
268-
.val;
269-
let discr = CValue::const_val(fx, ptr.layout().ty, to);
270-
ptr.write_cvalue(fx, discr);
271-
}
272-
layout::Variants::Multiple {
273-
discr: _,
274-
discr_index,
275-
discr_kind: layout::DiscriminantKind::Niche {
276-
dataful_variant,
277-
ref niche_variants,
278-
niche_start,
279-
},
280-
variants: _,
281-
} => {
282-
if *variant_index != dataful_variant {
283-
let niche = place.place_field(fx, mir::Field::new(discr_index));
284-
//let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
285-
let niche_value =
286-
((variant_index.as_u32() - niche_variants.start().as_u32()) as u128)
287-
.wrapping_add(niche_start);
288-
// FIXME(eddyb) Check the actual primitive type here.
289-
let niche_llval = if niche_value == 0 {
290-
CValue::const_val(fx, niche.layout().ty, 0)
291-
} else {
292-
CValue::const_val(fx, niche.layout().ty, niche_value)
293-
};
294-
niche.write_cvalue(fx, niche_llval);
295-
}
296-
}
297-
}
249+
crate::discriminant::codegen_set_discriminant(fx, place, *variant_index);
298250
}
299251
StatementKind::Assign(to_place, rval) => {
300252
let lval = trans_place(fx, to_place);
@@ -435,7 +387,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
435387
// FIXME avoid forcing to stack
436388
let place =
437389
CPlace::for_addr(operand.force_stack(fx), operand.layout());
438-
let discr = trans_get_discriminant(fx, place, fx.layout_of(to_ty));
390+
let discr = crate::discriminant::codegen_get_discriminant(fx, place, fx.layout_of(to_ty));
439391
lval.write_cvalue(fx, discr);
440392
} else {
441393
let to_clif_ty = fx.clif_type(to_ty).unwrap();
@@ -470,7 +422,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
470422
}
471423
Rvalue::Discriminant(place) => {
472424
let place = trans_place(fx, place);
473-
let discr = trans_get_discriminant(fx, place, dest_layout);
425+
let discr = crate::discriminant::codegen_get_discriminant(fx, place, dest_layout);
474426
lval.write_cvalue(fx, discr);
475427
}
476428
Rvalue::Repeat(operand, times) => {
@@ -619,89 +571,6 @@ fn codegen_array_len<'a, 'tcx: 'a>(
619571
}
620572
}
621573

622-
pub fn trans_get_discriminant<'a, 'tcx: 'a>(
623-
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
624-
place: CPlace<'tcx>,
625-
dest_layout: TyLayout<'tcx>,
626-
) -> CValue<'tcx> {
627-
let layout = place.layout();
628-
629-
if layout.abi == layout::Abi::Uninhabited {
630-
return trap_unreachable_ret_value(fx, dest_layout, "[panic] Tried to get discriminant for uninhabited type.");
631-
}
632-
633-
let (discr_scalar, discr_index, discr_kind) = match &layout.variants {
634-
layout::Variants::Single { index } => {
635-
let discr_val = layout
636-
.ty
637-
.ty_adt_def()
638-
.map_or(u128::from(index.as_u32()), |def| {
639-
def.discriminant_for_variant(fx.tcx, *index).val
640-
});
641-
return CValue::const_val(fx, dest_layout.ty, discr_val);
642-
}
643-
layout::Variants::Multiple { discr, discr_index, discr_kind, variants: _ } => {
644-
(discr, *discr_index, discr_kind)
645-
}
646-
};
647-
648-
let discr = place.place_field(fx, mir::Field::new(discr_index)).to_cvalue(fx);
649-
let discr_ty = discr.layout().ty;
650-
let lldiscr = discr.load_scalar(fx);
651-
match discr_kind {
652-
layout::DiscriminantKind::Tag => {
653-
let signed = match discr_scalar.value {
654-
layout::Int(_, signed) => signed,
655-
_ => false,
656-
};
657-
let val = clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), signed);
658-
return CValue::by_val(val, dest_layout);
659-
}
660-
layout::DiscriminantKind::Niche {
661-
dataful_variant,
662-
ref niche_variants,
663-
niche_start,
664-
} => {
665-
let niche_llty = fx.clif_type(discr_ty).unwrap();
666-
let dest_clif_ty = fx.clif_type(dest_layout.ty).unwrap();
667-
if niche_variants.start() == niche_variants.end() {
668-
let b = fx
669-
.bcx
670-
.ins()
671-
.icmp_imm(IntCC::Equal, lldiscr, *niche_start as u64 as i64);
672-
let if_true = fx
673-
.bcx
674-
.ins()
675-
.iconst(dest_clif_ty, niche_variants.start().as_u32() as i64);
676-
let if_false = fx
677-
.bcx
678-
.ins()
679-
.iconst(dest_clif_ty, dataful_variant.as_u32() as i64);
680-
let val = fx.bcx.ins().select(b, if_true, if_false);
681-
return CValue::by_val(val, dest_layout);
682-
} else {
683-
// Rebase from niche values to discriminant values.
684-
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
685-
let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
686-
let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
687-
let b = fx.bcx.ins().icmp_imm(
688-
IntCC::UnsignedLessThanOrEqual,
689-
lldiscr,
690-
niche_variants.end().as_u32() as i64,
691-
);
692-
let if_true =
693-
clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), false);
694-
let if_false = fx
695-
.bcx
696-
.ins()
697-
.iconst(dest_clif_ty, dataful_variant.as_u32() as i64);
698-
let val = fx.bcx.ins().select(b, if_true, if_false);
699-
return CValue::by_val(val, dest_layout);
700-
}
701-
}
702-
}
703-
}
704-
705574
pub fn trans_place<'a, 'tcx: 'a>(
706575
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
707576
place: &Place<'tcx>,

src/discriminant.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use crate::prelude::*;
2+
3+
pub fn codegen_set_discriminant<'tcx>(
4+
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
5+
place: CPlace<'tcx>,
6+
variant_index: VariantIdx,
7+
) {
8+
let layout = place.layout();
9+
if layout.for_variant(&*fx, variant_index).abi == layout::Abi::Uninhabited {
10+
return;
11+
}
12+
match layout.variants {
13+
layout::Variants::Single { index } => {
14+
assert_eq!(index, variant_index);
15+
}
16+
layout::Variants::Multiple {
17+
discr: _,
18+
discr_index,
19+
discr_kind: layout::DiscriminantKind::Tag,
20+
variants: _,
21+
} => {
22+
let ptr = place.place_field(fx, mir::Field::new(discr_index));
23+
let to = layout
24+
.ty
25+
.discriminant_for_variant(fx.tcx, variant_index)
26+
.unwrap()
27+
.val;
28+
let discr = CValue::const_val(fx, ptr.layout().ty, to);
29+
ptr.write_cvalue(fx, discr);
30+
}
31+
layout::Variants::Multiple {
32+
discr: _,
33+
discr_index,
34+
discr_kind: layout::DiscriminantKind::Niche {
35+
dataful_variant,
36+
ref niche_variants,
37+
niche_start,
38+
},
39+
variants: _,
40+
} => {
41+
if variant_index != dataful_variant {
42+
let niche = place.place_field(fx, mir::Field::new(discr_index));
43+
//let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
44+
let niche_value =
45+
((variant_index.as_u32() - niche_variants.start().as_u32()) as u128)
46+
.wrapping_add(niche_start);
47+
// FIXME(eddyb) Check the actual primitive type here.
48+
let niche_llval = if niche_value == 0 {
49+
CValue::const_val(fx, niche.layout().ty, 0)
50+
} else {
51+
CValue::const_val(fx, niche.layout().ty, niche_value)
52+
};
53+
niche.write_cvalue(fx, niche_llval);
54+
}
55+
}
56+
}
57+
}
58+
59+
pub fn codegen_get_discriminant<'tcx>(
60+
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
61+
place: CPlace<'tcx>,
62+
dest_layout: TyLayout<'tcx>,
63+
) -> CValue<'tcx> {
64+
let layout = place.layout();
65+
66+
if layout.abi == layout::Abi::Uninhabited {
67+
return trap_unreachable_ret_value(fx, dest_layout, "[panic] Tried to get discriminant for uninhabited type.");
68+
}
69+
70+
let (discr_scalar, discr_index, discr_kind) = match &layout.variants {
71+
layout::Variants::Single { index } => {
72+
let discr_val = layout
73+
.ty
74+
.ty_adt_def()
75+
.map_or(u128::from(index.as_u32()), |def| {
76+
def.discriminant_for_variant(fx.tcx, *index).val
77+
});
78+
return CValue::const_val(fx, dest_layout.ty, discr_val);
79+
}
80+
layout::Variants::Multiple { discr, discr_index, discr_kind, variants: _ } => {
81+
(discr, *discr_index, discr_kind)
82+
}
83+
};
84+
85+
let discr = place.place_field(fx, mir::Field::new(discr_index)).to_cvalue(fx);
86+
let discr_ty = discr.layout().ty;
87+
let lldiscr = discr.load_scalar(fx);
88+
match discr_kind {
89+
layout::DiscriminantKind::Tag => {
90+
let signed = match discr_scalar.value {
91+
layout::Int(_, signed) => signed,
92+
_ => false,
93+
};
94+
let val = clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), signed);
95+
return CValue::by_val(val, dest_layout);
96+
}
97+
layout::DiscriminantKind::Niche {
98+
dataful_variant,
99+
ref niche_variants,
100+
niche_start,
101+
} => {
102+
let niche_llty = fx.clif_type(discr_ty).unwrap();
103+
let dest_clif_ty = fx.clif_type(dest_layout.ty).unwrap();
104+
if niche_variants.start() == niche_variants.end() {
105+
let b = fx
106+
.bcx
107+
.ins()
108+
.icmp_imm(IntCC::Equal, lldiscr, *niche_start as u64 as i64);
109+
let if_true = fx
110+
.bcx
111+
.ins()
112+
.iconst(dest_clif_ty, niche_variants.start().as_u32() as i64);
113+
let if_false = fx
114+
.bcx
115+
.ins()
116+
.iconst(dest_clif_ty, dataful_variant.as_u32() as i64);
117+
let val = fx.bcx.ins().select(b, if_true, if_false);
118+
return CValue::by_val(val, dest_layout);
119+
} else {
120+
// Rebase from niche values to discriminant values.
121+
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
122+
let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
123+
let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
124+
let b = fx.bcx.ins().icmp_imm(
125+
IntCC::UnsignedLessThanOrEqual,
126+
lldiscr,
127+
niche_variants.end().as_u32() as i64,
128+
);
129+
let if_true =
130+
clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), false);
131+
let if_false = fx
132+
.bcx
133+
.ins()
134+
.iconst(dest_clif_ty, dataful_variant.as_u32() as i64);
135+
let val = fx.bcx.ins().select(b, if_true, if_false);
136+
return CValue::by_val(val, dest_layout);
137+
}
138+
}
139+
}
140+
}

src/intrinsics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
377377
discriminant_value, (c val) {
378378
let pointee_layout = fx.layout_of(val.layout().ty.builtin_deref(true).unwrap().ty);
379379
let place = CPlace::for_addr(val.load_scalar(fx), pointee_layout);
380-
let discr = crate::base::trans_get_discriminant(fx, place, ret.layout());
380+
let discr = crate::discriminant::codegen_get_discriminant(fx, place, ret.layout());
381381
ret.write_cvalue(fx, discr);
382382
};
383383
size_of, <T> () {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ mod codegen_i128;
3838
mod common;
3939
mod constant;
4040
mod debuginfo;
41+
mod discriminant;
4142
mod driver;
4243
mod intrinsics;
4344
mod linkage;

0 commit comments

Comments
 (0)