Fix linkage of 'static inline' Clang-imported definitions

If an external SIL function has a Clang-generated body, I think this
means we have a static function, and we want to use Shared linkage,
not Public.

Add a new flag to SILFunction for this and plumb it through to
appease assertions from SILVerifier.

Swift SVN r31763
This commit is contained in:
Slava Pestov
2015-09-08 06:26:35 +00:00
parent ae6afdda54
commit fc0a18be3f
9 changed files with 62 additions and 12 deletions

View File

@@ -348,10 +348,14 @@ struct SILDeclRef {
/// True if the referenced entity is some kind of thunk. /// True if the referenced entity is some kind of thunk.
bool isThunk() const; bool isThunk() const;
/// True if the referenced entity is generated on behalf of the Clang /// True if the referenced entity is emitted by Swift on behalf of the Clang
/// importer. /// importer.
bool isClangImported() const; bool isClangImported() const;
/// True if the referenced entity is emitted by Clang on behalf of the Clang
/// importer.
bool isClangGenerated() const;
bool isImplicit() const { bool isImplicit() const {
if (hasDecl()) if (hasDecl())
return getDecl()->isImplicit(); return getDecl()->isImplicit();

View File

@@ -120,11 +120,13 @@ private:
/// The linkage of the function. /// The linkage of the function.
unsigned Linkage : NumSILLinkageBits; unsigned Linkage : NumSILLinkageBits;
/// This flags indicates if a function can be /// This flag indicates if a function can be eliminated by dead function
/// eliminated by dead function elimination. /// elimination. If it is unset, DFE will preserve the function and make
/// If it is unset, DFE will preserve the function /// it public.
/// and make it public. unsigned KeepAsPublic : 1;
unsigned KeepAsPublic: 1;
/// This flag indicates if a function has a body generated by Clang.
unsigned ForeignBody : 1;
/// This is the number of uses of this SILFunction inside the SIL. /// This is the number of uses of this SILFunction inside the SIL.
/// It does not include references from debug scopes. /// It does not include references from debug scopes.
@@ -421,6 +423,10 @@ public:
bool isKeepAsPublic() const { return KeepAsPublic; } bool isKeepAsPublic() const { return KeepAsPublic; }
void setKeepAsPublic(bool keep) { KeepAsPublic = keep; } void setKeepAsPublic(bool keep) { KeepAsPublic = keep; }
/// Get this function's foreign body attribute.
HasForeignBody_t hasForeignBody() const { return HasForeignBody_t(ForeignBody); }
void setForeignBody(HasForeignBody_t foreign) { ForeignBody = foreign; }
/// Retrieve the generic parameter list containing the contextual archetypes /// Retrieve the generic parameter list containing the contextual archetypes
/// of the function. /// of the function.
/// ///

View File

@@ -84,12 +84,18 @@ enum {
NumSILLinkageBits = 3 NumSILLinkageBits = 3
}; };
/// Reslated to linkage: flag if a function or global variable is fragle. /// Related to linkage: flag if a function or global variable is fragile.
enum IsFragile_t { enum IsFragile_t {
IsNotFragile, IsNotFragile,
IsFragile IsFragile
}; };
/// True if we have an inline body generated by Clang.
enum HasForeignBody_t {
DoesNotHaveForeignBody,
HasForeignBody
};
/// Strip external from public_external, hidden_external. Otherwise just return /// Strip external from public_external, hidden_external. Otherwise just return
/// the linkage. /// the linkage.
inline SILLinkage stripExternalFromLinkage(SILLinkage linkage) { inline SILLinkage stripExternalFromLinkage(SILLinkage linkage) {

View File

@@ -215,6 +215,9 @@ bool SILDeclRef::isClangImported() const {
DeclContext *moduleContext = d->getDeclContext()->getModuleScopeContext(); DeclContext *moduleContext = d->getDeclContext()->getModuleScopeContext();
if (isa<ClangModuleUnit>(moduleContext)) { if (isa<ClangModuleUnit>(moduleContext)) {
if (isClangGenerated())
return true;
if (isa<ConstructorDecl>(d) || isa<EnumElementDecl>(d)) if (isa<ConstructorDecl>(d) || isa<EnumElementDecl>(d))
return true; return true;
@@ -226,6 +229,21 @@ bool SILDeclRef::isClangImported() const {
return false; return false;
} }
bool SILDeclRef::isClangGenerated() const {
if (!hasDecl())
return false;
if (auto *FD = dyn_cast<FuncDecl>(getDecl())) {
auto clangNode = FD->getClangNode().getAsDecl();
if (auto fd = dyn_cast_or_null<clang::FunctionDecl>(clangNode)) {
if (fd->hasBody())
return true;
}
}
return false;
}
SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const { SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
// Anonymous functions have local linkage. // Anonymous functions have local linkage.
if (auto closure = getAbstractClosureExpr()) if (auto closure = getAbstractClosureExpr())

View File

@@ -89,6 +89,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
InlineStrategy(inlineStrategy), InlineStrategy(inlineStrategy),
Linkage(unsigned(Linkage)), Linkage(unsigned(Linkage)),
KeepAsPublic(false), KeepAsPublic(false),
ForeignBody(false),
EK(E) { EK(E) {
if (InsertBefore) if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this); Module.functions.insert(SILModule::iterator(InsertBefore), this);

View File

@@ -359,10 +359,14 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
F->setDebugScope(new (*this) SILDebugScope(loc, *F)); F->setDebugScope(new (*this) SILDebugScope(loc, *F));
F->setGlobalInit(constant.isGlobal()); F->setGlobalInit(constant.isGlobal());
if (constant.hasDecl()) if (constant.hasDecl()) {
if (constant.isForeign && constant.isClangGenerated())
F->setForeignBody(HasForeignBody);
if (auto SemanticsA = if (auto SemanticsA =
constant.getDecl()->getAttrs().getAttribute<SemanticsAttr>()) constant.getDecl()->getAttrs().getAttribute<SemanticsAttr>())
F->setSemanticsAttr(SemanticsA->Value); F->setSemanticsAttr(SemanticsA->Value);
}
F->setDeclContext(constant.hasDecl() ? constant.getDecl() : nullptr); F->setDeclContext(constant.hasDecl() ? constant.getDecl() : nullptr);

View File

@@ -2947,16 +2947,21 @@ public:
verifySILFunctionType(FTy); verifySILFunctionType(FTy);
if (F->isExternalDeclaration()) { if (F->isExternalDeclaration()) {
if (F->hasForeignBody())
return;
assert(F->isAvailableExternally() && assert(F->isAvailableExternally() &&
"external declaration of internal SILFunction not allowed"); "external declaration of internal SILFunction not allowed");
assert(!hasSharedVisibility(F->getLinkage()) && assert(!hasSharedVisibility(F->getLinkage()) &&
"external declarations of SILFunctions with shared visiblity is not " "external declarations of SILFunctions with shared visibility is not "
"allowed"); "allowed");
// If F is an external declaration, there is nothing further to do, // If F is an external declaration, there is nothing further to do,
// return. // return.
return; return;
} }
assert(!F->hasForeignBody());
// Make sure that our SILFunction only has context generic params if our // Make sure that our SILFunction only has context generic params if our
// SILFunctionType is non-polymorphic. // SILFunctionType is non-polymorphic.
if (F->getContextGenericParams()) { if (F->getContextGenericParams()) {

View File

@@ -6,7 +6,7 @@ import c_layout
func blackHole<T>(t: T) { } func blackHole<T>(t: T) { }
// CHECK: @staticFloat = internal global float 1.700000e+01, align 4 // CHECK: @staticFloat = internal global float 1.700000e+01, align 4
// CHECK: define {{.*}}void @doubleTrouble() [[CLANG_FUNC_ATTR:#[0-9]+]] { // CHECK: define internal void @doubleTrouble() [[CLANG_FUNC_ATTR:#[0-9]+]] {
public func testStaticGlobal() { public func testStaticGlobal() {
blackHole(c_layout.staticFloat) blackHole(c_layout.staticFloat)

View File

@@ -4,8 +4,14 @@
- (Ansible*)initWithBellsOn:(id)theBells; - (Ansible*)initWithBellsOn:(id)theBells;
@end @end
Ansible *NSAnse(Ansible *x) { static Ansible *NSAnse(Ansible *x) {
return x;
}
Ansible *NSAnseExternal(Ansible *x) {
return x; return x;
} }
void hasNoPrototype(); void hasNoPrototype();
static void staticForwardDeclaration(void);