Skip to content

Commit ea0da3f

Browse files
authored
Merge pull request #34074 from atrick/make-fieldidx-unique
Change SIL ref_element_addr getFieldNo() to return a unique index.
2 parents 5f92463 + 5ae231e commit ea0da3f

38 files changed

+142
-95
lines changed

include/swift/SIL/PatternMatch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ template <typename LTy> struct tupleextractoperation_ty {
406406

407407
template <typename ITy> bool match(ITy *V) {
408408
if (auto *TEI = dyn_cast<TupleExtractInst>(V)) {
409-
return TEI->getFieldNo() == index &&
409+
return TEI->getFieldIndex() == index &&
410410
L.match((ValueBase *)TEI->getOperand());
411411
}
412412

include/swift/SIL/Projection.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,13 @@ struct ProjectionIndex {
152152
}
153153
case ValueKind::StructElementAddrInst: {
154154
StructElementAddrInst *SEA = cast<StructElementAddrInst>(V);
155-
Index = SEA->getFieldNo();
155+
Index = SEA->getFieldIndex();
156156
Aggregate = SEA->getOperand();
157157
break;
158158
}
159159
case ValueKind::RefElementAddrInst: {
160160
RefElementAddrInst *REA = cast<RefElementAddrInst>(V);
161-
Index = REA->getFieldNo();
161+
Index = REA->getFieldIndex();
162162
Aggregate = REA->getOperand();
163163
break;
164164
}
@@ -177,19 +177,19 @@ struct ProjectionIndex {
177177
}
178178
case ValueKind::TupleElementAddrInst: {
179179
TupleElementAddrInst *TEA = cast<TupleElementAddrInst>(V);
180-
Index = TEA->getFieldNo();
180+
Index = TEA->getFieldIndex();
181181
Aggregate = TEA->getOperand();
182182
break;
183183
}
184184
case ValueKind::StructExtractInst: {
185185
StructExtractInst *SEA = cast<StructExtractInst>(V);
186-
Index = SEA->getFieldNo();
186+
Index = SEA->getFieldIndex();
187187
Aggregate = SEA->getOperand();
188188
break;
189189
}
190190
case ValueKind::TupleExtractInst: {
191191
TupleExtractInst *TEA = cast<TupleExtractInst>(V);
192-
Index = TEA->getFieldNo();
192+
Index = TEA->getFieldIndex();
193193
Aggregate = TEA->getOperand();
194194
break;
195195
}
@@ -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/SILCloner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,7 +1946,7 @@ SILCloner<ImplClass>::visitTupleExtractInst(TupleExtractInst *Inst) {
19461946
recordClonedInstruction(
19471947
Inst, getBuilder().createTupleExtract(
19481948
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
1949-
Inst->getFieldNo(), getOpType(Inst->getType())));
1949+
Inst->getFieldIndex(), getOpType(Inst->getType())));
19501950
}
19511951

19521952
template<typename ImplClass>
@@ -1956,7 +1956,7 @@ SILCloner<ImplClass>::visitTupleElementAddrInst(TupleElementAddrInst *Inst) {
19561956
recordClonedInstruction(
19571957
Inst, getBuilder().createTupleElementAddr(
19581958
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
1959-
Inst->getFieldNo(), getOpType(Inst->getType())));
1959+
Inst->getFieldIndex(), getOpType(Inst->getType())));
19601960
}
19611961

19621962
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5715,7 +5715,7 @@ class TupleExtractInst
57155715
}
57165716

57175717
public:
5718-
unsigned getFieldNo() const {
5718+
unsigned getFieldIndex() const {
57195719
return SILInstruction::Bits.TupleExtractInst.FieldNo;
57205720
}
57215721

@@ -5747,7 +5747,7 @@ class TupleElementAddrInst
57475747
}
57485748

