Skip to content

Commit 90c0c8b

Browse files
committed
Add rebind_memory SIL instruction.
Required for UnsafeRawPointer.withMemoryReboud(to:). %out_token = rebind_memory %0 : $Builtin.RawPointer to %in_token %0 must be of $Builtin.RawPointer type %in_token represents a cached set of bound types from a prior memory state. %out_token is an opaque $Builtin.Word representing the previously bound types for this memory region. This instruction's semantics are identical to ``bind_memory``, except that the types to which memory will be bound, and the extent of the memory region is unknown at compile time. Instead, the bound-types are represented by a token that was produced by a prior memory binding operation. ``%in_token`` must be the result of bind_memory or
1 parent 17fef2f commit 90c0c8b

File tree

22 files changed

+200
-21
lines changed

22 files changed

+200
-21
lines changed

docs/SIL.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4000,6 +4000,26 @@ was previously bound to. The token cannot, however, be used to
40004000
retrieve a metatype. It's value is only meaningful to the Swift
40014001
runtime for typed pointer verification.
40024002

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+
40034023
begin_access
40044024
````````````
40054025

include/swift/AST/Builtins.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,12 @@ BUILTIN_SIL_OPERATION(EndCOWMutation, "endCOWMutation", Special)
458458
/// representing the memory region's previously bound types.
459459
BUILTIN_SIL_OPERATION(BindMemory, "bindMemory", Special)
460460

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+
461467
/// allocWithTailElems_<n>(C.Type,
462468
/// Builtin.Word, E1.Type, ... , Builtin.Word, En.Type) -> C\
463469
///

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: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4909,6 +4909,38 @@ class BindMemoryInst final : public InstructionBaseWithTrailingOperands<
49094909
}
49104910
};
49114911

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+
49124944
//===----------------------------------------------------------------------===//
49134945
// Conversion instructions.
49144946
//===----------------------------------------------------------------------===//

include/swift/SIL/SILNodes.def

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

753-
// BindMemory has no physical side effect. Semantically it writes to
754-
// its affected memory region because any reads or writes accessing
753+
// BindMemory and RebindMemory have no physical side effect. Semantically they
754+
// write to their affected memory region because any reads or writes accessing
755755
// that memory must be dependent on the bind operation.
756756
SINGLE_VALUE_INST(BindMemoryInst, bind_memory,
757757
SILInstruction, MayWrite, DoesNotRelease)
758+
SINGLE_VALUE_INST(RebindMemoryInst, rebind_memory,
759+
SILInstruction, MayWrite, DoesNotRelease)
758760

759-
SINGLE_VALUE_INST_RANGE(SingleValueInstruction, AllocStackInst, BindMemoryInst)
760-
NODE_RANGE(ValueBase, SILPhiArgument, BindMemoryInst)
761+
SINGLE_VALUE_INST_RANGE(SingleValueInstruction, AllocStackInst, RebindMemoryInst)
762+
NODE_RANGE(ValueBase, SILPhiArgument, RebindMemoryInst)
761763

762764
// Terminators
763765
ABSTRACT_INST(TermInst, SILInstruction)

lib/AST/Builtins.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,14 @@ static ValueDecl *getBindMemoryOperation(ASTContext &ctx, Identifier id) {
897897
fd->getAttrs().add(new (ctx) DiscardableResultAttr(/*implicit*/true));
898898
return fd;
899899
}
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;
900908
}
901909

