]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #31545 - dotdash:no_noalias, r=alexcrichton
authorbors <bors@rust-lang.org>
Thu, 11 Feb 2016 22:22:54 +0000 (22:22 +0000)
committerbors <bors@rust-lang.org>
Thu, 11 Feb 2016 22:22:54 +0000 (22:22 +0000)
LLVM's memory dependence analysis doesn't properly account for calls
that could unwind and thus effectively act as a branching point. This
can lead to stores that are only visible when the call unwinds being
removed, possibly leading to calls to drop() functions with b0rked
memory contents.

As there is no fix for this in LLVM yet and we want to keep
compatibility to current LLVM versions anyways, we have to workaround
this bug by omitting the noalias attribute on &mut function arguments.
Benchmarks suggest that the performance loss by this change is very
small.

Thanks to @RalfJung for pushing me towards not removing too many
noalias annotations and @alexcrichton for helping out with the test for
this bug.

Fixes #29485

1  2 
src/librustc_trans/trans/attributes.rs

index be0c62f511fb86451c97743c84745ee73ce3a3d8,95c3941354f22b2eab3bfb8af2d4ecaf85166218..8f9648b333b8240e68defaca03c86d7844e4383a
@@@ -14,7 -14,7 +14,7 @@@ use llvm::{self, ValueRef, AttrHelper}
  use middle::ty;
  use middle::infer;
  use session::config::NoDebugInfo;
 -use syntax::abi;
 +use syntax::abi::Abi;
  pub use syntax::attr::InlineAttr;
  use syntax::ast;
  use rustc_front::hir;
@@@ -136,7 -136,7 +136,7 @@@ pub fn from_fn_type<'a, 'tcx>(ccx: &Cra
              let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
              function_type = infcx.closure_type(closure_did, substs);
              let self_type = base::self_type_for_closure(ccx, closure_did, fn_type);
 -            (&function_type.sig, abi::RustCall, Some(self_type))
 +            (&function_type.sig, Abi::RustCall, Some(self_type))
          }
          _ => ccx.sess().bug("expected closure or function.")
      };
      // unpack the input ty's
      let input_tys = match fn_type.sty {
          ty::TyClosure(..) => {
 -            assert!(abi == abi::RustCall);
 +            assert!(abi == Abi::RustCall);
  
              match fn_sig.inputs[0].sty {
                  ty::TyTuple(ref inputs) => {
                  _ => ccx.sess().bug("expected tuple'd inputs")
              }
          },
 -        ty::TyBareFn(..) if abi == abi::RustCall => {
 +        ty::TyBareFn(..) if abi == Abi::RustCall => {
              let mut inputs = vec![fn_sig.inputs[0]];
  
              match fn_sig.inputs[1].sty {
                  // on memory dependencies rather than pointer equality
                  let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
  
-                 if mt.mutbl == hir::MutMutable || !interior_unsafe {
+                 if mt.mutbl != hir::MutMutable && !interior_unsafe {
                      attrs.arg(idx, llvm::Attribute::NoAlias);
                  }