Auto merge of #89092 - bjorn3:sync_cg_clif-2021-09-19, r=bjorn3
Sync rustc_codegen_cranelift Nothing exciting this time. Mostly internal refactorings. r? `@ghost` `@rustbot` label +A-codegen +A-cranelift +T-compiler
This commit is contained in:
commit
b2804655f5
24 changed files with 332 additions and 293 deletions
|
@ -1,17 +1,20 @@
|
|||
//! Creation of ar archives like for the lib and staticlib crate type
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Seek};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
|
||||
use rustc_session::Session;
|
||||
|
||||
use object::{Object, ObjectSymbol, SymbolKind};
|
||||
use object::read::archive::ArchiveFile;
|
||||
use object::{Object, ObjectSymbol, ReadCache, SymbolKind};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ArchiveEntry {
|
||||
FromArchive { archive_index: usize, entry_index: usize },
|
||||
FromArchive { archive_index: usize, file_range: (u64, u64) },
|
||||
File(PathBuf),
|
||||
}
|
||||
|
||||
|
@ -21,29 +24,28 @@ pub(crate) struct ArArchiveBuilder<'a> {
|
|||
use_gnu_style_archive: bool,
|
||||
no_builtin_ranlib: bool,
|
||||
|
||||
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
|
||||
src_archives: Vec<File>,
|
||||
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
|
||||
// the end of an archive for linkers to not get confused.
|
||||
entries: Vec<(String, ArchiveEntry)>,
|
||||
entries: Vec<(Vec<u8>, ArchiveEntry)>,
|
||||
}
|
||||
|
||||
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
||||
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
|
||||
let (src_archives, entries) = if let Some(input) = input {
|
||||
let mut archive = ar::Archive::new(File::open(input).unwrap());
|
||||
let read_cache = ReadCache::new(File::open(input).unwrap());
|
||||
let archive = ArchiveFile::parse(&read_cache).unwrap();
|
||||
let mut entries = Vec::new();
|
||||
|
||||
let mut i = 0;
|
||||
while let Some(entry) = archive.next_entry() {
|
||||
for entry in archive.members() {
|
||||
let entry = entry.unwrap();
|
||||
entries.push((
|
||||
String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
|
||||
ArchiveEntry::FromArchive { archive_index: 0, entry_index: i },
|
||||
entry.name().to_vec(),
|
||||
ArchiveEntry::FromArchive { archive_index: 0, file_range: entry.file_range() },
|
||||
));
|
||||
i += 1;
|
||||
}
|
||||
|
||||
(vec![(input.to_owned(), archive)], entries)
|
||||
(vec![read_cache.into_inner()], entries)
|
||||
} else {
|
||||
(vec![], Vec::new())
|
||||
};
|
||||
|
@ -61,21 +63,21 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
}
|
||||
|
||||
fn src_files(&mut self) -> Vec<String> {
|
||||
self.entries.iter().map(|(name, _)| name.clone()).collect()
|
||||
self.entries.iter().map(|(name, _)| String::from_utf8(name.clone()).unwrap()).collect()
|
||||
}
|
||||
|
||||
fn remove_file(&mut self, name: &str) {
|
||||
let index = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|(entry_name, _)| entry_name == name)
|
||||
.position(|(entry_name, _)| entry_name == name.as_bytes())
|
||||
.expect("Tried to remove file not existing in src archive");
|
||||
self.entries.remove(index);
|
||||
}
|
||||
|
||||
fn add_file(&mut self, file: &Path) {
|
||||
self.entries.push((
|
||||
file.file_name().unwrap().to_str().unwrap().to_string(),
|
||||
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
|
||||
ArchiveEntry::File(file.to_owned()),
|
||||
));
|
||||
}
|
||||
|
@ -84,22 +86,23 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
where
|
||||
F: FnMut(&str) -> bool + 'static,
|
||||
{
|
||||
let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
|
||||
let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?);
|
||||
let archive = ArchiveFile::parse(&read_cache).unwrap();
|
||||
let archive_index = self.src_archives.len();
|
||||
|
||||
let mut i = 0;
|
||||
while let Some(entry) = archive.next_entry() {
|
||||
let entry = entry?;
|
||||
let file_name = String::from_utf8(entry.header().identifier().to_vec())
|
||||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
|
||||
for entry in archive.members() {
|
||||
let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||
let file_name = String::from_utf8(entry.name().to_vec())
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||
if !skip(&file_name) {
|
||||
self.entries
|
||||
.push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
|
||||
self.entries.push((
|
||||
file_name.into_bytes(),
|
||||
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
|
||||
));
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
self.src_archives.push((archive_path.to_owned(), archive));
|
||||
self.src_archives.push(read_cache.into_inner());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -121,14 +124,14 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
// FIXME only read the symbol table of the object files to avoid having to keep all
|
||||
// object files in memory at once, or read them twice.
|
||||
let data = match entry {
|
||||
ArchiveEntry::FromArchive { archive_index, entry_index } => {
|
||||
ArchiveEntry::FromArchive { archive_index, file_range } => {
|
||||
// FIXME read symbols from symtab
|
||||
use std::io::Read;
|
||||
let (ref _src_archive_path, ref mut src_archive) =
|
||||
self.src_archives[archive_index];
|
||||
let mut entry = src_archive.jump_to_entry(entry_index).unwrap();
|
||||
let mut data = Vec::new();
|
||||
entry.read_to_end(&mut data).unwrap();
|
||||
let src_read_cache = &mut self.src_archives[archive_index];
|
||||
|
||||
src_read_cache.seek(io::SeekFrom::Start(file_range.0)).unwrap();
|
||||
let mut data = std::vec::from_elem(0, usize::try_from(file_range.1).unwrap());
|
||||
src_read_cache.read_exact(&mut data).unwrap();
|
||||
|
||||
data
|
||||
}
|
||||
ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| {
|
||||
|
@ -143,7 +146,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
match object::File::parse(&*data) {
|
||||
Ok(object) => {
|
||||
symbol_table.insert(
|
||||
entry_name.as_bytes().to_vec(),
|
||||
entry_name.to_vec(),
|
||||
object
|
||||
.symbols()
|
||||
.filter_map(|symbol| {
|
||||
|
@ -168,7 +171,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
} else {
|
||||
sess.fatal(&format!(
|
||||
"error parsing `{}` during archive creation: {}",
|
||||
entry_name, err
|
||||
String::from_utf8_lossy(&entry_name),
|
||||
err
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
err
|
||||
));
|
||||
}),
|
||||
entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(),
|
||||
entries.iter().map(|(name, _)| name.clone()).collect(),
|
||||
ar::GnuSymbolTableFormat::Size32,
|
||||
symbol_table,
|
||||
)
|
||||
|
@ -210,7 +214,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
|
||||
// Add all files
|
||||
for (entry_name, data) in entries.into_iter() {
|
||||
let header = ar::Header::new(entry_name.into_bytes(), data.len() as u64);
|
||||
let header = ar::Header::new(entry_name, data.len() as u64);
|
||||
match builder {
|
||||
BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
|
||||
BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(),
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
//! Abstraction around the object writing crate
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_session::Session;
|
||||
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_module::FuncId;
|
||||
use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
|
||||
|
||||
use object::write::*;
|
||||
use object::{RelocationEncoding, SectionKind, SymbolFlags};
|
||||
|
||||
use gimli::SectionId;
|
||||
|
||||
use crate::debuginfo::{DebugReloc, DebugRelocName};
|
||||
|
||||
pub(crate) trait WriteMetadata {
|
||||
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>);
|
||||
}
|
||||
|
||||
impl WriteMetadata for object::write::Object {
|
||||
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>) {
|
||||
let segment = self.segment_name(object::write::StandardSegment::Data).to_vec();
|
||||
let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data);
|
||||
let offset = self.append_section_data(section_id, &data, 1);
|
||||
// For MachO and probably PE this is necessary to prevent the linker from throwing away the
|
||||
// .rustc section. For ELF this isn't necessary, but it also doesn't harm.
|
||||
self.add_symbol(object::write::Symbol {
|
||||
name: symbol_name.into_bytes(),
|
||||
value: offset,
|
||||
size: data.len() as u64,
|
||||
kind: object::SymbolKind::Data,
|
||||
scope: object::SymbolScope::Dynamic,
|
||||
weak: false,
|
||||
section: SymbolSection::Section(section_id),
|
||||
flags: SymbolFlags::None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait WriteDebugInfo {
|
||||
type SectionId: Copy;
|
||||
|
||||
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
|
||||
fn add_debug_reloc(
|
||||
&mut self,
|
||||
section_map: &FxHashMap<SectionId, Self::SectionId>,
|
||||
from: &Self::SectionId,
|
||||
reloc: &DebugReloc,
|
||||
);
|
||||
}
|
||||
|
||||
impl WriteDebugInfo for ObjectProduct {
|
||||
type SectionId = (object::write::SectionId, object::write::SymbolId);
|
||||
|
||||
fn add_debug_section(
|
||||
&mut self,
|
||||
id: SectionId,
|
||||
data: Vec<u8>,
|
||||
) -> (object::write::SectionId, object::write::SymbolId) {
|
||||
let name = if self.object.format() == object::BinaryFormat::MachO {
|
||||
id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
|
||||
} else {
|
||||
id.name().to_string()
|
||||
}
|
||||
.into_bytes();
|
||||
|
||||
let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
|
||||
// FIXME use SHT_X86_64_UNWIND for .eh_frame
|
||||
let section_id = self.object.add_section(
|
||||
segment,
|
||||
name,
|
||||
if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
|
||||
);
|
||||
self.object
|
||||
.section_mut(section_id)
|
||||
.set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
|
||||
let symbol_id = self.object.section_symbol(section_id);
|
||||
(section_id, symbol_id)
|
||||
}
|
||||
|
||||
fn add_debug_reloc(
|
||||
&mut self,
|
||||
section_map: &FxHashMap<SectionId, Self::SectionId>,
|
||||
from: &Self::SectionId,
|
||||
reloc: &DebugReloc,
|
||||
) {
|
||||
let (symbol, symbol_offset) = match reloc.name {
|
||||
DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
|
||||
DebugRelocName::Symbol(id) => {
|
||||
let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
|
||||
self.object
|
||||
.symbol_section_and_offset(symbol_id)
|
||||
.expect("Debug reloc for undef sym???")
|
||||
}
|
||||
};
|
||||
self.object
|
||||
.add_relocation(
|
||||
from.0,
|
||||
Relocation {
|
||||
offset: u64::from(reloc.offset),
|
||||
symbol,
|
||||
kind: reloc.kind,
|
||||
encoding: RelocationEncoding::Generic,
|
||||
size: reloc.size * 8,
|
||||
addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> {
|
||||
let triple = crate::target_triple(sess);
|
||||
|
||||
let binary_format = match triple.binary_format {
|
||||
target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
|
||||
target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
|
||||
target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
|
||||
binary_format => sess.fatal(&format!("binary format {} is unsupported", binary_format)),
|
||||
};
|
||||
let architecture = match triple.architecture {
|
||||
target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
|
||||
target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
|
||||
target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
|
||||
target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
|
||||
architecture => {
|
||||
sess.fatal(&format!("target architecture {:?} is unsupported", architecture,))
|
||||
}
|
||||
};
|
||||
let endian = match triple.endianness().unwrap() {
|
||||
target_lexicon::Endianness::Little => object::Endianness::Little,
|
||||
target_lexicon::Endianness::Big => object::Endianness::Big,
|
||||
};
|
||||
|
||||
let mut metadata_object = object::write::Object::new(binary_format, architecture, endian);
|
||||
metadata_object.add_file_symbol(name.as_bytes().to_vec());
|
||||
f(&mut metadata_object);
|
||||
metadata_object.write().unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
|
||||
let mut builder =
|
||||
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
|
||||
// Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
|
||||
// is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
|
||||
// can easily double the amount of time necessary to perform linking.
|
||||
builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false));
|
||||
ObjectModule::new(builder)
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
#![feature(rustc_private, once_cell)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unused_lifetimes)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_driver;
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
//! target crates.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unused_lifetimes)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_interface;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
//! Write the debuginfo into an object file.
|
||||
|
||||
use cranelift_object::ObjectProduct;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
|
||||
use gimli::{RunTimeEndian, SectionId};
|
||||
|
||||
use crate::backend::WriteDebugInfo;
|
||||
|
||||
use super::object::WriteDebugInfo;
|
||||
use super::DebugContext;
|
||||
|
||||
impl DebugContext<'_> {
|
||||
pub(crate) fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
|
||||
pub(crate) fn emit(&mut self, product: &mut ObjectProduct) {
|
||||
let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
|
||||
let root = self.dwarf.unit.root();
|
||||
let root = self.dwarf.unit.get_mut(root);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
mod emit;
|
||||
mod line_info;
|
||||
mod object;
|
||||
mod unwind;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
|
85
compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
Normal file
85
compiler/rustc_codegen_cranelift/src/debuginfo/object.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
use cranelift_module::FuncId;
|
||||
use cranelift_object::ObjectProduct;
|
||||
|
||||
use object::write::{Relocation, StandardSegment};
|
||||
use object::{RelocationEncoding, SectionKind};
|
||||
|
||||
use gimli::SectionId;
|
||||
|
||||
use crate::debuginfo::{DebugReloc, DebugRelocName};
|
||||
|
||||
pub(super) trait WriteDebugInfo {
|
||||
type SectionId: Copy;
|
||||
|
||||
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
|
||||
fn add_debug_reloc(
|
||||
&mut self,
|
||||
section_map: &FxHashMap<SectionId, Self::SectionId>,
|
||||
from: &Self::SectionId,
|
||||
reloc: &DebugReloc,
|
||||
);
|
||||
}
|
||||
|
||||
impl WriteDebugInfo for ObjectProduct {
|
||||
type SectionId = (object::write::SectionId, object::write::SymbolId);
|
||||
|
||||
fn add_debug_section(
|
||||
&mut self,
|
||||
id: SectionId,
|
||||
data: Vec<u8>,
|
||||
) -> (object::write::SectionId, object::write::SymbolId) {
|
||||
let name = if self.object.format() == object::BinaryFormat::MachO {
|
||||
id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info
|
||||
} else {
|
||||
id.name().to_string()
|
||||
}
|
||||
.into_bytes();
|
||||
|
||||
let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
|
||||
// FIXME use SHT_X86_64_UNWIND for .eh_frame
|
||||
let section_id = self.object.add_section(
|
||||
segment,
|
||||
name,
|
||||
if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug },
|
||||
);
|
||||
self.object
|
||||
.section_mut(section_id)
|
||||
.set_data(data, if id == SectionId::EhFrame { 8 } else { 1 });
|
||||
let symbol_id = self.object.section_symbol(section_id);
|
||||
(section_id, symbol_id)
|
||||
}
|
||||
|
||||
fn add_debug_reloc(
|
||||
&mut self,
|
||||
section_map: &FxHashMap<SectionId, Self::SectionId>,
|
||||
from: &Self::SectionId,
|
||||
reloc: &DebugReloc,
|
||||
) {
|
||||
let (symbol, symbol_offset) = match reloc.name {
|
||||
DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
|
||||
DebugRelocName::Symbol(id) => {
|
||||
let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
|
||||
self.object
|
||||
.symbol_section_and_offset(symbol_id)
|
||||
.expect("Debug reloc for undef sym???")
|
||||
}
|
||||
};
|
||||
self.object
|
||||
.add_relocation(
|
||||
from.0,
|
||||
Relocation {
|
||||
offset: u64::from(reloc.offset),
|
||||
symbol,
|
||||
kind: reloc.kind,
|
||||
encoding: RelocationEncoding::Generic,
|
||||
size: reloc.size * 8,
|
||||
addend: i64::try_from(symbol_offset).unwrap() + reloc.addend,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
|
@ -4,10 +4,11 @@ use crate::prelude::*;
|
|||
|
||||
use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa};
|
||||
|
||||
use cranelift_object::ObjectProduct;
|
||||
use gimli::write::{Address, CieId, EhFrame, FrameTable, Section};
|
||||
use gimli::RunTimeEndian;
|
||||
|
||||
use crate::backend::WriteDebugInfo;
|
||||
use super::object::WriteDebugInfo;
|
||||
|
||||
pub(crate) struct UnwindContext {
|
||||
endian: RunTimeEndian,
|
||||
|
@ -55,7 +56,7 @@ impl UnwindContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn emit<P: WriteDebugInfo>(self, product: &mut P) {
|
||||
pub(crate) fn emit(self, product: &mut ObjectProduct) {
|
||||
let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(self.endian));
|
||||
self.frame_table.write_eh_frame(&mut eh_frame).unwrap();
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@ use rustc_middle::middle::cstore::EncodedMetadata;
|
|||
use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
|
||||
use rustc_session::cgu_reuse_tracker::CguReuse;
|
||||
use rustc_session::config::{DebugInfo, OutputType};
|
||||
use rustc_session::Session;
|
||||
|
||||
use cranelift_object::ObjectModule;
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_object::{ObjectBuilder, ObjectModule};
|
||||
|
||||
use crate::{prelude::*, BackendConfig};
|
||||
|
||||
|
@ -24,6 +26,16 @@ impl<HCX> HashStable<HCX> for ModuleCodegenResult {
|
|||
}
|
||||
}
|
||||
|
||||
fn make_module(sess: &Session, isa: Box<dyn TargetIsa>, name: String) -> ObjectModule {
|
||||
let mut builder =
|
||||
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();
|
||||
// Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size
|
||||
// is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections
|
||||
// can easily double the amount of time necessary to perform linking.
|
||||
builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false));
|
||||
ObjectModule::new(builder)
|
||||
}
|
||||
|
||||
fn emit_module(
|
||||
tcx: TyCtxt<'_>,
|
||||
backend_config: &BackendConfig,
|
||||
|
@ -104,7 +116,7 @@ fn module_codegen(
|
|||
let mono_items = cgu.items_in_deterministic_order(tcx);
|
||||
|
||||
let isa = crate::build_isa(tcx.sess, &backend_config);
|
||||
let mut module = crate::backend::make_module(tcx.sess, isa, cgu_name.as_str().to_string());
|
||||
let mut module = make_module(tcx.sess, isa, cgu_name.as_str().to_string());
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
|
@ -227,8 +239,7 @@ pub(crate) fn run_aot(
|
|||
tcx.sess.abort_if_errors();
|
||||
|
||||
let isa = crate::build_isa(tcx.sess, &backend_config);
|
||||
let mut allocator_module =
|
||||
crate::backend::make_module(tcx.sess, isa, "allocator_shim".to_string());
|
||||
let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string());
|
||||
assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type());
|
||||
let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa(), true);
|
||||
let created_alloc_shim =
|
||||
|
@ -266,9 +277,7 @@ pub(crate) fn run_aot(
|
|||
let tmp_file =
|
||||
tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
|
||||
|
||||
let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| {
|
||||
crate::metadata::write_metadata(tcx, object);
|
||||
});
|
||||
let obj = crate::metadata::new_metadata_object(tcx, &metadata_cgu_name, &metadata);
|
||||
|
||||
if let Err(err) = std::fs::write(&tmp_file, obj) {
|
||||
tcx.sess.fatal(&format!("error writing metadata object file: {}", err));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)]
|
||||
#![feature(rustc_private, decl_macro)]
|
||||
#![cfg_attr(feature = "jit", feature(never_type, vec_into_raw_parts, once_cell))]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unused_lifetimes)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
@ -44,7 +45,6 @@ mod abi;
|
|||
mod allocator;
|
||||
mod analyze;
|
||||
mod archive;
|
||||
mod backend;
|
||||
mod base;
|
||||
mod cast;
|
||||
mod codegen_i128;
|
||||
|
|
|
@ -1,20 +1,72 @@
|
|||
//! Writing of the rustc metadata for dylibs
|
||||
|
||||
use object::write::{Object, StandardSegment, Symbol, SymbolSection};
|
||||
use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope};
|
||||
|
||||
use rustc_middle::middle::cstore::EncodedMetadata;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use crate::backend::WriteMetadata;
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
|
||||
pub(crate) fn write_metadata<O: WriteMetadata>(tcx: TyCtxt<'_>, object: &mut O) {
|
||||
pub(crate) fn new_metadata_object(tcx: TyCtxt<'_>, cgu_name: &str, metadata: &EncodedMetadata) -> Vec<u8> {
|
||||
use snap::write::FrameEncoder;
|
||||
use std::io::Write;
|
||||
|
||||
let metadata = tcx.encode_metadata();
|
||||
let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
|
||||
FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data).unwrap();
|
||||
|
||||
object.add_rustc_section(
|
||||
rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx),
|
||||
compressed,
|
||||
);
|
||||
let triple = crate::target_triple(tcx.sess);
|
||||
|
||||
let binary_format = match triple.binary_format {
|
||||
target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
|
||||
target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
|
||||
target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
|
||||
binary_format => tcx.sess.fatal(&format!("binary format {} is unsupported", binary_format)),
|
||||
};
|
||||
let architecture = match triple.architecture {
|
||||
target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
|
||||
target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
|
||||
target_lexicon::Architecture::Avr => object::Architecture::Avr,
|
||||
target_lexicon::Architecture::Hexagon => object::Architecture::Hexagon,
|
||||
target_lexicon::Architecture::Mips32(_) => object::Architecture::Mips,
|
||||
target_lexicon::Architecture::Mips64(_) => object::Architecture::Mips64,
|
||||
target_lexicon::Architecture::Msp430 => object::Architecture::Msp430,
|
||||
target_lexicon::Architecture::Powerpc => object::Architecture::PowerPc,
|
||||
target_lexicon::Architecture::Powerpc64 => object::Architecture::PowerPc64,
|
||||
target_lexicon::Architecture::Powerpc64le => todo!(),
|
||||
target_lexicon::Architecture::Riscv32(_) => object::Architecture::Riscv32,
|
||||
target_lexicon::Architecture::Riscv64(_) => object::Architecture::Riscv64,
|
||||
target_lexicon::Architecture::S390x => object::Architecture::S390x,
|
||||
target_lexicon::Architecture::Sparc64 => object::Architecture::Sparc64,
|
||||
target_lexicon::Architecture::Sparcv9 => object::Architecture::Sparc64,
|
||||
target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
|
||||
target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
|
||||
architecture => {
|
||||
tcx.sess.fatal(&format!("target architecture {:?} is unsupported", architecture,))
|
||||
}
|
||||
};
|
||||
let endian = match triple.endianness().unwrap() {
|
||||
target_lexicon::Endianness::Little => object::Endianness::Little,
|
||||
target_lexicon::Endianness::Big => object::Endianness::Big,
|
||||
};
|
||||
|
||||
let mut object = Object::new(binary_format, architecture, endian);
|
||||
object.add_file_symbol(cgu_name.as_bytes().to_vec());
|
||||
|
||||
let segment = object.segment_name(StandardSegment::Data).to_vec();
|
||||
let section_id = object.add_section(segment, b".rustc".to_vec(), SectionKind::Data);
|
||||
let offset = object.append_section_data(section_id, &compressed, 1);
|
||||
// For MachO and probably PE this is necessary to prevent the linker from throwing away the
|
||||
// .rustc section. For ELF this isn't necessary, but it also doesn't harm.
|
||||
object.add_symbol(Symbol {
|
||||
name: rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx).into_bytes(),
|
||||
value: offset,
|
||||
size: compressed.len() as u64,
|
||||
kind: SymbolKind::Data,
|
||||
scope: SymbolScope::Dynamic,
|
||||
weak: false,
|
||||
section: SymbolSection::Section(section_id),
|
||||
flags: SymbolFlags::None,
|
||||
});
|
||||
|
||||
object.write().unwrap()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue