@@ -347,6 +347,7 @@ bool MemoryLocations::analyzeLocationUsesRecursively(SILValue V, unsigned locIdx
347
347
break ;
348
348
case SILInstructionKind::LoadInst:
349
349
case SILInstructionKind::StoreInst:
350
+ case SILInstructionKind::StoreBorrowInst:
350
351
case SILInstructionKind::EndAccessInst:
351
352
case SILInstructionKind::LoadBorrowInst:
352
353
case SILInstructionKind::DestroyAddrInst:
@@ -608,6 +609,9 @@ class MemoryLifetimeVerifier {
608
609
SILFunction *function;
609
610
MemoryLocations locations;
610
611
612
+ // / alloc_stack memory locations which are used for store_borrow.
613
+ Bits storeBorrowLocations;
614
+
611
615
// / Returns true if the enum location \p locIdx can be proven to hold a
612
616
// / hold a trivial value (e non-payload case) at \p atInst.
613
617
bool isEnumTrivialAt (int locIdx, SILInstruction *atInst);
@@ -640,6 +644,18 @@ class MemoryLifetimeVerifier {
640
644
// / \p addr, are set in \p bits.
641
645
void requireBitsSet (const Bits &bits, SILValue addr, SILInstruction *where);
642
646
647
+ bool isStoreBorrowLocation (SILValue addr) {
648
+ auto *loc = locations.getLocation (addr);
649
+ return loc && storeBorrowLocations.anyCommon (loc->subLocations );
650
+ }
651
+
652
+ // / Require that the location of addr is not an alloc_stack used for a
653
+ // / store_borrow.
654
+ void requireNoStoreBorrowLocation (SILValue addr, SILInstruction *where);
655
+
656
+ // / Register the destination address of a store_borrow as borrowed location.
657
+ void registerStoreBorrowLocation (SILValue addr);
658
+
643
659
// / Handles locations of the predecessor's terminator, which are only valid
644
660
// / in \p block.
645
661
// / Example: @out results of try_apply. They are only valid in the
@@ -800,6 +816,21 @@ void MemoryLifetimeVerifier::requireBitsSet(const Bits &bits, SILValue addr,
800
816
}
801
817
}
802
818
819
+ void MemoryLifetimeVerifier::requireNoStoreBorrowLocation (SILValue addr,
820
+ SILInstruction *where) {
821
+ if (isStoreBorrowLocation (addr)) {
822
+ reportError (" store-borrow location cannot be written" ,
823
+ locations.getLocation (addr)->selfAndParents .find_first (), where);
824
+ }
825
+ }
826
+
827
+ void MemoryLifetimeVerifier::registerStoreBorrowLocation (SILValue addr) {
828
+ if (auto *loc = locations.getLocation (addr)) {
829
+ storeBorrowLocations.resize (locations.getNumLocations ());
830
+ storeBorrowLocations |= loc->subLocations ;
831
+ }
832
+ }
833
+
803
834
void MemoryLifetimeVerifier::initDataflow (MemoryDataflow &dataFlow) {
804
835
// Initialize the entry and exit sets to all-bits-set. Except for the function
805
836
// entry.
@@ -849,6 +880,12 @@ void MemoryLifetimeVerifier::initDataflowInBlock(SILBasicBlock *block,
849
880
case SILInstructionKind::StoreInst:
850
881
state.genBits (cast<StoreInst>(&I)->getDest (), locations);
851
882
break ;
883
+ case SILInstructionKind::StoreBorrowInst: {
884
+ SILValue destAddr = cast<StoreBorrowInst>(&I)->getDest ();
885
+ state.genBits (destAddr, locations);
886
+ registerStoreBorrowLocation (destAddr);
887
+ break ;
888
+ }
852
889
case SILInstructionKind::CopyAddrInst: {
853
890
auto *CAI = cast<CopyAddrInst>(&I);
854
891
if (CAI->isTakeOfSrc ())
@@ -1019,6 +1056,7 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1019
1056
switch (LI->getOwnershipQualifier ()) {
1020
1057
case LoadOwnershipQualifier::Take:
1021
1058
locations.clearBits (bits, LI->getOperand ());
1059
+ requireNoStoreBorrowLocation (LI->getOperand (), &I);
1022
1060
break ;
1023
1061
case LoadOwnershipQualifier::Copy:
1024
1062
case LoadOwnershipQualifier::Trivial:
@@ -1044,19 +1082,29 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1044
1082
case StoreOwnershipQualifier::Unqualified:
1045
1083
llvm_unreachable (" unqualified store shouldn't be in ownership SIL" );
1046
1084
}
1085
+ requireNoStoreBorrowLocation (SI->getDest (), &I);
1086
+ break ;
1087
+ }
1088
+ case SILInstructionKind::StoreBorrowInst: {
1089
+ SILValue destAddr = cast<StoreBorrowInst>(&I)->getDest ();
1090
+ locations.setBits (bits, destAddr);
1091
+ registerStoreBorrowLocation (destAddr);
1047
1092
break ;
1048
1093
}
1049
1094
case SILInstructionKind::CopyAddrInst: {
1050
1095
auto *CAI = cast<CopyAddrInst>(&I);
1051
1096
requireBitsSet (bits, CAI->getSrc (), &I);
1052
- if (CAI->isTakeOfSrc ())
1097
+ if (CAI->isTakeOfSrc ()) {
1053
1098
locations.clearBits (bits, CAI->getSrc ());
1099
+ requireNoStoreBorrowLocation (CAI->getSrc (), &I);
1100
+ }
1054
1101
if (CAI->isInitializationOfDest ()) {
1055
1102
requireBitsClear (bits & nonTrivialLocations, CAI->getDest (), &I);
1056
1103
} else {
1057
1104
requireBitsSet (bits | ~nonTrivialLocations, CAI->getDest (), &I);
1058
1105
}
1059
1106
locations.setBits (bits, CAI->getDest ());
1107
+ requireNoStoreBorrowLocation (CAI->getDest (), &I);
1060
1108
break ;
1061
1109
}
1062
1110
case SILInstructionKind::InjectEnumAddrInst: {
@@ -1068,25 +1116,31 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1068
1116
requireBitsClear (bits & nonTrivialLocations, IEAI->getOperand (), &I);
1069
1117
locations.setBits (bits, IEAI->getOperand ());
1070
1118
}
1119
+ requireNoStoreBorrowLocation (IEAI->getOperand (), &I);
1071
1120
break ;
1072
1121
}
1073
- case SILInstructionKind::InitEnumDataAddrInst:
1074
- requireBitsClear (bits, cast<InitEnumDataAddrInst>(&I)->getOperand (), &I);
1122
+ case SILInstructionKind::InitEnumDataAddrInst: {
1123
+ SILValue enumAddr = cast<InitEnumDataAddrInst>(&I)->getOperand ();
1124
+ requireBitsClear (bits, enumAddr, &I);
1125
+ requireNoStoreBorrowLocation (enumAddr, &I);
1075
1126
break ;
1127
+ }
1076
1128
case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
1077
1129
// Note that despite the name, unchecked_take_enum_data_addr does _not_
1078
1130
// "take" the payload of the Swift.Optional enum. This is a terrible
1079
1131
// hack in SIL.
1080
- auto *UTEDAI = cast<UncheckedTakeEnumDataAddrInst>(&I);
1081
- int enumIdx = locations.getLocationIdx (UTEDAI-> getOperand () );
1132
+ SILValue enumAddr = cast<UncheckedTakeEnumDataAddrInst>(&I)-> getOperand ( );
1133
+ int enumIdx = locations.getLocationIdx (enumAddr );
1082
1134
if (enumIdx >= 0 )
1083
- requireBitsSet (bits, UTEDAI->getOperand (), &I);
1135
+ requireBitsSet (bits, enumAddr, &I);
1136
+ requireNoStoreBorrowLocation (enumAddr, &I);
1084
1137
break ;
1085
1138
}
1086
1139
case SILInstructionKind::DestroyAddrInst: {
1087
1140
SILValue opVal = cast<DestroyAddrInst>(&I)->getOperand ();
1088
1141
requireBitsSet (bits | ~nonTrivialLocations, opVal, &I);
1089
1142
locations.clearBits (bits, opVal);
1143
+ requireNoStoreBorrowLocation (opVal, &I);
1090
1144
break ;
1091
1145
}
1092
1146
case SILInstructionKind::EndBorrowInst: {
@@ -1117,7 +1171,11 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1117
1171
break ;
1118
1172
case SILInstructionKind::DeallocStackInst: {
1119
1173
SILValue opVal = cast<DeallocStackInst>(&I)->getOperand ();
1120
- requireBitsClear (bits & nonTrivialLocations, opVal, &I);
1174
+ if (isStoreBorrowLocation (opVal)) {
1175
+ requireBitsSet (bits, opVal, &I);
1176
+ } else {
1177
+ requireBitsClear (bits & nonTrivialLocations, opVal, &I);
1178
+ }
1121
1179
// Needed to clear any bits of trivial locations (which are not required
1122
1180
// to be zero).
1123
1181
locations.clearBits (bits, opVal);
@@ -1132,6 +1190,9 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1132
1190
void MemoryLifetimeVerifier::checkFuncArgument (Bits &bits, Operand &argumentOp,
1133
1191
SILArgumentConvention argumentConvention,
1134
1192
SILInstruction *applyInst) {
1193
+ if (argumentConvention != SILArgumentConvention::Indirect_In_Guaranteed)
1194
+ requireNoStoreBorrowLocation (argumentOp.get (), applyInst);
1195
+
1135
1196
switch (argumentConvention) {
1136
1197
case SILArgumentConvention::Indirect_In:
1137
1198
case SILArgumentConvention::Indirect_In_Constant:
@@ -1169,6 +1230,7 @@ void MemoryLifetimeVerifier::verify() {
1169
1230
}
1170
1231
// Second step: handle single-block locations.
1171
1232
locations.handleSingleBlockLocations ([this ](SILBasicBlock *block) {
1233
+ storeBorrowLocations.clear ();
1172
1234
Bits bits (locations.getNumLocations ());
1173
1235
checkBlock (block, bits);
1174
1236
});
0 commit comments