]> git.lizzy.rs Git - rust.git/commitdiff
Implement intrinsic discriminant_value and fix bug in discriminant reading
authorbjorn3 <bjorn3@users.noreply.github.com>
Mon, 30 Jul 2018 12:36:32 +0000 (14:36 +0200)
committerbjorn3 <bjorn3@users.noreply.github.com>
Mon, 30 Jul 2018 12:36:32 +0000 (14:36 +0200)
src/abi.rs
src/base.rs

index cc22ef06080721e38f8e751040ef7313732531d7..6e1c81e7bf1b95f152e24ca465cb1ee3606cf430 100644 (file)
@@ -263,6 +263,12 @@ pub fn codegen_call<'a, 'tcx: 'a>(
                     let count = args[2];*/
                     unimplemented!("copy");
                 }
+                "discriminant_value" => {
+                    assert_eq!(args.len(), 1);
+                    let discr = ::base::trans_get_discriminant(fx, args[0], ret.layout());
+                    ret.write_cvalue(fx, discr);
+                    unimplemented!("discriminant");
+                }
                 "size_of" => {
                     assert_eq!(args.len(), 0);
                     let size_of = fx.layout_of(substs.type_at(0)).size.bytes();
index e65abd0ddd7b6f31da8db8d05137661e88fcbcde..641cead4f3268828c61393a4afce594289323799 100644 (file)
@@ -11,7 +11,7 @@ pub fn trans_mono_item<'a, 'tcx: 'a>(cx: &mut CodegenCx<'a, 'tcx, CurrentBackend
             } => {
                 let mut mir = ::std::io::Cursor::new(Vec::new());
                 ::rustc_mir::util::write_mir_pretty(tcx, Some(def_id), &mut mir).unwrap();
-                tcx.sess.warn(&format!("{:?}:\n\n{}", def_id, String::from_utf8_lossy(&mir.into_inner())));
+                tcx.sess.warn(&format!("{:?}:\n\n{}", inst, String::from_utf8_lossy(&mir.into_inner())));
 
                 let fn_ty = inst.ty(tcx);
                 let fn_ty = tcx.subst_and_normalize_erasing_regions(
@@ -334,65 +334,9 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &
                 Rvalue::Cast(CastKind::ClosureFnPointer, operand, ty) => unimplemented!("rval closure_fn_ptr {:?} {:?}", operand, ty),
                 Rvalue::Cast(CastKind::Unsize, operand, ty) => return Err(format!("rval unsize {:?} {:?}", operand, ty)),
                 Rvalue::Discriminant(place) => {
-                    let place = trans_place(fx, place);
-                    let dest_cton_ty = fx.cton_type(dest_layout.ty).unwrap();
-                    let layout = lval.layout();
-
-                    if layout.abi == layout::Abi::Uninhabited {
-                        fx.bcx.ins().trap(TrapCode::User(!0));
-                    }
-                    match layout.variants {
-                        layout::Variants::Single { index } => {
-                            let discr_val = layout.ty.ty_adt_def().map_or(
-                                index as u128,
-                                |def| def.discriminant_for_variant(fx.tcx, index).val);
-                            let val = CValue::const_val(fx, dest_layout.ty, discr_val as u64 as i64);
-                            lval.write_cvalue(fx, val);
-                            return Ok(());
-                        }
-                        layout::Variants::Tagged { .. } |
-                        layout::Variants::NicheFilling { .. } => {},
-                    }
-
-                    let discr = place.to_cvalue(fx).value_field(fx, mir::Field::new(0));
-                    let discr_ty = discr.layout().ty;
-                    let lldiscr = discr.load_value(fx);
-                    match layout.variants {
-                        layout::Variants::Single { .. } => bug!(),
-                        layout::Variants::Tagged { ref tag, .. } => {
-                            let signed = match tag.value {
-                                layout::Int(_, signed) => signed,
-                                _ => false
-                            };
-                            let val = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, signed);
-                            lval.write_cvalue(fx, CValue::ByVal(val, dest_layout));
-                        }
-                        layout::Variants::NicheFilling {
-                            dataful_variant,
-                            ref niche_variants,
-                            niche_start,
-                            ..
-                        } => {
-                            let niche_llty = fx.cton_type(discr_ty).unwrap();
-                            if niche_variants.start() == niche_variants.end() {
-                                let b = fx.bcx.ins().icmp_imm(IntCC::Equal, lldiscr, niche_start as u64 as i64);
-                                let if_true = fx.bcx.ins().iconst(dest_cton_ty, *niche_variants.start() as u64 as i64);
-                                let if_false = fx.bcx.ins().iconst(dest_cton_ty, dataful_variant as u64 as i64);
-                                let val = fx.bcx.ins().select(b, if_true, if_false);
-                                lval.write_cvalue(fx, CValue::ByVal(val, dest_layout));
-                            } else {
-                                // Rebase from niche values to discriminant values.
-                                let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
-                                let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
-                                let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
-                                let b = fx.bcx.ins().icmp_imm(IntCC::UnsignedLessThanOrEqual, lldiscr, *niche_variants.end() as u64 as i64);
-                                let if_true = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, false);
-                                let if_false = fx.bcx.ins().iconst(niche_llty, dataful_variant as u64 as i64);
-                                let val = fx.bcx.ins().select(b, if_true, if_false);
-                                lval.write_cvalue(fx, CValue::ByVal(val, dest_layout));
-                            }
-                        }
-                    }
+                    let place = trans_place(fx, place).to_cvalue(fx);
+                    let discr = trans_get_discriminant(fx, place, dest_layout);
+                    lval.write_cvalue(fx, discr);
                 }
                 Rvalue::Repeat(operand, times) => unimplemented!("rval repeat {:?} {:?}", operand, times),
                 Rvalue::Len(lval) => return Err(format!("rval len {:?}", lval)),
