Skip to content

TBDGen: Improve the accuracy of swift-api-extract output #68978

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 6 commits into from
Oct 5, 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
48 changes: 21 additions & 27 deletions lib/IRGen/TBDGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ void TBDGenVisitor::addSymbolInternal(StringRef name, SymbolKind kind,
}
}
#endif
recorder.addSymbol(name, kind, source);
recorder.addSymbol(name, kind, source,
DeclStack.empty() ? nullptr : DeclStack.back());
}

static std::vector<OriginallyDefinedInAttr::ActiveVersion>
Expand Down Expand Up @@ -613,9 +614,8 @@ TBDFile GenerateTBDRequest::evaluate(Evaluator &evaluator,
targets.push_back(targetVar);
}

auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) {
file.addSymbol(kind, symbol, targets);
};
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) { file.addSymbol(kind, symbol, targets); };
SimpleAPIRecorder recorder(addSymbol);
TBDGenVisitor visitor(desc, recorder);
visitor.visit(desc);
Expand All @@ -626,7 +626,8 @@ std::vector<std::string>
PublicSymbolsRequest::evaluate(Evaluator &evaluator,
TBDGenDescriptor desc) const {
std::vector<std::string> symbols;
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) {
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) {
if (kind == SymbolKind::GlobalSymbol)
symbols.push_back(symbol.str());
// TextAPI ObjC Class Kinds represents two symbols.
Expand Down Expand Up @@ -655,10 +656,11 @@ void swift::writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os,
}

