diff --git a/include/swift/ABI/KeyPath.h b/include/swift/ABI/KeyPath.h index 53a6018933756..0c42b394af11b 100644 --- a/include/swift/ABI/KeyPath.h +++ b/include/swift/ABI/KeyPath.h @@ -192,6 +192,7 @@ class KeyPathComponentHeader { enum ComputedPropertyIDResolution { Resolved, + ResolvedAbsolute, IndirectPointer, FunctionCall, }; @@ -214,6 +215,7 @@ class KeyPathComponentHeader { ? _SwiftKeyPathComponentHeader_ComputedIDByVTableOffsetFlag : 0) | (hasArguments ? _SwiftKeyPathComponentHeader_ComputedHasArgumentsFlag : 0) | (resolution == Resolved ? _SwiftKeyPathComponentHeader_ComputedIDResolved + : resolution == ResolvedAbsolute ? _SwiftKeyPathComponentHeader_ComputedIDResolvedAbsolute : resolution == IndirectPointer ? _SwiftKeyPathComponentHeader_ComputedIDUnresolvedIndirectPointer : resolution == FunctionCall ? _SwiftKeyPathComponentHeader_ComputedIDUnresolvedFunctionCall : (assert(false && "invalid resolution"), 0))); diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index af1a22ab8db98..d95ebbef7a894 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -954,7 +954,11 @@ emitKeyPathComponent(IRGenModule &IGM, // instantiation time. idResolution = idRef.isIndirect() ? KeyPathComponentHeader::IndirectPointer - : KeyPathComponentHeader::Resolved; + // Compute absolute reference from relative reference if target supports it. + // Otherwise, embed absolute reference directly. + : (IGM.getOptions().CompactAbsoluteFunctionPointer + ? KeyPathComponentHeader::ResolvedAbsolute + : KeyPathComponentHeader::Resolved); break; } case KeyPathPatternComponent::ComputedPropertyId::DeclRef: { @@ -1089,8 +1093,12 @@ emitKeyPathComponent(IRGenModule &IGM, fields.addInt32(header.getData()); switch (idKind) { case KeyPathComponentHeader::Pointer: - // Use a relative offset to the referent. - fields.addRelativeAddress(idValue); + // Use a relative offset to the referent if value is not absolute. + if (idResolution == KeyPathComponentHeader::ResolvedAbsolute) { + fields.add(idValue); + } else { + fields.addRelativeAddress(idValue); + } break; case KeyPathComponentHeader::VTableOffset: diff --git a/stdlib/public/SwiftShims/KeyPath.h b/stdlib/public/SwiftShims/KeyPath.h index 9b6ba3bd40214..17e9adbc165b0 100644 --- a/stdlib/public/SwiftShims/KeyPath.h +++ b/stdlib/public/SwiftShims/KeyPath.h @@ -104,6 +104,8 @@ static const __swift_uint32_t _SwiftKeyPathComponentHeader_ComputedIDResolutionM = 0x0000000FU; static const __swift_uint32_t _SwiftKeyPathComponentHeader_ComputedIDResolved = 0x00000000U; +static const __swift_uint32_t _SwiftKeyPathComponentHeader_ComputedIDResolvedAbsolute + = 0x00000003U; static const __swift_uint32_t _SwiftKeyPathComponentHeader_ComputedIDUnresolvedIndirectPointer = 0x00000002U; static const __swift_uint32_t _SwiftKeyPathComponentHeader_ComputedIDUnresolvedFunctionCall diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift index 68c16969ef9f1..6058edd6483a2 100644 --- a/stdlib/public/core/KeyPath.swift +++ b/stdlib/public/core/KeyPath.swift @@ -874,6 +874,7 @@ internal enum KeyPathComputedIDKind { internal enum KeyPathComputedIDResolution { case resolved + case resolvedAbsolute case indirectPointer case functionCall } @@ -1108,6 +1109,9 @@ internal struct RawKeyPathComponent { internal static var computedIDResolved: UInt32 { return _SwiftKeyPathComponentHeader_ComputedIDResolved } + internal static var computedIDResolvedAbsolute: UInt32 { + return _SwiftKeyPathComponentHeader_ComputedIDResolvedAbsolute + } internal static var computedIDUnresolvedIndirectPointer: UInt32 { return _SwiftKeyPathComponentHeader_ComputedIDUnresolvedIndirectPointer } @@ -1118,6 +1122,8 @@ internal struct RawKeyPathComponent { switch payload & Header.computedIDResolutionMask { case Header.computedIDResolved: return .resolved + case Header.computedIDResolvedAbsolute: + return .resolvedAbsolute case Header.computedIDUnresolvedIndirectPointer: return .indirectPointer case Header.computedIDUnresolvedFunctionCall: @@ -3381,35 +3387,39 @@ internal struct InstantiateKeyPathBuffer: KeyPathPatternVisitor { resolvedID = UnsafeRawPointer(bitPattern: value) case .pointer: - // Resolve the sign-extended relative reference. - var absoluteID: UnsafeRawPointer? = _resolveRelativeAddress(idValueBase, idValue) - // If the pointer ID is unresolved, then it needs work to get to // the final value. switch idResolution { case .resolved: + resolvedID = _resolveRelativeAddress(idValueBase, idValue) + break + + case .resolvedAbsolute: + let value = UInt(UInt32(bitPattern: idValue)) + resolvedID = UnsafeRawPointer(bitPattern: value) break case .indirectPointer: // The pointer in the pattern is an indirect pointer to the real // identifier pointer. - absoluteID = absoluteID.unsafelyUnwrapped + let absoluteID = _resolveRelativeAddress(idValueBase, idValue) + resolvedID = absoluteID .load(as: UnsafeRawPointer?.self) case .functionCall: // The pointer in the pattern is to a function that generates the // identifier pointer. typealias Resolver = @convention(c) (UnsafeRawPointer?) -> UnsafeRawPointer? + let absoluteID = _resolveCompactFunctionPointer(idValueBase, idValue) let resolverSigned = _PtrAuth.sign( - pointer: absoluteID.unsafelyUnwrapped, + pointer: absoluteID, key: .processIndependentCode, discriminator: _PtrAuth.discriminator(for: Resolver.self)) let resolverFn = unsafeBitCast(resolverSigned, to: Resolver.self) - absoluteID = resolverFn(patternArgs) + resolvedID = resolverFn(patternArgs) } - resolvedID = absoluteID } // Bring over the header, getter, and setter.