3 pub fn codegen_set_discriminant<'tcx>(
4 fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
6 variant_index: VariantIdx,
8 let layout = place.layout();
9 if layout.for_variant(&*fx, variant_index).abi == layout::Abi::Uninhabited {
12 match layout.variants {
13 layout::Variants::Single { index } => {
14 assert_eq!(index, variant_index);
16 layout::Variants::Multiple {
19 discr_kind: layout::DiscriminantKind::Tag,
22 let ptr = place.place_field(fx, mir::Field::new(discr_index));
25 .discriminant_for_variant(fx.tcx, variant_index)
28 let discr = CValue::const_val(fx, ptr.layout().ty, to);
29 ptr.write_cvalue(fx, discr);
31 layout::Variants::Multiple {
34 discr_kind: layout::DiscriminantKind::Niche {
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);
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)
51 CValue::const_val(fx, niche.layout().ty, niche_value)
53 niche.write_cvalue(fx, niche_llval);
59 pub fn codegen_get_discriminant<'tcx>(
60 fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
62 dest_layout: TyLayout<'tcx>,
64 let layout = place.layout();
66 if layout.abi == layout::Abi::Uninhabited {
67 return trap_unreachable_ret_value(fx, dest_layout, "[panic] Tried to get discriminant for uninhabited type.");
70 let (discr_scalar, discr_index, discr_kind) = match &layout.variants {
71 layout::Variants::Single { index } => {
72 let discr_val = layout
75 .map_or(u128::from(index.as_u32()), |def| {
76 def.discriminant_for_variant(fx.tcx, *index).val
78 return CValue::const_val(fx, dest_layout.ty, discr_val);
80 layout::Variants::Multiple { discr, discr_index, discr_kind, variants: _ } => {
81 (discr, *discr_index, discr_kind)
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);
89 layout::DiscriminantKind::Tag => {
90 let signed = match discr_scalar.value {
91 layout::Int(_, signed) => signed,
94 let val = clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), signed);
95 return CValue::by_val(val, dest_layout);
97 layout::DiscriminantKind::Niche {
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() {
108 .icmp_imm(IntCC::Equal, lldiscr, *niche_start as u64 as i64);
112 .iconst(dest_clif_ty, niche_variants.start().as_u32() as i64);
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);
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,
127 niche_variants.end().as_u32() as i64,
130 clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), false);
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);