Skip to content

Commit 374c202

Browse files
committed
Add SIL instructions to generate pack indices
1 parent 4391d15 commit 374c202

20 files changed

+684
-10
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,32 @@ class SILBuilder {
19361936
getSILDebugLocation(Loc), Existential));
19371937
}
19381938

1939+
DynamicPackIndexInst *
1940+
createDynamicPackIndex(SILLocation loc, SILValue indexValue,
1941+
CanPackType indexedPackType) {
1942+
return insert(DynamicPackIndexInst::create(getFunction(),
1943+
getSILDebugLocation(loc),
1944+
indexValue, indexedPackType));
1945+
}
1946+
1947+
PackPackIndexInst *
1948+
createPackPackIndex(SILLocation loc, unsigned sliceStartIndex,
1949+
SILValue indexWithinSlice,
1950+
CanPackType indexedPackType) {
1951+
return insert(PackPackIndexInst::create(getFunction(),
1952+
getSILDebugLocation(loc),
1953+
sliceStartIndex, indexWithinSlice,
1954+
indexedPackType));
1955+
}
1956+
1957+
ScalarPackIndexInst *
1958+
createScalarPackIndex(SILLocation loc, unsigned componentIndex,
1959+
CanPackType indexedPackType) {
1960+
return insert(ScalarPackIndexInst::create(getFunction(),
1961+
getSILDebugLocation(loc),
1962+
componentIndex, indexedPackType));
1963+
}
1964+
19391965
OpenPackElementInst *
19401966
createOpenPackElement(SILLocation loc, SILValue packIndex,
19411967
GenericEnvironment *openedElementEnvironment) {

include/swift/SIL/SILCloner.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,25 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
250250
return asImpl().remapASTType(ty);
251251
}
252252

