Revert "Use callback-based interface to load ThinLTO import data into rustc."

This reverts commit e045a6cd8c.
This commit is contained in:
Michael Woerister 2018-07-16 08:57:49 +02:00
parent 99140df0bd
commit b822e699c3
4 changed files with 94 additions and 56 deletions

View File

@ -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;
}
let importing_module_name = CStr::from_ptr(*entry_ptr)
.to_str()
.expect("Non-utf8 LLVM module name encountered")
.to_owned();
entry_ptr = entry_ptr.offset(1);
let mut imported_modules = vec![];
loop {
let imported_module_name = *entry_ptr;
if imported_module_name.is_null() {
break
} }
}
}
unsafe extern "C" fn imported_module_callback(payload: *mut libc::c_void, let imported_module_name = CStr::from_ptr(imported_module_name)
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); imported_modules.push(imported_module_name);
let importing_module_name = module_name_to_str(&importing_module_name); entry_ptr = entry_ptr.offset(1);
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) {
map.imports.insert(importing_module_name.to_owned(), vec![]);
} }
map.imports imports.insert(importing_module_name, imported_modules);
.get_mut(importing_module_name)
.unwrap() module_ptr = module_ptr.offset(1);
.push(imported_module_name.to_owned()); module_index += 1;
} }
let mut map = ThinLTOImports { assert_eq!(module_index, imports.len());
imports: FxHashMap(),
};
llvm::LLVMRustGetThinLTOModuleImports(data, ThinLTOImports {
imported_module_callback, imports
&mut map as *mut _ as *mut libc::c_void); }
map
} }
pub fn save_to_file(&self, path: &Path) -> io::Result<()> { pub fn save_to_file(&self, path: &Path) -> io::Result<()> {

View File

@ -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) {

View File

@ -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,

View File

@ -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