Skip to content

Use IRGen's LinkInfo in TBDGen. #8596

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
Apr 7, 2017
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
16 changes: 12 additions & 4 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,25 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/IR/GlobalValue.h"

namespace llvm {
class Triple;
}

namespace swift {
namespace irgen {
class IRGenModule;

/// Determine if the triple uses the DLL storage.
bool useDllStorage(const llvm::Triple &triple);

class UniversalLinkageInfo {
public:
bool IsELFObject, UseDLLStorage, HasMultipleIGMs, IsWholeModule,
IsWholeModuleSerialized;
bool IsELFObject, UseDLLStorage, HasMultipleIGMs, IsWholeModule;

UniversalLinkageInfo(IRGenModule &IGM);

UniversalLinkageInfo(const llvm::Triple &triple, bool hasMultipleIGMs,
bool isWholeModule);
};

/// Selector for type metadata symbol kinds.
Expand Down Expand Up @@ -572,8 +581,7 @@ class LinkEntity {
/// Returns true if this function or global variable may be inlined into
/// another module.
///
bool isFragile(ForDefinition_t isDefinition,
bool wholeModuleSerialized) const;
bool isFragile(ForDefinition_t isDefinition) const;

const ValueDecl *getDecl() const {
assert(isDeclKind(getKind()));
Expand Down
3 changes: 2 additions & 1 deletion include/swift/TBDGen/TBDGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
namespace swift {
class FileUnit;

void enumeratePublicSymbols(FileUnit *module, llvm::StringSet<> &symbols);
void enumeratePublicSymbols(FileUnit *module, llvm::StringSet<> &symbols,
bool hasMultipleIRGenThreads, bool isWholeModule);
} // end namespace swift

#endif
17 changes: 12 additions & 5 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,9 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
}

if (Action == FrontendOptions::EmitTBD) {
return writeTBD(Instance->getMainModule(), opts.getSingleOutputFilename());
auto hasMultipleIRGenThreads = Invocation.getSILOptions().NumThreads > 1;
return writeTBD(Instance->getMainModule(), hasMultipleIRGenThreads,
opts.getSingleOutputFilename());
}

assert(Action >= FrontendOptions::EmitSILGen &&
Expand Down Expand Up @@ -761,10 +763,15 @@ static bool performCompile(std::unique_ptr<CompilerInstance> &Instance,
}

if (opts.ValidateTBDAgainstIR) {
bool validationError =
PrimarySourceFile ? validateTBD(PrimarySourceFile, *IRModule)
: validateTBD(Instance->getMainModule(), *IRModule);
if (validationError)
auto hasMultipleIRGenThreads = Invocation.getSILOptions().NumThreads > 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting should not influence the set of public symbols we emit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just passing through all the options that IRGen is asking for ( https://github.com/apple/swift/blob/d1c5de1cea6c388c78266cc1b691074d06b6eb33/lib/IRGen/GenDecl.cpp#L1372-L1386 ), to make sure we're matching as closely as possible. If you think this isn't required I'd be very happy to get rid of it.

bool error;
if (PrimarySourceFile)
error =
validateTBD(PrimarySourceFile, *IRModule, hasMultipleIRGenThreads);
else
error = validateTBD(Instance->getMainModule(), *IRModule,
hasMultipleIRGenThreads);
if (error)
return true;
}

Expand Down
18 changes: 12 additions & 6 deletions lib/FrontendTool/TBD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ static std::vector<StringRef> sortSymbols(llvm::StringSet<> &symbols) {
return sorted;
}

bool swift::writeTBD(ModuleDecl *M, StringRef OutputFilename) {
bool swift::writeTBD(ModuleDecl *M, bool hasMultipleIRGenThreads,
StringRef OutputFilename) {
std::error_code EC;
llvm::raw_fd_ostream OS(OutputFilename, EC, llvm::sys::fs::F_None);
if (EC) {
Expand All @@ -48,7 +49,8 @@ bool swift::writeTBD(ModuleDecl *M, StringRef OutputFilename) {
}
llvm::StringSet<> symbols;
for (auto file : M->getFiles())
enumeratePublicSymbols(file, symbols);
enumeratePublicSymbols(file, symbols, hasMultipleIRGenThreads,
/*isWholeModule=*/true);

// Ensure the order is stable.
for (auto &symbol : sortSymbols(symbols)) {
Expand Down Expand Up @@ -103,17 +105,21 @@ static bool validateSymbolSet(DiagnosticEngine &diags,
return error;
}

bool swift::validateTBD(ModuleDecl *M, llvm::Module &IRModule) {
bool swift::validateTBD(ModuleDecl *M, llvm::Module &IRModule,
bool hasMultipleIRGenThreads) {
llvm::StringSet<> symbols;
for (auto file : M->getFiles())
enumeratePublicSymbols(file, symbols);
enumeratePublicSymbols(file, symbols, hasMultipleIRGenThreads,
/*isWholeModule=*/true);

return validateSymbolSet(M->getASTContext().Diags, symbols, IRModule);
}

bool swift::validateTBD(FileUnit *file, llvm::Module &IRModule) {
bool swift::validateTBD(FileUnit *file, llvm::Module &IRModule,
bool hasMultipleIRGenThreads) {
llvm::StringSet<> symbols;
enumeratePublicSymbols(file, symbols);
enumeratePublicSymbols(file, symbols, hasMultipleIRGenThreads,
/*isWholeModule=*/false);

return validateSymbolSet(file->getParentModule()->getASTContext().Diags,
symbols, IRModule);
Expand Down
10 changes: 7 additions & 3 deletions lib/FrontendTool/TBD.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ class Module;
namespace swift {
class ModuleDecl;
class FileUnit;
class FrontendOptions;

bool writeTBD(ModuleDecl *M, llvm::StringRef OutputFilename);
bool validateTBD(ModuleDecl *M, llvm::Module &IRModule);
bool validateTBD(FileUnit *M, llvm::Module &IRModule);
bool writeTBD(ModuleDecl *M, bool hasMultipleIRGenThreads,
llvm::StringRef OutputFilename);
bool validateTBD(ModuleDecl *M, llvm::Module &IRModule,
bool hasMultipleIRGenThreads);
bool validateTBD(FileUnit *M, llvm::Module &IRModule,
bool hasMultipleIRGenThreads);
}

#endif
41 changes: 15 additions & 26 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1082,14 +1082,8 @@ static SILLinkage getNonUniqueSILLinkage(FormalLinkage linkage,
SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
// For when `this` is a protocol conformance of some kind.
auto getLinkageAsConformance = [&] {
auto linkage = getLinkageForProtocolConformance(
return getLinkageForProtocolConformance(
getProtocolConformance()->getRootNormalConformance(), forDefinition);

// A hidden-external conformance doesn't make sense: we can't refer to
// it. Thus, the only way to end up in that situation is if the linkage is
// actually public.
return linkage == SILLinkage::HiddenExternal ? SILLinkage::PublicExternal
: linkage;
};

switch (getKind()) {
Expand Down Expand Up @@ -1281,8 +1275,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
llvm_unreachable("bad link entity kind");
}

bool LinkEntity::isFragile(ForDefinition_t isDefinition,
bool wholeModuleSerialized) const {
bool LinkEntity::isFragile(ForDefinition_t isDefinition) const {
switch (getKind()) {
case Kind::SILFunction:
return getSILFunction()->isSerialized();
Expand All @@ -1304,16 +1297,14 @@ bool LinkEntity::isFragile(ForDefinition_t isDefinition,
}
if (isProtocolConformanceKind(getKind())) {
auto conformance = getProtocolConformance();
SILLinkage L = getLinkageForProtocolConformance(
conformance->getRootNormalConformance(), isDefinition);

// We don't deserialize the fragile attribute correctly. But we know that
// if the witness table was deserialized (= available externally) and it's
// not public, it must be fragile.
if (swift::isAvailableExternally(L) && !hasPublicVisibility(L))
return true;
auto conformanceModule = conformance->getDeclContext()->getParentModule();
auto isCompletelySerialized = conformanceModule->getResilienceStrategy() ==
ResilienceStrategy::Fragile;

return wholeModuleSerialized || conformance->hasFixedLayout();
// The conformance is fragile if it is in a -sil-serialize-all module, or
// has a fully publicly determined layout.
return isCompletelySerialized || conformance->hasFixedLayout();
}
return false;
}
Expand Down Expand Up @@ -1436,11 +1427,10 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
// TODO: there are probably cases where we can avoid redoing the
// entire linkage computation.
UniversalLinkageInfo linkInfo(IGM);
auto linkage = getIRLinkage(
linkInfo, entity.getLinkage(ForDefinition),
entity.isFragile(ForDefinition, linkInfo.IsWholeModuleSerialized),
entity.isSILOnly(), ForDefinition,
entity.isWeakImported(IGM.getSwiftModule()));
auto linkage =
getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
entity.isFragile(ForDefinition), entity.isSILOnly(),
ForDefinition, entity.isWeakImported(IGM.getSwiftModule()));
global->setLinkage(std::get<0>(linkage));
global->setVisibility(std::get<1>(linkage));
global->setDLLStorageClass(std::get<2>(linkage));
Expand Down Expand Up @@ -1470,10 +1460,9 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
entity.mangle(result.Name);

std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
getIRLinkage(
linkInfo, entity.getLinkage(isDefinition),
entity.isFragile(isDefinition, linkInfo.IsWholeModuleSerialized),
entity.isSILOnly(), isDefinition, entity.isWeakImported(swiftModule));
getIRLinkage(linkInfo, entity.getLinkage(isDefinition),
entity.isFragile(isDefinition), entity.isSILOnly(),
isDefinition, entity.isWeakImported(swiftModule));

result.ForDefinition = isDefinition;

Expand Down
5 changes: 0 additions & 5 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,6 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
return ClangCodeGen;
}

/// A helper for determining if the triple uses the DLL storage
static bool useDllStorage(const llvm::Triple &Triple) {
return Triple.isOSBinFormatCOFF() && !Triple.isOSCygMing();
}

IRGenModule::IRGenModule(IRGenerator &irgen,
std::unique_ptr<llvm::TargetMachine> &&target,
SourceFile *SF, llvm::LLVMContext &LLVMContext,
Expand Down
19 changes: 14 additions & 5 deletions lib/IRGen/Linking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,27 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;
using namespace irgen;

bool swift::irgen::useDllStorage(const llvm::Triple &triple) {
return triple.isOSBinFormatCOFF() && !triple.isOSCygMing();
}

UniversalLinkageInfo::UniversalLinkageInfo(IRGenModule &IGM)
: IsELFObject(IGM.TargetInfo.OutputObjectFormat == llvm::Triple::ELF),
UseDLLStorage(IGM.useDllStorage()),
HasMultipleIGMs(IGM.IRGen.hasMultipleIGMs()),
IsWholeModule(IGM.getSILModule().isWholeModule()),
IsWholeModuleSerialized(IGM.getSILModule().isWholeModuleSerialized()) {}
: UniversalLinkageInfo(IGM.Triple, IGM.IRGen.hasMultipleIGMs(),
IGM.getSILModule().isWholeModule()) {}

UniversalLinkageInfo::UniversalLinkageInfo(const llvm::Triple &triple,
bool hasMultipleIGMs,
bool isWholeModule)
: IsELFObject(triple.isOSBinFormatELF()),
UseDLLStorage(useDllStorage(triple)), HasMultipleIGMs(hasMultipleIGMs),
IsWholeModule(isWholeModule) {}

/// Mangle this entity into the given buffer.
void LinkEntity::mangle(SmallVectorImpl<char> &buffer) const {
Expand Down
68 changes: 44 additions & 24 deletions lib/TBDGen/TBDGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
#include "swift/IRGen/Linking.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/SILDeclRef.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/ADT/StringSet.h"

using namespace swift;
using namespace swift::irgen;
using StringSet = llvm::StringSet<>;

static bool isPrivateDecl(ValueDecl *VD) {
Expand All @@ -35,23 +37,38 @@ static bool isPrivateDecl(ValueDecl *VD) {
namespace {
class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
StringSet &Symbols;
const UniversalLinkageInfo &UniversalLinkInfo;
ModuleDecl *SwiftModule;

void addSymbol(StringRef name) {
auto isNewValue = Symbols.insert(name).second;
(void)isNewValue;
assert(isNewValue && "already inserted");
}

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

auto externallyVisible =
llvm::GlobalValue::isExternalLinkage(linkage.getLinkage()) &&
linkage.getVisibility() != llvm::GlobalValue::HiddenVisibility;

if (externallyVisible)
addSymbol(linkage.getName());
}

void visitValueTypeDecl(NominalTypeDecl *NTD) {
assert(isa<StructDecl>(NTD) || isa<EnumDecl>(NTD));
if (isPrivateDecl(NTD))
return;

visitNominalTypeDecl(NTD);
}

public:
TBDGenVisitor(StringSet &symbols) : Symbols(symbols) {}
TBDGenVisitor(StringSet &symbols,
const UniversalLinkageInfo &universalLinkInfo,
ModuleDecl *swiftModule)
: Symbols(symbols), UniversalLinkInfo(universalLinkInfo),
SwiftModule(swiftModule) {}

void visitMembers(Decl *D) {
SmallVector<Decl *, 4> members;
Expand Down Expand Up @@ -83,36 +100,34 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
void visitNominalTypeDecl(NominalTypeDecl *NTD) {
auto declaredType = NTD->getDeclaredType()->getCanonicalType();

auto ntDescriptor = irgen::LinkEntity::forNominalTypeDescriptor(NTD);
addSymbol(ntDescriptor.mangleAsString());
addSymbol(LinkEntity::forNominalTypeDescriptor(NTD));

auto tmd = irgen::LinkEntity::forTypeMetadata(
declaredType, irgen::TypeMetadataAddress::AddressPoint,
/*isPattern=*/false);
addSymbol(tmd.mangleAsString());
auto tmda = irgen::LinkEntity::forTypeMetadataAccessFunction(declaredType);
addSymbol(tmda.mangleAsString());
addSymbol(LinkEntity::forTypeMetadata(declaredType,
TypeMetadataAddress::AddressPoint,
/*isPattern=*/false));
addSymbol(LinkEntity::forTypeMetadataAccessFunction(declaredType));

if (isPrivateDecl(NTD))
return;
// There are symbols associated with any protocols this type conforms to.
for (auto conformance : NTD->getLocalConformances()) {
auto needsWTable = Lowering::TypeConverter::protocolRequiresWitnessTable(
conformance->getProtocol());
if (!needsWTable)
continue;

addSymbol(LinkEntity::forDirectProtocolWitnessTable(conformance));
addSymbol(LinkEntity::forProtocolWitnessTableAccessFunction(conformance));
}

visitMembers(NTD);
}
void visitClassDecl(ClassDecl *CD) {
if (isPrivateDecl(CD))
return;

visitNominalTypeDecl(CD);
}

void visitStructDecl(StructDecl *SD) { visitValueTypeDecl(SD); }
void visitEnumDecl(EnumDecl *ED) { visitValueTypeDecl(ED); }
void visitProtocolDecl(ProtocolDecl *PD) {
if (isPrivateDecl(PD))
return;

auto pDescriptor = irgen::LinkEntity::forProtocolDescriptor(PD);
addSymbol(pDescriptor.mangleAsString());
addSymbol(LinkEntity::forProtocolDescriptor(PD));

// There's no relevant information about members of a protocol at individual
// protocols, each conforming type has to handle them individually.
Expand Down Expand Up @@ -145,11 +160,16 @@ void TBDGenVisitor::visitVarDecl(VarDecl *VD) {
visitMembers(VD);
}

void swift::enumeratePublicSymbols(FileUnit *file, StringSet &symbols) {
void swift::enumeratePublicSymbols(FileUnit *file, StringSet &symbols,
bool hasMultipleIRGenThreads,
bool isWholeModule) {
UniversalLinkageInfo linkInfo(file->getASTContext().LangOpts.Target,
hasMultipleIRGenThreads, isWholeModule);

SmallVector<Decl *, 16> decls;
file->getTopLevelDecls(decls);

TBDGenVisitor visitor(symbols);
TBDGenVisitor visitor(symbols, linkInfo, file->getParentModule());
for (auto d : decls)
visitor.visit(d);
}
Loading