Skip to content

Commit 8b773dc

Browse files
committed
Add an ArrayLayoutEntry and dispatch to that for array raw layout
1 parent a029900 commit 8b773dc

File tree

6 files changed

+406
-90
lines changed

6 files changed

+406
-90
lines changed

lib/IRGen/GenRecord.h

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ class RecordTypeInfoImpl : public Base,
296296
// Because we have a rawlayout attribute, we know this has to be a struct.
297297
auto structDecl = T.getStructOrBoundGenericStruct();
298298

299-
auto take = [&](TypeInfo &likeTypeInfo, Address dest, Address stc) {
299+
auto take = [&](const TypeInfo &likeTypeInfo, SILType loweredLikeType,
300+
Address dest, Address src) {
300301
if (isInit) {
301302
likeTypeInfo.initializeWithTake(IGF, dest, src, loweredLikeType,
302303
isOutlined, zeroizeIfSensitive);
@@ -312,7 +313,7 @@ class RecordTypeInfoImpl : public Base,
312313
auto loweredLikeType = IGF.IGM.getLoweredType(likeType->subst(subs));
313314
auto &likeTypeInfo = IGF.IGM.getTypeInfo(loweredLikeType);
314315

315-
take(likeTypeInfo, dest, src);
316+
take(likeTypeInfo, loweredLikeType, dest, src);
316317
}
317318

318319
if (auto likeArray = rawLayout->getResolvedArrayLikeTypeAndCount(structDecl)) {
@@ -323,71 +324,13 @@ class RecordTypeInfoImpl : public Base,
323324
auto subs = astT->getContextSubstitutionMap();
324325
auto loweredLikeType = IGF.IGM.getLoweredType(likeType.subst(subs));
325326
auto &likeTypeInfo = IGF.IGM.getTypeInfo(loweredLikeType);
326-
countType = countType->subst(subs);
327-
328-
auto entry = IGF.Builder.GetInsertBlock();
329-
auto loop = IGF.createBasicBlock("loop");
330-
auto exit = IGF.createBasicBlock("exit");
331-
auto count = emitValueGenericRef(countType);
332-
333-
// FIXME: If we ever support generic value types other than Int, then
334-
// this needs to change to not assume signedness.
335-
auto cond = IGF.Builder.CreateICmpSLT(count,
336-
llvm::ConstantInt::get(IGF.IGM.SizeTy, 0));
337-
IGF.Builder.CreateCondBr(cond, loop, exit);
338-
339-
auto phi = IGF.Builder.CreatePHI(IGF.IGM.SizeTy, 2);
340-
phi->addIncoming(llvm::ConstantInt::get(IGF.IGM.SizeTy, 0), entry);
341-
342-
Address srcEltAddr;
343-
Address destEltAddr;
344-
345-
// If we have a fixed type, we can use a typed GEP to index into the
346-
// array raw layout. Otherwise, we need to advance by bytes given the
347-
// stride from the VWT of the like type.
348-
if (auto fixedLikeType = dyn_cast<FixedTypeInfo>(&likeTypeInfo)) {
349-
srcEltAddr = Address(IGF.Builder.CreateInBoundsGEP(
350-
fixedLikeType->getStorageType(),
351-
src.getAddress(),
352-
phi),
353-
fixedLikeType->getStorageType(),
354-
src.getAlignment());
355-
destEltAddr = Address(IGF.Builder.CreateInBoundsGEP(
356-
fixedLikeType->getStorageType(),
357-
dest.getAddress(),
358-
phi),
359-
fixedLikeType->getStorageType(),
360-
dest.getAlignment());
361-
} else {
362-
auto eltSize = likeTypeInfo.getStride(IGF, loweredLikeType);
363-
auto offset = IGF.Builder.CreateMul(phi, eltSize);
364-
365-
srcEltAddr = Address(IGF.Builder.CreateInBoundsGEP(
366-
IGF.IGM.Int8Ty,
367-
src.getAddress(),
368-
offset),
369-
IGF.IGM.Int8Ty,
370-
src.getAlignment());
371-
destEltAddr = Address(IGF.Builder.CreateInBoundsGEP(
372-
IGF.IGM.Int8Ty,
373-
dest.getAddress(),
374-
offset),
375-
IGF.IGM.Int8Ty,
376-
dest.getAlignment());
377-
}
378-
379-
take(likeTypeInfo, destEltAddr, srcEltAddr);
380-
381-
auto increment = IGF.Builder.CreateAdd(phi,
382-
llvm::ConstantInt::get(IGF.IGM.SizeTy, 1));
383-
384-
phi->addIncoming(increment, loop);
385-
386-
auto eqCond = IGF.Builder.CreateICmpEQ(increment, count);
387-
IGF.Builder.CreateCondBr(eqCond, exit, loop);
327+
countType = countType.subst(subs);
388328

389-
// We're done.
390-
IGF.Builder.emitBlock(exit);
329+
IGF.emitLoopOverElements(likeTypeInfo, loweredLikeType,
330+
countType->getCanonicalType(), dest, src,
331+
[&](Address dest, Address src) {
332+
take(likeTypeInfo, loweredLikeType, dest, src);
333+
});
391334
}
392335
}
393336
}

