jacobly0 / llvm-project

This fork of the canonical git mirror of the LLVM subversion repository adds (e)Z80 targets. Please refer to the wiki for important build instructions.
https://github.com/jacobly0/llvm-project/wiki
123 stars 15 forks source link

Figure out what's needed to support `rustc` #15

Closed elfprince13 closed 2 years ago

elfprince13 commented 3 years ago

Rust seems like an attractive language to support on TI Calculators (and other (e)Z80 platforms):

Therefore, I'm opening this issue to try and get the discussion moving forward!

tari commented 3 years ago

It's documented in the rustc dev guide: https://rustc-dev-guide.rust-lang.org/building/new-target.html

elfprince13 commented 3 years ago

Thanks @tari!

@jacobly0 - do you have a thread somewhere tracking progress your backends, and what should be expected to work/not work? I'm assuming that if TI Planet's Project Builder now supports C++17 / clang, things are in a decent shape?

adriweb commented 3 years ago

TI-Planet's PB is just using the llvm branch of the toolchain, but yes there hasn't been much trouble lately, so it's in pretty good shape I'd say. We're not necessarily far from a releasable state, compiler+toolchain wise.

mrk-its commented 3 years ago

You may try to compile rust code as described here: http://forum.6502.org/viewtopic.php?p=84048#p84048

6502 backend is very incomplete yet, but I was able to produce working executable this way. The trick is to compile rust code to llvm-ir first (.ll file) and then link it using your llvm fork.

Serentty commented 3 years ago

I was able to build a crate using Cargo and then use this method to have Clang compile and link all of the IR files. Unfortunately this means I still don't have access to the core library. There's also the issue that all I can figure out how to get is assembly in GAS syntax which I don't know of any Z80 assembler for. Still, it's fascinating to read through the generated code.

elfprince13 commented 3 years ago

@Serentty - which method did you try? The one linked by @tari sounds like it should be able to produce a cross-compiler that can handle core too?

Serentty commented 3 years ago

I tried that. I followed along with the changes made by @mrk-its to make a Rust compiler for the 6502 in his form, but for the Z80 instead. But unfortunately, I just ended up getting LLVM to segfault when I tried that. So I just wrote a custom JSON target specification (telling it that it was ARM, but changing all the data sizes to match the Z80), got it to generate IR, and then fed that into Clang.

dtomvan commented 3 years ago

I tried compiling core from the rust stdlib for the ti-84: here

However, llc outputs this:

tools/llc: /usr/lib/libtinfo.so.6: no version information available (required by tools/llc)
LLVM ERROR: unable to translate instruction: ret (in function: _ZN4core6result19Result$LT$T$C$E$GT$6unwrap17h902768c9e7854d83E)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: tools/llc incremental/ti_84_poc-a6bfe995eb836153.ll -o ./incremental/ti_84_poc.s
1.      Running pass 'Function Pass Manager' on module 'incremental/ti_84_poc-a6bfe995eb836153.ll'.
2.      Running pass 'IRTranslator' on function '@"_ZN4core6result19Result$LT$T$C$E$GT$6unwrap17h902768c9e7854d83E"'
 #0 0x000000000166c653 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (tools/llc+0x166c653)
 #1 0x000000000166a57e llvm::sys::RunSignalHandlers() (tools/llc+0x166a57e)
 #2 0x000000000166caff SignalHandler(int) (tools/llc+0x166caff)
 #3 0x00007feb2d964870 __restore_rt (/usr/lib/libpthread.so.0+0x13870)
 #4 0x00007feb2d5c4d22 raise (/usr/lib/libc.so.6+0x3cd22)
 #5 0x00007feb2d5ae862 abort (/usr/lib/libc.so.6+0x26862)
 #6 0x00000000015e9919 (tools/llc+0x15e9919)
 #7 0x00000000015e9937 (tools/llc+0x15e9937)
 #8 0x00000000018c4a4a (tools/llc+0x18c4a4a)
 #9 0x00000000018d5e88 llvm::IRTranslator::runOnMachineFunction(llvm::MachineFunction&) (tools/llc+0x18d5e88)
