Builtin.loadRaw

I am testing a test case "KeyPath.swift" on s390x for v4.0 . It is found
that " Builtin.loadRaw" as the below of
"stdlib/public/core/UnsafeRawPointer.swift.gyb" returns a different value
than that on x86-64.

     @_inlineable
     public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type)
   -> T {
       _debugPrecondition(0 == (UInt(bitPattern: self + offset)
           & (UInt(MemoryLayout<T>.alignment) - 1)),
         "load from misaligned raw pointer")

       return Builtin.loadRaw((self + offset)._rawValue) // return a
   different value on s390x vs x86-64
     }

My debugger (lldb) does not guide me to the detailed of " Builtin.loadRaw".
Searching "loadRaw" and finding
    swift/include/swift/AST/Builtins.def:BUILTIN_SIL_OPERATION(LoadRaw,
   "loadRaw", Special)

But I could not find the definition of this "LoadRaw" from the whole swift
v4.
Can anyone give me a hint where its implementation is?

Thanks,

Sam Ding,
Linux on z Systems Open Source Ecosystem
IBM Toronto Lab,
email: samding@ca.ibm.com
phone: (905)413-2947

Hi Sam,

The builtin is defined in lib/SILGen/SILGenBuiltin.cpp, look for the function named emitBuiltinLoadRaw().

However I suspect the problem in this case is not that the builtin is implemented incorrectly (it eventually lowers to an LLVM load instruction) but that something further upstream is going wrong, perhaps with alignment or endianness.

Can you tell us which unit tests are failing specifically?

Slava

···

On Sep 28, 2017, at 2:16 PM, Sam Ding via swift-dev <swift-dev@swift.org> wrote:

I am testing a test case "KeyPath.swift" on s390x for v4.0 . It is found that " Builtin.loadRaw" as the below of
"stdlib/public/core/UnsafeRawPointer.swift.gyb" returns a different value than that on x86-64.
@_inlineable
public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T {
_debugPrecondition(0 == (UInt(bitPattern: self + offset)
& (UInt(MemoryLayout<T>.alignment) - 1)),
"load from misaligned raw pointer")

return Builtin.loadRaw((self + offset)._rawValue) // return a different value on s390x vs x86-64
}
My debugger (lldb) does not guide me to the detailed of " Builtin.loadRaw". Searching "loadRaw" and finding
swift/include/swift/AST/Builtins.def:BUILTIN_SIL_OPERATION(LoadRaw, "loadRaw", Special)

But I could not find the definition of this "LoadRaw" from the whole swift v4.
Can anyone give me a hint where its implementation is?

Thanks,

Sam Ding,
Linux on z Systems Open Source Ecosystem
IBM Toronto Lab,
email: samding@ca.ibm.com
phone: (905)413-2947
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Builtins don't have any definition in Swift; they're lowered directly by the compiler. UnsafeRawPointer.load loads a value from memory at the address referenced by the pointer's value. The pointer may be getting miscalculated because of layout assumptions that hold on other platforms but not s390x.

-Joe

···

On Sep 28, 2017, at 2:16 PM, Sam Ding via swift-dev <swift-dev@swift.org> wrote:

I am testing a test case "KeyPath.swift" on s390x for v4.0 . It is found that " Builtin.loadRaw" as the below of
"stdlib/public/core/UnsafeRawPointer.swift.gyb" returns a different value than that on x86-64.
@_inlineable
public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T {
_debugPrecondition(0 == (UInt(bitPattern: self + offset)
& (UInt(MemoryLayout<T>.alignment) - 1)),
"load from misaligned raw pointer")

return Builtin.loadRaw((self + offset)._rawValue) // return a different value on s390x vs x86-64
}
My debugger (lldb) does not guide me to the detailed of " Builtin.loadRaw". Searching "loadRaw" and finding
swift/include/swift/AST/Builtins.def:BUILTIN_SIL_OPERATION(LoadRaw, "loadRaw", Special)

But I could not find the definition of this "LoadRaw" from the whole swift v4.
Can anyone give me a hint where its implementation is?

Hi Slava & Joe,

Thank you for the response.

