Skip to content

Commit 3ce7a74

Browse files
bitjammertkremenek
authored andcommitted
Ask SILFunction link entities' clang nodes for weakness when applicable (#2822)
* Provide ways to get back to the original Clang declaration from a SILFunction or SILGLobalVariable. This will be used as one step towards moving IRGen off of the global external-definitions list. * Ask SILFunction link entities' clang nodes for weakness when applicable When importing C functions with availability attributes, we don't properly use that information to decide whether a symbol should be weak_extern, causing load failures in dylibs that reference these symbols when deployed to an older OS. This is a very targeted fix and we need a better architecture for deciding this. rdar://problem/26359452
1 parent d7daa40 commit 3ce7a74

File tree

17 files changed

+131
-37
lines changed

17 files changed

+131
-37
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ struct SILDeclRef {
375375
/// True if the referenced entity is emitted by Clang on behalf of the Clang
376376
/// importer.
377377
bool isClangGenerated() const;
378+
static bool isClangGenerated(ClangNode node);
378379

379380
bool isImplicit() const {
380381
if (hasDecl())

include/swift/SIL/SILFunction.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ class SILFunction
105105
/// The declcontext of this function.
106106
DeclContext *DeclCtx;
107107

108+
/// The owning declaration of this function's clang node, if applicable.
109+
ValueDecl *ClangNodeOwner = nullptr;
110+
108111
/// The source location and scope of the function.
109112
const SILDebugScope *DebugScope;
110113

@@ -146,9 +149,6 @@ class SILFunction
146149
/// it public.
147150
unsigned KeepAsPublic : 1;
148151

149-
/// This flag indicates if a function has a body generated by Clang.
150-
unsigned ForeignBody : 1;
151-
152152
/// This is the number of uses of this SILFunction inside the SIL.
153153
/// It does not include references from debug scopes.
154154
unsigned RefCount = 0;
@@ -515,9 +515,37 @@ class SILFunction
515515
bool isKeepAsPublic() const { return KeepAsPublic; }
516516
void setKeepAsPublic(bool keep) { KeepAsPublic = keep; }
517517

518-
/// Get this function's foreign body attribute.
519-
HasForeignBody_t hasForeignBody() const { return HasForeignBody_t(ForeignBody); }
520-
void setForeignBody(HasForeignBody_t foreign) { ForeignBody = foreign; }
518+
/// Return whether this function has a foreign implementation which can
519+
/// be emitted on demand.
520+
bool hasForeignBody() const;
521+
522+
/// Return whether this function corresponds to a Clang node.
523+
bool hasClangNode() const {
524+
return ClangNodeOwner != nullptr;
525+
}
526+
527+
/// Set the owning declaration of the Clang node associated with this
528+
/// function. We have to store an owner (a Swift declaration) instead of
529+
/// directly referencing the original declaration due to current
530+
/// limitations in the serializer.
531+
void setClangNodeOwner(ValueDecl *owner) {
532+
assert(owner->hasClangNode());
533+
ClangNodeOwner = owner;
534+
}
535+
536+
/// Return the owning declaration of the Clang node associated with this
537+
/// function. This should only be used for serialization.
538+
ValueDecl *getClangNodeOwner() const {
539+
return ClangNodeOwner;
540+
}
541+
542+
/// Return the Clang node associated with this function if it has one.
543+
ClangNode getClangNode() const {
544+
return (ClangNodeOwner ? ClangNodeOwner->getClangNode() : ClangNode());
545+
}
546+
const clang::Decl *getClangDecl() const {
547+
return (ClangNodeOwner ? ClangNodeOwner->getClangDecl() : nullptr);
548+
}
521549

522550
/// Retrieve the generic parameter list containing the contextual archetypes
523551
/// of the function.

include/swift/SIL/SILGlobalVariable.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,19 @@ class SILGlobalVariable
144144
/// Return the value that is written into the global variable.
145145
SILInstruction *getValueOfStaticInitializer();
146146

147+
/// Return whether this variable corresponds to a Clang node.
148+
bool hasClangNode() const {
149+
return VDecl->hasClangNode();
150+
}
151+
152+
/// Return the Clang node associated with this variable if it has one.
153+
ClangNode getClangNode() const {
154+
return VDecl->getClangNode();
155+
}
156+
const clang::Decl *getClangDecl() const {
157+
return VDecl->getClangDecl();
158+
}
159+
147160
//===--------------------------------------------------------------------===//
148161
// Miscellaneous
149162
//===--------------------------------------------------------------------===//

include/swift/SIL/SILLinkage.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,6 @@ enum IsFragile_t {
9090
IsFragile
9191
};
9292

93-
/// True if we have an inline body generated by Clang.
94-
enum HasForeignBody_t {
95-
DoesNotHaveForeignBody,
96-
HasForeignBody
97-
};
98-
9993
/// Strip external from public_external, hidden_external. Otherwise just return
10094
/// the linkage.
10195
inline SILLinkage stripExternalFromLinkage(SILLinkage linkage) {

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
5353
/// in source control, you should also update the comment to briefly
5454
/// describe what change you made. The content of this comment isn't important;
5555
/// it just ensures a conflict if two people change the module format.
56-
const uint16_t VERSION_MINOR = 248; // Last change: [nonatomic] attribute
56+
const uint16_t VERSION_MINOR = 249; // Last change: SIL clang decls
5757

5858
using DeclID = PointerEmbeddedInt<unsigned, 31>;
5959
using DeclIDField = BCFixed<31>;

lib/IRGen/Linking.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,10 @@ class LinkEntity {
574574
getSILGlobalVariable()->getDecl())
575575
return getSILGlobalVariable()->getDecl()->isWeakImported(module);
576576

577+
if (getKind() == Kind::SILFunction)
578+
if (auto clangOwner = getSILFunction()->getClangNodeOwner())
579+
return clangOwner->isWeakImported(module);
580+
577581
if (!isDeclKind(getKind()))
578582
return false;
579583

lib/SIL/SILDeclRef.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,12 @@ bool SILDeclRef::isClangGenerated() const {
275275
if (!hasDecl())
276276
return false;
277277

278-
auto clangNode = getDecl()->getClangNode().getAsDecl();
279-
if (auto nd = dyn_cast_or_null<clang::NamedDecl>(clangNode)) {
278+
return isClangGenerated(getDecl()->getClangNode());
279+
}
280+
281+
// FIXME: this is a weird predicate.
282+
bool SILDeclRef::isClangGenerated(ClangNode node) {
283+
if (auto nd = dyn_cast_or_null<clang::NamedDecl>(node.getAsDecl())) {
280284
// ie, 'static inline' functions for which we must ask Clang to emit a body
281285
// for explicitly
282286
if (!nd->isExternallyVisible())

lib/SIL/SILFunction.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
101101
InlineStrategy(inlineStrategy),
102102
Linkage(unsigned(Linkage)),
103103
KeepAsPublic(false),
104-
ForeignBody(false),
105104
EffectsKindAttr(E) {
106105
if (InsertBefore)
107106
Module.functions.insert(SILModule::iterator(InsertBefore), this);
@@ -160,6 +159,11 @@ void SILFunction::setDeclContext(Expr *E) {
160159
DeclCtx = dyn_cast_or_null<AbstractClosureExpr>(E);
161160
}
162161

162+
bool SILFunction::hasForeignBody() const {
163+
if (!hasClangNode()) return false;
164+
return SILDeclRef::isClangGenerated(getClangNode());
165+
}
166+
163167
void SILFunction::numberValues(llvm::DenseMap<const ValueBase*,
164168
unsigned> &ValueToNumberMap) const {
165169
unsigned idx = 0;

lib/SIL/SILModule.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,12 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
355355

356356
F->setGlobalInit(constant.isGlobal());
357357
if (constant.hasDecl()) {
358-
if (constant.isForeign && constant.isClangGenerated())
359-
F->setForeignBody(HasForeignBody);
358+
auto decl = constant.getDecl();
360359

361-
auto Attrs = constant.getDecl()->getAttrs();
360+
if (constant.isForeign && decl->hasClangNode())
361+
F->setClangNodeOwner(decl);
362+
363+
auto Attrs = decl->getAttrs();
362364
for (auto *A : Attrs.getAttributes<SemanticsAttr, false /*AllowInvalid*/>())
363365
F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
364366

lib/Serialization/DeserializeSIL.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,16 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
376376
assert(kind == SIL_FUNCTION && "expect a sil function");
377377
(void)kind;
378378

379+
DeclID clangNodeOwnerID;
379380
TypeID funcTyID;
380381
unsigned rawLinkage, isTransparent, isFragile, isThunk, isGlobal,
381382
inlineStrategy, effect, numSpecAttrs;
382383
ArrayRef<uint64_t> SemanticsIDs;
383384
// TODO: read fragile
384385
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isFragile,
385386
isThunk, isGlobal, inlineStrategy, effect,
386-
numSpecAttrs, funcTyID, SemanticsIDs);
387+
numSpecAttrs, funcTyID, clangNodeOwnerID,
388+
SemanticsIDs);
387389

388390
if (funcTyID == 0) {
389391
DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n");
@@ -405,6 +407,16 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
405407
return nullptr;
406408
}
407409

410+
ValueDecl *clangNodeOwner = nullptr;
411+
if (clangNodeOwnerID != 0) {
412+
clangNodeOwner = dyn_cast_or_null<ValueDecl>(MF->getDecl(clangNodeOwnerID));
413+
if (!clangNodeOwner) {
414+
DEBUG(llvm::dbgs() << "invalid clang node owner for SILFunction\n");
415+
MF->error();
416+
return nullptr;
417+
}
418+
}
419+
408420
// If we weren't handed a function, check for an existing
409421
// declaration in the output module.
410422
if (!existingFn) existingFn = SILMod.lookUpFunction(name);
@@ -436,6 +448,8 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
436448
SILFunction::NotRelevant, (Inline_t)inlineStrategy);
437449
fn->setGlobalInit(isGlobal == 1);
438450
fn->setEffectsKind((EffectsKind)effect);
451+
if (clangNodeOwner)
452+
fn->setClangNodeOwner(clangNodeOwner);
439453
for (auto ID : SemanticsIDs) {
440454
fn->addSemanticsAttr(MF->getIdentifier(ID).str());
441455
}
@@ -1837,13 +1851,15 @@ bool SILDeserializer::hasSILFunction(StringRef Name,
18371851
// Read function properties only, e.g. its linkage and other attributes.
18381852
// TODO: If this results in any noticeable performance problems, Cache the
18391853
// linkage to avoid re-reading it from the bitcode each time?
1854+
DeclID clangOwnerID;
18401855
TypeID funcTyID;
18411856
unsigned rawLinkage, isTransparent, isFragile, isThunk, isGlobal,
18421857
inlineStrategy, effect, numSpecAttrs;
18431858
ArrayRef<uint64_t> SemanticsIDs;
18441859
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isFragile,
18451860
isThunk, isGlobal, inlineStrategy, effect,
1846-
numSpecAttrs, funcTyID, SemanticsIDs);
1861+
numSpecAttrs, funcTyID, clangOwnerID,
1862+
SemanticsIDs);
18471863
auto linkage = fromStableSILLinkage(rawLinkage);
18481864
if (!linkage) {
18491865
DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage
@@ -1909,8 +1925,8 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
19091925
TypeID TyID;
19101926
DeclID dID;
19111927
unsigned rawLinkage, isFragile, IsDeclaration, IsLet;
1912-
GlobalVarLayout::readRecord(scratch, rawLinkage, isFragile, TyID, dID,
1913-
IsDeclaration, IsLet);
1928+
SILGlobalVarLayout::readRecord(scratch, rawLinkage, isFragile,
1929+
IsDeclaration, IsLet, TyID, dID);
19141930
if (TyID == 0) {
19151931
DEBUG(llvm::dbgs() << "SILGlobalVariable typeID is 0.\n");
19161932
return nullptr;

0 commit comments

Comments
 (0)