253+
/// Remap a structural index into a pack so that it will point to the
254+
/// corresponding structural index in the remapped pack type.
255+
unsigned getOpStructuralPackIndex(CanPackType origPackType,
256+
unsigned origIndex) {
257+
assert(origIndex < origPackType->getNumElements());
258+
unsigned newIndex = 0;
259+
for (unsigned i = 0; i != origIndex; ++i) {
260+
auto origComponentType = origPackType.getElementType(i);
261+
if (auto origExpansionType =
262+
dyn_cast<PackExpansionType>(origComponentType)) {
263+
auto newShapeClass = getOpASTType(origExpansionType.getCountType());
264+
newIndex += cast<PackType>(newShapeClass)->getNumElements();
265+
} else {
266+
newIndex++;
267+
}
268+
}
269+
return newIndex;
270+
}
271+
253272
void remapRootOpenedType(CanOpenedArchetypeType archetypeTy) {
254273
assert(archetypeTy->isRoot());
255274

@@ -2392,6 +2411,54 @@ void SILCloner<ImplClass>::visitDeinitExistentialValueInst(
23922411
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
23932412
}
23942413

2414+
template <typename ImplClass>
2415+
void SILCloner<ImplClass>::visitDynamicPackIndexInst(
2416+
DynamicPackIndexInst *Inst) {
2417+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2418+
2419+
auto newIndexValue = getOpValue(Inst->getOperand());
2420+
auto loc = getOpLocation(Inst->getLoc());
2421+
auto newPackType = cast<PackType>(getOpASTType(Inst->getIndexedPackType()));
2422+
2423+
recordClonedInstruction(
2424+
Inst, getBuilder().createDynamicPackIndex(loc, newIndexValue,
2425+
newPackType));
2426+
}
2427+
2428+
template <typename ImplClass>
2429+
void SILCloner<ImplClass>::visitPackPackIndexInst(PackPackIndexInst *Inst) {
2430+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2431+
2432+
auto newIndexValue = getOpValue(Inst->getOperand());
2433+
auto loc = getOpLocation(Inst->getLoc());
2434+
auto newPackType = cast<PackType>(getOpASTType(Inst->getIndexedPackType()));
2435+
2436+
auto newComponentStartIndex =
2437+
getOpStructuralPackIndex(Inst->getIndexedPackType(),
2438+
Inst->getComponentStartIndex());
2439+
2440+
recordClonedInstruction(
2441+
Inst, getBuilder().createPackPackIndex(loc, newComponentStartIndex,
2442+
newIndexValue, newPackType));
2443+
}
2444+
2445+
template <typename ImplClass>
2446+
void SILCloner<ImplClass>::visitScalarPackIndexInst(
2447+
ScalarPackIndexInst *Inst) {
2448+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2449+
2450+
auto loc = getOpLocation(Inst->getLoc());
2451+
auto newPackType = cast<PackType>(getOpASTType(Inst->getIndexedPackType()));
2452+
2453+
auto newComponentIndex =
2454+
getOpStructuralPackIndex(Inst->getIndexedPackType(),
2455+
Inst->getComponentIndex());
2456+
2457+
recordClonedInstruction(
2458+
Inst, getBuilder().createScalarPackIndex(loc, newComponentIndex,
2459+
newPackType));
2460+
}
2461+
23952462
template <typename ImplClass>
23962463
void SILCloner<ImplClass>::visitOpenPackElementInst(
23972464
OpenPackElementInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 135 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7414,6 +7414,133 @@ class DeinitExistentialValueInst
74147414
: UnaryInstructionBase(DebugLoc, Existential) {}
74157415
};
74167416

7417+
/// An abstract class for instructions which producing variadic
7418+
/// pack indices.
7419+
///
7420+
/// All of these instructions produce a Builtin.PackIndex value which
7421+
/// can only be used in packs with a specific shape class. In
7422+
/// principle, that shape class could be reflected into the result type,
7423+
/// but we actually need more structue than that in order to get the
7424+
/// type-safety properties we want. It therefore makes more sense to
7425+
/// enforce structural properties on pack-index derivation than try
7426+
/// to go all-in on dependent types.
7427+
class AnyPackIndexInst : public SingleValueInstruction {
7428+
CanPackType IndexedPackType;
7429+
7430+
protected:
7431+
AnyPackIndexInst(SILInstructionKind kind, SILDebugLocation loc,
7432+
SILType type, CanPackType packType)
7433+
: SingleValueInstruction(kind, loc, type), IndexedPackType(packType) {
7434+
assert(type.isObject() && type.is<BuiltinPackIndexType>());
7435+
}
7436+
7437+
public:
7438+
/// Return the type that this pack index indexes into.
7439+
CanPackType getIndexedPackType() const { return IndexedPackType; }
7440+
7441+
static bool classof(const AnyPackIndexInst *) { return true; }
7442+
static bool classof(SILNodePointer node) {
7443+
return node->getKind() >= SILNodeKind::First_AnyPackIndexInst &&
7444+
node->getKind() <= SILNodeKind::Last_AnyPackIndexInst;
7445+
}
7446+
};
7447+
7448+
/// Produce a dynamic pack index from a Builtin.Int32.
7449+
///
7450+
/// This instruction has undefined behavior if the value is out of
7451+
/// bounds for the given pack (including the "one past the end" value).
7452+
class DynamicPackIndexInst final :
7453+
public UnaryInstructionWithTypeDependentOperandsBase<
7454+
SILInstructionKind::DynamicPackIndexInst,
7455+
DynamicPackIndexInst,
7456+
AnyPackIndexInst> {
7457+
friend SILBuilder;
7458+
DynamicPackIndexInst(SILDebugLocation loc,
7459+
SILValue indexOperand,
7460+
ArrayRef<SILValue> typeDependentOperands,
7461+
SILType type, CanPackType packType)
7462+
: UnaryInstructionWithTypeDependentOperandsBase(loc, indexOperand,
7463+
typeDependentOperands,
7464+
type, packType) {}
7465+
7466+
static DynamicPackIndexInst *create(SILFunction &parent,
7467+
SILDebugLocation loc,
7468+
SILValue indexOperand,
7469+
CanPackType packType);
7470+
};
7471+
7472+
/// Compute the pack index of an element of a slice of a pack.
7473+
class PackPackIndexInst final :
7474+
public UnaryInstructionWithTypeDependentOperandsBase<
7475+
SILInstructionKind::PackPackIndexInst,
7476+
PackPackIndexInst,
7477+
AnyPackIndexInst> {
7478+
unsigned ComponentStartIndex;
7479+
7480+
friend SILBuilder;
7481+
PackPackIndexInst(SILDebugLocation loc,
7482+
unsigned componentStartIndex,
7483+
SILValue indexWithinComponent,
7484+
ArrayRef<SILValue> typeDependentOperands,
7485+
SILType type, CanPackType packType)
7486+
: UnaryInstructionWithTypeDependentOperandsBase(loc,
7487+
indexWithinComponent,
7488+
typeDependentOperands,
7489+
type, packType),
7490+
ComponentStartIndex(componentStartIndex) {}
7491+
7492+
static PackPackIndexInst *create(SILFunction &parent,
7493+
SILDebugLocation loc,
7494+
unsigned componentIndex,
7495+
SILValue indexWithinComponent,
7496+
CanPackType packType);
7497+
public:
7498+
/// Return the instruction which produces the index within the
7499+
/// pack slice.
7500+
AnyPackIndexInst *getSliceIndexOperand() const {
7501+
return cast<AnyPackIndexInst>(getOperand());
7502+
}
7503+
7504+
/// Return the structural index of the start of the pack slice.
7505+
unsigned getComponentStartIndex() const {
7506+
return ComponentStartIndex;
7507+
}
7508+
7509+
/// Return the structural index of the end of the pack slice.
7510+
unsigned getComponentEndIndex() const {
7511+
return getComponentStartIndex()
7512+
+ getSliceIndexOperand()->getIndexedPackType()->getNumElements();
7513+
}
7514+
};
7515+
7516+
/// Compute the pack index of a scalar component of a pack.
7517+
class ScalarPackIndexInst final :
7518+
public NullaryInstructionWithTypeDependentOperandsBase<
7519+
SILInstructionKind::ScalarPackIndexInst,
7520+
ScalarPackIndexInst,
7521+
AnyPackIndexInst> {
7522+
unsigned ComponentIndex;
7523+
7524+
friend SILBuilder;
7525+
ScalarPackIndexInst(SILDebugLocation loc,
7526+
unsigned componentIndex,
7527+
ArrayRef<SILValue> typeDependentOperands,
7528+
SILType type, CanPackType packType)
7529+
: NullaryInstructionWithTypeDependentOperandsBase(loc,
7530+
typeDependentOperands, type, packType),
7531+
ComponentIndex(componentIndex) {}
7532+
7533+
static ScalarPackIndexInst *create(SILFunction &parent,
7534+
SILDebugLocation loc,
7535+
unsigned index,
7536+
CanPackType packType);
7537+
public:
7538+
/// Return the structural index of the component within the pack.
7539+
unsigned getComponentIndex() const {
7540+
return ComponentIndex;
7541+
}
7542+
};
7543+
74177544
/// Bind archetypes to the given element of one or more type packs.
74187545
///
74197546
/// The result of this instruction is just for use in recording type
@@ -7425,11 +7552,8 @@ class DeinitExistentialValueInst
74257552
/// shape $t_1_0,
74267553
/// uuid "01234567-89AB-CDEF-0123-000000000000"
74277554
///
7428-
/// In the printed representation, only the relevant portions of the
7429-
/// opened generic environment are given: the pack type parameters,
7430-
/// the opened element archetypes, the contextual substitutions of
7431-
/// the pack type parameters, and the requirements on the pack type
7432-
/// parameters.
7555+
/// The %index operand is always a $Builtin.PackIndex and must be
7556+
/// the immediate result of one of the pack-indexing instructions.
74337557
class OpenPackElementInst final
74347558
: public UnaryInstructionWithTypeDependentOperandsBase<
74357559
SILInstructionKind::OpenPackElementInst,
@@ -7490,8 +7614,12 @@ class OpenPackElementInst final
74907614
return Env;
74917615
}
74927616

