Skip to content

Commit 7a89642

Browse files
authored
Merge pull request swiftlang#63488 from rjmccall/pack_element_getset
Add SIL instructions to get and set pack elements
2 parents cfad960 + 27142e4 commit 7a89642

23 files changed

+671
-9
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,22 @@ class SILBuilder {
19751975
packIndex, openedElementEnvironment));
19761976
}
19771977

1978+
PackElementGetInst *
1979+
createPackElementGet(SILLocation loc, SILValue packIndex,
1980+
SILValue pack, SILType elementType) {
1981+
return insert(PackElementGetInst::create(getFunction(),
1982+
getSILDebugLocation(loc),
1983+
packIndex, pack, elementType));
1984+
}
1985+
1986+
PackElementSetInst *
1987+
createPackElementSet(SILLocation loc, SILValue elementValue,
1988+
SILValue packIndex, SILValue pack) {
1989+
return insert(new (getModule()) PackElementSetInst(
1990+
getSILDebugLocation(loc),
1991+
elementValue, packIndex, pack));
1992+
}
1993+
19781994
ProjectBlockStorageInst *createProjectBlockStorage(SILLocation Loc,
19791995
SILValue Storage) {
19801996
auto CaptureTy = Storage->getType()

include/swift/SIL/SILCloner.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,6 +2515,30 @@ void SILCloner<ImplClass>::visitOpenPackElementInst(
25152515
Inst, getBuilder().createOpenPackElement(loc, newIndexValue, newEnv));
25162516
}
25172517

2518+
template <typename ImplClass>
2519+
void SILCloner<ImplClass>::visitPackElementGetInst(PackElementGetInst *Inst) {
2520+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2521+
auto loc = getOpLocation(Inst->getLoc());
2522+
auto newIndex = getOpValue(Inst->getIndex());
2523+
auto newPack = getOpValue(Inst->getPack());
2524+
auto newElementType = getOpType(Inst->getElementType());
2525+
recordClonedInstruction(
2526+
Inst, getBuilder().createPackElementGet(loc, newIndex, newPack,
2527+
newElementType));
2528+
}
2529+
2530+
template <typename ImplClass>
2531+
void SILCloner<ImplClass>::visitPackElementSetInst(PackElementSetInst *Inst) {
2532+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2533+
auto loc = getOpLocation(Inst->getLoc());
2534+
auto newElementValue = getOpValue(Inst->getValue());
2535+
auto newIndex = getOpValue(Inst->getIndex());
2536+
auto newPack = getOpValue(Inst->getPack());
2537+
recordClonedInstruction(
2538+
Inst, getBuilder().createPackElementSet(loc, newElementValue,
2539+
newIndex, newPack));
2540+
}
2541+
25182542
template<typename ImplClass>
25192543
void
25202544
SILCloner<ImplClass>::visitCopyBlockInst(CopyBlockInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7654,6 +7654,99 @@ class OpenPackElementInst final
76547654
}
76557655
};
76567656

