[swift-dev] [SR-40] Port Swift to Arm progress / question

William Dillon william at housedillon.com
Tue Dec 15 01:20:18 CST 2015


I built a very simple swift program (minimal hello world) using the arm swiftc and the x86_64 swiftc, and had them emit the sil and llvm ir.  The sil it substantially similar between the toolchain tarball on swift.org and my arm swiftc, except that the arm version has a few sil_vtable, NSArray, and ObjectiveC references that are not in the x86_86 version.  Is it possible that the arm architecture is triggering assumptions about whether this target is linux or darwin?  Fortunately or unfortunately, by the time it gets to LLVM IR it’s effectively identical (other than the odd difference in variable size or alignment).

- Will

$ cat hello.swift 
print("Hello world!")

diff hello.sil-arm hello.sil-x86
...
< // Swift._SwiftNativeNSArrayWithContiguousStorage.__deallocating_deinit
< sil hidden_external [fragile] @_TFCs40_SwiftNativeNSArrayWithContiguousStorageD : $@convention(method) (@owned _SwiftNativeNSArrayWithContiguousStorage) -> ()
< 
< // Swift.NonObjectiveCBase.init () -> Swift.NonObjectiveCBase
< sil [fragile] @_TFCs17NonObjectiveCBasecfT_S_ : $@convention(method) (@owned NonObjectiveCBase) -> @owned NonObjectiveCBase
< 
< // Swift.NonObjectiveCBase.__deallocating_deinit
< sil [fragile] @_TFCs17NonObjectiveCBaseD : $@convention(method) (@owned NonObjectiveCBase) -> ()
...
< 
< sil_vtable _SwiftNativeNSArrayWithContiguousStorage {
<   #_SwiftNativeNSArrayWithContiguousStorage.deinit!deallocator: _TFCs40_SwiftNativeNSArrayWithContiguousStorageD      // Swift._SwiftNativeNSArrayWithContiguousStorage.__deallocating_deinit
< }
< 
< sil_vtable NonObjectiveCBase {
<   #NonObjectiveCBase.init!initializer.1: _TFCs17NonObjectiveCBasecfT_S_       // Swift.NonObjectiveCBase.init () -> Swift.NonObjectiveCBase
<   #NonObjectiveCBase.deinit!deallocator: _TFCs17NonObjectiveCBaseD    // Swift.NonObjectiveCBase.__deallocating_deinit
...

wdillon at tegra-ubuntu:~$ grep "sil_vtable" hello*
hello.sil-x86:sil_vtable _ContiguousArrayStorage {
hello.sil-x86:sil_vtable _HeapBufferStorage {
hello.sil-arm:sil_vtable _ContiguousArrayStorage {
hello.sil-arm:sil_vtable _HeapBufferStorage {
hello.sil-arm:sil_vtable _ContiguousArrayStorage1 {
hello.sil-arm:sil_vtable _ContiguousArrayStorageBase {
hello.sil-arm:sil_vtable _SwiftNativeNSArrayWithContiguousStorage {
hello.sil-arm:sil_vtable NonObjectiveCBase {
wdillon at tegra-ubuntu:~$ 

wdillon at tegra-ubuntu:~$ grep "NonObjectiveC" hello*
hello.sil-x86:  #NonObjectiveCBase.init!initializer.1: _TFCs18_HeapBufferStoragecfT_GS_xq__ // Swift._HeapBufferStorage.init () -> Swift._HeapBufferStorage<A, B>
hello.sil-x86:sil_witness_table NonObjectiveCBase: AnyObject module Swift
hello.sil-arm:// Swift.NonObjectiveCBase.init () -> Swift.NonObjectiveCBase
hello.sil-arm:sil [fragile] @_TFCs17NonObjectiveCBasecfT_S_ : $@convention(method) (@owned NonObjectiveCBase) -> @owned NonObjectiveCBase
hello.sil-arm:// Swift.NonObjectiveCBase.__deallocating_deinit
hello.sil-arm:sil [fragile] @_TFCs17NonObjectiveCBaseD : $@convention(method) (@owned NonObjectiveCBase) -> ()
hello.sil-arm:  #NonObjectiveCBase.init!initializer.1: _TFCs18_HeapBufferStoragecfT_GS_xq__     // Swift._HeapBufferStorage.init () -> Swift._HeapBufferStorage<A, B>
hello.sil-arm:sil_vtable NonObjectiveCBase {
hello.sil-arm:  #NonObjectiveCBase.init!initializer.1: _TFCs17NonObjectiveCBasecfT_S_   // Swift.NonObjectiveCBase.init () -> Swift.NonObjectiveCBase
hello.sil-arm:  #NonObjectiveCBase.deinit!deallocator: _TFCs17NonObjectiveCBaseD        // Swift.NonObjectiveCBase.__deallocating_deinit
hello.sil-arm:sil_witness_table NonObjectiveCBase: AnyObject module Swift


> On Dec 14, 2015, at 6:22 PM, Dmitri Gribenko <gribozavr at gmail.com> wrote:
> 
> On Mon, Dec 14, 2015 at 5:57 PM, William Dillon via swift-dev
> <swift-dev at swift.org> wrote:
>> I’m still stuck on this after a while, but I’ve been paying attention to other discussions (specifically the FreeBSD port), as well as reading tons of code.  One thing I noticed while writing up my observations on my blog http://www.housedillon.com/?p=2267 is that in stdlib/public/runtime/CMakeLists.txt there is a FIXME that seems relevant:
>> 
>> foreach(sdk ${SWIFT_CONFIGURED_SDKS})
>>  if("${sdk}" STREQUAL "LINUX" OR "${sdk}" STREQUAL "FREEBSD")
>>    foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
>>      set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")
>> 
>>      # FIXME: We will need a different linker script for 32-bit builds.
>>      configure_file(
>>          "swift.ld" "${SWIFTLIB_DIR}/${arch_subdir}/swift.ld" COPYONLY)
>> 
>>      swift_install_in_component(compiler
>>          FILES "swift.ld"
>>          DESTINATION "lib/swift/${arch_subdir}")
>> 
>>    endforeach()
>>  endif()
>> endforeach()
>> 
>> 
>> I went ahead and added a conditional for arm, and split swift.ld into swift_64.ld and swift_32.ld:
> 
> The reason why I left that comment there is that the linker script
> adds a size field to the protocol conformance section, and I thought
> that the 32-bit system should have the size be a 32-bit value, so that
> would be the difference.
> 
> But the source always loads a 64-bit quantity from the section, so the
> FIXME is stale:
> 
>  // Extract the size of the conformances block from the head of the section
>  auto conformancesSize = *reinterpret_cast<const uint64_t*>(conformances);
> 
>> I decided to go ahead and check the same conformances that Dmitri and Davide investigated:
>> 
>> $ objdump -t libswiftCore.so | grep conformances
>> 003b8ebc l    d  .swift2_protocol_conformances  00000000              .swift2_protocol_conformances
>> 003b8ec4 l     O .swift2_protocol_conformances  00002f50              l_protocol_conformances
>> 003b8ebc g       .swift2_protocol_conformances  00000000              .swift2_protocol_conformances_start
>> 
>> $ objdump -s -j .swift2_protocol_conformances libswiftCore.so |head -n 10
>> 
>> libswiftCore.so:     file format elf32-littlearm
>> 
>> Contents of section .swift2_protocol_conformances:
>> 3b8ebc 542f0000 00000000 00000000 00000000  T/..............
>> 3b8ecc 00000000 04000000 00000000 00000000  ................
>> 3b8edc 00000000 04000000 00000000 00000000  ................
>> 3b8eec 00000000 04000000 00000000 00000000  ................
>> 3b8efc 00000000 04000000 00000000 00000000  ................
>> 3b8f0c 00000000 04000000 00000000 00000000  ................
>> 
>> And that seems OK based on Dmitri’s basic description of how it works.
> 
> Yes, this looks correct to me.
> 
>> 
>> Paradoxically, I also added a print (and eventually an exit()) to _addImageProtocolConformances() to see if it’s ever run.  I don’t believe it is:
>> 
>> $ swiftc test.swift
>> <unknown>:0: error: unable to load standard library for target 'armv7l-unknown-linux-gnueabihf'
>> $ swiftc -target arm-unknown-linux-gnueabihf test.swift
>> $ ./test
>> ./test: error while loading shared libraries: /mnt/build/build/Ninja-ReleaseAssert/swift-linux-arm/lib/swift/linux/libswiftCore.so: unexpected reloc type 0x03
> 
> The dynamic loader does not finish running, so the code does not even
> get a chance to run.
> 
>> Are there any other paths that I should be following that you can think of?
> 
> I think it would make most sense to try to:
> 
> (1) figure out what part of the library code (on the LLVM IR level)
> produces this illegal relocation (on the high level, e.g., "this
> symbol", "this runtime data structure" etc.),
> 
> (2) provide a minimized LLVM IR example that produces the illegal relocation.
> 
> Dmitri
> 
> -- 
> main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
> (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/



More information about the swift-dev mailing list