Permalink
Browse files

Merge pull request #37173 from brson/stable-next

[stable] Backports for 1.12.1
  • Loading branch information...
2 parents 3191fba + 2d49342 commit d4f39402a0c2c2b94ec0375cd7f7f6d7918113cd @brson brson committed on GitHub Oct 19, 2016
View
@@ -13,7 +13,7 @@
######################################################################
# The version number
-CFG_RELEASE_NUM=1.12.0
+CFG_RELEASE_NUM=1.12.1
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release
@@ -107,6 +107,11 @@ impl FlagComputation {
}
&ty::TyProjection(ref data) => {
+ // currently we can't normalize projections that
+ // include bound regions, so track those separately.
+ if !data.has_escaping_regions() {
+ self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
+ }
self.add_flags(TypeFlags::HAS_PROJECTION);
self.add_projection_ty(data);
}
@@ -105,7 +105,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
TypeFlags::HAS_FREE_REGIONS |
TypeFlags::HAS_TY_INFER |
TypeFlags::HAS_PARAMS |
- TypeFlags::HAS_PROJECTION |
+ TypeFlags::HAS_NORMALIZABLE_PROJECTION |
TypeFlags::HAS_TY_ERR |
TypeFlags::HAS_SELF)
}
@@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns the def-id of `def_id`'s parent in the def tree. If
/// this returns `None`, then `def_id` represents a crate root or
/// inlined root.
- fn parent_def_id(&self, def_id: DefId) -> Option<DefId> {
+ pub fn parent_def_id(&self, def_id: DefId) -> Option<DefId> {
let key = self.def_key(def_id);
key.parent.map(|index| DefId { krate: def_id.krate, index: index })
}
@@ -527,6 +527,10 @@ bitflags! {
// Only set for TyInfer other than Fresh.
const KEEP_IN_LOCAL_TCX = 1 << 11,
+ // Is there a projection that does not involve a bound region?
+ // Currently we can't normalize projections w/ bound regions.
+ const HAS_NORMALIZABLE_PROJECTION = 1 << 12,
+
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits,
@@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::LogicalOp { .. } |
ExprKind::Box { .. } |
ExprKind::Cast { .. } |
+ ExprKind::Use { .. } |
ExprKind::NeverToAny { .. } |
ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } |
@@ -115,6 +115,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
}
+ ExprKind::Use { source } => {
+ let source = unpack!(block = this.as_operand(block, source));
+ block.and(Rvalue::Use(source))
+ }
ExprKind::ReifyFnPointer { source } => {
let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty))
@@ -68,6 +68,7 @@ impl Category {
ExprKind::Binary { .. } |
ExprKind::Box { .. } |
ExprKind::Cast { .. } |
+ ExprKind::Use { .. } |
ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } |
@@ -249,6 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Binary { .. } |
ExprKind::Box { .. } |
ExprKind::Cast { .. } |
+ ExprKind::Use { .. } |
ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } |
@@ -602,8 +602,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op).
if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) {
- // Skip the actual cast itexpr, as it's now a no-op.
- return source.make_mirror(cx);
+ // Convert the lexpr to a vexpr.
+ ExprKind::Use { source: source.to_ref() }
} else {
ExprKind::Cast { source: source.to_ref() }
}
@@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> {
Cast {
source: ExprRef<'tcx>,
},
+ Use {
+ source: ExprRef<'tcx>,
+ }, // Use a lexpr to get a vexpr.
NeverToAny {
source: ExprRef<'tcx>,
},
@@ -320,7 +320,16 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
_ => bug!("compare_scalar_types: must be a comparison operator"),
}
}
- ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
+ ty::TyBool => {
+ // FIXME(#36856) -- using `from_immediate` forces these booleans into `i8`,
+ // which works around some LLVM bugs
+ ICmp(bcx,
+ bin_op_to_icmp_predicate(op, false),
+ from_immediate(bcx, lhs),
+ from_immediate(bcx, rhs),
+ debug_loc)
+ }
+ ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyUint(_) | ty::TyChar => {
ICmp(bcx,
bin_op_to_icmp_predicate(op, false),
lhs,
@@ -22,6 +22,7 @@ use value::Value;
use util::nodemap::FnvHashMap;
use libc::{c_uint, c_char};
+use std::borrow::Cow;
use std::ffi::CString;
use std::ptr;
use syntax_pos::Span;
@@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.collect::<Vec<String>>()
.join(", "));
- check_call("invoke", llfn, args);
-
+ let args = self.check_call("invoke", llfn, args);
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
unsafe {
@@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
assert!(!self.llbuilder.is_null());
self.count_insn("store");
+ let ptr = self.check_store(val, ptr);
unsafe {
llvm::LLVMBuildStore(self.llbuilder, val, ptr)
}
@@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
assert!(!self.llbuilder.is_null());
self.count_insn("store.volatile");
+ let ptr = self.check_store(val, ptr);
unsafe {
let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
llvm::LLVMSetVolatile(insn, llvm::True);
@@ -562,6 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
self.count_insn("store.atomic");
+ let ptr = self.check_store(val, ptr);
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
let align = llalign_of_pref(self.ccx, ty.element_type());
@@ -857,8 +860,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.collect::<Vec<String>>()
.join(", "));
- check_call("call", llfn, args);
-
+ let args = self.check_call("call", llfn, args);
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
unsafe {
@@ -1100,10 +1102,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
}
}
-}
-fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
- if cfg!(debug_assertions) {
+ /// Returns the ptr value that should be used for storing `val`.
+ fn check_store<'b>(&self,
+ val: ValueRef,
+ ptr: ValueRef) -> ValueRef {
+ let dest_ptr_ty = val_ty(ptr);
+ let stored_ty = val_ty(val);
+ let stored_ptr_ty = stored_ty.ptr_to();
+
+ assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
+
+ if dest_ptr_ty == stored_ptr_ty {
+ ptr
+ } else {
+ debug!("Type mismatch in store. \
+ Expected {:?}, got {:?}; inserting bitcast",
+ dest_ptr_ty, stored_ptr_ty);
+ self.bitcast(ptr, stored_ptr_ty)
+ }
+ }
+
+ /// Returns the args that should be used for a call to `llfn`.
+ fn check_call<'b>(&self,
+ typ: &str,
+ llfn: ValueRef,
+ args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
let mut fn_ty = val_ty(llfn);
// Strip off pointers
while fn_ty.kind() == llvm::TypeKind::Pointer {
@@ -1115,16 +1139,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
let param_tys = fn_ty.func_params();
- let iter = param_tys.into_iter()
- .zip(args.iter().map(|&v| val_ty(v)));
- for (i, (expected_ty, actual_ty)) in iter.enumerate() {
- if expected_ty != actual_ty {
- bug!("Type mismatch in function call of {:?}. \
- Expected {:?} for param {}, got {:?}",
- Value(llfn),
- expected_ty, i, actual_ty);
+ let all_args_match = param_tys.iter()
+ .zip(args.iter().map(|&v| val_ty(v)))
+ .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
+
+ if all_args_match {
+ return Cow::Borrowed(args);
+ }
+
+ let casted_args: Vec<_> = param_tys.into_iter()
+ .zip(args.iter())
+ .enumerate()
+ .map(|(i, (expected_ty, &actual_val))| {
+ let actual_ty = val_ty(actual_val);
+ if expected_ty != actual_ty {
+ debug!("Type mismatch in function call of {:?}. \
+ Expected {:?} for param {}, got {:?}; injecting bitcast",
+ Value(llfn),
+ expected_ty, i, actual_ty);
+ self.bitcast(actual_val, expected_ty)
+ } else {
+ actual_val
+ }
+ })
+ .collect();
- }
- }
+ return Cow::Owned(casted_args);
}
}
@@ -1042,7 +1042,9 @@ fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let concrete_substs = monomorphize::apply_param_substs(tcx,
param_substs,
&fn_substs);
- assert!(concrete_substs.is_normalized_for_trans());
+ assert!(concrete_substs.is_normalized_for_trans(),
+ "concrete_substs not normalized for trans: {:?}",
+ concrete_substs);
TransItem::Fn(Instance::new(def_id, concrete_substs))
}
@@ -22,7 +22,6 @@ use machine;
use type_of;
use syntax_pos::DUMMY_SP;
-use syntax::parse::token::keywords;
use std::ops::Deref;
use std::rc::Rc;
@@ -301,7 +300,6 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
_ => bug!("spread argument isn't a tuple?!")
};
- let lltuplety = type_of::type_of(bcx.ccx(), arg_ty);
let lltemp = bcx.with_block(|bcx| {
base::alloc_ty(bcx, arg_ty, &format!("arg{}", arg_index))
});
@@ -319,27 +317,20 @@ fn arg_local_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
} else {
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
}
-
- bcx.with_block(|bcx| arg_scope.map(|scope| {
- let byte_offset_of_var_in_tuple =
- machine::llelement_offset(bcx.ccx(), lltuplety, i);
-
- let ops = unsafe {
- [llvm::LLVMRustDIBuilderCreateOpDeref(),
- llvm::LLVMRustDIBuilderCreateOpPlus(),
- byte_offset_of_var_in_tuple as i64]
- };
-
- let variable_access = VariableAccess::IndirectVariable {
- alloca: lltemp,
- address_operations: &ops
- };
- declare_local(bcx, keywords::Invalid.name(),
- tupled_arg_ty, scope, variable_access,
- VariableKind::ArgumentVariable(arg_index + i + 1),
- bcx.fcx().span.unwrap_or(DUMMY_SP));
- }));
}
+
+ // Now that we have one alloca that contains the aggregate value,
+ // we can create one debuginfo entry for the argument.
+ bcx.with_block(|bcx| arg_scope.map(|scope| {
+ let variable_access = VariableAccess::DirectVariable {
+ alloca: lltemp
+ };
+ declare_local(bcx, arg_decl.debug_name,
+ arg_ty, scope, variable_access,
+ VariableKind::ArgumentVariable(arg_index + 1),
+ bcx.fcx().span.unwrap_or(DUMMY_SP));
+ }));
+
return LocalRef::Lvalue(LvalueRef::new_sized(lltemp, LvalueTy::from_ty(arg_ty)));
}
@@ -535,13 +535,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
report_unexpected_def();
return;
}
- Def::Variant(..) | Def::Struct(..) => {
+ Def::Variant(..) => {
let variant = tcx.expect_variant_def(def);
if variant.kind != VariantKind::Unit {
report_unexpected_def();
return;
}
}
+ Def::Struct(ctor_did) => {
+ let did = tcx.parent_def_id(ctor_did).expect("struct ctor has no parent");
+ let variant = tcx.lookup_adt_def(did).struct_variant();
+ if variant.kind != VariantKind::Unit {
+ report_unexpected_def();
+ return;
+ }
+ }
Def::Const(..) | Def::AssociatedConst(..) => {} // OK
_ => bug!("unexpected pattern definition {:?}", def)
}
@@ -592,9 +600,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
report_unexpected_def(false);
return;
}
- Def::Variant(..) | Def::Struct(..) => {
+ Def::Variant(..) => {
tcx.expect_variant_def(def)
}
+ Def::Struct(ctor_did) => {
+ let did = tcx.parent_def_id(ctor_did).expect("struct ctor has no parent");
+ tcx.lookup_adt_def(did).struct_variant()
+ }
_ => bug!("unexpected pattern definition {:?}", def)
};
if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
@@ -1,4 +1,4 @@
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2016-09-17
+2016-10-10
Oops, something went wrong.

0 comments on commit d4f3940

Please sign in to comment.