about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_llvm/lib.rs1
-rw-r--r--src/librustc_trans/back/write.rs12
-rw-r--r--src/test/run-make/emit/Makefile15
-rw-r--r--src/test/run-make/emit/test-24876.rs19
-rw-r--r--src/test/run-make/emit/test-26235.rs56
5 files changed, 103 insertions, 0 deletions
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 0f05db86742..8dcaa4b5064 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -616,6 +616,7 @@ extern {
                                              C: ContextRef)
                                              -> ModuleRef;
     pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
+    pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef;
     pub fn LLVMDisposeModule(M: ModuleRef);
 
     /// Data layout. See Module::getDataLayout.
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 4815a399d99..5b38004396b 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -545,10 +545,22 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
         if config.emit_asm {
             let path = output_names.with_extension(&format!("{}.s", name_extra));
+
+            // We can't use the same module for asm and binary output, because that triggers
+            // various errors like invalid IR or broken binaries, so we might have to clone the
+            // module to produce the asm output
+            let llmod = if config.emit_obj {
+                llvm::LLVMCloneModule(llmod)
+            } else {
+                llmod
+            };
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(cgcx.handler, tm, cpm, llmod, &path,
                                   llvm::AssemblyFileType);
             });
+            if config.emit_obj {
+                llvm::LLVMDisposeModule(llmod);
+            }
         }
 
         if config.emit_obj {
diff --git a/src/test/run-make/emit/Makefile b/src/test/run-make/emit/Makefile
new file mode 100644
index 00000000000..be34028fe1d
--- /dev/null
+++ b/src/test/run-make/emit/Makefile
@@ -0,0 +1,15 @@
+-include ../tools.mk
+
+all:
+	$(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
+	$(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
+	$(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
+	$(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs
+	$(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
+	$(call RUN,test-26235) || exit 1
+	$(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
+	$(call RUN,test-26235) || exit 1
+	$(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
+	$(call RUN,test-26235) || exit 1
+	$(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs
+	$(call RUN,test-26235) || exit 1
diff --git a/src/test/run-make/emit/test-24876.rs b/src/test/run-make/emit/test-24876.rs
new file mode 100644
index 00000000000..ab69decbf00
--- /dev/null
+++ b/src/test/run-make/emit/test-24876.rs
@@ -0,0 +1,19 @@
+// 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 <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.
+
+// Checks for issue #24876
+
+fn main() {
+    let mut v = 0;
+    for i in 0..0 {
+        v += i;
+    }
+    println!("{}", v)
+}
diff --git a/src/test/run-make/emit/test-26235.rs b/src/test/run-make/emit/test-26235.rs
new file mode 100644
index 00000000000..97b58a3671b
--- /dev/null
+++ b/src/test/run-make/emit/test-26235.rs
@@ -0,0 +1,56 @@
+// 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 <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.
+
+// Checks for issue #26235
+
+fn main() {
+    use std::thread;
+
+    type Key = u32;
+    const NUM_THREADS: usize = 2;
+
+    #[derive(Clone,Copy)]
+    struct Stats<S> {
+        upsert: S,
+        delete: S,
+        insert: S,
+        update: S
+    };
+
+    impl<S> Stats<S> where S: Copy {
+        fn dot<B, F, T>(self, s: Stats<T>, f: F) -> Stats<B> where F: Fn(S, T) -> B {
+            let Stats { upsert: u1, delete: d1, insert: i1, update: p1 } = self;
+            let Stats { upsert: u2, delete: d2, insert: i2, update: p2 } = s;
+            Stats { upsert: f(u1, u2), delete: f(d1, d2), insert: f(i1, i2), update: f(p1, p2) }
+        }
+
+        fn new(init: S) -> Self {
+            Stats { upsert: init, delete: init, insert: init, update: init }
+        }
+    }
+
+    fn make_threads() -> Vec<thread::JoinHandle<()>> {
+        let mut t = Vec::with_capacity(NUM_THREADS);
+        for _ in 0..NUM_THREADS {
+            t.push(thread::spawn(move || {}));
+        }
+        t
+    }
+
+    let stats = [Stats::new(0); NUM_THREADS];
+    make_threads();
+
+    {
+        let Stats { ref upsert, ref delete, ref insert, ref update } = stats.iter().fold(
+            Stats::new(0), |res, &s| res.dot(s, |x: Key, y: Key| x.wrapping_add(y)));
+        println!("upserts: {}, deletes: {}, inserts: {}, updates: {}",
+                 upsert, delete, insert, update);
+    }
+}