Swift 4.1: storeEnumTagSinglePayload for _UIntBuffer.Index

Hello devs,

I have a code that looks like:

root@csz25065:/home/swift/testcode# cat art.swift
import Foundation
let foo = "foo" as NSMutableString

On s390x (big-endian) this code core dumps and stack indicates problem during getEnumTagSinglePayload for _UIntBuffer.Index:

* thread #1, name = 'art', stop reason = breakpoint 2.98
    frame #0: 0x000003fffdd63426 libswiftCore.so`getEnumTagSinglePayload for **_UIntBuffer.Index** at <unknown>:0 [opt]
Target 0: (art) stopped.
(lldb) c
Process 16422 resuming
Process 16422 stopped
* thread #1, name = 'art', stop reason = signal SIGSEGV: invalid address (fault address: 0x40000000000)
    frame #0: 0x000003fffc291394 libc.so.6`__memcpy_mvcle at memcpy.S:77
Target 0: (art) stopped.

Problem does not happen for following 2 cases:

import Foundation
let foo = "foo" as NSString
let foo = ["foo"] as NSMutableArray

It seems like compiler’s value witness table for _UIntBuffer.Index is not being generated properly on s390x.

I am looking for any guidance on how _UIntBuffer.Index value witness is generated. I can see that UIntBuffer.swift is part of core library but how compiler generates its value witness is not very clear.

I suspect storeEnumTagSinglePayload for _UIntBuffer.Index is fauly on this playform which causes get to core dump.

libswiftCore.so`storeEnumTagSinglePayload for _UIntBuffer.Index:
    0x3fffdd634c0 <+0>:   stmg   %r11, %r15, 88(%r15)
    0x3fffdd634c6 <+6>:   aghi   %r15, -160
    0x3fffdd634ca <+10>:  lgr    %r11, %r15
->  0x3fffdd634ce <+14>:  cije   %r4, 0, 4398010217806     ; <+142> at <unknown>
    0x3fffdd634d4 <+20>:  ahi    %r4, 255

Much of the big-endian stuff is already patched for get/storeEnumTagSinglePayload in GenType.cpp and we have seen positive results (especially in the areas of infinite loop whicg are now addressed) but there may be some corner cases left. I think I may have stepped onto one such case wrt _UIntBuffer.Index.

Thanks.

Hi @Arnold - could you help me decipher the storeEnumTagSinglePayload of value witness for Swift.UInt8 type.

From my understanding, this will be done during compiler build phase. What I don’t understand is why storeEnumTagSinglePayload assembly code for Swift.UInt8 and Swift._UIntBuffer.Index are so different and more importantly how are these 2 related (UInt8 and UIntBuffer.Index) and where is this relationship defined. From my understanding, GenType.cpp is responsible for IR code gen of storeEnumTagSinglePayload for all the data types.

storeEnumTagSinglePayload for Swift.UInt8

* thread #1, name = 'art', stop reason = breakpoint 1.269
    frame #0: 0x000003fffdd6e928 libswiftCore.so`storeEnumTagSinglePayload value witness for Swift.UInt8
libswiftCore.so`storeEnumTagSinglePayload value witness for Swift.UInt8:
->  0x3fffdd6e928 <+0>:  stmg   %r11, %r15, 88(%r15)
    0x3fffdd6e92e <+6>:  lgr    %r11, %r15
    0x3fffdd6e932 <+10>: lmg    %r11, %r15, 88(%r11)
    0x3fffdd6e938 <+16>: jg     4398010217664             ; storeEnumTagSinglePayload value witness for Swift._UIntBuffer.Index at <unknown>

storeEnumTagSinglePayload for _UIntBuffer.Index

libswiftCore.so`storeEnumTagSinglePayload for _UIntBuffer.Index:
    0x3fffdd634c0 <+0>:   stmg   %r11, %r15, 88(%r15)
    0x3fffdd634c6 <+6>:   aghi   %r15, -160
    0x3fffdd634ca <+10>:  lgr    %r11, %r15
->  0x3fffdd634ce <+14>:  cije   %r4, 0, 4398010217806     ; <+142> at <unknown>
    0x3fffdd634d4 <+20>:  ahi    %r4, 255
    0x3fffdd634d8 <+24>:  srl    %r4, 8
    0x3fffdd634dc <+28>:  ahi    %r4, 1
...

I also see this warning during compiler build phase but not sure if it is a red-herring - part of me thinks this may have implications on this platform:

Foundation/NSString.swift:301:24: warning: 'unsafeBitCast' from 'UnsafeMutablePointer<Unicode.UTF8.CodeUnit>' (aka 'UnsafeMutablePointer<UInt8>') to 'UnsafePointer<Int8>' changes pointee type and may lead to undefined behavior; use the 'withMemoryRebound' method on 'UnsafeMutablePointer<Unicode.UTF8.CodeUnit>' (aka 'UnsafeMutablePointer<UInt8>') to rebind the type of memory
                return unsafeBitCast(_storage._core.startASCII, to: UnsafePointer<Int8>.self)

Thanks again for any insight.