|
49 | 49 | #include "GenHeap.h"
|
50 | 50 | #include "GenMeta.h"
|
51 | 51 | #include "GenObjC.h"
|
| 52 | +#include "GenOpaque.h" |
52 | 53 | #include "GenPoly.h"
|
53 | 54 | #include "GenProto.h"
|
54 | 55 | #include "GenStruct.h"
|
@@ -3219,6 +3220,7 @@ static bool tryDeferFixedSizeBufferInitialization(IRGenSILFunction &IGF,
|
3219 | 3220 | const TypeInfo &ti,
|
3220 | 3221 | SILValue containerValue,
|
3221 | 3222 | SILValue addressValue,
|
| 3223 | + Address fixedSizeBuffer, |
3222 | 3224 | const llvm::Twine &name) {
|
3223 | 3225 | // There's no point in doing this for fixed-sized types, since we'll allocate
|
3224 | 3226 | // an appropriately-sized buffer for them statically.
|
@@ -3254,7 +3256,8 @@ static bool tryDeferFixedSizeBufferInitialization(IRGenSILFunction &IGF,
|
3254 | 3256 |
|
3255 | 3257 | // We can defer to this initialization. Allocate the fixed-size buffer
|
3256 | 3258 | // now, but don't allocate the value inside it.
|
3257 |
| - auto fixedSizeBuffer = IGF.createFixedSizeBufferAlloca(name); |
| 3259 | + if (!fixedSizeBuffer.getAddress()) |
| 3260 | + fixedSizeBuffer = IGF.createFixedSizeBufferAlloca(name); |
3258 | 3261 | if (containerValue)
|
3259 | 3262 | IGF.setLoweredAddress(containerValue, fixedSizeBuffer);
|
3260 | 3263 | IGF.setLoweredUnallocatedAddressInBuffer(addressValue, fixedSizeBuffer);
|
@@ -3307,6 +3310,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
|
3307 | 3310 | if (tryDeferFixedSizeBufferInitialization(*this, i, type,
|
3308 | 3311 | i->getContainerResult(),
|
3309 | 3312 | i->getAddressResult(),
|
| 3313 | + Address(), |
3310 | 3314 | dbgname))
|
3311 | 3315 | return;
|
3312 | 3316 |
|
@@ -4076,7 +4080,52 @@ void IRGenSILFunction::visitInitExistentialAddrInst(swift::InitExistentialAddrIn
|
4076 | 4080 | i->getFormalConcreteType(),
|
4077 | 4081 | i->getLoweredConcreteType(),
|
4078 | 4082 | i->getConformances());
|
4079 |
| - setLoweredAddress(SILValue(i, 0), buffer); |
| 4083 | + |
| 4084 | + auto &srcTI = getTypeInfo(i->getLoweredConcreteType()); |
| 4085 | + |
| 4086 | + // See if we can defer initialization of the buffer to a copy_addr into it. |
| 4087 | + if (tryDeferFixedSizeBufferInitialization(*this, i, srcTI, SILValue(), i, |
| 4088 | + buffer, "")) |
| 4089 | + return; |
| 4090 | + |
| 4091 | + // Compute basic layout information about the type. If we have a |
| 4092 | + // concrete type, we need to know how it packs into a fixed-size |
| 4093 | + // buffer. If we don't, we need a value witness table. |
| 4094 | + |
| 4095 | + |
| 4096 | + FixedPacking packing; |
| 4097 | + bool needValueWitnessToAllocate; |
| 4098 | + if (!isa<FixedTypeInfo>(srcTI)) { |
| 4099 | + packing = (FixedPacking) -1; |
| 4100 | + needValueWitnessToAllocate = true; |
| 4101 | + } else { |
| 4102 | + packing = srcTI.getFixedPacking(IGM); |
| 4103 | + needValueWitnessToAllocate = false; |
| 4104 | + } |
| 4105 | + |
| 4106 | + // Project down to the destination fixed-size buffer. |
| 4107 | + Address address = [&]{ |
| 4108 | + // If the type is provably empty, we're done. |
| 4109 | + if (srcTI.isKnownEmpty()) { |
| 4110 | + assert(packing == FixedPacking::OffsetZero); |
| 4111 | + return buffer; |
| 4112 | + } |
| 4113 | + |
| 4114 | + // Otherwise, allocate if necessary. |
| 4115 | + |
| 4116 | + if (needValueWitnessToAllocate) { |
| 4117 | + // If we're using a witness-table to do this, we need to emit a |
| 4118 | + // value-witness call to allocate the fixed-size buffer. |
| 4119 | + return Address(emitAllocateBufferCall(*this, i->getLoweredConcreteType(), |
| 4120 | + buffer), |
| 4121 | + Alignment(1)); |
| 4122 | + } else { |
| 4123 | + // Otherwise, allocate using what we know statically about the type. |
| 4124 | + return emitAllocateBuffer(*this, i->getLoweredConcreteType(), buffer); |
| 4125 | + } |
| 4126 | + }(); |
| 4127 | + |
| 4128 | + setLoweredAddress(SILValue(i, 0), address); |
4080 | 4129 | }
|
4081 | 4130 |
|
4082 | 4131 | void IRGenSILFunction::visitInitExistentialMetatypeInst(
|
@@ -4297,7 +4346,7 @@ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) {
|
4297 | 4346 | Address addr = addrTI.initializeBufferWithTake(*this, dest, src, addrTy);
|
4298 | 4347 | setAllocatedAddressForBuffer(i->getDest(), addr);
|
4299 | 4348 | } else
|
4300 |
| - addrTI.initializeWithTake(*this, dest, src, addrTy); |
| 4349 | + addrTI.initializeWithTake(*this, dest, src, addrTy); |
4301 | 4350 | break;
|
4302 | 4351 | default:
|
4303 | 4352 | llvm_unreachable("unexpected take/initialize attribute combination?!");
|
|
0 commit comments