Skip to content

Commit bbf64ce

Browse files
committed
Be more lenient about which LLVM library to use.
1 parent 6387d34 commit bbf64ce

File tree

5 files changed

+40
-95
lines changed

5 files changed

+40
-95
lines changed

lib/libLLVM_extra.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function LLVMAddNVVMReflectPass(PM::LLVMPassManagerRef, smversion)
9292
end
9393
else
9494

95-
if libllvm_version < v"8.0"
95+
if version() < v"8.0"
9696
function LLVMAddNVVMReflectPass(PM::LLVMPassManagerRef, smversion)
9797
@apicall(:LLVMExtraAddNVVMReflectPass,Cvoid,(LLVMPassManagerRef,), PM)
9898
end
@@ -180,7 +180,7 @@ function LLVMExtraAddGenericAnalysisPasses(PM)
180180
end
181181
end
182182

183-
if libllvm_version >= v"8.0"
183+
if version() >= v"8.0"
184184
@cenum(LLVMDebugEmissionKind,
185185
LLVMDebugEmissionKindNoDebug = 0,
186186
LLVMDebugEmissionKindFullDebug = 1,

src/LLVM.jl

Lines changed: 22 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,79 +7,23 @@ using Libdl
77

88
## discovery
99

10-
using Libdl
11-
12-
VERSION >= v"0.7.0-DEV.2576" || error("This version of LLVM.jl requires Julia 0.7")
13-
14-
let
15-
# find LLVM library
16-
17-
libllvm_paths = filter(Libdl.dllist()) do lib
18-
occursin(r"LLVM\b", basename(lib))
19-
end
20-
if isempty(libllvm_paths)
21-
error("""
22-
Cannot find the LLVM library loaded by Julia.
23-
Please use a version of Julia that has been built with USE_LLVM_SHLIB=1 (like the official binaries).
24-
If you are, please file an issue and attach the output of `Libdl.dllist()`.""")
25-
end
26-
if length(libllvm_paths) > 1
27-
error("""
28-
Multiple LLVM libraries loaded by Julia.
29-
Please file an issue and attach the output of `Libdl.dllist()`.""")
10+
export version
11+
12+
# make sure we precompile again when LLVM changes (some definitions are version-dependent)
13+
global const libllvm = Sys.iswindows() ? :LLVM : :libLLVM
14+
Base.include_dependency(Libdl.dlpath(libllvm))
15+
16+
const libllvm_version = Ref{VersionNumber}()
17+
function version()
18+
if !isassigned(libllvm_version)
19+
# FIXME: add a proper C API to LLVM
20+
version_str = unsafe_string(
21+
ccall((:_ZN4llvm16LTOCodeGenerator16getVersionStringEv, libllvm), Cstring, ()))
22+
m = match(r"LLVM version (?<version>.+)", version_str)
23+
m === nothing && error("Unrecognized version string: '$version_str'")
24+
libllvm_version[] =VersionNumber(m[:version])
3025
end
31-
global const libllvm = first(libllvm_paths)
32-
Base.include_dependency(libllvm)
33-
34-
global const libllvm_version = Base.libllvm_version::VersionNumber
35-
36-
# figure out the supported targets by looking at initialization routines
37-
lib = Libdl.dlopen(libllvm)
38-
llvm_targets = [:AArch64, :AMDGPU, :ARC, :ARM, :AVR, :BPF, :Hexagon, :Lanai, :MSP430,
39-
:Mips, :NVPTX, :PowerPC, :RISCV, :Sparc, :SystemZ, :WebAssembly, :X86,
40-
:XCore]
41-
global const libllvm_targets = filter(llvm_targets) do target
42-
sym = Libdl.dlsym_e(lib, Symbol("LLVMInitialize$(target)Target"))
43-
sym !== nothing
44-
end
45-
# TODO: figure out the name of the native target
46-
47-
@debug "Found LLVM v$libllvm_version at $libllvm with support for $(join(libllvm_targets, ", "))"
48-
49-
50-
# find appropriate LLVM.jl wrapper
51-
52-
vercmp_match(a,b) = a.major==b.major && a.minor==b.minor
53-
vercmp_compat(a,b) = a.major>b.major || (a.major==b.major && a.minor>=b.minor)
54-
55-
llvmjl_wrappers_path = joinpath(@__DIR__, "..", "lib")
56-
57-
llvmjl_wrappers = filter(path->isdir(joinpath(llvmjl_wrappers_path, path)),
58-
readdir(llvmjl_wrappers_path))
59-
@assert !isempty(llvmjl_wrappers)
60-
61-
matching_wrappers = filter(wrapper->vercmp_match(libllvm_version,
62-
VersionNumber(wrapper)),
63-
llvmjl_wrappers)
64-
global const llvmjl_wrapper = if !isempty(matching_wrappers)
65-
@assert length(matching_wrappers) == 1
66-
matching_wrappers[1]
67-
else
68-
compatible_wrappers = filter(wrapper->vercmp_compat(libllvm_version,
69-
VersionNumber(wrapper)),
70-
llvmjl_wrappers)
71-
isempty(compatible_wrappers) && error("Could not find any compatible wrapper for LLVM $(libllvm_version)")
72-
last(compatible_wrappers)
73-
end
74-
75-
@debug "Using LLVM.jl wrapper for LLVM v$llvmjl_wrapper"
76-
77-
78-
# backwards-compatible flags
79-
80-
global const libllvm_system = false
81-
82-
global const configured = true
26+
return libllvm_version[]
8327
end
8428

8529

@@ -130,19 +74,12 @@ include("deprecated.jl")
13074
## initialization
13175

13276
function __init__()
133-
libllvm_paths = filter(Libdl.dllist()) do lib
134-
occursin(r"LLVM\b", basename(lib))
135-
end
136-
if length(libllvm_paths) > 1
137-
# NOTE: this still allows switching to a non-USE_LLVM_SHLIB version, but
138-
# there's no way to detect that since the new libLLVM is loaded before this...
139-
cachefile = if VERSION >= v"1.3-"
140-
Base.compilecache_path(Base.PkgId(LLVM))
141-
else
142-
abspath(DEPOT_PATH[1], Base.cache_file_entry(Base.PkgId(LLVM)))
143-
end
144-
rm(cachefile)
145-
error("Your set-up changed, and LLVM.jl needs to be reconfigured. Please load the package again.")
77+
libllvm_version = version()
78+
@debug "Using LLVM $libllvm_version at $(Libdl.dlpath(libllvm))"
79+
if libllvm_version.major != Base.libllvm_version.major ||
80+
libllvm_version.minor != Base.libllvm_version.minor ||
81+
libllvm_version.patch != Base.libllvm_version.patch
82+
@warn "Using a different version of LLVM ($libllvm_version) than the one shipped with Julia ($(Base.libllvm_version)); this is unsupported"
14683
end
14784

14885
_install_handlers()

src/core/module.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ end
194194
## module flag iteration
195195
# TODO: doesn't actually iterate, since we can't list the available keys
196196

197-
if libllvm_version >= v"8.0"
197+
if version() >= v"8.0"
198198

199199
export flags
200200

src/debuginfo.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ DEBUG_METADATA_VERSION() = API.LLVMDebugMetadataVersion()
44

55
strip_debuginfo!(mod::Module) = API.LLVMStripModuleDebugInfo(ref(mod))
66

7-
if libllvm_version >= v"8.0"
7+
if version() >= v"8.0"
88
set_subprogram!(func::Function, sp::Metadata) = LLVM.API.LLVMSetSubprogram(ref(func), ref(sp))
99
get_subprogram(func::Function) = Metadata(LLVM.API.LLVMGetSubprogram(ref(func)))
1010
end

src/init.jl

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
## subsystem initialization
22

3-
export version, Shutdown,
4-
ismultithreaded
5-
6-
function version()
7-
return libllvm_version
8-
end
3+
export Shutdown, ismultithreaded
94

105
ismultithreaded() = convert(Core.Bool, API.LLVMIsMultithreaded())
116

@@ -22,6 +17,19 @@ end
2217

2318
## target initialization
2419

20+
# figure out the supported targets by looking at initialization routines
21+
# TODO: figure out the name of the native target
22+
let
23+
lib = Libdl.dlopen(libllvm)
24+
known_targets = [:AArch64, :AMDGPU, :ARC, :ARM, :AVR, :BPF, :Hexagon, :Lanai, :MSP430,
25+
:Mips, :NVPTX, :PowerPC, :RISCV, :Sparc, :SystemZ, :WebAssembly, :X86,
26+
:XCore]
27+
global const libllvm_targets = filter(known_targets) do target
28+
sym = Libdl.dlsym_e(lib, Symbol("LLVMInitialize$(target)Target"))
29+
sym !== nothing
30+
end
31+
end
32+
2533
for component in [:TargetInfo, :Target, :TargetMC, :AsmPrinter, :AsmParser, :Disassembler]
2634
jl_fname = Symbol(:Initialize, :All, component, :s)
2735
api_fname = Symbol(:LLVM, jl_fname)

0 commit comments

Comments
 (0)