Skip to content

Commit b822e69

Browse files
Revert "Use callback-based interface to load ThinLTO import data into rustc."
This reverts commit e045a6c.
1 parent 99140df commit b822e69

File tree

4 files changed

+96
-58
lines changed

4 files changed

+96
-58
lines changed

src/librustc_codegen_llvm/back/lto.rs

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -805,54 +805,66 @@ pub struct ThinLTOImports {
805805

806806
impl ThinLTOImports {
807807

808-
pub fn new() -> ThinLTOImports {
808+
pub fn new_empty() -> 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);
816818

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-
}
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;
825830
}
826-
}
827831

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);
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);
832838

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);
839+
let mut imported_modules = vec![];
837840

838-
if !map.imports.contains_key(importing_module_name) {
839-
map.imports.insert(importing_module_name.to_owned(), vec![]);
841+
loop {
842+
let imported_module_name = *entry_ptr;
843+
844+
if imported_module_name.is_null() {
845+
break
846+
}
847+
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();
852+
853+
imported_modules.push(imported_module_name);
854+
entry_ptr = entry_ptr.offset(1);
840855
}
841856

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

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

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

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

src/librustc_codegen_llvm/base.rs

Lines changed: 1 addition & 1 deletion
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();
1363+
return lto::ThinLTOImports::new_empty();
13641364
}
13651365

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

src/librustc_llvm/ffi.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -351,9 +351,10 @@ pub enum ThinLTOData {}
351351
/// LLVMRustThinLTOBuffer
352352
pub enum ThinLTOBuffer {}
353353

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

358359
/// LLVMRustThinLTOModule
359360
#[repr(C)]
@@ -1785,9 +1786,7 @@ extern "C" {
17851786
) -> bool;
17861787
pub fn LLVMRustGetThinLTOModuleImports(
17871788
Data: *const ThinLTOData,
1788-
ModuleNameCallback: ThinLTOModuleNameCallback,
1789-
CallbackPayload: *mut c_void,
1790-
);
1789+
) -> *const ThinLTOModuleImports;
17911790
pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData);
17921791
pub fn LLVMRustParseBitcodeForThinLTO(
17931792
Context: ContextRef,

src/rustllvm/PassWrapper.cpp

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,11 @@ 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+
801806
#if LLVM_VERSION_GE(4, 0)
802807

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

1102-
extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload
1103-
const char*, // importing module name
1104-
const char*); // imported module name
1105-
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());
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;
11221138
}
1139+
1140+
assert(imports_array_index == imports.size() + 1);
1141+
imports_array[imports_array_index] = nullptr;
1142+
1143+
thinLTOModuleImports[module_index] = imports_array;
1144+
module_index += 1;
11231145
}
1146+
1147+
assert(module_index == Data->ImportLists.size());
1148+
thinLTOModuleImports[module_index] = nullptr;
1149+
1150+
return thinLTOModuleImports;
11241151
}
11251152

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

0 commit comments

Comments
 (0)