Skip to content

Commit 33fecc9

Browse files
committed
Serialize SIL forwarding ownership on terminators.
1 parent f3d2f85 commit 33fecc9

File tree

6 files changed

+132
-22
lines changed

6 files changed

+132
-22
lines changed

lib/Serialization/DeserializeSIL.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,11 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
10731073
ApplyOptions ApplyOpts;
10741074
ArrayRef<uint64_t> ListOfValues;
10751075
SILLocation Loc = RegularLocation(SLoc);
1076+
ValueOwnershipKind forwardingOwnership(OwnershipKind::Any);
1077+
auto decodeValueOwnership = [](unsigned field){
1078+
// Invalid/Any ownership is never encoded.
1079+
return ValueOwnershipKind(field+1);
1080+
};
10761081

10771082
switch (RecordKind) {
10781083
default:
@@ -1111,6 +1116,14 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
11111116
SILOneTypeValuesLayout::readRecord(scratch, RawOpCode, TyID, TyCategory,
11121117
ListOfValues);
11131118
break;
1119+
case SIL_ONE_TYPE_OWNERSHIP_VALUES: {
1120+
unsigned ownershipField;
1121+
SILOneTypeOwnershipValuesLayout::readRecord(scratch, RawOpCode,
1122+
ownershipField, TyID,
1123+
TyCategory, ListOfValues);
1124+
forwardingOwnership = decodeValueOwnership(ownershipField);
1125+
break;
1126+
}
11141127
case SIL_TWO_OPERANDS:
11151128
SILTwoOperandsLayout::readRecord(scratch, RawOpCode, Attr,
11161129
TyID, TyCategory, ValID,
@@ -1941,7 +1954,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
19411954
}
19421955
case SILInstructionKind::UncheckedOwnershipConversionInst: {
19431956
auto Ty = MF->getType(TyID);
1944-
auto ResultKind = ValueOwnershipKind(Attr);
1957+
auto ResultKind = decodeValueOwnership(Attr);
19451958
ResultInst = Builder.createUncheckedOwnershipConversion(
19461959
Loc,
19471960
getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
@@ -2252,10 +2265,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
22522265
CaseBBs.push_back( {cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])),
22532266
getBBForReference(Fn, ListOfValues[I+1])} );
22542267
}
2255-
if (OpCode == SILInstructionKind::SwitchEnumInst)
2256-
ResultInst = Builder.createSwitchEnum(Loc, Cond, DefaultBB, CaseBBs);
2257-
else
2268+
if (OpCode == SILInstructionKind::SwitchEnumInst) {
2269+
ResultInst = Builder.createSwitchEnum(Loc, Cond, DefaultBB, CaseBBs,
2270+
None, ProfileCounter(),
2271+
forwardingOwnership);
2272+
} else {
22582273
ResultInst = Builder.createSwitchEnumAddr(Loc, Cond, DefaultBB, CaseBBs);
2274+
}
22592275
break;
22602276
}
22612277
case SILInstructionKind::SelectEnumInst:
@@ -2520,7 +2536,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
25202536

