From eeeabc29355cb5f1750ab4bce6afd40af423f028 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 8 Jun 2022 17:23:31 -0400 Subject: [PATCH 1/7] Make LLVMSymbol a subtype of AbstractString so that we can pass it directly to Libdl.dlsym --- src/orcv2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orcv2.jl b/src/orcv2.jl index 7434fbaf..7c1c73d3 100644 --- a/src/orcv2.jl +++ b/src/orcv2.jl @@ -87,7 +87,7 @@ end include("executionengine/ts_module.jl") -@checked struct LLVMSymbol +@checked struct LLVMSymbol <: AbstractString ref::API.LLVMOrcSymbolStringPoolEntryRef end Base.unsafe_convert(::Type{API.LLVMOrcSymbolStringPoolEntryRef}, sym::LLVMSymbol) = sym.ref From ccaa9de77c3a28f686da7e0c62f62faea75489b9 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 8 Jun 2022 17:26:19 -0400 Subject: [PATCH 2/7] Add CustomDefinitionGenerator --- src/orcv2.jl | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/orcv2.jl b/src/orcv2.jl index 7c1c73d3..e981926c 100644 --- a/src/orcv2.jl +++ b/src/orcv2.jl @@ -176,12 +176,13 @@ function JITDylib(es::ExecutionSession, name; bare=false) JITDylib(ref) end -@checked struct DefinitionGenerator +abstract type AbstractDefinitionGenerator end +@checked struct DefinitionGenerator <: AbstractDefinitionGenerator ref::API.LLVMOrcDefinitionGeneratorRef end Base.unsafe_convert(::Type{API.LLVMOrcDefinitionGeneratorRef}, dg::DefinitionGenerator) = dg.ref -function add!(jd::JITDylib, dg::DefinitionGenerator) +function add!(jd::JITDylib, dg::AbstractDefinitionGenerator) API.LLVMOrcJITDylibAddGenerator(jd, dg) end @@ -191,7 +192,37 @@ function CreateDynamicLibrarySearchGeneratorForProcess(prefix) DefinitionGenerator(ref[]) end -# LLVMOrcCreateCustomCAPIDefinitionGenerator(F, Ctx) +# We can do this async by copying content of `LookupState` and setting it to +# C_NULL and returning ErrorSuccess. We then would need to call `LookupContinue` +# but that function seems to be missing from teh CAPI. +# Note LookupSet get's destroyed when we return here +function DefinitionGeneratorTryToGenerateFunction(GeneratorObj::API.LLVMOrcDefinitionGeneratorRef, ctx::Ptr{Cvoid}, LookupState::Ptr{API.LLVMOrcLookupStateRef}, Kind::API.LLVMOrcLookupKind, JD::API.LLVMOrcJITDylibRef, JDLookupFlags::API.LLVMOrcJITDylibLookupFlags, LookupSet::API.LLVMOrcCLookupSet, LookupSetSize::Csize_t)::API.LLVMErrorRef + dg = Base.unsafe_pointer_to_objref(ctx)::CustomDefinitionGenerator + @assert dg.dg.ref === GeneratorObj + lookupSet = Base.unsafe_wrap(Array, LookupSet, LookupSetSize, own=false) + return dg.callback(Kind, JITDylib(JD), JDLookupFlags, lookupSet)::API.LLVMErrorRef +end + +mutable struct CustomDefinitionGenerator <: AbstractDefinitionGenerator + callback + dg::DefinitionGenerator + function CustomDefinitionGenerator(callback) + this = new(callback) + push!(CUSTOM_DG_ROOTS, this) + + ref = API.LLVMOrcCreateCustomCAPIDefinitionGenerator( + @cfunction(DefinitionGeneratorTryToGenerateFunction, API.LLVMErrorRef, (API.LLVMOrcDefinitionGeneratorRef, Ptr{Cvoid}, Ptr{API.LLVMOrcLookupStateRef}, API.LLVMOrcLookupKind, API.LLVMOrcJITDylibRef, API.LLVMOrcJITDylibLookupFlags, API.LLVMOrcCLookupSet, Csize_t)), + Base.pointer_from_objref(this) + ) + + this.dg = DefinitionGenerator(ref) + return this + end +end +Base.cconvert(::Type{API.LLVMOrcDefinitionGeneratorRef}, dg::CustomDefinitionGenerator) = dg.dg + +# todo: Delete +const CUSTOM_DG_ROOTS = Base.IdSet{CustomDefinitionGenerator}() function lookup_dylib(es::ExecutionSession, name) ref = API.LLVMOrcExecutionSessionGetJITDylibByName(es, name) From e7f4f964f578032fe2e34ec465f391b888a25e32 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 8 Jun 2022 17:26:46 -0400 Subject: [PATCH 3/7] Add a DynamicLibDefintionGenerator --- src/orcv2.jl | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/orcv2.jl b/src/orcv2.jl index e981926c..f05312ff 100644 --- a/src/orcv2.jl +++ b/src/orcv2.jl @@ -224,6 +224,40 @@ Base.cconvert(::Type{API.LLVMOrcDefinitionGeneratorRef}, dg::CustomDefinitionGen # todo: Delete const CUSTOM_DG_ROOTS = Base.IdSet{CustomDefinitionGenerator}() +function DynamicLibDefinitionGenerator(path) + handle = Libdl.dlopen(path) + + function libdl_definitions(kind, JD, lookupFlags, lookupSet) + @assert kind == API.LLVMOrcLookupKindStatic + @assert lookupFlags == API.LLVMOrcJITDylibLookupFlagsMatchAllSymbols + + symbols = API.LLVMJITCSymbolMapPair[] + for lookup in lookupSet + if lookup.LookupFlags == API.LLVMOrcSymbolLookupFlagsRequiredSymbol + name = LLVMSymbol(lookup.Name) + ptr = Libdl.dlsym(handle, name; throw_error=false) + + if ptr !== C_NULL + LLVM.retain(name) + address = API.LLVMOrcJITTargetAddress( + reinterpret(UInt, ptr)) + flags = API.LLVMJITSymbolFlags( + API.LLVMJITSymbolGenericFlagsCallable, 0) + symbol = API.LLVMJITEvaluatedSymbol(address, flags) + push!(symbols, API.LLVMJITCSymbolMapPair(name, symbol)) + end + else + @warn "Unkown" lookup.LookupFlags + end + end + mu = absolute_symbols(symbols) + define(JD, mu) + # TODO: API.LLVMErrorSuccess is not a LLVMErrorRef + return reinterpret(API.LLVMErrorRef, API.LLVMErrorSuccess) + end + return LLVM.CustomDefinitionGenerator(libdl_definitions) +end + function lookup_dylib(es::ExecutionSession, name) ref = API.LLVMOrcExecutionSessionGetJITDylibByName(es, name) if ref == C_NULL From c18e0bac718e39e11e8c29c93edae4fdb1914e0c Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 May 2023 15:07:34 -0400 Subject: [PATCH 4/7] add test for DynamicLibDefinitionGenerator --- test/Project.toml | 1 + test/orcv2.jl | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/test/Project.toml b/test/Project.toml index 6dd5450d..19351b9e 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,5 +1,6 @@ [deps] InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" LLVMExtra_jll = "dad2f222-ce93-54a1-a47d-0025e8a3acab" +NUMA_jll = "7f51dc2b-bb24-59f8-b771-bb1490e4195d" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" diff --git a/test/orcv2.jl b/test/orcv2.jl index df0a51c4..2c19403e 100644 --- a/test/orcv2.jl +++ b/test/orcv2.jl @@ -302,4 +302,21 @@ end end end +import NUMA_jll + +@testset "CustomDefinitionGenerator" begin + @dispose lljit=LLJIT() begin + if NUMA_jll.is_available() + @test_throws lookup(lljit, "numa_available") + + dg = LLVM.DynamicLibDefinitionGenerator(NUMA_jll.libnuma) + jd = JITDylib(lljit) + LLVM.add!(jd, dg) + + addr = lookup(lljit, "numa_available") + @test addr !== C_NULL + end + end +end + end From 565edd4d2f6f2500be365efd0d6a67890783b042 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 May 2023 15:16:02 -0400 Subject: [PATCH 5/7] fix comment --- src/orcv2.jl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/orcv2.jl b/src/orcv2.jl index f05312ff..7a36e732 100644 --- a/src/orcv2.jl +++ b/src/orcv2.jl @@ -194,9 +194,15 @@ end # We can do this async by copying content of `LookupState` and setting it to # C_NULL and returning ErrorSuccess. We then would need to call `LookupContinue` -# but that function seems to be missing from teh CAPI. +# but that function was only added in LLVM 15 to the API. +# # Note LookupSet get's destroyed when we return here -function DefinitionGeneratorTryToGenerateFunction(GeneratorObj::API.LLVMOrcDefinitionGeneratorRef, ctx::Ptr{Cvoid}, LookupState::Ptr{API.LLVMOrcLookupStateRef}, Kind::API.LLVMOrcLookupKind, JD::API.LLVMOrcJITDylibRef, JDLookupFlags::API.LLVMOrcJITDylibLookupFlags, LookupSet::API.LLVMOrcCLookupSet, LookupSetSize::Csize_t)::API.LLVMErrorRef +function DefinitionGeneratorTryToGenerateFunction( + GeneratorObj::API.LLVMOrcDefinitionGeneratorRef, ctx::Ptr{Cvoid}, + LookupState::Ptr{API.LLVMOrcLookupStateRef}, Kind::API.LLVMOrcLookupKind, + JD::API.LLVMOrcJITDylibRef, JDLookupFlags::API.LLVMOrcJITDylibLookupFlags, + LookupSet::API.LLVMOrcCLookupSet, LookupSetSize::Csize_t)::API.LLVMErrorRef + dg = Base.unsafe_pointer_to_objref(ctx)::CustomDefinitionGenerator @assert dg.dg.ref === GeneratorObj lookupSet = Base.unsafe_wrap(Array, LookupSet, LookupSetSize, own=false) @@ -208,10 +214,15 @@ mutable struct CustomDefinitionGenerator <: AbstractDefinitionGenerator dg::DefinitionGenerator function CustomDefinitionGenerator(callback) this = new(callback) - push!(CUSTOM_DG_ROOTS, this) + push!(CUSTOM_DG_ROOTS, this) # Globally root DefinitionGenerator ref = API.LLVMOrcCreateCustomCAPIDefinitionGenerator( - @cfunction(DefinitionGeneratorTryToGenerateFunction, API.LLVMErrorRef, (API.LLVMOrcDefinitionGeneratorRef, Ptr{Cvoid}, Ptr{API.LLVMOrcLookupStateRef}, API.LLVMOrcLookupKind, API.LLVMOrcJITDylibRef, API.LLVMOrcJITDylibLookupFlags, API.LLVMOrcCLookupSet, Csize_t)), + @cfunction(DefinitionGeneratorTryToGenerateFunction, + API.LLVMErrorRef, + (API.LLVMOrcDefinitionGeneratorRef, Ptr{Cvoid}, + Ptr{API.LLVMOrcLookupStateRef}, API.LLVMOrcLookupKind, + API.LLVMOrcJITDylibRef, API.LLVMOrcJITDylibLookupFlags, + API.LLVMOrcCLookupSet, Csize_t)), Base.pointer_from_objref(this) ) From 20d84cc7e2c280d28cbfa0156feef89f0289dd5b Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 15 May 2023 15:35:00 -0400 Subject: [PATCH 6/7] Check test --- test/orcv2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/orcv2.jl b/test/orcv2.jl index 2c19403e..5bff2ff2 100644 --- a/test/orcv2.jl +++ b/test/orcv2.jl @@ -307,7 +307,7 @@ import NUMA_jll @testset "CustomDefinitionGenerator" begin @dispose lljit=LLJIT() begin if NUMA_jll.is_available() - @test_throws lookup(lljit, "numa_available") + @test_throws ErrorException lookup(lljit, "numa_available") dg = LLVM.DynamicLibDefinitionGenerator(NUMA_jll.libnuma) jd = JITDylib(lljit) From 6d5ceec46ca1d5b97daf7f9c0822e5754cdc1c78 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 17 May 2023 14:57:03 -0400 Subject: [PATCH 7/7] Update src/orcv2.jl --- src/orcv2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/orcv2.jl b/src/orcv2.jl index 7a36e732..5edffe19 100644 --- a/src/orcv2.jl +++ b/src/orcv2.jl @@ -87,7 +87,7 @@ end include("executionengine/ts_module.jl") -@checked struct LLVMSymbol <: AbstractString +@checked struct LLVMSymbol ref::API.LLVMOrcSymbolStringPoolEntryRef end Base.unsafe_convert(::Type{API.LLVMOrcSymbolStringPoolEntryRef}, sym::LLVMSymbol) = sym.ref