-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Aarch64 support for macOS #10066
Comments
Huh, I thought Apple did their own ABI instead of following AAPCS? |
Before or after 1.0? |
@jhass Yes, it seems their arm64 ABI differs a bit from AAPCS, based on https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms. There's also, the arm64e ABI for ARMV8.3 which could be considered for another issue. |
So that needs implementation too :) https://github.com/crystal-lang/crystal/tree/master/src/llvm/abi |
@jhass don't be so confused it's just a question |
It's gonna be done when somebody finds the motivation and time for it, like everything else in a dominantly open source project ;) |
I will definitely try to implement this since I have access to the hardware. |
@RomainFranceschini did you check if LLVM 10 can be built for ARM? Even if it's not available on brew you can point LLVM_CONFIG to whatever llvm-config binary of your choice.
I think it does. The next binary to try would be the std_spec. If LLVM 10 happens to work we could be in a better shape and check if compiler_spec pass. Whatever you are able to accomplish it will be valuable. Ideally we need to find a way / wait for AArch64 macOS CI to avoid going backwards with its support. |
Maybe somebody will go through the trouble of doing a Linux distribution using Apple's ABI, then we could spin up VMs of that on our existing arm64 machine and it should be close enough, at least for a temporary solution. |
@bcardiff I did several attempts at building LLVM 10 from source, unsuccessfully. It seems checking whether std_spec and compiler_spec pass will have to wait. Regarding the ABI, I tried to review what would need an update from the existing aarch64 implementation, and AFAIU:
I still need to review more thoroughly how arguments passed on the stack should be aligned. |
@RomainFranceschini I was able to move forward with llvm 11 support at #9829 |
Was able to get the compiler building on the M1 Air with @RomainFranceschini's patch using the following steps: LLVM 11 on both ARM and Intel (both from Brew), though compiled bdw-gc, sigfault.o/libcrystal.a w/ just Clang from Xcode 12 Environment
Compiling libcrystal.a
Compiling bdw-gc
Then copy Compiling Crystal for ARM
Unfortunately, I think there's still a missing piece with maybe how the LLVM target triple is being presented or something in the ARM host environment, crystal eval output
EDIT: The answer seems to be yes, the target is being presented differently, as However, the fun stops with an LLVM error. LLVM error on eval
Perhaps someone with a good eye for LLVM IR or ARM asm can spot the issue immediately. |
FTR at crystal/src/compiler/crystal/crystal_path.cr Lines 36 to 44 in be5de4a
|
Yep, adding a print there pointed to the issue. But still unclear as to why the target is "arm-darwin" instead of something expected like "arm64-darwin" or "aarch64-darwin". |
Looked into it further. It all seems to stem from @bcardiff I see we already do some massaging of the default target triple for macOS here: Lines 76 to 84 in 90bbb0a
Would it be reasonable to handle |
On my side I was able to compile
I was not able to move forward with the ABI yet, due to lack of time (and knowledge). |
Interesting... after massaging the LLVM target triple to std_spec
for compiler_spec, just two as well (first one because I had an amd64 build sitting in compiler_spec
|
Hm.. after reading your compiling steps more closely, mine differs a bit. I'll try yours later (probably this week-end) and keep you posted. As for the compiler_spec, compilation fails altogether on my side. |
@maxfierke so, llvm on brew reports arm- , but outside brew reports aarch64-? If so, yes, we hand handle that difference in |
A little bit weirder than that... |
Hm, ok.... then let's go wiith the symlink in lib_c to support arm-darwin and aarch64-darwin . In i686 and i386 we do that. And the rewrite of x86_64-apple-darwin to x86_64-apple-macosx is to deal with darwin/macosx ambiguity and not arch aliases. Maybe is better to use the same solution as in i686/i386 and that's it. |
@bcardiff regardless of the libc issue, the problem with using |
You mean de abi that is used, right?. That can be handled in |
Yes and no. ABI but also architecture flags. However, I did find the source of crystal/src/compiler/crystal/codegen/target.cr Lines 23 to 32 in b632525
Adding a case there for turning Re-ran the test suite, and it mostly agrees 😄 . compiler_spec
std_spec
So, one spec failure all-told, and it's due to Complex being slightly too precise. Hopefully I'll get a chance this weekend to clean this up a bit, and maybe do some stuff to avoid having to pass around all those environment variables. Not supplying them leads to confusing things where a tool or library from Intel-land will be used instead, etc. and it's just not a great experience. But documented here, if folks with the hardware want to try. Patch (additive to what @RomainFranceschini provided for libc): 0001-Interpret-arm64-target-triple-for-Apple-Silicon-prop.patch
|
Awesome work! With @maxfierke 's instructions and @bcardiff 's patch I was able to get working |
@maxfierke nice work! I was able to get same results. Thanks for picking this up. Does that mean we don't have to tweak the ABI after all? I'm confused now 😄 |
I think that's right! AFAICT the arm64 / aarch64 backends and ABI are the same and mean the same thing (aarch64 being then official ARM terminology and arm64 being Apple's terminology) |
We're probably just lucky so far...
https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms |
Yeah it seems that way:
|
Did LLVM fix up the variadic intrinsics? Last time I looked at them they produced complete garbage for AArch64, clang was sporting its own fun implementation and the feedback I got from LLVM devs was "don't use". So for now variadics are disabled in Crystal for AArch64. |
Yeah we have the |
Since Apple now ships ARM processors on their computers, it would be nice to have this platform supported by the Crystal compiler.
Crystal already supports AArch64 for Linux and Darwin on x86_64, so achieve Tier 3 support as a first step should be feasible
without too much work.EDIT: Actually, an ABI for Apple devices should be adapted from the aarch64 one.
A target triple such as
aarch64-apple-darwin
can already be provided to the--target
argument, but the compiler will fail as C bindings for this target are missing.This commit adds the LibC bindings for the target. It is basically a copy-paste-modify from the
x86_64-darwin
target, where the modify part is inspired by what the rust team did (rust-lang/libc#1817) for the same purpose.It seems to be enough to produce simple binaries, maybe it could be the basis for a PR if you think it goes into the right direction.
Cross-compiling
To test whether this slight change is enough for cross-compilation, you need (besides the hardware):
brew
andibrew
respectively.brew install gmp libevent libyaml openssl@1.1 pcre pkg-config bdw-gc
. While homebrew on ARM is not officially supported yet, those compiles fine from sources.ibrew install crystal-lang llvm@9
The next step is to build the modified compiler for x86_64 first (using Homebrew's
crystal
running under Rosetta):LLVM_CONFIG="$(ibrew --prefix)/opt/llvm@9/bin/llvm-config make"
Now we can try to cross-compile programs to ARM using our built from source Crystal.
First, we need to build an ARM version of
libcrystal
:cc -c -o sigfault.o src/ext/sigfault.c/sigfault.c
ar -rcs libcrystal.a sigfault.o
And finally:
./bin/crystal build samples/binary-trees.cr --cross-compile --target aarch64-apple-darwin --release
cc binary-trees.o -o binary-trees -rdynamic -L$(brew --prefix)/opt/bdw-gc/lib -L$(brew --prefix)/opt/pcre/lib -lpcre -lgc -lpthread libcrystalarm.a -L$(brew --prefix)/opt/libevent/lib -levent -liconv -ldl
We can check the architecture with
file ./binary-trees
. My console shows./binary-trees: Mach-O 64-bit executable arm64
The next step would be to cross compile the compiler itself, but it is more difficult as:
The text was updated successfully, but these errors were encountered: