Skip to content

Commit 0d324d2

Browse files
committed
Add swift_getTypeByMangledNameInContextInMetadataState such that we can
use getTypeByMangledName when abstract metadata state is requested This can significantly reduce the code size of apps constructing deeply nested types with conditional conformances. Requires a new runtime. rdar://57157619
1 parent d9d6457 commit 0d324d2

File tree

8 files changed

+143
-25
lines changed

8 files changed

+143
-25
lines changed

include/swift/AST/ASTContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,11 @@ class ASTContext final {
577577
/// compiler for the target platform.
578578
AvailabilityContext getSwift51Availability();
579579

580+
/// Get the runtime availability of
581+
/// swift_getTypeByMangledNameInContextInMetadataState.
582+
AvailabilityContext getTypesInAbstractMetadataStateAvailability();
583+
584+
580585
//===--------------------------------------------------------------------===//
581586
// Diagnostics Helper functions
582587
//===--------------------------------------------------------------------===//

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,20 @@ FUNCTION(GetTypeByMangledNameInContext, swift_getTypeByMangledNameInContext,
14091409
ARGS(Int8PtrTy, SizeTy, TypeContextDescriptorPtrTy, Int8PtrPtrTy),
14101410
ATTRS(NoUnwind, ArgMemOnly))
14111411

1412+
// const Metadata *swift_getTypeByMangledNameInContextInMetadataState(
1413+
// size_t metadataState,
1414+
// const char *typeNameStart,
1415+
// size_t typeNameLength,
1416+
// const TargetContextDescriptor<InProcess> *context,
1417+
// const void * const *genericArgs)
1418+
FUNCTION(GetTypeByMangledNameInContextInMetadataState,
1419+
swift_getTypeByMangledNameInContextInMetadataState, SwiftCC,
1420+
GetTypesInAbstractMetadataStateAvailability,
1421+
RETURNS(TypeMetadataPtrTy),
1422+
ARGS(SizeTy, Int8PtrTy, SizeTy, TypeContextDescriptorPtrTy,
1423+
Int8PtrPtrTy),
1424+
ATTRS(NoUnwind, ArgMemOnly))
1425+
14121426
#undef RETURNS
14131427
#undef ARGS
14141428
#undef ATTRS

lib/AST/Availability.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,17 @@ AvailabilityContext ASTContext::getSwift51Availability() {
237237
return AvailabilityContext::alwaysAvailable();
238238
}
239239
}
240+
241+
AvailabilityContext ASTContext::getTypesInAbstractMetadataStateAvailability() {
242+
auto target = LangOpts.Target;
243+
244+
if (target.isMacOSX() ) {
245+
return AvailabilityContext(
246+
VersionRange::allGTE(llvm::VersionTuple(10, 99, 0)));
247+
} else if (target.isiOS() || target.isWatchOS()) {
248+
return AvailabilityContext(
249+
VersionRange::allGTE(llvm::VersionTuple(9999, 0, 0)));
250+
} else {
251+
return AvailabilityContext::alwaysAvailable();
252+
}
253+
}

lib/IRGen/IRGenModule.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,16 @@ namespace RuntimeConstants {
564564
return RuntimeAvailability::AlwaysAvailable;
565565
}
566566

567+
RuntimeAvailability
568+
GetTypesInAbstractMetadataStateAvailability(ASTContext &context) {
569+
auto featureAvailability =
570+
context.getTypesInAbstractMetadataStateAvailability();
571+
if (!isDeploymentAvailabilityContainedIn(context, featureAvailability)) {
572+
return RuntimeAvailability::ConditionallyAvailable;
573+
}
574+
return RuntimeAvailability::AlwaysAvailable;
575+
}
576+
567577
RuntimeAvailability DynamicReplacementAvailability(ASTContext &Context) {
568578
auto featureAvailability = Context.getSwift51Availability();
569579
if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) {

lib/IRGen/MetadataRequest.cpp

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,16 +2156,29 @@ static bool shouldAccessByMangledName(IRGenModule &IGM, CanType type) {
21562156

21572157
}
21582158

2159+
static bool canIssueIncompleteMetadataRequests(IRGenModule &IGM) {
2160+
// We can only answer blocking complete metadata requests with the <=5.1
2161+
// runtime ABI entry points.
2162+
auto &context = IGM.getSwiftModule()->getASTContext();
2163+
auto deploymentAvailability =
2164+
AvailabilityContext::forDeploymentTarget(context);
2165+
return deploymentAvailability.isContainedIn(
2166+
context.getTypesInAbstractMetadataStateAvailability());
2167+
}
2168+
21592169
/// Emit a call to a type metadata accessor using a mangled name.
21602170
static MetadataResponse
21612171
emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type,
21622172
DynamicMetadataRequest request) {
2163-
// TODO: We can only answer blocking complete metadata requests with the
2164-
// <=5.1 runtime ABI entry points.
2165-
assert(request.isStaticallyBlockingComplete()
2166-
&& "can only form complete metadata by mangled name");
2167-
21682173
auto &IGM = IGF.IGM;
2174+
2175+
// We can only answer blocking complete metadata requests with the <=5.1
2176+
// runtime ABI entry points.
2177+
assert((request.isStaticallyBlockingComplete() ||
2178+
(request.isStaticallyAbstract() &&
2179+
canIssueIncompleteMetadataRequests(IGM))) &&
2180+
"can only form complete metadata by mangled name");
2181+
21692182
llvm::Constant *mangledString;
21702183
unsigned mangledStringSize;
21712184
std::tie(mangledString, mangledStringSize) =
@@ -2198,11 +2211,15 @@ emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type,
21982211
}
21992212