7657+
/// Get the value previously stored in a pack by pack_element_set.
7658+
class PackElementGetInst final
7659+
: public InstructionBaseWithTrailingOperands<
7660+
SILInstructionKind::PackElementGetInst,
7661+
PackElementGetInst, SingleValueInstruction> {
7662+
public:
7663+
enum {
7664+
IndexOperand = 0,
7665+
PackOperand = 1
7666+
};
7667+
7668+
private:
7669+
friend SILBuilder;
7670+
7671+
PackElementGetInst(SILDebugLocation debugLoc,
7672+
ArrayRef<SILValue> allOperands,
7673+
SILType elementType)
7674+
: InstructionBaseWithTrailingOperands(allOperands, debugLoc,
7675+
elementType) {}
7676+
7677+
static PackElementGetInst *create(SILFunction &F,
7678+
SILDebugLocation debugLoc,
7679+
SILValue indexOperand,
7680+
SILValue packOperand,
7681+
SILType elementType);
7682+
7683+
public:
7684+
SILValue getIndex() const {
7685+
return getAllOperands()[IndexOperand].get();
7686+
}
7687+
7688+
SILValue getPack() const {
7689+
return getAllOperands()[PackOperand].get();
7690+
}
7691+
7692+
CanSILPackType getPackType() const {
7693+
return getPack()->getType().castTo<SILPackType>();
7694+
}
7695+
7696+
SILType getElementType() const {
7697+
return getType();
7698+
}
7699+
};
7700+
7701+
/// Set the value stored in a pack.
7702+
class PackElementSetInst
7703+
: public InstructionBase<SILInstructionKind::PackElementSetInst,
7704+
NonValueInstruction> {
7705+
public:
7706+
enum {
7707+
ValueOperand = 0,
7708+
IndexOperand = 1,
7709+
PackOperand = 2
7710+
};
7711+
7712+
private:
7713+
friend SILBuilder;
7714+
7715+
FixedOperandList<3> Operands;
7716+
7717+
PackElementSetInst(SILDebugLocation debugLoc,
7718+
SILValue valueOperand, SILValue indexOperand,
7719+
SILValue packOperand)
7720+
: InstructionBase(debugLoc),
7721+
Operands(this, valueOperand, indexOperand, packOperand) {
7722+
assert(packOperand->getType().is<SILPackType>());
7723+
}
7724+
7725+
public:
7726+
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
7727+
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
7728+
7729+
SILValue getValue() const {
7730+
return getAllOperands()[ValueOperand].get();
7731+
}
7732+
7733+
SILValue getIndex() const {
7734+
return getAllOperands()[IndexOperand].get();
7735+
}
7736+
7737+
SILValue getPack() const {
7738+
return getAllOperands()[PackOperand].get();
7739+
}
7740+
7741+
CanSILPackType getPackType() const {
7742+
return getPack()->getType().castTo<SILPackType>();
7743+
}
7744+
7745+
SILType getElementType() const {
7746+
return getValue()->getType();
7747+
}
7748+
};
7749+
76577750
/// Projects the capture storage address from a @block_storage address.
76587751
class ProjectBlockStorageInst
76597752
: public UnaryInstructionBase<SILInstructionKind::ProjectBlockStorageInst,

include/swift/SIL/SILNodes.def

Lines changed: 4 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(PackElementGetInst, pack_element_get,
554+
SingleValueInstruction, None, DoesNotRelease)
553555
SINGLE_VALUE_INST(StructInst, struct,
554556
SingleValueInstruction, None, DoesNotRelease)
555557
SINGLE_VALUE_INST(StructExtractInst, struct_extract,
@@ -816,6 +818,8 @@ NON_VALUE_INST(EndApplyInst, end_apply,
816818
SILInstruction, MayHaveSideEffects, MayRelease)
817819
NON_VALUE_INST(AbortApplyInst, abort_apply,
818820
SILInstruction, MayHaveSideEffects, MayRelease)
821+
NON_VALUE_INST(PackElementSetInst, pack_element_set,
822+
SILInstruction, MayHaveSideEffects, DoesNotRelease)
819823

820824
// Runtime failure
821825
// FIXME: Special MemBehavior for runtime failure?

lib/IRGen/GenPack.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,16 @@ void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF,
586586
IGF.IGM.getPointerSize() * (*elementCount));
587587
}
588588
}
589+
590+
Address irgen::emitStorageAddressOfPackElement(IRGenFunction &IGF,
591+
Address pack,
592+
llvm::Value *index,
593+
SILType elementType) {
594+
// When we have an indirect pack, the elements are pointers, so we can
595+
// simply index into that flat array.
596+
assert(elementType.isAddress() && "direct packs not currently supported");
597+
auto elementSize = IGF.IGM.getPointerSize();
598+
auto elementAddress = IGF.Builder.CreateArrayGEP(pack, index, elementSize);
599+
return IGF.Builder.CreateElementBitCast(elementAddress,
600+
IGF.IGM.getStoragePointerType(elementType));
601+
}

lib/IRGen/GenPack.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ llvm::Value *emitIndexOfStructuralPackComponent(IRGenFunction &IGF,
6767
CanPackType packType,
6868
unsigned componentIndex);
6969

70+
/// Emit the address that stores the given pack element.
71+
///
72+
/// For indirect packs, note that this is the address of the pack
73+
/// array element, not the address stored in the pack array element.
74+
Address emitStorageAddressOfPackElement(IRGenFunction &IGF,
75+
Address pack, llvm::Value *index,
76+
SILType elementType);
77+
7078
} // end namespace irgen
7179
} // end namespace swift
7280

lib/IRGen/IRBuilder.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,19 @@ class IRBuilder : public IRBuilderBase {
222222
base.getAlignment().alignmentAtOffset(eltSize * index));
223223
}
224224