The failed test case is "generic instantiation" of KeyPath.swift. Here is
details of log:
      [ RUN ] key paths.key path generic instantiation
      >>> check failed
      at /home/wk/sw4/swift/test/stdlib/KeyPath.swift, line 193
      >>> expected: Swift.ReferenceWritableKeyPath<a.S<Swift.Int>,
      Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.Int>,
      Swift.Int>)
      >>> actual: Swift.ReferenceWritableKeyPath<a.S<Swift.Int>,
      Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.Int>,
      Swift.Int>)
      >>> check failed
      at /home/wk/sw4/swift/test/stdlib/KeyPath.swift, line 197
      >>> expected: Swift.ReferenceWritableKeyPath<a.S<Swift.String>,
      Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.String>,
      Swift.Int>)
      >>> actual: Swift.ReferenceWritableKeyPath<a.S<Swift.String>,
      Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.String>,
      Swift.Int>)
      >>> check failed
      at /home/wk/sw4/swift/test/stdlib/KeyPath.swift, line 201
      >>> expected:
      Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>,
      Swift.Int> (of type
      Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>,
      Swift.Int>)
      >>> actual:
      Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>,
      Swift.Int> (of type
      Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>,
      Swift.Int>)
      [ FAIL ] key paths.key path generic instantiation

Other test cases of KeyPath.siwft are all passed.
It is found that the failure reason is @stdlib/public/core/KeyPath.swift

        85 if aComponent.header.endOfReferencePrefix
        86 != bComponent.header.endOfReferencePrefix
        87 || aComponent.value != bComponent.value // this
      is true on s390x, aComponent.value="struct(0)",
      bComponent.value="struct(48)"
        88 || aType != bType {
        89 return false
        90 }

Then tracing to:

   2094 func tryToResolveOffset() {
   2095 if header.payload ==
   RawKeyPathComponent.Header.unresolvedFieldOffsetPayload {
   2096 // Look up offset in type metadata. The value in the
   pattern is the
   2097 // offset within the metadata object.
   2098 let metadataPtr = unsafeBitCast(base, to:
   UnsafeRawPointer.self)
   2099 let offsetOfOffset = patternBuffer.pop(UInt32.self)
   2100 print("+++++++++++ int_offsetOfOffset=\(Int(offsetOfOffset))\n")
   2101 var offset = metadataPtr.load(fromByteOffset: Int
   (offsetOfOffset), // given the same input parameters
   (offsetOfOfferset=56),
   2102 as:
   UInt32.self) // different
   "offset" (0 on s390x, and 48 on x86_64)
   2103 // Rewrite the header for a resolved offset.

Then it comes Builtin.loadRaw of UnsafeRawPointer.swift.gyb

As My lldb and gdb do not stop @ emitBuiltinLoadRaw(),
I inserted a "printf" in the fucntion, but it does not print out anything.

Yes, I think it maybe related to alignment or endianness, so we need to
find the source code of LoadRaw.

Thanks,

Sam Ding,
Linux on z Systems Open Source Ecosystem
IBM Toronto Lab,
email: samding@ca.ibm.com
phone: (905)413-2947

···

From: Slava Pestov <spestov@apple.com>
To: Sam Ding <samding@ca.ibm.com>
Cc: swift-dev <swift-dev@swift.org>
Date: 09/28/2017 05:24 PM
Subject: Re: [swift-dev] Builtin.loadRaw
Sent by: spestov@apple.com

Hi Sam,

The builtin is defined in lib/SILGen/SILGenBuiltin.cpp, look for the
function named emitBuiltinLoadRaw().

However I suspect the problem in this case is not that the builtin is
implemented incorrectly (it eventually lowers to an LLVM load instruction)
but that something further upstream is going wrong, perhaps with alignment
or endianness.

Can you tell us which unit tests are failing specifically?

Slava

      On Sep 28, 2017, at 2:16 PM, Sam Ding via swift-dev < swift-dev@swift.org> wrote:

      I am testing a test case "KeyPath.swift" on s390x for v4.0 . It is
      found that " Builtin.loadRaw" as the below of
      "stdlib/public/core/UnsafeRawPointer.swift.gyb" returns a different
      value than that on x86-64.

            @_inlineable
            public func load<T>(fromByteOffset offset: Int = 0, as type:
            T.Type) -> T {
            _debugPrecondition(0 == (UInt(bitPattern: self + offset)
            & (UInt(MemoryLayout<T>.alignment) - 1)),
            "load from misaligned raw pointer")

            return Builtin.loadRaw((self + offset)._rawValue) // return a
            different value on s390x vs x86-64
            }
      My debugger (lldb) does not guide me to the detailed of "
      Builtin.loadRaw". Searching "loadRaw" and finding
            swift/include/swift/AST/Builtins.def:BUILTIN_SIL_OPERATION
            (LoadRaw, "loadRaw", Special)

      But I could not find the definition of this "LoadRaw" from the whole
      swift v4.
      Can anyone give me a hint where its implementation is?

      Thanks,

      Sam Ding,
      Linux on z Systems Open Source Ecosystem
      IBM Toronto Lab,
      email: samding@ca.ibm.com
      phone: (905)413-2947
      _______________________________________________
      swift-dev mailing list
      swift-dev@swift.org
      https://lists.swift.org/mailman/listinfo/swift-dev

I think you're focusing on the wrong level of abstraction. It is extremely unlikely that the implementation of UnsafeRawPointer.load is incorrect, because otherwise nothing would work. You should understand UnsafeRawPointer.load as a primitive operation, like *(uint32_t*)((char*)metadataPtr + offsetOfOffset) in C, and look at the address that's being computed and the memory layout of the KeyPath object being interpreted and how it differs on s390x vs. other platforms.

-Joe

···

On Sep 29, 2017, at 8:08 AM, Sam Ding <samding@ca.ibm.com> wrote:

Hi Slava & Joe,

Thank you for the response.

The failed test case is "generic instantiation" of KeyPath.swift. Here is details of log:

[ RUN ] key paths.key path generic instantiation
>>> check failed at /home/wk/sw4/swift/test/stdlib/KeyPath.swift, line 193
>>> expected: Swift.ReferenceWritableKeyPath<a.S<Swift.Int>, Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.Int>, Swift.Int>)
>>> actual: Swift.ReferenceWritableKeyPath<a.S<Swift.Int>, Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.Int>, Swift.Int>)
>>> check failed at /home/wk/sw4/swift/test/stdlib/KeyPath.swift, line 197
>>> expected: Swift.ReferenceWritableKeyPath<a.S<Swift.String>, Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.String>, Swift.Int>)
>>> actual: Swift.ReferenceWritableKeyPath<a.S<Swift.String>, Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<Swift.String>, Swift.Int>)
>>> check failed at /home/wk/sw4/swift/test/stdlib/KeyPath.swift, line 201
>>> expected: Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>, Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>, Swift.Int>)
>>> actual: Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>, Swift.Int> (of type Swift.ReferenceWritableKeyPath<a.S<StdlibUnittest.LifetimeTracked>, Swift.Int>)
[ FAIL ] key paths.key path generic instantiation