902910
static ValueDecl *getAllocWithTailElemsOperation(ASTContext &Context,
@@ -2632,6 +2640,10 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
26322640
if (!Types.empty()) return nullptr;
26332641
return getBindMemoryOperation(Context, Id);
26342642

2643+
case BuiltinValueKind::RebindMemory:
2644+
if (!Types.empty()) return nullptr;
2645+
return getRebindMemoryOperation(Context, Id);
2646+
26352647
case BuiltinValueKind::ProjectTailElems:
26362648
if (!Types.empty()) return nullptr;
26372649
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/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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ CONSTANT_OWNERSHIP_INST(None, AddressToPointer)
9595
CONSTANT_OWNERSHIP_INST(None, AllocStack)
9696
CONSTANT_OWNERSHIP_INST(None, BeginAccess)
9797
CONSTANT_OWNERSHIP_INST(None, BindMemory)
98+
CONSTANT_OWNERSHIP_INST(None, RebindMemory)
9899
CONSTANT_OWNERSHIP_INST(None, BridgeObjectToWord)
99100
CONSTANT_OWNERSHIP_INST(None, ClassMethod)
100101
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(

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,20 @@ static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF,
973973
return ManagedValue::forUnmanaged(bindMemory);
974974
}
975975

976+
static ManagedValue emitBuiltinRebindMemory(SILGenFunction &SGF,
977+
SILLocation loc,
978+
SubstitutionMap subs,
979+
ArrayRef<ManagedValue> args,
980+
SGFContext C) {
981+
assert(subs.empty() && "rebindMemory should have no substitutions");
982+
assert(args.size() == 2 && "rebindMemory should have two arguments");
983+
984+
auto *rebindMemory = SGF.B.createRebindMemory(loc, args[0].getValue(),
985+
args[1].getValue());
986+
987+
return ManagedValue::forUnmanaged(rebindMemory);
988+
}
989+
976990
static ManagedValue emitBuiltinAllocWithTailElems(SILGenFunction &SGF,
977991
SILLocation loc,
978992
SubstitutionMap subs,

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ static bool hasOpaqueArchetype(TypeExpansionContext context,
298298
case SILInstructionKind::SetDeallocatingInst:
299299
case SILInstructionKind::AutoreleaseValueInst:
300300
case SILInstructionKind::BindMemoryInst:
301+
case SILInstructionKind::RebindMemoryInst:
301302
case SILInstructionKind::FixLifetimeInst:
302303
case SILInstructionKind::DestroyValueInst:
303304
case SILInstructionKind::EndBorrowInst:

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
774774
case SILInstructionKind::EndLifetimeInst:
775775
case SILInstructionKind::UncheckedOwnershipConversionInst:
776776
case SILInstructionKind::BindMemoryInst:
777+
case SILInstructionKind::RebindMemoryInst:
777778
case SILInstructionKind::MoveValueInst:
778779
return InlineCost::Free;
779780

lib/Serialization/DeserializeSIL.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,17 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
21302130
getSILType(Ty, (SILValueCategory)TyCategory, Fn));
21312131
break;
21322132
}
2133+
case SILInstructionKind::RebindMemoryInst: {
2134+
assert(RecordKind == SIL_TWO_OPERANDS && "Layout should be TwoOperands.");
2135+
auto Ty = MF->getType(TyID);
2136+
auto Ty2 = MF->getType(TyID2);
2137+
ResultInst = Builder.createRebindMemory(
2138+
Loc,
2139+
getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)),
2140+
getLocalValue(ValID2,
2141+
getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)));
2142+
break;
2143+
}
21332144
case SILInstructionKind::StructElementAddrInst:
21342145
case SILInstructionKind::StructExtractInst: {
21352146
// Use SILOneValueOneOperandLayout.

lib/Serialization/SerializeSIL.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,21 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
19561956
ListOfValues);
19571957
break;
19581958
}
1959+
case SILInstructionKind::RebindMemoryInst: {
1960+
auto *RBI = cast<RebindMemoryInst>(&SI);
1961+
SILValue baseOperand = RBI->getBase();
1962+
SILValue inToken = RBI->getInToken();
1963+
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
1964+
SILAbbrCodes[SILTwoOperandsLayout::Code], (unsigned)SI.getKind(),
1965+
/*attr*/0,
1966+
S.addTypeRef(baseOperand->getType().getASTType()),
1967+
(unsigned)baseOperand->getType().getCategory(),
1968+
addValueRef(baseOperand),
1969+
S.addTypeRef(inToken->getType().getASTType()),
1970+
(unsigned)inToken->getType().getCategory(),
1971+
addValueRef(inToken));
1972+
break;
1973+
}
19591974
case SILInstructionKind::RefElementAddrInst:
19601975
case SILInstructionKind::StructElementAddrInst:
19611976
case SILInstructionKind::StructExtractInst:

test/SIL/Parser/basic.sil

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1612,7 +1612,11 @@ bb0(%0 : $Builtin.RawPointer, %1 : $X):
16121612
sil @test_bind_memory : $(Builtin.RawPointer, Builtin.Word) -> () {
16131613
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
16141614
%2 = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $*X
1615-
// CHECK: bind_memory {{%.*}} : $Builtin.RawPointer, {{%.*}} : $Builtin.Word to $*X
1615+
// CHECK: [[BIND:%.*]] = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $*X
1616+
%3 = rebind_memory %0 : $Builtin.RawPointer to %2 : $Builtin.Word
1617+
// CHECK: [[REBIND:%.*]] = rebind_memory %0 : $Builtin.RawPointer to [[BIND]] : $Builtin.Word
1618+
%4 = rebind_memory %0 : $Builtin.RawPointer to %3 : $Builtin.Word
1619+
// CHECK: %{{.*}} = rebind_memory %0 : $Builtin.RawPointer to [[REBIND]] : $Builtin.Word
16161620
%28 = tuple ()
16171621
return %28 : $()
16181622
}

test/SILGen/builtins.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,19 @@ func bindMemory<T>(ptr: Builtin.RawPointer, idx: Builtin.Word, _: T.Type) {
798798
Builtin.bindMemory(ptr, idx, T.self)
799799
}
800800

801+
// CHECK-LABEL: sil hidden [ossa] @$s8builtins12rebindMemory{{[_0-9a-zA-Z]*}}F
802+
// CHECK: bb0([[P:%.*]] : $Builtin.RawPointer, [[I:%.*]] : $Builtin.Word, [[T:%.*]] : $@thick T.Type):
803+
// CHECK: [[BIND:%.*]] = bind_memory [[P]] : $Builtin.RawPointer, [[I]] : $Builtin.Word to $*T
804+
// CHECK: [[REBIND:%.*]] = rebind_memory [[P]] : $Builtin.RawPointer to [[BIND]] : $Builtin.Word
805+
// CHECK: %{{.*}} = rebind_memory [[P]] : $Builtin.RawPointer to [[REBIND]] : $Builtin.Word
806+
// CHECK: return {{%.*}} : $()
807+
// CHECK: }
808+
func rebindMemory<T>(ptr: Builtin.RawPointer, idx: Builtin.Word, _: T.Type) {
809+
let previousBindings = Builtin.bindMemory(ptr, idx, T.self)
810+
let genericBinding = Builtin.rebindMemory(ptr, previousBindings)
811+
Builtin.rebindMemory(ptr, genericBinding)
812+
}
813+
801814
//===----------------------------------------------------------------------===//
802815
// RC Operations
803816
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)