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

Update the Pony compiler to be able to use LLVM 4.0.0 (#1592). #2061

Closed
wants to merge 19 commits into from

Conversation

chalcolith
Copy link
Member

This change includes the following:

  • Compiler code updates for changes to the LLVM 4.0.0 API.
  • Updates to Type-Based Alias Analysis metadata format for LLVM 4.0.0.
  • Builds in Release mode on Windows to conform to the Unix makefile.
  • Some efficiency tweaks for the Windows build.

@chalcolith chalcolith added changelog - added Automatically add "Added" CHANGELOG entry on merge do not merge This PR should not be merged at this time labels Jul 19, 2017
.travis.yml Outdated
packages:
- g++-6
env:
- FAVORITE_CONFIG=yes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can only have 1 favorite config. can you set this to "no" for now.

favorite config is used to decide which linux version will be done for release. so until we decide that 4.0.0 is the default, it should be "no"

@SeanTAllen
Copy link
Member

getting some build errors:

src/libponyc/codegen/gentype.c:160:21: error: ‘make_tbaa_descptr’ defined but not used [-Werror=unused-function]
 static LLVMValueRef make_tbaa_descptr(LLVMContextRef ctx, LLVMValueRef root)
                     ^~~~~~~~~~~~~~~~~
src/libponyc/codegen/gentype.c:149:21: error: ‘make_tbaa_descriptor’ defined but not used [-Werror=unused-function]
 static LLVMValueRef make_tbaa_descriptor(LLVMContextRef ctx,
                     ^~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make: *** [build/release/obj/libponyc/codegen/gentype.o] Error 1

Copy link
Member

@Praetonus Praetonus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thank you!

This should also contain README changes for LLVM 4. I've also left a few inline comments.


if(ast_id(def) != TK_STRUCT)
index++;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace here.

Makefile Outdated
else
$(warning WARNING: Unsupported LLVM version: $(llvm_version))
$(warning Please use LLVM 3.7.1, 3.8.1, or 3.9.1)
$(warning Please use LLVM 3.7.1, 3.8.1, 3.9.1, or 4.0.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should contain 4.0.1 as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wont work with homebrew on the mac until 4.0.1 is in here.

Based on how we do this, we shouldn't be supporting 4.0.0 we should only support 4.0.1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I wasn't aware of the homebrew status.

IIRC, we're not supporting 3.7.0, 3.8.0 and 3.9.0 because we've found blocking LLVM bugs in these versions. Until we find such a bug in either 4.0.0 or 4.0.1, I think it would be good to officially support both.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought we were only "supporting" the most recent version of any of the major releases. if we are supporting 4.0.0 then we need to do CI on it. Homebrew is going to install 4.0.1 on OSX.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI is a good point. You're right, we should keep the current scheme.

@@ -179,8 +181,10 @@ typedef struct compile_t
LLVMDIBuilderRef di;
LLVMMetadataRef di_unit;
LLVMValueRef tbaa_root;
#if LLVM_PONY < 400
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be PONY_LLVM.

static LLVMValueRef make_tbaa_root(LLVMContextRef ctx)
{
const char str[] = "Pony TBAA";
LLVMValueRef mdstr = LLVMMDStringInContext(ctx, str, sizeof(str) - 1);
return LLVMMDNodeInContext(ctx, &mdstr, 1);
}

static LLVMValueRef make_tbaa_descriptor(LLVMContextRef ctx, LLVMValueRef root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed? It is still needed for TBAA on type descriptors.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, you're right. Seems to have been lost when I reverted my over-ambitious TBAA stuff.

return LLVMMDNodeInContext(ctx, params, 3);
}

static LLVMValueRef make_tbaa_descptr(LLVMContextRef ctx, LLVMValueRef root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

{
pony_assert(parent != NULL);
pony_assert(node != NULL);
pony_assert((int)i >= 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check isn't needed. llvm::MDNode::replaceOperandWith has an unsigned parameter so i will never be used as signed.

@SeanTAllen
Copy link
Member

SeanTAllen commented Jul 20, 2017

@kulibali you need to update .travis_install.bash to correctly install LLVM 4.0 on Travis.

You'd need OSX and Linux versions.

brew install pcre2
brew install libressl

brew install [email protected]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is incorrect. there is no [email protected]

i would be:

brew install llvm

brew install libressl

brew install [email protected]
brew link --overwrite --force [email protected]
Copy link
Member

@SeanTAllen SeanTAllen Jul 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't want [email protected] here

brew link --overwrite --force [email protected]
mkdir llvmsym
ln -s "$(which llvm-config)" llvmsym/llvm-config-4.0
ln -s "$(which clang++)" llvmsym/clang++-4.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im not sure that these are needed. i'd say turn these 3 lines and the corresponding export PATH off and we can enable if needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be OK for the OSX section?

"osx:llvm-config-4.0")
  brew update
  brew install shellcheck
  shellcheck ./.*.bash ./*.bash

  brew install pcre2
  brew install libressl

  brew install llvm
  # brew link --overwrite --force llvm
  # mkdir llvmsym
  # ln -s "$(which llvm-config)" llvmsym/llvm-config-4.0
  # ln -s "$(which clang++)" llvmsym/clang++-4.0

  # do this elsewhere:
  #export PATH=llvmsym/:$PATH
;;

Makefile Outdated
LLVM_LINK = /usr/local/opt/[email protected]/bin/llvm-link
LLVM_OPT = /usr/local/opt/[email protected]/bin/opt
ifneq (,$(shell which /usr/local/opt/[email protected]/bin/llvm-config 2> /dev/null))
LLVM_CONFIG = /usr/local/opt/[email protected]/bin/llvm-config
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no [email protected]

it installs into /usr/local/opt/[email protected]/bin/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean /usr/local/opt/llvm/bin?

@chalcolith
Copy link
Member Author

Ok, I'll need to build new Windows libraries to support 4.0.1, and then I'll update the Windows build. I don't have any access to OSX so I'll try to get it right but will probably need some help.

static LLVMValueRef make_tbaa_root(LLVMContextRef ctx)
{
const char str[] = "Pony TBAA";
LLVMValueRef mdstr = LLVMMDStringInContext(ctx, str, sizeof(str) - 1);
return LLVMMDNodeInContext(ctx, &mdstr, 1);
}

#if PONY_LLVM < 400

static LLVMValueRef make_tbaa_descriptor(LLVMContextRef ctx, LLVMValueRef root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this still isn't correct. The two functions are needed even for LLVM 4. The created metadata nodes are used when loading an element of a type descriptor. See for example desc_field in gendesc.c.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For LLVM 4 they need to be in the new path-aware format. I had done some work on this but not finished it. I'll take a further look.

@chalcolith
Copy link
Member Author

I'm not sure what the Linux test errors are about. On my Ubuntu 16.04 machine all the tests pass.

I'm going to need some help with the OSX travis setup, as I have no access to an OSX machine.

@Praetonus
Copy link
Member

@kulibali I'll take a look, to see if it segfaults on my machine.

@Praetonus
Copy link
Member

I can reproduce the segfault. At first I suspected that it came from the descriptor TBAA stuff but I fixed that and it still happens. I'll continue to investigate.

Here's the diff for the TBAA.

@Praetonus
Copy link
Member

I've narrowed the crash down to the HeapToStack optimisation pass. It looks like a change in LLVM 4 made previously valid transformations invalid.

@chalcolith
Copy link
Member Author

Thanks! I have applied your patch. The tests still pass on Ubuntu 16.04 for me.

@Praetonus
Copy link
Member

Status update on the crash: it looks like the problem is related to the LICM pass in LLVM, which is hoisting loads and sinking stores in invalid places, resulting in reads from uninitialised memory. I'm still unsure whether the problem is coming from the custom passes in the Pony compiler or the LLVM passes.

I've reduced the crash in collections/persistent to a minimal case. I'll add it here in case somebody else wants to investigate. I suspect it could be reduced even more but I haven't been able to do so yet.

class val MapNode
  let entries: USize = 0

class val HashMap
  let root: MapNode = MapNode

actor Main
  new create(env: Env) =>
    var m6 = HashMap
    let vs = Array[U8].create(2).>push(0).>push(1)
    let i = vs.values()
    while i.has_next() do
      try
        i.next()
        if m6.root.entries != 0 then
          error
        end
        m6 = HashMap
      end
    end

@chalcolith
Copy link
Member Author

I have found by trial and error that if I change genopt.cc:276 to case Instruction::Load: return false; I do not encounter the crash. I am still trying to wrap my head around this pass's code, so I don't immediately understand why a load of the stack-allocated pointer would crash.

@Praetonus
Copy link
Member

@kulibali Unfortunately I don't think that's the problem. That function determines whether a given heap allocation can be stack allocated by looking at the uses of the allocation, on the basis that no use should capture the allocated pointer (e.g. by storing it somewhere).

A load never captures, so I think you're seeing that result because the change to the load case is overriding the hypothetical buggy case which is erroneously saying that the corresponding operation doesn't capture.

@chalcolith
Copy link
Member Author

chalcolith commented Aug 19, 2017

The segfault also disappears when I disable the inliner pass.

@SeanTAllen
Copy link
Member

Interesting

This change includes the following:

- Compiler code updates for changes to the LLVM 4.0.0 API.
- Updates to Type-Based Alias Analysis metadata format for LLVM 4.0.0.
- Builds in Release mode on Windows to conform to the Unix makefile.
- Some efficiency tweaks for the Windows build.
@chalcolith
Copy link
Member Author

Just for fun I have made a branch that uses LLVM 5.0.0: https://github.com/kulibali/ponyc/tree/llvm500

It compiles on Ubuntu, but crashes in LLVMLifetimeStart.

@chalcolith
Copy link
Member Author

I have fixed the crash in LLVMLifetimeStart. Everything works on Windows, but generated code on Linux still segfaults. If I disable the HeapToStack pass, it works.

@Praetonus
Copy link
Member

This sounds like the same bug that's blocking the LLVM 4 port.

@chalcolith
Copy link
Member Author

This PR is superceded by #2303

@chalcolith chalcolith closed this Oct 25, 2017
chalcolith added a commit to chalcolith/ponyc that referenced this pull request Nov 24, 2017
This change includes the following:

- Compiler code updates for changes to the LLVM 4.0.0 and 5.0.0 API.
- Updates to Type-Based Alias Analysis metadata format for LLVM 4.0.0 and up.

Note that this code contains a workaround for a problem with hoisting
loads of stack-allocated references (see ponylang#2303, ponylang#2061, ponylang#1592), and should be
considered experimental.  Do not use LLVM 4 or 5 for critical production
builds.
@chalcolith chalcolith deleted the llvm400 branch January 26, 2018 03:36
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 do not merge This PR should not be merged at this time
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants