Skip to content

[TBDGen] Capture segment symbols are defined in & emit tbd-v5 format #69779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,12 @@ class LinkEntity {
/// entity.
llvm::Type *getDefaultDeclarationType(IRGenModule &IGM) const;

/// Determine whether entity that represents a symbol is in TEXT segment.
bool isText() const;

/// Determine whether entity that represents a symbol is in DATA segment.
bool isData() const { return !isText(); }

bool isAlwaysSharedLinkage() const;
#undef LINKENTITY_GET_FIELD
#undef LINKENTITY_SET_FIELD
Expand Down
100 changes: 100 additions & 0 deletions lib/IRGen/Linking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,106 @@ Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
}
}

bool LinkEntity::isText() const {
switch (getKind()) {
case Kind::DispatchThunkAllocator:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorDerivative:
case Kind::MethodDescriptorAllocator:
case Kind::MethodLookupFunction:
case Kind::EnumCase:
case Kind::FieldOffset:
case Kind::ClassMetadataBaseOffset:
case Kind::PropertyDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::OpaqueTypeDescriptor:
case Kind::OpaqueTypeDescriptorAccessor:
case Kind::OpaqueTypeDescriptorAccessorImpl:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::AssociatedConformanceDescriptor:
case Kind::AssociatedTypeDescriptor:
case Kind::BaseConformanceDescriptor:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::DynamicallyReplaceableFunctionImpl:
case Kind::DispatchThunk:
case Kind::ProtocolDescriptor:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
case Kind::TypeMetadataAccessFunction:
return true;
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::SwiftMetaclassStub:
case Kind::ObjCResilientClassStub:
case Kind::OpaqueTypeDescriptorAccessorVar:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::AsyncFunctionPointerAST:
case Kind::ProtocolWitnessTable:
case Kind::TypeMetadata:
return false;
// The following cases do not currently generate linkable symbols
// through TBDGen. The full enumeration is captured to ensure
// that as more LinkEntity kind's are created their segement assignment
// will be known.
case Kind::ObjCMetadataUpdateFunction:
case Kind::NominalTypeDescriptorRecord:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::SILFunction:
case Kind::PartialApplyForwarder:
case Kind::DistributedAccessor:
case Kind::DispatchThunkDerivative:
case Kind::DispatchThunkInitializer:
case Kind::MethodDescriptorInitializer:
case Kind::TypeMetadataPattern:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadataCompletionFunction:
case Kind::ModuleDescriptor:
case Kind::DefaultAssociatedConformanceAccessor:
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::SILGlobalVariable:
case Kind::ReadOnlyGlobalObject:
case Kind::ProtocolWitnessTablePattern:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::DifferentiabilityWitness:
case Kind::ValueWitness:
case Kind::ValueWitnessTable:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataDemanglingCacheVariable:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::CoroutineContinuationPrototype:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Kind::ExtendedExistentialTypeShape:
return true;
case Kind::ObjCClass:
case Kind::ObjCClassRef:
case Kind::ObjCMetaclass:
case Kind::AsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::KnownAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::DistributedAccessorAsyncPointer:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ProtocolDescriptorRecord:
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::AccessibleFunctionRecord:
return false;
}
}

bool LinkEntity::isWeakImported(ModuleDecl *module) const {
switch (getKind()) {
case Kind::SILGlobalVariable:
Expand Down
47 changes: 27 additions & 20 deletions lib/IRGen/TBDGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ using namespace swift::tbdgen;
using namespace llvm::yaml;
using StringSet = llvm::StringSet<>;
using SymbolKind = llvm::MachO::SymbolKind;
using SymbolFlags = llvm::MachO::SymbolFlags;

TBDGenVisitor::TBDGenVisitor(const TBDGenDescriptor &desc,
APIRecorder &recorder)
: TBDGenVisitor(desc.getTarget(), desc.getDataLayoutString(),
desc.getParentModule(), desc.getOptions(), recorder) {}

void TBDGenVisitor::addSymbolInternal(StringRef name, SymbolKind kind,
SymbolSource source) {
SymbolSource source, SymbolFlags flags) {
if (!source.isLinkerDirective() && Opts.LinkerDirectivesOnly)
return;

Expand All @@ -82,7 +83,7 @@ void TBDGenVisitor::addSymbolInternal(StringRef name, SymbolKind kind,
}
#endif
recorder.addSymbol(name, kind, source,
DeclStack.empty() ? nullptr : DeclStack.back());
DeclStack.empty() ? nullptr : DeclStack.back(), flags);
}

static std::vector<OriginallyDefinedInAttr::ActiveVersion>
Expand Down Expand Up @@ -341,7 +342,7 @@ void TBDGenVisitor::addLinkerDirectiveSymbolsLdPrevious(StringRef name,
OS << Ver.Version.getMajor() << "." << getMinor(Ver.Version.getMinor()) << "$";
OS << name << "$";
addSymbolInternal(OS.str(), SymbolKind::GlobalSymbol,
SymbolSource::forLinkerDirective());
SymbolSource::forLinkerDirective(), SymbolFlags::Data);
}
}