Other test cases of KeyPath.siwft are all passed.
It is found that the failure reason is @stdlib/public/core/KeyPath.swift
85 if aComponent.header.endOfReferencePrefix
86 != bComponent.header.endOfReferencePrefix
87 || aComponent.value != bComponent.value // this is true on s390x, aComponent.value="struct(0)", bComponent.value="struct(48)"
88 || aType != bType {
89 return false
90 }

Then tracing to:
2094 func tryToResolveOffset() {
2095 if header.payload == RawKeyPathComponent.Header.unresolvedFieldOffsetPayload {
2096 // Look up offset in type metadata. The value in the pattern is the
2097 // offset within the metadata object.
2098 let metadataPtr = unsafeBitCast(base, to: UnsafeRawPointer.self)
2099 let offsetOfOffset = patternBuffer.pop(UInt32.self)
2100 print("+++++++++++ int_offsetOfOffset=\(Int(offsetOfOffset))\n")
2101 var offset = metadataPtr.load(fromByteOffset: Int(offsetOfOffset), // given the same input parameters (offsetOfOfferset=56),
2102 as: UInt32.self) // different "offset" (0 on s390x, and 48 on x86_64)
2103 // Rewrite the header for a resolved offset.

Then it comes Builtin.loadRaw of UnsafeRawPointer.swift.gyb

As My lldb and gdb do not stop @ emitBuiltinLoadRaw(),
I inserted a "printf" in the fucntion, but it does not print out anything.

Yes, I think it maybe related to alignment or endianness, so we need to find the source code of LoadRaw.