Skip to content

Commit 66ed09e

Browse files
committed
Runtime: Variadic generic type fixes
1 parent 13020c4 commit 66ed09e

File tree

4 files changed

+168
-76
lines changed

4 files changed

+168
-76
lines changed

include/swift/ABI/GenericContext.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,25 @@ struct TargetGenericContextDescriptorHeader {
5555
uint16_t NumRequirements;
5656

5757
/// The size of the "key" area of the argument layout, in words.
58-
/// Key arguments include generic parameters and conformance
59-
/// requirements which are part of the identity of the context.
58+
/// Key arguments include shape classes, generic parameters and
59+
/// conformance requirements which are part of the identity of
60+
/// the context.
6061
///
61-
/// The key area of the argument layout consists of a sequence
62-
/// of type metadata pointers (in the same order as the parameter
63-
/// descriptors, for those parameters which satisfy hasKeyArgument())
64-
/// followed by a sequence of witness table pointers (in the same
65-
/// order as the requirements, for those requirements which satisfy
66-
/// hasKeyArgument()).
62+
/// The key area of the argument layout consists of:
63+
///
64+
/// - a sequence of pack lengths, in the same order as the parameter
65+
/// descriptors which satisfy getKind() == GenericParamKind::TypePack
66+
/// and hasKeyArgument();
67+
///
68+
/// - a sequence of metadata or metadata pack pointers, in the same
69+
/// order as the parameter descriptors which satisfy hasKeyArgument();
70+
///
71+
/// - a sequence of witness table or witness table pack pointers, in the
72+
/// same order as the requirement descriptors which satisfy
73+
/// hasKeyArgument().
74+
///
75+
/// The elements above which are packs are precisely those appearing
76+
/// in the sequence of trailing GenericPackShapeDescriptors.
6777
uint16_t NumKeyArguments;
6878

6979
/// Originally this was the size of the "extra" area of the argument

include/swift/Runtime/Metadata.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ bool swift_compareProtocolConformanceDescriptors(
457457
/// bit set to true.
458458
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
459459
const Metadata * const *
460-
swift_allocateMetadataPack(const Metadata * const *ptr, unsigned count);
460+
swift_allocateMetadataPack(const Metadata * const *ptr, size_t count);
461461

462462
/// Allocate a witness table pack on the heap, unless this pack is already on
463463
/// the heap.
@@ -472,7 +472,7 @@ swift_allocateMetadataPack(const Metadata * const *ptr, unsigned count);
472472
/// significant bit set to true.
473473
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
474474
const WitnessTable * const *
475-
swift_allocateWitnessTablePack(const WitnessTable * const *ptr, unsigned count);
475+
swift_allocateWitnessTablePack(const WitnessTable * const *ptr, size_t count);
476476

477477
/// Fetch a uniqued metadata for a function type.
478478
SWIFT_RUNTIME_EXPORT

stdlib/public/runtime/Metadata.cpp

Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,40 @@ Metadata *TargetSingletonMetadataInitialization<InProcess>::allocate(
145145
static void installGenericArguments(Metadata *metadata,
146146
const TypeContextDescriptor *description,
147147
const void *arguments) {
148-
auto &generics = description->getFullGenericContextHeader();
148+
const auto &genericContext = *description->getGenericContext();
149+
const auto &header = genericContext.getGenericContextHeader();
149150

150-
// FIXME: variadic-parameter-packs
151-
memcpy(reinterpret_cast<const void **>(metadata)
152-
+ description->getGenericArgumentOffset(),
151+
auto dst = (reinterpret_cast<const void **>(metadata) +
152+
description->getGenericArgumentOffset());
153+
memcpy(dst,
153154
reinterpret_cast<const void * const *>(arguments),
154-
generics.Base.getNumArguments() * sizeof(void*));
155+
header.NumKeyArguments * sizeof(void *));
156+
157+
// If we don't have any pack arguments, there is nothing more to do.
158+
auto packShapeHeader = genericContext.getGenericPackShapeHeader();
159+
if (packShapeHeader.NumPacks == 0)
160+
return;
161+
162+
// Heap-allocate all installed metadata and witness table packs.
163+
for (auto pack : genericContext.getGenericPackShapeDescriptors()) {
164+
assert(pack.ShapeClass < packShapeHeader.NumShapeClasses);
165+
166+
size_t count = reinterpret_cast<size_t>(dst[pack.ShapeClass]);
167+
168+
switch (pack.Kind) {
169+
case GenericPackKind::Metadata:
170+
dst[pack.Index] = swift_allocateMetadataPack(
171+
reinterpret_cast<const Metadata * const *>(dst[pack.Index]),
172+
count);
173+
break;
174+
175+
case GenericPackKind::WitnessTable:
176+
dst[pack.Index] = swift_allocateWitnessTablePack(
177+
reinterpret_cast<const WitnessTable * const *>(dst[pack.Index]),
178+
count);
179+
break;
180+
}
181+
}
155182
}
156183

157184
#if SWIFT_OBJC_INTEROP
@@ -1154,7 +1181,7 @@ namespace {
11541181

11551182
class MetadataPackCacheEntry {
11561183
public:
1157-
unsigned Count;
1184+
size_t Count;
11581185

11591186
const Metadata * const * getElements() const {
11601187
return reinterpret_cast<const Metadata * const *>(this + 1);
@@ -1166,20 +1193,20 @@ class MetadataPackCacheEntry {
11661193

11671194
struct Key {
11681195
const Metadata *const *Data;
1169-
const unsigned Count;
1196+
const size_t Count;
11701197

1171-
unsigned getCount() const {
1198+
size_t getCount() const {
11721199
return Count;
11731200
}
11741201

1175-
const Metadata *getElement(unsigned index) const {
1202+
const Metadata *getElement(size_t index) const {
11761203
assert(index < Count);
11771204
return Data[index];
11781205
}
11791206

11801207
friend llvm::hash_code hash_value(const Key &key) {
11811208
llvm::hash_code hash = 0;
1182-
for (unsigned i = 0; i != key.getCount(); ++i)
1209+
for (size_t i = 0; i != key.getCount(); ++i)
11831210
hash = llvm::hash_combine(hash, key.getElement(i));
11841211
return hash;
11851212
}
@@ -1202,7 +1229,10 @@ class MetadataPackCacheEntry {
12021229
}
12031230

12041231
friend llvm::hash_code hash_value(const MetadataPackCacheEntry &value) {
1205-
return hash_value(value.getElements());
1232+
llvm::hash_code hash = 0;
1233+
for (size_t i = 0; i != value.Count; ++i)
1234+
hash = llvm::hash_combine(hash, value.getElements()[i]);
1235+
return hash;
12061236
}
12071237

12081238
static size_t getExtraAllocationSize(const Key &key) {
@@ -1219,9 +1249,9 @@ class MetadataPackCacheEntry {
12191249
};
12201250

12211251
MetadataPackCacheEntry::MetadataPackCacheEntry(const Key &key) {
1222-
auto count = key.getCount();
1252+
Count = key.getCount();
12231253

1224-
for (unsigned i = 0; i < count; ++i)
1254+
for (unsigned i = 0; i < Count; ++i)
12251255
getElements()[i] = key.getElement(i);
12261256
}
12271257

@@ -1232,7 +1262,7 @@ static SimpleGlobalCache<MetadataPackCacheEntry, MetadataPackTag> MetadataPacks;
12321262

12331263
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
12341264
const Metadata * const *
1235-
swift_allocateMetadataPack(const Metadata * const *ptr, unsigned count) {
1265+
swift_allocateMetadataPack(const Metadata * const *ptr, size_t count) {
12361266
if (MetadataPackPointer(reinterpret_cast<uintptr_t>(ptr)).getLifetime()
12371267
== PackLifetime::OnHeap)
12381268
return ptr;
@@ -1245,7 +1275,7 @@ swift_allocateMetadataPack(const Metadata * const *ptr, unsigned count) {
12451275

12461276
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
12471277
const WitnessTable * const *
1248-
swift_allocateWitnessTablePack(const WitnessTable * const *ptr, unsigned count) {
1278+
swift_allocateWitnessTablePack(const WitnessTable * const *ptr, size_t count) {
12491279
if (WitnessTablePackPointer(reinterpret_cast<uintptr_t>(ptr)).getLifetime()
12501280
== PackLifetime::OnHeap)
12511281
return ptr;
@@ -6513,13 +6543,54 @@ static bool findAnyTransitiveMetadata(const Metadata *type, T &&predicate) {
65136543

65146544
// Generic types require their type arguments to be transitively complete.
65156545
if (description->isGeneric()) {
6546+
auto *genericContext = description->getGenericContext();
6547+
65166548
auto keyArguments = description->getGenericArguments(type);
6517-
for (auto &param : description->getGenericParams()) {
6518-
if (param.hasKeyArgument()) {
6519-
if (predicate(*keyArguments++))
6549+
6550+
// The generic argument area begins with a pack count for each
6551+
// shape class; skip them first.
6552+
auto header = genericContext->getGenericPackShapeHeader();
6553+
unsigned paramIdx = header.NumShapeClasses;
6554+
6555+
auto packs = genericContext->getGenericPackShapeDescriptors();
6556+
unsigned packIdx = 0;
6557+
for (auto &param : genericContext->getGenericParams()) {
6558+
// Ignore parameters that don't have a key argument.
6559+
if (!param.hasKeyArgument())
6560+
continue;
6561+
6562+
switch (param.getKind()) {
6563+
case GenericParamKind::Type:
6564+
if (predicate(keyArguments[paramIdx]))
65206565
return true;
6566+
6567+
break;
6568+
6569+
case GenericParamKind::TypePack: {
6570+
assert(packIdx < header.NumPacks);
6571+
assert(packs[packIdx].Kind == GenericPackKind::Metadata);
6572+
assert(packs[packIdx].Index == paramIdx);
6573+
assert(packs[packIdx].ShapeClass < header.NumShapeClasses);
6574+
6575+
MetadataPackPointer pack(keyArguments[paramIdx]);
6576+
assert(pack.getLifetime() == PackLifetime::OnHeap);
6577+
6578+
uintptr_t count = reinterpret_cast<uintptr_t>(
6579+
keyArguments[packs[packIdx].ShapeClass]);
6580+
for (uintptr_t j = 0; j < count; ++j) {
6581+
if (predicate(pack.getElements()[j]))
6582+
return true;
6583+
}
6584+
6585+
++packIdx;
6586+
break;
65216587
}
6522-
// Ignore parameters that don't have a key argument.
6588+
6589+
default:
6590+
llvm_unreachable("Unsupported generic parameter kind");
6591+
}
6592+
6593+
++paramIdx;
65236594
}
65246595
}
65256596

0 commit comments

Comments
 (0)