Expand Down Expand Up @@ -387,13 +388,13 @@ void TBDGenVisitor::addLinkerDirectiveSymbolsLdHide(StringRef name,
llvm::raw_svector_ostream OS(Buffer);
OS << "$ld$hide$os" << CurMaj << "." << CurMin << "$" << name;
addSymbolInternal(OS.str(), SymbolKind::GlobalSymbol,
SymbolSource::forLinkerDirective());
SymbolSource::forLinkerDirective(), SymbolFlags::Data);
}
}
}

void TBDGenVisitor::addSymbol(StringRef name, SymbolSource source,
SymbolKind kind) {
SymbolFlags flags, SymbolKind kind) {
// The linker expects to see mangled symbol names in TBD files,
// except when being passed objective c classes,
// so make sure to mangle before inserting the symbol.
Expand All @@ -406,7 +407,7 @@ void TBDGenVisitor::addSymbol(StringRef name, SymbolSource source,
llvm::Mangler::getNameWithPrefix(mangled, name, *DataLayout);
}

addSymbolInternal(mangled, kind, source);
addSymbolInternal(mangled, kind, source, flags);
if (previousInstallNameMap) {
addLinkerDirectiveSymbolsLdPrevious(mangled, kind);
} else {
Expand Down Expand Up @@ -434,30 +435,33 @@ void TBDGenVisitor::didVisitDecl(Decl *D) {
}

void TBDGenVisitor::addFunction(SILDeclRef declRef) {
addSymbol(declRef.mangle(), SymbolSource::forSILDeclRef(declRef));
addSymbol(declRef.mangle(), SymbolSource::forSILDeclRef(declRef),
SymbolFlags::Text);
}

void TBDGenVisitor::addFunction(StringRef name, SILDeclRef declRef) {
addSymbol(name, SymbolSource::forSILDeclRef(declRef));
addSymbol(name, SymbolSource::forSILDeclRef(declRef), SymbolFlags::Text);
}

void TBDGenVisitor::addGlobalVar(VarDecl *VD) {
Mangle::ASTMangler mangler;
addSymbol(mangler.mangleEntity(VD), SymbolSource::forGlobal(VD));
addSymbol(mangler.mangleEntity(VD), SymbolSource::forGlobal(VD),
SymbolFlags::Data);
}

void TBDGenVisitor::addLinkEntity(LinkEntity entity) {
auto linkage =
LinkInfo::get(UniversalLinkInfo, SwiftModule, entity, ForDefinition);

addSymbol(linkage.getName(), SymbolSource::forIRLinkEntity(entity));
SymbolFlags flags = entity.isData() ? SymbolFlags::Data : SymbolFlags::Text;
addSymbol(linkage.getName(), SymbolSource::forIRLinkEntity(entity), flags);
}

void TBDGenVisitor::addObjCInterface(ClassDecl *CD) {
// FIXME: We ought to have a symbol source for this.
SmallString<128> buffer;
addSymbol(CD->getObjCRuntimeName(buffer), SymbolSource::forUnknown(),
SymbolKind::ObjectiveCClass);
SymbolFlags::Data, SymbolKind::ObjectiveCClass);
recorder.addObjCInterface(CD);
}

Expand All @@ -474,13 +478,14 @@ void TBDGenVisitor::addProtocolWitnessThunk(RootProtocolConformance *C,

std::string decorated = Mangler.mangleWitnessThunk(C, requirementDecl);
// FIXME: We should have a SILDeclRef SymbolSource for this.
addSymbol(decorated, SymbolSource::forUnknown());
addSymbol(decorated, SymbolSource::forUnknown(), SymbolFlags::Text);

if (requirementDecl->isProtocolRequirement()) {
ValueDecl *PWT = C->getWitness(requirementDecl).getDecl();
if (const auto *AFD = dyn_cast<AbstractFunctionDecl>(PWT))
if (AFD->hasAsync())
addSymbol(decorated + "Tu", SymbolSource::forUnknown());
addSymbol(decorated + "Tu", SymbolSource::forUnknown(),
SymbolFlags::Text);
}
}

Expand All @@ -489,7 +494,7 @@ void TBDGenVisitor::addFirstFileSymbols() {
// FIXME: We ought to have a symbol source for this.
SmallString<32> buf;
addSymbol(irgen::encodeForceLoadSymbolName(buf, Opts.ModuleLinkName),
SymbolSource::forUnknown());
SymbolSource::forUnknown(), SymbolFlags::Data);
}
}

