Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
Bob Wilson
2017-04-05 17:26:52 -07:00
38 changed files with 509 additions and 335 deletions

View File

@@ -27,34 +27,35 @@
#include "swift/AST/TypeMemberVisitor.h"
#include "swift/AST/Types.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/IRGen/Linking.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/GlobalDecl.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TypeBuilder.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Path.h"
#include "ConstantBuilder.h"
#include "Explosion.h"
#include "FixedTypeInfo.h"
#include "GenCall.h"
#include "GenClass.h"
#include "GenDecl.h"
#include "GenMeta.h"
#include "GenObjC.h"
#include "GenOpaque.h"
#include "GenMeta.h"
#include "GenType.h"
#include "IRGenDebugInfo.h"
#include "IRGenFunction.h"
#include "IRGenModule.h"
#include "Linking.h"
using namespace swift;
using namespace irgen;
@@ -1079,18 +1080,19 @@ static SILLinkage getNonUniqueSILLinkage(FormalLinkage linkage,
llvm_unreachable("bad formal linkage");
}
static SILLinkage getConformanceLinkage(IRGenModule &IGM,
const ProtocolConformance *conf) {
if (auto wt = IGM.getSILModule().lookUpWitnessTable(conf,
/*deserializeLazily*/ false)) {
return wt->getLinkage();
} else {
return SILLinkage::PublicExternal;
}
}
SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
// For when `this` is a protocol conformance of some kind.
auto getLinkageAsConformance = [&] {
auto linkage = 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;
};
SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
ForDefinition_t forDefinition) const {
switch (getKind()) {
// Most type metadata depend on the formal linkage of their type.
case Kind::ValueWitnessTable: {
@@ -1101,7 +1103,7 @@ SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
// Imported types.
if (getTypeMetadataAccessStrategy(IGM, type) ==
if (getTypeMetadataAccessStrategy(type) ==
MetadataAccessStrategy::NonUniqueAccessor)
return SILLinkage::Shared;
@@ -1113,7 +1115,7 @@ SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
auto type = getType();
// Imported types, non-primitive structural types.
if (getTypeMetadataAccessStrategy(IGM, type) ==
if (getTypeMetadataAccessStrategy(type) ==
MetadataAccessStrategy::NonUniqueAccessor)
return SILLinkage::Shared;
@@ -1143,7 +1145,7 @@ SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
return SILLinkage::Shared;
case Kind::TypeMetadataAccessFunction:
switch (getTypeMetadataAccessStrategy(IGM, getType())) {
switch (getTypeMetadataAccessStrategy(getType())) {
case MetadataAccessStrategy::PublicUniqueAccessor:
return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
case MetadataAccessStrategy::HiddenUniqueAccessor:
@@ -1171,13 +1173,12 @@ SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
case Kind::DirectProtocolWitnessTable:
case Kind::ProtocolWitnessTableAccessFunction:
return getConformanceLinkage(IGM, getProtocolConformance());
return getLinkageAsConformance();
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::ProtocolWitnessTableLazyCacheVariable:
if (getTypeLinkage(getType()) == FormalLinkage::Private ||
getConformanceLinkage(IGM, getProtocolConformance())
== SILLinkage::Private) {
getLinkageAsConformance() == SILLinkage::Private) {
return SILLinkage::Private;
} else {
return SILLinkage::Shared;
@@ -1203,8 +1204,7 @@ SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
return SILLinkage::Shared;
return SILLinkage::Private;
case Kind::ReflectionAssociatedTypeDescriptor:
if (getConformanceLinkage(IGM, getProtocolConformance())
== SILLinkage::Shared)
if (getLinkageAsConformance() == SILLinkage::Shared)
return SILLinkage::Shared;
return SILLinkage::Private;
case Kind::ReflectionSuperclassDescriptor:
@@ -1282,7 +1282,8 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
llvm_unreachable("bad link entity kind");
}
bool LinkEntity::isFragile(IRGenModule &IGM) const {
bool LinkEntity::isFragile(ForDefinition_t isDefinition,
bool wholeModuleSerialized) const {
switch (getKind()) {
case Kind::SILFunction:
return getSILFunction()->isSerialized();
@@ -1303,16 +1304,17 @@ bool LinkEntity::isFragile(IRGenModule &IGM) const {
break;
}
if (isProtocolConformanceKind(getKind())) {
if (SILWitnessTable *wt = IGM.getSILModule().lookUpWitnessTable(
getProtocolConformance(), false)) {
SILLinkage L = wt->getLinkage();
// 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;
return wt->isSerialized();
}
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;
return wholeModuleSerialized || conformance->hasFixedLayout();
}
return false;
}
@@ -1320,31 +1322,27 @@ bool LinkEntity::isFragile(IRGenModule &IGM) const {
static std::tuple<llvm::GlobalValue::LinkageTypes,
llvm::GlobalValue::VisibilityTypes,
llvm::GlobalValue::DLLStorageClassTypes>
getIRLinkage(IRGenModule &IGM, SILLinkage linkage, bool isFragile,
bool isSILOnly, ForDefinition_t isDefinition,
getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
bool isFragile, bool isSILOnly, ForDefinition_t isDefinition,
bool isWeakImported) {
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
std::make_tuple(llvm::GlobalValue::LINKAGE##Linkage, \
llvm::GlobalValue::VISIBILITY##Visibility, \
llvm::GlobalValue::DLL_STORAGE##StorageClass)
const auto ObjFormat = IGM.TargetInfo.OutputObjectFormat;
bool IsELFObject = ObjFormat == llvm::Triple::ELF;
bool UseDLLStorage = IGM.useDllStorage();
// Use protected visibility for public symbols we define on ELF. ld.so
// doesn't support relative relocations at load time, which interferes with
// our metadata formats. Default visibility should suffice for other object
// formats.
llvm::GlobalValue::VisibilityTypes PublicDefinitionVisibility =
IsELFObject ? llvm::GlobalValue::ProtectedVisibility
: llvm::GlobalValue::DefaultVisibility;
info.IsELFObject ? llvm::GlobalValue::ProtectedVisibility
: llvm::GlobalValue::DefaultVisibility;
llvm::GlobalValue::DLLStorageClassTypes ExportedStorage =
UseDLLStorage ? llvm::GlobalValue::DLLExportStorageClass
: llvm::GlobalValue::DefaultStorageClass;
info.UseDLLStorage ? llvm::GlobalValue::DLLExportStorageClass
: llvm::GlobalValue::DefaultStorageClass;
llvm::GlobalValue::DLLStorageClassTypes ImportedStorage =
UseDLLStorage ? llvm::GlobalValue::DLLImportStorageClass
: llvm::GlobalValue::DefaultStorageClass;
info.UseDLLStorage ? llvm::GlobalValue::DLLImportStorageClass
: llvm::GlobalValue::DefaultStorageClass;
if (isFragile) {
// Fragile functions/globals must be visible from outside, regardless of
@@ -1382,8 +1380,7 @@ getIRLinkage(IRGenModule &IGM, SILLinkage linkage, bool isFragile,
// TODO: In non-whole-module-opt the generated swiftmodules are "linked" and
// this strips all serialized transparent functions. So we have to code-gen
// transparent functions in non-whole-module-opt.
if (isSILOnly && !IGM.IRGen.hasMultipleIGMs() &&
IGM.getSILModule().isWholeModule())
if (isSILOnly && !info.HasMultipleIGMs && info.IsWholeModule)
return RESULT(Internal, Default, Default);
return std::make_tuple(llvm::GlobalValue::ExternalLinkage,
PublicDefinitionVisibility, ExportedStorage);
@@ -1398,7 +1395,7 @@ getIRLinkage(IRGenModule &IGM, SILLinkage linkage, bool isFragile,
case SILLinkage::Private:
// In case of multiple llvm modules (in multi-threaded compilation) all
// private decls must be visible from other files.
if (IGM.IRGen.hasMultipleIGMs())
if (info.HasMultipleIGMs)
return RESULT(External, Hidden, Default);
return RESULT(Internal, Default, Default);
@@ -1439,10 +1436,12 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
const LinkEntity &entity) {
// TODO: there are probably cases where we can avoid redoing the
// entire linkage computation.
auto linkage =
getIRLinkage(IGM, entity.getLinkage(IGM, ForDefinition),
entity.isFragile(IGM), entity.isSILOnly(), ForDefinition,
entity.isWeakImported(IGM.getSwiftModule()));
UniversalLinkageInfo linkInfo(IGM);
auto linkage = getIRLinkage(
linkInfo, entity.getLinkage(ForDefinition),
entity.isFragile(ForDefinition, linkInfo.IsWholeModuleSerialized),
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));
@@ -1461,14 +1460,21 @@ static void updateLinkageForDefinition(IRGenModule &IGM,
LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
ForDefinition_t isDefinition) {
return LinkInfo::get(IGM, IGM.getSwiftModule(), entity, isDefinition);
}
LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
ModuleDecl *swiftModule, const LinkEntity &entity,
ForDefinition_t isDefinition) {
LinkInfo result;
entity.mangle(result.Name);
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
getIRLinkage(IGM, entity.getLinkage(IGM, isDefinition),
entity.isFragile(IGM), entity.isSILOnly(), isDefinition,
entity.isWeakImported(IGM.getSwiftModule()));
getIRLinkage(
linkInfo, entity.getLinkage(isDefinition),
entity.isFragile(isDefinition, linkInfo.IsWholeModuleSerialized),
entity.isSILOnly(), isDefinition, entity.isWeakImported(swiftModule));
result.ForDefinition = isDefinition;
@@ -1480,27 +1486,31 @@ static bool isPointerTo(llvm::Type *ptrTy, llvm::Type *objTy) {
}
/// Get or create an LLVM function with these linkage rules.
llvm::Function *LinkInfo::createFunction(IRGenModule &IGM,
llvm::FunctionType *fnType,
llvm::CallingConv::ID cc,
const llvm::AttributeList &attrs,
llvm::Function *insertBefore) {
llvm::Function *existing = IGM.Module.getFunction(getName());
llvm::Function *swift::irgen::createFunction(IRGenModule &IGM,
LinkInfo &linkInfo,
llvm::FunctionType *fnType,
llvm::CallingConv::ID cc,
const llvm::AttributeList &attrs,
llvm::Function *insertBefore) {
auto name = linkInfo.getName();
llvm::Function *existing = IGM.Module.getFunction(name);
if (existing) {
if (isPointerTo(existing->getType(), fnType))
return cast<llvm::Function>(existing);
IGM.error(SourceLoc(),
"program too clever: function collides with existing symbol "
+ getName());
"program too clever: function collides with existing symbol " +
name);
// Note that this will implicitly unique if the .unique name is also taken.
existing->setName(getName() + ".unique");
existing->setName(name + ".unique");
}
llvm::Function *fn = llvm::Function::Create(fnType, getLinkage(), getName());
fn->setVisibility(getVisibility());
fn->setDLLStorageClass(getDLLStorage());
llvm::Function *fn =
llvm::Function::Create(fnType, linkInfo.getLinkage(), name);
fn->setVisibility(linkInfo.getVisibility());
fn->setDLLStorageClass(linkInfo.getDLLStorage());
fn->setCallingConv(cc);
if (insertBefore) {
@@ -1522,8 +1532,7 @@ llvm::Function *LinkInfo::createFunction(IRGenModule &IGM,
// Exclude "main", because it should naturally be used, and because adding it
// to llvm.used leaves a dangling use when the REPL attempts to discard
// intermediate mains.
if (isUsed() &&
getName() != SWIFT_ENTRY_POINT_FUNCTION) {
if (linkInfo.isUsed() && name != SWIFT_ENTRY_POINT_FUNCTION) {
IGM.addUsedGlobal(fn);
}
@@ -1543,42 +1552,41 @@ bool LinkInfo::isUsed(llvm::GlobalValue::LinkageTypes Linkage,
}
/// Get or create an LLVM global variable with these linkage rules.
llvm::GlobalVariable *LinkInfo::createVariable(IRGenModule &IGM,
llvm::Type *storageType,
Alignment alignment,
DebugTypeInfo DbgTy,
Optional<SILLocation> DebugLoc,
StringRef DebugName) {
llvm::GlobalValue *existingValue = IGM.Module.getNamedGlobal(getName());
llvm::GlobalVariable *swift::irgen::createVariable(
IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *storageType,
Alignment alignment, DebugTypeInfo DbgTy, Optional<SILLocation> DebugLoc,
StringRef DebugName) {
auto name = linkInfo.getName();
llvm::GlobalValue *existingValue = IGM.Module.getNamedGlobal(name);
if (existingValue) {
auto existingVar = dyn_cast<llvm::GlobalVariable>(existingValue);
if (existingVar && isPointerTo(existingVar->getType(), storageType))
return existingVar;
IGM.error(SourceLoc(),
"program too clever: variable collides with existing symbol "
+ getName());
"program too clever: variable collides with existing symbol " +
name);
// Note that this will implicitly unique if the .unique name is also taken.
existingValue->setName(getName() + ".unique");
existingValue->setName(name + ".unique");
}
auto var = new llvm::GlobalVariable(IGM.Module, storageType,
/*constant*/ false, getLinkage(),
/*initializer*/ nullptr, getName());
var->setVisibility(getVisibility());
var->setDLLStorageClass(getDLLStorage());
/*constant*/ false, linkInfo.getLinkage(),
/*initializer*/ nullptr, name);
var->setVisibility(linkInfo.getVisibility());
var->setDLLStorageClass(linkInfo.getDLLStorage());
var->setAlignment(alignment.getValue());
// Everything externally visible is considered used in Swift.
// That mostly means we need to be good at not marking things external.
if (isUsed()) {
if (linkInfo.isUsed()) {
IGM.addUsedGlobal(var);
}
if (IGM.DebugInfo && !DbgTy.isNull() && ForDefinition)
if (IGM.DebugInfo && !DbgTy.isNull() && linkInfo.isForDefinition())
IGM.DebugInfo->emitGlobalVariableDeclaration(
var, DebugName.empty() ? getName() : DebugName, getName(), DbgTy,
var, DebugName.empty() ? name : DebugName, name, DbgTy,
var->hasInternalLinkage(), DebugLoc);
return var;
@@ -1721,15 +1729,15 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
DebugTypeInfo::getGlobal(var, storageType, fixedSize, fixedAlignment);
if (var->getDecl()) {
// If we have the VarDecl, use it for more accurate debugging information.
gvar = link.createVariable(*this, storageType, fixedAlignment,
DbgTy, SILLocation(var->getDecl()),
var->getDecl()->getName().str());
gvar = createVariable(*this, link, storageType, fixedAlignment, DbgTy,
SILLocation(var->getDecl()),
var->getDecl()->getName().str());
} else {
Optional<SILLocation> loc;
if (var->hasLocation())
loc = var->getLocation();
gvar = link.createVariable(*this, storageType, fixedAlignment,
DbgTy, loc, var->getName());
gvar = createVariable(*this, link, storageType, fixedAlignment, DbgTy, loc,
var->getName());
}
// Set the alignment from the TypeInfo.
@@ -1853,7 +1861,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(SILFunction *f,
llvm::AttributeList::FunctionIndex,
llvm::Attribute::ReadOnly);
}
fn = link.createFunction(*this, fnType, cc, attrs, insertBefore);
fn = createFunction(*this, link, fnType, cc, attrs, insertBefore);
// If we have an order number for this function, set it up as appropriate.
if (hasOrderNumber) {
@@ -1995,7 +2003,7 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, Alignment alignment,
if (!definitionType) definitionType = defaultType;
// Create the variable.
auto var = link.createVariable(*this, definitionType, alignment, DbgTy);
auto var = createVariable(*this, link, definitionType, alignment, DbgTy);
// Install the concrete definition if we have one.
if (definition && definition.hasInit()) {
@@ -2475,7 +2483,7 @@ IRGenModule::getAddrOfTypeMetadataAccessFunction(CanType type,
auto fnType = llvm::FunctionType::get(TypeMetadataPtrTy, false);
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -2500,7 +2508,7 @@ IRGenModule::getAddrOfGenericTypeMetadataAccessFunction(
auto fnType = llvm::FunctionType::get(TypeMetadataPtrTy, genericArgs, false);
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -2817,7 +2825,7 @@ llvm::Function *IRGenModule::getAddrOfValueWitness(CanType abstractType,
cast<llvm::PointerType>(getValueWitnessTy(index))
->getElementType());
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -2850,7 +2858,7 @@ static Address getAddrOfSimpleVariable(IRGenModule &IGM,
// Otherwise, we need to create it.
LinkInfo link = LinkInfo::get(IGM, entity, forDefinition);
auto addr = link.createVariable(IGM, type, alignment);
auto addr = createVariable(IGM, link, type, alignment);
addr->setConstant(true);
entry = addr;
@@ -3152,7 +3160,7 @@ IRGenModule::getAddrOfGenericWitnessTableInstantiationFunction(
Int8PtrPtrTy },
/*varargs*/ false);
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -3200,7 +3208,7 @@ IRGenModule::getAddrOfWitnessTableAccessFunction(
}
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -3222,7 +3230,7 @@ IRGenModule::getAddrOfWitnessTableLazyAccessFunction(
= llvm::FunctionType::get(WitnessTablePtrTy, false);
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -3273,7 +3281,7 @@ IRGenModule::getAddrOfAssociatedTypeMetadataAccessFunction(
auto fnType = getAssociatedTypeMetadataAccessFunctionTy();
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}
@@ -3296,7 +3304,7 @@ IRGenModule::getAddrOfAssociatedTypeWitnessTableAccessFunction(
auto fnType = getAssociatedTypeWitnessTableAccessFunctionTy();
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = link.createFunction(*this, fnType, DefaultCC, llvm::AttributeList());
entry = createFunction(*this, link, fnType, DefaultCC, llvm::AttributeList());
return entry;
}