#10 0x0000000000bbc26e llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (tools/llc+0xbbc26e)
#11 0x0000000000f68f5d llvm::FPPassManager::runOnFunction(llvm::Function&) (tools/llc+0xf68f5d)
#12 0x0000000000f6ecf3 llvm::FPPassManager::runOnModule(llvm::Module&) (tools/llc+0xf6ecf3)
#13 0x0000000000f6959f llvm::legacy::PassManagerImpl::run(llvm::Module&) (tools/llc+0xf6959f)
#14 0x000000000081e683 main (tools/llc+0x81e683)
#15 0x00007feb2d5afb25 __libc_start_main (/usr/lib/libc.so.6+0x27b25)
#16 0x0000000000819eae _start (tools/llc+0x819eae)
/tmp/tomvd/fsio/CHns2yiOPZ.sh: line 5: 67714 Aborted                 (core dumped) tools/llc $(find incremental -name ${CARGO_MAKE_PROJECT_NAME}-*.ll) -o ./incremental/${CARGO_MAKE_PROJECT_NAME}.s
dtomvan commented 3 years ago

The person I forked this from to try out called it "a proof of concept" but then I start using the core library (I updated the compiler to the latest commit, see my fork) and it does not work properly. LLVM seems to not understand this ret instruction.

adriweb commented 3 years ago

The asm generated by the compiler, when targeting (e)z80, is made for the fasmg assembler with specific support for that target, see for example how it's used in here: https://github.com/CE-Programming/toolchain

dtomvan commented 3 years ago

Which compiler are you talking about exactly? rustc or llc

Edit: maybe related to this? https://github.com/rust-lang/rust/issues/58567

jacobly0 commented 3 years ago

That error means that the calling convention code didn't support however the function was trying to return.

sbechet commented 3 years ago

Hello,

maybe it can help as an example: https://github.com/rust-lang/rust/pull/88321

jacobly0 commented 2 years ago

Closing because I don't have plans to work on this, feel free to continue discussing or reopen if someone wants to have this issue assigned to them.

TrevorCow commented 1 year ago

I've been trying my hand at this and so far I've started with rust 1.65 as a base, since it has the most similar LLVM version to this project, and then merged this z80 branch into that one and rebuilt rust from src. All the steps work up until trying to transpile the LLVM bytecode into ASM (I think that's what it's doing? I'm still new to working with low-level LLVM forgive me if I'm misnaming or misunderstanding something). Wondering if I could get someone help that knows more about LLVM. It seems it's failing at translating a call instruction that has a non-primitive type.

Here is an example of the LLVM bytecode I'm trying to compile:

; ModuleID = 'calculator_snake-bf64b38161ffb5f6.3wbn5zfgu27wxvpa.rcgu.o'
source_filename = "3wbn5zfgu27wxvpa"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "ez80"

%"calculator_snake::ffi::types::ti_uint" = type { [3 x i8] }

@alloc1 = private unnamed_addr constant <{ [21 x i8] }> <{ [21 x i8] c"Running Screen Test \00" }>, align 1
@alloc2 = private unnamed_addr constant <{ [38 x i8] }> <{ [38 x i8] c"Press Enter to progress to next test \00" }>, align 1

; Function Attrs: nounwind
define dso_local void @main() unnamed_addr #0 {
start:
  %0 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc1) #1
  tail call void @os_NewLine() #1
  %1 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc2) #1
  br label %bb6

bb6:                                              ; preds = %bb6, %start
  %2 = tail call noundef zeroext i16 @os_GetKey() #1, !range !1
  %.not = icmp eq i16 %2, 5
  br i1 %.not, label %bb10, label %bb6

bb10:                                             ; preds = %bb6
  tail call void @os_ClrLCD() #1
  ret void
}

; Function Attrs: nounwind
declare dso_local %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr) unnamed_addr #0

; Function Attrs: nounwind
declare dso_local void @os_NewLine() unnamed_addr #0

; Function Attrs: nounwind
declare dso_local noundef zeroext i16 @os_GetKey() unnamed_addr #0

; Function Attrs: nounwind
declare dso_local void @os_ClrLCD() unnamed_addr #0

attributes #0 = { nounwind "target-cpu"="generic" }
attributes #1 = { nounwind }

!llvm.module.flags = !{!0}