class APIGenRecorder final : public APIRecorder {
bool isSPI(const ValueDecl* VD) {
assert(VD);
return VD->isSPI() || VD->isAvailableAsSPI();
static bool isSPI(const Decl *decl) {
assert(decl);
return decl->isSPI() || decl->isAvailableAsSPI();
}

public:
APIGenRecorder(apigen::API &api, ModuleDecl *module)
: api(api), module(module) {
Expand All @@ -667,26 +669,17 @@ class APIGenRecorder final : public APIRecorder {
}
~APIGenRecorder() {}

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

apigen::APIAvailability availability;
auto access = apigen::APIAccess::Public;
if (source.kind == SymbolSource::Kind::SIL) {
auto ref = source.getSILDeclRef();
if (ref.hasDecl()) {
availability = getAvailability(ref.getDecl());
if (isSPI(ref.getDecl()))
access = apigen::APIAccess::Private;
}
} else if (source.kind == SymbolSource::Kind::IR) {
auto ref = source.getIRLinkEntity();
if (ref.hasDecl()) {
if (isSPI(ref.getDecl()))
access = apigen::APIAccess::Private;
}
if (decl) {
availability = getAvailability(decl);
if (isSPI(decl))
access = apigen::APIAccess::Private;
}

api.addSymbol(symbol, moduleLoc, apigen::APILinkage::Exported,
Expand All @@ -712,7 +705,7 @@ class APIGenRecorder final : public APIRecorder {
if (method.getDecl()->getDescriptiveKind() ==
DescriptiveDeclKind::ClassMethod)
isInstanceMethod = false;
if (method.getDecl()->isSPI())
if (isSPI(method.getDecl()))
access = apigen::APIAccess::Private;
}

Expand Down Expand Up @@ -778,7 +771,7 @@ class APIGenRecorder final : public APIRecorder {
superCls = super->getObjCRuntimeName(buffer);
apigen::APIAvailability availability = getAvailability(decl);
apigen::APIAccess access =
decl->isSPI() ? apigen::APIAccess::Private : apigen::APIAccess::Public;
isSPI(decl) ? apigen::APIAccess::Private : apigen::APIAccess::Public;
apigen::APILinkage linkage =
decl->getFormalAccess() == AccessLevel::Public && decl->isObjC()
? apigen::APILinkage::Exported
Expand Down Expand Up @@ -811,7 +804,7 @@ class APIGenRecorder final : public APIRecorder {
buildCategoryName(decl, cls, nameBuffer);
apigen::APIAvailability availability = getAvailability(decl);
apigen::APIAccess access =
decl->isSPI() ? apigen::APIAccess::Private : apigen::APIAccess::Public;
isSPI(decl) ? apigen::APIAccess::Private : apigen::APIAccess::Public;
apigen::APILinkage linkage =
decl->getMaxAccessLevel() == AccessLevel::Public
? apigen::APILinkage::Exported
Expand Down Expand Up @@ -863,7 +856,8 @@ SymbolSourceMapRequest::evaluate(Evaluator &evaluator,
auto &Ctx = desc.getParentModule()->getASTContext();
auto *SymbolSources = Ctx.Allocate<SymbolSourceMap>();

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

Expand Down
9 changes: 5 additions & 4 deletions lib/IRGen/TBDGenVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class APIRecorder {
virtual ~APIRecorder() {}

virtual void addSymbol(StringRef name, llvm::MachO::SymbolKind kind,
SymbolSource source) {}
SymbolSource source, Decl *decl) {}
virtual void addObjCInterface(const ClassDecl *decl) {}
virtual void addObjCCategory(const ExtensionDecl *decl) {}
virtual void addObjCMethod(const GenericContext *ctx, SILDeclRef method) {}
Expand All @@ -71,14 +71,15 @@ class APIRecorder {
class SimpleAPIRecorder final : public APIRecorder {
public:
using SymbolCallbackFn = llvm::function_ref<void(
StringRef, llvm::MachO::SymbolKind, SymbolSource)>;
StringRef, llvm::MachO::SymbolKind, SymbolSource, Decl *)>;

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

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

private:
SymbolCallbackFn func;
};
Expand Down
21 changes: 13 additions & 8 deletions lib/SIL/IR/SILSymbolVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,19 +646,24 @@ class SILSymbolVisitorImpl : public ASTVisitor<SILSymbolVisitorImpl> {
void addMethod(SILDeclRef method) {
assert(method.getDecl()->getDeclContext() == CD);

if (VirtualFunctionElimination || CD->hasResilientMetadata()) {
if (FirstTime) {
FirstTime = false;

// If the class is itself resilient and has at least one vtable
// entry, it has a method lookup function.
// If the class is itself resilient and has at least one vtable
// entry, it has a method lookup function.
bool hasLookupFunc =
VirtualFunctionElimination || CD->hasResilientMetadata();
if (FirstTime) {
FirstTime = false;

if (hasLookupFunc)
Visitor.addMethodLookupFunction(CD);
}
}

if (!Visitor.willVisitDecl(method.getDecl()))
return;
if (hasLookupFunc)
Visitor.addDispatchThunk(method);
}

Visitor.addMethodDescriptor(method);
Visitor.didVisitDecl(method.getDecl());
}

void addMethodOverride(SILDeclRef baseRef, SILDeclRef derivedRef) {}
Expand Down
3 changes: 2 additions & 1 deletion test/APIJSON/access.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

// REQUIRES: objc_interop, OS=macosx
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/ModuleCache)
// RUN: cp %s %t/MyModule.swiftinterface
// RUN: %target-swift-api-extract -target x86_64-apple-macos11.0 -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s
// RUN: %target-swift-api-extract -target x86_64-apple-macos11.0 -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s

public func publicFunction()
internal func internalFunction()
Expand Down
66 changes: 52 additions & 14 deletions test/APIJSON/apigen.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// REQUIRES: objc_interop, OS=macosx
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s
// RUN: %empty-directory(%t/ModuleCache)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s

import Foundation

@available(macOS 10.13, *)
public class Test : NSObject {
@objc public func method1() {}
@available(macOS 10.14, *)
@objc public class func method2() {}
public func nonObjc() {}
}
Expand Down Expand Up @@ -42,6 +44,9 @@ public func myFunction1() {}
@available(*, unavailable)
public func myFunction2() {}

@available(macOS 10.13, *)
public var myGlobalVar: Int = 42

// CHECK: "target"
// CHECK-NEXT: "globals": [
// CHECK-NEXT: {
Expand All @@ -66,6 +71,27 @@ public func myFunction2() {}
// CHECK-NEXT: "unavailable": true
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivM",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivg",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivs",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method1yyFTj",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
Expand All @@ -81,13 +107,15 @@ public func myFunction2() {}
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method2yyFZTj",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.14"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method2yyFZTq",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.14"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7nonObjcyyFTj",
Expand Down Expand Up @@ -117,31 +145,36 @@ public func myFunction2() {}
// CHECK-NEXT: "name": "_$s8MyModule4TestCMa",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCMn",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCMo",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCMu",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCN",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCfD",
Expand Down Expand Up @@ -291,25 +324,29 @@ public func myFunction2() {}
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCMa",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCMn",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCMo",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCN",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCfD",
Expand Down Expand Up @@ -342,7 +379,8 @@ public func myFunction2() {}
// CHECK-NEXT: {
// CHECK-NEXT: "name": "method2",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface"
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "introduced": "10.14"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
Expand Down
7 changes: 4 additions & 3 deletions test/APIJSON/extension.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// REQUIRES: objc_interop, OS=macosx
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s
// RUN: %empty-directory(%t/ModuleCache)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s

import Foundation

Expand Down Expand Up @@ -105,4 +106,4 @@ extension B {
// CHECK-NEXT: ],
// CHECK-NEXT: "classMethods": []
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: ],
5 changes: 3 additions & 2 deletions test/APIJSON/non-objc-class.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// REQUIRES: objc_interop, OS=macosx
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t | %FileCheck %s
// RUN: %empty-directory(%t/ModuleCache)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) %s -typecheck -parse-as-library -emit-module-interface-path %t/MyModule.swiftinterface -enable-library-evolution -module-name MyModule -swift-version 5
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftinterface -module-name MyModule -module-cache-path %t/ModuleCache | %FileCheck %s

import Foundation

Expand Down
2 changes: 1 addition & 1 deletion test/APIJSON/non-swift-api.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// RUN: cp %S/Inputs/module.modulemap %t/NativeDep.framework/Modules
// RUN: cp %S/Inputs/NativeDep.h %t/NativeDep.framework/Headers

// RUN: %target-swift-frontend %s -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5
// RUN: %target-swift-frontend %s -parse-as-library -emit-module -emit-module-interface-path %t/MyModule.swiftinterface -emit-module-path %t/MyModule.swiftmodule -F %t -enable-library-evolution -module-cache-path %t/cache -module-name MyModule -swift-version 5

/// Check that both swiftmodule and swiftinterface can be used as input.
// RUN: %target-swift-api-extract -o - -pretty-print %t/MyModule.swiftmodule -module-name MyModule -module-cache-path %t/cache -F %t | %FileCheck %s
Expand Down
Loading