Skip to content

Commit 6143b83

Browse files
committed
Generate IR for @_objcImpl stored properties
Only works for trivial types right now because features related to initialization and deinitialization are seriously busted.
1 parent ba1ec90 commit 6143b83

14 files changed

+183
-29
lines changed

include/swift/AST/DeclContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,11 @@ class alignas(1 << DeclContextAlignInBits) DeclContext
507507
LLVM_READONLY
508508
DeclContext *getModuleScopeContext() const;
509509

510+
/// If this DeclContext is an \c \@_objcImplementation extension, returns the
511+
/// \c DeclContext for the Objective-C declaration it implements. Otherwise
512+
/// returns \c this.
513+
DeclContext *getImplementedObjCContext() const;
514+
510515
/// Returns the source file that contains this context, or null if this
511516
/// is not within a source file.
512517
LLVM_READONLY

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5229,6 +5229,13 @@ Decl *Decl::getImplementedObjCDecl() const {
52295229
.interfaceDecl;
52305230
}
52315231

5232+
DeclContext *DeclContext::getImplementedObjCContext() const {
5233+
if (auto ED = dyn_cast<ExtensionDecl>(this))
5234+
if (auto impl = dyn_cast_or_null<DeclContext>(ED->getImplementedObjCDecl()))
5235+
return impl;
5236+
return const_cast<DeclContext *>(this);
5237+
}
5238+
52325239
Decl *Decl::getObjCImplementationDecl() const {
52335240
if (!hasClangNode())
52345241
// This *is* the implementation, if it has one.

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ namespace {
227227
bool superclass) {
228228
if (theClass->hasClangNode() && !theClass->isForeignReferenceType()) {
229229
Options |= ClassMetadataFlags::ClassHasObjCAncestry;
230-
return;
230+
if (!theClass->getObjCImplementationDecl())
231+
return;
231232
}
232233

233234
if (theClass->isNativeNSObjectSubclass()) {

lib/IRGen/GenMeta.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3837,6 +3837,9 @@ namespace {
38373837
: super(IGM, theClass, builder, fieldLayout) {}
38383838

38393839
void addFieldOffset(VarDecl *var) {
3840+
if (asImpl().getFieldLayout().hasObjCImplementation())
3841+
return;
3842+
38403843
addFixedFieldOffset(IGM, B, var, [](DeclContext *dc) {
38413844
return dc->getDeclaredTypeInContext();
38423845
});
@@ -3873,12 +3876,18 @@ namespace {
38733876
: super(IGM, theClass, builder, fieldLayout) {}
38743877

38753878
void addFieldOffset(VarDecl *var) {
3879+
if (asImpl().getFieldLayout().hasObjCImplementation())
3880+
return;
3881+
38763882
// Field offsets are either copied from the superclass or calculated
38773883
// at runtime.
38783884
B.addInt(IGM.SizeTy, 0);
38793885
}
38803886

38813887
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
3888+
if (asImpl().getFieldLayout().hasObjCImplementation())
3889+
return;
3890+
38823891
for (unsigned i = 0,
38833892
e = placeholder->getNumberOfFieldOffsetVectorEntries();
38843893
i < e; ++i) {
@@ -4338,6 +4347,9 @@ namespace {
43384347
}
43394348

43404349
void addFieldOffset(VarDecl *var) {
4350+
if (asImpl().getFieldLayout().hasObjCImplementation())
4351+
return;
4352+
43414353
addFixedFieldOffset(IGM, B, var, [&](DeclContext *dc) {
43424354
return dc->mapTypeIntoContext(type);
43434355
});

lib/IRGen/Linking.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
703703
auto linkage = getDeclLinkage(varDecl);
704704

705705
// Classes with resilient storage don't expose field offset symbols.
706-
if (cast<ClassDecl>(varDecl->getDeclContext())->isResilient()) {
706+
auto implContext = varDecl->getDeclContext()->getImplementedObjCContext();
707+
if (cast<ClassDecl>(implContext)->isResilient()) {
707708
assert(linkage != FormalLinkage::PublicNonUnique &&
708709
"Cannot have a resilient class with non-unique linkage");
709710

lib/IRGen/MetadataLayout.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
366366
}
367367

368368
void addFieldOffset(VarDecl *field) {
369-
assert(IsInTargetFields == (field->getDeclContext() == Target));
369+
assert(IsInTargetFields ==
370+
(field->getDeclContext()->getImplementedObjCContext() == Target));
370371
if (IsInTargetFields) {
371372
++Layout.NumImmediateMembers;
372373
Layout.FieldOffsets.try_emplace(field, getNextOffset());
@@ -382,7 +383,7 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
382383
}
383384

384385
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
385-
if (placeholder->getDeclContext() == Target) {
386+
if (placeholder->getDeclContext()->getImplementedObjCContext() == Target) {
386387
Layout.NumImmediateMembers +=
387388
placeholder->getNumberOfFieldOffsetVectorEntries();
388389
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3304,7 +3304,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
33043304
F.getResilienceExpansion()),
33053305
"cannot access storage of resilient class");
33063306

3307-
require(EI->getField()->getDeclContext() == cd,
3307+
require(EI->getField()->getDeclContext() ==
3308+
cd->getImplementationContext()->getAsGenericContext(),
33083309
"ref_element_addr field must be a member of the class");
33093310

33103311
if (EI->getModule().getStage() != SILStage::Lowered) {

lib/SILGen/SILGenType.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,10 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
12381238

12391239
/// Emit SIL functions for all the members of the extension.
12401240
void emitExtension(ExtensionDecl *e) {
1241+
// Arguably, we should divert to SILGenType::emitType() here if it's an
1242+
// @_objcImplementation extension, but we don't actually need to do any of
1243+
// the stuff that it currently does.
1244+
12411245
for (Decl *member : e->getABIMembers())
12421246
visit(member);
12431247

@@ -1313,6 +1317,17 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
13131317

13141318
void visitVarDecl(VarDecl *vd) {
13151319
if (vd->hasStorage()) {
1320+
if (!vd->isStatic()) {
1321+
// Is this a stored property of an @_objcImplementation extension?
1322+
auto ed = cast<ExtensionDecl>(vd->getDeclContext());
1323+
if (auto cd =
1324+
dyn_cast_or_null<ClassDecl>(ed->getImplementedObjCDecl())) {
1325+
// Act as though we declared it on the class.
1326+
SILGenType(SGM, cd).visitVarDecl(vd);
1327+
return;
1328+
}
1329+
}
1330+
13161331
bool hasDidSetOrWillSetDynamicReplacement =
13171332
vd->hasDidSetOrWillSetDynamicReplacement();
13181333
assert((vd->isStatic() || hasDidSetOrWillSetDynamicReplacement) &&

test/IRGen/Inputs/objc_implementation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
@interface ImplClass: NSObject
44

5+
@property (assign) int implProperty;
6+
57
- (void)mainMethod:(int)param;
68

79
@end

0 commit comments

Comments
 (0)