Skip to content

Commit 682abf7

Browse files
authored
Auto merge of #34208 - shepmaster:llvm-3.7-linking-intrinsics, r=alexcrichton
Remove linking and intrinsics code made dead by only supporting LLVM 3.7 and up This is mostly based on Alex's throwaway comment: > probably reject those that LLVM just doesn't support... So I'm more than happy to adjust the PR based on how you thought this should look. Also happy to split it into two PRs, one for linking and one for intrinsics. r? @alexcrichton /cc @nagisa @brson
2 parents 945ba12 + 448e254 commit 682abf7

File tree

4 files changed

+32
-291
lines changed

4 files changed

+32
-291
lines changed

src/librustc_llvm/lib.rs

+15
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub use self::DiagnosticSeverity::*;
5454
pub use self::Linkage::*;
5555
pub use self::DLLStorageClassTypes::*;
5656

57+
use std::str::FromStr;
5758
use std::ffi::{CString, CStr};
5859
use std::cell::RefCell;
5960
use std::slice;
@@ -426,6 +427,20 @@ pub enum ArchiveKind {
426427
K_COFF,
427428
}
428429

430+
impl FromStr for ArchiveKind {
431+
type Err = ();
432+
433+
fn from_str(s: &str) -> Result<Self, Self::Err> {
434+
match s {
435+
"gnu" => Ok(ArchiveKind::K_GNU),
436+
"mips64" => Ok(ArchiveKind::K_MIPS64),
437+
"bsd" => Ok(ArchiveKind::K_BSD),
438+
"coff" => Ok(ArchiveKind::K_COFF),
439+
_ => Err(()),
440+
}
441+
}
442+
}
443+
429444
/// Represents the different LLVM passes Rust supports
430445
#[derive(Copy, Clone, PartialEq, Debug)]
431446
#[repr(C)]

src/librustc_trans/back/archive.rs

+15-241
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,17 @@
1010

1111
//! A helper class for dealing with static archives
1212
13-
use std::env;
1413
use std::ffi::{CString, CStr, OsString};
15-
use std::fs::{self, File};
16-
use std::io::prelude::*;
1714
use std::io;
1815
use std::mem;
1916
use std::path::{Path, PathBuf};
20-
use std::process::{Command, Output, Stdio};
2117
use std::ptr;
2218
use std::str;
2319

2420
use libc;
2521
use llvm::archive_ro::{ArchiveRO, Child};
2622
use llvm::{self, ArchiveKind};
2723
use rustc::session::Session;
28-
use rustc_back::tempdir::TempDir;
2924

3025
pub struct ArchiveConfig<'a> {
3126
pub sess: &'a Session,
@@ -41,7 +36,6 @@ pub struct ArchiveConfig<'a> {
4136
#[must_use = "must call build() to finish building the archive"]
4237
pub struct ArchiveBuilder<'a> {
4338
config: ArchiveConfig<'a>,
44-
work_dir: TempDir,
4539
removals: Vec<String>,
4640
additions: Vec<Addition>,
4741
should_update_symbols: bool,
@@ -55,17 +49,10 @@ enum Addition {
5549
},
5650
Archive {
5751
archive: ArchiveRO,
58-
archive_name: String,
5952
skip: Box<FnMut(&str) -> bool>,
6053
},
6154
}
6255