225+
/// Given a pointer to an array element, GEP to the array element
226+
/// N elements past it. The type is not changed.
227+
Address CreateArrayGEP(Address base, llvm::Value *index, Size eltSize,
228+
const llvm::Twine &name = "") {
229+
auto addr = CreateInBoundsGEP(base.getElementType(),
230+
base.getAddress(), index, name);
231+
// Given that Alignment doesn't remember offset alignment,
232+
// the alignment at index 1 should be conservatively correct for
233+
// any element in the array.
234+
return Address(addr, base.getElementType(),
235+
base.getAlignment().alignmentAtOffset(eltSize));
236+
}
237+
225238
/// Given an i8*, GEP to N bytes past it.
226239
Address CreateConstByteArrayGEP(Address base, Size offset,
227240
const llvm::Twine &name = "") {

lib/IRGen/IRGenSIL.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,8 @@ class IRGenSILFunction :
12791279
void visitDynamicPackIndexInst(DynamicPackIndexInst *i);
12801280
void visitPackPackIndexInst(PackPackIndexInst *i);
12811281
void visitScalarPackIndexInst(ScalarPackIndexInst *i);
1282+
void visitPackElementGetInst(PackElementGetInst *i);
1283+
void visitPackElementSetInst(PackElementSetInst *i);
12821284

12831285
void visitProjectBlockStorageInst(ProjectBlockStorageInst *i);
12841286
void visitInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *i);
@@ -6885,6 +6887,39 @@ void IRGenSILFunction::visitOpenPackElementInst(swift::OpenPackElementInst *i) {
68856887
// The result is just used for type dependencies.
68866888
}
68876889

6890+
void IRGenSILFunction::visitPackElementGetInst(PackElementGetInst *i) {
6891+
Address pack = getLoweredAddress(i->getPack());
6892+
llvm::Value *index = getLoweredSingletonExplosion(i->getIndex());
6893+
6894+
auto elementType = i->getElementType();
6895+
auto &elementTI = getTypeInfo(elementType);
6896+
6897+
auto elementStorageAddr =
6898+
emitStorageAddressOfPackElement(*this, pack, index, elementType);
6899+
6900+
assert(elementType.isAddress() &&
6901+
i->getPackType()->isElementAddress() &&
6902+
"direct packs not currently supported");
6903+
auto ptr = Builder.CreateLoad(elementStorageAddr);
6904+
auto elementAddr = elementTI.getAddressForPointer(ptr);
6905+
setLoweredAddress(i, elementAddr);
6906+
}
6907+
6908+
void IRGenSILFunction::visitPackElementSetInst(PackElementSetInst *i) {
6909+
Address pack = getLoweredAddress(i->getPack());
6910+
llvm::Value *index = getLoweredSingletonExplosion(i->getIndex());
6911+
6912+
auto elementType = i->getElementType();
6913+
auto elementStorageAddress =
6914+
emitStorageAddressOfPackElement(*this, pack, index, elementType);
6915+
6916+
assert(elementType.isAddress() &&
6917+
i->getPackType()->isElementAddress() &&
6918+
"direct packs not currently supported");
6919+
auto elementValue = getLoweredAddress(i->getValue());
6920+
Builder.CreateStore(elementValue.getAddress(), elementStorageAddress);
6921+
}
6922+
68886923
void IRGenSILFunction::visitProjectBlockStorageInst(ProjectBlockStorageInst *i){
68896924
// TODO
68906925
Address block = getLoweredAddress(i->getOperand());

lib/Parse/ParseType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
179179
case tok::identifier:
180180
// In SIL files (not just when parsing SIL types), accept the
181181
// Pack{} syntax for spelling variadic type packs.
182-
if (SIL && Tok.isContextualKeyword("Pack") &&
182+
if (isInSILMode() && Tok.isContextualKeyword("Pack") &&
183183
peekToken().is(tok::l_brace)) {
184184
TokReceiver->registerTokenKindChange(Tok.getLoc(),
185185
tok::contextual_keyword);

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ OPERAND_OWNERSHIP(TrivialUse, UncheckedTakeEnumDataAddr)
197197
OPERAND_OWNERSHIP(TrivialUse, UnconditionalCheckedCastAddr)
198198
OPERAND_OWNERSHIP(TrivialUse, DynamicPackIndex)
199199
OPERAND_OWNERSHIP(TrivialUse, PackPackIndex)
200+
OPERAND_OWNERSHIP(TrivialUse, PackElementGet)
201+
OPERAND_OWNERSHIP(TrivialUse, PackElementSet)
200202

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

0 commit comments

Comments
 (0)