Skip to content

Commit 159c653

Browse files
committed
Add the tuple_pack_element_addr SIL instruction.
This allows dynamically indexing into tuples. IRGen not yet implemented. I think I'm going to need a type_refine_addr instruction in order to handle substitutions into the operand type that eliminate the outer layer of tuple-ness. Gonna handle that in a follow-up commit.
1 parent 3dc53ee commit 159c653

20 files changed

+231
-3
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,14 @@ class SILBuilder {
19911991
elementValue, packIndex, pack));
19921992
}
19931993

1994+
TuplePackElementAddrInst *
1995+
createTuplePackElementAddr(SILLocation loc, SILValue packIndex,
1996+
SILValue tupleAddr, SILType elementType) {
1997+
return insert(TuplePackElementAddrInst::create(getFunction(),
1998+
getSILDebugLocation(loc),
1999+
packIndex, tupleAddr, elementType));
2000+
}
2001+
19942002
ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
19952003
SILValue Storage) {
19962004
auto CaptureTy = Storage->getType()

include/swift/SIL/SILCloner.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,21 @@ void SILCloner<ImplClass>::visitPackElementSetInst(PackElementSetInst *Inst) {
25392539
newIndex, newPack));
25402540
}
25412541

2542+
template <typename ImplClass>
2543+
void SILCloner<ImplClass>::visitTuplePackElementAddrInst(
2544+
TuplePackElementAddrInst *Inst) {
2545+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2546+
auto loc = getOpLocation(Inst->getLoc());
2547+
auto newIndex = getOpValue(Inst->getIndex());
2548+
auto newTuple = getOpValue(Inst->getTuple());
2549+
auto newElementType = getOpType(Inst->getElementType());
2550+
// FIXME: do we need to rewrite when substitution removes the
2551+
// tuple-ness of the type? If so, what do we rewrite to?
2552+
recordClonedInstruction(
2553+
Inst, getBuilder().createTuplePackElementAddr(loc, newIndex, newTuple,
2554+
newElementType));
2555+
}
2556+
25422557
template<typename ImplClass>
25432558
void
25442559
SILCloner<ImplClass>::visitCopyBlockInst(CopyBlockInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7747,6 +7747,53 @@ class PackElementSetInst
77477747
}
77487748
};
77497749

7750+
/// Projects a tuple element as appropriate for the given
7751+
/// pack element index. The pack index must index into a pack with
7752+
/// the same shape as the tuple element type list.
7753+
class TuplePackElementAddrInst final
7754+
: public InstructionBaseWithTrailingOperands<
7755+
SILInstructionKind::TuplePackElementAddrInst,
7756+
TuplePackElementAddrInst,
7757+
SingleValueInstruction> {
7758+
public:
7759+
enum {
7760+
IndexOperand = 0,
7761+
TupleOperand = 1
7762+
};
7763+
7764+
private:
7765+
friend SILBuilder;
7766+
7767+
TuplePackElementAddrInst(SILDebugLocation debugLoc,
7768+
ArrayRef<SILValue> allOperands,
7769+
SILType elementType)
7770+
: InstructionBaseWithTrailingOperands(allOperands, debugLoc,
7771+
elementType) {}
7772+
7773+
static TuplePackElementAddrInst *create(SILFunction &F,
7774+
SILDebugLocation debugLoc,
7775+
SILValue indexOperand,
7776+
SILValue tupleOperand,
7777+
SILType elementType);
7778+
7779+
public:
7780+
SILValue getIndex() const {
7781+
return getAllOperands()[IndexOperand].get();
7782+
}
7783+
7784+
SILValue getTuple() const {
7785+
return getAllOperands()[TupleOperand].get();
7786+
}
7787+
7788+
CanTupleType getTupleType() const {
7789+
return getTuple()->getType().castTo<TupleType>();
7790+
}
7791+
7792+
SILType getElementType() const {
7793+
return getType();
7794+
}
7795+
};
7796+
77507797
/// Projects the capture storage address from a @block_storage address.
77517798
class ProjectBlockStorageInst
77527799
: public UnaryInstructionBase<SILInstructionKind::ProjectBlockStorageInst,

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
550550
SingleValueInstruction, None, DoesNotRelease)
551551
SINGLE_VALUE_INST(TupleElementAddrInst, tuple_element_addr,
552552
SingleValueInstruction, None, DoesNotRelease)
553+
SINGLE_VALUE_INST(TuplePackElementAddrInst, tuple_pack_element_addr,
554+
SingleValueInstruction, None, DoesNotRelease)
553555
SINGLE_VALUE_INST(PackElementGetInst, pack_element_get,
554556
SingleValueInstruction, None, DoesNotRelease)
555557
SINGLE_VALUE_INST(StructInst, struct,

lib/IRGen/GenTuple.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,21 @@ Address irgen::projectTupleElementAddress(IRGenFunction &IGF,
489489
tupleType, fieldNo);
490490
}
491491

492+
Address irgen::projectTupleElementAddressByDynamicIndex(IRGenFunction &IGF,
493+
Address tuple,
494+
SILType tupleType,
495+
llvm::Value *index,
496+
SILType elementType) {
497+
// TODO: retrieve type metadata (ForLayout) for the tuple type
498+
// and retrieve the field offset for the given index. Consider
499+
// special-casing constant indices if we can reason statically
500+
// about the prior elements. It's probably not necessary to try
501+
// to handle fixed-size tuples specially, because the optimizer
502+
// should ideally be lowering this operation to something static
503+
// in that case.
504+
llvm_unreachable("unimplemented");
505+
}
506+
492507
Optional<Size> irgen::getFixedTupleElementOffset(IRGenModule &IGM,
493508
SILType tupleType,
494509
unsigned fieldNo) {

lib/IRGen/GenTuple.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
#include "swift/Basic/LLVM.h"
2121

22+
namespace llvm {
23+
class Value;
24+
}
25+
2226
namespace swift {
2327
class CanType;
2428

@@ -34,6 +38,13 @@ namespace irgen {
3438
SILType tupleType,
3539
unsigned fieldNo);
3640

41+
/// Project the address of a tuple element, given a dynamic index.
42+
Address projectTupleElementAddressByDynamicIndex(IRGenFunction &IGF,
43+
Address base,
44+
SILType tupleType,
45+
llvm::Value *index,
46+
SILType elementType);
47+
3748
/// Project a tuple element rvalue from an already-exploded tuple rvalue.
3849
void projectTupleElementFromExplosion(IRGenFunction &IGF,
3950
SILType tupleType,

lib/IRGen/IRGenSIL.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,7 @@ class IRGenSILFunction :
12811281
void visitScalarPackIndexInst(ScalarPackIndexInst *i);
12821282
void visitPackElementGetInst(PackElementGetInst *i);
12831283
void visitPackElementSetInst(PackElementSetInst *i);
1284+
void visitTuplePackElementAddrInst(TuplePackElementAddrInst *i);
12841285

12851286
void visitProjectBlockStorageInst(ProjectBlockStorageInst *i);
12861287
void visitInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *i);
@@ -6920,6 +6921,19 @@ void IRGenSILFunction::visitPackElementSetInst(PackElementSetInst *i) {
69206921
Builder.CreateStore(elementValue.getAddress(), elementStorageAddress);
69216922
}
69226923

6924+
void IRGenSILFunction::visitTuplePackElementAddrInst(
6925+
TuplePackElementAddrInst *i) {
6926+
Address tuple = getLoweredAddress(i->getTuple());
6927+
llvm::Value *index = getLoweredSingletonExplosion(i->getIndex());
6928+
6929+
auto elementType = i->getElementType();
6930+
auto elementAddr =
6931+
projectTupleElementAddressByDynamicIndex(*this, tuple,
6932+
i->getTuple()->getType(),
6933+
index, elementType);
6934+
setLoweredAddress(i, elementAddr);
6935+
}
6936+
69236937
void IRGenSILFunction::visitProjectBlockStorageInst(ProjectBlockStorageInst *i){
69246938
// TODO
69256939
Address block = getLoweredAddress(i->getOperand());

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ OPERAND_OWNERSHIP(TrivialUse, DynamicPackIndex)
199199
OPERAND_OWNERSHIP(TrivialUse, PackPackIndex)
200200
OPERAND_OWNERSHIP(TrivialUse, PackElementGet)
201201
OPERAND_OWNERSHIP(TrivialUse, PackElementSet)
202+
OPERAND_OWNERSHIP(TrivialUse, TuplePackElementAddr)
202203

203204
// The dealloc_stack_ref operand needs to have NonUse ownership because
204205
// this use comes after the last consuming use (which is usually a dealloc_ref).

lib/SIL/IR/SILInstructions.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,28 @@ PackElementGetInst *PackElementGetInst::create(SILFunction &F,
24002400
return ::new (buffer) PackElementGetInst(debugLoc, allOperands, elementType);
24012401
}
24022402

2403+
TuplePackElementAddrInst *
2404+
TuplePackElementAddrInst::create(SILFunction &F,
2405+
SILDebugLocation debugLoc,
2406+
SILValue indexOperand,
2407+
SILValue tupleOperand,
2408+
SILType elementType) {
2409+
assert(indexOperand->getType().is<BuiltinPackIndexType>());
2410+
assert(tupleOperand->getType().isAddress() &&
2411+
tupleOperand->getType().is<TupleType>());
2412+
2413+
SmallVector<SILValue, 8> allOperands;
2414+
allOperands.push_back(indexOperand);
2415+
allOperands.push_back(tupleOperand);
2416+
collectTypeDependentOperands(allOperands, F, elementType);
2417+
2418+
auto size = totalSizeToAlloc<swift::Operand>(allOperands.size());
2419+
auto buffer =
2420+
F.getModule().allocateInst(size, alignof(TuplePackElementAddrInst));
2421+
return ::new (buffer) TuplePackElementAddrInst(debugLoc, allOperands,
2422+
elementType);
2423+
}
2424+
24032425
BeginCOWMutationInst::BeginCOWMutationInst(SILDebugLocation loc,
24042426
SILValue operand,
24052427
ArrayRef<SILType> resultTypes,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,6 +2318,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
23182318
<< Ctx.getID(I->getIndex()) << " of "
23192319
<< getIDAndType(I->getPack());
23202320
}
2321+
void visitTuplePackElementAddrInst(TuplePackElementAddrInst *I) {
2322+
*this << Ctx.getID(I->getIndex()) << " of "
2323+
<< getIDAndType(I->getTuple()) << " as "
2324+
<< I->getElementType();
2325+
}
23212326
void visitProjectBlockStorageInst(ProjectBlockStorageInst *PBSI) {
23222327
*this << getIDAndType(PBSI->getOperand());
23232328
}

0 commit comments

Comments
 (0)