Skip to content

Commit ffcfdcf

Browse files
committed
Inline the function with_lvalue_ref into trans_transmute
The function was a footgun because it created `undef` references to ZSTs, which could cause trouble were they to leak to user code.
1 parent 7ce1f51 commit ffcfdcf

File tree

2 files changed

+31
-49
lines changed

2 files changed

+31
-49
lines changed

src/librustc_trans/mir/block.rs

+30-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use llvm::{self, ValueRef, BasicBlockRef};
1212
use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err};
1313
use rustc::middle::lang_items;
14-
use rustc::ty::{self, layout};
14+
use rustc::ty::{self, layout, TypeFoldable};
1515
use rustc::mir;
1616
use abi::{Abi, FnType, ArgType};
1717
use adt;
@@ -435,10 +435,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
435435

436436
if intrinsic == Some("transmute") {
437437
let &(ref dest, target) = destination.as_ref().unwrap();
438-
self.with_lvalue_ref(&bcx, dest, |this, dest| {
439-
this.trans_transmute(&bcx, &args[0], dest);
440-
});
441-
438+
self.trans_transmute(&bcx, &args[0], dest);
442439
funclet_br(self, bcx, target);
443440
return;
444441
}
@@ -877,7 +874,34 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
877874
}
878875

879876
fn trans_transmute(&mut self, bcx: &Builder<'a, 'tcx>,
880-
src: &mir::Operand<'tcx>, dst: LvalueRef<'tcx>) {
877+
src: &mir::Operand<'tcx>,
878+
dst: &mir::Lvalue<'tcx>) {
879+
if let mir::Lvalue::Local(index) = *dst {
880+
match self.locals[index] {
881+
LocalRef::Lvalue(lvalue) => self.trans_transmute_into(bcx, src, &lvalue),
882+
LocalRef::Operand(None) => {
883+
let lvalue_ty = self.monomorphized_lvalue_ty(dst);
884+
assert!(!lvalue_ty.has_erasable_regions());
885+
let lvalue = LvalueRef::alloca(bcx, lvalue_ty, "transmute_temp");
886+
self.trans_transmute_into(bcx, src, &lvalue);
887+
let op = self.trans_load(bcx, lvalue.llval, lvalue.alignment, lvalue_ty);
888+
self.locals[index] = LocalRef::Operand(Some(op));
889+
}
890+
LocalRef::Operand(Some(_)) => {
891+
let ty = self.monomorphized_lvalue_ty(dst);
892+
assert!(common::type_is_zero_size(bcx.ccx, ty),
893+
"assigning to initialized SSAtemp");
894+
}
895+
}
896+
} else {
897+
let dst = self.trans_lvalue(bcx, dst);
898+
self.trans_transmute_into(bcx, src, &dst);
899+
}
900+
}
901+
902+
fn trans_transmute_into(&mut self, bcx: &Builder<'a, 'tcx>,
903+
src: &mir::Operand<'tcx>,
904+
dst: &LvalueRef<'tcx>) {
881905
let mut val = self.trans_operand(bcx, src);
882906
if let ty::TyFnDef(def_id, substs, _) = val.ty.sty {
883907
let llouttype = type_of::type_of(bcx.ccx, dst.ty.to_ty(bcx.tcx()));

src/librustc_trans/mir/lvalue.rs

+1-43
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ use rustc::mir::tcx::LvalueTy;
1515
use rustc_data_structures::indexed_vec::Idx;
1616
use adt;
1717
use builder::Builder;
18-
use common::{self, CrateContext, C_uint, C_undef};
18+
use common::{self, CrateContext, C_uint};
1919
use consts;
2020
use machine;
21-
use type_of::type_of;
2221
use type_of;
2322
use type_::Type;
2423
use value::Value;
@@ -416,47 +415,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
416415
result
417416
}
418417

419-
// Perform an action using the given Lvalue.
420-
// If the Lvalue is an empty LocalRef::Operand, then a temporary stack slot
421-
// is created first, then used as an operand to update the Lvalue.
422-
//
423-
// FIXME: this is only called from transmute; please remove it.
424-
pub fn with_lvalue_ref<F, U>(&mut self, bcx: &Builder<'a, 'tcx>,
425-
lvalue: &mir::Lvalue<'tcx>, f: F) -> U
426-
where F: FnOnce(&mut Self, LvalueRef<'tcx>) -> U
427-
{
428-
if let mir::Lvalue::Local(index) = *lvalue {
429-
match self.locals[index] {
430-
LocalRef::Lvalue(lvalue) => f(self, lvalue),
431-
LocalRef::Operand(None) => {
432-
let lvalue_ty = self.monomorphized_lvalue_ty(lvalue);
433-
assert!(!lvalue_ty.has_erasable_regions());
434-
let lvalue = LvalueRef::alloca(bcx, lvalue_ty, "lvalue_temp");
435-
let ret = f(self, lvalue);
436-
let op = self.trans_load(bcx, lvalue.llval, lvalue.alignment, lvalue_ty);
437-
self.locals[index] = LocalRef::Operand(Some(op));
438-
ret
439-
}
440-
LocalRef::Operand(Some(_)) => {
441-
// See comments in LocalRef::new_operand as to why
442-
// we always have Some in a ZST LocalRef::Operand.
443-
let ty = self.monomorphized_lvalue_ty(lvalue);
444-
if common::type_is_zero_size(bcx.ccx, ty) {
445-
// Pass an undef pointer as no stores can actually occur.
446-
let llptr = C_undef(type_of(bcx.ccx, ty).ptr_to());
447-
f(self, LvalueRef::new_sized(llptr, LvalueTy::from_ty(ty),
448-
Alignment::AbiAligned))
449-
} else {
450-
bug!("Lvalue local already set");
451-
}
452-
}
453-
}
454-
} else {
455-
let lvalue = self.trans_lvalue(bcx, lvalue);
456-
f(self, lvalue)
457-
}
458-
}
459-
460418
/// Adjust the bitwidth of an index since LLVM is less forgiving
461419
/// than we are.
462420
///

0 commit comments

Comments
 (0)