!0 = !{i32 1, !"LTOPostLink", i32 1}
!1 = !{i16 1, i16 252}

Changing the

  %0 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc1) #1
  tail call void @os_NewLine() #1
  %1 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc2) #1

to

  %0 = tail call i32 @os_PutStrFull(ptr nonnull @alloc1) #1
  tail call void @os_NewLine() #1
  %1 = tail call i32 @os_PutStrFull(ptr nonnull @alloc2) #1

Compiles successfully (of course being actually incorrect)

Here is the full stack trace of the failed compile:

LLVM ERROR: unable to translate instruction: call (in function: main)
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: C:/Dev/CLionProjects/rust_z80_llvm/build/x86_64-pc-windows-gnu/llvm/bin/llc ./atest_incremental/test_screen-6da35421ec774f08.ll -o ./atest_incremental/test_screen.s
1.      Running pass 'Function Pass Manager' on module './atest_incremental/test_screen-6da35421ec774f08.ll'.
2.      Running pass 'IRTranslator' on function '@main'
Exception Code: 0xC000001D
 #0 0x00007ff722058e70 HandleAbort.cold (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x2a08e70)
 #1 0x00007ffb89d2e0ac (C:\Windows\System32\msvcrt.dll+0x2e0ac)
 #2 0x00007ffb89d3255b (C:\Windows\System32\msvcrt.dll+0x3255b)
 #3 0x00007ff722058d65 llvm::report_fatal_error(llvm::Twine const&, bool) (.cold) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x2a08d65)
 #4 0x00007ff71f94917d reportTranslationError(llvm::MachineFunction&, llvm::TargetPassConfig const&, llvm::OptimizationRemarkEmitter&, llvm::OptimizationRemarkMissed&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x2f917d)
 #5 0x00007ff720550a35 llvm::IRTranslator::runOnMachineFunction(llvm::MachineFunction&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0xf00a35)
 #6 0x00007ff720e30cc8 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x17e0cc8)
 #7 0x00007ff7206a72aa llvm::FPPassManager::runOnFunction(llvm::Function&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x10572aa)
 #8 0x00007ff7206a6f53 llvm::FPPassManager::runOnModule(llvm::Module&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x1056f53)
 #9 0x00007ff72125c9c5 llvm::legacy::PassManagerImpl::run(llvm::Module&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x1c0c9c5)
#10 0x00007ff71f71975d compileModule(char**, llvm::LLVMContext&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0xc975d)
#11 0x00007ff721fbcf7a main (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x296cf7a)
#12 0x00007ff71f6512ee __tmainCRTStartup C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:268:8
#13 0x00007ff71f651406 .l_start C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:190:3
#14 0x00007ffb8adc257d (C:\Windows\System32\KERNEL32.DLL+0x1257d)
#15 0x00007ffb8baeaa58 (C:\Windows\SYSTEM32\ntdll.dll+0x5aa58)

Any help would be greatly appreciated!

boondocklabs commented 7 months ago

I've been trying my hand at this and so far I've started with rust 1.65 as a base, since it has the most similar LLVM version to this project, and then merged this z80 branch into that one and rebuilt rust from src. All the steps work up until trying to transpile the LLVM bytecode into ASM (I think that's what it's doing? I'm still new to working with low-level LLVM forgive me if I'm misnaming or misunderstanding something). Wondering if I could get someone help that knows more about LLVM. It seems it's failing at translating a call instruction that has a non-primitive type.

Here is an example of the LLVM bytecode I'm trying to compile:

; ModuleID = 'calculator_snake-bf64b38161ffb5f6.3wbn5zfgu27wxvpa.rcgu.o'
source_filename = "3wbn5zfgu27wxvpa"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "ez80"

%"calculator_snake::ffi::types::ti_uint" = type { [3 x i8] }

@alloc1 = private unnamed_addr constant <{ [21 x i8] }> <{ [21 x i8] c"Running Screen Test \00" }>, align 1
@alloc2 = private unnamed_addr constant <{ [38 x i8] }> <{ [38 x i8] c"Press Enter to progress to next test \00" }>, align 1

; Function Attrs: nounwind
define dso_local void @main() unnamed_addr #0 {
start:
  %0 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc1) #1
  tail call void @os_NewLine() #1
  %1 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc2) #1
  br label %bb6

