mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Front-end: teach the compiler to generate a .c file for $ld$add$os symbols.
When symbols are moved to this module, this module declares them as HIDE for the OS versions prior to when the move happened. On the other hand, the original module should declare ADD them for these OS versions. An executable can choose the right library to link against depending on the deployment target. This is a walk-around that linker directives cannot specify other install name per symbol, we should eventually remove this.
This commit is contained in:
@@ -1047,6 +1047,59 @@ static bool writeTBDIfNeeded(CompilerInvocation &Invocation,
|
||||
return writeTBD(Instance.getMainModule(), TBDPath, tbdOpts);
|
||||
}
|
||||
|
||||
static std::string changeToLdAdd(StringRef ldHide) {
|
||||
SmallString<64> SymbolBuffer;
|
||||
llvm::raw_svector_ostream OS(SymbolBuffer);
|
||||
auto Parts = ldHide.split("$hide$");
|
||||
assert(!Parts.first.empty());
|
||||
assert(!Parts.second.empty());
|
||||
OS << Parts.first << "$add$" << Parts.second;
|
||||
return OS.str().str();
|
||||
}
|
||||
|
||||
static bool writeLdAddCFileIfNeeded(CompilerInvocation &Invocation,
|
||||
CompilerInstance &Instance) {
|
||||
auto frontendOpts = Invocation.getFrontendOptions();
|
||||
if (!frontendOpts.InputsAndOutputs.isWholeModule())
|
||||
return false;
|
||||
auto Path = Invocation.getLdAddCFileOutputPathForWholeModule();
|
||||
if (Path.empty())
|
||||
return false;
|
||||
if (!frontendOpts.InputsAndOutputs.isWholeModule()) {
|
||||
Instance.getDiags().diagnose(SourceLoc(),
|
||||
diag::tbd_only_supported_in_whole_module);
|
||||
return true;
|
||||
}
|
||||
auto tbdOpts = Invocation.getTBDGenOptions();
|
||||
tbdOpts.LinkerDirectivesOnly = true;
|
||||
llvm::StringSet<> ldSymbols;
|
||||
auto *module = Instance.getMainModule();
|
||||
enumeratePublicSymbols(module, ldSymbols, tbdOpts);
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream OS(Path, EC, llvm::sys::fs::F_None);
|
||||
if (EC) {
|
||||
module->getASTContext().Diags.diagnose(SourceLoc(),
|
||||
diag::error_opening_output,
|
||||
Path, EC.message());
|
||||
return true;
|
||||
}
|
||||
OS << "// Automatically generated C source file from the Swift compiler \n"
|
||||
<< "// to add removed symbols back to the high-level framework for deployment\n"
|
||||
<< "// targets prior to the OS version when these symbols were moved to\n"
|
||||
<< "// a low-level framework " << module->getName().str() << ".\n\n";
|
||||
unsigned Idx = 0;
|
||||
for (auto &S: ldSymbols) {
|
||||
SmallString<32> NameBuffer;
|
||||
llvm::raw_svector_ostream NameOS(NameBuffer);
|
||||
NameOS << "ldAdd_" << Idx;
|
||||
OS << "extern const char " << NameOS.str() << " __asm(\"" <<
|
||||
changeToLdAdd(S.getKey()) << "\");\n";
|
||||
OS << "const char " << NameOS.str() << " = 0;\n";
|
||||
++ Idx;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool performCompileStepsPostSILGen(
|
||||
CompilerInstance &Instance, CompilerInvocation &Invocation,
|
||||
std::unique_ptr<SILModule> SM, bool astGuaranteedToCorrespondToSIL,
|
||||
@@ -1172,6 +1225,9 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
|
||||
{
|
||||
hadAnyError |= writeTBDIfNeeded(Invocation, Instance);
|
||||
}
|
||||
{
|
||||
hadAnyError |= writeLdAddCFileIfNeeded(Invocation, Instance);
|
||||
}
|
||||
|
||||
return hadAnyError;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user