From e9dfc94d263eeb7c4ce25a50619cc2e0cdc32b66 Mon Sep 17 00:00:00 2001 From: Guillaume Bonnet Date: Wed, 3 Feb 2016 16:08:18 +0100 Subject: [PATCH 1/8] compiler-rt: Handle -Werror=* arguments in CFLAGS --- mk/rt.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/rt.mk b/mk/rt.mk index 9dbbcbebb979d..14b8abb12b8fc 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -245,7 +245,7 @@ COMPRT_AR_$(1) := $$(AR_$(1)) # We chomp -Werror here because GCC warns about the type signature of # builtins not matching its own and the build fails. It's a bit hacky, # but what can we do, we're building libclang-rt using GCC ...... -COMPRT_CFLAGS_$(1) := $$(subst -Werror,,$$(CFG_GCCISH_CFLAGS_$(1))) -std=c99 +COMPRT_CFLAGS_$(1) := $$(filter-out -Werror -Werror=*,$$(CFG_GCCISH_CFLAGS_$(1))) -std=c99 # FreeBSD Clang's packaging is problematic; it doesn't copy unwind.h to # the standard include directory. This should really be in our changes to From 1fcdedb8fb1725c8f1dafa6badb890ca8181699f Mon Sep 17 00:00:00 2001 From: mitaa Date: Wed, 3 Feb 2016 16:07:40 +0100 Subject: [PATCH 2/8] Fix rendering of single-char-span A span spanning only a single character would render like `^~` instead of just `^`. --- src/libsyntax/errors/emitter.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index 94bbd1bd12816..4272f281edb44 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -410,7 +410,7 @@ impl EmitterWriter { chars.next(); } } - if (col - col_ptr) > 1 { + if (col - col_ptr) > 0 { // One extra squiggly is replaced by a "^" s.pop(); } @@ -962,7 +962,7 @@ mod test { _____\n\ ddd__eee_\n\ elided\n\ - _ff_gg"; + __f_gg"; let file = cm.new_filemap_and_lines("dummy.txt", inp); let span = |lo, hi, (off_lo, off_hi)| { @@ -976,7 +976,7 @@ mod test { let sp1 = span(0, 6, (0, 5)); let sp2 = span(8, 8, (0, 3)); let sp3 = span(8, 8, (5, 8)); - let sp4 = span(10, 10, (1, 3)); + let sp4 = span(10, 10, (2, 3)); let sp5 = span(10, 10, (4, 6)); let expect0 = "dummy.txt: 5 ccccc\n\ @@ -986,8 +986,8 @@ mod test { dummy.txt: 9 ddd__eee_\n\ \x20 ^~~ ^~~\n\ \x20 ...\n\ - dummy.txt:11 _ff_gg\n\ - \x20 ^~ ^~\n"; + dummy.txt:11 __f_gg\n\ + \x20 ^ ^~\n"; let expect = "dummy.txt: 1 aaaaa\n\ dummy.txt: 2 aaaaa\n\ @@ -1008,8 +1008,8 @@ mod test { let expect2 = "dummy.txt: 9 ddd__eee_\n\ \x20 ^~~ ^~~\n\ \x20 ...\n\ - dummy.txt:11 _ff_gg\n\ - \x20 ^~ ^~\n"; + dummy.txt:11 __f_gg\n\ + \x20 ^ ^~\n"; let expect_end = "dummy.txt: 1 aaaaa\n\ @@ -1020,7 +1020,7 @@ mod test { dummy.txt: 9 ddd__eee_\n\ \x20 ^ ^\n\ \x20 ...\n\ - dummy.txt:11 _ff_gg\n\ + dummy.txt:11 __f_gg\n\ \x20 ^ ^\n"; let expect0_end = "dummy.txt: 5 ccccc\n\ @@ -1031,7 +1031,7 @@ mod test { dummy.txt: 9 ddd__eee_\n\ \x20 ^ ^\n\ \x20 ...\n\ - dummy.txt:11 _ff_gg\n\ + dummy.txt:11 __f_gg\n\ \x20 ^ ^\n"; let expect_end_g1 = "dummy.txt:1 aaaaa\n\ @@ -1042,7 +1042,7 @@ mod test { let expect2_end = "dummy.txt: 9 ddd__eee_\n\ \x20 ^ ^\n\ \x20 ...\n\ - dummy.txt:11 _ff_gg\n\ + dummy.txt:11 __f_gg\n\ \x20 ^ ^\n"; let expect_groups = [expect2, expect_g1]; From f30f569f3ba0667414074dd8d95685ea5348c77a Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 3 Feb 2016 13:57:02 +0100 Subject: [PATCH 3/8] Add `Cow::from` for `Vec` and slices Fixes #31354. --- src/libcollections/vec.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a49b7304643cc..805d9a9807a33 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1505,6 +1505,20 @@ impl<'a> From<&'a str> for Vec { // Clone-on-write //////////////////////////////////////////////////////////////////////////////// +#[stable(feature = "cow_from_vec", since = "1.7.0")] +impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + fn from(s: &'a [T]) -> Cow<'a, [T]> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_vec", since = "1.7.0")] +impl<'a, T: Clone> From> for Cow<'a, [T]> { + fn from(v: Vec) -> Cow<'a, [T]> { + Cow::Owned(v) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { fn from_iter>(it: I) -> Cow<'a, [T]> { From b27b8f63bc51d9aba2a1fe88cf428243d4fedfa8 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 3 Feb 2016 13:57:25 +0100 Subject: [PATCH 4/8] Add tests for `Cow::from` for strings, vectors and slices --- src/libcollectionstest/str.rs | 11 +++++++++++ src/libcollectionstest/vec.rs | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 0fde70aacdca9..25457043a9df4 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; use std::cmp::Ordering::{Equal, Greater, Less}; use std::str::from_utf8; @@ -1267,6 +1268,16 @@ fn test_box_slice_clone() { assert_eq!(data, data2); } +#[test] +fn test_cow_from() { + let borrowed = "borrowed"; + let owned = String::from("owned"); + match (Cow::from(owned.clone()), Cow::from(borrowed)) { + (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), + _ => panic!("invalid `Cow::from`"), + } +} + mod pattern { use std::str::pattern::Pattern; use std::str::pattern::{Searcher, ReverseSearcher}; diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index b799be218e624..6a47f16c5ca77 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; use std::iter::{FromIterator, repeat}; use std::mem::size_of; @@ -466,6 +467,16 @@ fn test_into_iter_count() { assert_eq!(vec![1, 2, 3].into_iter().count(), 3); } +#[test] +fn test_cow_from() { + let borrowed: &[_] = &["borrowed", "(slice)"]; + let owned = vec!["owned", "(vec)"]; + match (Cow::from(owned.clone()), Cow::from(borrowed)) { + (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), + _ => panic!("invalid `Cow::from`"), + } +} + #[bench] fn bench_new(b: &mut Bencher) { b.iter(|| { From 8c0f4f5d3aa6deac4ef8b371bd043f5c1df2c254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 3 Feb 2016 19:27:32 +0100 Subject: [PATCH 5/8] Avoid quadratic growth of functions due to cleanups If a new cleanup is added to a cleanup scope, the cached exits for that scope are cleared, so all previous cleanups have to be translated again. In the worst case this means that we get N distinct landing pads where the last one has N cleanups, then N-1 and so on. As new cleanups are to be executed before older ones, we can instead cache the number of already translated cleanups in addition to the block that contains them, and then only translate new ones, if any and then jump to the cached ones, getting away with linear growth instead. For the crate in #31381 this reduces the compile time for an optimized build from >20 minutes (I cancelled the build at that point) to about 11 seconds. Testing a few crates that come with rustc show compile time improvements somewhere between 1 and 8%. The "big" winner being rustc_platform_intrinsics which features code similar to that in #31381. Fixes #31381 --- src/librustc_trans/trans/cleanup.rs | 37 +++++++++++++++-------- src/test/codegen/drop.rs | 47 +++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 src/test/codegen/drop.rs diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index dee9fb3447b45..7c98868dfe7c6 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -200,6 +200,7 @@ pub enum UnwindKind { pub struct CachedEarlyExit { label: EarlyExitLabel, cleanup_block: BasicBlockRef, + last_cleanup: usize, } pub trait Cleanup<'tcx> { @@ -560,7 +561,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { for scope in self.scopes.borrow_mut().iter_mut().rev() { if scope.kind.is_ast_with_id(cleanup_scope) { scope.cleanups.push(cleanup); - scope.clear_cached_exits(); + scope.cached_landing_pad = None; return; } else { // will be adding a cleanup to some enclosing scope @@ -585,7 +586,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { let mut scopes = self.scopes.borrow_mut(); let scope = &mut (*scopes)[custom_scope.index]; scope.cleanups.push(cleanup); - scope.clear_cached_exits(); + scope.cached_landing_pad = None; } /// Returns true if there are pending cleanups that should execute on panic. @@ -723,6 +724,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx let orig_scopes_len = self.scopes_len(); let mut prev_llbb; let mut popped_scopes = vec!(); + let mut skip = 0; // First we pop off all the cleanup stacks that are // traversed until the exit is reached, pushing them @@ -769,20 +771,25 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx } } + // Pop off the scope, since we may be generating + // unwinding code for it. + let top_scope = self.pop_scope(); + let cached_exit = top_scope.cached_early_exit(label); + popped_scopes.push(top_scope); + // Check if we have already cached the unwinding of this // scope for this label. If so, we can stop popping scopes // and branch to the cached label, since it contains the // cleanups for any subsequent scopes. - if let Some(exit) = self.top_scope(|s| s.cached_early_exit(label)) { + if let Some((exit, last_cleanup)) = cached_exit { prev_llbb = exit; + skip = last_cleanup; break; } - // Pop off the scope, since we will be generating - // unwinding code for it. If we are searching for a loop exit, + // If we are searching for a loop exit, // and this scope is that loop, then stop popping and set // `prev_llbb` to the appropriate exit block from the loop. - popped_scopes.push(self.pop_scope()); let scope = popped_scopes.last().unwrap(); match label { UnwindExit(..) | ReturnExit => { } @@ -826,13 +833,15 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx let bcx_in = self.new_block(&name[..], None); let exit_label = label.start(bcx_in); let mut bcx_out = bcx_in; - for cleanup in scope.cleanups.iter().rev() { + let len = scope.cleanups.len(); + for cleanup in scope.cleanups.iter().rev().take(len - skip) { bcx_out = cleanup.trans(bcx_out, scope.debug_loc); } + skip = 0; exit_label.branch(bcx_out, prev_llbb); prev_llbb = bcx_in.llbb; - scope.add_cached_early_exit(exit_label, prev_llbb); + scope.add_cached_early_exit(exit_label, prev_llbb, len); } self.push_scope(scope); } @@ -938,18 +947,20 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { fn cached_early_exit(&self, label: EarlyExitLabel) - -> Option { - self.cached_early_exits.iter(). + -> Option<(BasicBlockRef, usize)> { + self.cached_early_exits.iter().rev(). find(|e| e.label == label). - map(|e| e.cleanup_block) + map(|e| (e.cleanup_block, e.last_cleanup)) } fn add_cached_early_exit(&mut self, label: EarlyExitLabel, - blk: BasicBlockRef) { + blk: BasicBlockRef, + last_cleanup: usize) { self.cached_early_exits.push( CachedEarlyExit { label: label, - cleanup_block: blk }); + cleanup_block: blk, + last_cleanup: last_cleanup}); } /// True if this scope has cleanups that need unwinding diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs new file mode 100644 index 0000000000000..2ac8de6d80294 --- /dev/null +++ b/src/test/codegen/drop.rs @@ -0,0 +1,47 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +struct SomeUniqueName; + +impl Drop for SomeUniqueName { + fn drop(&mut self) { + } +} + +pub fn possibly_unwinding() { +} + +// CHECK-LABEL: @droppy +#[no_mangle] +pub fn droppy() { +// Check that there are exactly 6 drop calls. The cleanups for the unwinding should be reused, so +// that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for the +// regular function exit. We used to have problems with quadratic growths of drop calls in such +// functions. +// CHECK: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK-NOT: call{{.*}}SomeUniqueName{{.*}}drop +// The next line checks for the } that ends the function definition +// CHECK-LABEL: {{^[}]}} + let _s = SomeUniqueName; + possibly_unwinding(); + let _s = SomeUniqueName; + possibly_unwinding(); + let _s = SomeUniqueName; + possibly_unwinding(); +} From f6e22e53f3fd3bad2f005b5d517b65f83dd4c386 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 3 Feb 2016 19:41:54 -0500 Subject: [PATCH 6/8] remove dead #[derive(FromPrimitive)] code --- src/libsyntax_ext/deriving/mod.rs | 3 - src/libsyntax_ext/deriving/primitive.rs | 142 ------------------------ 2 files changed, 145 deletions(-) delete mode 100644 src/libsyntax_ext/deriving/primitive.rs diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 919540724ca6d..dcaa96446036b 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -63,7 +63,6 @@ pub mod decodable; pub mod hash; pub mod debug; pub mod default; -pub mod primitive; #[path="cmp/partial_eq.rs"] pub mod partial_eq; @@ -178,8 +177,6 @@ derive_traits! { "Default" => default::expand_deriving_default, - "FromPrimitive" => primitive::expand_deriving_from_primitive, - "Send" => bounds::expand_deriving_unsafe_bound, "Sync" => bounds::expand_deriving_unsafe_bound, "Copy" => bounds::expand_deriving_copy, diff --git a/src/libsyntax_ext/deriving/primitive.rs b/src/libsyntax_ext/deriving/primitive.rs deleted file mode 100644 index 121fe01976ef7..0000000000000 --- a/src/libsyntax_ext/deriving/primitive.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2012-2013 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. - -use deriving::generic::*; -use deriving::generic::ty::*; - -use syntax::ast::{MetaItem, Expr}; -use syntax::ast; -use syntax::codemap::Span; -use syntax::ext::base::{ExtCtxt, Annotatable}; -use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; -use syntax::ptr::P; - -pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut FnMut(Annotatable)) -{ - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::num::FromPrimitive), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - is_unsafe: false, - methods: vec!( - MethodDef { - name: "from_i64", - generics: LifetimeBounds::empty(), - explicit_self: None, - args: vec!(Literal(path_local!(i64))), - ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), - None, - vec!(Box::new(Self_)), - true)), - // #[inline] liable to cause code-bloat - attributes: attrs.clone(), - is_unsafe: false, - combine_substructure: combine_substructure(Box::new(|c, s, sub| { - cs_from("i64", c, s, sub) - })), - }, - MethodDef { - name: "from_u64", - generics: LifetimeBounds::empty(), - explicit_self: None, - args: vec!(Literal(path_local!(u64))), - ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), - None, - vec!(Box::new(Self_)), - true)), - // #[inline] liable to cause code-bloat - attributes: attrs, - is_unsafe: false, - combine_substructure: combine_substructure(Box::new(|c, s, sub| { - cs_from("u64", c, s, sub) - })), - } - ), - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push) -} - -fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P { - let n = match (substr.nonself_args.len(), substr.nonself_args.get(0)) { - (1, Some(o_f)) => o_f, - _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(FromPrimitive)`") - }; - - match *substr.fields { - StaticStruct(..) => { - cx.span_err(trait_span, "`FromPrimitive` cannot be derived for structs"); - return cx.expr_fail(trait_span, InternedString::new("")); - } - StaticEnum(enum_def, _) => { - if enum_def.variants.is_empty() { - cx.span_err(trait_span, - "`FromPrimitive` cannot be derived for enums with no variants"); - return cx.expr_fail(trait_span, InternedString::new("")); - } - - let mut arms = Vec::new(); - - for variant in &enum_def.variants { - let def = &variant.node.data; - if !def.is_unit() { - cx.span_err(trait_span, "`FromPrimitive` cannot be derived \ - for enums with non-unit variants"); - return cx.expr_fail(trait_span, - InternedString::new("")); - } - - let span = variant.span; - - // expr for `$n == $variant as $name` - let path = cx.path(span, vec![substr.type_ident, variant.node.name]); - let variant = cx.expr_path(path); - let ty = cx.ty_ident(span, cx.ident_of(name)); - let cast = cx.expr_cast(span, variant.clone(), ty); - let guard = cx.expr_binary(span, ast::BiEq, n.clone(), cast); - - // expr for `Some($variant)` - let body = cx.expr_some(span, variant); - - // arm for `_ if $guard => $body` - let arm = ast::Arm { - attrs: vec!(), - pats: vec!(cx.pat_wild(span)), - guard: Some(guard), - body: body, - }; - - arms.push(arm); - } - - // arm for `_ => None` - let arm = ast::Arm { - attrs: vec!(), - pats: vec!(cx.pat_wild(trait_span)), - guard: None, - body: cx.expr_none(trait_span), - }; - arms.push(arm); - - cx.expr_match(trait_span, n.clone(), arms) - } - _ => cx.span_bug(trait_span, "expected StaticEnum in derive(FromPrimitive)") - } -} From 45e716e51cd8b7f982645bfefb129e7618e241b3 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 3 Feb 2016 19:58:07 -0500 Subject: [PATCH 7/8] test #[derive(FromPrimitive)] triggers custom-derive error --- src/test/compile-fail/deriving-primitive.rs | 27 +++------------------ 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs index e8e37d8804986..be822a173ab58 100644 --- a/src/test/compile-fail/deriving-primitive.rs +++ b/src/test/compile-fail/deriving-primitive.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,27 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::num::FromPrimitive; -use std::isize; +#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable +enum Foo {} -#[derive(FromPrimitive)] -struct A { x: isize } -//~^^ ERROR `FromPrimitive` cannot be derived for structs -//~^^^ ERROR `FromPrimitive` cannot be derived for structs +fn main() {} -#[derive(FromPrimitive)] -struct B(isize); -//~^^ ERROR `FromPrimitive` cannot be derived for structs -//~^^^ ERROR `FromPrimitive` cannot be derived for structs - -#[derive(FromPrimitive)] -enum C { Foo(isize), Bar(usize) } -//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants -//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants - -#[derive(FromPrimitive)] -enum D { Baz { x: isize } } -//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants -//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants - -pub fn main() {} From ffcba8010b8b38b0cb68935f7f4d28531892b2be Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 1 Feb 2016 23:46:02 -0500 Subject: [PATCH 8/8] Add LLVM ModulePass regression test using run-make. Part of #31185 --- mk/tests.mk | 3 +- src/etc/maketest.py | 1 + src/test/run-make/llvm-module-pass/Makefile | 8 +++ .../run-make/llvm-module-pass/llvm-pass.so.cc | 55 +++++++++++++++++++ src/test/run-make/llvm-module-pass/main.rs | 14 +++++ src/test/run-make/llvm-module-pass/plugin.rs | 26 +++++++++ 6 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make/llvm-module-pass/Makefile create mode 100644 src/test/run-make/llvm-module-pass/llvm-pass.so.cc create mode 100644 src/test/run-make/llvm-module-pass/main.rs create mode 100644 src/test/run-make/llvm-module-pass/plugin.rs diff --git a/mk/tests.mk b/mk/tests.mk index 19587a28d5594..2cc1a612cc9f3 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -1048,7 +1048,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ $$(S) \ $(3) \ "$$(LLVM_LIBDIR_RUSTFLAGS_$(3))" \ - "$$(LLVM_ALL_COMPONENTS_$(3))" + "$$(LLVM_ALL_COMPONENTS_$(3))" \ + "$$(LLVM_CXXFLAGS_$(3))" @touch -r $$@.start_time $$@ && rm $$@.start_time else # FIXME #11094 - The above rule doesn't work right for multiple targets diff --git a/src/etc/maketest.py b/src/etc/maketest.py index 34c2cdbef3538..275785f874605 100644 --- a/src/etc/maketest.py +++ b/src/etc/maketest.py @@ -55,6 +55,7 @@ def convert_path_spec(name, value): putenv('S', os.path.abspath(sys.argv[13])) putenv('RUSTFLAGS', sys.argv[15]) putenv('LLVM_COMPONENTS', sys.argv[16]) +putenv('LLVM_CXXFLAGS', sys.argv[17]) putenv('PYTHON', sys.executable) os.putenv('TARGET', target_triple) diff --git a/src/test/run-make/llvm-module-pass/Makefile b/src/test/run-make/llvm-module-pass/Makefile new file mode 100644 index 0000000000000..188b1f72e39b2 --- /dev/null +++ b/src/test/run-make/llvm-module-pass/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,llvm-pass) + $(RUSTC) plugin.rs -C prefer-dynamic + $(RUSTC) main.rs + +$(TMPDIR)/libllvm-pass.o: + $(CXX) $(LLVM_CXXFLAGS) -c llvm-pass.so.cc -o $(TMPDIR)/libllvm-pass.o diff --git a/src/test/run-make/llvm-module-pass/llvm-pass.so.cc b/src/test/run-make/llvm-module-pass/llvm-pass.so.cc new file mode 100644 index 0000000000000..8723f24569775 --- /dev/null +++ b/src/test/run-make/llvm-module-pass/llvm-pass.so.cc @@ -0,0 +1,55 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include +#include + +#include "llvm/IR/Module.h" + +using namespace llvm; + +namespace { + + class TestLLVMPass : public ModulePass { + + public: + + static char ID; + TestLLVMPass() : ModulePass(ID) { } + + bool runOnModule(Module &M) override; + + const char *getPassName() const override { + return "Some LLVM pass"; + } + + }; + +} + +bool TestLLVMPass::runOnModule(Module &M) { + // A couple examples of operations that previously caused segmentation faults + // https://github.com/rust-lang/rust/issues/31067 + + for (auto F = M.begin(); F != M.end(); ++F) { + /* code */ + } + + LLVMContext &C = M.getContext(); + IntegerType *Int8Ty = IntegerType::getInt8Ty(C); + llvm::Type *i = PointerType::get(Int8Ty, 0); + return true; +} + +char TestLLVMPass::ID = 0; + +static RegisterPass RegisterAFLPass( + "some-llvm-pass", "Some LLVM pass"); diff --git a/src/test/run-make/llvm-module-pass/main.rs b/src/test/run-make/llvm-module-pass/main.rs new file mode 100644 index 0000000000000..5b5ab94bcef02 --- /dev/null +++ b/src/test/run-make/llvm-module-pass/main.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(plugin)] +#![plugin(some_plugin)] + +fn main() {} diff --git a/src/test/run-make/llvm-module-pass/plugin.rs b/src/test/run-make/llvm-module-pass/plugin.rs new file mode 100644 index 0000000000000..039de3c717961 --- /dev/null +++ b/src/test/run-make/llvm-module-pass/plugin.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(plugin_registrar, rustc_private)] +#![crate_type = "dylib"] +#![crate_name = "some_plugin"] + +extern crate rustc; +extern crate rustc_plugin; + +#[link(name = "llvm-pass", kind = "static")] +extern {} + +use rustc_plugin::registry::Registry; + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_llvm_pass("some-llvm-pass"); +}