22002213
// Get or create a shared helper function to do the instantiation.
2214+
auto instantiationFnName =
2215+
request.isStaticallyAbstract()
2216+
? "__swift_instantiateConcreteTypeFromMangledNameAbstract"
2217+
: "__swift_instantiateConcreteTypeFromMangledName";
22012218
auto instantiationFn = cast<llvm::Function>(
2202-
IGM.getModule()
2203-
->getOrInsertFunction("__swift_instantiateConcreteTypeFromMangledName",
2204-
IGF.IGM.TypeMetadataPtrTy, cache->getType())
2205-
.getCallee());
2219+
IGM.getModule()
2220+
->getOrInsertFunction(instantiationFnName, IGF.IGM.TypeMetadataPtrTy,
2221+
cache->getType())
2222+
.getCallee());
22062223
if (instantiationFn->empty()) {
22072224
ApplyIRLinkage(IRLinkage::InternalLinkOnceODR)
22082225
.to(instantiationFn);
@@ -2212,7 +2229,7 @@ emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type,
22122229
llvm::Attribute::NoInline);
22132230
IGM.setHasFramePointer(instantiationFn, false);
22142231

2215-
[&IGM, instantiationFn]{
2232+
[&IGM, instantiationFn, request]{
22162233
IRGenFunction subIGF(IGM, instantiationFn);
22172234

22182235
auto params = subIGF.collectParameters();
@@ -2279,15 +2296,26 @@ emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type,
22792296
auto stringAddr = subIGF.Builder.CreateAdd(stringAddrBase,
22802297
stringAddrOffset);
22812298
stringAddr = subIGF.Builder.CreateIntToPtr(stringAddr, IGM.Int8PtrTy);
2282-
2283-
auto call =
2284-
subIGF.Builder.CreateCall(IGM.getGetTypeByMangledNameInContextFn(),
2285-
{stringAddr,
2286-
size,
2287-
// TODO: Use mangled name lookup in generic
2288-
// contexts?
2289-
llvm::ConstantPointerNull::get(IGM.TypeContextDescriptorPtrTy),
2290-
llvm::ConstantPointerNull::get(IGM.Int8PtrPtrTy)});
2299+
2300+
llvm::CallInst *call;
2301+
if (request.isStaticallyAbstract()) {
2302+
call = subIGF.Builder.CreateCall(
2303+
IGM.getGetTypeByMangledNameInContextInMetadataStateFn(),
2304+
{llvm::ConstantInt::get(IGM.SizeTy, (size_t)MetadataState::Abstract),
2305+
stringAddr, size,
2306+
// TODO: Use mangled name lookup in generic
2307+
// contexts?
2308+
llvm::ConstantPointerNull::get(IGM.TypeContextDescriptorPtrTy),
2309+
llvm::ConstantPointerNull::get(IGM.Int8PtrPtrTy)});
2310+
} else {
2311+
call = subIGF.Builder.CreateCall(
2312+
IGM.getGetTypeByMangledNameInContextFn(),
2313+
{stringAddr, size,
2314+
// TODO: Use mangled name lookup in generic
2315+
// contexts?
2316+
llvm::ConstantPointerNull::get(IGM.TypeContextDescriptorPtrTy),
2317+
llvm::ConstantPointerNull::get(IGM.Int8PtrPtrTy)});
2318+
}
22912319
call->setDoesNotThrow();
22922320
call->setDoesNotAccessMemory();
22932321
call->setCallingConv(IGM.SwiftCC);
@@ -2339,14 +2367,13 @@ emitCallToTypeMetadataAccessFunction(IRGenFunction &IGF, CanType type,
23392367
// single access by mangled name instead, if we're asking for complete
23402368
// metadata.
23412369
//
2342-
// TODO: The getTypeByMangledNameInContext entry point in Swift <=5.1 can
2343-
// only answer requests for complete metadata. We could introduce new
2344-
// entry points that could answer all metadata requests.
2345-
if (request.isStaticallyBlockingComplete()
2346-
&& shouldAccessByMangledName(IGF.IGM, type)) {
2370+
if ((request.isStaticallyBlockingComplete() ||
2371+
(request.isStaticallyAbstract() &&
2372+
canIssueIncompleteMetadataRequests(IGF.IGM))) &&
2373+
shouldAccessByMangledName(IGF.IGM, type)) {
23472374
return emitMetadataAccessByMangledName(IGF, type, request);
23482375
}
2349-
2376+
23502377
llvm::Constant *accessor =
23512378
getOrCreateTypeMetadataAccessFunction(IGF.IGM, type);
23522379
llvm::CallInst *call = IGF.Builder.CreateCall(accessor, { request.get(IGF) });

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,26 @@ swift_getTypeByMangledNameInContext(
17081708
}).getMetadata();
17091709
}
17101710

1711+
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
1712+
const Metadata * _Nullable
1713+
swift_getTypeByMangledNameInContextInMetadataState(
1714+
size_t metadataState,
1715+
const char *typeNameStart,
1716+
size_t typeNameLength,
1717+
const TargetContextDescriptor<InProcess> *context,
1718+
const void * const *genericArgs) {
1719+
llvm::StringRef typeName(typeNameStart, typeNameLength);
1720+
SubstGenericParametersFromMetadata substitutions(context, genericArgs);
1721+
return swift_getTypeByMangledName((MetadataState)metadataState, typeName,
1722+
genericArgs,
1723+
[&substitutions](unsigned depth, unsigned index) {
1724+
return substitutions.getMetadata(depth, index);
1725+
},
1726+
[&substitutions](const Metadata *type, unsigned index) {
1727+
return substitutions.getWitnessTable(type, index);
1728+
}).getMetadata();
1729+
}
1730+
17111731
/// Demangle a mangled name, but don't allow symbolic references.
17121732
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
17131733
const Metadata *_Nullable
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.99 -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift --check-prefix=TYPEBYNAME
2+
3+
// Too many pointer-sized integers in the IR
4+
// REQUIRES: PTRSIZE=64
5+
// REQUIRES: OS=macosx
6+

test/Inputs/conditional_conformance_basic_conformances.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,28 @@ public func single_concrete() {
100100
// CHECK-NEXT: ret i8** [[T0]]
101101
// CHECK-NEXT: }
102102

103+
// TYPEBYNAME-LABEL: define linkonce_odr hidden i8** @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWl"()
104+
// TYPEBYNAME-NEXT: entry:
105+
// TYPEBYNAME-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
106+
// TYPEBYNAME-NEXT: [[CACHE:%.*]] = load i8**, i8*** @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL", align 8
107+
// TYPEBYNAME-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
108+
// TYPEBYNAME-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
109+
110+
// TYPEBYNAME: cacheIsNull:
111+
// TYPEBYNAME-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMD")
112+
// TYPEBYNAME-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
113+
// TYPEBYNAME-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
114+
// TYPEBYNAME-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s42conditional_conformance_basic_conformances4IsP2VAA0F0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
115+
116+
// TYPEBYNAME-NEXT: [[Single_P1:%.*]] = call i8** @swift_getWitnessTable
117+
// TYPEBYNAME-NEXT: store atomic i8** [[Single_P1]], i8*** @"$s42conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL" release, align 8
118+
// TYPEBYNAME-NEXT: br label %cont
119+
120+
// TYPEBYNAME: cont:
121+
// TYPEBYNAME-NEXT: [[T0:%.*]] = phi i8** [ [[CACHE]], %entry ], [ [[Single_P1]], %cacheIsNull ]
122+
// TYPEBYNAME-NEXT: ret i8** [[T0]]
123+
// TYPEBYNAME-NEXT: }
124+
103125

104126
public struct Double<B, C> {}
105127
extension Double: P1 where B: P2, C: P3 {

0 commit comments

Comments
 (0)