about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-07-16 00:11:09 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-07-16 20:25:51 -0700
commit74e198126b19efb7871aa673ae17483753f067b0 (patch)
tree29ecd1434421fc39bd3e56f0fa2f8278978803b7
parent7f0e733f1d8e597faee4bff0fc04838867725fad (diff)
downloadrust-74e198126b19efb7871aa673ae17483753f067b0.tar.gz
rust-74e198126b19efb7871aa673ae17483753f067b0.zip
trans: Add kind to writeArchive
Updates our LLVM bindings to be able to write out multiple kinds of archives.
This commit also enables using LLVM instead of the system ar on all current
targets.
-rw-r--r--src/librustc_back/target/apple_base.rs1
-rw-r--r--src/librustc_back/target/bitrig_base.rs1
-rw-r--r--src/librustc_back/target/dragonfly_base.rs1
-rw-r--r--src/librustc_back/target/freebsd_base.rs1
-rw-r--r--src/librustc_back/target/netbsd_base.rs1
-rw-r--r--src/librustc_back/target/openbsd_base.rs1
-rw-r--r--src/librustc_llvm/archive_ro.rs3
-rw-r--r--src/librustc_llvm/lib.rs12
-rw-r--r--src/librustc_trans/back/archive.rs29
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp17
10 files changed, 52 insertions, 15 deletions
diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs
index 795a2c18bc6..f34ba40a8b2 100644
--- a/src/librustc_back/target/apple_base.rs
+++ b/src/librustc_back/target/apple_base.rs
@@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
         has_rpath: true,
         dll_prefix: "lib".to_string(),
         dll_suffix: ".dylib".to_string(),
+        archive_format: "bsd".to_string(),
         pre_link_args: Vec::new(),
         .. Default::default()
     }
diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_back/target/bitrig_base.rs
index 6e5a48c0ea1..9f6a1f1e530 100644
--- a/src/librustc_back/target/bitrig_base.rs
+++ b/src/librustc_back/target/bitrig_base.rs
@@ -22,6 +22,7 @@ pub fn opts() -> TargetOptions {
         position_independent_executables: true,
         pre_link_args: vec!(
         ),
+        archive_format: "bsd".to_string(),
 
         .. Default::default()
     }
diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_back/target/dragonfly_base.rs
index a56621ff97e..51a371db724 100644
--- a/src/librustc_back/target/dragonfly_base.rs
+++ b/src/librustc_back/target/dragonfly_base.rs
@@ -29,6 +29,7 @@ pub fn opts() -> TargetOptions {
             "-Wl,--as-needed".to_string(),
         ),
         position_independent_executables: true,
+        archive_format: "bsd".to_string(),
         .. Default::default()
     }
 }
diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs
index 3ec6307c72f..2c3d240dbf3 100644
--- a/src/librustc_back/target/freebsd_base.rs
+++ b/src/librustc_back/target/freebsd_base.rs
@@ -18,6 +18,7 @@ pub fn opts() -> TargetOptions {
         executables: true,
         morestack: true,
         has_rpath: true,
+        archive_format: "bsd".to_string(),
 
         .. Default::default()
     }
diff --git a/src/librustc_back/target/netbsd_base.rs b/src/librustc_back/target/netbsd_base.rs
index 0f2ab32be24..9b20bd927cb 100644
--- a/src/librustc_back/target/netbsd_base.rs
+++ b/src/librustc_back/target/netbsd_base.rs
@@ -27,6 +27,7 @@ pub fn opts() -> TargetOptions {
             "-Wl,--as-needed".to_string(),
         ),
         position_independent_executables: true,
+        archive_format: "bsd".to_string(),
         .. Default::default()
     }
 }
diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs
index 0f2ab32be24..9b20bd927cb 100644
--- a/src/librustc_back/target/openbsd_base.rs
+++ b/src/librustc_back/target/openbsd_base.rs
@@ -27,6 +27,7 @@ pub fn opts() -> TargetOptions {
             "-Wl,--as-needed".to_string(),
         ),
         position_independent_executables: true,
+        archive_format: "bsd".to_string(),
         .. Default::default()
     }
 }
diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs
index 2c6022bc614..85c0c721114 100644
--- a/src/librustc_llvm/archive_ro.rs
+++ b/src/librustc_llvm/archive_ro.rs
@@ -118,6 +118,9 @@ impl<'a> Child<'a> {
         unsafe {
             let mut data_len = 0;
             let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len);
+            if data_ptr.is_null() {
+                panic!("failed to read data from archive child");
+            }
             slice::from_raw_parts(data_ptr as *const u8, data_len as usize)
         }
     }
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 05f82b86ebb..051cc1c5bb2 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -452,6 +452,15 @@ pub enum DiagnosticKind {
     DK_OptimizationFailure,
 }
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub enum ArchiveKind {
+    K_GNU,
+    K_MIPS64,
+    K_BSD,
+    K_COFF,
+}
+
 // Opaque pointer types
 #[allow(missing_copy_implementations)]
 pub enum Module_opaque {}
@@ -2119,7 +2128,8 @@ extern {
     pub fn LLVMRustWriteArchive(Dst: *const c_char,
                                 NumMembers: size_t,
                                 Members: *const RustArchiveMemberRef,
-                                WriteSymbtab: bool) -> c_int;
+                                WriteSymbtab: bool,
+                                Kind: ArchiveKind) -> c_int;
     pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
                                     Name: *const c_char,
                                     Child: ArchiveChildRef) -> RustArchiveMemberRef;
diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs
index cc3d1d842fa..02f4bc83b75 100644
--- a/src/librustc_trans/back/archive.rs
+++ b/src/librustc_trans/back/archive.rs
@@ -22,7 +22,7 @@ use std::str;
 
 use libc;
 use llvm::archive_ro::{ArchiveRO, Child};
-use llvm;
+use llvm::{self, ArchiveKind};
 use rustc::metadata::loader::METADATA_FILENAME;
 use rustc::session::Session;
 use rustc_back::tempdir::TempDir;
@@ -208,28 +208,34 @@ impl<'a> ArchiveBuilder<'a> {
     /// Combine the provided files, rlibs, and native libraries into a single
     /// `Archive`.
     pub fn build(&mut self) {
-        let res = if self.using_llvm() {
-            self.build_with_llvm()
-        } else {
-            self.build_with_ar_cmd()
+        let res = match self.llvm_archive_kind() {
+            Some(kind) => self.build_with_llvm(kind),
+            None => self.build_with_ar_cmd(),
         };
         if let Err(e) = res {
             self.config.sess.fatal(&format!("failed to build archive: {}", e));
         }
     }
 
-    pub fn using_llvm(&self) -> bool {
+    pub fn llvm_archive_kind(&self) -> Option<ArchiveKind> {
         if unsafe { llvm::LLVMVersionMinor() < 7 } {
-            return false
+            return None
         }
 
         // Currently LLVM only supports writing archives in the 'gnu' format.
         match &self.config.sess.target.target.options.archive_format[..] {
-            "gnu" => true,
-            _ => false,
+            "gnu" => Some(ArchiveKind::K_GNU),
+            "mips64" => Some(ArchiveKind::K_MIPS64),
+            "bsd" => Some(ArchiveKind::K_BSD),
+            "coff" => Some(ArchiveKind::K_COFF),
+            _ => None,
         }
     }
 
+    pub fn using_llvm(&self) -> bool {
+        self.llvm_archive_kind().is_some()
+    }
+
     fn build_with_ar_cmd(&mut self) -> io::Result<()> {
         let removals = mem::replace(&mut self.removals, Vec::new());
         let additions = mem::replace(&mut self.additions, Vec::new());
@@ -425,7 +431,7 @@ impl<'a> ArchiveBuilder<'a> {
         }
     }
 
-    fn build_with_llvm(&mut self) -> io::Result<()> {
+    fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
         let mut archives = Vec::new();
         let mut strings = Vec::new();
         let mut members = Vec::new();
@@ -482,7 +488,8 @@ impl<'a> ArchiveBuilder<'a> {
             let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
                                                members.len() as libc::size_t,
                                                members.as_ptr(),
-                                               self.should_update_symbols);
+                                               self.should_update_symbols,
+                                               kind);
             let ret = if r != 0 {
                 let err = llvm::LLVMRustGetLastError();
                 let msg = if err.is_null() {
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 2e94c196935..86225874df7 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -120,7 +120,17 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
 
 extern "C" const char*
 LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
-    StringRef buf = child->getBuffer();
+    StringRef buf;
+#if LLVM_VERSION_MINOR >= 7
+    ErrorOr<StringRef> buf_or_err = child->getBuffer();
+    if (buf_or_err.getError()) {
+      LLVMRustSetLastError(buf_or_err.getError().message().c_str());
+      return NULL;
+    }
+    buf = buf_or_err.get();
+#else
+    buf = child->getBuffer();
+#endif
     *size = buf.size();
     return buf.data();
 }
@@ -144,7 +154,8 @@ extern "C" int
 LLVMRustWriteArchive(char *Dst,
                      size_t NumMembers,
                      const LLVMRustArchiveMember **NewMembers,
-                     bool WriteSymbtab) {
+                     bool WriteSymbtab,
+                     Archive::Kind Kind) {
 #if LLVM_VERSION_MINOR >= 7
   std::vector<NewArchiveIterator> Members;
 
@@ -157,7 +168,7 @@ LLVMRustWriteArchive(char *Dst,
       Members.push_back(NewArchiveIterator(Member->child, Member->name));
     }
   }
-  auto pair = writeArchive(Dst, Members, WriteSymbtab);
+  auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, false);
   if (!pair.second)
     return 0;
   LLVMRustSetLastError(pair.second.message().c_str());