Skip to content
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

Support LLVM 11.0 #9829

Merged
merged 7 commits into from
Jan 6, 2021
Merged

Support LLVM 11.0 #9829

merged 7 commits into from
Jan 6, 2021

Conversation

bcardiff
Copy link
Member

@bcardiff bcardiff commented Oct 14, 2020

Closes #9809

Pending unresolved issue #9809 (comment)

src/llvm/lib_llvm.cr Outdated Show resolved Hide resolved
Since LLVM 8 there is progress towards "opaque pointer types". The build_call and build_invoke methods are deprecated and the new alternatives should be used. 

These alternative require passing the function type also as an argument.

Since LLVM 9 there is a FunctionCallee structure that wrap these two values.

Eventually the Crystal LLVM::Function could be replaced by a LLVM::FunctionCallee. That is delayed until the oldest support LLVM version is bumped to 9 to avoid additional mess.
Expose LibLLVM.build_call and LibLLVM.build_invoke on LLVM < 11.0

Expose LibLLVM.build_call2 and LibLLVM.build_invoke2 on LLVM >= 8.0

Use opaque pointers alternatives in llvm_ext.cc and in LLVM::Builder for LLVM >= 8.0 since they are available from that version.
@bcardiff
Copy link
Member Author

Ok, the support for llvm 11 is ready for review.

There 1 std spec failing when running against llvm 11.

$ bin/crystal run spec/std/data/collect_within_ensure --release
Using compiled compiler at .build/crystal
Unhandled exception: Oh no! (Exception)
Program received and didn't handle signal ILL (4)

But when run without debug information if works fine.

$ bin/crystal run spec/std/data/collect_within_ensure --release --no-debug
Using compiled compiler at .build/crystal
Unhandled exception: Oh no! (Exception)
  from raise<Exception>:NoReturn
  from raise<String>:NoReturn
  from __crystal_main
  from main

When I use lldb I get the following.

$ bin/crystal build spec/std/data/collect_within_ensure --release
$ ./collect_within_ensure
Illegal instruction: 4
$ lldb ./collect_within_ensure 
(lldb) run
Process 89525 launched: '.../crystal/master/collect_within_ensure' (x86_64)
collect_within_ensure was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 89525 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x0000000100019e71 collect_within_ensure`read_attribute_value at info.cr:123:11 [opt]
   120          when FORM::String
   121            @io.gets('\0', chomp: true).to_s
   122          when FORM::Strp
-> 123            read_ulong
   124          when FORM::Indirect
   125            form = FORM.new(DWARF.read_unsigned_leb128(@io))
   126            read_attribute_value(form)
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x0000000100019e71 collect_within_ensure`read_attribute_value at info.cr:123:11 [opt]
    frame #1: 0x000000010000f82e collect_within_ensure`read_dwarf_sections at info.cr:50:23 [opt]
    frame #2: 0x0000000100002990 collect_within_ensure`__crystal_main [inlined] load_dwarf_impl at mach_o.cr:13:5 [opt]
    frame #3: 0x000000010000298b collect_within_ensure`__crystal_main [inlined] load_dwarf at dwarf.cr:15 [opt]
    frame #4: 0x0000000100002982 collect_within_ensure`__crystal_main at kernel.cr:530 [opt]
    frame #5: 0x0000000100004064 collect_within_ensure`main [inlined] main_user_code at main.cr:105:5 [opt]
    frame #6: 0x000000010000405c collect_within_ensure`main [inlined] main at main.cr:91 [opt]
    frame #7: 0x0000000100004041 collect_within_ensure`main at main.cr:114 [opt]
    frame #8: 0x00007fff77cbc3d5 libdyld.dylib`start + 1

(lldb) disassemble --frame
... stripped ...
    0x100019e1c <+2060>: callq  0x1000061a0               ; interpolation at string.cr:5171
    0x100019e21 <+2065>: movq   %rax, %rdi
    0x100019e24 <+2068>: callq  0x1000035c0               ; raise at raise.cr:229
    0x100019e29 <+2073>: movq   0x50(%r14), %rdi
    0x100019e2d <+2077>: cmpb   $0x1, 0x38(%r14)
    0x100019e32 <+2082>: jne    0x100019e45               ; <+2101> [inlined] read_ulong + 28 at info.cr:123
    0x100019e34 <+2084>: movb   $0x1, %al
    0x100019e36 <+2086>: testb  %al, %al
    0x100019e38 <+2088>: je     0x100019e4b               ; <+2107> at info.cr
    0x100019e3a <+2090>: leaq   -0x38(%rbp), %rcx
    0x100019e3e <+2094>: movl   $0x8, %esi
    0x100019e43 <+2099>: jmp    0x100019e59               ; <+2121> [inlined] read_ulong + 5 at info.cr:123
    0x100019e45 <+2101>: movb   $0x1, %al
    0x100019e47 <+2103>: testb  %al, %al
    0x100019e49 <+2105>: jne    0x100019e50               ; <+2112> at info.cr
    0x100019e4b <+2107>: callq  0x1000030e0               ; __crystal_raise_overflow at raise.cr:239
    0x100019e50 <+2112>: leaq   -0x38(%rbp), %rcx
    0x100019e54 <+2116>: movl   $0x4, %esi
    0x100019e59 <+2121>: xorl   %edx, %edx
    0x100019e5b <+2123>: callq  0x100012dd0               ; read_fully? at io.cr:517
    0x100019e60 <+2128>: testl  %eax, %eax
    0x100019e62 <+2130>: jne    0x100019e71               ; <+2145> at info.cr:123:11
    0x100019e64 <+2132>: callq  0x100013ac0               ; new at error.cr:16
    0x100019e69 <+2137>: movq   %rax, %rdi
    0x100019e6c <+2140>: callq  0x100013b40               ; raise at raise.cr:191
->  0x100019e71 <+2145>: ud2 

I'm not sure if something is getting wrongly optimized and end up generating an ud2 instruction.

So --release builds with llvm might require an additional --no-debug if this is merged.

This affects Linux and Darwin.

@bcardiff bcardiff marked this pull request as ready for review December 21, 2020 20:44
@bcardiff bcardiff removed the pr:wip label Dec 21, 2020
@bcardiff
Copy link
Member Author

bcardiff commented Jan 5, 2021

I iterated a bit more to get rid of one more deprecation ahead of time. Improved a bit how dwarf information is loaded to avoid reloading it.

The underlying issue pointed in #9829 (comment) smells like an llvm optimization issue to me. The best I could get the hack/workaround submitted. With that code there the issue is gone in Linux and Darwin.

So if I can have another review we can claim llvm 11 support I guess.

The bonus in this PR is that if the load_dwarf fails (due to some runtime exception) the program will not crash, it will report the error on start, and the runtime backtraces will have no dwarf information.

src/llvm/lib_llvm.cr Outdated Show resolved Hide resolved
@bcardiff bcardiff merged commit 47f8403 into crystal-lang:master Jan 6, 2021
@bcardiff bcardiff added this to the 1.0.0 milestone Jan 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LLVM 11 support
4 participants