63-
enum Action<'a> {
64-
Remove(&'a [String]),
65-
AddObjects(&'a [&'a PathBuf], bool),
66-
UpdateSymbols,
67-
}
68-
6956
pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
7057
-> PathBuf {
7158
// On Windows, static libraries sometimes show up as libfoo.a and other
@@ -102,7 +89,6 @@ impl<'a> ArchiveBuilder<'a> {
10289
pub fn new(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
10390
ArchiveBuilder {
10491
config: config,
105-
work_dir: TempDir::new("rsar").unwrap(),
10692
removals: Vec::new(),
10793
additions: Vec::new(),
10894
should_update_symbols: false,
@@ -148,7 +134,7 @@ impl<'a> ArchiveBuilder<'a> {
148134
pub fn add_native_library(&mut self, name: &str) {
149135
let location = find_library(name, &self.config.lib_search_paths,
150136
self.config.sess);
151-
self.add_archive(&location, name, |_| false).unwrap_or_else(|e| {
137+
self.add_archive(&location, |_| false).unwrap_or_else(|e| {
152138
self.config.sess.fatal(&format!("failed to add native library {}: {}",
153139
location.to_string_lossy(), e));
154140
});
@@ -172,14 +158,14 @@ impl<'a> ArchiveBuilder<'a> {
172158
let metadata_filename =
173159
self.config.sess.cstore.metadata_filename().to_owned();
174160

175-
self.add_archive(rlib, &name[..], move |fname: &str| {
161+
self.add_archive(rlib, move |fname: &str| {
176162
let skip_obj = lto && fname.starts_with(&obj_start)
177163
&& fname.ends_with(".o");
178164
skip_obj || fname.ends_with(bc_ext) || fname == metadata_filename
179165
})
180166
}
181167

182-
fn add_archive<F>(&mut self, archive: &Path, name: &str, skip: F)
168+
fn add_archive<F>(&mut self, archive: &Path, skip: F)
183169
-> io::Result<()>
184170
where F: FnMut(&str) -> bool + 'static
185171
{
@@ -190,7 +176,6 @@ impl<'a> ArchiveBuilder<'a> {
190176
};
191177
self.additions.push(Addition::Archive {
192178
archive: archive,
193-
archive_name: name.to_string(),
194179
skip: Box::new(skip),
195180
});
196181
Ok(())
@@ -214,234 +199,23 @@ impl<'a> ArchiveBuilder<'a> {
214199
/// Combine the provided files, rlibs, and native libraries into a single
215200
/// `Archive`.
216201
pub fn build(&mut self) {
217-
let res = match self.llvm_archive_kind() {
218-
Some(kind) => self.build_with_llvm(kind),
219-
None => self.build_with_ar_cmd(),
220-
};
221-
if let Err(e) = res {
222-
self.config.sess.fatal(&format!("failed to build archive: {}", e));
223-
}
224-
}
225-
226-
pub fn llvm_archive_kind(&self) -> Option<ArchiveKind> {
227-
if unsafe { llvm::LLVMVersionMinor() < 7 } {
228-
return None
229-
}
230-
231-
// Currently LLVM only supports writing archives in the 'gnu' format.
232-
match &self.config.sess.target.target.options.archive_format[..] {
233-
"gnu" => Some(ArchiveKind::K_GNU),
234-
"mips64" => Some(ArchiveKind::K_MIPS64),
235-
"bsd" => Some(ArchiveKind::K_BSD),
236-
"coff" => Some(ArchiveKind::K_COFF),
237-
_ => None,
238-
}
239-
}
240-
241-
pub fn using_llvm(&self) -> bool {
242-
self.llvm_archive_kind().is_some()
243-
}
244-
245-
fn build_with_ar_cmd(&mut self) -> io::Result<()> {
246-
let removals = mem::replace(&mut self.removals, Vec::new());
247-
let additions = mem::replace(&mut self.additions, Vec::new());
248-
let should_update_symbols = mem::replace(&mut self.should_update_symbols,
249-
false);
250-
251-
// Don't use fs::copy because libs may be installed as read-only and we
252-
// want to modify this archive, so we use `io::copy` to not preserve
253-
// permission bits.
254-
if let Some(ref s) = self.config.src {
255-
io::copy(&mut File::open(s)?,
256-
&mut File::create(&self.config.dst)?)?;
257-
}
258-
259-
if removals.len() > 0 {
260-
self.run(None, Action::Remove(&removals));
261-
}
262-
263-
let mut members = Vec::new();
264-
for addition in additions {
265-
match addition {
266-
Addition::File { path, name_in_archive } => {
267-
let dst = self.work_dir.path().join(&name_in_archive);
268-
fs::copy(&path, &dst)?;
269-
members.push(PathBuf::from(name_in_archive));
270-
}
271-
Addition::Archive { archive, archive_name, mut skip } => {
272-
self.add_archive_members(&mut members, archive,
273-
&archive_name, &mut *skip)?;
274-
}
275-
}
276-
}
277-
278-
// Get an absolute path to the destination, so `ar` will work even
279-
// though we run it from `self.work_dir`.
280-
let mut objects = Vec::new();
281-
let mut total_len = self.config.dst.to_string_lossy().len();
282-
283-
if members.is_empty() {
284-
if should_update_symbols {
285-
self.run(Some(self.work_dir.path()), Action::UpdateSymbols);
286-
}
287-
return Ok(())
288-
}
289-
290-
// Don't allow the total size of `args` to grow beyond 32,000 bytes.
291-
// Windows will raise an error if the argument string is longer than
292-
// 32,768, and we leave a bit of extra space for the program name.
293-
const ARG_LENGTH_LIMIT: usize = 32_000;
294-
295-
for member_name in &members {
296-
let len = member_name.to_string_lossy().len();
297-
298-
// `len + 1` to account for the space that's inserted before each
299-
// argument. (Windows passes command-line arguments as a single
300-
// string, not an array of strings.)
301-
if total_len + len + 1 > ARG_LENGTH_LIMIT {
302-
// Add the archive members seen so far, without updating the
303-
// symbol table.
304-
self.run(Some(self.work_dir.path()),
305-
Action::AddObjects(&objects, false));
306-
307-
objects.clear();
308-
total_len = self.config.dst.to_string_lossy().len();
309-
}
310-
311-
objects.push(member_name);
312-
total_len += len + 1;
313-
}
314-
315-
// Add the remaining archive members, and update the symbol table if
316-
// necessary.
317-
self.run(Some(self.work_dir.path()),
318-
Action::AddObjects(&objects, should_update_symbols));
319-
Ok(())
320-
}
321-
322-
fn add_archive_members(&mut self, members: &mut Vec<PathBuf>,
323-
archive: ArchiveRO, name: &str,
324-
skip: &mut FnMut(&str) -> bool) -> io::Result<()> {
325-
// Next, we must rename all of the inputs to "guaranteed unique names".
326-
// We write each file into `self.work_dir` under its new unique name.
327-
// The reason for this renaming is that archives are keyed off the name
328-
// of the files, so if two files have the same name they will override
329-
// one another in the archive (bad).
330-
//
331-
// We skip any files explicitly desired for skipping, and we also skip
332-
// all SYMDEF files as these are just magical placeholders which get
333-
// re-created when we make a new archive anyway.
334-
for file in archive.iter() {
335-
let file = file.map_err(string_to_io_error)?;
336-
if !is_relevant_child(&file) {
337-
continue
338-
}
339-
let filename = file.name().unwrap();
340-
if skip(filename) {
341-
continue
202+
let kind = match self.llvm_archive_kind() {
203+
Ok(kind) => kind,
204+
Err(kind) => {
205+
self.config.sess.fatal(&format!("Don't know how to build archive of type: {}",
206+
kind));
342207
}
343-
let filename = Path::new(filename).file_name().unwrap()
344-
.to_str().unwrap();
345-
346-
// Archives on unix systems typically do not have slashes in
347-
// filenames as the `ar` utility generally only uses the last
348-
// component of a path for the filename list in the archive. On
349-
// Windows, however, archives assembled with `lib.exe` will preserve
350-
// the full path to the file that was placed in the archive,
351-
// including path separators.
352-
//
353-
// The code below is munging paths so it'll go wrong pretty quickly
354-
// if there's some unexpected slashes in the filename, so here we
355-
// just chop off everything but the filename component. Note that
356-
// this can cause duplicate filenames, but that's also handled below
357-
// as well.
358-
let filename = Path::new(filename).file_name().unwrap()
359-
.to_str().unwrap();
360-
361-
// An archive can contain files of the same name multiple times, so
362-
// we need to be sure to not have them overwrite one another when we
363-
// extract them. Consequently we need to find a truly unique file
364-
// name for us!
365-
let mut new_filename = String::new();
366-
for n in 0.. {
367-
let n = if n == 0 {String::new()} else {format!("-{}", n)};
368-
new_filename = format!("r{}-{}-{}", n, name, filename);
369-
370-
// LLDB (as mentioned in back::link) crashes on filenames of
371-
// exactly
372-
// 16 bytes in length. If we're including an object file with
373-
// exactly 16-bytes of characters, give it some prefix so
374-
// that it's not 16 bytes.
375-
new_filename = if new_filename.len() == 16 {
376-
format!("lldb-fix-{}", new_filename)
377-
} else {
378-
new_filename
379-
};
380-
381-
let present = members.iter().filter_map(|p| {
382-
p.file_name().and_then(|f| f.to_str())
383-
}).any(|s| s == new_filename);
384-
if !present {
385-
break
386-
}
387-
}
388-
let dst = self.work_dir.path().join(&new_filename);
389-
File::create(&dst)?.write_all(file.data())?;
390-
members.push(PathBuf::from(new_filename));
391-
}
392-
Ok(())
393-
}
394-
395-
fn run(&self, cwd: Option<&Path>, action: Action) -> Output {
396-
let abs_dst = env::current_dir().unwrap().join(&self.config.dst);
397-
let ar = &self.config.ar_prog;
398-
let mut cmd = Command::new(ar);
399-
cmd.env("PATH", &self.config.command_path);
400-
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
401-
self.prepare_ar_action(&mut cmd, &abs_dst, action);
402-
info!("{:?}", cmd);
208+
};
403209

404-
if let Some(p) = cwd {
405-
cmd.current_dir(p);
406-
info!("inside {:?}", p.display());
210+
if let Err(e) = self.build_with_llvm(kind) {
211+
self.config.sess.fatal(&format!("failed to build archive: {}", e));
407212
}
408213

409-
let sess = &self.config.sess;
410-
match cmd.spawn() {
411-
Ok(prog) => {
412-
let o = prog.wait_with_output().unwrap();
413-
if !o.status.success() {
414-
sess.struct_err(&format!("{:?} failed with: {}", cmd, o.status))
415-
.note(&format!("stdout ---\n{}",
416-
str::from_utf8(&o.stdout).unwrap()))
417-
.note(&format!("stderr ---\n{}",
418-
str::from_utf8(&o.stderr).unwrap()))
419-
.emit();
420-
sess.abort_if_errors();
421-
}
422-
o
423-
},
424-
Err(e) => {
425-
sess.fatal(&format!("could not exec `{}`: {}",
426-
self.config.ar_prog, e));
427-
}
428-
}
429214
}
430215

431-
fn prepare_ar_action(&self, cmd: &mut Command, dst: &Path, action: Action) {
432-
match action {
433-
Action::Remove(files) => {
434-
cmd.arg("d").arg(dst).args(files);
435-
}
436-
Action::AddObjects(objs, update_symbols) => {
437-
cmd.arg(if update_symbols {"crs"} else {"crS"})
438-
.arg(dst)
439-
.args(objs);
440-
}
441-
Action::UpdateSymbols => {
442-
cmd.arg("s").arg(dst);
443-
}
444-
}
216+
fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
217+
let kind = &self.config.sess.target.target.options.archive_format[..];
218+
kind.parse().map_err(|_| kind)
445219
}
446220

447221
fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
@@ -480,7 +254,7 @@ impl<'a> ArchiveBuilder<'a> {
480254
strings.push(path);
481255
strings.push(name);
482256
}
483-
Addition::Archive { archive, archive_name: _, mut skip } => {
257+
Addition::Archive { archive, mut skip } => {
484258
for child in archive.iter() {
485259
let child = child.map_err(string_to_io_error)?;
486260
if !is_relevant_child(&child) {

0 commit comments

Comments
 (0)