@@ -347,9 +347,11 @@ 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:
354
+ case SILInstructionKind::PartialApplyInst:
353
355
case SILInstructionKind::ApplyInst:
354
356
case SILInstructionKind::TryApplyInst:
355
357
case SILInstructionKind::BeginApplyInst:
@@ -607,6 +609,9 @@ class MemoryLifetimeVerifier {
607
609
SILFunction *function;
608
610
MemoryLocations locations;
609
611
612
+ // / alloc_stack memory locations which are used for store_borrow.
613
+ Bits storeBorrowLocations;
614
+
610
615
// / Returns true if the enum location \p locIdx can be proven to hold a
611
616
// / hold a trivial value (e non-payload case) at \p atInst.
612
617
bool isEnumTrivialAt (int locIdx, SILInstruction *atInst);
@@ -639,6 +644,18 @@ class MemoryLifetimeVerifier {
639
644
// / \p addr, are set in \p bits.
640
645
void requireBitsSet (const Bits &bits, SILValue addr, SILInstruction *where);
641
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
+
642
659
// / Handles locations of the predecessor's terminator, which are only valid
643
660
// / in \p block.
644
661
// / Example: @out results of try_apply. They are only valid in the
@@ -799,6 +816,21 @@ void MemoryLifetimeVerifier::requireBitsSet(const Bits &bits, SILValue addr,
799
816
}
800
817
}
801
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
+
802
834
void MemoryLifetimeVerifier::initDataflow (MemoryDataflow &dataFlow) {
803
835
// Initialize the entry and exit sets to all-bits-set. Except for the function
804
836
// entry.
@@ -848,6 +880,12 @@ void MemoryLifetimeVerifier::initDataflowInBlock(SILBasicBlock *block,
848
880
case SILInstructionKind::StoreInst:
849
881
state.genBits (cast<StoreInst>(&I)->getDest (), locations);
850
882
break ;
883
+ case SILInstructionKind::StoreBorrowInst: {
884
+ SILValue destAddr = cast<StoreBorrowInst>(&I)->getDest ();
885
+ state.genBits (destAddr, locations);
886
+ registerStoreBorrowLocation (destAddr);
887
+ break ;
888
+ }
851
889
case SILInstructionKind::CopyAddrInst: {
852
890
auto *CAI = cast<CopyAddrInst>(&I);
853
891
if (CAI->isTakeOfSrc ())
@@ -870,12 +908,13 @@ void MemoryLifetimeVerifier::initDataflowInBlock(SILBasicBlock *block,
870
908
case SILInstructionKind::DeallocStackInst:
871
909
state.killBits (I.getOperand (0 ), locations);
872
910
break ;
911
+ case SILInstructionKind::PartialApplyInst:
873
912
case SILInstructionKind::ApplyInst:
874
913
case SILInstructionKind::TryApplyInst: {
875
- FullApplySite FAS (&I);
914
+ ApplySite AS (&I);
876
915
for (Operand &op : I.getAllOperands ()) {
877
- if (FAS .isArgumentOperand (op)) {
878
- setFuncOperandBits (state, op, FAS. getArgumentConvention (op),
916
+ if (AS .isArgumentOperand (op)) {
917
+ setFuncOperandBits (state, op, AS. getArgumentOperandConvention (op),
879
918
isa<TryApplyInst>(&I));
880
919
}
881
920
}
@@ -1017,6 +1056,7 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1017
1056
switch (LI->getOwnershipQualifier ()) {
1018
1057
case LoadOwnershipQualifier::Take:
1019
1058
locations.clearBits (bits, LI->getOperand ());
1059
+ requireNoStoreBorrowLocation (LI->getOperand (), &I);
1020
1060
break ;
1021
1061
case LoadOwnershipQualifier::Copy:
1022
1062
case LoadOwnershipQualifier::Trivial:
@@ -1042,19 +1082,29 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1042
1082
case StoreOwnershipQualifier::Unqualified:
1043
1083
llvm_unreachable (" unqualified store shouldn't be in ownership SIL" );
1044
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);
1045
1092
break ;
1046
1093
}
1047
1094
case SILInstructionKind::CopyAddrInst: {
1048
1095
auto *CAI = cast<CopyAddrInst>(&I);
1049
1096
requireBitsSet (bits, CAI->getSrc (), &I);
1050
- if (CAI->isTakeOfSrc ())
1097
+ if (CAI->isTakeOfSrc ()) {
1051
1098
locations.clearBits (bits, CAI->getSrc ());
1099
+ requireNoStoreBorrowLocation (CAI->getSrc (), &I);
1100
+ }
1052
1101
if (CAI->isInitializationOfDest ()) {
1053
1102
requireBitsClear (bits & nonTrivialLocations, CAI->getDest (), &I);
1054
1103
} else {
1055
1104
requireBitsSet (bits | ~nonTrivialLocations, CAI->getDest (), &I);
1056
1105
}
1057
1106
locations.setBits (bits, CAI->getDest ());
1107
+ requireNoStoreBorrowLocation (CAI->getDest (), &I);
1058
1108
break ;
1059
1109
}
1060
1110
case SILInstructionKind::InjectEnumAddrInst: {
@@ -1066,38 +1116,45 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1066
1116
requireBitsClear (bits & nonTrivialLocations, IEAI->getOperand (), &I);
1067
1117
locations.setBits (bits, IEAI->getOperand ());
1068
1118
}
1119
+ requireNoStoreBorrowLocation (IEAI->getOperand (), &I);
1069
1120
break ;
1070
1121
}
1071
- case SILInstructionKind::InitEnumDataAddrInst:
1072
- 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);
1073
1126
break ;
1127
+ }
1074
1128
case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
1075
1129
// Note that despite the name, unchecked_take_enum_data_addr does _not_
1076
1130
// "take" the payload of the Swift.Optional enum. This is a terrible
1077
1131
// hack in SIL.
1078
- auto *UTEDAI = cast<UncheckedTakeEnumDataAddrInst>(&I);
1079
- int enumIdx = locations.getLocationIdx (UTEDAI-> getOperand () );
1132
+ SILValue enumAddr = cast<UncheckedTakeEnumDataAddrInst>(&I)-> getOperand ( );
1133
+ int enumIdx = locations.getLocationIdx (enumAddr );
1080
1134
if (enumIdx >= 0 )
1081
- requireBitsSet (bits, UTEDAI->getOperand (), &I);
1135
+ requireBitsSet (bits, enumAddr, &I);
1136
+ requireNoStoreBorrowLocation (enumAddr, &I);
1082
1137
break ;
1083
1138
}
1084
1139
case SILInstructionKind::DestroyAddrInst: {
1085
1140
SILValue opVal = cast<DestroyAddrInst>(&I)->getOperand ();
1086
1141
requireBitsSet (bits | ~nonTrivialLocations, opVal, &I);
1087
1142
locations.clearBits (bits, opVal);
1143
+ requireNoStoreBorrowLocation (opVal, &I);
1088
1144
break ;
1089
1145
}
1090
1146
case SILInstructionKind::EndBorrowInst: {
1091
1147
if (SILValue orig = cast<EndBorrowInst>(&I)->getSingleOriginalValue ())
1092
1148
requireBitsSet (bits, orig, &I);
1093
1149
break ;
1094
1150
}
1151
+ case SILInstructionKind::PartialApplyInst:
1095
1152
case SILInstructionKind::ApplyInst:
1096
1153
case SILInstructionKind::TryApplyInst: {
1097
- FullApplySite FAS (&I);
1154
+ ApplySite AS (&I);
1098
1155
for (Operand &op : I.getAllOperands ()) {
1099
- if (FAS .isArgumentOperand (op))
1100
- checkFuncArgument (bits, op, FAS. getArgumentConvention (op), &I);
1156
+ if (AS .isArgumentOperand (op))
1157
+ checkFuncArgument (bits, op, AS. getArgumentOperandConvention (op), &I);
1101
1158
}
1102
1159
break ;
1103
1160
}
@@ -1114,7 +1171,11 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1114
1171
break ;
1115
1172
case SILInstructionKind::DeallocStackInst: {
1116
1173
SILValue opVal = cast<DeallocStackInst>(&I)->getOperand ();
1117
- requireBitsClear (bits & nonTrivialLocations, opVal, &I);
1174
+ if (isStoreBorrowLocation (opVal)) {
1175
+ requireBitsSet (bits, opVal, &I);
1176
+ } else {
1177
+ requireBitsClear (bits & nonTrivialLocations, opVal, &I);
1178
+ }
1118
1179
// Needed to clear any bits of trivial locations (which are not required
1119
1180
// to be zero).
1120
1181
locations.clearBits (bits, opVal);
@@ -1129,6 +1190,9 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
1129
1190
void MemoryLifetimeVerifier::checkFuncArgument (Bits &bits, Operand &argumentOp,
1130
1191
SILArgumentConvention argumentConvention,
1131
1192
SILInstruction *applyInst) {
1193
+ if (argumentConvention != SILArgumentConvention::Indirect_In_Guaranteed)
1194
+ requireNoStoreBorrowLocation (argumentOp.get (), applyInst);
1195
+
1132
1196
switch (argumentConvention) {
1133
1197
case SILArgumentConvention::Indirect_In:
1134
1198
case SILArgumentConvention::Indirect_In_Constant:
@@ -1166,6 +1230,7 @@ void MemoryLifetimeVerifier::verify() {
1166
1230
}
1167
1231
// Second step: handle single-block locations.
1168
1232
locations.handleSingleBlockLocations ([this ](SILBasicBlock *block) {
1233
+ storeBorrowLocations.clear ();
1169
1234
Bits bits (locations.getNumLocations ());
1170
1235
checkBlock (block, bits);
1171
1236
});
0 commit comments