Skip to content

Commit 3a5ba2a

Browse files
authored
Merge pull request #40156 from atrick/rawrebound
Builtin.rebindMemory
2 parents 008317b + b548a6e commit 3a5ba2a

29 files changed

+340
-127
lines changed

docs/SIL.rst

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3985,13 +3985,41 @@ bind_memory
39853985

39863986
sil-instruction ::= 'bind_memory' sil-operand ',' sil-operand 'to' sil-type
39873987

3988-
bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $T
3988+
%token = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $T
39893989
// %0 must be of $Builtin.RawPointer type
39903990
// %1 must be of $Builtin.Word type
3991+
// %token is an opaque $Builtin.Word representing the previously bound types
3992+
// for this memory region.
39913993

39923994
Binds memory at ``Builtin.RawPointer`` value ``%0`` to type ``$T`` with enough
39933995
capacity to hold ``%1`` values. See SE-0107: UnsafeRawPointer.
39943996

3997+
Produces a opaque token representing the previous memory state. For
3998+
memory binding semantics, this state includes the type that the memory
3999+
was previously bound to. The token cannot, however, be used to
4000+
retrieve a metatype. It's value is only meaningful to the Swift
4001+
runtime for typed pointer verification.
4002+
4003+
rebind_memory
4004+
`````````````
4005+
4006+
::
4007+
4008+
sil-instruction ::= 'rebind_memory' sil-operand ' 'to' sil-value
4009+
4010+
%out_token = rebind_memory %0 : $Builtin.RawPointer to %in_token
4011+
// %0 must be of $Builtin.RawPointer type
4012+
// %in_token represents a cached set of bound types from a prior memory state.
4013+
// %out_token is an opaque $Builtin.Word representing the previously bound
4014+
// types for this memory region.
4015+
4016+
This instruction's semantics are identical to ``bind_memory``, except
4017+
that the types to which memory will be bound, and the extent of the
4018+
memory region is unknown at compile time. Instead, the bound-types are
4019+
represented by a token that was produced by a prior memory binding
4020+
operation. ``%in_token`` must be the result of bind_memory or
4021+
rebind_memory.
4022+
39954023
begin_access
39964024
````````````
39974025

include/swift/AST/Builtins.def

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,9 +452,18 @@ BUILTIN_SIL_OPERATION(BeginCOWMutation_native, "beginCOWMutation_native", Specia
452452
/// inout argument. After calling this builtin, the buffer must not be mutated.
453453
BUILTIN_SIL_OPERATION(EndCOWMutation, "endCOWMutation", Special)
454454

455-
/// bindMemory : <T> (Builtin.RawPointer, Builtin.Word, T.Type) -> ()
455+
/// bindMemory : <T> (Builtin.RawPointer, Builtin.Word, T.Type) -> Builtin.Word
456+
///
457+
/// Binds memory to a statically known type. Returns an opaque token
458+
/// representing the memory region's previously bound types.
456459
BUILTIN_SIL_OPERATION(BindMemory, "bindMemory", Special)
457460

461+
/// rebindMemory : (Builtin.RawPointer, Builtin.Word) -> Builtin.Word
462+
///
463+
/// Binds memory to the types represented by an opaque token operand. Returns an
464+
/// opaque token representing the memory region's previously bound types.
465+
BUILTIN_SIL_OPERATION(RebindMemory, "rebindMemory", Special)
466+
458467
/// allocWithTailElems_<n>(C.Type,
459468
/// Builtin.Word, E1.Type, ... , Builtin.Word, En.Type) -> C\
460469
///

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,13 @@ class SILBuilder {
10271027
boundType, getFunction()));
10281028
}
10291029

1030+
RebindMemoryInst *createRebindMemory(SILLocation Loc, SILValue base,
1031+
SILValue inToken) {
1032+
auto tokenTy = SILType::getBuiltinWordType(F->getASTContext());
1033+
return insert(new (getModule()) RebindMemoryInst(getSILDebugLocation(Loc),
1034+
base, inToken, tokenTy));
1035+
}
1036+
10301037
ConvertFunctionInst *createConvertFunction(SILLocation Loc, SILValue Op,
10311038
SILType Ty,
10321039
bool WithoutActuallyEscaping) {

include/swift/SIL/SILCloner.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,15 @@ SILCloner<ImplClass>::visitBindMemoryInst(BindMemoryInst *Inst) {
13511351
getOpValue(Inst->getIndex()), getOpType(Inst->getBoundType())));
13521352
}
13531353

1354+
template <typename ImplClass>
1355+
void SILCloner<ImplClass>::visitRebindMemoryInst(RebindMemoryInst *Inst) {
1356+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1357+
recordClonedInstruction(
1358+
Inst, getBuilder().createRebindMemory(getOpLocation(Inst->getLoc()),
1359+
getOpValue(Inst->getBase()),
1360+
getOpValue(Inst->getInToken())));
1361+
}
1362+
13541363
template<typename ImplClass>
13551364
void
13561365
SILCloner<ImplClass>::visitConvertFunctionInst(ConvertFunctionInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4866,14 +4866,16 @@ class CopyAddrInst
48664866
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
48674867
};
48684868

4869-
/// BindMemoryInst -
4870-
/// "bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $T"
4869+
/// "%token = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $T"
4870+
///
48714871
/// Binds memory at the raw pointer %0 to type $T with enough capacity
4872-
/// to hold $1 values.
4873-
class BindMemoryInst final :
4874-
public InstructionBaseWithTrailingOperands<
4875-
SILInstructionKind::BindMemoryInst,
4876-
BindMemoryInst, NonValueInstruction> {
4872+
/// to hold %1 values.
4873+
///
4874+
/// %token is an opaque word representing the previously bound types of this
4875+
/// memory region, before binding it to a contiguous region of type $T.
4876+
class BindMemoryInst final : public InstructionBaseWithTrailingOperands<
4877+
SILInstructionKind::BindMemoryInst,
4878+
BindMemoryInst, SingleValueInstruction> {
48774879
friend SILBuilder;
48784880

48794881
SILType BoundType;
@@ -4883,10 +4885,11 @@ class BindMemoryInst final :
48834885
SILFunction &F);
48844886

48854887
BindMemoryInst(SILDebugLocation Loc, SILValue Base, SILValue Index,
4886-
SILType BoundType,
4888+
SILType BoundType, SILType TokenType,
48874889
ArrayRef<SILValue> TypeDependentOperands)
4888-
: InstructionBaseWithTrailingOperands(Base, Index, TypeDependentOperands,
4889-
Loc), BoundType(BoundType) {}
4890+
: InstructionBaseWithTrailingOperands(Base, Index, TypeDependentOperands,
4891+
Loc, TokenType),
4892+
BoundType(BoundType) {}
48904893

48914894
public:
48924895
enum { BaseOperIdx, IndexOperIdx, NumFixedOpers };
@@ -4906,6 +4909,38 @@ class BindMemoryInst final :
49064909
}
49074910
};
49084911

4912+
/// "%out_token = rebind_memory
4913+
/// %0 : $Builtin.RawPointer, %in_token : $Builtin.Word
4914+
///
4915+
/// Binds memory at the raw pointer %0 to the types abstractly represented by
4916+
/// %in_token.
4917+
///
4918+
/// %in_token is itself the result of a bind_memory or rebind_memory and
4919+
/// represents a previously cached set of bound types.
4920+
///
4921+
/// %out_token represents the previously bound types of this memory region,
4922+
/// before binding it to %in_token.
4923+
class RebindMemoryInst final : public SingleValueInstruction {
4924+
FixedOperandList<2> Operands;
4925+
4926+
public:
4927+
enum { BaseOperIdx, InTokenOperIdx };
4928+
4929+
RebindMemoryInst(SILDebugLocation Loc, SILValue Base, SILValue InToken,
4930+
SILType TokenType)
4931+
: SingleValueInstruction(SILInstructionKind::RebindMemoryInst, Loc,
4932+
TokenType),
4933+
Operands{this, Base, InToken} {}
4934+
4935+
public:
4936+
SILValue getBase() const { return getAllOperands()[BaseOperIdx].get(); }
4937+
4938+
SILValue getInToken() const { return getAllOperands()[InTokenOperIdx].get(); }
4939+
4940+
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
4941+
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
4942+
};
4943+
49094944
//===----------------------------------------------------------------------===//
49104945
// Conversion instructions.
49114946
//===----------------------------------------------------------------------===//

include/swift/SIL/SILNodes.def

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -750,9 +750,16 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
750750
SINGLE_VALUE_INST(KeyPathInst, keypath,
751751
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
752752

753-
SINGLE_VALUE_INST_RANGE(SingleValueInstruction, AllocStackInst, KeyPathInst)
753+
// BindMemory and RebindMemory have no physical side effect. Semantically they
754+
// write to their affected memory region because any reads or writes accessing
755+
// that memory must be dependent on the bind operation.
756+
SINGLE_VALUE_INST(BindMemoryInst, bind_memory,
757+
SILInstruction, MayWrite, DoesNotRelease)
758+
SINGLE_VALUE_INST(RebindMemoryInst, rebind_memory,
759+
SILInstruction, MayWrite, DoesNotRelease)
754760

755-
NODE_RANGE(ValueBase, SILPhiArgument, KeyPathInst)
761+
SINGLE_VALUE_INST_RANGE(SingleValueInstruction, AllocStackInst, RebindMemoryInst)
762+
NODE_RANGE(ValueBase, SILPhiArgument, RebindMemoryInst)
756763

757764
// Terminators
758765
ABSTRACT_INST(TermInst, SILInstruction)
@@ -840,12 +847,6 @@ ABSTRACT_INST(RefCountingInst, SILInstruction)
840847
DoesNotRelease)
841848
INST_RANGE(RefCountingInst, StrongRetainInst, AutoreleaseValueInst)
842849

843-
// BindMemory has no physical side effect. Semantically it writes to
844-
// its affected memory region because any reads or writes accessing
845-
// that memory must be dependent on the bind operation.
846-
NON_VALUE_INST(BindMemoryInst, bind_memory,
847-
SILInstruction, MayWrite, DoesNotRelease)
848-
849850
// FIXME: Is MayHaveSideEffects appropriate?
850851
BRIDGED_NON_VALUE_INST(FixLifetimeInst, fix_lifetime,
851852
SILInstruction, MayHaveSideEffects, DoesNotRelease)

lib/AST/Builtins.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -888,12 +888,23 @@ static ValueDecl *getEndCOWMutation(ASTContext &ctx, Identifier id) {
888888
}
889889

890890
static ValueDecl *getBindMemoryOperation(ASTContext &ctx, Identifier id) {
891-
return getBuiltinFunction(ctx, id, _thin,
892-
_generics(_unrestricted),
893-
_parameters(_rawPointer,
894-
_word,
895-
_metatype(_typeparam(0))),
896-
_void);
891+
FuncDecl *fd = getBuiltinFunction(ctx, id, _thin,
892+
_generics(_unrestricted),
893+
_parameters(_rawPointer,
894+
_word,
895+
_metatype(_typeparam(0))),
896+
_word);
897+
fd->getAttrs().add(new (ctx) DiscardableResultAttr(/*implicit*/true));
898+
return fd;
899+
}
900+
901+
static ValueDecl *getRebindMemoryOperation(ASTContext &ctx, Identifier id) {
902+
FuncDecl *fd = getBuiltinFunction(ctx, id, _thin,
903+
_parameters(_rawPointer,
904+
_word),
905+
_word);
906+
fd->getAttrs().add(new (ctx) DiscardableResultAttr(/*implicit*/true));
907+
return fd;
897908
}
898909

899910
static ValueDecl *getAllocWithTailElemsOperation(ASTContext &Context,
@@ -2629,6 +2640,10 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
26292640
if (!Types.empty()) return nullptr;
26302641
return getBindMemoryOperation(Context, Id);
26312642

2643+
case BuiltinValueKind::RebindMemory:
2644+
if (!Types.empty()) return nullptr;
2645+
return getRebindMemoryOperation(Context, Id);
2646+
26322647
case BuiltinValueKind::ProjectTailElems:
26332648
if (!Types.empty()) return nullptr;
26342649
return getProjectTailElemsOperation(Context, Id);

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,7 @@ class IRGenSILFunction :
12651265
void visitDestroyAddrInst(DestroyAddrInst *i);
12661266

12671267
void visitBindMemoryInst(BindMemoryInst *i);
1268+
void visitRebindMemoryInst(RebindMemoryInst *i);
12681269

12691270
void visitCondFailInst(CondFailInst *i);
12701271

@@ -6785,10 +6786,13 @@ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) {
67856786
}
67866787
}
67876788

6788-
// This is a no-op because we do not lower Swift TBAA info to LLVM IR, and it
6789-
// does not produce any values.
6789+
// bind_memory and rebind_memory are no-ops because Swift TBAA info is not
6790+
// lowered to LLVM IR TBAA, and the output token is ignored except for
6791+
// verification.
67906792
void IRGenSILFunction::visitBindMemoryInst(swift::BindMemoryInst *) {}
67916793

6794+
void IRGenSILFunction::visitRebindMemoryInst(swift::RebindMemoryInst *) {}
6795+
67926796
void IRGenSILFunction::visitDestroyAddrInst(swift::DestroyAddrInst *i) {
67936797
SILType addrTy = i->getOperand()->getType();
67946798
const TypeInfo &addrTI = getTypeInfo(addrTy);

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ OPERAND_OWNERSHIP(TrivialUse, AllocRefDynamic) // with tail operand
138138
OPERAND_OWNERSHIP(TrivialUse, BeginAccess)
139139
OPERAND_OWNERSHIP(TrivialUse, BeginUnpairedAccess)
140140
OPERAND_OWNERSHIP(TrivialUse, BindMemory)
141+
OPERAND_OWNERSHIP(TrivialUse, RebindMemory)
141142
OPERAND_OWNERSHIP(TrivialUse, CheckedCastAddrBranch)
142143
OPERAND_OWNERSHIP(TrivialUse, CondBranch)
143144
OPERAND_OWNERSHIP(TrivialUse, CondFail)

lib/SIL/IR/SILInstructions.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,12 +1144,14 @@ CopyAddrInst::CopyAddrInst(SILDebugLocation Loc, SILValue SrcLValue,
11441144
BindMemoryInst *
11451145
BindMemoryInst::create(SILDebugLocation Loc, SILValue Base, SILValue Index,
11461146
SILType BoundType, SILFunction &F) {
1147+
auto tokenTy = SILType::getBuiltinWordType(F.getASTContext());
11471148
SmallVector<SILValue, 8> TypeDependentOperands;
1148-
collectTypeDependentOperands(TypeDependentOperands, F, BoundType.getASTType());
1149+
collectTypeDependentOperands(TypeDependentOperands, F,
1150+
BoundType.getASTType());
11491151
auto Size = totalSizeToAlloc<swift::Operand>(TypeDependentOperands.size() +
11501152
NumFixedOpers);
11511153
auto Buffer = F.getModule().allocateInst(Size, alignof(BindMemoryInst));
1152-
return ::new (Buffer) BindMemoryInst(Loc, Base, Index, BoundType,
1154+
return ::new (Buffer) BindMemoryInst(Loc, Base, Index, BoundType, tokenTy,
11531155
TypeDependentOperands);
11541156
}
11551157

lib/SIL/IR/SILPrinter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1708,7 +1708,12 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17081708
*this << getIDAndType(BI->getIndex()) << " to ";
17091709
*this << BI->getBoundType();
17101710
}
1711-
1711+
1712+
void visitRebindMemoryInst(RebindMemoryInst *BI) {
1713+
*this << getIDAndType(BI->getBase()) << " to ";
1714+
*this << getIDAndType(BI->getInToken());
1715+
}
1716+
17121717
void visitUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *CI) {
17131718
*this << getIDAndType(CI->getOperand()) << " to " << CI->getTargetFormalType();
17141719
printForwardingOwnershipKind(CI, CI->getOperand());

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ CONSTANT_OWNERSHIP_INST(Owned, ObjCMetatypeToObject)
9494
CONSTANT_OWNERSHIP_INST(None, AddressToPointer)
9595
CONSTANT_OWNERSHIP_INST(None, AllocStack)
9696
CONSTANT_OWNERSHIP_INST(None, BeginAccess)
97+
CONSTANT_OWNERSHIP_INST(None, BindMemory)
98+
CONSTANT_OWNERSHIP_INST(None, RebindMemory)
9799
CONSTANT_OWNERSHIP_INST(None, BridgeObjectToWord)
98100
CONSTANT_OWNERSHIP_INST(None, ClassMethod)
99101
CONSTANT_OWNERSHIP_INST(None, ClassifyBridgeObject)

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4768,24 +4768,29 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
47684768
}
47694769
case SILInstructionKind::BindMemoryInst: {
47704770
SILValue IndexVal;
4771-
Identifier ToToken;
4772-
SourceLoc ToLoc;
47734771
SILType EltTy;
4774-
if (parseTypedValueRef(Val, B) ||
4775-
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
4776-
parseTypedValueRef(IndexVal, B) ||
4777-
parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
4778-
"to") ||
4779-
parseSILType(EltTy) || parseSILDebugLocation(InstLoc, B))
4772+
if (parseTypedValueRef(Val, B)
4773+
|| P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",")
4774+
|| parseTypedValueRef(IndexVal, B)
4775+
|| parseVerbatim("to")
4776+
|| parseSILType(EltTy)
4777+
|| parseSILDebugLocation(InstLoc, B))
47804778
return true;
47814779

4782-
if (ToToken.str() != "to") {
4783-
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
4784-
return true;
4785-
}
47864780
ResultVal = B.createBindMemory(InstLoc, Val, IndexVal, EltTy);
47874781
break;
47884782
}
4783+
case SILInstructionKind::RebindMemoryInst: {
4784+
SILValue InToken;
4785+
if (parseTypedValueRef(Val, B)
4786+
|| parseVerbatim("to")
4787+
|| parseTypedValueRef(InToken, B)
4788+
|| parseSILDebugLocation(InstLoc, B))
4789+
return true;
4790+
4791+
ResultVal = B.createRebindMemory(InstLoc, Val, InToken);
4792+
break;
4793+
}
47894794
case SILInstructionKind::ObjectInst:
47904795
case SILInstructionKind::StructInst: {
47914796
SILType Ty;

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
475475
case SILInstructionKind::DeallocStackInst:
476476
case SILInstructionKind::AutoreleaseValueInst:
477477
case SILInstructionKind::BindMemoryInst:
478+
case SILInstructionKind::RebindMemoryInst:
478479
case SILInstructionKind::FixLifetimeInst:
479480
case SILInstructionKind::EndBorrowInst:
480481
case SILInstructionKind::AssignInst:

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3040,6 +3040,17 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
30403040
"bind_memory index must be a Word");
30413041
}
30423042

3043+
void checkRebindMemoryInst(RebindMemoryInst *rbi) {
3044+
require(rbi->getBase()->getType().is<BuiltinRawPointerType>(),
3045+
"rebind_memory base be a RawPointer");
3046+
requireSameType(rbi->getInToken()->getType(),
3047+
SILType::getBuiltinWordType(F.getASTContext()),
3048+
"rebind_memory token must be a Builtin.Int64");
3049+
require(isa<BindMemoryInst>(rbi->getInToken())
3050+
|| isa<RebindMemoryInst>(rbi->getInToken()),
3051+
"rebind_memory token must originate from bind_memory");
3052+
}
3053+
30433054
void checkIndexAddrInst(IndexAddrInst *IAI) {
30443055
require(IAI->getType().isAddress(), "index_addr must produce an address");
30453056
requireSameType(

0 commit comments

Comments
 (0)