@@ -282,15 +282,48 @@ Expected<bool> ForceLoadMachOArchiveMembers::operator()(
282282 return true ;
283283}
284284
285- Expected<SymbolNameSet> getDylibInterfaceFromDylib (ExecutionSession &ES,
286- Twine Path) {
287- auto CPUType = MachO::getCPUType (ES.getTargetTriple ());
288- if (!CPUType)
289- return CPUType.takeError ();
285+ LLVM_ABI SmallVector<std::pair<uint32_t , uint32_t >>
286+ noFallbackArchs (uint32_t CPUType, uint32_t CPUSubType) {
287+ SmallVector<std::pair<uint32_t , uint32_t >> Result;
288+ Result.push_back ({CPUType, CPUSubType});
289+ return Result;
290+ }
291+
292+ SmallVector<std::pair<uint32_t , uint32_t >>
293+ standardMachOFallbackArchs (uint32_t CPUType, uint32_t CPUSubType) {
294+ SmallVector<std::pair<uint32_t , uint32_t >> Archs;
295+
296+ // Match given CPU type/subtype first.
297+ Archs.push_back ({CPUType, CPUSubType});
298+
299+ switch (CPUType) {
300+ case MachO::CPU_TYPE_ARM64:
301+ // Handle arm64 variants.
302+ switch (CPUSubType) {
303+ case MachO::CPU_SUBTYPE_ARM64_ALL:
304+ Archs.push_back ({CPUType, MachO::CPU_SUBTYPE_ARM64E});
305+ break ;
306+ default :
307+ break ;
308+ }
309+ break ;
310+ default :
311+ break ;
312+ }
313+
314+ return Archs;
315+ }
316+
317+ Expected<SymbolNameSet>
318+ getDylibInterfaceFromDylib (ExecutionSession &ES, Twine Path,
319+ GetFallbackArchsFn GetFallbackArchs) {
320+ auto InitCPUType = MachO::getCPUType (ES.getTargetTriple ());
321+ if (!InitCPUType)
322+ return InitCPUType.takeError ();
290323
291- auto CPUSubType = MachO::getCPUSubType (ES.getTargetTriple ());
292- if (!CPUSubType )
293- return CPUSubType .takeError ();
324+ auto InitCPUSubType = MachO::getCPUSubType (ES.getTargetTriple ());
325+ if (!InitCPUSubType )
326+ return InitCPUSubType .takeError ();
294327
295328 auto Buf = MemoryBuffer::getFile (Path);
296329 if (!Buf)
@@ -301,25 +334,38 @@ Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES,
301334 return BinFile.takeError ();
302335
303336 std::unique_ptr<object::MachOObjectFile> MachOFile;
304- if (isa<object::MachOObjectFile>(**BinFile))
337+ if (isa<object::MachOObjectFile>(**BinFile)) {
305338 MachOFile.reset (dyn_cast<object::MachOObjectFile>(BinFile->release ()));
306- else if (auto *MachOUni =
307- dyn_cast<object::MachOUniversalBinary>(BinFile->get ())) {
308- for (auto &O : MachOUni->objects ()) {
309- if (O.getCPUType () == *CPUType &&
310- (O.getCPUSubType () & ~MachO::CPU_SUBTYPE_MASK) == *CPUSubType) {
311- if (auto Obj = O.getAsObjectFile ())
312- MachOFile = std::move (*Obj);
313- else
314- return Obj.takeError ();
315- break ;
339+
340+ // TODO: Check that dylib arch is compatible.
341+ } else if (auto *MachOUni =
342+ dyn_cast<object::MachOUniversalBinary>(BinFile->get ())) {
343+ SmallVector<std::pair<uint32_t , uint32_t >> ArchsToTry;
344+ if (GetFallbackArchs)
345+ ArchsToTry = GetFallbackArchs (*InitCPUType, *InitCPUSubType);
346+ else
347+ ArchsToTry.push_back ({*InitCPUType, *InitCPUSubType});
348+
349+ for (auto &[CPUType, CPUSubType] : ArchsToTry) {
350+ for (auto &O : MachOUni->objects ()) {
351+ if (O.getCPUType () == CPUType &&
352+ (O.getCPUSubType () & ~MachO::CPU_SUBTYPE_MASK) == CPUSubType) {
353+ if (auto Obj = O.getAsObjectFile ())
354+ MachOFile = std::move (*Obj);
355+ else
356+ return Obj.takeError ();
357+ break ;
358+ }
316359 }
360+ if (MachOFile) // If found, break out.
361+ break ;
317362 }
318363 if (!MachOFile)
319- return make_error<StringError>(" MachO universal binary at " + Path +
320- " does not contain a slice for " +
321- ES.getTargetTriple ().str (),
322- inconvertibleErrorCode ());
364+ return make_error<StringError>(
365+ " MachO universal binary at " + Path +
366+ " does not contain a compatible slice for " +
367+ ES.getTargetTriple ().str (),
368+ inconvertibleErrorCode ());
323369 } else
324370 return make_error<StringError>(" File at " + Path + " is not a MachO" ,
325371 inconvertibleErrorCode ());
@@ -339,8 +385,9 @@ Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES,
339385 return std::move (Symbols);
340386}
341387
342- Expected<SymbolNameSet> getDylibInterfaceFromTapiFile (ExecutionSession &ES,
343- Twine Path) {
388+ Expected<SymbolNameSet>
389+ getDylibInterfaceFromTapiFile (ExecutionSession &ES, Twine Path,
390+ GetFallbackArchsFn GetFallbackArchs) {
344391 SymbolNameSet Symbols;
345392
346393 auto TapiFileBuffer = MemoryBuffer::getFile (Path);
@@ -352,37 +399,54 @@ Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES,
352399 if (!Tapi)
353400 return Tapi.takeError ();
354401
355- auto CPUType = MachO::getCPUType (ES.getTargetTriple ());
356- if (!CPUType )
357- return CPUType .takeError ();
402+ auto InitCPUType = MachO::getCPUType (ES.getTargetTriple ());
403+ if (!InitCPUType )
404+ return InitCPUType .takeError ();
358405
359- auto CPUSubType = MachO::getCPUSubType (ES.getTargetTriple ());
360- if (!CPUSubType)
361- return CPUSubType.takeError ();
406+ auto InitCPUSubType = MachO::getCPUSubType (ES.getTargetTriple ());
407+ if (!InitCPUSubType)
408+ return InitCPUSubType.takeError ();
409+
410+ SmallVector<std::pair<uint32_t , uint32_t >> ArchsToTry;
411+ if (GetFallbackArchs)
412+ ArchsToTry = GetFallbackArchs (*InitCPUType, *InitCPUSubType);
413+ else
414+ ArchsToTry.push_back ({*InitCPUType, *InitCPUSubType});
362415
363416 auto &IF = (*Tapi)->getInterfaceFile ();
364- auto Interface =
365- IF.extract (MachO::getArchitectureFromCpuType (*CPUType, *CPUSubType));
366- if (!Interface)
367- return Interface.takeError ();
368417
369- for (auto *Sym : (*Interface)->exports ())
370- Symbols.insert (ES.intern (Sym->getName ()));
418+ auto ArchSet = IF.getArchitectures ();
419+ for (auto [CPUType, CPUSubType] : ArchsToTry) {
420+ auto A = MachO::getArchitectureFromCpuType (CPUType, CPUSubType);
421+ if (ArchSet.has (A)) {
422+ if (auto Interface = IF.extract (A)) {
423+ for (auto *Sym : (*Interface)->exports ())
424+ Symbols.insert (ES.intern (Sym->getName ()));
425+ return Symbols;
426+ } else
427+ return Interface.takeError ();
428+ }
429+ }
371430
372- return Symbols;
431+ return make_error<StringError>(
432+ " MachO interface file at " + Path +
433+ " does not contain a compatible slice for " +
434+ ES.getTargetTriple ().str (),
435+ inconvertibleErrorCode ());
373436}
374437
375- Expected<SymbolNameSet> getDylibInterface (ExecutionSession &ES, Twine Path) {
438+ Expected<SymbolNameSet> getDylibInterface (ExecutionSession &ES, Twine Path,
439+ GetFallbackArchsFn GetFallbackArchs) {
376440 file_magic Magic;
377441 if (auto EC = identify_magic (Path, Magic))
378442 return createFileError (Path, EC);
379443
380444 switch (Magic) {
381445 case file_magic::macho_universal_binary:
382446 case file_magic::macho_dynamically_linked_shared_lib:
383- return getDylibInterfaceFromDylib (ES, Path);
447+ return getDylibInterfaceFromDylib (ES, Path, std::move (GetFallbackArchs) );
384448 case file_magic::tapi_file:
385- return getDylibInterfaceFromTapiFile (ES, Path);
449+ return getDylibInterfaceFromTapiFile (ES, Path, std::move (GetFallbackArchs) );
386450 default :
387451 return make_error<StringError>(" Cannot get interface for " + Path +
388452 " unrecognized file type" ,
0 commit comments