Remove LlvmArchiveBuilder and supporting code/bindings
This commit is contained in:
@@ -1,104 +1,21 @@
|
||||
//! A helper class for dealing with static archives
|
||||
|
||||
use std::ffi::{CStr, CString, c_char, c_void};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{io, mem, ptr, str};
|
||||
use std::ffi::{CStr, c_char, c_void};
|
||||
use std::io;
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder,
|
||||
DEFAULT_OBJECT_READER, ObjectReader, UnknownArchiveKind, try_extract_macho_fat_archive,
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, ObjectReader,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, last_error};
|
||||
|
||||
/// Helper for adding many files to an archive.
|
||||
#[must_use = "must call build() to finish building the archive"]
|
||||
pub(crate) struct LlvmArchiveBuilder<'a> {
|
||||
sess: &'a Session,
|
||||
additions: Vec<Addition>,
|
||||
}
|
||||
|
||||
enum Addition {
|
||||
File { path: PathBuf, name_in_archive: String },
|
||||
Archive { path: PathBuf, archive: ArchiveRO, skip: Box<dyn FnMut(&str) -> bool> },
|
||||
}
|
||||
|
||||
impl Addition {
|
||||
fn path(&self) -> &Path {
|
||||
match self {
|
||||
Addition::File { path, .. } | Addition::Archive { path, .. } => path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_relevant_child(c: &Child<'_>) -> bool {
|
||||
match c.name() {
|
||||
Some(name) => !name.contains("SYMDEF"),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> {
|
||||
fn add_archive(
|
||||
&mut self,
|
||||
archive: &Path,
|
||||
skip: Box<dyn FnMut(&str) -> bool + 'static>,
|
||||
) -> io::Result<()> {
|
||||
let mut archive = archive.to_path_buf();
|
||||
if self.sess.target.llvm_target.contains("-apple-macosx") {
|
||||
if let Some(new_archive) = try_extract_macho_fat_archive(self.sess, &archive)? {
|
||||
archive = new_archive
|
||||
}
|
||||
}
|
||||
let archive_ro = match ArchiveRO::open(&archive) {
|
||||
Ok(ar) => ar,
|
||||
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
||||
};
|
||||
if self.additions.iter().any(|ar| ar.path() == archive) {
|
||||
return Ok(());
|
||||
}
|
||||
self.additions.push(Addition::Archive {
|
||||
path: archive,
|
||||
archive: archive_ro,
|
||||
skip: Box::new(skip),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds an arbitrary file to this archive
|
||||
fn add_file(&mut self, file: &Path) {
|
||||
let name = file.file_name().unwrap().to_str().unwrap();
|
||||
self.additions
|
||||
.push(Addition::File { path: file.to_path_buf(), name_in_archive: name.to_owned() });
|
||||
}
|
||||
|
||||
/// Combine the provided files, rlibs, and native libraries into a single
|
||||
/// `Archive`.
|
||||
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||
match self.build_with_llvm(output) {
|
||||
Ok(any_members) => any_members,
|
||||
Err(error) => {
|
||||
self.sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::llvm;
|
||||
|
||||
pub(crate) struct LlvmArchiveBuilderBuilder;
|
||||
|
||||
impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
||||
// Keeping LlvmArchiveBuilder around in case of a regression caused by using
|
||||
// ArArchiveBuilder.
|
||||
// FIXME(#128955) remove a couple of months after #128936 gets merged in case
|
||||
// no regression is found.
|
||||
if false {
|
||||
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
|
||||
} else {
|
||||
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
|
||||
}
|
||||
// Use the `object` crate to build archives, with a little bit of help from LLVM.
|
||||
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,91 +95,3 @@ fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
|
||||
fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
|
||||
unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
|
||||
}
|
||||
|
||||
impl<'a> LlvmArchiveBuilder<'a> {
|
||||
fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
|
||||
let kind = &*self.sess.target.archive_format;
|
||||
let kind = kind
|
||||
.parse::<ArchiveKind>()
|
||||
.map_err(|_| kind)
|
||||
.unwrap_or_else(|kind| self.sess.dcx().emit_fatal(UnknownArchiveKind { kind }));
|
||||
|
||||
let mut additions = mem::take(&mut self.additions);
|
||||
// Values in the `members` list below will contain pointers to the strings allocated here.
|
||||
// So they need to get dropped after all elements of `members` get freed.
|
||||
let mut strings = Vec::new();
|
||||
let mut members = Vec::new();
|
||||
|
||||
let dst = CString::new(output.to_str().unwrap())?;
|
||||
|
||||
unsafe {
|
||||
for addition in &mut additions {
|
||||
match addition {
|
||||
Addition::File { path, name_in_archive } => {
|
||||
let path = CString::new(path.to_str().unwrap())?;
|
||||
let name = CString::new(name_in_archive.as_bytes())?;
|
||||
members.push(llvm::LLVMRustArchiveMemberNew(
|
||||
path.as_ptr(),
|
||||
name.as_ptr(),
|
||||
None,
|
||||
));
|
||||
strings.push(path);
|
||||
strings.push(name);
|
||||
}
|
||||
Addition::Archive { archive, skip, .. } => {
|
||||
for child in archive.iter() {
|
||||
let child = child.map_err(string_to_io_error)?;
|
||||
if !is_relevant_child(&child) {
|
||||
continue;
|
||||
}
|
||||
let child_name = child.name().unwrap();
|
||||
if skip(child_name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// It appears that LLVM's archive writer is a little
|
||||
// buggy if the name we pass down isn't just the
|
||||
// filename component, so chop that off here and
|
||||
// pass it in.
|
||||
//
|
||||
// See LLVM bug 25877 for more info.
|
||||
let child_name =
|
||||
Path::new(child_name).file_name().unwrap().to_str().unwrap();
|
||||
let name = CString::new(child_name)?;
|
||||
let m = llvm::LLVMRustArchiveMemberNew(
|
||||
ptr::null(),
|
||||
name.as_ptr(),
|
||||
Some(child.raw),
|
||||
);
|
||||
members.push(m);
|
||||
strings.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let r = llvm::LLVMRustWriteArchive(
|
||||
dst.as_ptr(),
|
||||
members.len() as libc::size_t,
|
||||
members.as_ptr() as *const &_,
|
||||
true,
|
||||
kind,
|
||||
self.sess.target.arch == "arm64ec",
|
||||
);
|
||||
let ret = if r.into_result().is_err() {
|
||||
let msg = last_error().unwrap_or_else(|| "failed to write archive".into());
|
||||
Err(io::Error::new(io::ErrorKind::Other, msg))
|
||||
} else {
|
||||
Ok(!members.is_empty())
|
||||
};
|
||||
for member in members {
|
||||
llvm::LLVMRustArchiveMemberFree(member);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_io_error(s: String) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}"))
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
//! A wrapper around LLVM's archive (.a) code
|
||||
|
||||
use std::path::Path;
|
||||
use std::{slice, str};
|
||||
|
||||
use rustc_fs_util::path_to_c_string;
|
||||
|
||||
pub(crate) struct ArchiveRO {
|
||||
pub raw: &'static mut super::Archive,
|
||||
}
|
||||
|
||||
unsafe impl Send for ArchiveRO {}
|
||||
|
||||
pub(crate) struct Iter<'a> {
|
||||
raw: &'a mut super::ArchiveIterator<'a>,
|
||||
}
|
||||
|
||||
pub(crate) struct Child<'a> {
|
||||
pub raw: &'a mut super::ArchiveChild<'a>,
|
||||
}
|
||||
|
||||
impl ArchiveRO {
|
||||
/// Opens a static archive for read-only purposes. This is more optimized
|
||||
/// than the `open` method because it uses LLVM's internal `Archive` class
|
||||
/// rather than shelling out to `ar` for everything.
|
||||
///
|
||||
/// If this archive is used with a mutable method, then an error will be
|
||||
/// raised.
|
||||
pub(crate) fn open(dst: &Path) -> Result<ArchiveRO, String> {
|
||||
unsafe {
|
||||
let s = path_to_c_string(dst);
|
||||
let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| {
|
||||
super::last_error().unwrap_or_else(|| "failed to open archive".to_owned())
|
||||
})?;
|
||||
Ok(ArchiveRO { raw: ar })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn iter(&self) -> Iter<'_> {
|
||||
unsafe { Iter { raw: super::LLVMRustArchiveIteratorNew(self.raw) } }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ArchiveRO {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
super::LLVMRustDestroyArchive(&mut *(self.raw as *mut _));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = Result<Child<'a>, String>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<Child<'a>, String>> {
|
||||
unsafe {
|
||||
match super::LLVMRustArchiveIteratorNext(self.raw) {
|
||||
Some(raw) => Some(Ok(Child { raw })),
|
||||
None => super::last_error().map(Err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Iter<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
super::LLVMRustArchiveIteratorFree(&mut *(self.raw as *mut _));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Child<'a> {
|
||||
pub(crate) fn name(&self) -> Option<&'a str> {
|
||||
unsafe {
|
||||
let mut name_len = 0;
|
||||
let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len);
|
||||
if name_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize);
|
||||
str::from_utf8(name).ok().map(|s| s.trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Child<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
super::LLVMRustArchiveChildFree(&mut *(self.raw as *mut _));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -610,17 +610,6 @@ pub(crate) enum DiagnosticLevel {
|
||||
Remark,
|
||||
}
|
||||
|
||||
/// LLVMRustArchiveKind
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub(crate) enum ArchiveKind {
|
||||
K_GNU,
|
||||
K_BSD,
|
||||
K_DARWIN,
|
||||
K_COFF,
|
||||
K_AIXBIG,
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
// LLVMRustThinLTOData
|
||||
pub(crate) type ThinLTOData;
|
||||
@@ -769,19 +758,12 @@ pub(crate) struct Builder<'a>(InvariantOpaque<'a>);
|
||||
pub(crate) struct PassManager<'a>(InvariantOpaque<'a>);
|
||||
unsafe extern "C" {
|
||||
pub type TargetMachine;
|
||||
pub(crate) type Archive;
|
||||
}
|
||||
#[repr(C)]
|
||||
pub(crate) struct ArchiveIterator<'a>(InvariantOpaque<'a>);
|
||||
#[repr(C)]
|
||||
pub(crate) struct ArchiveChild<'a>(InvariantOpaque<'a>);
|
||||
unsafe extern "C" {
|
||||
pub(crate) type Twine;
|
||||
pub(crate) type DiagnosticInfo;
|
||||
pub(crate) type SMDiagnostic;
|
||||
}
|
||||
#[repr(C)]
|
||||
pub(crate) struct RustArchiveMember<'a>(InvariantOpaque<'a>);
|
||||
/// Opaque pointee of `LLVMOperandBundleRef`.
|
||||
#[repr(C)]
|
||||
pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>);
|
||||
@@ -2505,19 +2487,6 @@ unsafe extern "C" {
|
||||
pub(crate) fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
|
||||
pub(crate) fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
|
||||
|
||||
pub(crate) fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
|
||||
pub(crate) fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>;
|
||||
pub(crate) fn LLVMRustArchiveIteratorNext<'a>(
|
||||
AIR: &ArchiveIterator<'a>,
|
||||
) -> Option<&'a mut ArchiveChild<'a>>;
|
||||
pub(crate) fn LLVMRustArchiveChildName(
|
||||
ACR: &ArchiveChild<'_>,
|
||||
size: &mut size_t,
|
||||
) -> *const c_char;
|
||||
pub(crate) fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>);
|
||||
pub(crate) fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>);
|
||||
pub(crate) fn LLVMRustDestroyArchive(AR: &'static mut Archive);
|
||||
|
||||
pub(crate) fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
|
||||
|
||||
pub(crate) fn LLVMRustUnpackOptimizationDiagnostic<'a>(
|
||||
@@ -2555,21 +2524,6 @@ unsafe extern "C" {
|
||||
num_ranges: &mut usize,
|
||||
) -> bool;
|
||||
|
||||
pub(crate) fn LLVMRustWriteArchive(
|
||||
Dst: *const c_char,
|
||||
NumMembers: size_t,
|
||||
Members: *const &RustArchiveMember<'_>,
|
||||
WriteSymbtab: bool,
|
||||
Kind: ArchiveKind,
|
||||
isEC: bool,
|
||||
) -> LLVMRustResult;
|
||||
pub(crate) fn LLVMRustArchiveMemberNew<'a>(
|
||||
Filename: *const c_char,
|
||||
Name: *const c_char,
|
||||
Child: Option<&ArchiveChild<'a>>,
|
||||
) -> &'a mut RustArchiveMember<'a>;
|
||||
pub(crate) fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>);
|
||||
|
||||
pub(crate) fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
|
||||
|
||||
pub(crate) fn LLVMRustPositionBuilderPastAllocas<'a>(B: &Builder<'a>, Fn: &'a Value);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::num::NonZero;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use libc::c_uint;
|
||||
@@ -16,7 +15,6 @@ pub(crate) use self::MetadataType::*;
|
||||
pub(crate) use self::ffi::*;
|
||||
use crate::common::AsCCharPtr;
|
||||
|
||||
pub(crate) mod archive_ro;
|
||||
pub(crate) mod diagnostic;
|
||||
pub(crate) mod enzyme_ffi;
|
||||
mod ffi;
|
||||
@@ -152,21 +150,6 @@ pub(crate) enum CodeGenOptSize {
|
||||
CodeGenOptSizeAggressive = 2,
|
||||
}
|
||||
|
||||
impl FromStr for ArchiveKind {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"gnu" => Ok(ArchiveKind::K_GNU),
|
||||
"bsd" => Ok(ArchiveKind::K_BSD),
|
||||
"darwin" => Ok(ArchiveKind::K_DARWIN),
|
||||
"coff" => Ok(ArchiveKind::K_COFF),
|
||||
"aix_big" => Ok(ArchiveKind::K_AIXBIG),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn SetInstructionCallConv(instr: &Value, cc: CallConv) {
|
||||
unsafe {
|
||||
LLVMSetInstructionCallConv(instr, cc as c_uint);
|
||||
|
||||
Reference in New Issue
Block a user