Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use a newtype for the variant discriminant in trans instead of u64 #30931

Merged
merged 1 commit into from
Jan 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/librustc_trans/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ use trans::expr::{self, Dest};
use trans::monomorphize;
use trans::tvec;
use trans::type_of;
use trans::Disr;
use middle::ty::{self, Ty};
use session::config::NoDebugInfo;
use util::common::indenter;
Expand Down Expand Up @@ -249,7 +250,7 @@ impl<'a> ConstantExpr<'a> {
enum Opt<'a, 'tcx> {
ConstantValue(ConstantExpr<'a>, DebugLoc),
ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>, DebugLoc),
Variant(ty::Disr, Rc<adt::Repr<'tcx>>, DefId, DebugLoc),
Variant(Disr, Rc<adt::Repr<'tcx>>, DefId, DebugLoc),
SliceLengthEqual(usize, DebugLoc),
SliceLengthGreaterOrEqual(/* prefix length */ usize,
/* suffix length */ usize,
Expand Down Expand Up @@ -670,7 +671,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
match opt_def {
Some(def::DefVariant(enum_id, var_id, _)) => {
let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id);
Variant(variant.disr_val,
Variant(Disr::from(variant.disr_val),
adt::represent_node(bcx, cur.id),
var_id,
debug_loc)
Expand Down Expand Up @@ -704,7 +705,7 @@ struct ExtractedBlock<'blk, 'tcx: 'blk> {

fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
repr: &adt::Repr<'tcx>,
disr_val: ty::Disr,
disr_val: Disr,
val: MatchInput)
-> ExtractedBlock<'blk, 'tcx> {
let _icx = push_ctxt("match::extract_variant_args");
Expand Down Expand Up @@ -1189,7 +1190,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
};
let adt_vals = if any_irrefutable_adt_pat(bcx.tcx(), m, col) {
let repr = adt::represent_type(bcx.ccx(), left_ty);
let arg_count = adt::num_args(&*repr, 0);
let arg_count = adt::num_args(&*repr, Disr(0));
let (arg_count, struct_val) = if type_is_sized(bcx.tcx(), left_ty) {
(arg_count, val.val)
} else {
Expand All @@ -1201,7 +1202,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
};
let mut field_vals: Vec<ValueRef> = (0..arg_count).map(|ix|
// By definition, these are all sized
adt::trans_field_ptr(bcx, &*repr, adt::MaybeSizedValue::sized(struct_val), 0, ix)
adt::trans_field_ptr(bcx, &*repr, adt::MaybeSizedValue::sized(struct_val), Disr(0), ix)
).collect();

match left_ty.sty {
Expand All @@ -1217,7 +1218,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let meta = Load(bcx, expr::get_meta(bcx, val.val));
let struct_val = adt::MaybeSizedValue::unsized_(struct_val, meta);

let data = adt::trans_field_ptr(bcx, &*repr, struct_val, 0, arg_count);
let data = adt::trans_field_ptr(bcx, &*repr, struct_val, Disr(0), arg_count);
Store(bcx, data, expr::get_dataptr(bcx, scratch));
Store(bcx, meta, expr::get_meta(bcx, scratch));
field_vals.push(scratch);
Expand Down Expand Up @@ -1855,7 +1856,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id);
let args = extract_variant_args(bcx,
&*repr,
vinfo.disr_val,
Disr::from(vinfo.disr_val),
val);
if let Some(ref sub_pat) = *sub_pats {
for (i, &argval) in args.vals.iter().enumerate() {
Expand All @@ -1878,7 +1879,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let val = adt::MaybeSizedValue::sized(val.val);
for (i, elem) in elems.iter().enumerate() {
let fldptr = adt::trans_field_ptr(bcx, &*repr,
val, 0, i);
val, Disr(0), i);
bcx = bind_irrefutable_pat(
bcx,
&**elem,
Expand Down Expand Up @@ -1937,7 +1938,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let repr = adt::represent_node(bcx, pat.id);
let val = adt::MaybeSizedValue::sized(val.val);
for (i, elem) in elems.iter().enumerate() {
let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i);
let fldptr = adt::trans_field_ptr(bcx, &*repr, val, Disr(0), i);
bcx = bind_irrefutable_pat(
bcx,
&**elem,
Expand Down
88 changes: 47 additions & 41 deletions src/librustc_trans/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
//! taken to it, implementing them for Rust seems difficult.

pub use self::Repr::*;
use super::Disr;

use std;
use std::rc::Rc;
Expand All @@ -50,7 +51,6 @@ use llvm::{ValueRef, True, IntEQ, IntNE};
use back::abi::FAT_PTR_ADDR;
use middle::subst;
use middle::ty::{self, Ty};
use middle::ty::Disr;
use syntax::ast;
use syntax::attr;
use syntax::attr::IntType;
Expand Down Expand Up @@ -308,20 +308,20 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,

if !dtor && cases.iter().all(|c| c.tys.is_empty()) {
// All bodies empty -> intlike
let discrs: Vec<u64> = cases.iter().map(|c| c.discr).collect();
let discrs: Vec<_> = cases.iter().map(|c| Disr::from(c.discr)).collect();
let bounds = IntBounds {
ulo: *discrs.iter().min().unwrap(),
uhi: *discrs.iter().max().unwrap(),
slo: discrs.iter().map(|n| *n as i64).min().unwrap(),
shi: discrs.iter().map(|n| *n as i64).max().unwrap()
ulo: discrs.iter().min().unwrap().0,
uhi: discrs.iter().max().unwrap().0,
slo: discrs.iter().map(|n| n.0 as i64).min().unwrap(),
shi: discrs.iter().map(|n| n.0 as i64).max().unwrap()
};
return mk_cenum(cx, hint, &bounds);
}

// Since there's at least one
// non-empty body, explicit discriminants should have
// been rejected by a checker before this point.
if !cases.iter().enumerate().all(|(i,c)| c.discr == (i as Disr)) {
if !cases.iter().enumerate().all(|(i,c)| c.discr == Disr::from(i)) {
cx.sess().bug(&format!("non-C-like enum {} with specified \
discriminants",
cx.tcx().item_path_str(def.did)));
Expand All @@ -347,7 +347,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
match cases[discr].find_ptr(cx) {
Some(ref df) if df.len() == 1 && st.fields.len() == 1 => {
return RawNullablePointer {
nndiscr: discr as Disr,
nndiscr: Disr::from(discr),
nnty: st.fields[0],
nullfields: cases[1 - discr].tys.clone()
};
Expand All @@ -356,7 +356,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
discrfield.push(0);
discrfield.reverse();
return StructWrappedNullablePointer {
nndiscr: discr as Disr,
nndiscr: Disr::from(discr),
nonnull: st,
discrfield: discrfield,
nullfields: cases[1 - discr].tys.clone()
Expand Down Expand Up @@ -564,7 +564,7 @@ fn get_cases<'tcx>(tcx: &ty::ctxt<'tcx>,
let field_tys = vi.fields.iter().map(|field| {
monomorphize::field_ty(tcx, substs, field)
}).collect();
Case { discr: vi.disr_val, tys: field_tys }
Case { discr: Disr::from(vi.disr_val), tys: field_tys }
}).collect()
}

Expand Down Expand Up @@ -605,8 +605,8 @@ fn mk_cenum<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-> Repr<'tcx> {
let it = range_to_inttype(cx, hint, bounds);
match it {
attr::SignedInt(_) => CEnum(it, bounds.slo as Disr, bounds.shi as Disr),
attr::UnsignedInt(_) => CEnum(it, bounds.ulo, bounds.uhi)
attr::SignedInt(_) => CEnum(it, Disr(bounds.slo as u64), Disr(bounds.shi as u64)),
attr::UnsignedInt(_) => CEnum(it, Disr(bounds.ulo), Disr(bounds.uhi))
}
}

Expand Down Expand Up @@ -923,11 +923,11 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
CEnum(ity, min, max) => load_discr(bcx, ity, scrutinee, min, max),
General(ity, ref cases, _) => {
let ptr = StructGEP(bcx, scrutinee, 0);
load_discr(bcx, ity, ptr, 0, (cases.len() - 1) as Disr)
load_discr(bcx, ity, ptr, Disr(0), Disr(cases.len() as u64 - 1))
}
Univariant(..) => C_u8(bcx.ccx(), 0),
RawNullablePointer { nndiscr, nnty, .. } => {
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
let cmp = if nndiscr == Disr(0) { IntEQ } else { IntNE };
let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty);
ICmp(bcx, cmp, Load(bcx, scrutinee), C_null(llptrty), DebugLoc::None)
}
Expand All @@ -945,7 +945,7 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
scrutinee: ValueRef) -> ValueRef {
let llptrptr = GEPi(bcx, scrutinee, &discrfield[..]);
let llptr = Load(bcx, llptrptr);
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
let cmp = if nndiscr == Disr(0) { IntEQ } else { IntNE };
ICmp(bcx, cmp, llptr, C_null(val_ty(llptr)), DebugLoc::None)
}

Expand All @@ -957,10 +957,10 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
let bits = machine::llbitsize_of_real(bcx.ccx(), llty);
assert!(bits <= 64);
let bits = bits as usize;
let mask = (!0u64 >> (64 - bits)) as Disr;
let mask = Disr(!0u64 >> (64 - bits));
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
// However, that is fine here (it would still represent the full range),
if (max.wrapping_add(1)) & mask == min & mask {
if max.wrapping_add(Disr(1)) & mask == min & mask {
// i.e., if the range is everything. The lo==hi case would be
// rejected by the LLVM verifier (it would mean either an
// empty set, which is impossible, or the entire range of the
Expand All @@ -969,7 +969,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
} else {
// llvm::ConstantRange can deal with ranges that wrap around,
// so an overflow on (max + 1) is fine.
LoadRangeAssert(bcx, ptr, min, (max.wrapping_add(1)), /* signed: */ True)
LoadRangeAssert(bcx, ptr, min, max.wrapping_add(Disr(1)), /* signed: */ True)
}
}

Expand All @@ -981,18 +981,18 @@ pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
-> ValueRef {
match *r {
CEnum(ity, _, _) => {
C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true)
C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true)
}
General(ity, _, _) => {
C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true)
C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true)
}
Univariant(..) => {
bcx.ccx().sess().bug("no cases for univariants or structs")
}
RawNullablePointer { .. } |
StructWrappedNullablePointer { .. } => {
assert!(discr == 0 || discr == 1);
C_bool(bcx.ccx(), discr != 0)
assert!(discr == Disr(0) || discr == Disr(1));
C_bool(bcx.ccx(), discr != Disr(0))
}
}
}
Expand All @@ -1004,20 +1004,20 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
match *r {
CEnum(ity, min, max) => {
assert_discr_in_range(ity, min, max, discr);
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true),
val);
}
General(ity, ref cases, dtor) => {
if dtor_active(dtor) {
let ptr = trans_field_ptr(bcx, r, MaybeSizedValue::sized(val), discr,
cases[discr as usize].fields.len() - 2);
cases[discr.0 as usize].fields.len() - 2);
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED), ptr);
}
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true),
StructGEP(bcx, val, 0));
}
Univariant(ref st, dtor) => {
assert_eq!(discr, 0);
assert_eq!(discr, Disr(0));
if dtor_active(dtor) {
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED),
StructGEP(bcx, val, st.fields.len() - 1));
Expand All @@ -1041,8 +1041,14 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,

fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) {
match ity {
attr::UnsignedInt(_) => assert!(min <= discr && discr <= max),
attr::SignedInt(_) => assert!(min as i64 <= discr as i64 && discr as i64 <= max as i64)
attr::UnsignedInt(_) => {
assert!(min <= discr);
assert!(discr <= max)
},
attr::SignedInt(_) => {
assert!(min.0 as i64 <= discr.0 as i64);
assert!(discr.0 as i64 <= max.0 as i64);
},
}
}

Expand All @@ -1052,11 +1058,11 @@ pub fn num_args(r: &Repr, discr: Disr) -> usize {
match *r {
CEnum(..) => 0,
Univariant(ref st, dtor) => {
assert_eq!(discr, 0);
assert_eq!(discr, Disr(0));
st.fields.len() - (if dtor_active(dtor) { 1 } else { 0 })
}
General(_, ref cases, dtor) => {
cases[discr as usize].fields.len() - 1 - (if dtor_active(dtor) { 1 } else { 0 })
cases[discr.0 as usize].fields.len() - 1 - (if dtor_active(dtor) { 1 } else { 0 })
}
RawNullablePointer { nndiscr, ref nullfields, .. } => {
if discr == nndiscr { 1 } else { nullfields.len() }
Expand All @@ -1079,11 +1085,11 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
bcx.ccx().sess().bug("element access in C-like enum")
}
Univariant(ref st, _dtor) => {
assert_eq!(discr, 0);
assert_eq!(discr, Disr(0));
struct_field_ptr(bcx, st, val, ix, false)
}
General(_, ref cases, _) => {
struct_field_ptr(bcx, &cases[discr as usize], val, ix + 1, true)
struct_field_ptr(bcx, &cases[discr.0 as usize], val, ix + 1, true)
}
RawNullablePointer { nndiscr, ref nullfields, .. } |
StructWrappedNullablePointer { nndiscr, ref nullfields, .. } if discr != nndiscr => {
Expand Down Expand Up @@ -1326,20 +1332,20 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
CEnum(ity, min, max) => {
assert_eq!(vals.len(), 0);
assert_discr_in_range(ity, min, max, discr);
C_integral(ll_inttype(ccx, ity), discr as u64, true)
C_integral(ll_inttype(ccx, ity), discr.0, true)
}
General(ity, ref cases, _) => {
let case = &cases[discr as usize];
let case = &cases[discr.0 as usize];
let (max_sz, _) = union_size_and_align(&cases[..]);
let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true);
let lldiscr = C_integral(ll_inttype(ccx, ity), discr.0 as u64, true);
let mut f = vec![lldiscr];
f.extend_from_slice(vals);
let mut contents = build_const_struct(ccx, case, &f[..]);
contents.extend_from_slice(&[padding(ccx, max_sz - case.size)]);
C_struct(ccx, &contents[..], false)
}
Univariant(ref st, _dro) => {
assert!(discr == 0);
assert_eq!(discr, Disr(0));
let contents = build_const_struct(ccx, st, vals);
C_struct(ccx, &contents[..], st.packed)
}
Expand Down Expand Up @@ -1444,17 +1450,17 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef) -> Disr {
match *r {
CEnum(ity, _, _) => {
match ity {
attr::SignedInt(..) => const_to_int(val) as Disr,
attr::UnsignedInt(..) => const_to_uint(val) as Disr
attr::SignedInt(..) => Disr(const_to_int(val) as u64),
attr::UnsignedInt(..) => Disr(const_to_uint(val)),
}
}
General(ity, _, _) => {
match ity {
attr::SignedInt(..) => const_to_int(const_get_elt(ccx, val, &[0])) as Disr,
attr::UnsignedInt(..) => const_to_uint(const_get_elt(ccx, val, &[0])) as Disr
attr::SignedInt(..) => Disr(const_to_int(const_get_elt(ccx, val, &[0])) as u64),
attr::UnsignedInt(..) => Disr(const_to_uint(const_get_elt(ccx, val, &[0])))
}
}
Univariant(..) => 0,
Univariant(..) => Disr(0),
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
ccx.sess().bug("const discrim access of non c-like enum")
}
Expand Down
Loading