Revert "Use callback-based interface to load ThinLTO import data into rustc."
This reverts commit e045a6cd8c
.
This commit is contained in:
parent
99140df0bd
commit
b822e699c3
4 changed files with 94 additions and 56 deletions
|
@ -805,7 +805,7 @@ pub struct ThinLTOImports {
|
||||||
|
|
||||||
impl ThinLTOImports {
|
impl ThinLTOImports {
|
||||||
|
|
||||||
pub fn new() -> ThinLTOImports {
|
pub fn new_empty() -> ThinLTOImports {
|
||||||
ThinLTOImports {
|
ThinLTOImports {
|
||||||
imports: FxHashMap(),
|
imports: FxHashMap(),
|
||||||
}
|
}
|
||||||
|
@ -813,46 +813,58 @@ impl ThinLTOImports {
|
||||||
|
|
||||||
/// Load the ThinLTO import map from ThinLTOData.
|
/// Load the ThinLTO import map from ThinLTOData.
|
||||||
unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
|
unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
|
||||||
|
let raw_data: *const llvm::ThinLTOModuleImports =
|
||||||
|
llvm::LLVMRustGetThinLTOModuleImports(data);
|
||||||
|
|
||||||
fn module_name_to_str(c_str: &CStr) -> &str {
|
assert!(!raw_data.is_null());
|
||||||
match c_str.to_str() {
|
|
||||||
Ok(s) => s,
|
let mut imports = FxHashMap();
|
||||||
Err(e) => {
|
let mut module_ptr = raw_data;
|
||||||
bug!("Encountered non-utf8 LLVM module name `{}`: {}",
|
let mut module_index = 0;
|
||||||
c_str.to_string_lossy(),
|
|
||||||
e)
|
loop {
|
||||||
}
|
let mut entry_ptr: *const llvm::ThinLTOModuleName = *module_ptr;
|
||||||
}
|
|
||||||
|
if entry_ptr.is_null() {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn imported_module_callback(payload: *mut libc::c_void,
|
let importing_module_name = CStr::from_ptr(*entry_ptr)
|
||||||
importing_module_name: *const libc::c_char,
|
.to_str()
|
||||||
imported_module_name: *const libc::c_char) {
|
.expect("Non-utf8 LLVM module name encountered")
|
||||||
let map = &mut* (payload as *mut ThinLTOImports);
|
.to_owned();
|
||||||
|
|
||||||
let importing_module_name = CStr::from_ptr(importing_module_name);
|
entry_ptr = entry_ptr.offset(1);
|
||||||
let importing_module_name = module_name_to_str(&importing_module_name);
|
|
||||||
let imported_module_name = CStr::from_ptr(imported_module_name);
|
|
||||||
let imported_module_name = module_name_to_str(&imported_module_name);
|
|
||||||
|
|
||||||
if !map.imports.contains_key(importing_module_name) {
|
let mut imported_modules = vec![];
|
||||||
map.imports.insert(importing_module_name.to_owned(), vec![]);
|
|
||||||
|
loop {
|
||||||
|
let imported_module_name = *entry_ptr;
|
||||||
|
|
||||||
|
if imported_module_name.is_null() {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
map.imports
|
let imported_module_name = CStr::from_ptr(imported_module_name)
|
||||||
.get_mut(importing_module_name)
|
.to_str()
|
||||||
.unwrap()
|
.expect("Non-utf8 LLVM module name encountered")
|
||||||
.push(imported_module_name.to_owned());
|
.to_owned();
|
||||||
|
|
||||||
|
imported_modules.push(imported_module_name);
|
||||||
|
entry_ptr = entry_ptr.offset(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut map = ThinLTOImports {
|
imports.insert(importing_module_name, imported_modules);
|
||||||
imports: FxHashMap(),
|
|
||||||
};
|
|
||||||
|
|
||||||
llvm::LLVMRustGetThinLTOModuleImports(data,
|
module_ptr = module_ptr.offset(1);
|
||||||
imported_module_callback,
|
module_index += 1;
|
||||||
&mut map as *mut _ as *mut libc::c_void);
|
}
|
||||||
map
|
|
||||||
|
assert_eq!(module_index, imports.len());
|
||||||
|
|
||||||
|
ThinLTOImports {
|
||||||
|
imports
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_to_file(&self, path: &Path) -> io::Result<()> {
|
pub fn save_to_file(&self, path: &Path) -> io::Result<()> {
|
||||||
|
|
|
@ -1360,7 +1360,7 @@ fn load_thin_lto_imports(sess: &Session) -> lto::ThinLTOImports {
|
||||||
);
|
);
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return lto::ThinLTOImports::new();
|
return lto::ThinLTOImports::new_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
match lto::ThinLTOImports::load_from_file(&path) {
|
match lto::ThinLTOImports::load_from_file(&path) {
|
||||||
|
|
|
@ -351,9 +351,10 @@ pub enum ThinLTOData {}
|
||||||
/// LLVMRustThinLTOBuffer
|
/// LLVMRustThinLTOBuffer
|
||||||
pub enum ThinLTOBuffer {}
|
pub enum ThinLTOBuffer {}
|
||||||
|
|
||||||
// LLVMRustModuleNameCallback
|
/// LLVMRustThinLTOModuleName
|
||||||
pub type ThinLTOModuleNameCallback =
|
pub type ThinLTOModuleName = *const c_char;
|
||||||
unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char);
|
/// LLVMRustThinLTOModuleImports
|
||||||
|
pub type ThinLTOModuleImports = *const ThinLTOModuleName;
|
||||||
|
|
||||||
/// LLVMRustThinLTOModule
|
/// LLVMRustThinLTOModule
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -1785,9 +1786,7 @@ extern "C" {
|
||||||
) -> bool;
|
) -> bool;
|
||||||
pub fn LLVMRustGetThinLTOModuleImports(
|
pub fn LLVMRustGetThinLTOModuleImports(
|
||||||
Data: *const ThinLTOData,
|
Data: *const ThinLTOData,
|
||||||
ModuleNameCallback: ThinLTOModuleNameCallback,
|
) -> *const ThinLTOModuleImports;
|
||||||
CallbackPayload: *mut c_void,
|
|
||||||
);
|
|
||||||
pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
|
pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
|
||||||
pub fn LLVMRustParseBitcodeForThinLTO(
|
pub fn LLVMRustParseBitcodeForThinLTO(
|
||||||
Context: ContextRef,
|
Context: ContextRef,
|
||||||
|
|
|
@ -798,6 +798,11 @@ LLVMRustPGOAvailable() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We encode the ThinLTO module import map as a nested null-terminated list to
|
||||||
|
// get it into Rust.
|
||||||
|
typedef const char* LLVMRustThinLTOModuleName;
|
||||||
|
typedef LLVMRustThinLTOModuleName* LLVMRustThinLTOModuleImports;
|
||||||
|
|
||||||
#if LLVM_VERSION_GE(4, 0)
|
#if LLVM_VERSION_GE(4, 0)
|
||||||
|
|
||||||
// Here you'll find an implementation of ThinLTO as used by the Rust compiler
|
// Here you'll find an implementation of ThinLTO as used by the Rust compiler
|
||||||
|
@ -1099,28 +1104,50 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
|
/// Converts the LLVMRustThinLTOData::ImportLists map into a nested list. The
|
||||||
const char*, // importing module name
|
/// first level is a null-terminated array with an entry for each module. Each
|
||||||
const char*); // imported module name
|
/// entry is a pointer that points to a null-termined array of module names. The
|
||||||
|
/// first entry is always the name of the *importing* module, the following
|
||||||
|
/// entries are the names of the modules it imports from. Each module name is
|
||||||
|
/// a regular C string.
|
||||||
|
extern "C" LLVMRustThinLTOModuleImports*
|
||||||
|
LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *Data) {
|
||||||
|
// Allocate number of module +1. This is a null-terminated array.
|
||||||
|
LLVMRustThinLTOModuleImports* thinLTOModuleImports =
|
||||||
|
new LLVMRustThinLTOModuleImports[Data->ImportLists.size() + 1];
|
||||||
|
size_t module_index = 0;
|
||||||
|
|
||||||
// Calls `module_name_callback` for each module import done by ThinLTO.
|
for (const auto & module : Data->ImportLists) {
|
||||||
// The callback is provided with regular null-terminated C strings.
|
StringRef module_id = module.getKey();
|
||||||
extern "C" void
|
const auto& imports = module.getValue();
|
||||||
LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *data,
|
|
||||||
LLVMRustModuleNameCallback module_name_callback,
|
|
||||||
void* callback_payload) {
|
|
||||||
for (const auto& importing_module : data->ImportLists) {
|
|
||||||
const std::string importing_module_id = importing_module.getKey().str();
|
|
||||||
|
|
||||||
const auto& imports = importing_module.getValue();
|
// Allocate number of imported module + 2, one extra for the name of the
|
||||||
|
// importing module and another one for null-termination.
|
||||||
|
LLVMRustThinLTOModuleImports imports_array =
|
||||||
|
new LLVMRustThinLTOModuleName[imports.size() + 2];
|
||||||
|
|
||||||
for (const auto& imported_module : imports) {
|
// The first value is always the name of the *importing* module.
|
||||||
const std::string imported_module_id = imported_module.getKey().str();
|
imports_array[0] = strndup(module_id.data(), module_id.size());
|
||||||
module_name_callback(callback_payload,
|
|
||||||
importing_module_id.c_str(),
|
size_t imports_array_index = 1;
|
||||||
imported_module_id.c_str());
|
for (const auto imported_module_id : imports.keys()) {
|
||||||
|
// The following values are the names of the imported modules.
|
||||||
|
imports_array[imports_array_index] = strndup(imported_module_id.data(),
|
||||||
|
imported_module_id.size());
|
||||||
|
imports_array_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(imports_array_index == imports.size() + 1);
|
||||||
|
imports_array[imports_array_index] = nullptr;
|
||||||
|
|
||||||
|
thinLTOModuleImports[module_index] = imports_array;
|
||||||
|
module_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(module_index == Data->ImportLists.size());
|
||||||
|
thinLTOModuleImports[module_index] = nullptr;
|
||||||
|
|
||||||
|
return thinLTOModuleImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This struct and various functions are sort of a hack right now, but the
|
// This struct and various functions are sort of a hack right now, but the
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue