Skip to content

Commit

Permalink
Merge pull request #36620 from pnkfelix/beta-next
Browse files Browse the repository at this point in the history
Beta backports
  • Loading branch information
nikomatsakis authored Sep 21, 2016
2 parents f1376ce + f0d4add commit 7504d2a
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 31 deletions.
25 changes: 22 additions & 3 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
use consts;
use debuginfo::DebugLoc;
use Disr;
use expr;
use machine::{llalign_of_min, llbitsize_of_real};
use meth;
use type_of;
Expand Down Expand Up @@ -242,10 +243,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let lvalue = self.trans_lvalue(&bcx, location);
let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
let drop_ty = glue::get_drop_glue_type(bcx.tcx(), ty);
let llvalue = if drop_ty != ty {
bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
let is_sized = common::type_is_sized(bcx.tcx(), ty);
let llvalue = if is_sized {
if drop_ty != ty {
bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
} else {
lvalue.llval
}
} else {
lvalue.llval
// FIXME(#36457) Currently drop glue takes sized
// values as a `*(data, meta)`, but elsewhere in
// MIR we pass `(data, meta)` as two separate
// arguments. It would be better to fix drop glue,
// but I am shooting for a quick fix to #35546
// here that can be cleanly backported to beta, so
// I want to avoid touching all of trans.
bcx.with_block(|bcx| {
let scratch = base::alloc_ty(bcx, ty, "drop");
base::call_lifetime_start(bcx, scratch);
build::Store(bcx, lvalue.llval, expr::get_dataptr(bcx, scratch));
build::Store(bcx, lvalue.llextra, expr::get_meta(bcx, scratch));
scratch
})
};
if let Some(unwind) = unwind {
bcx.invoke(drop_fn,
Expand Down
86 changes: 58 additions & 28 deletions src/librustc_trans/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use value::Value;

use syntax_pos::{Span, DUMMY_SP};

use std::fmt;
use std::ptr;

use super::operand::{OperandRef, OperandValue};
Expand Down Expand Up @@ -147,6 +148,12 @@ impl<'tcx> Const<'tcx> {
}
}

impl<'tcx> fmt::Debug for Const<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Const({:?}: {:?})", Value(self.llval), self.ty)
}
}

#[derive(Copy, Clone)]
enum Base {
/// A constant value without an unique address.
Expand Down Expand Up @@ -466,7 +473,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {

fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
-> Result<Const<'tcx>, ConstEvalFailure> {
match *operand {
debug!("const_operand({:?} @ {:?})", operand, span);
let result = match *operand {
mir::Operand::Consume(ref lvalue) => {
Ok(self.const_lvalue(lvalue, span)?.to_const(span))
}
Expand Down Expand Up @@ -495,29 +503,41 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
}
}
}
}
};
debug!("const_operand({:?} @ {:?}) = {:?}", operand, span,
result.as_ref().ok());
result
}

fn const_array(&self, array_ty: Ty<'tcx>, fields: &[ValueRef])
-> Const<'tcx>
{
let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
bug!("bad array type {:?}", array_ty)
});
let llunitty = type_of::type_of(self.ccx, elem_ty);
// If the array contains enums, an LLVM array won't work.
let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
C_array(llunitty, fields)
} else {
C_struct(self.ccx, fields, false)
};
Const::new(val, array_ty)
}

fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
dest_ty: Ty<'tcx>, span: Span)
-> Result<Const<'tcx>, ConstEvalFailure> {
let tcx = self.ccx.tcx();
debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span);
let val = match *rvalue {
mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?,

mir::Rvalue::Repeat(ref elem, ref count) => {
let elem = self.const_operand(elem, span)?;
let size = count.value.as_u64(tcx.sess.target.uint_type);
let fields = vec![elem.llval; size as usize];

let llunitty = type_of::type_of(self.ccx, elem.ty);
// If the array contains enums, an LLVM array won't work.
let val = if val_ty(elem.llval) == llunitty {
C_array(llunitty, &fields)
} else {
C_struct(self.ccx, &fields, false)
};
Const::new(val, dest_ty)
self.const_array(dest_ty, &fields)
}

mir::Rvalue::Aggregate(ref kind, ref operands) => {
Expand All @@ -541,22 +561,26 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
self.monomorphize(&substs));
}

let val = if let mir::AggregateKind::Adt(adt_def, index, _) = *kind {
let repr = adt::represent_type(self.ccx, dest_ty);
let disr = Disr::from(adt_def.variants[index].disr_val);
adt::trans_const(self.ccx, &repr, disr, &fields)
} else if let ty::TyArray(elem_ty, _) = dest_ty.sty {
let llunitty = type_of::type_of(self.ccx, elem_ty);
// If the array contains enums, an LLVM array won't work.
if fields.iter().all(|&f| val_ty(f) == llunitty) {
C_array(llunitty, &fields)
} else {
C_struct(self.ccx, &fields, false)
match *kind {
mir::AggregateKind::Vec => {
self.const_array(dest_ty, &fields)
}
} else {
C_struct(self.ccx, &fields, false)
};
Const::new(val, dest_ty)
mir::AggregateKind::Adt(..) |
mir::AggregateKind::Closure(..) |
mir::AggregateKind::Tuple => {
let disr = match *kind {
mir::AggregateKind::Adt(adt_def, index, _) => {
Disr::from(adt_def.variants[index].disr_val)
}
_ => Disr(0)
};
let repr = adt::represent_type(self.ccx, dest_ty);
Const::new(
adt::trans_const(self.ccx, &repr, disr, &fields),
dest_ty
)
}
}
}

mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
Expand Down Expand Up @@ -780,6 +804,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
_ => span_bug!(span, "{:?} in constant", rvalue)
};

debug!("const_rvalue({:?}: {:?} @ {:?}) = {:?}", rvalue, dest_ty, span, val);

Ok(val)
}

Expand Down Expand Up @@ -881,6 +907,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
constant: &mir::Constant<'tcx>)
-> Const<'tcx>
{
debug!("trans_constant({:?})", constant);
let ty = bcx.monomorphize(&constant.ty);
let result = match constant.literal.clone() {
mir::Literal::Item { def_id, substs } => {
Expand All @@ -905,7 +932,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
}
};

match result {
let result = match result {
Ok(v) => v,
Err(ConstEvalFailure::Compiletime(_)) => {
// We've errored, so we don't have to produce working code.
Expand All @@ -917,7 +944,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
"MIR constant {:?} results in runtime panic: {:?}",
constant, err.description())
}
}
};

debug!("trans_constant({:?}) = {:?}", constant, result);
result
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/test/run-pass/issue-35546.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Regression test for #35546. Check that we are able to codegen
// this. Before we had problems because of the drop glue signature
// around dropping a trait object (specifically, when dropping the
// `value` field of `Node<Send>`).

struct Node<T: ?Sized + Send> {
next: Option<Box<Node<Send>>>,
value: T,
}

fn clear(head: &mut Option<Box<Node<Send>>>) {
match head.take() {
Some(node) => *head = node.next,
None => (),
}
}

fn main() {}
25 changes: 25 additions & 0 deletions src/test/run-pass/issue-36401.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[derive(Debug)]
pub enum Event {
Key(u8),
Resize,
Unknown(u16),
}

static XTERM_SINGLE_BYTES : [(u8, Event); 1] = [(1, Event::Resize)];

fn main() {
match XTERM_SINGLE_BYTES[0] {
(1, Event::Resize) => {},
ref bad => panic!("unexpected {:?}", bad)
}
}

0 comments on commit 7504d2a

Please sign in to comment.