Skip to content

Commit e045a6c

Browse files
Use callback-based interface to load ThinLTO import data into rustc.
1 parent dd3f445 commit e045a6c

File tree

4 files changed

+58
-96
lines changed

4 files changed

+58
-96
lines changed

src/librustc_codegen_llvm/back/lto.rs

+31-43
Original file line numberDiff line numberDiff line change
@@ -805,66 +805,54 @@ pub struct ThinLTOImports {
805805

806806
impl ThinLTOImports {
807807

808-
pub fn new_empty() -> ThinLTOImports {
808+
pub fn new() -> ThinLTOImports {
809809
ThinLTOImports {
810810
imports: FxHashMap(),
811811
}
812812
}
813813

814814
/// Load the ThinLTO import map from ThinLTOData.
815815
unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
816-
let raw_data: *const llvm::ThinLTOModuleImports =
817-
llvm::LLVMRustGetThinLTOModuleImports(data);
818816

819-
assert!(!raw_data.is_null());
820-
821-
let mut imports = FxHashMap();
822-
let mut module_ptr = raw_data;
823-
let mut module_index = 0;
824-
825-
loop {
826-
let mut entry_ptr: *const llvm::ThinLTOModuleName = *module_ptr;
827-
828-
if entry_ptr.is_null() {
829-
break;
817+
fn module_name_to_str(c_str: &CStr) -> &str {
818+
match c_str.to_str() {
819+
Ok(s) => s,
820+
Err(e) => {
821+
bug!("Encountered non-utf8 LLVM module name `{}`: {}",
822+
c_str.to_string_lossy(),
823+
e)
824+
}
830825
}
826+
}
831827

832-
let importing_module_name = CStr::from_ptr(*entry_ptr)
833-
.to_str()
834-
.expect("Non-utf8 LLVM module name encountered")
835-
.to_owned();
836-
837-
entry_ptr = entry_ptr.offset(1);
838-
839-
let mut imported_modules = vec![];
840-
841-
loop {
842-
let imported_module_name = *entry_ptr;
843-
844-
if imported_module_name.is_null() {
845-
break
846-
}
828+
unsafe extern "C" fn imported_module_callback(payload: *mut libc::c_void,
829+
importing_module_name: *const libc::c_char,
830+
imported_module_name: *const libc::c_char) {
831+
let map = &mut* (payload as *mut ThinLTOImports);
847832

848-
let imported_module_name = CStr::from_ptr(imported_module_name)
849-
.to_str()
850-
.expect("Non-utf8 LLVM module name encountered")
851-
.to_owned();
833+
let importing_module_name = CStr::from_ptr(importing_module_name);
834+
let importing_module_name = module_name_to_str(&importing_module_name);
835+
let imported_module_name = CStr::from_ptr(imported_module_name);
836+
let imported_module_name = module_name_to_str(&imported_module_name);
852837

853-
imported_modules.push(imported_module_name);
854-
entry_ptr = entry_ptr.offset(1);
838+
if !map.imports.contains_key(importing_module_name) {
839+
map.imports.insert(importing_module_name.to_owned(), vec![]);
855840
}
856841

857-
imports.insert(importing_module_name, imported_modules);
858-
859-
module_ptr = module_ptr.offset(1);
860-
module_index += 1;
842+
map.imports
843+
.get_mut(importing_module_name)
844+
.unwrap()
845+
.push(imported_module_name.to_owned());
861846
}
862847

863-
assert_eq!(module_index, imports.len());
848+
let mut map = ThinLTOImports {
849+
imports: FxHashMap(),
850+
};
864851

865-
ThinLTOImports {
866-
imports
867-
}
852+
llvm::LLVMRustGetThinLTOModuleImports(data,
853+
imported_module_callback,
854+
&mut map as *mut _ as *mut libc::c_void);
855+
map
868856
}
869857

870858
pub fn save_to_file(&self, path: &Path) -> io::Result<()> {

src/librustc_codegen_llvm/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1360,7 +1360,7 @@ fn load_thin_lto_imports(sess: &Session) -> lto::ThinLTOImports {
13601360
);
13611361

13621362
if !path.exists() {
1363-
return lto::ThinLTOImports::new_empty();
1363+
return lto::ThinLTOImports::new();
13641364
}
13651365

13661366
match lto::ThinLTOImports::load_from_file(&path) {

src/librustc_llvm/ffi.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,9 @@ pub enum ThinLTOData {}
350350
/// LLVMRustThinLTOBuffer
351351
pub enum ThinLTOBuffer {}
352352

353-
/// LLVMRustThinLTOModuleName
354-
pub type ThinLTOModuleName = *const c_char;
355-
/// LLVMRustThinLTOModuleImports
356-
pub type ThinLTOModuleImports = *const ThinLTOModuleName;
353+
// LLVMRustModuleNameCallback
354+
pub type ThinLTOModuleNameCallback =
355+
unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char);
357356

358357
/// LLVMRustThinLTOModule
359358
#[repr(C)]
@@ -1785,7 +1784,9 @@ extern "C" {
17851784
) -> bool;
17861785
pub fn LLVMRustGetThinLTOModuleImports(
17871786
Data: *const ThinLTOData,
1788-
) -> *const ThinLTOModuleImports;
1787+
ModuleNameCallback: ThinLTOModuleNameCallback,
1788+
CallbackPayload: *mut c_void,
1789+
);
17891790
pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
17901791
pub fn LLVMRustParseBitcodeForThinLTO(
17911792
Context: ContextRef,

src/rustllvm/PassWrapper.cpp

+20-47
Original file line numberDiff line numberDiff line change
@@ -798,11 +798,6 @@ LLVMRustPGOAvailable() {
798798
#endif
799799
}
800800

801-
// We encode the ThinLTO module import map as a nested null-terminated list to
802-
// get it into Rust.
803-
typedef const char* LLVMRustThinLTOModuleName;
804-
typedef LLVMRustThinLTOModuleName* LLVMRustThinLTOModuleImports;
805-
806801
#if LLVM_VERSION_GE(4, 0)
807802

808803
// Here you'll find an implementation of ThinLTO as used by the Rust compiler
@@ -1104,50 +1099,28 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
11041099
return true;
11051100
}
11061101

1107-
/// Converts the LLVMRustThinLTOData::ImportLists map into a nested list. The
1108-
/// first level is a null-terminated array with an entry for each module. Each
1109-
/// entry is a pointer that points to a null-termined array of module names. The
1110-
/// first entry is always the name of the *importing* module, the following
1111-
/// entries are the names of the modules it imports from. Each module name is
1112-
/// a regular C string.
1113-
extern "C" LLVMRustThinLTOModuleImports*
1114-
LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *Data) {
1115-
// Allocate number of module +1. This is a null-terminated array.
1116-
LLVMRustThinLTOModuleImports* thinLTOModuleImports =
1117-
new LLVMRustThinLTOModuleImports[Data->ImportLists.size() + 1];
1118-
size_t module_index = 0;
1119-
1120-
for (const auto & module : Data->ImportLists) {
1121-
StringRef module_id = module.getKey();
1122-
const auto& imports = module.getValue();
1123-
1124-
// Allocate number of imported module + 2, one extra for the name of the
1125-
// importing module and another one for null-termination.
1126-
LLVMRustThinLTOModuleImports imports_array =
1127-
new LLVMRustThinLTOModuleName[imports.size() + 2];
1128-
1129-
// The first value is always the name of the *importing* module.
1130-
imports_array[0] = strndup(module_id.data(), module_id.size());
1131-
1132-
size_t imports_array_index = 1;
1133-
for (const auto imported_module_id : imports.keys()) {
1134-
// The following values are the names of the imported modules.
1135-
imports_array[imports_array_index] = strndup(imported_module_id.data(),
1136-
imported_module_id.size());
1137-
imports_array_index += 1;
1138-
}
1139-
1140-
assert(imports_array_index == imports.size() + 1);
1141-
imports_array[imports_array_index] = nullptr;
1102+
extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1103+
const char*, // importing module name
1104+
const char*); // imported module name
11421105

1143-
thinLTOModuleImports[module_index] = imports_array;
1144-
module_index += 1;
1106+
// Calls `module_name_callback` for each module import done by ThinLTO.
1107+
// The callback is provided with regular null-terminated C strings.
1108+
extern "C" void
1109+
LLVMRustGetThinLTOModuleImports(const LLVMRustThinLTOData *data,
1110+
LLVMRustModuleNameCallback module_name_callback,
1111+
void* callback_payload) {
1112+
for (const auto& importing_module : data->ImportLists) {
1113+
const std::string importing_module_id = importing_module.getKey().str();
1114+
1115+
const auto& imports = importing_module.getValue();
1116+
1117+
for (const auto& imported_module : imports) {
1118+
const std::string imported_module_id = imported_module.getKey().str();
1119+
module_name_callback(callback_payload,
1120+
importing_module_id.c_str(),
1121+
imported_module_id.c_str());
1122+
}
11451123
}
1146-
1147-
assert(module_index == Data->ImportLists.size());
1148-
thinLTOModuleImports[module_index] = nullptr;
1149-
1150-
return thinLTOModuleImports;
11511124
}
11521125

11531126
// This struct and various functions are sort of a hack right now, but the

0 commit comments

Comments
 (0)