57495749
public:
5750-
unsigned getFieldNo() const {
5750+
unsigned getFieldIndex() const {
57515751
return SILInstruction::Bits.TupleElementAddrInst.FieldNo;
57525752
}
57535753

@@ -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
@@ -5791,8 +5811,7 @@ class FieldIndexCacheBase : public SingleValueInstruction {
57915811

57925812
VarDecl *getField() const { return field; }
57935813

5794-
// FIXME: this should be called getFieldIndex().
5795-
unsigned getFieldNo() const {
5814+
unsigned getFieldIndex() const {
57965815
unsigned idx = SILInstruction::Bits.FieldIndexCacheBase.FieldIndex;
57975816
if (idx != InvalidFieldIndex)
57985817
return idx;

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3787,7 +3787,7 @@ void IRGenSILFunction::visitTupleExtractInst(swift::TupleExtractInst *i) {
37873787
projectTupleElementFromExplosion(*this,
37883788
baseType,
37893789
fullTuple,
3790-
i->getFieldNo(),
3790+
i->getFieldIndex(),
37913791
output);
37923792
(void)fullTuple.claimAll();
37933793
setLoweredExplosion(i, output);
@@ -3799,7 +3799,7 @@ void IRGenSILFunction::visitTupleElementAddrInst(swift::TupleElementAddrInst *i)
37993799
SILType baseType = i->getOperand()->getType();
38003800

38013801
Address field = projectTupleElementAddress(*this, base, baseType,
3802-
i->getFieldNo());
3802+
i->getFieldIndex());
38033803
setLoweredAddress(i, field);
38043804
}
38053805

lib/SIL/IR/SILGlobalVariable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ BuiltinInst *SILGlobalVariable::getOffsetSubtract(const TupleExtractInst *TE,
8585
// Match the pattern:
8686
// tuple_extract(usub_with_overflow(x, integer_literal, integer_literal 0), 0)
8787

88-
if (TE->getFieldNo() != 0)
88+
if (TE->getFieldIndex() != 0)
8989
return nullptr;
9090

9191
auto *BI = dyn_cast<BuiltinInst>(TE->getOperand());

lib/SIL/IR/SILInstruction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ namespace {
579579
auto *X = cast<TupleExtractInst>(LHS);
580580
if (X->getTupleType() != RHS->getTupleType())
581581
return false;
582-
if (X->getFieldNo() != RHS->getFieldNo())
582+
if (X->getFieldIndex() != RHS->getFieldIndex())
583583
return false;
584584
return true;
585585
}
@@ -590,7 +590,7 @@ namespace {
590590
auto *X = cast<TupleElementAddrInst>(LHS);
591591
if (X->getTupleType() != RHS->getTupleType())
592592
return false;
593-
if (X->getFieldNo() != RHS->getFieldNo())
593+
if (X->getFieldIndex() != RHS->getFieldIndex())
594594
return false;
595595
return true;
596596
}

lib/SIL/IR/SILInstructions.cpp

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ bool TupleExtractInst::isTrivialEltOfOneRCIDTuple() const {
12581258
// parent tuple has only one non-trivial field.
12591259
bool FoundNonTrivialField = false;
12601260
SILType OpTy = getOperand()->getType();
1261-
unsigned FieldNo = getFieldNo();
1261+
unsigned FieldNo = getFieldIndex();
12621262

12631263
// For each element index of the tuple...
12641264
for (unsigned i = 0, e = getNumTupleElts(); i != e; ++i) {
@@ -1300,7 +1300,7 @@ bool TupleExtractInst::isEltOnlyNonTrivialElt() const {
13001300
// Ok, we know that the elt we are extracting is non-trivial. Make sure that
13011301
// we have no other non-trivial elts.
13021302
SILType OpTy = getOperand()->getType();
1303-
unsigned FieldNo = getFieldNo();
1303+
unsigned FieldNo = getFieldIndex();
13041304

13051305
// For each element index of the tuple...
13061306
for (unsigned i = 0, e = getNumTupleElts(); i != e; ++i) {
@@ -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/IR/SILPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,11 +1773,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17731773
}
17741774

17751775
void visitTupleExtractInst(TupleExtractInst *EI) {
1776-
*this << getIDAndType(EI->getOperand()) << ", " << EI->getFieldNo();
1776+
*this << getIDAndType(EI->getOperand()) << ", " << EI->getFieldIndex();
17771777
}
17781778

17791779
void visitTupleElementAddrInst(TupleElementAddrInst *EI) {
1780-
*this << getIDAndType(EI->getOperand()) << ", " << EI->getFieldNo();
1780+
*this << getIDAndType(EI->getOperand()) << ", " << EI->getFieldIndex();
17811781
}
17821782
void visitStructExtractInst(StructExtractInst *EI) {
17831783
*this << getIDAndType(EI->getOperand()) << ", #";

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ AccessedStorage::AccessedStorage(SILValue base, Kind kind) {
118118
// conservative given that classes are not "uniquely identified".
119119
auto *REA = cast<RefElementAddrInst>(base);
120120
value = stripBorrow(REA->getOperand());
121-
setElementIndex(REA->getFieldNo());
121+
setElementIndex(REA->getFieldIndex());
122122
break;
123123
}
124124
case Tail: {
@@ -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: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,23 @@ Projection::Projection(SingleValueInstruction *I) : Value() {
7070
return;
7171
case SILInstructionKind::StructElementAddrInst: {
7272
auto *SEAI = cast<StructElementAddrInst>(I);
73-
Value = ValueTy(ProjectionKind::Struct, SEAI->getFieldNo());
73+
Value = ValueTy(ProjectionKind::Struct, SEAI->getFieldIndex());
7474
assert(getKind() == ProjectionKind::Struct);
75-
assert(getIndex() == SEAI->getFieldNo());
75+
assert(getIndex() == SEAI->getFieldIndex());
7676
break;
7777
}
7878
case SILInstructionKind::StructExtractInst: {
7979
auto *SEI = cast<StructExtractInst>(I);
80-
Value = ValueTy(ProjectionKind::Struct, SEI->getFieldNo());
80+
Value = ValueTy(ProjectionKind::Struct, SEI->getFieldIndex());
8181
assert(getKind() == ProjectionKind::Struct);
82-
assert(getIndex() == SEI->getFieldNo());
82+
assert(getIndex() == SEI->getFieldIndex());
8383
break;
8484
}
8585
case SILInstructionKind::RefElementAddrInst: {
8686
auto *REAI = cast<RefElementAddrInst>(I);
87-
Value = ValueTy(ProjectionKind::Class, REAI->getFieldNo());
87+
Value = ValueTy(ProjectionKind::Class, REAI->getFieldIndex());
8888
assert(getKind() == ProjectionKind::Class);
89-
assert(getIndex() == REAI->getFieldNo());
89+
assert(getIndex() == REAI->getFieldIndex());
9090
break;
9191
}
9292
case SILInstructionKind::RefTailAddrInst: {
@@ -106,16 +106,16 @@ Projection::Projection(SingleValueInstruction *I) : Value() {
106106
}
107107
case SILInstructionKind::TupleExtractInst: {
108108
auto *TEI = cast<TupleExtractInst>(I);
109-
Value = ValueTy(ProjectionKind::Tuple, TEI->getFieldNo());
109+
Value = ValueTy(ProjectionKind::Tuple, TEI->getFieldIndex());
110110
assert(getKind() == ProjectionKind::Tuple);
111-
assert(getIndex() == TEI->getFieldNo());
111+
assert(getIndex() == TEI->getFieldIndex());
112112
break;
113113
}
114114
case SILInstructionKind::TupleElementAddrInst: {
115115
auto *TEAI = cast<TupleElementAddrInst>(I);
116-
Value = ValueTy(ProjectionKind::Tuple, TEAI->getFieldNo());
116+
Value = ValueTy(ProjectionKind::Tuple, TEAI->getFieldIndex());
117117
assert(getKind() == ProjectionKind::Tuple);
118-
assert(getIndex() == TEAI->getFieldNo());
118+
assert(getIndex() == TEAI->getFieldIndex());
119119
break;
120120
}
121121
case SILInstructionKind::UncheckedEnumDataInst: {
@@ -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++);

lib/SIL/Verifier/MemoryLifetime.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,14 +261,14 @@ bool MemoryLocations::analyzeLocationUsesRecursively(SILValue V, unsigned locIdx
261261
switch (user->getKind()) {
262262
case SILInstructionKind::StructElementAddrInst: {
263263
auto SEAI = cast<StructElementAddrInst>(user);
264-
if (!analyzeAddrProjection(SEAI, locIdx, SEAI->getFieldNo(),
264+
if (!analyzeAddrProjection(SEAI, locIdx, SEAI->getFieldIndex(),
265265
collectedVals, subLocationMap))
266266
return false;
267267
break;
268268
}
269269
case SILInstructionKind::TupleElementAddrInst: {
270270
auto *TEAI = cast<TupleElementAddrInst>(user);
271-
if (!analyzeAddrProjection(TEAI, locIdx, TEAI->getFieldNo(),
271+
if (!analyzeAddrProjection(TEAI, locIdx, TEAI->getFieldIndex(),
272272
collectedVals, subLocationMap))
273273
return false;
274274
break;

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,11 +2747,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27472747
require(EI->getType().isObject(),
27482748
"result of tuple_extract must be object");
27492749

2750-
require(EI->getFieldNo() < operandTy->getNumElements(),
2750+
require(EI->getFieldIndex() < operandTy->getNumElements(),
27512751
"invalid field index for tuple_extract instruction");
27522752
if (EI->getModule().getStage() != SILStage::Lowered) {
27532753
requireSameType(EI->getType().getASTType(),
2754-
operandTy.getElementType(EI->getFieldNo()),
2754+
operandTy.getElementType(EI->getFieldIndex()),
27552755
"type of tuple_extract does not match type of element");
27562756
}
27572757
}
@@ -2793,12 +2793,12 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
27932793
"must derive tuple_element_addr from tuple");
27942794

27952795
ArrayRef<TupleTypeElt> fields = operandTy.castTo<TupleType>()->getElements();
2796-
require(EI->getFieldNo() < fields.size(),
2796+
require(EI->getFieldIndex() < fields.size(),
27972797
"invalid field index for element_addr instruction");
27982798
if (EI->getModule().getStage() != SILStage::Lowered) {
27992799
requireSameType(
28002800
EI->getType().getASTType(),
2801-
CanType(fields[EI->getFieldNo()].getType()),
2801+
CanType(fields[EI->getFieldIndex()].getType()),
28022802
"type of tuple_element_addr does not match type of element");
28032803
}
28042804
}
@@ -2856,7 +2856,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
28562856
loweredFieldTy, EI->getType(),
28572857
"result of ref_element_addr does not match type of field");
28582858
}
2859-
EI->getFieldNo(); // Make sure we can access the field without crashing.
2859+
EI->getFieldIndex(); // Make sure we can access the field without crashing.
28602860
}
28612861

28622862
void checkRefTailAddrInst(RefTailAddrInst *RTAI) {

0 commit comments

Comments
 (0)