Skip to content

Commit 7b8bbcd

Browse files
committed
[Keypaths] Start using mangled type names for non-dependent types.
When a type in keypath metadata is non-dependent, use a mangled type name rather than a symbolic reference to an accessor function. Part of rdar://problem/38038799.
1 parent b192ced commit 7b8bbcd

File tree

4 files changed

+77
-35
lines changed

4 files changed

+77
-35
lines changed

lib/IRGen/GenKeyPath.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,8 +706,14 @@ emitMetadataGeneratorForKeyPath(IRGenModule &IGM,
706706
CanType type,
707707
GenericEnvironment *genericEnv,
708708
ArrayRef<GenericRequirement> requirements) {
709-
// TODO: Use a mangled name when we can.
709+
// If we have a non-dependent type, use a normal mangled type name.
710+
if (!type->hasTypeParameter()) {
711+
auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata);
712+
auto bitConstant = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
713+
return llvm::ConstantExpr::getGetElementPtr(nullptr, constant, bitConstant);
714+
}
710715

716+
// Otherwise, create an accessor.
711717
CanGenericSignature genericSig;
712718
if (genericEnv)
713719
genericSig = genericEnv->getGenericSignature()->getCanonicalSignature();

lib/IRGen/MetadataRequest.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,19 @@ llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef(
222222
StringRef symbolName,
223223
bool shouldSetLowBit,
224224
llvm::function_ref<ConstantInitFuture (ConstantInitBuilder &)> body) {
225+
// Call this to form the return value.
226+
auto returnValue = [&](llvm::Constant *addr) {
227+
if (!shouldSetLowBit)
228+
return addr;
229+
230+
auto bitConstant = llvm::ConstantInt::get(IntPtrTy, 1);
231+
return llvm::ConstantExpr::getGetElementPtr(nullptr, addr, bitConstant);
232+
};
233+
225234
// Check whether we already have an entry with this name.
226235
auto &entry = StringsForTypeRef[symbolName];
227236
if (entry.second) {
228-
return entry.second;
237+
return returnValue(entry.second);
229238
}
230239

231240
// Construct the initializer.
@@ -250,16 +259,9 @@ llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef(
250259

251260
// Drill down to the i8* at the beginning of the constant.
252261
auto addr = llvm::ConstantExpr::getBitCast(var, Int8PtrTy);
253-
254-
// If requested, set the low bit.
255-
if (shouldSetLowBit) {
256-
auto bitConstant = llvm::ConstantInt::get(IntPtrTy, 1);
257-
addr = llvm::ConstantExpr::getGetElementPtr(nullptr, addr, bitConstant);
258-
}
259-
260262
StringsForTypeRef[symbolName] = { var, addr };
261263

262-
return addr;
264+
return returnValue(addr);
263265
}
264266

265267
llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(StringRef str,

stdlib/public/core/KeyPath.swift

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2378,6 +2378,24 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
23782378
// A reference to metadata, which is a pointer to a mangled name.
23792379
internal typealias MetadataReference = UnsafeRawPointer
23802380

2381+
// Determine the length of the given mangled name.
2382+
internal func _getSymbolicMangledNameLength(_ base: UnsafeRawPointer) -> Int {
2383+
var end = base
2384+
while let current = Optional(end.load(as: UInt8.self)), current != 0 {
2385+
// Skip the current character
2386+
end = end + 1
2387+
2388+
// Skip over a symbolic reference
2389+
if current >= 0x1 && current <= 0x17 {
2390+
end += 4
2391+
} else if current >= 0x18 && current <= 0x1F {
2392+
end += MemoryLayout<Int>.size
2393+
}
2394+
}
2395+
2396+
return end - base
2397+
}
2398+
23812399
// Resolve the given generic argument reference to a generic argument.
23822400
internal func _resolveKeyPathGenericArgReference(_ reference: UnsafeRawPointer,
23832401
arguments: UnsafeRawPointer)
@@ -2405,7 +2423,23 @@ internal func _resolveKeyPathGenericArgReference(_ reference: UnsafeRawPointer,
24052423
return accessor(arguments)
24062424
}
24072425

2408-
fatalError("unhandled keypath metadata reference")
2426+
let nameLength = _getSymbolicMangledNameLength(referenceStart)
2427+
let namePtr = referenceStart.bindMemory(to: UInt8.self,
2428+
capacity: nameLength + 1)
2429+
// FIXME: Could extract this information from the mangled name.
2430+
let parametersPerLevel: [UInt] = []
2431+
let substitutions: [Any.Type] = []
2432+
guard let result = _getTypeByMangledName(namePtr, UInt(nameLength), 0,
2433+
parametersPerLevel, substitutions)
2434+
else {
2435+
let nameStr = String._fromUTF8Repairing(
2436+
UnsafeBufferPointer(start: namePtr, count: nameLength)
2437+
).0
2438+
2439+
fatalError("could not demangle keypath type from '\(nameStr)'")
2440+
}
2441+
2442+
return unsafeBitCast(result, to: UnsafeRawPointer.self)
24092443
}
24102444

24112445
// Resolve the given metadata reference to (type) metadata.

test/IRGen/keypaths.sil

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ sil_vtable C2 {}
4747
// -- %a: S.x
4848
// CHECK: [[KP_A:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
4949
// CHECK-SAME: [[WORD]]* @keypath_once
50-
// CHECK-SAME: @"keypath_get_type 8keypaths1SV
51-
// CHECK-SAME: @"keypath_get_type Si
50+
// CHECK-SAME: @"symbolic 8keypaths1SV"
51+
// CHECK-SAME: @"symbolic Si
5252
// -- instantiable in-line, size 4
5353
// CHECK-SAME: <i32 0x8000_0004>,
5454
// -- offset of S.x, mutable
@@ -57,8 +57,8 @@ sil_vtable C2 {}
5757
// -- %b: S.y
5858
// CHECK: [[KP_B:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
5959
// CHECK-SAME: [[WORD]]* @keypath_once
60-
// CHECK-SAME: @"keypath_get_type 8keypaths1SV
61-
// CHECK-SAME: @"keypath_get_type SS
60+
// CHECK-SAME: @"symbolic 8keypaths1SV
61+
// CHECK-SAME: @"symbolic SS
6262
// -- instantiable in-line, size 4
6363
// CHECK-SAME: <i32 0x8000_0004>,
6464
// -- offset of S.y, immutable
@@ -68,8 +68,8 @@ sil_vtable C2 {}
6868
// -- %c: S.z
6969
// CHECK: [[KP_C:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
7070
// CHECK-SAME: [[WORD]]* @keypath_once
71-
// CHECK-SAME: @"keypath_get_type 8keypaths1SV
72-
// CHECK-SAME: @"keypath_get_type 8keypaths1CC
71+
// CHECK-SAME: @"symbolic 8keypaths1SV
72+
// CHECK-SAME: @"symbolic 8keypaths1CC
7373
// -- instantiable in-line, size 4
7474
// CHECK-SAME: <i32 0x8000_0004>,
7575
// -- offset of S.z, mutable
@@ -79,8 +79,8 @@ sil_vtable C2 {}
7979
// -- %d: C.x
8080
// CHECK: [[KP_D:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
8181
// CHECK-SAME: [[WORD]]* @keypath_once
82-
// CHECK-SAME: @"keypath_get_type
83-
// CHECK-SAME: @"keypath_get_type
82+
// CHECK-SAME: @"symbolic
83+
// CHECK-SAME: @"symbolic
8484
// -- instantiable in-line, size 4
8585
// CHECK-SAME: <i32 0x8000_0004>,
8686
// -- 0x0300_0000 (class) + mutable + offset of C.x
@@ -90,8 +90,8 @@ sil_vtable C2 {}
9090
// -- %e: C.y
9191
// CHECK: [[KP_E:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
9292
// CHECK-SAME: [[WORD]]* @keypath_once
93-
// CHECK-SAME: @"keypath_get_type
94-
// CHECK-SAME: @"keypath_get_type
93+
// CHECK-SAME: @"symbolic
94+
// CHECK-SAME: @"symbolic
9595
// -- instantiable in-line, size 4
9696
// CHECK-SAME: <i32 0x8000_0004>,
9797
// -- 0x0300_0000 (class) + immutable + offset of C.y
@@ -101,8 +101,8 @@ sil_vtable C2 {}
101101
// -- %f: C.z
102102
// CHECK: [[KP_F:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
103103
// CHECK-SAME: [[WORD]]* @keypath_once
104-
// CHECK-SAME: @"keypath_get_type
105-
// CHECK-SAME: @"keypath_get_type
104+
// CHECK-SAME: @"symbolic
105+
// CHECK-SAME: @"symbolic
106106
// -- instantiable in-line, size 4
107107
// CHECK-SAME: <i32 0x8000_0004>,
108108
// -- 0x0300_0000 (class) + mutable offset of C.z
@@ -112,36 +112,36 @@ sil_vtable C2 {}
112112
// -- %g: S.z.x
113113
// CHECK: [[KP_G:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
114114
// CHECK-SAME: [[WORD]]* @keypath_once
115-
// CHECK-SAME: @"keypath_get_type
116-
// CHECK-SAME: @"keypath_get_type
115+
// CHECK-SAME: @"symbolic
116+
// CHECK-SAME: @"symbolic
117117
// -- instantiable in-line, size 12
118118
// CHECK-SAME: <i32 0x8000_000c>,
119119
// -- offset of S.z
120120
// CHECK-32-SAME: <i32 0x0180_0010>,
121121
// CHECK-64-SAME: <i32 0x0180_0018>,
122-
// CHECK: @"keypath_get_type
122+
// CHECK: @"symbolic
123123
// -- 0x0300_0000 (class) + offset of C.x
124124
// CHECK-32-SAME: <i32 0x0380_0008> }>
125125
// CHECK-64-SAME: <i32 0x0380_0010> }>
126126

127127
// -- %h: C.z.x
128128
// CHECK: [[KP_H:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
129129
// CHECK-SAME: [[WORD]]* @keypath_once
130-
// CHECK-SAME: @"keypath_get_type
131-
// CHECK-SAME: @"keypath_get_type
130+
// CHECK-SAME: @"symbolic
131+
// CHECK-SAME: @"symbolic
132132
// CHECK-SAME: <i32 0x8000_000c>,
133133
// -- 0x0300_0000 (class) + offset of C.z
134134
// CHECK-32-SAME: <i32 0x0380_0018>,
135135
// CHECK-64-SAME: <i32 0x0380_0028>,
136-
// CHECK: @"keypath_get_type
136+
// CHECK: @"symbolic
137137
// -- offset of S.x
138138
// CHECK-SAME: <i32 0x0180_0000> }>
139139

140140
// -- %k: computed
141141
// CHECK: [[KP_K:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
142142
// CHECK-SAME: [[WORD]]* @keypath_once
143-
// CHECK-SAME: @"keypath_get_type
144-
// CHECK-SAME: @"keypath_get_type
143+
// CHECK-SAME: @"symbolic
144+
// CHECK-SAME: @"symbolic
145145
// -- instantiable in-line, size 12
146146
// CHECK-SAME: <i32 0x8000_000c>,
147147
// -- computed, get-only, identified by (indirected) function pointer, no args
@@ -152,8 +152,8 @@ sil_vtable C2 {}
152152
// -- %l: computed
153153
// CHECK: [[KP_L:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
154154
// CHECK-SAME: [[WORD]]* @keypath_once
155-
// CHECK-SAME: @"keypath_get_type
156-
// CHECK-SAME: @"keypath_get_type
155+
// CHECK-SAME: @"symbolic
156+
// CHECK-SAME: @"symbolic
157157
// -- instantiable in-line, size 16
158158
// CHECK-SAME: <i32 0x8000_0010>,
159159
// -- computed, settable, nonmutating, identified by indirect pointer, no args
@@ -165,8 +165,8 @@ sil_vtable C2 {}
165165
// -- %m: computed
166166
// CHECK: [[KP_M:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
167167
// CHECK-SAME: [[WORD]]* @keypath_once
168-
// CHECK-SAME: @"keypath_get_type
169-
// CHECK-SAME: @"keypath_get_type
168+
// CHECK-SAME: @"symbolic
169+
// CHECK-SAME: @"symbolic
170170
// -- instantiable in-line, size 16
171171
// CHECK-SAME: <i32 0x8000_0010>,
172172
// -- computed, settable, nonmutating, identified by property offset, no args

0 commit comments

Comments
 (0)