Skip to content

Commit b7ea3b9

Browse files
committed
[SIL] Let alloc_existential_box return a single value.
And use the new project_existential_box to get to the address value. SILGen now generates a project_existential_box for each alloc_existential_box. And IRGen re-uses the address value from the alloc_existential_box if the operand of project_existential_box is an alloc_existential_box. This lets the generated code be the same as before.
1 parent 4dab67c commit b7ea3b9

24 files changed

+137
-165
lines changed

docs/SIL.rst

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -703,25 +703,14 @@ Values and Operands
703703

704704
sil-identifier ::= [A-Za-z_0-9]+
705705
sil-value-name ::= '%' sil-identifier
706-
sil-value ::= sil-value-name ('#' [0-9]+)?
706+
sil-value ::= sil-value-name
707707
sil-value ::= 'undef'
708708
sil-operand ::= sil-value ':' sil-type
709709

710710
SIL values are introduced with the ``%`` sigil and named by an
711711
alphanumeric identifier, which references the instruction or basic block
712712
argument that produces the value. SIL values may also refer to the keyword
713713
'undef', which is a value of undefined contents.
714-
In SIL, a single instruction may produce multiple values. Operands that refer
715-
to multiple-value instructions choose the value by following the ``%name`` with
716-
``#`` and the index of the value. For example::
717-
718-
// alloc_existential_box produces two values--the refcounted pointer %box#0,
719-
// and the value address %box#1
720-
%box = alloc_existential_box $ErrorType, $MyError
721-
// Refer to the address
722-
store %value to %box#1 : $*MyError
723-
// Refer to the refcounted pointer
724-
throw %box#0 : $ErrorType
725714

726715
Unlike LLVM IR, SIL instructions that take value operands *only* accept
727716
value operands. References to literal constants, functions, global variables, or
@@ -3289,8 +3278,9 @@ more expensive ``alloc_existential_box``::
32893278
// The slow general way to form an ErrorType, allocating a box and
32903279
// storing to its value buffer:
32913280
%error1 = alloc_existential_box $ErrorType, $NSError
3281+
%addr = project_existential_box $NSError in %error1 : $ErrorType
32923282
strong_retain %nserror: $NSError
3293-
store %nserror to %error1#1 : $NSError
3283+
store %nserror to %addr : $NSError
32943284

32953285
// The fast path supported for NSError:
32963286
strong_retain %nserror: $NSError
@@ -3432,16 +3422,16 @@ alloc_existential_box
34323422
// $P must be a protocol or protocol composition type with boxed
34333423
// representation
34343424
// $T must be an AST type that conforms to P
3435-
// %1#0 will be of type $P
3425+
// %1 will be of type $P
34363426
// %1#1 will be of type $*T', where T' is the most abstracted lowering of T
34373427

34383428
Allocates a boxed existential container of type ``$P`` with space to hold a
34393429
value of type ``$T'``. The box is not fully initialized until a valid value
34403430
has been stored into the box. If the box must be deallocated before it is
34413431
fully initialized, ``dealloc_existential_box`` must be used. A fully
34423432
initialized box can be ``retain``-ed and ``release``-d like any
3443-
reference-counted type. The address ``%0#1`` is dependent on the lifetime of
3444-
the owner reference ``%0#0``.
3433+
reference-counted type. The ``project_existential_box`` instruction is used
3434+
to retrieve the address of the value inside the container.
34453435

