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

Handle MlirStringRef and Strings #12

Merged
merged 1 commit into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
# MLIR.jl
# MLIR.jl

## Design

### String and MlirStringRef.
`MlirStringRef` is a non-owning pointer, the caller is in charge of performing necessary
copies or ensuring that the pointee outlives all uses of `MlirStringRef`.
Since Julia is a GC'd language special care must be taken around the live-time of Julia
objects such as `String`s when interacting with foreign libraries.

For convenience and safty sake, users of the API should use Julia `String` or `Symbol` as
the argument to the C-ABI of MLIR instead of directly using `MlirStringRef`. We translate
(cheaply) between Julia `String` and `MlirStringRef`.
15 changes: 15 additions & 0 deletions src/MLIR.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,19 @@ module API
end
end # module API

# MlirStringRef is a non-owning reference to a string,
# we thus need to ensure that the Julia string remains alive
# over the use. For that we use the cconvert/unsafe_convert mechanism
# for foreign-calls. The returned value of the cconvert is rooted across
# foreign-call.
Base.cconvert(::Type{API.MlirStringRef}, s::Union{Symbol, String}) = s
Base.cconvert(::Type{API.MlirStringRef}, s::AbstractString) =
Base.cconvert(API.MlirStringRef, String(s)::String)

# Directly create `MlirStringRef` instead of adding an extra ccall.
function Base.unsafe_convert(::Type{API.MlirStringRef}, s::Union{Symbol, String, AbstractVector{UInt8}})
p = Base.unsafe_convert(Ptr{Cchar}, s)
return API.MlirStringRef(p, length(s))
end

end # module
15 changes: 5 additions & 10 deletions test/executionengine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ end
function lowerModuleToLLVM(ctx, mod)
pm = MLIR.API.mlirPassManagerCreate(ctx)
if LLVM.version() >= v"15"
op = MLIR.API.mlirStringRefCreateFromCString("func.func")
op = "func.func"
else
op = MLIR.API.mlirStringRefCreateFromCString("builtin.func")
op = "builtin.func"
end
opm = MLIR.API.mlirPassManagerGetNestedUnder(pm, op)
if LLVM.version() >= v"15"
Expand All @@ -49,27 +49,23 @@ ctx = MLIR.API.mlirContextCreate()
registerAllUpstreamDialects!(ctx)

if LLVM.version() >= v"15"
ir = MLIR.API.mlirStringRefCreateFromCString(
"""
ir = """
module {
func.func @add(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } {
%res = arith.addi %arg0, %arg0 : i32
return %res : i32
}
}
"""
)
else
ir = MLIR.API.mlirStringRefCreateFromCString(
"""
ir = """
module {
func @add(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } {
%res = arith.addi %arg0, %arg0 : i32
return %res : i32
}
}
"""
)
end
mod = MLIR.API.mlirModuleCreateParse(ctx, ir)
lowerModuleToLLVM(ctx, mod)
Expand All @@ -85,8 +81,7 @@ if jit == C_NULL
error("Execution engine creation failed")
end

addr = MLIR.API.mlirExecutionEngineLookup(jit,
MLIR.API.mlirStringRefCreateFromCString("add"))
addr = MLIR.API.mlirExecutionEngineLookup(jit, "add")

if addr == C_NULL
error("Lookup failed")
Expand Down