@@ -408,6 +352,65 @@ fn trans_stmt<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, cur_ebb: Ebb, stmt: &
     Ok(())
 }
 
+pub fn trans_get_discriminant<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, value: CValue<'tcx>, dest_layout: TyLayout<'tcx>) -> CValue<'tcx> {
+    let layout = value.layout();
+
+    if layout.abi == layout::Abi::Uninhabited {
+        fx.bcx.ins().trap(TrapCode::User(!0));
+    }
+    match layout.variants {
+        layout::Variants::Single { index } => {
+            let discr_val = layout.ty.ty_adt_def().map_or(
+                index as u128,
+                |def| def.discriminant_for_variant(fx.tcx, index).val);
+            return CValue::const_val(fx, dest_layout.ty, discr_val as u64 as i64);
+        }
+        layout::Variants::Tagged { .. } |
+        layout::Variants::NicheFilling { .. } => {},
+    }
+
+    let discr = value.value_field(fx, mir::Field::new(0));
+    let discr_ty = discr.layout().ty;
+    let lldiscr = discr.load_value(fx);
+    match layout.variants {
+        layout::Variants::Single { .. } => bug!(),
+        layout::Variants::Tagged { ref tag, .. } => {
+            let signed = match tag.value {
+                layout::Int(_, signed) => signed,
+                _ => false
+            };
+            let val = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, signed);
+            return CValue::ByVal(val, dest_layout);
+        }
+        layout::Variants::NicheFilling {
+            dataful_variant,
+            ref niche_variants,
+            niche_start,
+            ..
+        } => {
+            let niche_llty = fx.cton_type(discr_ty).unwrap();
+            if niche_variants.start() == niche_variants.end() {
+                let dest_cton_ty = fx.cton_type(dest_layout.ty).unwrap();
+                let b = fx.bcx.ins().icmp_imm(IntCC::Equal, lldiscr, niche_start as u64 as i64);
+                let if_true = fx.bcx.ins().iconst(dest_cton_ty, *niche_variants.start() as u64 as i64);
+                let if_false = fx.bcx.ins().iconst(dest_cton_ty, dataful_variant as u64 as i64);
+                let val = fx.bcx.ins().select(b, if_true, if_false);
+                return CValue::ByVal(val, dest_layout);
+            } else {
+                // Rebase from niche values to discriminant values.
+                let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
+                let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
+                let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
+                let b = fx.bcx.ins().icmp_imm(IntCC::UnsignedLessThanOrEqual, lldiscr, *niche_variants.end() as u64 as i64);
+                let if_true = cton_intcast(fx, lldiscr, discr_ty, dest_layout.ty, false);
+                let if_false = fx.bcx.ins().iconst(niche_llty, dataful_variant as u64 as i64);
+                let val = fx.bcx.ins().select(b, if_true, if_false);
+                return CValue::ByVal(val, dest_layout);
+            }
+        }
+    }
+}
+
 macro_rules! binop_match {
     (@single $fx:expr, $bug_fmt:expr, $var:expr, $lhs:expr, $rhs:expr, bug) => {
         bug!("bin op {} on {} lhs: {:?} rhs: {:?}", stringify!($var), $bug_fmt, $lhs, $rhs)