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

Hi all,

I’ve been working on trying to get Swift to compile on ARMv7 (armv7l specifically, not sure if other variants will work as well). I’ve gotten pretty far, but I ran a cross an issue that has me a little confused. For convenience, here’s the bug that has some of my messages in the comments: [SR-40] Port Swift to Linux on Raspberry Pi · Issue #5337 · apple/swift-package-manager · GitHub and here’s my Github fork if you want to play along at home: https://github.com/hpux735/swift By the way, I’m compiling on an Nvidia tegra TK2 development board with 2GB of ram and a 25GB swapfile on an external SSD. This brings native compile times down to reasonable levels. I was compiling on the BeagleBone Black formerly, and that was painful (like over a day for LLVM).

So far, cmark and llvm compile just fine (no surprise there), and swift gets pretty far along. The weird issue, which will certainly expose my weakness in C++ and large build systems, is that the swift_ssize_t doesn’t match ssize_t.

[6/61] Building CXX object stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/Stubs.cpp.o
FAILED: /usr/bin/clang++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fno-stack-protector -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wcovered-switch-default -Wnon-virtual-dtor -Werror=date-time -std=c++11 -fcolor-diagnostics -ffunction-sections -fdata-sections -Wdocumentation -Wimplicit-fallthrough -Wunreachable-code -Woverloaded-virtual -O3 -Istdlib/public/stubs -I/home/wdillon/swift/stdlib/public/stubs -I/home/wdillon/swift/include -Iinclude -I/home/wdillon/build/Ninja-ReleaseAssert/llvm-linux-armv7/include -I/home/wdillon/llvm/include -I/home/wdillon/build/Ninja-ReleaseAssert/llvm-linux-armv7/tools/clang/include -I/home/wdillon/llvm/tools/clang/include -I/home/wdillon/cmark/src -I/home/wdillon/build/Ninja-ReleaseAssert/cmark-linux-armv7/src -UNDEBUG -fno-exceptions -fno-rtti -Wglobal-constructors -Wexit-time-destructors -target arm-unknown-linux-gnueabihf -isysroot / -O2 -g0 -UNDEBUG -MMD -MT stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/LibcShims.cpp.o -MF "stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/LibcShims.cpp.o.d" -o stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/LibcShims.cpp.o -c /home/wdillon/swift/stdlib/public/stubs/LibcShims.cpp
/home/wdillon/swift/stdlib/public/stubs/LibcShims.cpp:24:1: error: static_assert failed "__swift_ssize_t is wrong"
static_assert(std::is_same<ssize_t, swift::__swift_ssize_t>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

Now, the sizes match (4 bytes each), but the std::is_same() function says no. I grep’d the clang codebase for the definition of ssize_t, and it seems like it’s a ‘long’ whereas the swift_ssize_t is a 'long int’. I looked into the LibcShims a bit, and the expectation is that the definition in the header is not universally correct, and will be checked:

// This declaration is not universally correct. We verify its correctness for
// the current platform in the runtime code.
typedef long int __swift_ssize_t;

And it is thusly (in LibcShims.cpp):

static_assert(std::is_same<ssize_t, swift::__swift_ssize_t>::value, "__swift_ssize_t is wrong”);

What’s less clear is the mechanism with which I am to change this definition in a way that doesn’t mess-up other platforms.

Any thoughts and ideas are welcome!
Cheers,
- Will

Hi William,

Hi all,

I’ve been working on trying to get Swift to compile on ARMv7 (armv7l
specifically, not sure if other variants will work as well). I’ve gotten
pretty far, but I ran a cross an issue that has me a little confused. For
convenience, here’s the bug that has some of my messages in the comments:
[SR-40] Port Swift to Linux on Raspberry Pi · Issue #5337 · apple/swift-package-manager · GitHub and here’s my Github fork if you want
to play along at home: https://github.com/hpux735/swift By the way, I’m
compiling on an Nvidia tegra TK2 development board with 2GB of ram and a
25GB swapfile on an external SSD. This brings native compile times down to
reasonable levels. I was compiling on the BeagleBone Black formerly, and
that was painful (like over a day for LLVM).

So far, cmark and llvm compile just fine (no surprise there), and swift
gets pretty far along. The weird issue, which will certainly expose my
weakness in C++ and large build systems, is that the swift_ssize_t doesn’t
match ssize_t.

[6/61] Building CXX object
stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/Stubs.cpp.o
FAILED: /usr/bin/clang++ -DGTEST_HAS_RTTI=0 -D_DEBUG
-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
-fno-stack-protector -fPIC -fvisibility-inlines-hidden -Wall -W
-Wno-unused-parameter -Wwrite-strings -Wcast-qual
-Wmissing-field-initializers -Wcovered-switch-default -Wnon-virtual-dtor
-Werror=date-time -std=c++11 -fcolor-diagnostics -ffunction-sections
-fdata-sections -Wdocumentation -Wimplicit-fallthrough -Wunreachable-code
-Woverloaded-virtual -O3 -Istdlib/public/stubs
-I/home/wdillon/swift/stdlib/public/stubs -I/home/wdillon/swift/include
-Iinclude
-I/home/wdillon/build/Ninja-ReleaseAssert/llvm-linux-armv7/include
-I/home/wdillon/llvm/include
-I/home/wdillon/build/Ninja-ReleaseAssert/llvm-linux-armv7/tools/clang/include
-I/home/wdillon/llvm/tools/clang/include -I/home/wdillon/cmark/src
-I/home/wdillon/build/Ninja-ReleaseAssert/cmark-linux-armv7/src -UNDEBUG
-fno-exceptions -fno-rtti -Wglobal-constructors -Wexit-time-destructors
-target arm-unknown-linux-gnueabihf -isysroot / -O2 -g0 -UNDEBUG -MMD -MT
stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/LibcShims.cpp.o
-MF
"stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/LibcShims.cpp.o.d"
-o
stdlib/public/stubs/CMakeFiles/swiftStdlibStubs-linux-armv7.dir/LibcShims.cpp.o
-c /home/wdillon/swift/stdlib/public/stubs/LibcShims.cpp
/home/wdillon/swift/stdlib/public/stubs/LibcShims.cpp:24:1: error:
static_assert failed "__swift_ssize_t is wrong"
static_assert(std::is_same<ssize_t, swift::__swift_ssize_t>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

Now, the sizes match (4 bytes each), but the std::is_same() function says
no. I grep’d the clang codebase for the definition of ssize_t, and it
seems like it’s a ‘long’ whereas the swift_ssize_t is a 'long int’.

'long' and 'long int' are the same type.

Try preprocessing the following program with 'clang -E' and check how the
type is defined:

#include <unistd.h>
#include <sys/types.h>

I looked into the LibcShims a bit, and the expectation is that the
definition in the header is not universally correct, and will be checked:

// This declaration is not universally correct. We verify its correctness
for
// the current platform in the runtime code.
typedef long int __swift_ssize_t;

And it is thusly (in LibcShims.cpp):

static_assert(std::is_same<ssize_t, swift::__swift_ssize_t>::value,
"__swift_ssize_t is wrong”);

What’s less clear is the mechanism with which I am to change this
definition in a way that doesn’t mess-up other platforms.

Use #if:

if defined(__linux__) && defined(__arm__)
...
#else
...
#endif

To find the specific macro names to check for, dump the predefines buffer
and find an appropriate one (although I think __linux__ and __arm__ are
correct):

echo "" | clang -x c++ -std=c++11 - -dM -E

Dmitri

···

On Tue, Dec 8, 2015 at 8:00 PM, William Dillon via swift-dev < swift-dev@swift.org> wrote:

--
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@gmail.com>*/

Try preprocessing the following program with 'clang -E' and check how the type
is defined:

#include <unistd.h>
#include <sys/types.h>

It's probably defined as `int` as it is on Linux i386:

https://github.com/nwellnhof/swift/commit/1a5962c890e43f115fc5d629a7b2ec108e1f489a#diff-58073e2ae1d7149ac7f3fe3d32dff142

Use #if:

if defined(__linux__) && defined(__arm__)
...
#else
...
#endif

I guess this only works on 32-bit and needs another check for 64-bit. Why isnt't `__swift_ssize_t` simply defined as `ssize_t`? This would avoid this kind of problems.

Nick

···

On 09/12/2015 05:50, Dmitri Gribenko via swift-dev wrote:

Sure enough, it’s all true.

__ssize_t is an int, added the preprocessor conditional, and we’re moving forward.

I have no intention of addressing every issue here, but there is another I have a question about while I’m at it. While linking Swift.o, there is an undefined reference to __mulodi4. I found that __muloti4 is copied from compiler-rt into Stubbs.cpp to avoid new dependencies on compiler-rt in linux. I went ahead and copied __mulodi4 into the same file after __muloti4, but that seems a little hack-y. Is there a better way to get that symbol, and why wasn’t this a problem for x86_64? (also, is this: typedef int di_int __attribute__ ((mode (DI))); an appropriate way to define di_int?)

Even with that hack, I’m still getting undefined references to __multi3 and __divti3.

Thanks!
- Will

···

On Dec 9, 2015, at 3:42 AM, Nick Wellnhofer via swift-dev <swift-dev@swift.org> wrote:

On 09/12/2015 05:50, Dmitri Gribenko via swift-dev wrote:

Try preprocessing the following program with 'clang -E' and check how the type
is defined:

#include <unistd.h>
#include <sys/types.h>

It's probably defined as `int` as it is on Linux i386:

https://github.com/nwellnhof/swift/commit/1a5962c890e43f115fc5d629a7b2ec108e1f489a#diff-58073e2ae1d7149ac7f3fe3d32dff142

Use #if:

if defined(__linux__) && defined(__arm__)
...
#else
...
#endif

I guess this only works on 32-bit and needs another check for 64-bit. Why isnt't `__swift_ssize_t` simply defined as `ssize_t`? This would avoid this kind of problems.

Nick

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Because we can't include Glibc headers in SwiftShims.

Dmitri

···

On Wed, Dec 9, 2015 at 3:42 AM, Nick Wellnhofer via swift-dev <swift-dev@swift.org> wrote:

I guess this only works on 32-bit and needs another check for 64-bit. Why
isnt't `__swift_ssize_t` simply defined as `ssize_t`? This would avoid this
kind of problems.

--
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@gmail.com>*/

It does feel hacky. A better solution would be to link in parts of
compiler-rt, but that involves a lot of plumbing.

Dmitri

···

On Wed, Dec 9, 2015 at 9:43 AM, William Dillon via swift-dev <swift-dev@swift.org> wrote:

I went ahead and copied __mulodi4 into the same file after __muloti4, but that seems a little hack-y.

--
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@gmail.com>*/

I have no intention of addressing every issue here, but there is another I have a question about while I’m at it. While linking Swift.o, there is an undefined reference to __mulodi4. I found that __muloti4 is copied from compiler-rt into Stubbs.cpp to avoid new dependencies on compiler-rt in linux. I went ahead and copied __mulodi4 into the same file after __muloti4, but that seems a little hack-y.

I had the same issues with my proof-of-concept Linux i386 port. I also copied the __mulodi4 implementation from compiler-rt.

Is there a better way to get that symbol, and why wasn’t this a problem for x86_64?

AFAICS, this is a problem for x86_64 Linux. It's not a problem on Apple platforms, because there C++ binaries are linked with compiler-rt instead of the GCC runtime.

(also, is this: typedef int di_int __attribute__ ((mode (DI))); an appropriate way to define di_int?)

I think so.

Even with that hack, I’m still getting undefined references to __multi3 and __divti3.

I fixed that by disabling the __muloti4 implementation on i386 which created the references to __multi3 and __divti3:

https://github.com/nwellnhof/swift/commit/1a5962c890e43f115fc5d629a7b2ec108e1f489a#diff-197db3bb942ecdeff5ddb9e82c59de22

Nick

···

On 09/12/2015 18:43, William Dillon via swift-dev wrote:

Ah, you probably meant why __mulodi4 isn't a problem on x86_64 Linux. I think that's because it's defined by the 64-bit GCC runtime. (clang on Linux uses the GCC runtime AFAIK.)

Nick

···

On 09/12/2015 18:55, Nick Wellnhofer via swift-dev wrote:

Is there a better way to get that symbol, and why wasn’t this a problem for
x86_64?

AFAICS, this is a problem for x86_64 Linux. It's not a problem on Apple
platforms, because there C++ binaries are linked with compiler-rt instead of
the GCC runtime.

Right, libgcc doesn't provide 128-bit integer entry points on 32-bit platforms, and doesn't provide the overflow-checking variant __muloti4 at all AFAIK.

-Joe

···

On Dec 9, 2015, at 10:05 AM, Nick Wellnhofer via swift-dev <swift-dev@swift.org> wrote:

On 09/12/2015 18:55, Nick Wellnhofer via swift-dev wrote:

Is there a better way to get that symbol, and why wasn’t this a problem for
x86_64?

AFAICS, this is a problem for x86_64 Linux. It's not a problem on Apple
platforms, because there C++ binaries are linked with compiler-rt instead of
the GCC runtime.

Ah, you probably meant why __mulodi4 isn't a problem on x86_64 Linux. I think that's because it's defined by the 64-bit GCC runtime. (clang on Linux uses the GCC runtime AFAIK.)

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms. I added another case to the preprocessor conditional for __muloti4, and specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3 references went away.

Then, I went on to the module.map file for bringing in the Glibc headers. I’m trying to think of a way to either remove the architecture specific paths to many of those libraries (they’re now x86_64-linux-gnu, but need to be arm-linux-gnueabihf for arm). I read the modules documentation at http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s possible to have conditionals in there. I’m considering whether it’s a good idea to preprocess that file in some way to fill them out with the correct paths in the build scripts. I went ahead and changed them all (breaking x86_64 for the time being).

At this point, the compiler and standard library are all built, and I think I have one final issue. In the testing suite, the binaries generated by the swift compiler don’t run. They’re emitting unexpected reloc type errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries: /home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so: unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for testing.

Ideas?
Thanks!
- Will

···

On Dec 9, 2015, at 10:58 AM, Joe Groff via swift-dev <swift-dev@swift.org> wrote:

On Dec 9, 2015, at 10:05 AM, Nick Wellnhofer via swift-dev <swift-dev@swift.org> wrote:

On 09/12/2015 18:55, Nick Wellnhofer via swift-dev wrote:

Is there a better way to get that symbol, and why wasn’t this a problem for
x86_64?

AFAICS, this is a problem for x86_64 Linux. It's not a problem on Apple
platforms, because there C++ binaries are linked with compiler-rt instead of
the GCC runtime.

Ah, you probably meant why __mulodi4 isn't a problem on x86_64 Linux. I think that's because it's defined by the 64-bit GCC runtime. (clang on Linux uses the GCC runtime AFAIK.)

Right, libgcc doesn't provide 128-bit integer entry points on 32-bit platforms, and doesn't provide the overflow-checking variant __muloti4 at all AFAIK.

-Joe
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms. I added another case to the preprocessor conditional for __muloti4, and specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3 references went away.

Then, I went on to the module.map file for bringing in the Glibc headers. I’m trying to think of a way to either remove the architecture specific paths to many of those libraries (they’re now x86_64-linux-gnu, but need to be arm-linux-gnueabihf for arm). I read the modules documentation at http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s possible to have conditionals in there. I’m considering whether it’s a good idea to preprocess that file in some way to fill them out with the correct paths in the build scripts. I went ahead and changed them all (breaking x86_64 for the time being).

Did you try Glibc module: detect location of glibc header files by orobio · Pull Request #282 · apple/swift · GitHub ?

At this point, the compiler and standard library are all built, and I think I have one final issue. In the testing suite, the binaries generated by the swift compiler don’t run. They’re emitting unexpected reloc type errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries: /home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so: unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for testing.

+John for this error.

Dmitri

···

On Wed, Dec 9, 2015 at 3:05 PM, William Dillon via swift-dev <swift-dev@swift.org> wrote:

--
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@gmail.com>*/

Can you make sure you're compiling with the -fPIC flag? This is normally set by CMake depending on the platform, but it's possible that CMake doesn't know about Linux-ARM yet.

Nick

···

On 10/12/2015 00:05, William Dillon via swift-dev wrote:

At this point, the compiler and standard library are all built, and I think I have one final issue. In the testing suite, the binaries generated by the swift compiler don’t run. They’re emitting unexpected reloc type errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries: /home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so: unexpected reloc type 0x03

It would be also helpful if you could find which code contains these
relocations. Try 'objdump -R libswiftCore.so' or 'readelf -r'.

Dmitri

···

On Wed, Dec 9, 2015 at 7:05 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 3:05 PM, William Dillon via swift-dev > <swift-dev@swift.org> wrote:

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms. I added another case to the preprocessor conditional for __muloti4, and specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3 references went away.

Then, I went on to the module.map file for bringing in the Glibc headers. I’m trying to think of a way to either remove the architecture specific paths to many of those libraries (they’re now x86_64-linux-gnu, but need to be arm-linux-gnueabihf for arm). I read the modules documentation at http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s possible to have conditionals in there. I’m considering whether it’s a good idea to preprocess that file in some way to fill them out with the correct paths in the build scripts. I went ahead and changed them all (breaking x86_64 for the time being).

Did you try Glibc module: detect location of glibc header files by orobio · Pull Request #282 · apple/swift · GitHub ?

At this point, the compiler and standard library are all built, and I think I have one final issue. In the testing suite, the binaries generated by the swift compiler don’t run. They’re emitting unexpected reloc type errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries: /home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so: unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for testing.

+John for this error.

--
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@gmail.com>*/

Good point. Another possibility is that it could be that the Swift compiler
is not setting the PIC flag when setting up LLVM for Linux/arm.

This is one of the reasons why isolating the issue to specific symbols
would be very interesting, it would allow us to focus on a specific
object file.

Dmitri

···

On Tue, Dec 15, 2015 at 2:39 AM, Nick Wellnhofer via swift-dev <swift-dev@swift.org> wrote:

On 10/12/2015 00:05, William Dillon via swift-dev wrote:

At this point, the compiler and standard library are all built, and I
think I have one final issue. In the testing suite, the binaries generated
by the swift compiler don’t run. They’re emitting unexpected reloc type
errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not
permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries:
/home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so:
unexpected reloc type 0x03

Can you make sure you're compiling with the -fPIC flag? This is normally set
by CMake depending on the platform, but it's possible that CMake doesn't
know about Linux-ARM yet.

--
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@gmail.com>*/

Hi all,

I think that I’ve found the culprit with linking errors on ARMv7-linux. I was looking at the changes between the SwiftAndroid port, and I noticed an extra flag they added in the AddSwift cmake module: -Wl,-Bsymbolic. I added that to my copy of the module, and re-built swift. I’m now able to compile and run a hello world program:

$ cat hello.swift
print("Hello world!")
$ swiftc hello.swift
$ ./hello
Hello world!
$ uname -s -m
Linux armv7l

-target is not required, and no linker/loader errors!!

I just finished building and testing on linux-x86_64 and mac, and I don’t think I’ve added any regressions. I’m starting to clean up to submit a new pull request to the apple repo. To that end, I had been required to add -target armv7-unknown-linux-gnueabihf to the swiftc invocation while using armv7 as the architecture. Apparently, swiftc is getting a triple from the OS somehow, and that triple has armv7l-unknown-linux-gnueabihf. Because these triples don’t match, I have to force it with -target. What is the desired direction here? I’m happy to leave it armv7l and not have to dig into the triple determination logic, wherever it may live, but I can do that if we want to keep it armv7 everywhere (except for the references to armv7k for watchOS). By the way, at first glance, it seems like foundation will build better using just ‘arm’ or ‘armv7’.

Thoughts/preferences?

Thanks!
- Will

···

On Dec 15, 2015, at 2:52 AM, Dmitri Gribenko via swift-dev <swift-dev@swift.org> wrote:

On Tue, Dec 15, 2015 at 2:39 AM, Nick Wellnhofer via swift-dev > <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

On 10/12/2015 00:05, William Dillon via swift-dev wrote:

At this point, the compiler and standard library are all built, and I
think I have one final issue. In the testing suite, the binaries generated
by the swift compiler don’t run. They’re emitting unexpected reloc type
errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not
permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries:
/home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so:
unexpected reloc type 0x03

Can you make sure you're compiling with the -fPIC flag? This is normally set
by CMake depending on the platform, but it's possible that CMake doesn't
know about Linux-ARM yet.

Good point. Another possibility is that it could be that the Swift compiler
is not setting the PIC flag when setting up LLVM for Linux/arm.

This is one of the reasons why isolating the issue to specific symbols
would be very interesting, it would allow us to focus on a specific
object file.

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@gmail.com <mailto:gribozavr@gmail.com>>*/
_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

Hi all,

I think that I’ve found the culprit with linking errors on ARMv7-linux. I was looking at the changes between the SwiftAndroid port, and I noticed an extra flag they added in the AddSwift cmake module: -Wl,-Bsymbolic. I added that to my copy of the module, and re-built swift. I’m now able to compile and run a hello world program:

$ cat hello.swift
print("Hello world!")
$ swiftc hello.swift
$ ./hello
Hello world!
$ uname -s -m
Linux armv7l

-target is not required, and no linker/loader errors!!

Awesome!

I just finished building and testing on linux-x86_64 and mac, and I don’t think I’ve added any regressions. I’m starting to clean up to submit a new pull request to the apple repo. To that end, I had been required to add -target armv7-unknown-linux-gnueabihf to the swiftc invocation while using armv7 as the architecture. Apparently, swiftc is getting a triple from the OS somehow, and that triple has armv7l-unknown-linux-gnueabihf.

I think we should make sure that autodetection works correctly (that
is, so that using the armv7l autodetected triple does not confuse the
compiler). I think we should make adjustments in the directory names
and everywhere else to ensure that we use 'armv7l' consistently. I'm
asking Tim Northover to confirm that this is the right thing.

Dmitri

···

On Wed, Dec 16, 2015 at 11:55 AM, William Dillon <wdillon@coas.oregonstate.edu> wrote:

--
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@gmail.com>*/

I’m looking at that pull request currently, thanks for the link.

Here is the output of readelf -r for libswiftcore, test.swift (as compiled) and test.swift.

Thanks for looking into this!
- Will

relocatable.tar.bz2 (88.2 KB)

···

On Dec 9, 2015, at 7:14 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 7:05 PM, Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>> wrote:

On Wed, Dec 9, 2015 at 3:05 PM, William Dillon via swift-dev >> <swift-dev@swift.org> wrote:

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms. I added another case to the preprocessor conditional for __muloti4, and specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3 references went away.

Then, I went on to the module.map file for bringing in the Glibc headers. I’m trying to think of a way to either remove the architecture specific paths to many of those libraries (they’re now x86_64-linux-gnu, but need to be arm-linux-gnueabihf for arm). I read the modules documentation at http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s possible to have conditionals in there. I’m considering whether it’s a good idea to preprocess that file in some way to fill them out with the correct paths in the build scripts. I went ahead and changed them all (breaking x86_64 for the time being).

Did you try https://github.com/apple/swift/pull/282 ?

At this point, the compiler and standard library are all built, and I think I have one final issue. In the testing suite, the binaries generated by the swift compiler don’t run. They’re emitting unexpected reloc type errors. It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries: /home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so: unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for testing.

+John for this error.

It would be also helpful if you could find which code contains these
relocations. Try 'objdump -R libswiftCore.so' or 'readelf -r'.

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@gmail.com <mailto:gribozavr@gmail.com>>*/

Here's a relevant line (there are lots, this is just one instance):

003a91cc 0015d403 R_ARM_REL32 003af914 _TMps13GeneratorType

_TMps13GeneratorType ---> protocol descriptor for Swift.GeneratorType

Dmitri

···

On Wed, Dec 9, 2015 at 7:25 PM, William Dillon <william@housedillon.com> wrote:

I’m looking at that pull request currently, thanks for the link.

Here is the output of readelf -r for libswiftcore, test.swift (as compiled)
and test.swift.

Thanks for looking into this!
- Will

On Dec 9, 2015, at 7:14 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 7:05 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 3:05 PM, William Dillon via swift-dev > <swift-dev@swift.org> wrote:

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms.
I added another case to the preprocessor conditional for __muloti4, and
specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3
references went away.

Then, I went on to the module.map file for bringing in the Glibc headers.
I’m trying to think of a way to either remove the architecture specific
paths to many of those libraries (they’re now x86_64-linux-gnu, but need to
be arm-linux-gnueabihf for arm). I read the modules documentation at
http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s
possible to have conditionals in there. I’m considering whether it’s a good
idea to preprocess that file in some way to fill them out with the correct
paths in the build scripts. I went ahead and changed them all (breaking
x86_64 for the time being).

Did you try https://github.com/apple/swift/pull/282 ?

At this point, the compiler and standard library are all built, and I think
I have one final issue. In the testing suite, the binaries generated by the
swift compiler don’t run. They’re emitting unexpected reloc type errors.
It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for
use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries:
/home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so:
unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for
testing.

+John for this error.

It would be also helpful if you could find which code contains these
relocations. Try 'objdump -R libswiftCore.so' or 'readelf -r'.

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@gmail.com>*/

--
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@gmail.com>*/

Yep. I see that are a few of those in there (1700 and change). When it comes to linking and ELF, I am fumbling in the dark a bit. With the hope of getting some context, I decided to see whether R_ARM_REL32 is used in any other shared libraries in the system; it is not. It seems as though R_ARM_REL32 is not appropriate for use in dynamic libraries, but the generated swift executables are trying to use it that way. I thought I remembered that swift binaries are only capable of static liking for the time being, is that true? Could the problem be as simple as the compiler that I built on ARM is trying to emit executables expecting dynamic linking when that’s not supported yet?

I’m building the debug variant (I’ve been using release due to the memory requirements of linking debug) now to see if it does the same thing. I don’t understand why the arch. change would cause differences here.

By the way, that pull request for module.map looks perfect. I’ll have to wait for it to merge in before I can prepare any kind of pull request of my own. I think that is the only thing that breaks other builds that I don’t know how to fix on my own.

Thanks,
- Will

···

On Dec 9, 2015, at 8:23 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

Here's a relevant line (there are lots, this is just one instance):

003a91cc 0015d403 R_ARM_REL32 003af914 _TMps13GeneratorType

_TMps13GeneratorType ---> protocol descriptor for Swift.GeneratorType

Dmitri

On Wed, Dec 9, 2015 at 7:25 PM, William Dillon <william@housedillon.com> wrote:

I’m looking at that pull request currently, thanks for the link.

Here is the output of readelf -r for libswiftcore, test.swift (as compiled)
and test.swift.

Thanks for looking into this!
- Will

On Dec 9, 2015, at 7:14 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 7:05 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 3:05 PM, William Dillon via swift-dev >> <swift-dev@swift.org> wrote:

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms.
I added another case to the preprocessor conditional for __muloti4, and
specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3
references went away.

Then, I went on to the module.map file for bringing in the Glibc headers.
I’m trying to think of a way to either remove the architecture specific
paths to many of those libraries (they’re now x86_64-linux-gnu, but need to
be arm-linux-gnueabihf for arm). I read the modules documentation at
http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s
possible to have conditionals in there. I’m considering whether it’s a good
idea to preprocess that file in some way to fill them out with the correct
paths in the build scripts. I went ahead and changed them all (breaking
x86_64 for the time being).

Did you try https://github.com/apple/swift/pull/282 ?

At this point, the compiler and standard library are all built, and I think
I have one final issue. In the testing suite, the binaries generated by the
swift compiler don’t run. They’re emitting unexpected reloc type errors.
It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for
use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries:
/home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so:
unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for
testing.

+John for this error.

It would be also helpful if you could find which code contains these
relocations. Try 'objdump -R libswiftCore.so' or 'readelf -r'.

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@gmail.com>*/

--
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@gmail.com>*/

Yep. I see that are a few of those in there (1700 and change). When it comes to linking and ELF, I am fumbling in the dark a bit. With the hope of getting some context, I decided to see whether R_ARM_REL32 is used in any other shared libraries in the system; it is not. It seems as though R_ARM_REL32 is not appropriate for use in dynamic libraries, but the generated swift executables are trying to use it that way. I thought I remembered that swift binaries are only capable of static liking for the time being, is that true? Could the problem be as simple as the compiler that I built on ARM is trying to emit executables expecting dynamic linking when that’s not supported yet?

We use relative references to symbols in the conformance table to avoid the need for the dynamic linker to eagerly resolve relocations. These should be wholly internal to the image, though, and resolvable by the static linker. I'm not sure why they'd persist to dynamic linking time like this.

-Joe

···

On Dec 10, 2015, at 9:29 AM, William Dillon <william@housedillon.com> wrote:

I’m building the debug variant (I’ve been using release due to the memory requirements of linking debug) now to see if it does the same thing. I don’t understand why the arch. change would cause differences here.

By the way, that pull request for module.map looks perfect. I’ll have to wait for it to merge in before I can prepare any kind of pull request of my own. I think that is the only thing that breaks other builds that I don’t know how to fix on my own.

Thanks,
- Will

On Dec 9, 2015, at 8:23 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

Here's a relevant line (there are lots, this is just one instance):

003a91cc 0015d403 R_ARM_REL32 003af914 _TMps13GeneratorType

_TMps13GeneratorType ---> protocol descriptor for Swift.GeneratorType

Dmitri

On Wed, Dec 9, 2015 at 7:25 PM, William Dillon <william@housedillon.com> wrote:

I’m looking at that pull request currently, thanks for the link.

Here is the output of readelf -r for libswiftcore, test.swift (as compiled)
and test.swift.

Thanks for looking into this!
- Will

On Dec 9, 2015, at 7:14 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 7:05 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Wed, Dec 9, 2015 at 3:05 PM, William Dillon via swift-dev >>> <swift-dev@swift.org> wrote:

Nick was correct in noting that __muloti4 wasn’t needed on 32-bit platforms.
I added another case to the preprocessor conditional for __muloti4, and
specified __arm__ and __linux__ for mulodi4. The __multi3 and __divti3
references went away.

Then, I went on to the module.map file for bringing in the Glibc headers.
I’m trying to think of a way to either remove the architecture specific
paths to many of those libraries (they’re now x86_64-linux-gnu, but need to
be arm-linux-gnueabihf for arm). I read the modules documentation at
http://clang.llvm.org/docs/Modules.html and it doesn’t look like it’s
possible to have conditionals in there. I’m considering whether it’s a good
idea to preprocess that file in some way to fill them out with the correct
paths in the build scripts. I went ahead and changed them all (breaking
x86_64 for the time being).

Did you try https://github.com/apple/swift/pull/282 ?

At this point, the compiler and standard library are all built, and I think
I have one final issue. In the testing suite, the binaries generated by the
swift compiler don’t run. They’re emitting unexpected reloc type errors.
It appears that reolc type 0x03 is R_ARM_REL32 which is not permitted for
use with shared libraries:

CollectionOfOne.swift.tmp/a.out: error while loading shared libraries:
/home/wdillon/build/Ninja-ReleaseAssert/swift-linux-armv7/lib/swift/linux/libswiftCore.so:
unexpected reloc type 0x03

This also happens with small example swift programs that I’ve written for
testing.

+John for this error.

It would be also helpful if you could find which code contains these
relocations. Try 'objdump -R libswiftCore.so' or 'readelf -r'.

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@gmail.com>*/

--
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@gmail.com>*/