From 4b70269854a701668ba47641201c4403228db06b Mon Sep 17 00:00:00 2001
From: Stuart Pernsteiner <spernsteiner@mozilla.com>
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 00000000000..8f5d3b5768a
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..1cb7ead2cff
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..d1d9e3b8ff3
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..59706e20bed
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..fdb39f85197
--- /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 00000000000..099101d6f26
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..c702e578c09
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..6cb9f9a3f31
--- /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 00000000000..20fd18b8295
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..265bd68bd2e
--- /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 00000000000..fe6a7b5a18f
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..0178b5e786d
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..a5506e3fc76
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..61f008ad854
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..09f2a4281be
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..28adb55399b
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..26a652ae0ea
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..5d154e02af6
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
+}