7493-
SILValue getIndexOperand() const {
7494-
return getAllOperands()[0].get();
7617+
/// Return a pack type which represents the contextual shape class
7618+
/// of the types this opens.
7619+
CanPackType getOpenedShapeClass() const;
7620+
7621+
AnyPackIndexInst *getIndexOperand() const {
7622+
return cast<AnyPackIndexInst>(getOperand());
74957623
}
74967624
};
74977625

include/swift/SIL/SILNodes.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,16 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
643643
SINGLE_VALUE_INST(KeyPathInst, keypath,
644644
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
645645

646+
// Variadic pack indexing
647+
ABSTRACT_SINGLE_VALUE_INST(AnyPackIndexInst, SingleValueInstruction)
648+
SINGLE_VALUE_INST(DynamicPackIndexInst, dynamic_pack_index,
649+
AnyPackIndexInst, None, DoesNotRelease)
650+
SINGLE_VALUE_INST(PackPackIndexInst, pack_pack_index,
651+
AnyPackIndexInst, None, DoesNotRelease)
652+
SINGLE_VALUE_INST(ScalarPackIndexInst, scalar_pack_index,
653+
AnyPackIndexInst, None, DoesNotRelease)
654+
SINGLE_VALUE_INST_RANGE(AnyPackIndexInst, DynamicPackIndexInst, ScalarPackIndexInst)
655+
646656
// BindMemory and RebindMemory have no physical side effect. Semantically they
647657
// write to their affected memory region because any reads or writes accessing
648658
// that memory must be dependent on the bind operation.

lib/IRGen/GenPack.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,34 @@ static void accumulateSum(IRGenFunction &IGF, llvm::Value *&result,
4141
result = IGF.Builder.CreateAdd(result, value);
4242
}
4343

44+
llvm::Value *
45+
irgen::emitIndexOfStructuralPackComponent(IRGenFunction &IGF,
46+
CanPackType packType,
47+
unsigned structuralIndex) {
48+
assert(structuralIndex < packType->getNumElements());
49+
unsigned numFixedComponents = 0;
50+
llvm::Value *length = nullptr;
51+
for (unsigned i = 0; i < structuralIndex; ++i) {
52+
auto componentType = packType.getElementType(i);
53+
if (auto expansion = dyn_cast<PackExpansionType>(componentType)) {
54+
auto countType = expansion.getCountType();
55+
auto expansionLength = IGF.emitPackShapeExpression(countType);
56+
accumulateSum(IGF, length, expansionLength);
57+
} else {
58+
numFixedComponents++;
59+
}
60+
}
61+
62+
if (numFixedComponents > 0 || !length) {
63+
auto fixedLength =
64+
llvm::ConstantInt::get(IGF.IGM.SizeTy, numFixedComponents);
65+
accumulateSum(IGF, length, fixedLength);
66+
}
67+
68+
assert(length);
69+
return length;
70+
}
71+
4472
using PackExplosionCallback = void (CanType eltTy,
4573
unsigned scalarIndex,
4674
llvm::Value *dynamicIndex,

lib/IRGen/GenPack.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ void cleanupTypeMetadataPack(IRGenFunction &IGF,
5454
StackAddress pack,
5555
Optional<unsigned> elementCount);
5656

57+
/// Emit the dynamic index of a particular structural component
58+
/// of the given pack type. If the component is a pack expansion, this
59+
/// is the index of the first element of the pack (or where it would be
60+
/// if it had any elements).
61+
llvm::Value *emitIndexOfStructuralPackComponent(IRGenFunction &IGF,
62+
CanPackType packType,
63+
unsigned componentIndex);
64+
5765
} // end namespace irgen
5866
} // end namespace swift
5967