Expand Down Expand Up @@ -588,7 +593,7 @@ TBDFile GenerateTBDRequest::evaluate(Evaluator &evaluator,
auto &ctx = M->getASTContext();

llvm::MachO::InterfaceFile file;
file.setFileType(llvm::MachO::FileType::TBD_V4);
file.setFileType(llvm::MachO::FileType::TBD_V5);
file.setApplicationExtensionSafe(isApplicationExtensionSafe(ctx.LangOpts));
file.setInstallName(opts.InstallName);
file.setTwoLevelNamespace();
Expand All @@ -615,7 +620,9 @@ TBDFile GenerateTBDRequest::evaluate(Evaluator &evaluator,
}

auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) { file.addSymbol(kind, symbol, targets); };
Decl *decl, SymbolFlags flags) {
file.addSymbol(kind, symbol, targets, flags);
};
SimpleAPIRecorder recorder(addSymbol);
TBDGenVisitor visitor(desc, recorder);
visitor.visit(desc);
Expand All @@ -627,7 +634,7 @@ PublicSymbolsRequest::evaluate(Evaluator &evaluator,
TBDGenDescriptor desc) const {
std::vector<std::string> symbols;
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) {
Decl *decl, SymbolFlags flags) {
if (kind == SymbolKind::GlobalSymbol)
symbols.push_back(symbol.str());
// TextAPI ObjC Class Kinds represents two symbols.
Expand All @@ -652,7 +659,7 @@ void swift::writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os,
auto desc = TBDGenDescriptor::forModule(M, opts);
auto file = llvm::cantFail(evaluator(GenerateTBDRequest{desc}));
llvm::cantFail(llvm::MachO::TextAPIWriter::writeToStream(os, file),
"YAML writing should be error-free");
"TBD writing should be error-free");
}

