Skip to content

Commit 2829472

Browse files
committed
Change SIL ref_element_addr getFieldNo() to return a unique index.
I don't have a test case for this bug based on the current code. But the fix is clearly needed to have a unique AccessStorage object for each property. The AccessPath commits will contain test cases for this functionality.
1 parent 2544806 commit 2829472

File tree

5 files changed

+61
-13
lines changed

5 files changed

+61
-13
lines changed

include/swift/SIL/Projection.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,9 @@ class Projection {
302302
assert(isValid());
303303
assert((getKind() == ProjectionKind::Struct ||
304304
getKind() == ProjectionKind::Class));
305-
assert(BaseType.getNominalOrBoundGenericNominal() &&
306-
"This should only be called with a nominal type");
307-
auto *NDecl = BaseType.getNominalOrBoundGenericNominal();
308-
return NDecl->getStoredProperties()[getIndex()];
305+
auto *nominalDecl = BaseType.getNominalOrBoundGenericNominal();
306+
assert(nominalDecl && "This should only be called with a nominal type");
307+
return getIndexedField(nominalDecl, getIndex());
309308
}
310309

311310
EnumElementDecl *getEnumElementDecl(SILType BaseType) const {

include/swift/SIL/SILInstruction.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5757,6 +5757,26 @@ class TupleElementAddrInst
57575757
}
57585758
};
57595759

5760+
/// Get a unique index for a struct or class field in layout order.
5761+
///
5762+
/// Precondition: \p decl must be a non-resilient struct or class.
5763+
///
5764+
/// Precondition: \p field must be a stored property declared in \p decl,
5765+
/// not in a superclass.
5766+
///
5767+
/// Postcondition: The returned index is unique across all properties in the
5768+
/// object, including properties declared in a superclass.
5769+
unsigned getFieldIndex(NominalTypeDecl *decl, VarDecl *property);
5770+
5771+
/// Get the property for a struct or class by its unique index.
5772+
///
5773+
/// Precondition: \p decl must be a non-resilient struct or class.
5774+
///
5775+
/// Precondition: \p index must be the index of a stored property
5776+
/// (as returned by getFieldIndex()) which is declared
5777+
/// in \p decl, not in a superclass.
5778+
VarDecl *getIndexedField(NominalTypeDecl *decl, unsigned index);
5779+
57605780
/// A common base for instructions that require a cached field index.
57615781
///
57625782
/// "Field" is a term used here to refer to the ordered, accessible stored

lib/SIL/IR/SILInstructions.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,18 +1323,43 @@ bool TupleExtractInst::isEltOnlyNonTrivialElt() const {
13231323
return true;
13241324
}
13251325

1326-
unsigned FieldIndexCacheBase::cacheFieldIndex() {
1327-
unsigned i = 0;
1328-
for (VarDecl *property : getParentDecl()->getStoredProperties()) {
1326+
/// Get a unique index for a struct or class field in layout order.
1327+
unsigned swift::getFieldIndex(NominalTypeDecl *decl, VarDecl *field) {
1328+
unsigned index = 0;
1329+
if (auto *classDecl = dyn_cast<ClassDecl>(decl)) {
1330+
for (auto *superDecl = classDecl->getSuperclassDecl(); superDecl != nullptr;
1331+
superDecl = superDecl->getSuperclassDecl()) {
1332+
index += superDecl->getStoredProperties().size();
1333+
}
1334+
}
1335+
for (VarDecl *property : decl->getStoredProperties()) {
13291336
if (field == property) {
1330-
SILInstruction::Bits.FieldIndexCacheBase.FieldIndex = i;
1331-
return i;
1337+
return index;
13321338
}
1333-
++i;
1339+
++index;
13341340
}
13351341
llvm_unreachable("The field decl for a struct_extract, struct_element_addr, "
1336-
"or ref_element_addr must be an accessible stored property "
1337-
"of the operand's type");
1342+
"or ref_element_addr must be an accessible stored "
1343+
"property of the operand type");
1344+
}
1345+
1346+
/// Get the property for a struct or class by its unique index.
1347+
VarDecl *swift::getIndexedField(NominalTypeDecl *decl, unsigned index) {
1348+
if (auto *classDecl = dyn_cast<ClassDecl>(decl)) {
1349+
for (auto *superDecl = classDecl->getSuperclassDecl(); superDecl != nullptr;
1350+
superDecl = superDecl->getSuperclassDecl()) {
1351+
assert(index > superDecl->getStoredProperties().size()
1352+
&& "field index cannot refer to a superclass field");
1353+
index -= superDecl->getStoredProperties().size();
1354+
}
1355+
}
1356+
return decl->getStoredProperties()[index];
1357+
}
1358+
1359+
unsigned FieldIndexCacheBase::cacheFieldIndex() {
1360+
unsigned index = getFieldIndex(getParentDecl(), getField());
1361+
SILInstruction::Bits.FieldIndexCacheBase.FieldIndex = index;
1362+
return index;
13381363
}
13391364

13401365
// FIXME: this should be cached during cacheFieldIndex().

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ const ValueDecl *AccessedStorage::getDecl() const {
156156

157157
case Class: {
158158
auto *decl = getObject()->getType().getNominalOrBoundGenericNominal();
159-
return decl->getStoredProperties()[getPropertyIndex()];
159+
return getIndexedField(decl, getPropertyIndex());
160160
}
161161
case Tail:
162162
return nullptr;

lib/SIL/Utils/Projection.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ void Projection::getFirstLevelProjections(
321321

322322
if (auto *C = Ty.getClassOrBoundGenericClass()) {
323323
unsigned Count = 0;
324+
for (auto *superDecl = C->getSuperclassDecl(); superDecl != nullptr;
325+
superDecl = superDecl->getSuperclassDecl()) {
326+
Count += superDecl->getStoredProperties().size();
327+
}
324328
for (auto *VDecl : C->getStoredProperties()) {
325329
(void) VDecl;
326330
Projection P(ProjectionKind::Class, Count++);

0 commit comments

Comments
 (0)