Skip to content

Commit

Permalink
Fix some type-related bugs
Browse files Browse the repository at this point in the history
Some types weren't being properly monomorphised, and didn't have their
regions properly erased. This is now fixed.

Also fixes an issue where a temp was initialized in two separate
branches, but wasn't given an alloca.
  • Loading branch information
Aatch committed Apr 8, 2016
1 parent 73790f0 commit cb1bec9
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
4 changes: 3 additions & 1 deletion src/librustc_trans/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ impl<'tcx> Visitor<'tcx> for TempAnalyzer {
match *lvalue {
mir::Lvalue::Temp(index) => {
match context {
LvalueContext::Call |
LvalueContext::Call => {
self.mark_assigned(index as usize);
}
LvalueContext::Consume => {
}
LvalueContext::Store |
Expand Down
47 changes: 31 additions & 16 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use adt;
use base;
use build;
use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
use common::{self, Block, BlockAndBuilder, C_undef};
use common::{self, type_is_fat_ptr, Block, BlockAndBuilder, C_undef};
use debuginfo::DebugLoc;
use Disr;
use machine::{llalign_of_min, llbitsize_of_real};
Expand Down Expand Up @@ -169,6 +169,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
_ => bug!("{} is not callable", callee.ty)
};

let sig = bcx.tcx().erase_late_bound_regions(sig);

// Handle intrinsics old trans wants Expr's for, ourselves.
let intrinsic = match (&callee.ty.sty, &callee.data) {
(&ty::TyFnDef(def_id, _, _), &Intrinsic) => {
Expand Down Expand Up @@ -200,7 +202,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
return;
}

let extra_args = &args[sig.0.inputs.len()..];
let extra_args = &args[sig.inputs.len()..];
let extra_args = extra_args.iter().map(|op_arg| {
self.mir.operand_ty(bcx.tcx(), op_arg)
}).collect::<Vec<_>>();
Expand Down Expand Up @@ -263,30 +265,30 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
};

bcx.with_block(|bcx| {
let res = trans_intrinsic_call(bcx, callee.ty, &fn_ty,
trans_intrinsic_call(bcx, callee.ty, &fn_ty,
ArgVals(llargs), dest,
DebugLoc::None);
let bcx = res.bcx.build();
if let Some((_, target)) = *destination {
for op in args {
self.set_operand_dropped(&bcx, op);
}
funclet_br(bcx, self.llblock(target));
} else {
// trans_intrinsic_call already used Unreachable.
// bcx.unreachable();
}
});

if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
// Make a fake operand for store_return
let op = OperandRef {
val: OperandValue::Ref(dst),
ty: sig.0.output.unwrap()
ty: sig.output.unwrap()
};
self.store_return(&bcx, ret_dest, fn_ty.ret, op);
}

if let Some((_, target)) = *destination {
for op in args {
self.set_operand_dropped(&bcx, op);
}
funclet_br(bcx, self.llblock(target));
} else {
// trans_intrinsic_call already used Unreachable.
// bcx.unreachable();
}

return;
}
Fn(f) => f,
Expand Down Expand Up @@ -318,7 +320,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
ret_bcx.at_start(|ret_bcx| {
let op = OperandRef {
val: OperandValue::Immediate(invokeret),
ty: sig.0.output.unwrap()
ty: sig.output.unwrap()
};
self.store_return(&ret_bcx, ret_dest, fn_ty.ret, op);
for op in args {
Expand All @@ -332,7 +334,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
if let Some((_, target)) = *destination {
let op = OperandRef {
val: OperandValue::Immediate(llret),
ty: sig.0.output.unwrap()
ty: sig.output.unwrap()
};
self.store_return(&bcx, ret_dest, fn_ty.ret, op);
for op in args {
Expand Down Expand Up @@ -554,6 +556,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let dest = match *dest {
mir::Lvalue::Temp(idx) => {
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), dest);
let lvalue_ty = bcx.monomorphize(&lvalue_ty);
let ret_ty = lvalue_ty.to_ty(bcx.tcx());
match self.temps[idx as usize] {
TempRef::Lvalue(dest) => dest,
Expand Down Expand Up @@ -633,6 +636,18 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
self.temps[idx as usize] = TempRef::Operand(Some(op));
}
DirectOperand(idx) => {
let op = if type_is_fat_ptr(bcx.tcx(), op.ty) {
let llval = op.immediate();
let ptr = bcx.extract_value(llval, 0);
let meta = bcx.extract_value(llval, 1);

OperandRef {
val: OperandValue::FatPtr(ptr, meta),
ty: op.ty
}
} else {
op
};
self.temps[idx as usize] = TempRef::Operand(Some(op));
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/mir/lvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
TempRef::Lvalue(lvalue) => f(self, lvalue),
TempRef::Operand(None) => {
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), lvalue);
let lvalue_ty = bcx.monomorphize(&lvalue_ty);
let lvalue = LvalueRef::alloca(bcx,
lvalue_ty.to_ty(bcx.tcx()),
"lvalue_temp");
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->

debug!("type_of {:?}", t);

assert!(!t.has_escaping_regions());
assert!(!t.has_escaping_regions(), "{:?} has escaping regions", t);

// Replace any typedef'd types with their equivalent non-typedef
// type. This ensures that all LLVM nominal types that contain
Expand Down

0 comments on commit cb1bec9

Please sign in to comment.