lib/IRGen/IRGenSIL.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include "GenMeta.h"
8080
#include "GenObjC.h"
8181
#include "GenOpaque.h"
82+
#include "GenPack.h"
8283
#include "GenPointerAuth.h"
8384
#include "GenPoly.h"
8485
#include "GenProto.h"
@@ -1272,7 +1273,10 @@ class IRGenSILFunction :
12721273
void visitProjectExistentialBoxInst(ProjectExistentialBoxInst *i);
12731274
void visitDeallocExistentialBoxInst(DeallocExistentialBoxInst *i);
12741275

1275-
void visitOpenPackElementInst(swift::OpenPackElementInst *i);
1276+
void visitOpenPackElementInst(OpenPackElementInst *i);
1277+
void visitDynamicPackIndexInst(DynamicPackIndexInst *i);
1278+
void visitPackPackIndexInst(PackPackIndexInst *i);
1279+
void visitScalarPackIndexInst(ScalarPackIndexInst *i);
12761280

12771281
void visitProjectBlockStorageInst(ProjectBlockStorageInst *i);
12781282
void visitInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *i);
@@ -6759,6 +6763,29 @@ void IRGenSILFunction::visitOpenExistentialValueInst(
67596763
llvm_unreachable("unsupported instruction during IRGen");
67606764
}
67616765

6766+
void IRGenSILFunction::visitDynamicPackIndexInst(DynamicPackIndexInst *i) {
6767+
// At the IRGen level, this is just a type change.
6768+
auto index = getLoweredSingletonExplosion(i->getOperand());
6769+
setLoweredSingletonExplosion(i, index);
6770+
}
6771+
6772+
void IRGenSILFunction::visitPackPackIndexInst(PackPackIndexInst *i) {
6773+
auto startIndexOfSlice =
6774+
emitIndexOfStructuralPackComponent(*this, i->getIndexedPackType(),
6775+
i->getComponentStartIndex());
6776+
auto indexWithinSlice =
6777+
getLoweredSingletonExplosion(i->getSliceIndexOperand());
6778+
auto index = Builder.CreateAdd(startIndexOfSlice, indexWithinSlice);
6779+
setLoweredSingletonExplosion(i, index);
6780+
}
6781+
6782+
void IRGenSILFunction::visitScalarPackIndexInst(ScalarPackIndexInst *i) {
6783+
auto index =
6784+
emitIndexOfStructuralPackComponent(*this, i->getIndexedPackType(),
6785+
i->getComponentIndex());
6786+
setLoweredSingletonExplosion(i, index);
6787+
}
6788+
67626789
void IRGenSILFunction::visitOpenPackElementInst(swift::OpenPackElementInst *i) {
67636790
llvm::Value *index = getLoweredSingletonExplosion(i->getIndexOperand());
67646791

0 commit comments

Comments
 (0)