bb6:                                              ; preds = %bb6, %start
  %2 = tail call noundef zeroext i16 @os_GetKey() #1, !range !1
  %.not = icmp eq i16 %2, 5
  br i1 %.not, label %bb10, label %bb6

bb10:                                             ; preds = %bb6
  tail call void @os_ClrLCD() #1
  ret void
}

; Function Attrs: nounwind
declare dso_local %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr) unnamed_addr #0

; Function Attrs: nounwind
declare dso_local void @os_NewLine() unnamed_addr #0

; Function Attrs: nounwind
declare dso_local noundef zeroext i16 @os_GetKey() unnamed_addr #0

; Function Attrs: nounwind
declare dso_local void @os_ClrLCD() unnamed_addr #0

attributes #0 = { nounwind "target-cpu"="generic" }
attributes #1 = { nounwind }

!llvm.module.flags = !{!0}

!0 = !{i32 1, !"LTOPostLink", i32 1}
!1 = !{i16 1, i16 252}

Changing the

  %0 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc1) #1
  tail call void @os_NewLine() #1
  %1 = tail call %"calculator_snake::ffi::types::ti_uint" @os_PutStrFull(ptr nonnull @alloc2) #1

to

  %0 = tail call i32 @os_PutStrFull(ptr nonnull @alloc1) #1
  tail call void @os_NewLine() #1
  %1 = tail call i32 @os_PutStrFull(ptr nonnull @alloc2) #1

Compiles successfully (of course being actually incorrect)

Here is the full stack trace of the failed compile:

LLVM ERROR: unable to translate instruction: call (in function: main)
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: C:/Dev/CLionProjects/rust_z80_llvm/build/x86_64-pc-windows-gnu/llvm/bin/llc ./atest_incremental/test_screen-6da35421ec774f08.ll -o ./atest_incremental/test_screen.s
1.      Running pass 'Function Pass Manager' on module './atest_incremental/test_screen-6da35421ec774f08.ll'.
2.      Running pass 'IRTranslator' on function '@main'
Exception Code: 0xC000001D
 #0 0x00007ff722058e70 HandleAbort.cold (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x2a08e70)
 #1 0x00007ffb89d2e0ac (C:\Windows\System32\msvcrt.dll+0x2e0ac)
 #2 0x00007ffb89d3255b (C:\Windows\System32\msvcrt.dll+0x3255b)
 #3 0x00007ff722058d65 llvm::report_fatal_error(llvm::Twine const&, bool) (.cold) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x2a08d65)
 #4 0x00007ff71f94917d reportTranslationError(llvm::MachineFunction&, llvm::TargetPassConfig const&, llvm::OptimizationRemarkEmitter&, llvm::OptimizationRemarkMissed&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x2f917d)
 #5 0x00007ff720550a35 llvm::IRTranslator::runOnMachineFunction(llvm::MachineFunction&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0xf00a35)
 #6 0x00007ff720e30cc8 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x17e0cc8)
 #7 0x00007ff7206a72aa llvm::FPPassManager::runOnFunction(llvm::Function&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x10572aa)
 #8 0x00007ff7206a6f53 llvm::FPPassManager::runOnModule(llvm::Module&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x1056f53)
 #9 0x00007ff72125c9c5 llvm::legacy::PassManagerImpl::run(llvm::Module&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x1c0c9c5)
#10 0x00007ff71f71975d compileModule(char**, llvm::LLVMContext&) (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0xc975d)
#11 0x00007ff721fbcf7a main (C:\Dev\CLionProjects\rust_z80_llvm\build\x86_64-pc-windows-gnu\llvm\bin\llc.exe+0x296cf7a)
#12 0x00007ff71f6512ee __tmainCRTStartup C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:268:8
#13 0x00007ff71f651406 .l_start C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:190:3
#14 0x00007ffb8adc257d (C:\Windows\System32\KERNEL32.DLL+0x1257d)
#15 0x00007ffb8baeaa58 (C:\Windows\SYSTEM32\ntdll.dll+0x5aa58)

Any help would be greatly appreciated!

Have you made any progress on this? I pulled out my RC2014 today and went to see if there had been any progress on Rust support for the z80