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.
This commit is contained in:
parent
7ce1f5194c
commit
ffcfdcfe4c
2 changed files with 31 additions and 49 deletions
|
@ -11,7 +11,7 @@
|
|||
use llvm::{self, ValueRef, BasicBlockRef};
|
||||
use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::ty::{self, layout};
|
||||
use rustc::ty::{self, layout, TypeFoldable};
|
||||
use rustc::mir;
|
||||
use abi::{Abi, FnType, ArgType};
|
||||
use adt;
|
||||
|
@ -435,10 +435,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
|
||||
if intrinsic == Some("transmute") {
|
||||
let &(ref dest, target) = destination.as_ref().unwrap();
|
||||
self.with_lvalue_ref(&bcx, dest, |this, dest| {
|
||||
this.trans_transmute(&bcx, &args[0], dest);
|
||||
});
|
||||
|
||||
self.trans_transmute(&bcx, &args[0], dest);
|
||||
funclet_br(self, bcx, target);
|
||||
return;
|
||||
}
|
||||
|
@ -877,7 +874,34 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn trans_transmute(&mut self, bcx: &Builder<'a, 'tcx>,
|
||||
src: &mir::Operand<'tcx>, dst: LvalueRef<'tcx>) {
|
||||
src: &mir::Operand<'tcx>,
|
||||
dst: &mir::Lvalue<'tcx>) {
|
||||
if let mir::Lvalue::Local(index) = *dst {
|
||||
match self.locals[index] {
|
||||
LocalRef::Lvalue(lvalue) => self.trans_transmute_into(bcx, src, &lvalue),
|
||||
LocalRef::Operand(None) => {
|
||||
let lvalue_ty = self.monomorphized_lvalue_ty(dst);
|
||||
assert!(!lvalue_ty.has_erasable_regions());
|
||||
let lvalue = LvalueRef::alloca(bcx, lvalue_ty, "transmute_temp");
|
||||
self.trans_transmute_into(bcx, src, &lvalue);
|
||||
let op = self.trans_load(bcx, lvalue.llval, lvalue.alignment, lvalue_ty);
|
||||
self.locals[index] = LocalRef::Operand(Some(op));
|
||||
}
|
||||
LocalRef::Operand(Some(_)) => {
|
||||
let ty = self.monomorphized_lvalue_ty(dst);
|
||||
assert!(common::type_is_zero_size(bcx.ccx, ty),
|
||||
"assigning to initialized SSAtemp");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let dst = self.trans_lvalue(bcx, dst);
|
||||
self.trans_transmute_into(bcx, src, &dst);
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_transmute_into(&mut self, bcx: &Builder<'a, 'tcx>,
|
||||
src: &mir::Operand<'tcx>,
|
||||
dst: &LvalueRef<'tcx>) {
|
||||
let mut val = self.trans_operand(bcx, src);
|
||||
if let ty::TyFnDef(def_id, substs, _) = val.ty.sty {
|
||||
let llouttype = type_of::type_of(bcx.ccx, dst.ty.to_ty(bcx.tcx()));
|
||||
|
|
|
@ -15,10 +15,9 @@ use rustc::mir::tcx::LvalueTy;
|
|||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use adt;
|
||||
use builder::Builder;
|
||||
use common::{self, CrateContext, C_uint, C_undef};
|
||||
use common::{self, CrateContext, C_uint};
|
||||
use consts;
|
||||
use machine;
|
||||
use type_of::type_of;
|
||||
use type_of;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
|
@ -416,47 +415,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
result
|
||||
}
|
||||
|
||||
// Perform an action using the given Lvalue.
|
||||
// If the Lvalue is an empty LocalRef::Operand, then a temporary stack slot
|
||||
// is created first, then used as an operand to update the Lvalue.
|
||||
//
|
||||
// FIXME: this is only called from transmute; please remove it.
|
||||
pub fn with_lvalue_ref<F, U>(&mut self, bcx: &Builder<'a, 'tcx>,
|
||||
lvalue: &mir::Lvalue<'tcx>, f: F) -> U
|
||||
where F: FnOnce(&mut Self, LvalueRef<'tcx>) -> U
|
||||
{
|
||||
if let mir::Lvalue::Local(index) = *lvalue {
|
||||
match self.locals[index] {
|
||||
LocalRef::Lvalue(lvalue) => f(self, lvalue),
|
||||
LocalRef::Operand(None) => {
|
||||
let lvalue_ty = self.monomorphized_lvalue_ty(lvalue);
|
||||
assert!(!lvalue_ty.has_erasable_regions());
|
||||
let lvalue = LvalueRef::alloca(bcx, lvalue_ty, "lvalue_temp");
|
||||
let ret = f(self, lvalue);
|
||||
let op = self.trans_load(bcx, lvalue.llval, lvalue.alignment, lvalue_ty);
|
||||
self.locals[index] = LocalRef::Operand(Some(op));
|
||||
ret
|
||||
}
|
||||
LocalRef::Operand(Some(_)) => {
|
||||
// See comments in LocalRef::new_operand as to why
|
||||
// we always have Some in a ZST LocalRef::Operand.
|
||||
let ty = self.monomorphized_lvalue_ty(lvalue);
|
||||
if common::type_is_zero_size(bcx.ccx, ty) {
|
||||
// Pass an undef pointer as no stores can actually occur.
|
||||
let llptr = C_undef(type_of(bcx.ccx, ty).ptr_to());
|
||||
f(self, LvalueRef::new_sized(llptr, LvalueTy::from_ty(ty),
|
||||
Alignment::AbiAligned))
|
||||
} else {
|
||||
bug!("Lvalue local already set");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let lvalue = self.trans_lvalue(bcx, lvalue);
|
||||
f(self, lvalue)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adjust the bitwidth of an index since LLVM is less forgiving
|
||||
/// than we are.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue