SmallVector<std::unique_ptr<lto::InputFile>, 4> BitcodeFiles;
SmallVector<std::string, 4> NewInputFiles;
StringMap<bool> UsedInRegularObj;
+ StringMap<bool> UsedInSharedLib;
// Search for bitcode files in the input and create an LTO input file. If it
// is not a bitcode file, scan its symbol table for symbols we need to
if (!Name)
return Name.takeError();
- UsedInRegularObj[*Name] = true;
+ // Record if we've seen these symbols in any object or shared libraries.
+ if ((*ObjFile)->isRelocatableObject()) {
+ UsedInRegularObj[*Name] = true;
+ } else
+ UsedInSharedLib[*Name] = true;
}
} else {
Expected<std::unique_ptr<lto::InputFile>> InputFileOrErr =
if (!InputFileOrErr)
return InputFileOrErr.takeError();
+ // Save the input file and the buffer associated with its memory.
BitcodeFiles.push_back(std::move(*InputFileOrErr));
SavedBuffers.push_back(std::move(*BufferOrErr));
}
return false;
};
- // We have visibility of the whole program if every input is bitcode, all
- // inputs are statically linked so there should be no external references.
+ // We assume visibility of the whole program if every input file was bitcode.
bool WholeProgram = BitcodeFiles.size() == InputFiles.size();
auto LTOBackend = (EmbedBC)
? createLTO(TheTriple, Arch, WholeProgram, LinkOnly)
: createLTO(TheTriple, Arch, WholeProgram);
- // TODO: Run more tests to verify that this is correct.
- // Create the LTO instance with the necessary config and add the bitcode files
- // to it after resolving symbols. We make a few assumptions about symbol
- // resolution.
- // 1. The target is going to be a stand-alone executable file.
- // 2. We do not support relocatable object files.
- // 3. All inputs are relocatable object files extracted from host binaries, so
- // there is no resolution to a dynamic library.
- StringMap<bool> PrevailingSymbols;
+ // We need to resolve the symbols so the LTO backend knows which symbols need
+ // to be kept or can be internalized. This is a simplified symbol resolution
+ // scheme to approximate the full resolution a linker would do.
+ DenseSet<StringRef> PrevailingSymbols;
for (auto &BitcodeFile : BitcodeFiles) {
const auto Symbols = BitcodeFile->symbols();
SmallVector<lto::SymbolResolution, 16> Resolutions(Symbols.size());
lto::SymbolResolution &Res = Resolutions[Idx++];
// We will use this as the prevailing symbol definition in LTO unless
- // it is undefined in the module or another symbol has already been used.
- Res.Prevailing = !Sym.isUndefined() && !PrevailingSymbols[Sym.getName()];
-
- // We need LTO to preserve symbols referenced in other object files, or
- // are needed by the rest of the toolchain.
+ // it is undefined or another definition has already been used.
+ Res.Prevailing =
+ !Sym.isUndefined() && PrevailingSymbols.insert(Sym.getName()).second;
+
+ // We need LTO to preseve the following global symbols:
+ // 1) Symbols used in regular objects.
+ // 2) Sections that will be given a __start/__stop symbol.
+ // 3) Prevailing symbols that are needed visibile to external libraries.
Res.VisibleToRegularObj =
UsedInRegularObj[Sym.getName()] ||
isValidCIdentifier(Sym.getSectionName()) ||
- (Res.Prevailing && Sym.getName().startswith("__omp"));
-
- // We do not currently support shared libraries, so no symbols will be
- // referenced externally by shared libraries.
- Res.ExportDynamic = false;
-
- // The result will currently always be an executable, so the only time the
- // definition will not reside in this link unit is if it's undefined.
- Res.FinalDefinitionInLinkageUnit = !Sym.isUndefined();
+ (Res.Prevailing &&
+ (Sym.getVisibility() != GlobalValue::HiddenVisibility &&
+ !Sym.canBeOmittedFromSymbolTable()));
+
+ // Identify symbols that must be exported dynamically and can be
+ // referenced by other files.
+ Res.ExportDynamic =
+ Sym.getVisibility() != GlobalValue::HiddenVisibility &&
+ (UsedInSharedLib[Sym.getName()] ||
+ !Sym.canBeOmittedFromSymbolTable());
+
+ // The final definition will reside in this linkage unit if the symbol is
+ // defined and local to the module. This only checks for bitcode files,
+ // full assertion will require complete symbol resolution.
+ Res.FinalDefinitionInLinkageUnit =
+ Sym.getVisibility() != GlobalValue::DefaultVisibility &&
+ (!Sym.isUndefined() && !Sym.isCommon());
// We do not support linker redefined symbols (e.g. --wrap) for device
// image linking, so the symbols will not be changed after LTO.
Res.LinkerRedefined = false;
-
- // Mark this symbol as the prevailing one.
- PrevailingSymbols[Sym.getName()] |= Res.Prevailing;
}
// Add the bitcode file with its resolved symbols to the LTO job.
if (Error Err = LTOBackend->add(std::move(BitcodeFile), Resolutions))
- return std::move(Err);
+ return Err;
}
// Run the LTO job to compile the bitcode.
};
if (Error Err = LTOBackend->run(AddStream))
- return std::move(Err);
+ return Err;
// Is we are compiling for NVPTX we need to run the assembler first.
for (auto &File : Files) {
// Run LTO on any bitcode files and replace the input with the result.
if (Error Err = linkBitcodeFiles(LinkerInput.getValue(), TheTriple, Arch))
- return std::move(Err);
+ return Err;
// If we are embedding bitcode for JIT, skip the final device linking.
if (EmbedBC) {