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 building against llvm15 #1035

Merged
merged 11 commits into from
Mar 30, 2024
2 changes: 1 addition & 1 deletion ffi/Makefile.linux
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
CXX ?= g++

# -flto and --exclude-libs allow us to remove those parts of LLVM we don't use
CXX_FLTO_FLAGS ?= -flto
#CXX_FLTO_FLAGS ?= -flto
gmarkall marked this conversation as resolved.
Show resolved Hide resolved
LD_FLTO_FLAGS ?= -flto -Wl,--exclude-libs=ALL
# -fPIC is required when compiling objects for a shared library
CXX_FPIC_FLAGS ?= -fPIC
Expand Down
1 change: 0 additions & 1 deletion ffi/assembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ API_EXPORT(LLVMModuleRef)
LLVMPY_ParseAssembly(LLVMContextRef context, const char *ir,
const char **outmsg) {
using namespace llvm;

SMDiagnostic error;

Module *m = parseAssemblyString(ir, error, *unwrap(context)).release();
Expand Down
21 changes: 14 additions & 7 deletions ffi/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ def run_llvm_config(llvm_config, args):
return out


def show_warning(message):
header = ' * '.join(("WARNING",) * 8)
blk = '=' * 80
warning = f'{blk}\n{header}\n{blk}'
print(f"{warning}\n{message}\n{warning}")


def find_windows_generator():
"""
Find a suitable cmake "generator" under Windows.
Expand Down Expand Up @@ -156,16 +163,16 @@ def main_posix(kind, library_ext):
"overridden.\nThis is unsupported behaviour, llvmlite may not "
"work as intended.\nRequested LLVM version: {}".format(
out.strip()))
warn = ' * '.join(("WARNING",) * 8)
blk = '=' * 80
warning = '{}\n{}\n{}'.format(blk, warn, blk)
print(warning)
print(msg)
print(warning + '\n')
show_warning(msg)
else:
(version, _) = out.split('.', 1)
version = int(version)
if version != 14:
if version == 15:
msg = ("Building with LLVM 15; note that LLVM 15 support is "
"presently experimental")
show_warning(msg)
elif version != 14:

msg = ("Building llvmlite requires LLVM 14, got "
"{!r}. Be sure to set LLVM_CONFIG to the right executable "
"path.\nRead the documentation at "
Expand Down
17 changes: 15 additions & 2 deletions ffi/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,23 @@ API_EXPORT(void)
LLVMPY_DisposeString(const char *msg) { free(const_cast<char *>(msg)); }

API_EXPORT(LLVMContextRef)
LLVMPY_GetGlobalContext() { return LLVMGetGlobalContext(); }
LLVMPY_GetGlobalContext() {
auto context = LLVMGetGlobalContext();
#if LLVM_VERSION_MAJOR > 14
LLVMContextSetOpaquePointers(context, false);
Copy link
Member

Choose a reason for hiding this comment

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

Note to other reviewers - this does result in opaque pointers being disabled for the global context multiple times, but this operation is idempotent.

#endif
return context;
}


API_EXPORT(LLVMContextRef)
LLVMPY_ContextCreate() { return LLVMContextCreate(); }
LLVMPY_ContextCreate() {
LLVMContextRef context = LLVMContextCreate();
#if LLVM_VERSION_MAJOR > 14
LLVMContextSetOpaquePointers(context, false);
#endif
return context;
}

API_EXPORT(void)
LLVMPY_ContextDispose(LLVMContextRef context) {
Expand Down
5 changes: 5 additions & 0 deletions ffi/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
#define LLVMPY_CORE_H_

#include "llvm-c/Core.h"

// Needed for macros that control version-specific behaviour - included here so
// that they are available in all ffi translation units
Copy link
Member

Choose a reason for hiding this comment

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

In particular, this defines the LLVM_VERSION_MAJOR macro referenced in various places in this PR.

#include "llvm/Config/llvm-config.h"

#include <cstdlib>
#include <cstring>

Expand Down
11 changes: 10 additions & 1 deletion ffi/orcjit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ LLVMPY_LLJITLookup(std::shared_ptr<LLJIT> *lljit, const char *dylib_name,
return nullptr;
}

*addr = sym->getAddress();
#if LLVM_VERSION_MAJOR <= 14
*addr = sym->getAddress();
#else
*addr = sym->getValue();
#endif

return new JITDylibTracker(*lljit, *dylib,
std::move(dylib->createResourceTracker()));
}
Expand Down Expand Up @@ -334,7 +339,11 @@ LLVMPY_LLJIT_Link(std::shared_ptr<LLJIT> *lljit, const char *libraryName,
LLVMDisposeErrorMessage(message);
return nullptr;
}
#if LLVM_VERSION_MAJOR <= 14
exports[export_idx].address = lookup->getAddress();
#else
exports[export_idx].address = lookup->getValue();
#endif
}
return new JITDylibTracker(*lljit, *dylib,
std::move(dylib->getDefaultResourceTracker()));
Expand Down
14 changes: 14 additions & 0 deletions ffi/passmanagers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,13 @@ LLVMPY_AddCallGraphDOTPrinterPass(LLVMPassManagerRef PM) {

API_EXPORT(void)
LLVMPY_AddDotDomPrinterPass(LLVMPassManagerRef PM, bool showBody) {
#if LLVM_VERSION_MAJOR <= 14

Choose a reason for hiding this comment

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

Suggest being consistent with the #ifs, either all "<= 14" or all "< 15"

unwrap(PM)->add(showBody ? llvm::createDomPrinterPass()
: llvm::createDomOnlyPrinterPass());
#else
unwrap(PM)->add(showBody ? llvm::createDomPrinterWrapperPassPass()
: llvm::createDomOnlyPrinterWrapperPassPass());
#endif
}

API_EXPORT(void)
Expand All @@ -172,8 +177,13 @@ LLVMPY_AddGlobalsModRefAAPass(LLVMPassManagerRef PM) {

API_EXPORT(void)
LLVMPY_AddDotPostDomPrinterPass(LLVMPassManagerRef PM, bool showBody) {
#if LLVM_VERSION_MAJOR <= 14
unwrap(PM)->add(showBody ? llvm::createPostDomPrinterPass()
: llvm::createPostDomOnlyPrinterPass());
#else
unwrap(PM)->add(showBody ? llvm::createPostDomPrinterWrapperPassPass()
: llvm::createPostDomOnlyPrinterWrapperPassPass());
#endif
}

API_EXPORT(void)
Expand Down Expand Up @@ -244,10 +254,12 @@ LLVMPY_AddAlwaysInlinerPass(LLVMPassManagerRef PM, bool insertLifetime) {
unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass(insertLifetime));
}

#if LLVM_VERSION_MAJOR < 15
API_EXPORT(void)
LLVMPY_AddArgPromotionPass(LLVMPassManagerRef PM, unsigned int maxElements) {

Choose a reason for hiding this comment

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

Ditto with ArgumentPromotionPass in NPM as below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did you mean legacy version of this pass is available as well? I couldn't find it.

Choose a reason for hiding this comment

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

Sorry I meant the new pass version, I wrote both of these comments together then saw the legacy pass still existed.

On that note, the NPM setup slots in differently (using pipeline tuning options) so we can’t replace these in-situ. No needed for this change though.

unwrap(PM)->add(llvm::createArgumentPromotionPass(maxElements));
}
#endif

API_EXPORT(void)
LLVMPY_AddBreakCriticalEdgesPass(LLVMPassManagerRef PM) {
Expand Down Expand Up @@ -333,12 +345,14 @@ LLVMPY_AddLoopUnrollAndJamPass(LLVMPassManagerRef PM) {
LLVMAddLoopUnrollAndJamPass(PM);
}

#if LLVM_VERSION_MAJOR < 15
API_EXPORT(void)
LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize,

Choose a reason for hiding this comment

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

For reference the loop unswitch pass has been renamed to SimpleLoopUnswitchPass in the new pass manager (https://reviews.llvm.org/D124376). Naturally to enable this we need to move to NPM so it makes sense that this is disabled for now but it can come back with NPM.

Choose a reason for hiding this comment

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

Actually createSimpleLoopUnswitchLegacyPass still exists in LLVM-15 so it can be dropped in here without issue.

Choose a reason for hiding this comment

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

API_EXPORT(void)
LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize,
                           bool hasBranchDivergence) {
#if LLVM_VERSION_MAJOR < 15
    unwrap(PM)->add(
        createLoopUnswitchPass(optimizeForSize, hasBranchDivergence));
#else
    unwrap(PM)->add(
        createSimpleLoopUnswitchLegacyPass(optimizeForSize));
#endif
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for finding this, I have updated the code.

bool hasBranchDivergence) {
unwrap(PM)->add(
createLoopUnswitchPass(optimizeForSize, hasBranchDivergence));
}
#endif

API_EXPORT(void)
LLVMPY_AddLowerAtomicPass(LLVMPassManagerRef PM) {
Expand Down
3 changes: 3 additions & 0 deletions ffi/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

// the following is needed for WriteGraph()
#include "llvm/Analysis/CFGPrinter.h"
#if LLVM_VERSION_MAJOR > 14
#include "llvm/Support/GraphWriter.h"
#endif

/* An iterator around a attribute list, including the stop condition */
struct AttributeListIterator {
Expand Down
22 changes: 17 additions & 5 deletions llvmlite/binding/passmanagers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
from collections import namedtuple
from enum import IntFlag
from llvmlite.binding import ffi
from llvmlite.binding.initfini import llvm_version_info
import os
from tempfile import mkstemp
from llvmlite.binding.common import _encode_string

_prunestats = namedtuple('PruneStats',
('basicblock diamond fanout fanout_raise'))

llvm_version_major = llvm_version_info[0]

class PruneStats(_prunestats):
""" Holds statistics from reference count pruning.
Expand Down Expand Up @@ -258,6 +260,8 @@ def add_arg_promotion_pass(self, max_elements=3):

LLVM 14: `llvm::createArgumentPromotionPass`
""" # noqa E501
if llvm_version_major > 14:
raise RuntimeError('ArgumentPromotionPass unavailable in LLVM > 14')
ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements)

def add_break_critical_edges_pass(self):
Expand Down Expand Up @@ -467,6 +471,8 @@ def add_loop_unswitch_pass(self,

LLVM 14: `llvm::createLoopUnswitchPass`
""" # noqa E501
if llvm_version_major > 14:
raise RuntimeError('LoopUnswitchPass unavailable in LLVM > 14')
ffi.lib.LLVMPY_AddLoopUnswitchPass(self,
optimize_for_size,
has_branch_divergence)
Expand Down Expand Up @@ -866,7 +872,10 @@ def run_with_remarks(self, function, remarks_format='yaml',
ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool]
ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ffi.LLVMPassManagerRef, c_uint]