lib/IRGen/GenStruct.cpp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,20 +1019,26 @@ namespace {
10191019
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
10201020
}
10211021

1022-
auto likeType = rawLayout->getResolvedLikeType(decl)->getCanonicalType();
1023-
SILType loweredLikeType = IGM.getLoweredType(likeType);
1024-
10251022
// The given struct type T that we're building is fully concrete, but
10261023
// our like type is still in terms of the potential archetype of the
10271024
// type.
10281025
auto subs = T.getASTType()->getContextSubstitutionMap(decl);
1026+
auto likeType = rawLayout->getResolvedLikeType(decl).subst(subs);
1027+
auto loweredLikeType = IGM.getLoweredType(likeType->getCanonicalType());
1028+
auto likeTypeLayout = IGM.getTypeInfo(loweredLikeType)
1029+
.buildTypeLayoutEntry(IGM, loweredLikeType, useStructLayouts);
10291030

1030-
loweredLikeType = loweredLikeType.subst(IGM.getSILModule(), subs);
1031+
// If we're an array, use the ArrayLayoutEntry.
1032+
if (auto likeArray = rawLayout->getResolvedArrayLikeTypeAndCount(decl)) {
1033+
auto countType = likeArray->second.subst(subs)->getCanonicalType();
1034+
return IGM.typeLayoutCache.getOrCreateArrayEntry(likeTypeLayout,
1035+
loweredLikeType,
1036+
countType);
1037+
}
10311038

1032-
// Array like raw layouts are still handled correctly even though the
1033-
// type layout entry is only that of the like type.
1034-
return IGM.getTypeInfo(loweredLikeType)
1035-
.buildTypeLayoutEntry(IGM, loweredLikeType, useStructLayouts);
1039+
// Otherwise, this is just going to use the same layout entry as the
1040+
// like type.
1041+
return likeTypeLayout;
10361042
}
10371043

