Skip to content

Commit 85343be

Browse files
authored
Merge pull request #5379 from gottesmm/load_borrow_end_borrow
Load borrow end borrow
2 parents 0ca4b69 + c41ead0 commit 85343be

File tree

17 files changed

+251
-7
lines changed

17 files changed

+251
-7
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,12 +453,25 @@ class SILBuilder {
453453
LoadInst(getSILDebugLocation(Loc), LV, Qualifier));
454454
}
455455

456+
LoadBorrowInst *createLoadBorrow(SILLocation Loc, SILValue LV) {
457+
assert(LV->getType().isLoadable(F.getModule()));
458+
return insert(new (F.getModule())
459+
LoadBorrowInst(getSILDebugLocation(Loc), LV));
460+
}
461+
456462
StoreInst *createStore(SILLocation Loc, SILValue Src, SILValue DestAddr,
457463
StoreOwnershipQualifier Qualifier =
458464
StoreOwnershipQualifier::Unqualified) {
459465
return insert(new (F.getModule()) StoreInst(getSILDebugLocation(Loc), Src,
460466
DestAddr, Qualifier));
461467
}
468+
469+
EndBorrowInst *createEndBorrow(SILLocation Loc, SILValue Src,
470+
SILValue DestAddr) {
471+
return insert(new (F.getModule())
472+
EndBorrowInst(getSILDebugLocation(Loc), Src, DestAddr));
473+
}
474+
462475
AssignInst *createAssign(SILLocation Loc, SILValue Src, SILValue DestAddr) {
463476
return insert(new (F.getModule())
464477
AssignInst(getSILDebugLocation(Loc), Src, DestAddr));

include/swift/SIL/SILCloner.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -665,19 +665,34 @@ SILCloner<ImplClass>::visitLoadInst(LoadInst *Inst) {
665665
getOpValue(Inst->getOperand())));
666666
}
667667

