add NullOp::SizeOf and BinOp::Offset
This commit is contained in:
parent
3bcd6fa571
commit
7b295eea42
|
@ -315,7 +315,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for mir::Rvalue<'tcx>
|
|||
mir::Rvalue::Discriminant(ref lvalue) => {
|
||||
lvalue.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::Rvalue::Box(ty) => {
|
||||
mir::Rvalue::NullaryOp(op, ty) => {
|
||||
op.hash_stable(hcx, hasher);
|
||||
ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::Rvalue::Aggregate(ref kind, ref operands) => {
|
||||
|
@ -374,7 +375,8 @@ impl_stable_hash_for!(enum mir::BinOp {
|
|||
Le,
|
||||
Ne,
|
||||
Ge,
|
||||
Gt
|
||||
Gt,
|
||||
Offset
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum mir::UnOp {
|
||||
|
@ -382,6 +384,10 @@ impl_stable_hash_for!(enum mir::UnOp {
|
|||
Neg
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum mir::NullOp {
|
||||
Box,
|
||||
SizeOf
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal });
|
||||
|
||||
|
|
|
@ -1046,6 +1046,7 @@ pub enum Rvalue<'tcx> {
|
|||
BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
|
||||
CheckedBinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
|
||||
|
||||
NullaryOp(NullOp, Ty<'tcx>),
|
||||
UnaryOp(UnOp, Operand<'tcx>),
|
||||
|
||||
/// Read the discriminant of an ADT.
|
||||
|
@ -1054,9 +1055,6 @@ pub enum Rvalue<'tcx> {
|
|||
/// be defined to return, say, a 0) if ADT is not an enum.
|
||||
Discriminant(Lvalue<'tcx>),
|
||||
|
||||
/// Creates an *uninitialized* Box
|
||||
Box(Ty<'tcx>),
|
||||
|
||||
/// Create an aggregate value, like a tuple or struct. This is
|
||||
/// only needed because we want to distinguish `dest = Foo { x:
|
||||
/// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
|
||||
|
@ -1132,6 +1130,8 @@ pub enum BinOp {
|
|||
Ge,
|
||||
/// The `>` operator (greater than)
|
||||
Gt,
|
||||
/// The `ptr.offset` operator
|
||||
Offset,
|
||||
}
|
||||
|
||||
impl BinOp {
|
||||
|
@ -1144,6 +1144,14 @@ impl BinOp {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum NullOp {
|
||||
/// Return the size of a value of that type
|
||||
SizeOf,
|
||||
/// Create a new uninitialized box for a value of that type
|
||||
Box,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum UnOp {
|
||||
/// The `!` operator for logical inversion
|
||||
|
@ -1167,7 +1175,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||
}
|
||||
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
|
||||
Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
|
||||
Box(ref t) => write!(fmt, "Box({:?})", t),
|
||||
NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
|
||||
Ref(_, borrow_kind, ref lv) => {
|
||||
let kind_str = match borrow_kind {
|
||||
BorrowKind::Shared => "",
|
||||
|
@ -1601,7 +1609,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|||
CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
|
||||
UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
|
||||
Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
|
||||
Box(ty) => Box(ty.fold_with(folder)),
|
||||
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)),
|
||||
Aggregate(ref kind, ref fields) => {
|
||||
let kind = box match **kind {
|
||||
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
|
||||
|
@ -1629,7 +1637,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|||
rhs.visit_with(visitor) || lhs.visit_with(visitor),
|
||||
UnaryOp(_, ref val) => val.visit_with(visitor),
|
||||
Discriminant(ref lval) => lval.visit_with(visitor),
|
||||
Box(ty) => ty.visit_with(visitor),
|
||||
NullaryOp(_, ty) => ty.visit_with(visitor),
|
||||
Aggregate(ref kind, ref fields) => {
|
||||
(match **kind {
|
||||
AggregateKind::Array(ty) => ty.visit_with(visitor),
|
||||
|
|
|
@ -166,7 +166,8 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
let ty = op.ty(tcx, lhs_ty, rhs_ty);
|
||||
tcx.intern_tup(&[ty, tcx.types.bool], false)
|
||||
}
|
||||
Rvalue::UnaryOp(_, ref operand) => {
|
||||
Rvalue::UnaryOp(UnOp::Not, ref operand) |
|
||||
Rvalue::UnaryOp(UnOp::Neg, ref operand) => {
|
||||
operand.ty(mir, tcx)
|
||||
}
|
||||
Rvalue::Discriminant(ref lval) => {
|
||||
|
@ -179,9 +180,8 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
bug!("Rvalue::Discriminant on Lvalue of type {:?}", ty);
|
||||
}
|
||||
}
|
||||
Rvalue::Box(t) => {
|
||||
tcx.mk_box(t)
|
||||
}
|
||||
Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
|
||||
Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize,
|
||||
Rvalue::Aggregate(ref ak, ref ops) => {
|
||||
match **ak {
|
||||
AggregateKind::Array(ty) => {
|
||||
|
@ -227,7 +227,7 @@ impl<'tcx> BinOp {
|
|||
assert_eq!(lhs_ty, rhs_ty);
|
||||
lhs_ty
|
||||
}
|
||||
&BinOp::Shl | &BinOp::Shr => {
|
||||
&BinOp::Shl | &BinOp::Shr | &BinOp::Offset => {
|
||||
lhs_ty // lhs_ty can be != rhs_ty
|
||||
}
|
||||
&BinOp::Eq | &BinOp::Lt | &BinOp::Le |
|
||||
|
@ -270,7 +270,8 @@ impl BinOp {
|
|||
BinOp::Lt => hir::BinOp_::BiLt,
|
||||
BinOp::Gt => hir::BinOp_::BiGt,
|
||||
BinOp::Le => hir::BinOp_::BiLe,
|
||||
BinOp::Ge => hir::BinOp_::BiGe
|
||||
BinOp::Ge => hir::BinOp_::BiGe,
|
||||
BinOp::Offset => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -509,7 +509,7 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
|
||||
}
|
||||
|
||||
Rvalue::Box(ref $($mutability)* ty) => {
|
||||
Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
|
||||
|
|
|
@ -438,7 +438,8 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
|
|||
Rvalue::Ref(..) |
|
||||
Rvalue::Discriminant(..) |
|
||||
Rvalue::Len(..) |
|
||||
Rvalue::Box(..) => {
|
||||
Rvalue::NullaryOp(NullOp::SizeOf, _) |
|
||||
Rvalue::NullaryOp(NullOp::Box, _) => {
|
||||
// This returns an rvalue with uninitialized contents. We can't
|
||||
// move out of it here because it is an rvalue - assignments always
|
||||
// completely initialize their lvalue.
|
||||
|
|
|
@ -97,7 +97,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let value = this.hir.mirror(value);
|
||||
let result = this.temp(expr.ty, expr_span);
|
||||
// to start, malloc some memory of suitable type (thus far, uninitialized):
|
||||
this.cfg.push_assign(block, source_info, &result, Rvalue::Box(value.ty));
|
||||
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
|
||||
this.cfg.push_assign(block, source_info, &result, box_);
|
||||
this.in_scope(value_extents, block, |this| {
|
||||
// schedule a shallow free of that memory, lest we unwind:
|
||||
this.schedule_box_free(expr_span, value_extents, &result, value.ty);
|
||||
|
|
|
@ -53,7 +53,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
|||
Rvalue::CheckedBinaryOp(..) |
|
||||
Rvalue::UnaryOp(..) |
|
||||
Rvalue::Discriminant(..) |
|
||||
Rvalue::Box(..) |
|
||||
Rvalue::NullaryOp(..) |
|
||||
Rvalue::Aggregate(..) => {
|
||||
// These variants don't contain regions.
|
||||
}
|
||||
|
|
|
@ -595,7 +595,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||
match *rvalue {
|
||||
Rvalue::Use(_) |
|
||||
Rvalue::Repeat(..) |
|
||||
Rvalue::UnaryOp(..) |
|
||||
Rvalue::UnaryOp(UnOp::Neg, _) |
|
||||
Rvalue::UnaryOp(UnOp::Not, _) |
|
||||
Rvalue::NullaryOp(NullOp::SizeOf, _) |
|
||||
Rvalue::CheckedBinaryOp(..) |
|
||||
Rvalue::Cast(CastKind::ReifyFnPointer, ..) |
|
||||
Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
|
||||
|
@ -703,7 +705,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||
if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
|
||||
assert!(op == BinOp::Eq || op == BinOp::Ne ||
|
||||
op == BinOp::Le || op == BinOp::Lt ||
|
||||
op == BinOp::Ge || op == BinOp::Gt);
|
||||
op == BinOp::Ge || op == BinOp::Gt ||
|
||||
op == BinOp::Offset);
|
||||
|
||||
self.add(Qualif::NOT_CONST);
|
||||
if self.mode != Mode::Fn {
|
||||
|
@ -719,7 +722,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Rvalue::Box(_) => {
|
||||
Rvalue::NullaryOp(NullOp::Box, _) => {
|
||||
self.add(Qualif::NOT_CONST);
|
||||
if self.mode != Mode::Fn {
|
||||
struct_span_err!(self.tcx.sess, self.span, E0010,
|
||||
|
|
|
@ -186,7 +186,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
|
|||
Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp",
|
||||
Rvalue::UnaryOp(..) => "Rvalue::UnaryOp",
|
||||
Rvalue::Discriminant(..) => "Rvalue::Discriminant",
|
||||
Rvalue::Box(..) => "Rvalue::Box",
|
||||
Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
|
||||
Rvalue::Aggregate(ref kind, ref _operands) => {
|
||||
// AggregateKind is not distinguished by visit API, so
|
||||
// record it. (`super_rvalue` handles `_operands`.)
|
||||
|
|
|
@ -502,7 +502,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
mir::Rvalue::Box(..) => {
|
||||
mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => {
|
||||
let tcx = self.scx.tcx();
|
||||
let exchange_malloc_fn_def_id = tcx
|
||||
.lang_items
|
||||
|
|
|
@ -76,6 +76,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
|
|||
let align = C_uint(bcx.ccx, align);
|
||||
return (size, align);
|
||||
}
|
||||
assert!(!info.is_null());
|
||||
match t.sty {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let ccx = bcx.ccx;
|
||||
|
|
|
@ -796,6 +796,12 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
|||
Const::new(llval, operand.ty)
|
||||
}
|
||||
|
||||
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
|
||||
assert!(self.ccx.shared().type_is_sized(ty));
|
||||
let llval = C_uint(self.ccx, self.ccx.size_of(ty));
|
||||
Const::new(llval, tcx.types.usize)
|
||||
}
|
||||
|
||||
_ => span_bug!(span, "{:?} in constant", rvalue)
|
||||
};
|
||||
|
||||
|
@ -870,6 +876,7 @@ pub fn const_scalar_binop(op: mir::BinOp,
|
|||
llvm::LLVMConstICmp(cmp, lhs, rhs)
|
||||
}
|
||||
}
|
||||
mir::BinOp::Offset => unreachable!("BinOp::Offset in const-eval!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
|
|||
|
||||
pub fn deref(self) -> LvalueRef<'tcx> {
|
||||
let projected_ty = self.ty.builtin_deref(true, ty::NoPreference)
|
||||
.unwrap().ty;
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty;
|
||||
let (llptr, llextra) = match self.val {
|
||||
OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
|
||||
OperandValue::Pair(llptr, llextra) => (llptr, llextra),
|
||||
|
|
|
@ -432,7 +432,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
mir::Rvalue::Box(content_ty) => {
|
||||
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
|
||||
assert!(bcx.ccx.shared().type_is_sized(ty));
|
||||
let val = C_uint(bcx.ccx, bcx.ccx.size_of(ty));
|
||||
let tcx = bcx.tcx();
|
||||
(bcx, OperandRef {
|
||||
val: OperandValue::Immediate(val),
|
||||
ty: tcx.types.usize,
|
||||
})
|
||||
}
|
||||
|
||||
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
|
||||
let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
|
||||
let llty = type_of::type_of(bcx.ccx, content_ty);
|
||||
let llsize = machine::llsize_of(bcx.ccx, llty);
|
||||
|
@ -515,6 +525,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
mir::BinOp::BitOr => bcx.or(lhs, rhs),
|
||||
mir::BinOp::BitAnd => bcx.and(lhs, rhs),
|
||||
mir::BinOp::BitXor => bcx.xor(lhs, rhs),
|
||||
mir::BinOp::Offset => bcx.inbounds_gep(lhs, &[rhs]),
|
||||
mir::BinOp::Shl => common::build_unchecked_lshift(bcx, lhs, rhs),
|
||||
mir::BinOp::Shr => common::build_unchecked_rshift(bcx, input_ty, lhs, rhs),
|
||||
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
|
||||
|
@ -660,7 +671,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
mir::Rvalue::CheckedBinaryOp(..) |
|
||||
mir::Rvalue::UnaryOp(..) |
|
||||
mir::Rvalue::Discriminant(..) |
|
||||
mir::Rvalue::Box(..) |
|
||||
mir::Rvalue::NullaryOp(..) |
|
||||
mir::Rvalue::Use(..) => // (*)
|
||||
true,
|
||||
mir::Rvalue::Repeat(..) |
|
||||
|
|
|
@ -781,11 +781,15 @@ extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
|
|||
extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
|
||||
RustStringRef Str) {
|
||||
RawRustStringOstream OS(Str);
|
||||
OS << "(";
|
||||
unwrap<llvm::Value>(V)->getType()->print(OS);
|
||||
OS << ":";
|
||||
unwrap<llvm::Value>(V)->print(OS);
|
||||
OS << ")";
|
||||
if (!V) {
|
||||
OS << "(null)";
|
||||
} else {
|
||||
OS << "(";
|
||||
unwrap<llvm::Value>(V)->getType()->print(OS);
|
||||
OS << ":";
|
||||
unwrap<llvm::Value>(V)->print(OS);
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef DstRef, char *BC,
|
||||
|
|
Loading…
Reference in New Issue