@@ -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,6 +1104,52 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
10991104 return true ;
11001105}
11011106
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 ;
1142+
1143+ thinLTOModuleImports[module_index] = imports_array;
1144+ module_index += 1 ;
1145+ }
1146+
1147+ assert (module_index == Data->ImportLists .size ());
1148+ thinLTOModuleImports[module_index] = nullptr ;
1149+
1150+ return thinLTOModuleImports;
1151+ }
1152+
11021153// This struct and various functions are sort of a hack right now, but the
11031154// problem is that we've got in-memory LLVM modules after we generate and
11041155// optimize all codegen-units for one compilation in rustc. To be compatible
@@ -1280,6 +1331,11 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
12801331 report_fatal_error (" ThinLTO not available" );
12811332}
12821333
1334+ extern " C" LLVMRustThinLTOModuleImports
1335+ LLVMRustGetLLVMRustThinLTOModuleImports (const LLVMRustThinLTOData *Data) {
1336+ report_fatal_error (" ThinLTO not available" );
1337+ }
1338+
12831339extern " C" void
12841340LLVMRustFreeThinLTOData (LLVMRustThinLTOData *Data) {
12851341 report_fatal_error (" ThinLTO not available" );
0 commit comments