668-
template<typename ImplClass>
669-
void
670-
SILCloner<ImplClass>::visitStoreInst(StoreInst *Inst) {
668+
template <typename ImplClass>
669+
void SILCloner<ImplClass>::visitLoadBorrowInst(LoadBorrowInst *Inst) {
670+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
671+
doPostProcess(Inst,
672+
getBuilder().createLoadBorrow(getOpLocation(Inst->getLoc()),
673+
getOpValue(Inst->getOperand())));
674+
}
675+
676+
template <typename ImplClass>
677+
void SILCloner<ImplClass>::visitStoreInst(StoreInst *Inst) {
671678
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
672679
doPostProcess(Inst,
673680
getBuilder().createStore(getOpLocation(Inst->getLoc()),
674681
getOpValue(Inst->getSrc()),
675682
getOpValue(Inst->getDest())));
676683
}
677684

678-
template<typename ImplClass>
679-
void
680-
SILCloner<ImplClass>::visitAssignInst(AssignInst *Inst) {
685+
template <typename ImplClass>
686+
void SILCloner<ImplClass>::visitEndBorrowInst(EndBorrowInst *Inst) {
687+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
688+
doPostProcess(Inst,
689+
getBuilder().createEndBorrow(getOpLocation(Inst->getLoc()),
690+
getOpValue(Inst->getSrc()),
691+
getOpValue(Inst->getDest())));
692+
}
693+
694+
template <typename ImplClass>
695+
void SILCloner<ImplClass>::visitAssignInst(AssignInst *Inst) {
681696
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
682697
doPostProcess(Inst,
683698
getBuilder().createAssign(getOpLocation(Inst->getLoc()),

include/swift/SIL/SILInstruction.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,50 @@ class StoreInst : public SILInstruction {
17391739
}
17401740
};
17411741

1742+
/// Represents a load of a borrowed value. Must be paired with an end_borrow
1743+
/// instruction in its use-def list.
1744+
class LoadBorrowInst : public UnaryInstructionBase<ValueKind::LoadBorrowInst> {
1745+
friend class SILBuilder;
1746+
1747+
LoadBorrowInst(SILDebugLocation DebugLoc, SILValue LValue)
1748+
: UnaryInstructionBase(DebugLoc, LValue,
1749+
LValue->getType().getObjectType()) {}
1750+
};
1751+
1752+
/// Represents the end of a borrow scope for a value or address from another
1753+
/// value or address.
1754+
///
1755+
/// The semantics of the instruction here is that the "dest" SILValue can not be
1756+
/// used after this instruction and the "src" SILValue must stay alive up to
1757+
/// EndBorrowInst.
1758+
class EndBorrowInst : public SILInstruction {
1759+
friend class SILBuilder;
1760+
1761+
public:
1762+
enum {
1763+
/// The source of the value being borrowed.
1764+
Src,
1765+
/// The destination of the borrowed value.
1766+
Dest
1767+
};
1768+
1769+
private:
1770+
FixedOperandList<2> Operands;
1771+
EndBorrowInst(SILDebugLocation DebugLoc, SILValue Src, SILValue Dest);
1772+
1773+
public:
1774+
SILValue getSrc() const { return Operands[Src].get(); }
1775+
1776+
SILValue getDest() const { return Operands[Dest].get(); }
1777+
1778+
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
1779+
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
1780+
1781+
static bool classof(const ValueBase *V) {
1782+
return V->getKind() == ValueKind::EndBorrowInst;
1783+
}
1784+
};
1785+
17421786
/// AssignInst - Represents an abstract assignment to a memory location, which
17431787
/// may either be an initialization or a store sequence. This is only valid in
17441788
/// Raw SIL.

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
9494

9595
// Accessing memory
9696
INST(LoadInst, SILInstruction, load, MayRead, DoesNotRelease)
97+
INST(LoadBorrowInst, SILInstruction, load_borrow, MayRead, DoesNotRelease)
98+
INST(EndBorrowInst, SILInstruction, end_borrow, MayHaveSideEffects, DoesNotRelease)
9799
INST(LoadUnownedInst, SILInstruction, load_unowned, MayRead, DoesNotRelease)
98100
INST(LoadWeakInst, SILInstruction, load_weak, MayRead, DoesNotRelease)
99101
INST(StoreInst, SILInstruction, store, MayWrite, DoesNotRelease)

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 277; // Last change: closure SIL @convention
57+
const uint16_t VERSION_MINOR = 278; // Last change: end_borrow and load_borrow
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,9 @@ class IRGenSILFunction :
798798
void visitMarkFunctionEscapeInst(MarkFunctionEscapeInst *i) {
799799
llvm_unreachable("mark_function_escape is not valid in canonical SIL");
800800
}
801+
void visitLoadBorrowInst(LoadBorrowInst *i) {
802+
llvm_unreachable("unimplemented");
803+
}
801804
void visitDebugValueInst(DebugValueInst *i);
802805
void visitDebugValueAddrInst(DebugValueAddrInst *i);
803806
void visitLoadWeakInst(LoadWeakInst *i);
@@ -853,6 +856,9 @@ class IRGenSILFunction :
853856
void visitInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *i);
854857

855858
void visitFixLifetimeInst(FixLifetimeInst *i);
859+
void visitEndBorrowInst(EndBorrowInst *i) {
860+
llvm_unreachable("unimplemented");
861+
}
856862
void visitMarkDependenceInst(MarkDependenceInst *i);
857863
void visitCopyBlockInst(CopyBlockInst *i);
858864
void visitStrongPinInst(StrongPinInst *i);

lib/Parse/ParseSIL.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,16 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
19651965
break;
19661966
}
19671967

1968+
case ValueKind::LoadBorrowInst: {
1969+
SourceLoc AddrLoc;
1970+
1971+
if (parseTypedValueRef(Val, AddrLoc, B) || parseSILDebugLocation(InstLoc, B))
1972+
return true;
1973+
1974+
ResultVal = B.createLoadBorrow(InstLoc, Val);
1975+
break;
1976+
}
1977+
19681978
case ValueKind::LoadUnownedInst:
19691979
case ValueKind::LoadWeakInst: {
19701980
bool isTake = false;
@@ -2416,6 +2426,36 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
24162426
break;
24172427
}
24182428

2429+
case ValueKind::EndBorrowInst: {
2430+
UnresolvedValueName BorrowDestName, BorrowSourceName;
2431+
SourceLoc ToLoc, BorrowDestLoc;
2432+
Identifier ToToken;
2433+
SILType BorrowDestTy, BorrowSourceTy;
2434+
2435+
if (parseValueName(BorrowDestName) ||
2436+
parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
2437+
"from") ||
2438+
parseValueName(BorrowSourceName) ||
2439+
P.parseToken(tok::colon, diag::expected_sil_colon_value_ref) ||
2440+
parseSILType(BorrowDestTy) ||
2441+
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
2442+
parseSILType(BorrowSourceTy) || parseSILDebugLocation(InstLoc, B))
2443+
return true;
2444+
2445+
if (ToToken.str() != "from") {
2446+
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "from");
2447+
return true;
2448+
}
2449+
2450+
SILValue BorrowDest =
2451+
getLocalValue(BorrowDestName, BorrowDestTy, InstLoc, B);
2452+
SILValue BorrowSource =
2453+
getLocalValue(BorrowSourceName, BorrowSourceTy, InstLoc, B);
2454+
2455+
ResultVal = B.createEndBorrow(InstLoc, BorrowDest, BorrowSource);
2456+
break;
2457+
}
2458+
24192459
case ValueKind::AssignInst:
24202460
case ValueKind::StoreUnownedInst:
24212461
case ValueKind::StoreWeakInst: {

lib/SIL/SILInstruction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ namespace {
283283
return true;
284284
}
285285

286+
bool visitLoadBorrowInst(const LoadBorrowInst *RHS) { return true; }
287+
288+
bool visitEndBorrowInst(const EndBorrowInst *RHS) { return true; }
289+
286290
bool visitStoreInst(const StoreInst *RHS) {
287291
auto *X = cast<StoreInst>(LHS);
288292
return (X->getSrc() == RHS->getSrc() && X->getDest() == RHS->getDest());

lib/SIL/SILInstructions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,11 @@ StoreInst::StoreInst(
662662
: SILInstruction(ValueKind::StoreInst, Loc), Operands(this, Src, Dest),
663663
OwnershipQualifier(Qualifier) {}
664664

665+
EndBorrowInst::EndBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
666+
SILValue Dest)
667+
: SILInstruction(ValueKind::EndBorrowInst, DebugLoc),
668+
Operands(this, Src, Dest) {}
669+
665670
AssignInst::AssignInst(SILDebugLocation Loc, SILValue Src, SILValue Dest)
666671
: SILInstruction(ValueKind::AssignInst, Loc), Operands(this, Src, Dest) {}
667672

lib/SIL/SILPrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,10 @@ class SILPrinter : public SILVisitor<SILPrinter> {
10331033
*this << getIDAndType(LI->getOperand());
10341034
}
10351035

1036+
void visitLoadBorrowInst(LoadBorrowInst *LBI) {
1037+
*this << getIDAndType(LBI->getOperand());
1038+
}
1039+
10361040
void printStoreOwnershipQualifier(StoreOwnershipQualifier Qualifier) {
10371041
switch (Qualifier) {
10381042
case StoreOwnershipQualifier::Unqualified:
@@ -1055,9 +1059,15 @@ class SILPrinter : public SILVisitor<SILPrinter> {
10551059
*this << getIDAndType(SI->getDest());
10561060
}
10571061

1062+
void visitEndBorrowInst(EndBorrowInst *EBI) {
1063+
*this << getID(EBI->getDest()) << " from " << getID(EBI->getSrc()) << " : "
1064+
<< EBI->getDest()->getType() << ", " << EBI->getSrc()->getType();
1065+
}
1066+
10581067
void visitAssignInst(AssignInst *AI) {
10591068
*this << getID(AI->getSrc()) << " to " << getIDAndType(AI->getDest());
10601069
}
1070+
10611071
void visitMarkUninitializedInst(MarkUninitializedInst *MU) {
10621072
switch (MU->getKind()) {
10631073
case MarkUninitializedInst::Var: *this << "[var] "; break;

lib/SIL/SILVerifier.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,26 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11341134
}
11351135
}
11361136

1137+
void checkLoadBorrowInst(LoadBorrowInst *LBI) {
1138+
require(LBI->getType().isObject(), "Result of load must be an object");
1139+
require(LBI->getType().isLoadable(LBI->getModule()),
1140+
"Load must have a loadable type");
1141+
require(LBI->getOperand()->getType().isAddress(),
1142+
"Load operand must be an address");
1143+
require(LBI->getOperand()->getType().getObjectType() == LBI->getType(),
1144+
"Load operand type and result type mismatch");
1145+
}
1146+
1147+
void checkEndBorrowInst(EndBorrowInst *EBI) {
1148+
// We allow for end_borrow to express relationships in between addresses and
1149+
// values, but we require that the types are the same ignoring value
1150+
// category.
1151+
require(EBI->getDest()->getType().getObjectType() ==
1152+
EBI->getSrc()->getType().getObjectType(),
1153+
"end_borrow can only relate the same types ignoring value "
1154+
"category");
1155+
}
1156+
11371157
void checkStoreInst(StoreInst *SI) {
11381158
require(SI->getSrc()->getType().isObject(),
11391159
"Can't store from an address source");

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
226226
case ValueKind::DebugValueAddrInst:
227227
case ValueKind::StringLiteralInst:
228228
case ValueKind::FixLifetimeInst:
229+
case ValueKind::EndBorrowInst:
229230
case ValueKind::MarkDependenceInst:
230231
case ValueKind::FunctionRefInst:
231232
case ValueKind::AllocGlobalInst:
@@ -350,6 +351,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
350351
case ValueKind::InjectEnumAddrInst:
351352
case ValueKind::IsNonnullInst:
352353
case ValueKind::LoadInst:
354+
case ValueKind::LoadBorrowInst:
353355
case ValueKind::LoadUnownedInst:
354356
case ValueKind::LoadWeakInst:
355357
case ValueKind::OpenExistentialAddrInst:

lib/Serialization/DeserializeSIL.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
12821282
UNARY_INSTRUCTION(Throw)
12831283
UNARY_INSTRUCTION(FixLifetime)
12841284
UNARY_INSTRUCTION(CopyBlock)
1285+
UNARY_INSTRUCTION(LoadBorrow)
12851286
REFCOUNTING_INSTRUCTION(StrongPin)
12861287
REFCOUNTING_INSTRUCTION(StrongUnpin)
12871288
REFCOUNTING_INSTRUCTION(StrongRetain)
@@ -1337,6 +1338,15 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
13371338
getLocalValue(ValID2, addrType), Qualifier);
13381339
break;
13391340
}
1341+
case ValueKind::EndBorrowInst: {
1342+
SILValue BorrowSource, BorrowDest;
1343+
BorrowSource = getLocalValue(
1344+
ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
1345+
BorrowDest = getLocalValue(
1346+
ValID2, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2));
1347+
ResultVal = Builder.createEndBorrow(Loc, BorrowSource, BorrowDest);
1348+
break;
1349+
}
13401350
case ValueKind::StoreUnownedInst: {
13411351
auto Ty = MF->getType(TyID);
13421352
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);

lib/Serialization/SerializeSIL.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
10011001
case ValueKind::DestroyAddrInst:
10021002
case ValueKind::IsNonnullInst:
10031003
case ValueKind::LoadInst:
1004+
case ValueKind::LoadBorrowInst:
10041005
case ValueKind::LoadUnownedInst:
10051006
case ValueKind::LoadWeakInst:
10061007
case ValueKind::MarkUninitializedInst:
@@ -1259,6 +1260,22 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
12591260
break;
12601261
}
12611262

1263+
case ValueKind::EndBorrowInst: {
1264+
unsigned abbrCode = SILAbbrCodes[SILTwoOperandsLayout::Code];
1265+
unsigned Attr = 0;
1266+
auto *EBI = cast<EndBorrowInst>(&SI);
1267+
SILValue Src = EBI->getSrc();
1268+
SILValue Dest = EBI->getDest();
1269+
1270+
SILTwoOperandsLayout::emitRecord(
1271+
Out, ScratchRecord, abbrCode, (unsigned)SI.getKind(), Attr,
1272+
S.addTypeRef(Src->getType().getSwiftRValueType()),
1273+
(unsigned)Src->getType().getCategory(), addValueRef(Src),
1274+
S.addTypeRef(Dest->getType().getSwiftRValueType()),
1275+
(unsigned)Dest->getType().getCategory(), addValueRef(Dest));
1276+
break;
1277+
}
1278+
12621279
case ValueKind::AssignInst:
12631280
case ValueKind::CopyAddrInst:
12641281
case ValueKind::StoreInst:

test/SIL/Parser/borrow.sil

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-sil-opt %s | %target-sil-opt | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
7+
// We do not verify here, but just make sure that all of the combinations parse and print correctly.
8+
// CHECK-LABEL: sil @borrow_test : $@convention(thin) (@in Builtin.NativeObject, Builtin.NativeObject) -> () {
9+
// CHECK: bb0([[ARG1:%[0-9]+]] : $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : $Builtin.NativeObject):
10+
// CHECK: end_borrow [[ARG1]] from [[ARG2]] : $*Builtin.NativeObject, $Builtin.NativeObject
11+
// CHECK: end_borrow [[ARG2]] from [[ARG1]] : $Builtin.NativeObject, $*Builtin.NativeObject
12+
// CHECK: end_borrow [[ARG1]] from [[ARG1]] : $*Builtin.NativeObject, $*Builtin.NativeObject
13+
// CHECK: end_borrow [[ARG2]] from [[ARG2]] : $Builtin.NativeObject, $Builtin.NativeObject
14+
sil @borrow_test : $@convention(thin) (@in Builtin.NativeObject, Builtin.NativeObject) -> () {
15+
bb0(%0 : $*Builtin.NativeObject, %1 : $Builtin.NativeObject):
16+
end_borrow %0 from %1 : $*Builtin.NativeObject, $Builtin.NativeObject
17+
end_borrow %1 from %0 : $Builtin.NativeObject, $*Builtin.NativeObject
18+
end_borrow %0 from %0 : $*Builtin.NativeObject, $*Builtin.NativeObject
19+
end_borrow %1 from %1 : $Builtin.NativeObject, $Builtin.NativeObject
20+
%2 = tuple()
21+
return %2 : $()
22+
}

0 commit comments

Comments
 (0)