if llvm_version_major < 15:
ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ffi.LLVMPassManagerRef, c_uint]

ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [
ffi.LLVMPassManagerRef]
Expand All @@ -883,10 +892,13 @@ def run_with_remarks(self, function, remarks_format='yaml',
ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [
ffi.LLVMPassManagerRef,
c_bool,
c_bool]

if llvm_version_major < 15:
ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [
ffi.LLVMPassManagerRef,
c_bool,
c_bool]

ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef]
Expand Down
17 changes: 11 additions & 6 deletions llvmlite/tests/test_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from llvmlite.binding import ffi
from llvmlite.tests import TestCase

llvm_version_major = llvm.llvm_version_info[0]

# arvm7l needs extra ABI symbols to link successfully
if platform.machine() == 'armv7l':
Expand Down Expand Up @@ -653,7 +654,7 @@ def break_up_asm(self, asm):
def test_rv32d_ilp32(self):
self.check_riscv_target()
llmod = self.fpadd_ll_module()
target = self.riscv_target_machine(features="+f,+d")
target = self.riscv_target_machine(features="+f,+d", abiname="ilp32")
Copy link
Member

Choose a reason for hiding this comment

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

LLVM 14 defaults to the soft-float ABI, LLVM 15 defaults to the hard-float ABI. We explicitly specify the soft-float ABI for consistency with the expected output. Note that hard float and hard double ABIs are tested in the subsequent two tests below.

