Skip to content

Commit 6ff2f09

Browse files
committed
[SIL] Let alloc_stack return a single value.
Having a separate address and container value returned from alloc_stack is not really needed in SIL. Even if they differ we have both addresses available during IRGen, because a dealloc_stack is always dominated by the corresponding alloc_stack in the same function. Although this commit quite large, most changes are trivial. The largest non-trivial change is in IRGenSIL. This commit is a NFC regarding the generated code. Even the generated SIL is the same (except removed #0, #1 and @local_storage).
1 parent 5f80471 commit 6ff2f09

File tree

188 files changed

+2851
-2889
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

188 files changed

+2851
-2889
lines changed

docs/SIL.rst

+12-26
Original file line numberDiff line numberDiff line change
@@ -386,22 +386,6 @@ type. Values of address type thus cannot be allocated, loaded, or stored
386386
Addresses can be passed as arguments to functions if the corresponding
387387
parameter is indirect. They cannot be returned.
388388

389-
Local Storage Types
390-
```````````````````
391-
392-
The *address of local storage for T* ``$*@local_storage T`` is a
393-
handle to a stack allocation of a variable of type ``$T``.
394-
395-
For many types, the handle for a stack allocation is simply the
396-
allocated address itself. However, if a type is runtime-sized, the
397-
compiler must emit code to potentially dynamically allocate memory.
398-
SIL abstracts over such differences by using values of local-storage
399-
type as the first result of ``alloc_stack`` and the operand of
400-
``dealloc_stack``.
401-
402-
Local-storage address types are not *first-class* in the same sense
403-
that address types are not first-class.
404-
405389
Box Types
406390
`````````
407391

@@ -1634,13 +1618,15 @@ alloc_stack
16341618
sil-instruction ::= 'alloc_stack' sil-type (',' debug-var-attr)*
16351619

16361620
%1 = alloc_stack $T
1637-
// %1#0 has type $*@local_storage T
1638-
// %1#1 has type $*T
1621+
// %1 has type $*T
16391622

16401623
Allocates uninitialized memory that is sufficiently aligned on the stack
1641-
to contain a value of type ``T``. The first result of the instruction
1642-
is a local-storage handle suitable for passing to ``dealloc_stack``.
1643-
The second result of the instruction is the address of the allocated memory.
1624+
to contain a value of type ``T``. The result of the instruction is the address
1625+
of the allocated memory.
1626+
1627+
If a type is runtime-sized, the compiler must emit code to potentially
1628+
dynamically allocate memory. So there is no guarantee that the allocated
1629+
memory is really located on the stack.
16441630

16451631
``alloc_stack`` marks the start of the lifetime of the value; the
16461632
allocation must be balanced with a ``dealloc_stack`` instruction to
@@ -1741,16 +1727,16 @@ dealloc_stack
17411727

17421728
sil-instruction ::= 'dealloc_stack' sil-operand
17431729

1744-
dealloc_stack %0 : $*@local_storage T
1745-
// %0 must be of a local-storage $*@local_storage T type
1730+
dealloc_stack %0 : $*T
1731+
// %0 must be of $*T type
17461732

17471733
Deallocates memory previously allocated by ``alloc_stack``. The
17481734
allocated value in memory must be uninitialized or destroyed prior to
17491735
being deallocated. This instruction marks the end of the lifetime for
17501736
the value created by the corresponding ``alloc_stack`` instruction. The operand
1751-
must be the ``@local_storage`` of the shallowest live ``alloc_stack``
1752-
allocation preceding the deallocation. In other words, deallocations must be
1753-
in last-in, first-out stack order.
1737+
must be the shallowest live ``alloc_stack`` allocation preceding the
1738+
deallocation. In other words, deallocations must be in last-in, first-out
1739+
stack order.
17541740

17551741
dealloc_box
17561742
```````````

include/swift/SIL/SILInstruction.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,15 @@ class AllocStackInst : public AllocationInst {
460460
};
461461
void setArgNo(unsigned N) { VarInfo.setArgNo(N); }
462462

463+
/// getType() is ok since this is known to only have one type.
464+
SILType getType(unsigned i = 0) const { return ValueBase::getType(i); }
465+
463466
/// getElementType - Get the type of the allocated memory (as opposed to the
464-
/// (second) type of the instruction itself, which will be an address type).
467+
/// type of the instruction itself, which will be an address type).
465468
SILType getElementType() const {
466-
return getType(1).getObjectType();
469+
return getType().getObjectType();
467470
}
468471

469-
SILValue getContainerResult() const { return SILValue(this, 0); }
470-
SILValue getAddressResult() const { return SILValue(this, 1); }
471-
472472
ArrayRef<Operand> getAllOperands() const { return {}; }
473473
MutableArrayRef<Operand> getAllOperands() { return {}; }
474474

include/swift/Serialization/ModuleFormat.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t VERSION_MAJOR = 0;
5252
/// in source control, you should also update the comment to briefly
5353
/// describe what change you made. The content of this comment isn't important;
5454
/// it just ensures a conflict if two people change the module format.
55-
const uint16_t VERSION_MINOR = 228; // no substitutions for value witnesses
55+
const uint16_t VERSION_MINOR = 229; // alloc_stack returns a single value
5656

5757
using DeclID = Fixnum<31>;
5858
using DeclIDField = BCFixed<31>;

lib/IRGen/IRGenSIL.cpp

+59-46
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,15 @@ class LoweredValue {
124124
public:
125125
enum class Kind {
126126
/// This LoweredValue corresponds to a SIL address value.
127+
/// The LoweredValue of an alloc_stack keeps an owning container in
128+
/// addition to the address of the allocated buffer.
129+
/// Depending on the allocated type, the container may be equal to the
130+
/// buffer itself (for types with known sizes) or it may be the address
131+
/// of a fixed-size container which points to the heap-allocated buffer.
132+
/// In this case the address-part may be null, which means that the buffer
133+
/// is not allocated yet.
127134
Address,
128135

129-
/// This LoweredValue corresponds to a SIL address value owned by an
130-
/// uninitialized fixed-size buffer.
131-
UnallocatedAddressInBuffer,
132-
133136
/// The following kinds correspond to SIL non-address values.
134137
Value_First,
135138
/// A normal value, represented as an exploded array of llvm Values.
@@ -151,7 +154,7 @@ class LoweredValue {
151154
using ExplosionVector = SmallVector<llvm::Value *, 4>;
152155

153156
union {
154-
Address address;
157+
ContainedAddress address;
155158
struct {
156159
ExplosionVector values;
157160
} explosion;
@@ -160,14 +163,24 @@ class LoweredValue {
160163
};
161164

162165
public:
166+
167+
/// Create an address value without a container (the usual case).
163168
LoweredValue(const Address &address)
164-
: kind(Kind::Address), address(address)
169+
: kind(Kind::Address), address(Address(), address)
165170
{}
166171

167-
enum UnallocatedAddressInBuffer_t { UnallocatedAddressInBuffer };
172+
enum ContainerForUnallocatedAddress_t { ContainerForUnallocatedAddress };
173+
174+
/// Create an address value for an alloc_stack, consisting of a container and
175+
/// a not yet allocated buffer.
176+
LoweredValue(const Address &container, ContainerForUnallocatedAddress_t)
177+
: kind(Kind::Address), address(container, Address())
178+
{}
168179

169-
LoweredValue(const Address &address, UnallocatedAddressInBuffer_t)
170-
: kind(Kind::UnallocatedAddressInBuffer), address(address)
180+
/// Create an address value for an alloc_stack, consisting of a container and
181+
/// the address of the allocated buffer.
182+
LoweredValue(const ContainedAddress &address)
183+
: kind(Kind::Address), address(address)
171184
{}
172185

173186
LoweredValue(StaticFunction &&staticFunction)
@@ -189,8 +202,7 @@ class LoweredValue {
189202
{
190203
switch (kind) {
191204
case Kind::Address:
192-
case Kind::UnallocatedAddressInBuffer:
193-
::new (&address) Address(std::move(lv.address));
205+
::new (&address) ContainedAddress(std::move(lv.address));
194206
break;
195207
case Kind::Explosion:
196208
::new (&explosion.values) ExplosionVector(std::move(lv.explosion.values));
@@ -212,23 +224,24 @@ class LoweredValue {
212224
}
213225

214226
bool isAddress() const {
215-
return kind == Kind::Address;
227+
return kind == Kind::Address && address.getAddress().isValid();
216228
}
217229
bool isUnallocatedAddressInBuffer() const {
218-
return kind == Kind::UnallocatedAddressInBuffer;
230+
return kind == Kind::Address && !address.getAddress().isValid();
219231
}
220232
bool isValue() const {
221233
return kind >= Kind::Value_First && kind <= Kind::Value_Last;
222234
}
223235

224236
Address getAddress() const {
225-
assert(kind == Kind::Address && "not an allocated address");
226-
return address;
237+
assert(isAddress() && "not an allocated address");
238+
return address.getAddress();
227239
}
228240

229-
Address getAddressOfUnallocatedBuffer() const {
230-
assert(kind == Kind::UnallocatedAddressInBuffer);
231-
return address;
241+
Address getContainerOfAddress() const {
242+
assert(kind == Kind::Address);
243+
assert(address.getContainer().isValid() && "address has no container");
244+
return address.getContainer();
232245
}
233246

234247
void getExplosion(IRGenFunction &IGF, Explosion &ex) const;
@@ -254,8 +267,7 @@ class LoweredValue {
254267
~LoweredValue() {
255268
switch (kind) {
256269
case Kind::Address:
257-
case Kind::UnallocatedAddressInBuffer:
258-
address.~Address();
270+
address.~ContainedAddress();
259271
break;
260272
case Kind::Explosion:
261273
explosion.values.~ExplosionVector();
@@ -345,18 +357,28 @@ class IRGenSILFunction :
345357
setLoweredValue(v, address);
346358
}
347359

348-
void setLoweredUnallocatedAddressInBuffer(SILValue v,
349-
const Address &buffer) {
360+
void setLoweredContainedAddress(SILValue v, const ContainedAddress &address) {
361+
assert((v.getType().isAddress() || v.getType().isLocalStorage()) &&
362+
"address for non-address value?!");
363+
setLoweredValue(v, address);
364+
}
365+
366+
void setContainerOfUnallocatedAddress(SILValue v,
367+
const Address &buffer) {
350368
assert((v.getType().isAddress() || v.getType().isLocalStorage()) &&
351369
"address for non-address value?!");
352370
setLoweredValue(v,
353-
LoweredValue(buffer, LoweredValue::UnallocatedAddressInBuffer));
371+
LoweredValue(buffer, LoweredValue::ContainerForUnallocatedAddress));
354372
}
355373

356-
void overwriteLoweredAddress(SILValue v, const Address &address) {
374+
void overwriteAllocatedAddress(SILValue v, const Address &address) {
357375
assert((v.getType().isAddress() || v.getType().isLocalStorage()) &&
358376
"address for non-address value?!");
359-
overwriteLoweredValue(v, address);
377+
auto it = LoweredValues.find(v);
378+
assert(it != LoweredValues.end() && "no existing entry for overwrite?");
379+
assert(it->second.isUnallocatedAddressInBuffer() &&
380+
"not an unallocated address");
381+
it->second = ContainedAddress(it->second.getContainerOfAddress(), address);
360382
}
361383

362384
void setAllocatedAddressForBuffer(SILValue v, const Address &allocedAddress);
@@ -466,6 +488,9 @@ class IRGenSILFunction :
466488
Address getLoweredAddress(SILValue v) {
467489
return getLoweredValue(v).getAddress();
468490
}
491+
Address getLoweredContainerOfAddress(SILValue v) {
492+
return getLoweredValue(v).getContainerOfAddress();
493+
}
469494
/// Add the unmanaged LLVM values lowered from a SIL value to an explosion.
470495
void getLoweredExplosion(SILValue v, Explosion &e) {
471496
getLoweredValue(v).getExplosion(*this, e);
@@ -781,7 +806,6 @@ llvm::Value *StaticFunction::getExplosionValue(IRGenFunction &IGF) const {
781806
void LoweredValue::getExplosion(IRGenFunction &IGF, Explosion &ex) const {
782807
switch (kind) {
783808
case Kind::Address:
784-
case Kind::UnallocatedAddressInBuffer:
785809
llvm_unreachable("not a value");
786810

787811
case Kind::Explosion:
@@ -802,7 +826,6 @@ void LoweredValue::getExplosion(IRGenFunction &IGF, Explosion &ex) const {
802826
llvm::Value *LoweredValue::getSingletonExplosion(IRGenFunction &IGF) const {
803827
switch (kind) {
804828
case Kind::Address:
805-
case Kind::UnallocatedAddressInBuffer:
806829
llvm_unreachable("not a value");
807830

808831
case Kind::Explosion:
@@ -1849,7 +1872,6 @@ static CallEmission getCallEmissionForLoweredValue(IRGenSILFunction &IGF,
18491872
}
18501873

18511874
case LoweredValue::Kind::Address:
1852-
case LoweredValue::Kind::UnallocatedAddressInBuffer:
18531875
llvm_unreachable("sil address isn't a valid callee");
18541876
}
18551877

@@ -2015,7 +2037,6 @@ getPartialApplicationFunction(IRGenSILFunction &IGF,
20152037

20162038
switch (lv.kind) {
20172039
case LoweredValue::Kind::Address:
2018-
case LoweredValue::Kind::UnallocatedAddressInBuffer:
20192040
llvm_unreachable("can't partially apply an address");
20202041
case LoweredValue::Kind::ObjCMethod:
20212042
llvm_unreachable("objc method partial application shouldn't get here");
@@ -3255,7 +3276,6 @@ visitIsUniqueOrPinnedInst(swift::IsUniqueOrPinnedInst *i) {
32553276
static bool tryDeferFixedSizeBufferInitialization(IRGenSILFunction &IGF,
32563277
const SILInstruction *allocInst,
32573278
const TypeInfo &ti,
3258-
SILValue containerValue,
32593279
SILValue addressValue,
32603280
Address fixedSizeBuffer,
32613281
const llvm::Twine &name) {
@@ -3298,9 +3318,7 @@ static bool tryDeferFixedSizeBufferInitialization(IRGenSILFunction &IGF,
32983318
IGF.Builder.CreateLifetimeStart(fixedSizeBuffer,
32993319
getFixedBufferSize(IGF.IGM));
33003320
}
3301-
if (containerValue)
3302-
IGF.setLoweredAddress(containerValue, fixedSizeBuffer);
3303-
IGF.setLoweredUnallocatedAddressInBuffer(addressValue, fixedSizeBuffer);
3321+
IGF.setContainerOfUnallocatedAddress(addressValue, fixedSizeBuffer);
33043322
return true;
33053323
}
33063324

@@ -3345,8 +3363,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
33453363
// operation, we can combine the allocation and initialization using an
33463364
// optimized value witness.
33473365
if (tryDeferFixedSizeBufferInitialization(*this, i, type,
3348-
i->getContainerResult(),
3349-
i->getAddressResult(),
3366+
SILValue(i, 0),
33503367
Address(),
33513368
dbgname))
33523369
return;
@@ -3356,8 +3373,8 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
33563373
dbgname);
33573374

33583375
emitDebugInfoForAllocStack(i, type, addr.getAddress().getAddress());
3359-
setLoweredAddress(i->getContainerResult(), addr.getContainer());
3360-
setLoweredAddress(i->getAddressResult(), addr.getAddress());
3376+
3377+
setLoweredContainedAddress(i, addr);
33613378
}
33623379

33633380
void IRGenSILFunction::visitAllocRefInst(swift::AllocRefInst *i) {
@@ -3392,8 +3409,8 @@ void IRGenSILFunction::visitAllocRefDynamicInst(swift::AllocRefDynamicInst *i) {
33923409

33933410
void IRGenSILFunction::visitDeallocStackInst(swift::DeallocStackInst *i) {
33943411
const TypeInfo &type = getTypeInfo(i->getOperand().getType());
3395-
Address addr = getLoweredAddress(i->getOperand());
3396-
type.deallocateStack(*this, addr,
3412+
Address container = getLoweredContainerOfAddress(i->getOperand());
3413+
type.deallocateStack(*this, container,
33973414
i->getOperand().getType());
33983415
}
33993416

@@ -4204,8 +4221,7 @@ void IRGenSILFunction::visitInitExistentialAddrInst(swift::InitExistentialAddrIn
42044221
auto &srcTI = getTypeInfo(i->getLoweredConcreteType());
42054222

42064223
// See if we can defer initialization of the buffer to a copy_addr into it.
4207-
if (tryDeferFixedSizeBufferInitialization(*this, i, srcTI, SILValue(), i,
4208-
buffer, ""))
4224+
if (tryDeferFixedSizeBufferInitialization(*this, i, srcTI, i, buffer, ""))
42094225
return;
42104226

42114227
// Compute basic layout information about the type. If we have a
@@ -4414,11 +4430,8 @@ void IRGenSILFunction::visitWitnessMethodInst(swift::WitnessMethodInst *i) {
44144430

44154431
void IRGenSILFunction::setAllocatedAddressForBuffer(SILValue v,
44164432
const Address &allocedAddress) {
4417-
assert(getLoweredValue(v).kind ==
4418-
LoweredValue::Kind::UnallocatedAddressInBuffer &&
4419-
"not an unallocated address");
4433+
overwriteAllocatedAddress(v, allocedAddress);
44204434

4421-
overwriteLoweredAddress(v, allocedAddress);
44224435
// Emit the debug info for the variable if any.
44234436
if (auto allocStack = dyn_cast<AllocStackInst>(v)) {
44244437
emitDebugInfoForAllocStack(allocStack, getTypeInfo(v.getType()),
@@ -4435,7 +4448,7 @@ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) {
44354448
auto &loweredDest = getLoweredValue(i->getDest());
44364449
if (loweredDest.isUnallocatedAddressInBuffer()) {
44374450
isFixedBufferInitialization = true;
4438-
dest = loweredDest.getAddressOfUnallocatedBuffer();
4451+
dest = loweredDest.getContainerOfAddress();
44394452
} else {
44404453
isFixedBufferInitialization = false;
44414454
dest = loweredDest.getAddress();

lib/SIL/DynamicCasts.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ namespace {
658658
if (!source.shouldTake()) {
659659
sourceTemp = B.createAllocStack(Loc,
660660
sourceAddr.getType().getObjectType());
661-
sourceAddr = sourceTemp->getAddressResult();
661+
sourceAddr = sourceTemp;
662662
B.createCopyAddr(Loc, source.Value, sourceAddr, IsNotTake,
663663
IsInitialization);
664664
}
@@ -677,7 +677,7 @@ namespace {
677677

678678
// Deallocate the source temporary if we needed one.
679679
if (sourceTemp) {
680-
B.createDeallocStack(Loc, sourceTemp->getContainerResult());
680+
B.createDeallocStack(Loc, sourceTemp);
681681
}
682682

683683
Source result = emitSome(resultObject, target, state);

0 commit comments

Comments
 (0)