@@ -1477,14 +1477,7 @@ Expected<bool> getSymbolsFromBitcode(MemoryBufferRef Buffer, OffloadKind Kind,
14771477 bool ResolvesStrongReference =
14781478 ((OldSym & Sym_Undefined && !(OldSym & Sym_Weak)) &&
14791479 !Sym.isUndefined ());
1480- // We will extract if it defines a new global symbol visible to the
1481- // host. This is only necessary for code targeting an offloading
1482- // language.
1483- bool NewGlobalSymbol =
1484- ((NewSymbol || (OldSym & Sym_Undefined)) && !Sym.isUndefined () &&
1485- !Sym.canBeOmittedFromSymbolTable () && Kind != object::OFK_None &&
1486- (Sym.getVisibility () != GlobalValue::HiddenVisibility));
1487- ShouldExtract |= ResolvesStrongReference | NewGlobalSymbol;
1480+ ShouldExtract |= ResolvesStrongReference;
14881481
14891482 // Update this symbol in the "table" with the new information.
14901483 if (OldSym & Sym_Undefined && !Sym.isUndefined ())
@@ -1533,15 +1526,7 @@ Expected<bool> getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind,
15331526 bool ResolvesStrongReference = (OldSym & Sym_Undefined) &&
15341527 !(OldSym & Sym_Weak) &&
15351528 !(*FlagsOrErr & SymbolRef::SF_Undefined);
1536-
1537- // We will extract if it defines a new global symbol visible to the
1538- // host. This is only necessary for code targeting an offloading
1539- // language.
1540- bool NewGlobalSymbol =
1541- ((NewSymbol || (OldSym & Sym_Undefined)) &&
1542- !(*FlagsOrErr & SymbolRef::SF_Undefined) && Kind != object::OFK_None &&
1543- !(*FlagsOrErr & SymbolRef::SF_Hidden));
1544- ShouldExtract |= ResolvesStrongReference | NewGlobalSymbol;
1529+ ShouldExtract |= ResolvesStrongReference;
15451530
15461531 // Update this symbol in the "table" with the new information.
15471532 if (OldSym & Sym_Undefined && !(*FlagsOrErr & SymbolRef::SF_Undefined))
@@ -1586,10 +1571,101 @@ Expected<bool> getSymbols(StringRef Image, OffloadKind Kind, bool IsArchive,
15861571 }
15871572}
15881573
1574+ Error getNeededDeviceGlobalsFromBitcode (MemoryBufferRef Buffer,
1575+ SmallVectorImpl<std::string> &Symbols) {
1576+
1577+ LLVMContext Context;
1578+ SMDiagnostic Err;
1579+ std::unique_ptr<Module> M = getLazyIRModule (
1580+ MemoryBuffer::getMemBuffer (Buffer, /* RequiresNullTerminator=*/ false ), Err,
1581+ Context);
1582+ if (!M)
1583+ return createStringError (inconvertibleErrorCode (),
1584+ " Failed to create module" );
1585+
1586+ // Extract offloading data from globals referenced by the
1587+ // `llvm.embedded.object` metadata with the `.llvm.offloading` section.
1588+ auto *MD = M->getNamedMetadata (" llvm.offloading.symbols" );
1589+ if (!MD)
1590+ return Error::success ();
1591+
1592+ for (const MDNode *Op : MD->operands ()) {
1593+ GlobalVariable *GV =
1594+ mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand (0 ));
1595+ if (!GV)
1596+ continue ;
1597+
1598+ auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer ());
1599+ if (!CDS)
1600+ continue ;
1601+
1602+ Symbols.emplace_back (CDS->getAsCString ().str ());
1603+ }
1604+
1605+ return Error::success ();
1606+ }
1607+
1608+ Error getNeededDeviceGlobalsFromObject (const ObjectFile &Obj,
1609+ SmallVectorImpl<std::string> &Symbols) {
1610+ for (const auto &Sec : Obj.sections ()) {
1611+ auto NameOrErr = Sec.getName ();
1612+ if (!NameOrErr)
1613+ return NameOrErr.takeError ();
1614+
1615+ if (*NameOrErr != " .llvm.rodata.offloading" )
1616+ continue ;
1617+
1618+ auto ContentsOrErr = Sec.getContents ();
1619+ if (!ContentsOrErr)
1620+ return ContentsOrErr.takeError ();
1621+ llvm::transform (llvm::split (ContentsOrErr->drop_back (), ' \0 ' ),
1622+ std::back_inserter (Symbols),
1623+ [](StringRef Str) { return Str.str (); });
1624+ }
1625+ return Error::success ();
1626+ }
1627+
1628+ Error getNeededDeviceGlobals (MemoryBufferRef Buffer,
1629+ SmallVectorImpl<std::string> &Symbols) {
1630+ file_magic Type = identify_magic (Buffer.getBuffer ());
1631+ switch (Type) {
1632+ case file_magic::bitcode:
1633+ return getNeededDeviceGlobalsFromBitcode (Buffer, Symbols);
1634+ case file_magic::elf_relocatable:
1635+ case file_magic::coff_object: {
1636+ Expected<std::unique_ptr<ObjectFile>> ObjFile =
1637+ ObjectFile::createObjectFile (Buffer, Type);
1638+ if (!ObjFile)
1639+ return ObjFile.takeError ();
1640+ return getNeededDeviceGlobalsFromObject (*ObjFile->get (), Symbols);
1641+ }
1642+ case file_magic::archive: {
1643+ Expected<std::unique_ptr<llvm::object::Archive>> LibFile =
1644+ object::Archive::create (Buffer);
1645+ if (!LibFile)
1646+ return LibFile.takeError ();
1647+ Error Err = Error::success ();
1648+ for (auto Child : (*LibFile)->children (Err)) {
1649+ auto ChildBufferOrErr = Child.getMemoryBufferRef ();
1650+ if (!ChildBufferOrErr)
1651+ return ChildBufferOrErr.takeError ();
1652+ if (Error Err = getNeededDeviceGlobals (*ChildBufferOrErr, Symbols))
1653+ return Err;
1654+ }
1655+ if (Err)
1656+ return Err;
1657+ return Error::success ();
1658+ }
1659+ default :
1660+ return Error::success ();
1661+ }
1662+ }
1663+
15891664// / Search the input files and libraries for embedded device offloading code
15901665// / and add it to the list of files to be linked. Files coming from static
15911666// / libraries are only added to the input if they are used by an existing
1592- // / input file. Returns a list of input files intended for a single linking job.
1667+ // / input file. Returns a list of input files intended for a single linking
1668+ // / job.
15931669Expected<SmallVector<SmallVector<OffloadFile>>>
15941670getDeviceInput (const ArgList &Args) {
15951671 llvm::TimeTraceScope TimeScope (" ExtractDeviceCode" );
@@ -1610,6 +1686,7 @@ getDeviceInput(const ArgList &Args) {
16101686 bool WholeArchive = Args.hasArg (OPT_wholearchive_flag) ? true : false ;
16111687 SmallVector<OffloadFile> ObjectFilesToExtract;
16121688 SmallVector<OffloadFile> ArchiveFilesToExtract;
1689+ SmallVector<std::string> NeededSymbols;
16131690 for (const opt::Arg *Arg : Args.filtered (
16141691 OPT_INPUT, OPT_library, OPT_whole_archive, OPT_no_whole_archive)) {
16151692 if (Arg->getOption ().matches (OPT_whole_archive) ||
@@ -1640,6 +1717,9 @@ getDeviceInput(const ArgList &Args) {
16401717 if (identify_magic (Buffer.getBuffer ()) == file_magic::elf_shared_object)
16411718 continue ;
16421719
1720+ if (Error Err = getNeededDeviceGlobals (Buffer, NeededSymbols))
1721+ return std::move (Err);
1722+
16431723 SmallVector<OffloadFile> Binaries;
16441724 if (Error Err = extractOffloadBinaries (Buffer, Binaries))
16451725 return std::move (Err);
@@ -1666,6 +1746,13 @@ getDeviceInput(const ArgList &Args) {
16661746 CompatibleTargets.emplace_back (ID);
16671747
16681748 for (const auto &[Index, ID] : llvm::enumerate (CompatibleTargets)) {
1749+ // Initialize the symbol table with the device globals that host needs.
1750+ // This will force them to be extracted if they are defined in a library.
1751+ if (!Syms.contains (ID)) {
1752+ for (auto &Symbol : NeededSymbols)
1753+ auto &Val = Syms[ID][Symbol] = Sym_Undefined;
1754+ }
1755+
16691756 Expected<bool > ExtractOrErr = getSymbols (
16701757 Binary.getBinary ()->getImage (), Binary.getBinary ()->getOffloadKind (),
16711758 /* IsArchive=*/ false , Saver, Syms[ID]);
0 commit comments