Skip to content

Commit f759296

Browse files
committed
[Keypaths] Encode generic environment in the key-path pattern.
Extend the key-path pattern with a representation of the generic environment of the key-path, which includes the generic parameters and generic requirements of the environment.
1 parent 201dcba commit f759296

File tree

10 files changed

+195
-18
lines changed

10 files changed

+195
-18
lines changed

include/swift/ABI/Metadata.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,6 +2611,57 @@ class TargetGenericRequirementDescriptor {
26112611
using GenericRequirementDescriptor =
26122612
TargetGenericRequirementDescriptor<InProcess>;
26132613

2614+
template<typename Runtime>
2615+
class TargetGenericEnvironment
2616+
: public swift::ABI::TrailingObjects<TargetGenericEnvironment<Runtime>,
2617+
uint16_t, GenericParamDescriptor,
2618+
TargetGenericRequirementDescriptor<Runtime>> {
2619+
using GenericRequirementDescriptor =
2620+
TargetGenericRequirementDescriptor<Runtime>;
2621+
using TrailingObjects =
2622+
swift::ABI::TrailingObjects<TargetGenericEnvironment<Runtime>,
2623+
uint16_t, GenericParamDescriptor, GenericRequirementDescriptor>;
2624+
friend TrailingObjects;
2625+
2626+
template<typename T>
2627+
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
2628+
2629+
size_t numTrailingObjects(OverloadToken<uint16_t>) const {
2630+
return Flags.getNumGenericParameterLevels();
2631+
}
2632+
2633+
size_t numTrailingObjects(OverloadToken<GenericParamDescriptor>) const {
2634+
return getGenericParameterCounts().back();
2635+
}
2636+
2637+
size_t numTrailingObjects(OverloadToken<GenericRequirementDescriptor>) const {
2638+
return Flags.getNumGenericRequirements();
2639+
}
2640+
2641+
GenericEnvironmentFlags Flags;
2642+
2643+
public:
2644+
/// Retrieve the cumulative generic parameter counts at each level of genericity.
2645+
ArrayRef<uint16_t> getGenericParameterCounts() const {
2646+
return ArrayRef<uint16_t>(this->template getTrailingObjects<uint16_t>(),
2647+
Flags.getNumGenericParameterLevels());
2648+
}
2649+
2650+
/// Retrieve the generic parameters descriptors.
2651+
ArrayRef<GenericParamDescriptor> getGenericParameters() const {
2652+
return ArrayRef<GenericParamDescriptor>(
2653+
this->template getTrailingObjects<GenericParamDescriptor>(),
2654+
getGenericParameterCounts().back());
2655+
}
2656+
2657+
/// Retrieve the generic requirements.
2658+
ArrayRef<GenericRequirementDescriptor> getGenericRequirements() const {
2659+
return ArrayRef<GenericRequirementDescriptor>(
2660+
this->template getTrailingObjects<GenericRequirementDescriptor>(),
2661+
Flags.getNumGenericRequirements());
2662+
}
2663+
};
2664+
26142665
/// CRTP class for a context descriptor that includes trailing generic
26152666
/// context description.
26162667
template<class Self,

include/swift/ABI/MetadataValues.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,45 @@ enum class GenericRequirementLayoutKind : uint32_t {
15081508
Class = 0,
15091509
};
15101510

1511+
class GenericEnvironmentFlags {
1512+
uint32_t Value;
1513+
1514+
enum : uint32_t {
1515+
NumGenericParameterLevelsMask = 0xFFF,
1516+
NumGenericRequirementsShift = 12,
1517+
NumGenericRequirementsMask = 0xFFFF << NumGenericRequirementsShift,
1518+
};
1519+
1520+
constexpr explicit GenericEnvironmentFlags(uint32_t value) : Value(value) { }
1521+
1522+
public:
1523+
constexpr GenericEnvironmentFlags() : Value(0) { }
1524+
1525+
constexpr GenericEnvironmentFlags
1526+
withNumGenericParameterLevels(uint16_t numGenericParameterLevels) const {
1527+
return GenericEnvironmentFlags((Value &~ NumGenericParameterLevelsMask)
1528+
| numGenericParameterLevels);
1529+
}
1530+
1531+
constexpr GenericEnvironmentFlags
1532+
withNumGenericRequirements(uint16_t numGenericRequirements) const {
1533+
return GenericEnvironmentFlags((Value &~ NumGenericParameterLevelsMask)
1534+
| (numGenericRequirements << NumGenericRequirementsShift));
1535+
}
1536+
1537+
constexpr unsigned getNumGenericParameterLevels() const {
1538+
return Value & NumGenericParameterLevelsMask;
1539+
}
1540+
1541+
constexpr unsigned getNumGenericRequirements() const {
1542+
return (Value & NumGenericRequirementsMask) >> NumGenericRequirementsShift;
1543+
}
1544+
1545+
constexpr uint32_t getIntValue() const {
1546+
return Value;
1547+
}
1548+
};
1549+
15111550
/// Flags used by generic metadata patterns.
15121551
class GenericMetadataPatternFlags : public FlagSet<uint32_t> {
15131552
enum {

lib/IRGen/GenKeyPath.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ emitGeneratorForKeyPath(IRGenModule &IGM,
657657
ArrayRef<GenericRequirement> requirements,
658658
llvm::function_ref<void(IRGenFunction&,CanType)> emit) {
659659

660-
return IGM.getAddrOfStringForMetadataRef(name,
660+
return IGM.getAddrOfStringForMetadataRef(name, /*alignment=*/2,
661661
/*shouldSetLowBit=*/true,
662662
[&](ConstantInitBuilder &B) {
663663
// Build a stub that loads the necessary bindings from the key path's
@@ -1171,6 +1171,9 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
11711171
fields.addInt32(0);
11721172
}
11731173

1174+
// Add the generic environment.
1175+
fields.addRelativeAddressOrNull(
1176+
getAddrOfGenericEnvironment(pattern->getGenericSignature()));
11741177
// Store type references for the root and leaf.
11751178
fields.addRelativeAddress(
11761179
emitMetadataGeneratorForKeyPath(*this, rootTy, genericEnv, requirements));

lib/IRGen/GenProto.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "GenericRequirement.h"
6868
#include "IRGenDebugInfo.h"
6969
#include "IRGenFunction.h"
70+
#include "IRGenMangler.h"
7071
#include "IRGenModule.h"
7172
#include "MetadataPath.h"
7273
#include "MetadataRequest.h"
@@ -3419,3 +3420,58 @@ llvm::Value *irgen::emitProtocolDescriptorRef(IRGenFunction &IGF,
34193420

34203421
return val;
34213422
}
3423+
3424+
llvm::Constant *IRGenModule::getAddrOfGenericEnvironment(
3425+
CanGenericSignature signature) {
3426+
if (!signature)
3427+
return nullptr;
3428+
3429+
IRGenMangler mangler;
3430+
auto symbolName = mangler.mangleSymbolNameForGenericEnvironment(signature);
3431+
return getAddrOfStringForMetadataRef(symbolName, /*alignment=*/0, false,
3432+
[&] (ConstantInitBuilder &builder) -> ConstantInitFuture {
3433+
/// Collect the cumulative count of parameters at each level.
3434+
llvm::SmallVector<uint16_t, 4> genericParamCounts;
3435+
unsigned curDepth = 0;
3436+
unsigned genericParamCount = 0;
3437+
for (const auto gp : signature->getGenericParams()) {
3438+
if (curDepth != gp->getDepth()) {
3439+
genericParamCounts.push_back(genericParamCount);
3440+
curDepth = gp->getDepth();
3441+
}
3442+
3443+
++genericParamCount;
3444+
}
3445+
genericParamCounts.push_back(genericParamCount);
3446+
3447+
auto flags = GenericEnvironmentFlags()
3448+
.withNumGenericParameterLevels(genericParamCounts.size())
3449+
.withNumGenericRequirements(signature->getRequirements().size());
3450+
3451+
ConstantStructBuilder fields = builder.beginStruct();
3452+
fields.setPacked(true);
3453+
3454+
// Flags
3455+
fields.addInt32(flags.getIntValue());
3456+
3457+
// Parameter counts.
3458+
for (auto count : genericParamCounts) {
3459+
fields.addInt16(count);
3460+
}
3461+
3462+
// Generic parameters.
3463+
signature->forEachParam([&](GenericTypeParamType *param,
3464+
bool canonical) {
3465+
fields.addInt(Int8Ty,
3466+
GenericParamDescriptor(GenericParamKind::Type,
3467+
canonical,
3468+
false)
3469+
.getIntValue());
3470+
});
3471+
3472+
// Generic requirements
3473+
irgen::addGenericRequirements(*this, fields, signature,
3474+
signature->getRequirements());
3475+
return fields.finishAndCreateFuture();
3476+
});
3477+
}

lib/IRGen/IRGenMangler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,11 @@ std::string IRGenMangler::mangleSymbolNameForKeyPathMetadata(
294294
assert(conformance.isInvalid() && "Unknown protocol conformance");
295295
return finalize();
296296
}
297+
298+
std::string IRGenMangler::mangleSymbolNameForGenericEnvironment(
299+
CanGenericSignature genericSig) {
300+
beginManglingWithoutPrefix();
301+
Buffer << "generic environment ";
302+
appendGenericSignature(genericSig);
303+
return finalize();
304+
}

lib/IRGen/IRGenMangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ class IRGenMangler : public Mangle::ASTMangler {
416416
CanType type,
417417
ProtocolConformanceRef conformance);
418418

419+
std::string mangleSymbolNameForGenericEnvironment(
420+
CanGenericSignature genericSig);
419421
protected:
420422
SymbolicMangling
421423
withSymbolicReferences(IRGenModule &IGM,

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,7 @@ class IRGenModule {
10321032
///
10331033
/// \param symbolName The name of the symbol that describes the metadata
10341034
/// being referenced.
1035+
/// \param alignment If non-zero, the alignment of the requested variable.
10351036
/// \param shouldSetLowBit Whether to set the low bit of the result
10361037
/// constant, which is used by some clients to indicate that the result is
10371038
/// a mangled name.
@@ -1041,6 +1042,7 @@ class IRGenModule {
10411042
/// \returns the address of the global variable describing this metadata.
10421043
llvm::Constant *getAddrOfStringForMetadataRef(
10431044
StringRef symbolName,
1045+
unsigned alignment,
10441046
bool shouldSetLowBit,
10451047
llvm::function_ref<ConstantInitFuture(ConstantInitBuilder &)> body);
10461048

@@ -1276,6 +1278,7 @@ private: \
12761278
llvm::Constant *getAddrOfObjCModuleContextDescriptor();
12771279
llvm::Constant *getAddrOfClangImporterModuleContextDescriptor();
12781280
ConstantReference getAddrOfParentContextDescriptor(DeclContext *from);
1281+
llvm::Constant *getAddrOfGenericEnvironment(CanGenericSignature signature);
12791282
llvm::Constant *getAddrOfProtocolRequirementsBaseDescriptor(
12801283
ProtocolDecl *proto);
12811284
llvm::GlobalValue *defineProtocolRequirementsBaseDescriptor(

lib/IRGen/MetadataRequest.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ MetadataDependency MetadataDependencyCollector::finish(IRGenFunction &IGF) {
220220

221221
llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef(
222222
StringRef symbolName,
223+
unsigned alignment,
223224
bool shouldSetLowBit,
224225
llvm::function_ref<ConstantInitFuture (ConstantInitBuilder &)> body) {
225226
// Call this to form the return value.
@@ -251,7 +252,8 @@ llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef(
251252
llvm::GlobalValue::HiddenVisibility,
252253
llvm::GlobalValue::DefaultStorageClass})
253254
.to(var);
254-
var->setAlignment(2);
255+
if (alignment)
256+
var->setAlignment(alignment);
255257
setTrueConstGlobal(var);
256258
var->setSection(getReflectionTypeRefSectionName());
257259

stdlib/public/core/KeyPath.swift

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,7 +2245,7 @@ internal var keyPathObjectHeaderSize: Int {
22452245
}
22462246

22472247
internal var keyPathPatternHeaderSize: Int {
2248-
return 12
2248+
return 16
22492249
}
22502250

22512251
// Runtime entry point to instantiate a key path object.
@@ -2323,7 +2323,7 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
23232323
}
23242324

23252325
// Adopt the KVC string from the pattern.
2326-
let kvcStringBase = patternPtr.advanced(by: 8)
2326+
let kvcStringBase = patternPtr.advanced(by: 12)
23272327
let kvcStringOffset = kvcStringBase.load(as: Int32.self)
23282328

23292329
if kvcStringOffset == 0 {
@@ -2465,9 +2465,10 @@ internal struct KeyPathPatternComputedArguments {
24652465
}
24662466

24672467
internal protocol KeyPathPatternVisitor {
2468-
mutating func visitHeader(rootMetadataRef: MetadataReference,
2468+
mutating func visitHeader(genericEnvironment: UnsafeRawPointer?,
2469+
rootMetadataRef: MetadataReference,
24692470
leafMetadataRef: MetadataReference,
2470-
kvcCompatibilityString: UnsafeRawPointer)
2471+
kvcCompatibilityString: UnsafeRawPointer?)
24712472
mutating func visitStoredComponent(kind: KeyPathStructOrClass,
24722473
mutable: Bool,
24732474
offset: KeyPathPatternStoredOffset)
@@ -2517,14 +2518,17 @@ internal func _walkKeyPathPattern<W: KeyPathPatternVisitor>(
25172518
_ pattern: UnsafeRawPointer,
25182519
walker: inout W) {
25192520
// Visit the header.
2520-
let rootMetadataRef = _loadRelativeAddress(at: pattern,
2521+
let genericEnvironment = _loadRelativeAddress(at: pattern,
2522+
as: UnsafeRawPointer.self)
2523+
let rootMetadataRef = _loadRelativeAddress(at: pattern, fromByteOffset: 4,
25212524
as: MetadataReference.self)
2522-
let leafMetadataRef = _loadRelativeAddress(at: pattern, fromByteOffset: 4,
2525+
let leafMetadataRef = _loadRelativeAddress(at: pattern, fromByteOffset: 8,
25232526
as: MetadataReference.self)
2524-
let kvcString = _loadRelativeAddress(at: pattern, fromByteOffset: 8,
2527+
let kvcString = _loadRelativeAddress(at: pattern, fromByteOffset: 12,
25252528
as: UnsafeRawPointer.self)
25262529

2527-
walker.visitHeader(rootMetadataRef: rootMetadataRef,
2530+
walker.visitHeader(genericEnvironment: genericEnvironment,
2531+
rootMetadataRef: rootMetadataRef,
25282532
leafMetadataRef: leafMetadataRef,
25292533
kvcCompatibilityString: kvcString)
25302534

@@ -2803,9 +2807,10 @@ internal struct GetKeyPathClassAndInstanceSizeFromPattern
28032807
size = MemoryLayout<Int>._roundingUpToAlignment(size)
28042808
}
28052809

2806-
mutating func visitHeader(rootMetadataRef: MetadataReference,
2810+
mutating func visitHeader(genericEnvironment: UnsafeRawPointer?,
2811+
rootMetadataRef: MetadataReference,
28072812
leafMetadataRef: MetadataReference,
2808-
kvcCompatibilityString: UnsafeRawPointer) {
2813+
kvcCompatibilityString: UnsafeRawPointer?) {
28092814
// Get the root and leaf type metadata so we can form the class type
28102815
// for the entire key path.
28112816
root = _resolveKeyPathMetadataReference(rootMetadataRef,
@@ -3035,9 +3040,10 @@ internal struct InstantiateKeyPathBuffer : KeyPathPatternVisitor {
30353040
return oldValue
30363041
}
30373042

3038-
mutating func visitHeader(rootMetadataRef: MetadataReference,
3043+
mutating func visitHeader(genericEnvironment: UnsafeRawPointer?,
3044+
rootMetadataRef: MetadataReference,
30393045
leafMetadataRef: MetadataReference,
3040-
kvcCompatibilityString: UnsafeRawPointer) {
3046+
kvcCompatibilityString: UnsafeRawPointer?) {
30413047
}
30423048

30433049
mutating func visitStoredComponent(kind: KeyPathStructOrClass,
@@ -3261,13 +3267,16 @@ internal struct ValidatingInstantiateKeyPathBuffer: KeyPathPatternVisitor {
32613267
origDest = self.instantiateVisitor.destData.baseAddress.unsafelyUnwrapped
32623268
}
32633269

3264-
mutating func visitHeader(rootMetadataRef: MetadataReference,
3270+
mutating func visitHeader(genericEnvironment: UnsafeRawPointer?,
3271+
rootMetadataRef: MetadataReference,
32653272
leafMetadataRef: MetadataReference,
3266-
kvcCompatibilityString: UnsafeRawPointer) {
3267-
sizeVisitor.visitHeader(rootMetadataRef: rootMetadataRef,
3273+
kvcCompatibilityString: UnsafeRawPointer?) {
3274+
sizeVisitor.visitHeader(genericEnvironment: genericEnvironment,
3275+
rootMetadataRef: rootMetadataRef,
32683276
leafMetadataRef: leafMetadataRef,
32693277
kvcCompatibilityString: kvcCompatibilityString)
3270-
instantiateVisitor.visitHeader(rootMetadataRef: rootMetadataRef,
3278+
instantiateVisitor.visitHeader(genericEnvironment: genericEnvironment,
3279+
rootMetadataRef: rootMetadataRef,
32713280
leafMetadataRef: leafMetadataRef,
32723281
kvcCompatibilityString: kvcCompatibilityString)
32733282
}

test/IRGen/keypaths.sil

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ sil_vtable C2 {}
195195
// -- %j: Gen<A>.y
196196
// CHECK: [[KP_J:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
197197
// CHECK-SAME: i32 0
198+
// CHECK-SAME: @"generic environment l"
198199
// CHECK-SAME: @"keypath_get_type
199200
// CHECK-SAME: @"keypath_get_type
200201
// -- size 8
@@ -204,6 +205,9 @@ sil_vtable C2 {}
204205
// CHECK-32-SAME: i32 20 }>
205206
// CHECK-64-SAME: i32 36 }>
206207

208+
// CHECK-LABEL: @"generic environment SHRzSHR_r0_l" = linkonce_odr hidden constant
209+
// CHECK-SAME: i32 8192, i16 2, i8 -128, i8 -128, i32 128
210+
207211
// -- %t
208212
// CHECK: [[KP_T:@keypath(\..*)?]] = private global <{ {{.*}} }> <{ {{.*}} i32 1, {{.*}} @"got.$s8keypaths1GV1xxvpMV"
209213
// CHECK-SAME: @"keypath_get_type

0 commit comments

Comments
 (0)