From 4b70269854a701668ba47641201c4403228db06b Mon Sep 17 00:00:00 2001 From: Stuart Pernsteiner Date: Fri, 1 Aug 2014 15:45:24 -0700 Subject: [PATCH] add tests for separate compilation --- src/test/auxiliary/sepcomp-extern-lib.rs | 14 +++++++ src/test/auxiliary/sepcomp_cci_lib.rs | 17 ++++++++ src/test/auxiliary/sepcomp_lib.rs | 31 ++++++++++++++ src/test/compile-fail/sepcomp-lib-lto.rs | 28 +++++++++++++ src/test/run-make/sepcomp-cci-copies/Makefile | 10 +++++ .../run-make/sepcomp-cci-copies/cci_lib.rs | 19 +++++++++ src/test/run-make/sepcomp-cci-copies/foo.rs | 36 ++++++++++++++++ src/test/run-make/sepcomp-inlining/Makefile | 13 ++++++ src/test/run-make/sepcomp-inlining/foo.rs | 35 ++++++++++++++++ src/test/run-make/sepcomp-separate/Makefile | 9 ++++ src/test/run-make/sepcomp-separate/foo.rs | 27 ++++++++++++ src/test/run-pass/sepcomp-cci.rs | 41 ++++++++++++++++++ src/test/run-pass/sepcomp-extern.rs | 42 +++++++++++++++++++ src/test/run-pass/sepcomp-fns-backwards.rs | 41 ++++++++++++++++++ src/test/run-pass/sepcomp-fns.rs | 38 +++++++++++++++++ src/test/run-pass/sepcomp-lib.rs | 24 +++++++++++ src/test/run-pass/sepcomp-statics.rs | 39 +++++++++++++++++ src/test/run-pass/sepcomp-unwind.rs | 38 +++++++++++++++++ 18 files changed, 502 insertions(+) create mode 100644 src/test/auxiliary/sepcomp-extern-lib.rs create mode 100644 src/test/auxiliary/sepcomp_cci_lib.rs create mode 100644 src/test/auxiliary/sepcomp_lib.rs create mode 100644 src/test/compile-fail/sepcomp-lib-lto.rs create mode 100644 src/test/run-make/sepcomp-cci-copies/Makefile create mode 100644 src/test/run-make/sepcomp-cci-copies/cci_lib.rs create mode 100644 src/test/run-make/sepcomp-cci-copies/foo.rs create mode 100644 src/test/run-make/sepcomp-inlining/Makefile create mode 100644 src/test/run-make/sepcomp-inlining/foo.rs create mode 100644 src/test/run-make/sepcomp-separate/Makefile create mode 100644 src/test/run-make/sepcomp-separate/foo.rs create mode 100644 src/test/run-pass/sepcomp-cci.rs create mode 100644 src/test/run-pass/sepcomp-extern.rs create mode 100644 src/test/run-pass/sepcomp-fns-backwards.rs create mode 100644 src/test/run-pass/sepcomp-fns.rs create mode 100644 src/test/run-pass/sepcomp-lib.rs create mode 100644 src/test/run-pass/sepcomp-statics.rs create mode 100644 src/test/run-pass/sepcomp-unwind.rs diff --git a/src/test/auxiliary/sepcomp-extern-lib.rs b/src/test/auxiliary/sepcomp-extern-lib.rs new file mode 100644 index 0000000000000..8f5d3b5768a1a --- /dev/null +++ b/src/test/auxiliary/sepcomp-extern-lib.rs @@ -0,0 +1,14 @@ +// Copyright 2012 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. + +#[no_mangle] +pub extern "C" fn foo() -> uint { + 1234 +} diff --git a/src/test/auxiliary/sepcomp_cci_lib.rs b/src/test/auxiliary/sepcomp_cci_lib.rs new file mode 100644 index 0000000000000..1cb7ead2cff05 --- /dev/null +++ b/src/test/auxiliary/sepcomp_cci_lib.rs @@ -0,0 +1,17 @@ +// Copyright 2012 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. + +#[inline] +pub fn cci_fn() -> uint { + 1200 +} + +#[inline] +pub static CCI_STATIC: uint = 34; diff --git a/src/test/auxiliary/sepcomp_lib.rs b/src/test/auxiliary/sepcomp_lib.rs new file mode 100644 index 0000000000000..d1d9e3b8ff3ac --- /dev/null +++ b/src/test/auxiliary/sepcomp_lib.rs @@ -0,0 +1,31 @@ +// Copyright 2012 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 codegen-units=3 --crate-type=rlib,dylib + +pub mod a { + pub fn one() -> uint { + 1 + } +} + +pub mod b { + pub fn two() -> uint { + 2 + } +} + +pub mod c { + use a::one; + use b::two; + pub fn three() -> uint { + one() + two() + } +} diff --git a/src/test/compile-fail/sepcomp-lib-lto.rs b/src/test/compile-fail/sepcomp-lib-lto.rs new file mode 100644 index 0000000000000..59706e20bede2 --- /dev/null +++ b/src/test/compile-fail/sepcomp-lib-lto.rs @@ -0,0 +1,28 @@ +// Copyright 2012 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. + +// Make sure we give a sane error message when the user requests LTO with a +// library built with -C codegen-units > 1. + +// aux-build:sepcomp_lib.rs +// compile-flags: -Z lto +// error-pattern:missing compressed bytecode +// no-prefer-dynamic + +extern crate sepcomp_lib; +use sepcomp_lib::a::one; +use sepcomp_lib::b::two; +use sepcomp_lib::c::three; + +fn main() { + assert_eq!(one(), 1); + assert_eq!(two(), 2); + assert_eq!(three(), 3); +} diff --git a/src/test/run-make/sepcomp-cci-copies/Makefile b/src/test/run-make/sepcomp-cci-copies/Makefile new file mode 100644 index 0000000000000..fdb39f851970f --- /dev/null +++ b/src/test/run-make/sepcomp-cci-copies/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +# Check that cross-crate inlined items are inlined in all compilation units +# that refer to them, and not in any other compilation units. + +all: + $(RUSTC) cci_lib.rs + $(RUSTC) foo.rs --emit=ir -C codegen-units=3 + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ .*cci_fn)" -eq "2" ] + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c CCI_STATIC.*=.*constant)" -eq "2" ] diff --git a/src/test/run-make/sepcomp-cci-copies/cci_lib.rs b/src/test/run-make/sepcomp-cci-copies/cci_lib.rs new file mode 100644 index 0000000000000..099101d6f2679 --- /dev/null +++ b/src/test/run-make/sepcomp-cci-copies/cci_lib.rs @@ -0,0 +1,19 @@ +// Copyright 2012 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. + +#![crate_type = "rlib"] + +#[inline] +pub fn cci_fn() -> uint { + 1234 +} + +#[inline] +pub static CCI_STATIC: uint = 2345; diff --git a/src/test/run-make/sepcomp-cci-copies/foo.rs b/src/test/run-make/sepcomp-cci-copies/foo.rs new file mode 100644 index 0000000000000..c702e578c0965 --- /dev/null +++ b/src/test/run-make/sepcomp-cci-copies/foo.rs @@ -0,0 +1,36 @@ +// Copyright 2014 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. + +extern crate cci_lib; +use cci_lib::{cci_fn, CCI_STATIC}; + +fn call1() -> uint { + cci_fn() + CCI_STATIC +} + +mod a { + use cci_lib::cci_fn; + pub fn call2() -> uint { + cci_fn() + } +} + +mod b { + use cci_lib::CCI_STATIC; + pub fn call3() -> uint { + CCI_STATIC + } +} + +fn main() { + call1(); + a::call2(); + b::call3(); +} diff --git a/src/test/run-make/sepcomp-inlining/Makefile b/src/test/run-make/sepcomp-inlining/Makefile new file mode 100644 index 0000000000000..6cb9f9a3f31bc --- /dev/null +++ b/src/test/run-make/sepcomp-inlining/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +# Test that #[inline(always)] functions still get inlined across compilation +# unit boundaries. Compilation should produce three IR files, with each one +# containing a definition of the inlined function. Also, the non-#[inline] +# function should be defined in only one compilation unit. + +all: + $(RUSTC) foo.rs --emit=ir -C codegen-units=3 + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ i32\ .*inlined)" -eq "1" ] + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ available_externally\ i32\ .*inlined)" -eq "2" ] + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ i32\ .*normal)" -eq "1" ] + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c declare\ i32\ .*normal)" -eq "2" ] diff --git a/src/test/run-make/sepcomp-inlining/foo.rs b/src/test/run-make/sepcomp-inlining/foo.rs new file mode 100644 index 0000000000000..20fd18b829562 --- /dev/null +++ b/src/test/run-make/sepcomp-inlining/foo.rs @@ -0,0 +1,35 @@ +// Copyright 2014 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. + +#[inline] +fn inlined() -> u32 { + 1234 +} + +fn normal() -> u32 { + 2345 +} + +mod a { + pub fn f() -> u32 { + ::inlined() + ::normal() + } +} + +mod b { + pub fn f() -> u32 { + ::inlined() + ::normal() + } +} + +fn main() { + a::f(); + b::f(); +} diff --git a/src/test/run-make/sepcomp-separate/Makefile b/src/test/run-make/sepcomp-separate/Makefile new file mode 100644 index 0000000000000..265bd68bd2e82 --- /dev/null +++ b/src/test/run-make/sepcomp-separate/Makefile @@ -0,0 +1,9 @@ +-include ../tools.mk + +# Test that separate compilation actually puts code into separate compilation +# units. `foo.rs` defines `magic_fn` in three different modules, which should +# wind up in three different compilation units. + +all: + $(RUSTC) foo.rs --emit=ir -C codegen-units=3 + [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ .*magic_fn)" -eq "3" ] diff --git a/src/test/run-make/sepcomp-separate/foo.rs b/src/test/run-make/sepcomp-separate/foo.rs new file mode 100644 index 0000000000000..fe6a7b5a18f27 --- /dev/null +++ b/src/test/run-make/sepcomp-separate/foo.rs @@ -0,0 +1,27 @@ +// Copyright 2014 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. + +fn magic_fn() -> uint { + 1234 +} + +mod a { + pub fn magic_fn() -> uint { + 2345 + } +} + +mod b { + pub fn magic_fn() -> uint { + 3456 + } +} + +fn main() { } diff --git a/src/test/run-pass/sepcomp-cci.rs b/src/test/run-pass/sepcomp-cci.rs new file mode 100644 index 0000000000000..0178b5e786d65 --- /dev/null +++ b/src/test/run-pass/sepcomp-cci.rs @@ -0,0 +1,41 @@ +// Copyright 2012 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 codegen-units=3 +// aux-build:sepcomp_cci_lib.rs + +// Test accessing cross-crate inlined items from multiple compilation units. + +extern crate sepcomp_cci_lib; +use sepcomp_cci_lib::{cci_fn, CCI_STATIC}; + +fn call1() -> uint { + cci_fn() + CCI_STATIC +} + +mod a { + use sepcomp_cci_lib::{cci_fn, CCI_STATIC}; + pub fn call2() -> uint { + cci_fn() + CCI_STATIC + } +} + +mod b { + use sepcomp_cci_lib::{cci_fn, CCI_STATIC}; + pub fn call3() -> uint { + cci_fn() + CCI_STATIC + } +} + +fn main() { + assert_eq!(call1(), 1234); + assert_eq!(a::call2(), 1234); + assert_eq!(b::call3(), 1234); +} diff --git a/src/test/run-pass/sepcomp-extern.rs b/src/test/run-pass/sepcomp-extern.rs new file mode 100644 index 0000000000000..a5506e3fc761d --- /dev/null +++ b/src/test/run-pass/sepcomp-extern.rs @@ -0,0 +1,42 @@ +// Copyright 2012 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 codegen-units=3 +// aux-build:sepcomp-extern-lib.rs + +// Test accessing external items from multiple compilation units. + +#[link(name = "sepcomp-extern-lib")] +extern { + #[allow(ctypes)] + fn foo() -> uint; +} + +fn call1() -> uint { + unsafe { foo() } +} + +mod a { + pub fn call2() -> uint { + unsafe { ::foo() } + } +} + +mod b { + pub fn call3() -> uint { + unsafe { ::foo() } + } +} + +fn main() { + assert_eq!(call1(), 1234); + assert_eq!(a::call2(), 1234); + assert_eq!(b::call3(), 1234); +} diff --git a/src/test/run-pass/sepcomp-fns-backwards.rs b/src/test/run-pass/sepcomp-fns-backwards.rs new file mode 100644 index 0000000000000..61f008ad854eb --- /dev/null +++ b/src/test/run-pass/sepcomp-fns-backwards.rs @@ -0,0 +1,41 @@ +// Copyright 2012 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 codegen-units=3 + +// Test references to items that haven't been translated yet. + +// Generate some code in the first compilation unit before declaring any +// modules. This ensures that the first module doesn't go into the same +// compilation unit as the top-level module. +fn pad() -> uint { 0 } + +mod b { + pub fn three() -> uint { + ::one() + ::a::two() + } +} + +mod a { + pub fn two() -> uint { + ::one() + ::one() + } +} + +fn one() -> uint { + 1 +} + +fn main() { + assert_eq!(one(), 1); + assert_eq!(a::two(), 2); + assert_eq!(b::three(), 3); +} + diff --git a/src/test/run-pass/sepcomp-fns.rs b/src/test/run-pass/sepcomp-fns.rs new file mode 100644 index 0000000000000..09f2a4281be08 --- /dev/null +++ b/src/test/run-pass/sepcomp-fns.rs @@ -0,0 +1,38 @@ +// Copyright 2012 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 codegen-units=3 + +// Test basic separate compilation functionality. The functions should be able +// to call each other even though they will be placed in different compilation +// units. + +// Generate some code in the first compilation unit before declaring any +// modules. This ensures that the first module doesn't go into the same +// compilation unit as the top-level module. +fn one() -> uint { 1 } + +mod a { + pub fn two() -> uint { + ::one() + ::one() + } +} + +mod b { + pub fn three() -> uint { + ::one() + ::a::two() + } +} + +fn main() { + assert_eq!(one(), 1); + assert_eq!(a::two(), 2); + assert_eq!(b::three(), 3); +} diff --git a/src/test/run-pass/sepcomp-lib.rs b/src/test/run-pass/sepcomp-lib.rs new file mode 100644 index 0000000000000..28adb55399b44 --- /dev/null +++ b/src/test/run-pass/sepcomp-lib.rs @@ -0,0 +1,24 @@ +// Copyright 2012 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. + +// aux-build:sepcomp_lib.rs + +// Test linking against a library built with -C codegen-units > 1 + +extern crate sepcomp_lib; +use sepcomp_lib::a::one; +use sepcomp_lib::b::two; +use sepcomp_lib::c::three; + +fn main() { + assert_eq!(one(), 1); + assert_eq!(two(), 2); + assert_eq!(three(), 3); +} diff --git a/src/test/run-pass/sepcomp-statics.rs b/src/test/run-pass/sepcomp-statics.rs new file mode 100644 index 0000000000000..26a652ae0ea4f --- /dev/null +++ b/src/test/run-pass/sepcomp-statics.rs @@ -0,0 +1,39 @@ +// Copyright 2012 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 codegen-units=3 + +// Test references to static items across compilation units. + +fn pad() -> uint { 0 } + +static ONE: uint = 1; + +mod b { + // Separate compilation always switches to the LLVM module with the fewest + // instructions. Make sure we have some instructions in this module so + // that `a` and `b` don't go into the same compilation unit. + fn pad() -> uint { 0 } + + pub static THREE: uint = ::ONE + ::a::TWO; +} + +mod a { + fn pad() -> uint { 0 } + + pub static TWO: uint = ::ONE + ::ONE; +} + +fn main() { + assert_eq!(ONE, 1); + assert_eq!(a::TWO, 2); + assert_eq!(b::THREE, 3); +} + diff --git a/src/test/run-pass/sepcomp-unwind.rs b/src/test/run-pass/sepcomp-unwind.rs new file mode 100644 index 0000000000000..5d154e02af670 --- /dev/null +++ b/src/test/run-pass/sepcomp-unwind.rs @@ -0,0 +1,38 @@ +// Copyright 2012 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 codegen-units=3 + +// Test unwinding through multiple compilation units. + +// According to acrichto, in the distant past `ld -r` (which is used during +// linking when codegen-units > 1) was known to produce object files with +// damaged unwinding tables. This may be related to GNU binutils bug #6893 +// ("Partial linking results in corrupt .eh_frame_hdr"), but I'm not certain. +// In any case, this test should let us know if enabling parallel codegen ever +// breaks unwinding. + +fn pad() -> uint { 0 } + +mod a { + pub fn f() { + fail!(); + } +} + +mod b { + pub fn g() { + ::a::f(); + } +} + +fn main() { + std::task::try(proc() { ::b::g() }).unwrap_err(); +}