self.assertEqual(self.break_up_asm(target.emit_assembly(llmod)),
riscv_asm_ilp32)

Expand Down Expand Up @@ -783,12 +784,14 @@ def test_set_option(self):
"""
subprocess.check_call([sys.executable, "-c", code])

@unittest.skip('Edit this test to test for both llvm14 and llvm15')
gmarkall marked this conversation as resolved.
Show resolved Hide resolved
def test_version(self):
major, minor, patch = llvm.llvm_version_info
# one of these can be valid
valid = [(14, )]
self.assertIn((major,), valid)
self.assertIn(patch, range(10))
valid = (14, 15)
self.assertIn(major, valid)
self.assertIn(patch, range(8))
Copy link
Member

Choose a reason for hiding this comment

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

(Max patch versions are 14.0.6 and 15.0.7)



def test_check_jit_execution(self):
llvm.check_jit_execution()
Expand Down Expand Up @@ -2176,7 +2179,8 @@ def test_populate(self):
pm.add_aggressive_dead_code_elimination_pass()
pm.add_aa_eval_pass()
pm.add_always_inliner_pass()
pm.add_arg_promotion_pass(42)
if llvm_version_major < 15:
pm.add_arg_promotion_pass(42)
pm.add_break_critical_edges_pass()
pm.add_dead_store_elimination_pass()
pm.add_reverse_post_order_function_attrs_pass()
Expand All @@ -2191,7 +2195,8 @@ def test_populate(self):
pm.add_loop_simplification_pass()
pm.add_loop_unroll_pass()
pm.add_loop_unroll_and_jam_pass()
pm.add_loop_unswitch_pass()
if llvm_version_major < 15:
pm.add_loop_unswitch_pass()
pm.add_lower_atomic_pass()
pm.add_lower_invoke_pass()
pm.add_lower_switch_pass()
Expand Down
Loading