10381044
std::vector<TypeLayoutEntry *> fields;
@@ -1138,21 +1144,26 @@ namespace {
11381144
// raw layout because those are always fixed, so only dependent layouts
11391145
// will be non-fixed.
11401146

1141-
auto likeType = rawLayout->getResolvedLikeType(decl)->getCanonicalType();
1142-
SILType loweredLikeType = IGM.getLoweredType(likeType);
1143-
1144-
// The given struct type T that we're building may be in a generic
1145-
// environment that is different than that which was built our
1146-
// resolved rawLayout like type. Map our like type into the given
1147-
// environment.
1147+
// The given struct type T that we're building is fully concrete, but
1148+
// our like type is still in terms of the potential archetype of the
1149+
// type.
11481150
auto subs = T.getASTType()->getContextSubstitutionMap(decl);
1151+
auto likeType = rawLayout->getResolvedLikeType(decl).subst(subs);
1152+
auto loweredLikeType = IGM.getLoweredType(likeType->getCanonicalType());
1153+
auto likeTypeLayout = IGM.getTypeInfo(loweredLikeType)
1154+
.buildTypeLayoutEntry(IGM, loweredLikeType, useStructLayouts);
11491155

1150-
loweredLikeType = loweredLikeType.subst(IGM.getSILModule(), subs);
1156+
// If we're an array, use the ArrayLayoutEntry.
1157+
if (auto likeArray = rawLayout->getResolvedArrayLikeTypeAndCount(decl)) {
1158+
auto countType = likeArray->second.subst(subs)->getCanonicalType();
1159+
return IGM.typeLayoutCache.getOrCreateArrayEntry(likeTypeLayout,
1160+
loweredLikeType,
1161+
countType);
1162+
}
11511163

1152-
// Array like raw layouts are still handled correctly even though the
1153-
// type layout entry is only that of the like type.
1154-
return IGM.getTypeInfo(loweredLikeType)
1155-
.buildTypeLayoutEntry(IGM, loweredLikeType, useStructLayouts);
1164+
// Otherwise, this is just going to use the same layout entry as the
1165+
// like type.
1166+
return likeTypeLayout;
11561167
}
11571168

11581169
std::vector<TypeLayoutEntry *> fields;

lib/IRGen/IRGenFunction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,15 @@ class IRGenFunction {
453453
/// Emit a non-mergeable trap call, optionally followed by a terminator.
454454
void emitTrap(StringRef failureMessage, bool EmitUnreachable);
455455

456+
/// Given at least a src address to a list of elements, runs body over each
457+
/// element passing its address. An optional destination address can be
458+
/// provided which this will run over as well to perform things like
459+
/// 'initWithTake' from src to dest.
460+
void emitLoopOverElements(const TypeInfo &elementTypeInfo,
461+
SILType elementType, CanType countType,
462+
Address dest, Address src,
463+
std::function<void (Address dest, Address src)> body);
464+
456465
private:
457466
llvm::Instruction *AllocaIP;
458467
const SILDebugScope *DbgScope;

lib/IRGen/StructLayout.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ StructLayout::StructLayout(IRGenModule &IGM, std::optional<CanType> type,
129129
// substitute it out.
130130
auto subs = (*type)->getContextSubstitutionMap();
131131
auto loweredLikeType = IGM.getLoweredType(likeType->subst(subs));
132-
const TypeInfo &likeTypeInfo = IGM.getTypeInfo(loweredLikeType);
133-
auto likeFixedType = dyn_cast<FixedTypeInfo>(likeTypeInfo);
132+
auto &likeTypeInfo = IGM.getTypeInfo(loweredLikeType);
133+
auto likeFixedType = dyn_cast<FixedTypeInfo>(&likeTypeInfo);
134134

135135
// Substitute our count type if we have one.
136136
if (countType) {
@@ -142,11 +142,11 @@ StructLayout::StructLayout(IRGenModule &IGM, std::optional<CanType> type,
142142
// We can only fixup the type's layout when either this is a scalar and
143143
// the like type is a fixed type or if we're an array and both the like
144144
// type and count are statically known. Otherwise this is opaque.
145-
if (likeFixedType && (!countType || countType->is<IntegerType>())) {
145+
if (likeFixedType && (!countType || countType.value()->is<IntegerType>())) {
146146
// If we have a count type, then we're the array variant so
147147
// 'stride * count'. Otherwise we're a scalar which is just 'size'.
148148
if (countType) {
149-
auto integer = countType->getAs<IntegerType>();
149+
auto integer = countType.value()->getAs<IntegerType>();
150150

151151
if (integer->isNegative()) {
152152
MinimumSize = Size(0);

0 commit comments

Comments
 (0)