Skip to content

Commit cb3c4d0

Browse files
committed
rustc_trans: don't emit ZST allocas that are only assigned to.
1 parent 910c481 commit cb3c4d0

File tree

4 files changed

+49
-41
lines changed

4 files changed

+49
-41
lines changed

src/librustc_trans/mir/analyze.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc::mir::visit::{Visitor, LvalueContext};
1919
use rustc::mir::traversal;
2020
use common;
2121
use super::MirContext;
22-
use super::rvalue;
2322

2423
pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
2524
let mir = mircx.mir;
@@ -93,7 +92,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
9392

9493
if let mir::Lvalue::Local(index) = *lvalue {
9594
self.mark_assigned(index);
96-
if !rvalue::rvalue_creates_operand(rvalue) {
95+
if !self.cx.rvalue_creates_operand(rvalue) {
9796
self.mark_as_lvalue(index);
9897
}
9998
} else {

src/librustc_trans/mir/mod.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,16 @@
1111
use libc::c_uint;
1212
use llvm::{self, ValueRef, BasicBlockRef};
1313
use llvm::debuginfo::DIScope;
14-
use rustc::ty;
14+
use rustc::ty::{self, Ty, TypeFoldable};
1515
use rustc::ty::layout::{self, LayoutTyper};
1616
use rustc::mir::{self, Mir};
1717
use rustc::mir::tcx::LvalueTy;
1818
use rustc::ty::subst::Substs;
1919
use rustc::infer::TransNormalize;
20-
use rustc::ty::TypeFoldable;
2120
use session::config::FullDebugInfo;
2221
use base;
2322
use builder::Builder;
24-
use common::{self, CrateContext, C_null, Funclet};
23+
use common::{self, CrateContext, Funclet};
2524
use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
2625
use monomorphize::{self, Instance};
2726
use abi::FnType;
@@ -171,23 +170,12 @@ enum LocalRef<'tcx> {
171170

172171
impl<'tcx> LocalRef<'tcx> {
173172
fn new_operand<'a>(ccx: &CrateContext<'a, 'tcx>,
174-
ty: ty::Ty<'tcx>) -> LocalRef<'tcx> {
173+
ty: Ty<'tcx>) -> LocalRef<'tcx> {
175174
if common::type_is_zero_size(ccx, ty) {
176175
// Zero-size temporaries aren't always initialized, which
177176
// doesn't matter because they don't contain data, but
178177
// we need something in the operand.
179-
let llty = type_of::type_of(ccx, ty);
180-
let val = if common::type_is_imm_pair(ccx, ty) {
181-
let fields = llty.field_types();
182-
OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
183-
} else {
184-
OperandValue::Immediate(C_null(llty))
185-
};
186-
let op = OperandRef {
187-
val: val,
188-
ty: ty
189-
};
190-
LocalRef::Operand(Some(op))
178+
LocalRef::Operand(Some(OperandRef::new_zst(ccx, ty)))
191179
} else {
192180
LocalRef::Operand(None)
193181
}

src/librustc_trans/mir/operand.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc::mir::tcx::LvalueTy;
1616
use rustc_data_structures::indexed_vec::Idx;
1717

1818
use base;
19-
use common;
19+
use common::{self, CrateContext, C_null};
2020
use builder::Builder;
2121
use value::Value;
2222
use type_of;
@@ -79,6 +79,22 @@ impl<'tcx> fmt::Debug for OperandRef<'tcx> {
7979
}
8080

8181
impl<'a, 'tcx> OperandRef<'tcx> {
82+
pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
83+
ty: Ty<'tcx>) -> OperandRef<'tcx> {
84+
assert!(common::type_is_zero_size(ccx, ty));
85+
let llty = type_of::type_of(ccx, ty);
86+
let val = if common::type_is_imm_pair(ccx, ty) {
87+
let fields = llty.field_types();
88+
OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
89+
} else {
90+
OperandValue::Immediate(C_null(llty))
91+
};
92+
OperandRef {
93+
val: val,
94+
ty: ty
95+
}
96+
}
97+
8298
/// Asserts that this operand refers to a scalar and returns
8399
/// a reference to its value.
84100
pub fn immediate(self) -> ValueRef {

src/librustc_trans/mir/rvalue.rs

+27-22
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
158158
}
159159

160160
_ => {
161-
assert!(rvalue_creates_operand(rvalue));
161+
assert!(self.rvalue_creates_operand(rvalue));
162162
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
163163
self.store_operand(&bcx, dest.llval, dest.alignment.to_align(), temp);
164164
bcx
@@ -171,7 +171,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
171171
rvalue: &mir::Rvalue<'tcx>)
172172
-> (Builder<'a, 'tcx>, OperandRef<'tcx>)
173173
{
174-
assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
174+
assert!(self.rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
175175

176176
match *rvalue {
177177
mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
@@ -466,8 +466,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
466466
}
467467
mir::Rvalue::Repeat(..) |
468468
mir::Rvalue::Aggregate(..) => {
469-
bug!("cannot generate operand from rvalue {:?}", rvalue);
470-
469+
// According to `rvalue_creates_operand`, only ZST
470+
// aggregate rvalues are allowed to be operands.
471+
let ty = rvalue.ty(self.mir, self.ccx.tcx());
472+
(bcx, OperandRef::new_zst(self.ccx, self.monomorphize(&ty)))
471473
}
472474
}
473475
}
@@ -650,26 +652,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
650652

651653
OperandValue::Pair(val, of)
652654
}
653-
}
654655

655-
pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
656-
match *rvalue {
657-
mir::Rvalue::Ref(..) |
658-
mir::Rvalue::Len(..) |
659-
mir::Rvalue::Cast(..) | // (*)
660-
mir::Rvalue::BinaryOp(..) |
661-
mir::Rvalue::CheckedBinaryOp(..) |
662-
mir::Rvalue::UnaryOp(..) |
663-
mir::Rvalue::Discriminant(..) |
664-
mir::Rvalue::Box(..) |
665-
mir::Rvalue::Use(..) => // (*)
666-
true,
667-
mir::Rvalue::Repeat(..) |
668-
mir::Rvalue::Aggregate(..) =>
669-
false,
670-
}
656+
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
657+
match *rvalue {
658+
mir::Rvalue::Ref(..) |
659+
mir::Rvalue::Len(..) |
660+
mir::Rvalue::Cast(..) | // (*)
661+
mir::Rvalue::BinaryOp(..) |
662+
mir::Rvalue::CheckedBinaryOp(..) |
663+
mir::Rvalue::UnaryOp(..) |
664+
mir::Rvalue::Discriminant(..) |
665+
mir::Rvalue::Box(..) |
666+
mir::Rvalue::Use(..) => // (*)
667+
true,
668+
mir::Rvalue::Repeat(..) |
669+
mir::Rvalue::Aggregate(..) => {
670+
let ty = rvalue.ty(self.mir, self.ccx.tcx());
671+
let ty = self.monomorphize(&ty);
672+
common::type_is_zero_size(self.ccx, ty)
673+
}
674+
}
671675

672-
// (*) this is only true if the type is suitable
676+
// (*) this is only true if the type is suitable
677+
}
673678
}
674679

675680
#[derive(Copy, Clone)]

0 commit comments

Comments
 (0)