Skip to content

Commit 75ea939

Browse files
authored
Merge pull request #33465 from nate-chandler/generic-metadata-prespecialization-components/return-canonical-prespecializations-from-getGenericMetadata
2 parents f4ae514 + 409bc9d commit 75ea939

File tree

74 files changed

+64
-2146
lines changed

Some content is hidden

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

74 files changed

+64
-2146
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,21 +1164,10 @@ void IRGenerator::emitTypeMetadataRecords() {
11641164
}
11651165
}
11661166

1167-
void IRGenerator::
1168-
deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords(
1169-
IRGenModule &IGM, CanType typeWithCanonicalMetadataPrespecialization,
1170-
NominalTypeDecl &decl) {
1171-
// The accessor depends on canonical metadata records because they are
1172-
// returned from the function when the arguments match.
1173-
//
1174-
// TODO: Once work of looking through canonical prespecialized metadata has
1175-
// been moved into getGenericMetadata, this reemission will no longer
1176-
// be necessary.
1177-
auto *accessor = IGM.getAddrOfTypeMetadataAccessFunction(
1178-
decl.getDeclaredType()->getCanonicalType(), NotForDefinition);
1179-
accessor->deleteBody();
1180-
IGM.IRGen.noteUseOfMetadataAccessor(&decl);
1181-
1167+
static void
1168+
deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords(
1169+
IRGenModule &IGM, CanType typeWithCanonicalMetadataPrespecialization,
1170+
NominalTypeDecl &decl) {
11821171
// The type context descriptor depends on canonical metadata records because
11831172
// pointers to them are attached as trailing objects to it.
11841173
//

lib/IRGen/IRGenModule.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,6 @@ class IRGenerator {
436436
return MetadataPrespecializationsForGenericTypes.lookup(type);
437437
}
438438

439-
void
440-
deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords(
441-
IRGenModule &IGM, CanType typeWithCanonicalMetadataPrespecialization,
442-
NominalTypeDecl &decl);
443-
444439
void noteUseOfMetadataAccessor(NominalTypeDecl *decl) {
445440
if (LazyMetadataAccessors.count(decl) == 0) {
446441
LazyMetadataAccessors.insert(decl);

lib/IRGen/MetadataRequest.cpp

Lines changed: 0 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,176 +1986,6 @@ IRGenFunction::emitGenericTypeMetadataAccessFunctionCall(
19861986
return MetadataResponse::handle(*this, request, call);
19871987
}
19881988

1989-
static void emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction(
1990-
IRGenFunction &IGF, llvm::Value *request, NominalTypeDecl *nominal,
1991-
GenericArguments &genericArgs,
1992-
std::function<llvm::Value *(int)> valueAtIndex) {
1993-
auto &IGM = IGF.IGM;
1994-
auto specializations = IGM.IRGen.metadataPrespecializationsForType(nominal);
1995-
auto canonicalCount = llvm::count_if(specializations, [](auto pair) {
1996-
return pair.second == TypeMetadataCanonicality::Canonical;
1997-
});
1998-
1999-
if (canonicalCount > 0) {
2000-
SmallVector<llvm::BasicBlock *, 4> conditionBlocks;
2001-
for (size_t index = 0; index < specializations.size(); ++index) {
2002-
conditionBlocks.push_back(llvm::BasicBlock::Create(IGM.getLLVMContext()));
2003-
}
2004-
2005-
IGF.Builder.CreateBr(conditionBlocks[0]);
2006-
2007-
SmallVector<std::tuple<llvm::BasicBlock *, CanType,
2008-
std::function<llvm::Value *(llvm::Value *, CanType,
2009-
IRGenFunction &,
2010-
IRGenModule &)>>,
2011-
4>
2012-
specializationBlocks;
2013-
auto switchDestination = llvm::BasicBlock::Create(IGM.getLLVMContext());
2014-
unsigned long blockIndex = 0;
2015-
for (auto pair : specializations) {
2016-
if (pair.second != TypeMetadataCanonicality::Canonical) {
2017-
continue;
2018-
}
2019-
auto specialization = pair.first;
2020-
auto conditionBlock = conditionBlocks[blockIndex];
2021-
IGF.Builder.emitBlock(conditionBlock);
2022-
auto successorBlock = blockIndex < conditionBlocks.size() - 1
2023-
? conditionBlocks[blockIndex + 1]
2024-
: switchDestination;
2025-
auto specializationBlock = llvm::BasicBlock::Create(IGM.getLLVMContext());
2026-
auto substitutions = specialization->getContextSubstitutionMap(
2027-
IGM.getSwiftModule(), nominal);
2028-
2029-
llvm::Value *condition = llvm::ConstantInt::get(IGM.Int1Ty, 1);
2030-
auto nominal = specialization->getAnyNominal();
2031-
auto requirements = GenericTypeRequirements(IGM, nominal);
2032-
int requirementIndex = 0;
2033-
for (auto requirement : requirements.getRequirements()) {
2034-
auto parameter = requirement.TypeParameter;
2035-
auto argument = parameter.subst(substitutions);
2036-
if (requirement.Protocol) {
2037-
auto conformance = substitutions.lookupConformance(
2038-
requirement.TypeParameter->getCanonicalType(),
2039-
requirement.Protocol);
2040-
ProtocolConformance *concreteConformance = conformance.getConcrete();
2041-
auto argumentNominal = argument->getAnyNominal();
2042-
if (argumentNominal && argumentNominal->isGenericContext()) {
2043-
// TODO: Statically specialize the witness table pattern for t's
2044-
// conformance.
2045-
llvm_unreachable(
2046-
"Statically specializing metadata at generic types is "
2047-
"not supported.");
2048-
} else {
2049-
RootProtocolConformance *rootConformance =
2050-
concreteConformance->getRootConformance();
2051-
llvm::Value *expectedDescriptor =
2052-
IGM.getAddrOfProtocolConformanceDescriptor(rootConformance);
2053-
auto *witnessTable = valueAtIndex(requirementIndex);
2054-
auto *witnessBuffer =
2055-
IGF.Builder.CreateBitCast(witnessTable, IGM.Int8PtrPtrTy);
2056-
auto *uncastProvidedDescriptor =
2057-
IGF.Builder.CreateLoad(witnessBuffer, Alignment());
2058-
auto *providedDescriptor = IGF.Builder.CreateBitCast(
2059-
uncastProvidedDescriptor,
2060-
IGM.ProtocolConformanceDescriptorPtrTy);
2061-
2062-
// Auth the stored descriptor.
2063-
auto storedScheme =
2064-
IGM.getOptions().PointerAuth.ProtocolConformanceDescriptors;
2065-
if (storedScheme) {
2066-
auto authInfo = PointerAuthInfo::emit(
2067-
IGF, storedScheme, witnessTable,
2068-
PointerAuthEntity::Special::ProtocolConformanceDescriptor);
2069-
providedDescriptor =
2070-
emitPointerAuthAuth(IGF, providedDescriptor, authInfo);
2071-
}
2072-
2073-
// Sign the descriptors.
2074-
auto argScheme =
2075-
IGM.getOptions()
2076-
.PointerAuth.ProtocolConformanceDescriptorsAsArguments;
2077-
if (argScheme) {
2078-
auto authInfo = PointerAuthInfo::emit(
2079-
IGF, argScheme, nullptr,
2080-
PointerAuthEntity::Special::
2081-
ProtocolConformanceDescriptorAsArgument);
2082-
expectedDescriptor =
2083-
emitPointerAuthSign(IGF, expectedDescriptor, authInfo);
2084-
providedDescriptor =
2085-
emitPointerAuthSign(IGF, providedDescriptor, authInfo);
2086-
}
2087-
2088-
auto *call = IGF.Builder.CreateCall(
2089-
IGM.getCompareProtocolConformanceDescriptorsFn(),
2090-
{providedDescriptor, expectedDescriptor});
2091-
call->setDoesNotThrow();
2092-
call->setCallingConv(IGM.SwiftCC);
2093-
call->addAttribute(llvm::AttributeList::FunctionIndex,
2094-
llvm::Attribute::ReadNone);
2095-
condition = IGF.Builder.CreateAnd(condition, call);
2096-
}
2097-
} else {
2098-
llvm::Constant *addr =
2099-
IGM.getAddrOfTypeMetadata(argument->getCanonicalType());
2100-
auto addrInt = IGF.Builder.CreateBitCast(addr, IGM.Int8PtrTy);
2101-
condition = IGF.Builder.CreateAnd(
2102-
condition, IGF.Builder.CreateICmpEQ(
2103-
addrInt, valueAtIndex(requirementIndex)));
2104-
}
2105-
++requirementIndex;
2106-
}
2107-
IGF.Builder.CreateCondBr(condition, specializationBlock, successorBlock);
2108-
2109-
auto responseBuilder = [](llvm::Value *request, CanType specialization,
2110-
IRGenFunction &IGF, IRGenModule &IGM) {
2111-
auto nominal = specialization->getAnyNominal();
2112-
llvm::Value *specializedMetadata;
2113-
if (isa<ClassDecl>(nominal)) {
2114-
llvm::Function *accessor =
2115-
IGM
2116-
.getAddrOfCanonicalSpecializedGenericTypeMetadataAccessFunction(
2117-
specialization, NotForDefinition);
2118-
2119-
specializedMetadata =
2120-
IGF.emitGenericTypeMetadataAccessFunctionCall(
2121-
accessor, {}, DynamicMetadataRequest(request))
2122-
.getMetadata();
2123-
} else {
2124-
specializedMetadata = IGM.getAddrOfTypeMetadata(specialization);
2125-
}
2126-
// Construct a MetadataResponse. It has three fields in the following
2127-
// order:
2128-
// - const Metadata *Metadata;
2129-
// - MetadataState (i32) StaticState;
2130-
llvm::Value *response =
2131-
llvm::UndefValue::get(IGM.TypeMetadataResponseTy);
2132-
response = IGF.Builder.CreateInsertValue(
2133-
response, specializedMetadata, 0,
2134-
"insert metadata address into response");
2135-
auto state = MetadataResponse::getCompletedState(IGM);
2136-
response = IGF.Builder.CreateInsertValue(
2137-
response, state, 1, "insert metadata state into response");
2138-
return response;
2139-
};
2140-
specializationBlocks.push_back(std::make_tuple(
2141-
specializationBlock, specialization, responseBuilder));
2142-
++blockIndex;
2143-
}
2144-
2145-
for (auto tuple : specializationBlocks) {
2146-
llvm::BasicBlock *block;
2147-
CanType type;
2148-
std::function<llvm::Value *(llvm::Value *, CanType, IRGenFunction &,
2149-
IRGenModule &)>
2150-
builder;
2151-
std::tie(block, type, builder) = tuple;
2152-
IGF.Builder.emitBlock(block);
2153-
IGF.Builder.CreateRet(builder(request, type, IGF, IGM));
2154-
}
2155-
IGF.Builder.emitBlock(switchDestination);
2156-
}
2157-
}
2158-
21591989
MetadataResponse irgen::emitGenericTypeMetadataAccessFunction(
21601990
IRGenFunction &IGF, Explosion &params, NominalTypeDecl *nominal,
21611991
GenericArguments &genericArgs) {
@@ -2186,20 +2016,6 @@ MetadataResponse irgen::emitGenericTypeMetadataAccessFunction(
21862016
llvm::Value *arguments =
21872017
IGF.Builder.CreateBitCast(argsBuffer.getAddress(), IGM.Int8PtrTy);
21882018

2189-
llvm::Value *argumentsBuffer =
2190-
IGF.Builder.CreateBitCast(argsBuffer.getAddress(), IGM.Int8PtrPtrTy);
2191-
2192-
emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction(
2193-
IGF, request, nominal, genericArgs, [&](int index) {
2194-
llvm::Value *indexValue = llvm::ConstantInt::get(IGM.Int64Ty, index);
2195-
llvm::Value *elementPointer =
2196-
IGF.Builder.CreateGEP(argumentsBuffer, indexValue);
2197-
llvm::LoadInst *retval = IGF.Builder.CreateLoad(
2198-
elementPointer, Alignment(),
2199-
llvm::formatv("load argument at index {0} from buffer", index));
2200-
return retval;
2201-
});
2202-
22032019
// Make the call.
22042020
auto call = IGF.Builder.CreateCall(IGM.getGetGenericMetadataFn(),
22052021
{request, arguments, descriptor});
@@ -2278,12 +2094,6 @@ MetadataResponse irgen::emitGenericTypeMetadataAccessFunction(
22782094
? IGF.Builder.CreateBitCast(params.claimNext(), IGM.Int8PtrTy)
22792095
: llvm::UndefValue::get(IGM.Int8PtrTy);
22802096

2281-
std::array<llvm::Value *, 3> argValues = {arg0, arg1, arg2};
2282-
2283-
emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction(
2284-
IGF, request, nominal, genericArgs,
2285-
[&](int index) { return argValues[index]; });
2286-
22872097
auto call = IGF.Builder.CreateCall(thunkFn,
22882098
{request, arg0, arg1, arg2, descriptor});
22892099
call->setDoesNotAccessMemory();

stdlib/public/runtime/Metadata.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,12 +756,53 @@ MetadataResponse swift::swift_getCanonicalSpecializedMetadata(
756756
return result.second;
757757
}
758758

759+
// Look into the canonical prespecialized metadata attached to the type
760+
// descriptor and return matching records, if any.
761+
static Metadata *
762+
findCanonicalSpecializedMetadata(MetadataRequest request,
763+
const void *const *arguments,
764+
const TypeContextDescriptor *description) {
765+
auto &cache = getCache(*description);
766+
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
767+
arguments);
768+
auto prespecializedMetadatas =
769+
description->getCanonicicalMetadataPrespecializations();
770+
int index = 0;
771+
for (auto &prespecializedMetadataPtr : prespecializedMetadatas) {
772+
Metadata *prespecializationMetadata = prespecializedMetadataPtr.get();
773+
const void *const *prespecializationArguments =
774+
reinterpret_cast<const void *const *>(
775+
prespecializationMetadata->getGenericArgs());
776+
auto prespecializationKey =
777+
MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
778+
prespecializationArguments);
779+
if (key == prespecializationKey) {
780+
if (auto *classDescription = dyn_cast<ClassDescriptor>(description)) {
781+
auto canonicalMetadataAccessors =
782+
classDescription->getCanonicalMetadataPrespecializationAccessors();
783+
auto &canonicalMetadataAccessorPtr = canonicalMetadataAccessors[index];
784+
auto *canonicalMetadataAccessor = canonicalMetadataAccessorPtr.get();
785+
auto response = canonicalMetadataAccessor(request);
786+
return const_cast<Metadata *>(response.Value);
787+
} else {
788+
return prespecializationMetadata;
789+
}
790+
}
791+
++index;
792+
}
793+
return nullptr;
794+
}
795+
759796
/// The primary entrypoint.
760797
MetadataResponse
761798
swift::swift_getGenericMetadata(MetadataRequest request,
762799
const void * const *arguments,
763800
const TypeContextDescriptor *description) {
764801
description = swift_auth_data_non_address(description, SpecialPointerAuthDiscriminators::TypeDescriptor);
802+
if (auto *prespecialization =
803+
findCanonicalSpecializedMetadata(request, arguments, description)) {
804+
return {prespecialization, MetadataState::Complete};
805+
}
765806
auto &cache = getCache(*description);
766807
assert(description->getFullGenericContextHeader().Base.NumKeyArguments ==
767808
cache.NumKeyParameters + cache.NumWitnessTables);

test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_distinct_generic_class.swift

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -238,90 +238,6 @@ doit()
238238
// CHECK: entry:
239239
// CHECK: [[ERASED_ARGUMENT1:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT1_METADATA]] to i8*
240240
// CHECK: [[ERASED_ARGUMENT2:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT2_METADATA]] to i8*
241-
// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]]
242-
// CHECK: [[TYPE_COMPARISON_LABEL]]:
243-
// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast (
244-
// : %swift.type* getelementptr inbounds (
245-
// : %swift.full_heapmetadata,
246-
// : %swift.full_heapmetadata* bitcast (
247-
// : <{
248-
// : void (
249-
// : %T4main9Argument1[[UNIQUE_ID_1]]LLC*
250-
// : )*,
251-
// : i8**,
252-
// : [[INT]],
253-
// : %objc_class*,
254-
// : %swift.opaque*,
255-
// : %swift.opaque*,
256-
// : [[INT]],
257-
// : i32,
258-
// : i32,
259-
// : i32,
260-
// : i16,
261-
// : i16,
262-
// : i32,
263-
// : i32,
264-
// : %swift.type_descriptor*,
265-
// : i8*,
266-
// : %swift.type*,
267-
// : [[INT]],
268-
// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* (
269-
// : %swift.opaque*,
270-
// : %swift.type*
271-
// : )*
272-
// : }>*
273-
// CHECK-SAME: @"$s4main9Argument1[[UNIQUE_ID_1]]LLCySiGMf"
274-
// : to %swift.full_heapmetadata*
275-
// : ),
276-
// : i32 0,
277-
// : i32 2
278-
// : ) to i8*
279-
// CHECK-SAME: ), [[ERASED_ARGUMENT1]]
280-
// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]]
281-
// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast (
282-
// : %swift.type* getelementptr inbounds (
283-
// : %swift.full_heapmetadata,
284-
// : %swift.full_heapmetadata* bitcast (
285-
// : <{
286-
// : void (
287-
// : %T4main9Argument2[[UNIQUE_ID_1]]LLC*
288-
// : )*,
289-
// : i8**,
290-
// : [[INT]],
291-
// : %objc_class*,
292-
// : %swift.opaque*,
293-
// : %swift.opaque*,
294-
// : [[INT]],
295-
// : i32,
296-
// : i32,
297-
// : i32,
298-
// : i16,
299-
// : i16,
300-
// : i32,
301-
// : i32,
302-
// : %swift.type_descriptor*,
303-
// : i8*,
304-
// : %swift.type*,
305-
// : [[INT]],
306-
// : %T4main9Argument2[[UNIQUE_ID_1]]LLC* (
307-
// : %swift.opaque*,
308-
// : %swift.type*
309-
// : )*
310-
// CHECK-SAME: }>* @"$s4main9Argument2[[UNIQUE_ID_1]]LLCySSGMf" to %swift.full_heapmetadata*
311-
// : ),
312-
// : i32 0,
313-
// : i32 2
314-
// : ) to i8*
315-
// : ), [[ERASED_ARGUMENT2]]
316-
// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1]], [[EQUAL_TYPE_2]]
317-
// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]]
318-
// CHECK: [[EXIT_PRESPECIALIZED]]:
319-
// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCyAA9Argument1ACLLCySiGAA9Argument2ACLLCySSGGMb"([[INT]] [[METADATA_REQUEST]])
320-
// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0
321-
// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0
322-
// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1
323-
// CHECK: ret %swift.metadata_response [[RESULT_METADATA]]
324-
// CHECK: [[EXIT_NORMAL]]:
325241
// CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata(
326242
// CHECK: [[INT]] [[METADATA_REQUEST]],
327243
// CHECK: i8* [[ERASED_ARGUMENT1]],

0 commit comments

Comments
 (0)