34463436
project_existential_box
34473437
```````````````````````
@@ -3456,6 +3446,7 @@ project_existential_box
34563446
// %1 will be of type $*T
34573447

34583448
Projects the address of the value inside a boxed existential container.
3449+
The address is dependent on the lifetime of the owner reference ``%0``.
34593450
It is undefined behavior if the concrete type ``$T`` is not the same type for
34603451
which the box was allocated with ``alloc_existential_box``.
34613452

include/swift/SIL/SILBuilder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,11 @@ class SILBuilder {
260260

261261
AllocExistentialBoxInst *
262262
createAllocExistentialBox(SILLocation Loc, SILType ExistentialType,
263-
CanType ConcreteType, SILType ConcreteLoweredType,
263+
CanType ConcreteType,
264264
ArrayRef<ProtocolConformanceRef> Conformances) {
265265
return insert(AllocExistentialBoxInst::create(
266266
createSILDebugLocation(Loc), ExistentialType, ConcreteType,
267-
ConcreteLoweredType, Conformances, &F));
267+
Conformances, &F));
268268
}
269269

270270
ApplyInst *createApply(SILLocation Loc, SILValue Fn, SILType SubstFnTy,

include/swift/SIL/SILCloner.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,6 @@ SILCloner<ImplClass>::visitAllocExistentialBoxInst(
457457
getBuilder().createAllocExistentialBox(getOpLocation(Inst->getLoc()),
458458
getOpType(origExistentialType),
459459
getOpASTType(origFormalType),
460-
getOpType(Inst->getLoweredConcreteType()),
461460
conformances));
462461
}
463462

include/swift/SIL/SILInstruction.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -588,18 +588,17 @@ class AllocBoxInst : public AllocationInst {
588588
/// value is uninitialized.
589589
class AllocExistentialBoxInst : public AllocationInst {
590590
friend class SILBuilder;
591-
592591
CanType ConcreteType;
593592
ArrayRef<ProtocolConformanceRef> Conformances;
594593

595594
AllocExistentialBoxInst(SILDebugLocation *DebugLoc, SILType ExistentialType,
596-
CanType ConcreteType, SILType ConcreteLoweredType,
595+
CanType ConcreteType,
597596
ArrayRef<ProtocolConformanceRef> Conformances,
598597
SILFunction *Parent);
599598

600599
static AllocExistentialBoxInst *
601600
create(SILDebugLocation *DebugLoc, SILType ExistentialType,
602-
CanType ConcreteType, SILType ConcreteLoweredType,
601+
CanType ConcreteType,
603602
ArrayRef<ProtocolConformanceRef> Conformances, SILFunction *Parent);
604603

605604
public:
@@ -611,17 +610,10 @@ class AllocExistentialBoxInst : public AllocationInst {
611610
return getType(0);
612611
}
613612

614-
SILType getLoweredConcreteType() const {
615-
return getType(1);
616-
}
617-
618613
ArrayRef<ProtocolConformanceRef> getConformances() const {
619614
return Conformances;
620615
}
621616

622-
SILValue getExistentialResult() const { return SILValue(this, 0); }
623-
SILValue getValueAddressResult() const { return SILValue(this, 1); }
624-
625617
ArrayRef<Operand> getAllOperands() const { return {}; }
626618
MutableArrayRef<Operand> getAllOperands() { return {}; }
627619

lib/IRGen/GenExistential.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,18 +1668,14 @@ Address irgen::emitOpenExistentialBox(IRGenFunction &IGF,
16681668

16691669
/// Allocate a boxed existential container with uninitialized space to hold a
16701670
/// value of a given type.
1671-
Address irgen::emitBoxedExistentialContainerAllocation(IRGenFunction &IGF,
1672-
Explosion &dest,
1671+
OwnedAddress irgen::emitBoxedExistentialContainerAllocation(IRGenFunction &IGF,
16731672
SILType destType,
16741673
CanType formalSrcType,
1675-
SILType loweredSrcType,
16761674
ArrayRef<ProtocolConformanceRef> conformances) {
16771675
// TODO: Non-ErrorType boxed existentials.
16781676
assert(_isErrorType(destType));
16791677

16801678
auto &destTI = IGF.getTypeInfo(destType).as<ErrorExistentialTypeInfo>();
1681-
auto &srcTI = IGF.getTypeInfo(loweredSrcType);
1682-
16831679
auto srcMetadata = IGF.emitTypeMetadataRef(formalSrcType);
16841680
// Should only be one conformance, for the ErrorType protocol.
16851681
assert(conformances.size() == 1 && destTI.getStoredProtocols().size() == 1);
@@ -1699,11 +1695,13 @@ Address irgen::emitBoxedExistentialContainerAllocation(IRGenFunction &IGF,
16991695
// Extract the box and value address from the result.
17001696
auto box = IGF.Builder.CreateExtractValue(result, 0);
17011697
auto addr = IGF.Builder.CreateExtractValue(result, 1);
1702-
dest.add(box);
1703-
1698+
1699+
auto archetype = ArchetypeType::getOpened(destType.getSwiftRValueType());
1700+
auto &srcTI = IGF.getTypeInfoForUnlowered(AbstractionPattern(archetype),
1701+
formalSrcType);
17041702
addr = IGF.Builder.CreateBitCast(addr,
17051703
srcTI.getStorageType()->getPointerTo());
1706-
return srcTI.getAddressForPointer(addr);
1704+
return OwnedAddress(srcTI.getAddressForPointer(addr), box);
17071705
}
17081706

17091707
/// Deallocate a boxed existential container with uninitialized space to hold a

lib/IRGen/GenExistential.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,9 @@ namespace irgen {
6565

6666
/// Allocate a boxed existential container with uninitialized space to hold a
6767
/// value of a given type.
68-
Address emitBoxedExistentialContainerAllocation(IRGenFunction &IGF,
69-
Explosion &dest,
68+
OwnedAddress emitBoxedExistentialContainerAllocation(IRGenFunction &IGF,
7069
SILType destType,
7170
CanType formalSrcType,
72-
SILType loweredSrcType,
7371
ArrayRef<ProtocolConformanceRef> conformances);
7472

7573
/// "Deinitialize" an existential container whose contained value is allocated

lib/IRGen/IRGenSIL.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4456,14 +4456,11 @@ void IRGenSILFunction::visitInitBlockStorageHeaderInst(
44564456
}
44574457

44584458
void IRGenSILFunction::visitAllocExistentialBoxInst(AllocExistentialBoxInst *i){
4459-
Explosion box;
4460-
auto projectionAddr =
4461-
emitBoxedExistentialContainerAllocation(*this, box, i->getExistentialType(),
4459+
OwnedAddress boxWithAddr =
4460+
emitBoxedExistentialContainerAllocation(*this, i->getExistentialType(),
44624461
i->getFormalConcreteType(),
4463-
i->getLoweredConcreteType(),
44644462
i->getConformances());
4465-
setLoweredExplosion(i->getExistentialResult(), box);
4466-
setLoweredAddress(i->getValueAddressResult(), projectionAddr);
4463+
setLoweredBox(i, boxWithAddr);
44674464
}
44684465

44694466
void IRGenSILFunction::visitDeallocExistentialBoxInst(
@@ -4485,11 +4482,18 @@ void IRGenSILFunction::visitOpenExistentialBoxInst(OpenExistentialBoxInst *i) {
44854482

44864483
void
44874484
IRGenSILFunction::visitProjectExistentialBoxInst(ProjectExistentialBoxInst *i) {
4488-
Explosion box = getLoweredExplosion(i->getOperand());
4489-
auto caddr = emitBoxedExistentialProjection(*this, box,
4490-
i->getOperand().getType(),
4491-
i->getType().getSwiftRValueType());
4492-
setLoweredAddress(i, caddr.getAddress());
4485+
const LoweredValue &val = getLoweredValue(i->getOperand());
4486+
if (val.isBoxWithAddress()) {
4487+
// The operand is an alloc_existential_box.
4488+
// We can directly reuse the address.
4489+
setLoweredAddress(i, val.getAddressOfBox());
4490+
} else {
4491+
Explosion box = getLoweredExplosion(i->getOperand());
4492+
auto caddr = emitBoxedExistentialProjection(*this, box,
4493+
i->getOperand().getType(),
4494+
i->getType().getSwiftRValueType());
4495+
setLoweredAddress(i, caddr.getAddress());
4496+
}
44934497
}
44944498

44954499
void IRGenSILFunction::visitDynamicMethodInst(DynamicMethodInst *i) {

lib/Parse/ParseSIL.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,22 +3301,13 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB) {
33013301
parseASTType(ConcreteFormalTy))
33023302
return true;
33033303

3304-
// Lower the type at the abstraction level of the existential.
3305-
auto archetype
3306-
= ArchetypeType::getOpened(ExistentialTy.getSwiftRValueType())
3307-
->getCanonicalType();
3308-
3309-
SILType LoweredTy = SILMod.Types.getLoweredType(
3310-
Lowering::AbstractionPattern(archetype), ConcreteFormalTy)
3311-
.getAddressType();
3312-
33133304
// Collect conformances for the type.
33143305
ArrayRef<ProtocolConformanceRef> conformances
33153306
= collectExistentialConformances(P, ConcreteFormalTy,
33163307
ExistentialTy.getSwiftRValueType());
33173308

33183309
ResultVal = B.createAllocExistentialBox(InstLoc, ExistentialTy,
3319-
ConcreteFormalTy, LoweredTy, conformances);
3310+
ConcreteFormalTy, conformances);
33203311

33213312
break;
33223313
}

lib/SIL/SILInstructions.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,11 @@ VarDecl *DebugValueAddrInst::getDecl() const {
127127
return getLoc().getAsASTNode<VarDecl>();
128128
}
129129

130-
static SILTypeList *getAllocExistentialBoxType(SILType ExistTy,
131-
SILType ConcreteTy,
132-
SILFunction &F) {
133-
SILType Tys[] = {
134-
ExistTy.getObjectType(),
135-
ConcreteTy.getAddressType(),
136-
};
137-
return F.getModule().getSILTypeList(Tys);
138-
}
139-
140130
AllocExistentialBoxInst::AllocExistentialBoxInst(
141131
SILDebugLocation *Loc, SILType ExistentialType, CanType ConcreteType,
142-
SILType ConcreteLoweredType, ArrayRef<ProtocolConformanceRef> Conformances,
143-
SILFunction *Parent)
132+
ArrayRef<ProtocolConformanceRef> Conformances, SILFunction *Parent)
144133
: AllocationInst(ValueKind::AllocExistentialBoxInst, Loc,
145-
getAllocExistentialBoxType(ExistentialType,
146-
ConcreteLoweredType, *Parent)),
134+
ExistentialType.getObjectType()),
147135
ConcreteType(ConcreteType), Conformances(Conformances) {}
148136

149137
static void declareWitnessTable(SILModule &Mod,
@@ -159,7 +147,7 @@ static void declareWitnessTable(SILModule &Mod,
159147

160148
AllocExistentialBoxInst *AllocExistentialBoxInst::create(
161149
SILDebugLocation *Loc, SILType ExistentialType, CanType ConcreteType,
162-
SILType ConcreteLoweredType, ArrayRef<ProtocolConformanceRef> Conformances,
150+
ArrayRef<ProtocolConformanceRef> Conformances,
163151
SILFunction *F) {
164152
SILModule &Mod = F->getModule();
165153
void *Buffer = Mod.allocateInst(sizeof(AllocExistentialBoxInst),
@@ -169,7 +157,6 @@ AllocExistentialBoxInst *AllocExistentialBoxInst::create(
169157
return ::new (Buffer) AllocExistentialBoxInst(Loc,
170158
ExistentialType,
171159
ConcreteType,
172-
ConcreteLoweredType,
173160
Conformances, F);
174161
}
175162

lib/SIL/Verifier.cpp

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,9 +1126,18 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11261126
"project_existential_box result must be an address");
11271127

11281128
if (auto *AEBI = dyn_cast<AllocExistentialBoxInst>(PEBI->getOperand())) {
1129-
require(AEBI->getLoweredConcreteType() == PEBI->getType(),
1130-
"type of project_existential_box does not match with the formal "
1131-
"type of alloc_existential_box");
1129+
// The lowered type must be the properly-abstracted form of the AST type.
1130+
SILType exType = AEBI->getExistentialType();
1131+
auto archetype = ArchetypeType::getOpened(exType.getSwiftRValueType());
1132+
1133+
auto loweredTy = F.getModule().Types.getLoweredType(
1134+
Lowering::AbstractionPattern(archetype),
1135+
AEBI->getFormalConcreteType())
1136+
.getAddressType();
1137+
1138+
requireSameType(loweredTy, PEBI->getType(),
1139+
"project_existential_box result should be the lowered "
1140+
"concrete type of its alloc_existential_box");
11321141
}
11331142
}
11341143

@@ -1836,22 +1845,6 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
18361845
"alloc_existential_box must be used with a boxed existential "
18371846
"type");
18381847

1839-
// The lowered type must be the properly-abstracted form of the AST type.
1840-
auto archetype = ArchetypeType::getOpened(exType.getSwiftRValueType());
1841-
1842-
auto loweredTy = F.getModule().Types.getLoweredType(
1843-
Lowering::AbstractionPattern(archetype),
1844-
AEBI->getFormalConcreteType())
1845-
.getAddressType();
1846-
1847-
requireSameType(loweredTy, AEBI->getLoweredConcreteType(),
1848-
"alloc_existential_box #1 result should be the lowered "
1849-
"concrete type at the right abstraction level");
1850-
require(isLoweringOf(AEBI->getLoweredConcreteType(),
1851-
AEBI->getFormalConcreteType()),
1852-
"alloc_existential_box payload must be a lowering of the formal "
1853-
"concrete type");
1854-
18551848
checkExistentialProtocolConformances(exType, AEBI->getConformances());
18561849
}
18571850

lib/SILGen/SILGenConvert.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -448,14 +448,13 @@ ManagedValue SILGenFunction::emitExistentialErasure(
448448
}
449449
case ExistentialRepresentation::Boxed: {
450450
// Allocate the existential.
451-
auto box = B.createAllocExistentialBox(loc,
451+
auto *existential = B.createAllocExistentialBox(loc,
452452
existentialTL.getLoweredType(),
453453
concreteFormalType,
454-
concreteTL.getLoweredType(),
455454
conformances);
456-
auto existential = box->getExistentialResult();
457-
auto valueAddr = box->getValueAddressResult();
458-
455+
auto *valueAddr = B.createProjectExistentialBox(loc,
456+
concreteTL.getLoweredType(),
457+
existential);
459458
// Initialize the concrete value in-place.
460459
InitializationPtr init(
461460
new ExistentialInitialization(existential, valueAddr, concreteFormalType,

lib/SILGen/SILGenFunction.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,13 +887,11 @@ AllocExistentialBoxInst *
887887
SILGenBuilder::createAllocExistentialBox(SILLocation Loc,
888888
SILType ExistentialType,
889889
CanType ConcreteType,
890-
SILType ConcreteLoweredType,
891890
ArrayRef<ProtocolConformanceRef> Conformances) {
892891
for (auto conformance : Conformances)
893892
SGM.useConformance(conformance);
894893

895894
return SILBuilder::createAllocExistentialBox(Loc, ExistentialType,
896895
ConcreteType,
897-
ConcreteLoweredType,
898896
Conformances);
899897
}

lib/SILGen/SILGenFunction.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ class SILGenBuilder : public SILBuilder {
254254
AllocExistentialBoxInst *createAllocExistentialBox(SILLocation Loc,
255255
SILType ExistentialType,
256256
CanType ConcreteType,
257-
SILType ConcreteLoweredType,
258257
ArrayRef<ProtocolConformanceRef> Conformances);
259258
};
260259

0 commit comments

Comments
 (0)