mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -348,10 +348,14 @@ struct SILDeclRef {
|
||||
/// True if the referenced entity is some kind of thunk.
|
||||
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.
|
||||
bool isClangImported() const;
|
||||
|
||||
/// True if the referenced entity is emitted by Clang on behalf of the Clang
|
||||
/// importer.
|
||||
bool isClangGenerated() const;
|
||||
|
||||
bool isImplicit() const {
|
||||
if (hasDecl())
|
||||
return getDecl()->isImplicit();
|
||||
|
||||
@@ -120,12 +120,14 @@ private:
|
||||
/// The linkage of the function.
|
||||
unsigned Linkage : NumSILLinkageBits;
|
||||
|
||||
/// This flags indicates if a function can be
|
||||
/// eliminated by dead function elimination.
|
||||
/// If it is unset, DFE will preserve the function
|
||||
/// and make it public.
|
||||
/// This flag indicates if a function can be eliminated by dead function
|
||||
/// elimination. If it is unset, DFE will preserve the function and make
|
||||
/// it public.
|
||||
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.
|
||||
/// It does not include references from debug scopes.
|
||||
unsigned RefCount = 0;
|
||||
@@ -421,6 +423,10 @@ public:
|
||||
bool isKeepAsPublic() const { return KeepAsPublic; }
|
||||
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
|
||||
/// of the function.
|
||||
///
|
||||
|
||||
@@ -84,12 +84,18 @@ enum {
|
||||
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 {
|
||||
IsNotFragile,
|
||||
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
|
||||
/// the linkage.
|
||||
inline SILLinkage stripExternalFromLinkage(SILLinkage linkage) {
|
||||
|
||||
@@ -215,6 +215,9 @@ bool SILDeclRef::isClangImported() const {
|
||||
DeclContext *moduleContext = d->getDeclContext()->getModuleScopeContext();
|
||||
|
||||
if (isa<ClangModuleUnit>(moduleContext)) {
|
||||
if (isClangGenerated())
|
||||
return true;
|
||||
|
||||
if (isa<ConstructorDecl>(d) || isa<EnumElementDecl>(d))
|
||||
return true;
|
||||
|
||||
@@ -226,6 +229,21 @@ bool SILDeclRef::isClangImported() const {
|
||||
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 {
|
||||
// Anonymous functions have local linkage.
|
||||
if (auto closure = getAbstractClosureExpr())
|
||||
|
||||
@@ -89,6 +89,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
|
||||
InlineStrategy(inlineStrategy),
|
||||
Linkage(unsigned(Linkage)),
|
||||
KeepAsPublic(false),
|
||||
ForeignBody(false),
|
||||
EK(E) {
|
||||
if (InsertBefore)
|
||||
Module.functions.insert(SILModule::iterator(InsertBefore), this);
|
||||
|
||||
@@ -359,10 +359,14 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
|
||||
F->setDebugScope(new (*this) SILDebugScope(loc, *F));
|
||||
|
||||
F->setGlobalInit(constant.isGlobal());
|
||||
if (constant.hasDecl())
|
||||
if (constant.hasDecl()) {
|
||||
if (constant.isForeign && constant.isClangGenerated())
|
||||
F->setForeignBody(HasForeignBody);
|
||||
|
||||
if (auto SemanticsA =
|
||||
constant.getDecl()->getAttrs().getAttribute<SemanticsAttr>())
|
||||
F->setSemanticsAttr(SemanticsA->Value);
|
||||
}
|
||||
|
||||
F->setDeclContext(constant.hasDecl() ? constant.getDecl() : nullptr);
|
||||
|
||||
|
||||
@@ -2947,16 +2947,21 @@ public:
|
||||
verifySILFunctionType(FTy);
|
||||
|
||||
if (F->isExternalDeclaration()) {
|
||||
if (F->hasForeignBody())
|
||||
return;
|
||||
|
||||
assert(F->isAvailableExternally() &&
|
||||
"external declaration of internal SILFunction not allowed");
|
||||
assert(!hasSharedVisibility(F->getLinkage()) &&
|
||||
"external declarations of SILFunctions with shared visiblity is not "
|
||||
"external declarations of SILFunctions with shared visibility is not "
|
||||
"allowed");
|
||||
// If F is an external declaration, there is nothing further to do,
|
||||
// return.
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!F->hasForeignBody());
|
||||
|
||||
// Make sure that our SILFunction only has context generic params if our
|
||||
// SILFunctionType is non-polymorphic.
|
||||
if (F->getContextGenericParams()) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import c_layout
|
||||
func blackHole<T>(t: T) { }
|
||||
|
||||
// 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() {
|
||||
blackHole(c_layout.staticFloat)
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
- (Ansible*)initWithBellsOn:(id)theBells;
|
||||
@end
|
||||
|
||||
Ansible *NSAnse(Ansible *x) {
|
||||
static Ansible *NSAnse(Ansible *x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
Ansible *NSAnseExternal(Ansible *x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
void hasNoPrototype();
|
||||
|
||||
static void staticForwardDeclaration(void);
|
||||
|
||||
Reference in New Issue
Block a user