From 4808561c45df77b6a7f8721f22b2f1e324cbeb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sun, 15 Feb 2015 23:23:19 +0100 Subject: [PATCH] Fix misoptimizations when matching against strings/slices When matching against strings/slices, we call the comparison function for strings, which takes two string slices by value. The slices are passed in memory, and currently we just pass in a pointer to the original slice. That can cause misoptimizations because we emit a call to llvm.lifetime.end for all by-value arguments at the end of a function, which in this case marks the original slice as dead. So we need to properly create copies of the slices to pass them to the comparison function. Fixes #22008 --- src/librustc_trans/trans/_match.rs | 14 +++++++++++++- src/test/run-pass/issue22008.rs | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue22008.rs diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 0f014800480e9..13b37141f40a7 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -828,7 +828,19 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, &format!("comparison of `{}`", cx.ty_to_string(rhs_t))[], StrEqFnLangItem); - callee::trans_lang_call(cx, did, &[lhs, rhs], None, debug_loc) + let t = ty::mk_str_slice(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ast::MutImmutable); + // The comparison function gets the slices by value, so we have to make copies here. Even + // if the function doesn't write through the pointer, things like lifetime intrinsics + // require that we do this properly + let lhs_arg = alloc_ty(cx, t, "lhs"); + let rhs_arg = alloc_ty(cx, t, "rhs"); + memcpy_ty(cx, lhs_arg, lhs, t); + memcpy_ty(cx, rhs_arg, rhs, t); + let res = callee::trans_lang_call(cx, did, &[lhs_arg, rhs_arg], None, debug_loc); + call_lifetime_end(res.bcx, lhs_arg); + call_lifetime_end(res.bcx, rhs_arg); + + res } let _icx = push_ctxt("compare_values"); diff --git a/src/test/run-pass/issue22008.rs b/src/test/run-pass/issue22008.rs new file mode 100644 index 0000000000000..3e145122e5aeb --- /dev/null +++ b/src/test/run-pass/issue22008.rs @@ -0,0 +1,18 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + let command = "a"; + + match command { + "foo" => println!("foo"), + _ => println!("{}", command), + } +}