25212537
ResultInst =
25222538
Builder.createCheckedCastBranch(Loc, isExact, op, targetLoweredType,
2523-
targetFormalType, successBB, failureBB);
2539+
targetFormalType, successBB, failureBB,
2540+
forwardingOwnership);
25242541
break;
25252542
}
25262543
case SILInstructionKind::CheckedCastValueBranchInst: {

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 625; // is concurrency checked?
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 626; // switch & checkcast ownership
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///

lib/Serialization/SILFormat.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ using ValueIDField = DeclIDField;
2828

2929
using SILInstOpCodeField = BCFixed<8>;
3030
using SILTypeCategoryField = BCFixed<2>;
31+
using SILValueOwnershipField = BCFixed<2>;
3132

3233
enum SILStringEncoding : uint8_t {
3334
SIL_UTF8,
@@ -126,6 +127,7 @@ namespace sil_block {
126127
SIL_ONE_OPERAND,
127128
SIL_ONE_TYPE_ONE_OPERAND,
128129
SIL_ONE_TYPE_VALUES,
130+
SIL_ONE_TYPE_OWNERSHIP_VALUES,
129131
SIL_TWO_OPERANDS,
130132
SIL_TAIL_ADDR,
131133
SIL_INST_APPLY,
@@ -362,6 +364,16 @@ namespace sil_block {
362364
BCArray<ValueIDField>
363365
>;
364366

367+
// SIL instructions with one type, forwarding ownership, and a list of values.
368+
// For OwnershipForwardingTermInst.
369+
using SILOneTypeOwnershipValuesLayout = BCRecordLayout<
370+
SIL_ONE_TYPE_OWNERSHIP_VALUES,
371+
SILInstOpCodeField,
372+
SILValueOwnershipField,
373+
TypeIDField,
374+
SILTypeCategoryField,
375+
BCArray<ValueIDField>>;
376+
365377
enum ApplyKind : unsigned {
366378
SIL_APPLY = 0,
367379
SIL_PARTIAL_APPLY,

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ void Serializer::writeBlockInfoBlock() {
870870
BLOCK_RECORD(sil_block, SIL_ONE_OPERAND);
871871
BLOCK_RECORD(sil_block, SIL_ONE_TYPE_ONE_OPERAND);
872872
BLOCK_RECORD(sil_block, SIL_ONE_TYPE_VALUES);
873+
BLOCK_RECORD(sil_block, SIL_ONE_TYPE_OWNERSHIP_VALUES);
873874
BLOCK_RECORD(sil_block, SIL_TWO_OPERANDS);
874875
BLOCK_RECORD(sil_block, SIL_TAIL_ADDR);
875876
BLOCK_RECORD(sil_block, SIL_INST_APPLY);

lib/Serialization/SerializeSIL.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ toStableDifferentiabilityKind(swift::DifferentiabilityKind kind) {
111111
llvm_unreachable("covered switch");
112112
}
113113

114+
static unsigned encodeValueOwnership(ValueOwnershipKind ownership) {
115+
assert(ownership.value > 0 && "invalid value ownership");
116+
return ownership.value - 1;
117+
}
118+
114119
namespace {
115120
/// Used to serialize the on-disk func hash table.
116121
class FuncTableInfo {
@@ -1213,10 +1218,11 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
12131218
}
12141219
case SILInstructionKind::SwitchEnumInst:
12151220
case SILInstructionKind::SwitchEnumAddrInst: {
1216-
// Format: condition, a list of cases (EnumElementDecl + Basic Block ID),
1217-
// default basic block ID. Use SILOneTypeValuesLayout: the type is
1218-
// for condition, the list has value for condition, hasDefault, default
1219-
// basic block ID, a list of (DeclID, BasicBlock ID).
1221+
// Format:
1222+
// - [ownership]
1223+
// - the type of the condition operand,
1224+
// - a list a values: operand, hasDefault, defaultBB,
1225+
// [EnumElementDecl, Basic Block ID]*
12201226
SwitchEnumTermInst SOI(&SI);
12211227
assert(SOI);
12221228
SmallVector<ValueID, 4> ListOfValues;
@@ -1234,11 +1240,22 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
12341240
ListOfValues.push_back(S.addDeclRef(elt));
12351241
ListOfValues.push_back(BasicBlockMap[dest]);
12361242
}
1237-
SILOneTypeValuesLayout::emitRecord(
1238-
Out, ScratchRecord, SILAbbrCodes[SILOneTypeValuesLayout::Code],
1239-
(unsigned)SI.getKind(),
1240-
S.addTypeRef(SOI.getOperand()->getType().getASTType()),
1241-
(unsigned)SOI.getOperand()->getType().getCategory(), ListOfValues);
1243+
if (auto *switchEnum = dyn_cast<SwitchEnumInst>(&SI)) {
1244+
unsigned ownershipField =
1245+
encodeValueOwnership(switchEnum->getForwardingOwnershipKind());
1246+
SILOneTypeOwnershipValuesLayout::emitRecord(
1247+
Out, ScratchRecord,
1248+
SILAbbrCodes[SILOneTypeOwnershipValuesLayout::Code],
1249+
(unsigned)SI.getKind(), ownershipField,
1250+
S.addTypeRef(SOI.getOperand()->getType().getASTType()),
1251+
(unsigned)SOI.getOperand()->getType().getCategory(), ListOfValues);
1252+
} else {
1253+
SILOneTypeValuesLayout::emitRecord(
1254+
Out, ScratchRecord, SILAbbrCodes[SILOneTypeValuesLayout::Code],
1255+
(unsigned)SI.getKind(),
1256+
S.addTypeRef(SOI.getOperand()->getType().getASTType()),
1257+
(unsigned)SOI.getOperand()->getType().getCategory(), ListOfValues);
1258+
}
12421259
break;
12431260
}
12441261
case SILInstructionKind::SelectEnumInst:
@@ -1400,7 +1417,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
14001417
else if (auto *RCI = dyn_cast<RefCountingInst>(&SI))
14011418
Attr = RCI->isNonAtomic();
14021419
else if (auto *UOCI = dyn_cast<UncheckedOwnershipConversionInst>(&SI)) {
1403-
Attr = unsigned(SILValue(UOCI).getOwnershipKind());
1420+
Attr = encodeValueOwnership(UOCI->getOwnershipKind());
14041421
} else if (auto *IEC = dyn_cast<IsEscapingClosureInst>(&SI)) {
14051422
Attr = IEC->getVerificationType();
14061423
} else if (auto *HTE = dyn_cast<HopToExecutorInst>(&SI)) {
@@ -2153,12 +2170,14 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
21532170
BasicBlockMap[CBI->getSuccessBB()],
21542171
BasicBlockMap[CBI->getFailureBB()]
21552172
};
2156-
2157-
SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
2158-
SILAbbrCodes[SILOneTypeValuesLayout::Code], (unsigned)SI.getKind(),
2159-
S.addTypeRef(CBI->getTargetLoweredType().getASTType()),
2160-
(unsigned)CBI->getTargetLoweredType().getCategory(),
2161-
llvm::makeArrayRef(listOfValues));
2173+
unsigned ownershipField =
2174+
encodeValueOwnership(CBI->getForwardingOwnershipKind());
2175+
SILOneTypeOwnershipValuesLayout::emitRecord(
2176+
Out, ScratchRecord, SILAbbrCodes[SILOneTypeOwnershipValuesLayout::Code],
2177+
(unsigned)SI.getKind(), ownershipField,
2178+
S.addTypeRef(CBI->getTargetLoweredType().getASTType()),
2179+
(unsigned)CBI->getTargetLoweredType().getCategory(),
2180+
llvm::makeArrayRef(listOfValues));
21622181
break;
21632182
}
21642183
case SILInstructionKind::CheckedCastValueBranchInst: {
@@ -2744,6 +2763,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) {
27442763
registerSILAbbr<SILOneTypeOneOperandLayout>();
27452764
registerSILAbbr<SILInitExistentialLayout>();
27462765
registerSILAbbr<SILOneTypeValuesLayout>();
2766+
registerSILAbbr<SILOneTypeOwnershipValuesLayout>();
27472767
registerSILAbbr<SILTwoOperandsLayout>();
27482768
registerSILAbbr<SILTwoOperandsExtraAttributeLayout>();
27492769
registerSILAbbr<SILTailAddrLayout>();
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
2+
// RUN: %empty-directory(%t)
3+
// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name temp
4+
// RUN: %target-sil-opt %t/tmp.sib -o %t/tmp.2.sib -module-name temp
5+
// RUN: %target-sil-opt %t/tmp.2.sib -module-name temp | %FileCheck %s
6+
7+
import Builtin
8+
9+
enum FakeOptional<T> {
10+
case none
11+
case some(T)
12+
}
13+
14+
class Klass {
15+
}
16+
class SubKlass : Klass {
17+
}
18+
19+
// CHECK-LABEL: sil [ossa] @switch_test : $@convention(thin) () -> () {
20+
// CHECK: switch_enum {{.*}}, forwarding: @guaranteed
21+
// CHECK-LABEL: } // end sil function 'switch_test'
22+
sil [ossa] @switch_test : $@convention(thin) () -> () {
23+
%none = enum $FakeOptional<Klass>, #FakeOptional.none
24+
switch_enum %none : $FakeOptional<Klass>, case #FakeOptional.some!enumelt:bb1, case #FakeOptional.none!enumelt:bb2, forwarding: @guaranteed
25+
26+
bb1(%arg : @guaranteed $Klass):
27+
br bb3
28+
29+
bb2:
30+
br bb3
31+
32+
bb3:
33+
%8 = tuple ()
34+
return %8 : $()
35+
}
36+
37+
// Test checked_cast_br ownership forwarding.
38+
//
39+
// Also test unchecked_ownership_conversion @none serialization (@none
40+
// is the highest value ownership encoding).
41+
//
42+
// CHECK-LABEL: sil [ossa] @checked_cast_test : $@convention(thin) (@owned Klass) -> () {
43+
// CHECK: checked_cast_br {{.*}}, forwarding: @guaranteed
44+
// CHECK-LABEL: } // end sil function 'checked_cast_test'
45+
sil [ossa] @checked_cast_test : $@convention(thin) (@owned Klass) -> () {
46+
bb0(%0 : @owned $Klass):
47+
%trivial = unchecked_ownership_conversion %0 : $Klass, @owned to @none
48+
checked_cast_br %trivial : $Klass to SubKlass, bb1, bb2, forwarding: @guaranteed
49+
50+
bb1(%arg1 : @guaranteed $SubKlass):
51+
br bb3
52+
53+
bb2(%arg2: @guaranteed $Klass):
54+
br bb3
55+
56+
bb3:
57+
destroy_value %0 : $Klass
58+
%8 = tuple ()
59+
return %8 : $()
60+
}

0 commit comments

Comments
 (0)