提交 0b869724 编写于 作者: E Eduard-Mihai Burtescu

rustc_trans: be more relaxed with non-lvalue consumes, especially ZSTs.

上级 c4d9ada7
...@@ -136,19 +136,29 @@ fn visit_lvalue(&mut self, ...@@ -136,19 +136,29 @@ fn visit_lvalue(&mut self,
context: LvalueContext<'tcx>, context: LvalueContext<'tcx>,
location: Location) { location: Location) {
debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context); debug!("visit_lvalue(lvalue={:?}, context={:?})", lvalue, context);
let ccx = self.cx.ccx;
if let mir::Lvalue::Projection(ref proj) = *lvalue { if let mir::Lvalue::Projection(ref proj) = *lvalue {
// Allow uses of projections of immediate pair fields. // Allow uses of projections that are ZSTs or from immediate scalar fields.
if let LvalueContext::Consume = context { if let LvalueContext::Consume = context {
if let mir::Lvalue::Local(_) = proj.base { let base_ty = proj.base.ty(self.cx.mir, ccx.tcx());
if let mir::ProjectionElem::Field(..) = proj.elem { let base_ty = self.cx.monomorphize(&base_ty);
let ty = proj.base.ty(self.cx.mir, self.cx.ccx.tcx());
let ty = self.cx.monomorphize(&ty.to_ty(self.cx.ccx.tcx())); // ZSTs don't require any actual memory access.
let layout = self.cx.ccx.layout_of(ty); let elem_ty = base_ty.projection_ty(ccx.tcx(), &proj.elem).to_ty(ccx.tcx());
if layout.is_llvm_scalar_pair() { let elem_ty = self.cx.monomorphize(&elem_ty);
if ccx.layout_of(elem_ty).is_zst() {
return; return;
} }
if let mir::ProjectionElem::Field(..) = proj.elem {
let layout = ccx.layout_of(base_ty.to_ty(ccx.tcx()));
if layout.is_llvm_scalar_pair() {
// Recurse as a `Consume` instead of `Projection`,
// potentially stopping at non-operand projections,
// which would trigger `mark_as_lvalue` on locals.
self.visit_lvalue(&proj.base, LvalueContext::Consume, location);
return;
} }
} }
} }
......
...@@ -179,19 +179,19 @@ pub fn store(self, bcx: &Builder<'a, 'tcx>, dest: LvalueRef<'tcx>) { ...@@ -179,19 +179,19 @@ pub fn store(self, bcx: &Builder<'a, 'tcx>, dest: LvalueRef<'tcx>) {
} }
impl<'a, 'tcx> MirContext<'a, 'tcx> { impl<'a, 'tcx> MirContext<'a, 'tcx> {
pub fn trans_consume(&mut self, fn maybe_trans_consume_direct(&mut self,
bcx: &Builder<'a, 'tcx>, bcx: &Builder<'a, 'tcx>,
lvalue: &mir::Lvalue<'tcx>) lvalue: &mir::Lvalue<'tcx>)
-> OperandRef<'tcx> -> Option<OperandRef<'tcx>>
{ {
debug!("trans_consume(lvalue={:?})", lvalue); debug!("maybe_trans_consume_direct(lvalue={:?})", lvalue);
// watch out for locals that do not have an // watch out for locals that do not have an
// alloca; they are handled somewhat differently // alloca; they are handled somewhat differently
if let mir::Lvalue::Local(index) = *lvalue { if let mir::Lvalue::Local(index) = *lvalue {
match self.locals[index] { match self.locals[index] {
LocalRef::Operand(Some(o)) => { LocalRef::Operand(Some(o)) => {
return o; return Some(o);
} }
LocalRef::Operand(None) => { LocalRef::Operand(None) => {
bug!("use of {:?} before def", lvalue); bug!("use of {:?} before def", lvalue);
...@@ -204,21 +204,24 @@ pub fn trans_consume(&mut self, ...@@ -204,21 +204,24 @@ pub fn trans_consume(&mut self,
// Moves out of pair fields are trivial. // Moves out of pair fields are trivial.
if let &mir::Lvalue::Projection(ref proj) = lvalue { if let &mir::Lvalue::Projection(ref proj) = lvalue {
if let mir::Lvalue::Local(index) = proj.base { if let mir::ProjectionElem::Field(ref f, _) = proj.elem {
if let LocalRef::Operand(Some(o)) = self.locals[index] { if let Some(o) = self.maybe_trans_consume_direct(bcx, &proj.base) {
match (o.val, &proj.elem) { let layout = o.layout.field(bcx.ccx, f.index());
(OperandValue::Pair(a, b),
&mir::ProjectionElem::Field(ref f, ty)) => { // Handled in `trans_consume`.
let layout = bcx.ccx.layout_of(self.monomorphize(&ty)); assert!(!layout.is_zst());
match o.val {
OperandValue::Pair(a, b) => {
let llval = [a, b][f.index()]; let llval = [a, b][f.index()];
// HACK(eddyb) have to bitcast pointers // HACK(eddyb) have to bitcast pointers
// until LLVM removes pointee types. // until LLVM removes pointee types.
let llval = bcx.bitcast(llval, let llval = bcx.bitcast(llval,
layout.immediate_llvm_type(bcx.ccx)); layout.immediate_llvm_type(bcx.ccx));
return OperandRef { return Some(OperandRef {
val: OperandValue::Immediate(llval), val: OperandValue::Immediate(llval),
layout layout
}; });
} }
_ => {} _ => {}
} }
...@@ -226,6 +229,28 @@ pub fn trans_consume(&mut self, ...@@ -226,6 +229,28 @@ pub fn trans_consume(&mut self,
} }
} }
None
}
pub fn trans_consume(&mut self,
bcx: &Builder<'a, 'tcx>,
lvalue: &mir::Lvalue<'tcx>)
-> OperandRef<'tcx>
{
debug!("trans_consume(lvalue={:?})", lvalue);
let ty = self.monomorphized_lvalue_ty(lvalue);
let layout = bcx.ccx.layout_of(ty);
// ZSTs don't require any actual memory access.
if layout.is_zst() {
return OperandRef::new_zst(bcx.ccx, layout);
}
if let Some(o) = self.maybe_trans_consume_direct(bcx, lvalue) {
return o;
}
// for most lvalues, to consume them we just load them // for most lvalues, to consume them we just load them
// out from their home // out from their home
self.trans_lvalue(bcx, lvalue).load(bcx) self.trans_lvalue(bcx, lvalue).load(bcx)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册