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

LLVM 9.0.x support #3320

Merged
merged 5 commits into from
Dec 23, 2019
Merged

LLVM 9.0.x support #3320

merged 5 commits into from
Dec 23, 2019

Conversation

chalcolith
Copy link
Member

This PR is for compiling with LLVM 9.0.0.

@chalcolith chalcolith added do not merge This PR should not be merged at this time LLVM labels Oct 4, 2019
@chalcolith
Copy link
Member Author

Ok, will do.

@SeanTAllen
Copy link
Member

@kulibali i deleted my comment. decided that it was out of scope and should be done as part of a different PR. only thing i think we need is a changelog for 9.0.0 support when it comes.

@mshockwave
Copy link
Contributor

I'm wondering if there is any list of pending tasks or known bugs on moving toward 9.0?
The only TODO list I found now are the failing tests in some of the build bots.

@chalcolith
Copy link
Member Author

There are failing tests on both Windows and Linux that need to be fixed -- that's the main area that we need help in.

Also the Linux CI setup needs to be updated to build with LLVM 9, but the branch should be rebased before doing that since Sean has been making lots of changes to the CI.

@mshockwave
Copy link
Contributor

I just came up with some small fixes, what is the best way to present them here? Fork and PR maybe?

@chalcolith
Copy link
Member Author

Yes please.

@chalcolith
Copy link
Member Author

Or if the diff is small enough, just include it here.

@mshockwave
Copy link
Contributor

The diff is pretty small so I'll just post it here:

diff --git a/src/libponyc/codegen/codegen.c b/src/libponyc/codegen/codegen.c
index 91bf4b3c..1b89b16d 100644
--- a/src/libponyc/codegen/codegen.c
+++ b/src/libponyc/codegen/codegen.c
@@ -1179,7 +1179,7 @@ void codegen_poptry(compile_t* c)

 void codegen_debugloc(compile_t* c, ast_t* ast)
 {
-  if(ast != NULL)
+  if(ast != NULL && c->frame->di_scope != NULL)
   {
 #if PONY_LLVM < 900
     LLVMSetCurrentDebugLocation2(c->builder,
@@ -1194,9 +1194,7 @@ void codegen_debugloc(compile_t* c, ast_t* ast)
 #if PONY_LLVM < 900
     LLVMSetCurrentDebugLocation2(c->builder, 0, 0, NULL);
 #else
-    LLVMMetadataRef loc = LLVMDIBuilderCreateDebugLocation(c->context, 0, 0,
-      c->frame->di_scope, NULL);
-    LLVMSetCurrentDebugLocation2(c->builder, loc);
+    LLVMSetCurrentDebugLocation2(c->builder, NULL);
 #endif
   }
 } 

@mshockwave
Copy link
Contributor

Here is the root cause:
Previously we use our own wrapper function, LLVMSetCurrentDebugLocation2 (it has the same name as another API in LLVM 9, unfortunately) defined in src/libponyc/codegen/gendebug.cc, to attach the debug MD. That wrapper called DebugLoc::get(...), which will do sanity check on the scope parameter and use an empty DebugLoc (which will not even attached on an instruction actually) instead if the scope is null.

The new API we use, LLVMDIBuilderCreateDebugLocation and LLVMSetCurrentDebugLocation2 in LLVM 9, will not do any sanity check on scope. So it's possible to have a DILocation with a null scope. However, LLVM verify rules doesn't allow null scope, so it bail out.

The fix I just presented will match the behavior of old LLVM: If the scope passed in is null, don't even create a DebugLoc for it.

@chalcolith
Copy link
Member Author

Awesome, thanks @mshockwave!

@chalcolith
Copy link
Member Author

Windows is working now. The one remaining issue is that CodegenTest.TryBlockCantCatchCppExcept fails on Unix, only when it is run in combination with other codegen tests. If it is run by itself it succeeds.

@mshockwave
Copy link
Contributor

Windows is working now. The one remaining issue is that CodegenTest.TryBlockCantCatchCppExcept fails on Unix, only when it is run in combination with other codegen tests. If it is run by itself it succeeds.

Yes I also found that problem. It didn't appear when using LLVM 7 and it's more difficult to debug since most of the stack frames are corrupted when looking into it with a debugger. My rough guess will be something to do with different EH behaviors in LLVM 9 or libunwind.

@lenary
Copy link

lenary commented Nov 18, 2019

@chalcolith
Copy link
Member Author

Building with 9.0.1-rc1 shows the same problem in CodegenTest.TryBlockCantCatchCppExcept on Linux.

@SeanTAllen
Copy link
Member

@kulibali all the tests are passing, what environment are you getting a failure in?

@SeanTAllen
Copy link
Member

O I C, this isn't testing with using 9.0.0, right?

@mshockwave
Copy link
Contributor

@SeanTAllen I don't think any of the bot is using 9.x now

@mshockwave
Copy link
Contributor

So I finally figure out the problem on the CodegenTest.TryBlockCantCatchCppExcept test case. It took me so long (at least a month I would say) to dig out the root cause, which is pretty complicate and required an separate matter to describe it. So I will only put the solution here:

Again, the problem falls inside the LLVM part. Apply the following patch on the release/9.x branch of LLVM and you're good to go.

diff --git a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
index 925049b2a1b..b30628a6448 100644
--- a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
@@ -226,6 +226,7 @@ void SectionMemoryManager::invalidateInstructionCache() {
 }

 SectionMemoryManager::~SectionMemoryManager() {
+  deregisterEHFrames();
   for (MemoryGroup *Group : {&CodeMem, &RWDataMem, &RODataMem}) {
     for (sys::MemoryBlock &Block : Group->AllocatedMem)
       MMapper.releaseMappedMemory(Block);

Just an off-topic story: this bug has been discovered since 2015: https://bugs.llvm.org/show_bug.cgi?id=23991
But it never got fixed due to the rapid-changing architecture of ORC JIT in recent years.

Also, this bug is actually pretty hard to triggered in real-world Pony: you need to invoke PonyJIT several times (at lease 10 times) within single program execution.

@chalcolith
Copy link
Member Author

Awesome! Thanks so much @mshockwave!

@mshockwave
Copy link
Contributor

Update: During my development I temporarily comment out the -static-libstdc++ flag in Makefile:

diff --git a/Makefile-ponyc b/Makefile-ponyc
index 9f031a2d..85875f0c 100644
--- a/Makefile-ponyc
+++ b/Makefile-ponyc
@@ -187,7 +187,7 @@ endif
 ifneq (,$(filter $(link),static llvm-static))
   LLVM_LINKING =--link-static
   ifeq (,$(filter $(OSTYPE),bsd osx))
-    LINKER_FLAGS += -static-libstdc++
+    #LINKER_FLAGS += -static-libstdc++
   endif
   ifneq (,$(shell $(CC) -v 2>&1 | grep gcc))
     LINKER_FLAGS += -static-libgcc

And I found my solution doesn't work if I restore the Makefile 😢
Looks like we need more investigation

@chalcolith
Copy link
Member Author

We have decided to:

  • Disable this test for now, as it seems to be related to the JIT and does not necessarily affect regular programs.
  • Update vendored LLVM to 9.0.x and merge.
  • Create issues to investigate further, both the JIT issue and also exception handling on Windows.

@dipinhora
Copy link
Contributor

@mshockwave your fix worked for me in a fresh docker container (i confirmed the segfault prior to applying your diff):

[----------] Global test environment tear-down
[==========] 1364 tests from 48 test cases ran. (69793 ms total)
[  PASSED  ] 1364 tests.
root@12d2f5497507:/home/pony/ponyc# ./build/release/ponyc --version
0.33.0-cd7805ad [release]
compiled with: llvm 9.0.1 -- cc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Defaults: pic=true
root@12d2f5497507:/home/pony/ponyc# git diff
diff --git a/lib/llvm/llvm-8.x.cfg b/lib/llvm/llvm-8.x.cfg
index e73df4e6..d70d3eea 100644
--- a/lib/llvm/llvm-8.x.cfg
+++ b/lib/llvm/llvm-8.x.cfg
@@ -1 +1 @@
-LLVM_CHECKOUT_REF := release/8.x
+LLVM_CHECKOUT_REF := release/9.x
diff --git a/lib/llvm/src b/lib/llvm/src
index 4856a933..c1a0a213 160000
--- a/lib/llvm/src
+++ b/lib/llvm/src
@@ -1 +1 @@
-Subproject commit 4856a9330ee01d30e9e11b6c2f991662b4c04b07
+Subproject commit c1a0a213378a458fbea1a5c77b315c7dce08fd05-dirty
root@12d2f5497507:/home/pony/ponyc# cd lib/llvm/src
root@12d2f5497507:/home/pony/ponyc/lib/llvm/src# git diff
diff --git a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
index 925049b2a1b..b30628a6448 100644
--- a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
@@ -226,6 +226,7 @@ void SectionMemoryManager::invalidateInstructionCache() {
 }

 SectionMemoryManager::~SectionMemoryManager() {
+  deregisterEHFrames();
   for (MemoryGroup *Group : {&CodeMem, &RWDataMem, &RODataMem}) {
     for (sys::MemoryBlock &Block : Group->AllocatedMem)
       MMapper.releaseMappedMemory(Block);
root@12d2f5497507:/home/pony/ponyc/lib/llvm/src# 

@mshockwave
Copy link
Contributor

@kulibali that sounds a reasonable decision. This issue has taken me and rest of us too much time. Regardless, I think we still can create a JIT fix patch mentioned earlier for our vendored LLVM

@dipinhora thanks for your verifying. That reminded me a config that was different from the usual building process: I'm linking all the LLVM libraries dynamically.

I will also report our discovery regarding the JIT issue to the LLVM community.

@mshockwave
Copy link
Contributor

mshockwave commented Dec 21, 2019

There was a small twist regarding the JIT fix patch I posted earlier: One of the ORC JIT creators, Lang Hames, also committed a patch to solve the same problem (i.e. missing EH frames deregistration in ORCv2) but with a more general solution. So I think (before we synchronize with upstream LLVM) we should use that patch instead.

Also, I did some extra experiments to confirm that under the following conditions, both my patch and Lang's patch will fix our problem:

  • Link libstdc++ statically
  • Link LLVM libraries statically
  • Link libgcc dynamically

Which, are the "normal" build configurations.

Thanks very much to @mshockwave for their help!
@chalcolith chalcolith removed the do not merge This PR should not be merged at this time label Dec 23, 2019
@chalcolith chalcolith marked this pull request as ready for review December 23, 2019 19:15
@chalcolith chalcolith changed the title WIP compiling LLVM 9.0.0 Compiling with LLVM 9.0.1 Dec 23, 2019
@SeanTAllen
Copy link
Member

@kulibali LLVM 9.0.1 doesn't seem to have been released yet, what version is the vendored LLVM updated to? 9.0.0? an rc candidate for 9.0.1?

@chalcolith
Copy link
Member Author

9.0.1 final has been tagged; the vendored LLVM is at c1a0a213378a458fbea1a5c77b315c7dce08fd05 llvmorg-9.0.1.

@SeanTAllen
Copy link
Member

Awesome. @kulibali I'm going to add a couple of CHANGELOG entries to this PR.

@SeanTAllen SeanTAllen changed the title Compiling with LLVM 9.0.1 LLVM 9.0.x support Dec 23, 2019
@SeanTAllen SeanTAllen added the changelog - added Automatically add "Added" CHANGELOG entry on merge label Dec 23, 2019
@SeanTAllen
Copy link
Member

@kulibali I fixed a small formatting error. I'm going to make sure it passes CI and will then merge.

@SeanTAllen SeanTAllen merged commit 0fea9f8 into master Dec 23, 2019
@SeanTAllen SeanTAllen deleted the llvm900 branch December 23, 2019 23:09
@SeanTAllen
Copy link
Member

Party time @kulibali. This one was merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog - added Automatically add "Added" CHANGELOG entry on merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants