KeyPath issue with s390x

(Leo) #1

Hi, there, i am having a trouble with using KeyPath on s390x platform. Here is the example:

func generic<A: Equatable, B: Equatable>(a: A, b: B) {
    typealias T = (A, B)
    let kp_t_1 = \T.1

    let tuple = (a, b)
    let k1 = tuple[keyPath: kp_t_1]

generic(a: 2, b: 31)

It supposes to print 31, however it prints 2 instead, which is obviously wrong. I have managed to find a hack fix in the source code:

diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 599757bce3..7159d78e37 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -3134,14 +3134,24 @@ internal struct InstantiateKeyPathBuffer : KeyPathPatternVisitor {
         // Look up offset in the type metadata. The value in the pattern is
         // the offset within the metadata object.
         let metadataPtr = unsafeBitCast(base, to: UnsafeRawPointer.self)
         let offset: UInt32
         switch kind {
         case .class:
           offset = UInt32(metadataPtr.load(fromByteOffset: Int(offsetOfOffset),
                                            as: UInt.self))
         case .struct:
           offset = UInt32(metadataPtr.load(fromByteOffset: Int(offsetOfOffset),
-                                           as: UInt32.self))
+                                           as: UInt.self))

The idea is to load the value at metadataPtr+offsetOfOffset as 8 bytes (UInt) wide rather than 4 bytes (UInt32) wide. After checking lib/IRGen/GenKeyPath.swift, it doesn’t seem there is a 64-bit offset stored anywhere. Does anyone have any idea where the root cause might be?