class APIGenRecorder final : public APIRecorder {
Expand All @@ -675,7 +682,7 @@ class APIGenRecorder final : public APIRecorder {
~APIGenRecorder() {}

void addSymbol(StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) override {
Decl *decl, SymbolFlags flags) override {
if (kind != SymbolKind::GlobalSymbol)
return;

Expand Down Expand Up @@ -879,7 +886,7 @@ SymbolSourceMapRequest::evaluate(Evaluator &evaluator,
auto *SymbolSources = Ctx.Allocate<SymbolSourceMap>();

auto addSymbol = [=](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) {
Decl *decl, SymbolFlags flags) {
SymbolSources->insert({symbol, source});
};

Expand Down
24 changes: 14 additions & 10 deletions lib/IRGen/TBDGenVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,25 @@ class APIRecorder {
virtual ~APIRecorder() {}

virtual void addSymbol(StringRef name, llvm::MachO::SymbolKind kind,
SymbolSource source, Decl *decl) {}
SymbolSource source, Decl *decl,
llvm::MachO::SymbolFlags flags) {}
virtual void addObjCInterface(const ClassDecl *decl) {}
virtual void addObjCCategory(const ExtensionDecl *decl) {}
virtual void addObjCMethod(const GenericContext *ctx, SILDeclRef method) {}
};

class SimpleAPIRecorder final : public APIRecorder {
public:
using SymbolCallbackFn = llvm::function_ref<void(
StringRef, llvm::MachO::SymbolKind, SymbolSource, Decl *)>;
using SymbolCallbackFn =
llvm::function_ref<void(StringRef, llvm::MachO::SymbolKind, SymbolSource,
Decl *, llvm::MachO::SymbolFlags)>;

SimpleAPIRecorder(SymbolCallbackFn func) : func(func) {}

void addSymbol(StringRef symbol, llvm::MachO::SymbolKind kind,
SymbolSource source, Decl *decl) override {
func(symbol, kind, source, decl);
SymbolSource source, Decl *decl,
llvm::MachO::SymbolFlags flags) override {
func(symbol, kind, source, decl, flags);
}

private:
Expand All @@ -99,17 +102,18 @@ class TBDGenVisitor : public IRSymbolVisitor {
APIRecorder &recorder;

using SymbolKind = llvm::MachO::SymbolKind;
using SymbolFlags = llvm::MachO::SymbolFlags;

std::vector<Decl*> DeclStack;
std::unique_ptr<std::map<std::string, InstallNameStore>>
previousInstallNameMap;
std::unique_ptr<std::map<std::string, InstallNameStore>>
parsePreviousModuleInstallNameMap();
void addSymbolInternal(StringRef name, llvm::MachO::SymbolKind kind,
SymbolSource source);
void addLinkerDirectiveSymbolsLdHide(StringRef name, llvm::MachO::SymbolKind kind);
void addLinkerDirectiveSymbolsLdPrevious(StringRef name, llvm::MachO::SymbolKind kind);
void addSymbol(StringRef name, SymbolSource source,
void addSymbolInternal(StringRef name, SymbolKind kind, SymbolSource source,
SymbolFlags);
void addLinkerDirectiveSymbolsLdHide(StringRef name, SymbolKind kind);
void addLinkerDirectiveSymbolsLdPrevious(StringRef name, SymbolKind kind);
void addSymbol(StringRef name, SymbolSource source, SymbolFlags flags,
SymbolKind kind = SymbolKind::GlobalSymbol);

void addSymbol(LinkEntity entity);
Expand Down
3 changes: 3 additions & 0 deletions test/IRGen/virtual-function-elimination-two-modules.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// FIXME: Disabled due to https://github.com/apple/swift/issues/69485
// REQUIRES: issue_69485

// Tests that under -enable-llvm-vfe + -internalize-at-link, cross-module
// virtual calls are done via thunks and LLVM GlobalDCE is able to remove unused
// virtual methods from a library based on a list of used symbols by a client.
Expand Down
3 changes: 3 additions & 0 deletions test/IRGen/witness-method-elimination-two-modules.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// FIXME: Disabled due to https://github.com/apple/swift/issues/69485
// REQUIRES: issue_69485

// Tests that under -enable-llvm-wme + -internalize-at-link, cross-module
// witness method calls are done via thunks and LLVM GlobalDCE is able to remove
// unused witness methods from a library based on a list of used symbols by a
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/default-cmo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-module -emit-module-path=%t/Submodule.swiftmodule -module-name=Submodule %S/Inputs/cross-module/default-submodule.swift -c -o %t/submodule.o
// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-module -emit-module-path=%t/Module.swiftmodule -module-name=Module -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/module.o
// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-tbd -emit-tbd-path %t/ModuleTBD.tbd -emit-module -emit-module-path=%t/ModuleTBD.swiftmodule -module-name=ModuleTBD -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/moduletbd.o
// RUN: %target-build-swift -O -wmo -Xfrontend -enable-default-cmo -parse-as-library -emit-tbd -emit-tbd-path %t/ModuleTBD.tbd -emit-module -emit-module-path=%t/ModuleTBD.swiftmodule -module-name=ModuleTBD -I%t -I%S/Inputs/cross-module %S/Inputs/cross-module/default-module.swift -c -o %t/moduletbd.o -Xfrontend -tbd-install_name -Xfrontend module

// RUN: %target-build-swift -O -wmo -module-name=Main -I%t -I%S/Inputs/cross-module %s -emit-sil | %FileCheck %s

Expand Down
4 changes: 2 additions & 2 deletions test/SPI/spi_symbols.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// REQUIRES: VENDOR=apple
// RUN: %empty-directory(%t)

// RUN: %target-swift-frontend %S/Inputs/spi_helper.swift -emit-ir -o %t/spi_helper.ll -emit-tbd-path %t/spi_helper.tbd -module-name spi_helper
// RUN: %target-swift-frontend %S/Inputs/spi_helper.swift -emit-ir -o %t/spi_helper.ll -emit-tbd-path %t/spi_helper.tbd -module-name spi_helper -tbd-install_name spi_helper

// RUN: cat %t/spi_helper.ll | %FileCheck -check-prefix=CHECK-IR %s
// RUN: cat %t/spi_helper.tbd | %FileCheck -check-prefix=CHECK-TBD %s
// RUN: %llvm-nm %t/spi_helper.tbd | %FileCheck -check-prefix=CHECK-TBD %s

// Look for the SPI symbols in the IR
// CHECK-IR: define swiftcc void @"$s10spi_helper0A4FuncyyF"
Expand Down
Loading