I'm currently using cranelift-isle
for a project of my own. However, unlike Cranelift, the types that I use with ISLE cannot be cheaply cloned like Cranelift types used in the ISLE context, so I must use a reference for them.
As long as I'm aware of, ISLE doesn't emit a lifetime parameter on the context, so ISLE can't generate code like:
// ISLE generated Context
trait Context<'a> {
fn get_foo(&mut self) -> FooRef<'a>;
}
... and let me implement that like:
type FooRef<'a> = &'a Foo;
#[derive(Debug)]
struct Foo(i32);
struct FooCtx<'a> {
foo: &'a Foo
}
impl<'a> Context<'a> for FooCtx<'a> {
fn get_foo(&mut self) -> FooRef<'a> {
self.foo
}
}
I'm thinking of patching ISLE so that it can emit a lifetime parameter for the context type and defined primitive types. Is this a good idea, or is there any workaround I haven't yet discovered?
You could pass indices into a table to ISLE generated code.
I don't think references will work as FooRef
presumably is still needed when you mutate the IR, which invalidates all outstanding references.
Happy to think about options here, and if you have a working solution to start with, that's even better! The issue I ran into before with this is that all external calls are on a mut Context, so outstanding borrows cause lifetime-overlap errors. In the end it was simpler to use value semantics everywhere
I'd echo the suggestions to perhaps use entity indices as an alternative, unless there's a strong reason that won't work (e.g. the borrowed thing is deep in a data structure that can't be easily indexed)
Thanks for the reply! The reason why I think FooRef<'a>
would work is that it has the same lifetime as the whole context (Context<'a>
), so it is not constrained by the &mut Context
borrow lifetime (I'm not mutating existing data structures; The whole input to ISLE is immutably borrowed and I'm generating new code (LLVM IR) based on that).
I think using entity indices is a good idea to test out with, but doing so would require changing many other parts of my codebase. So for now I'm going to try to add a type parameter to the context and see how well it goes.
Rynco Maekawa said:
The whole input to ISLE is immutably borrowed and I'm generating new code (LLVM IR) based on that).
In that case keeping references around should indeed be fine. Adding support for it to ISLE makes sense.
I'm now digging into the code. My plan on changing the language is the following:
<def> ::= ...
| "(" "pragma" <pragma> ")" ;; Seems there's already a pragma parser in the code!
;; Adds the lifetime pragma. Lifetimes are always bound to the context.
<pragma> ::= "context_lifetime" <lifetime-ident>*
;; Lifetime identifiers start with quotes (`'`)
<lifetime-ident> ::= "'" ( "A".."Z" | "a".."z" | "_" | "$" | "0".."9" | "." )*
;; Primitive types can now have a lifetime parameter.
<typevalue> ::= "(" "primitive" <primitivetype> ")" ;; <-
| ...
<primitivetype> ::= <ident>
| "(" <ident> <lifetime-ident>* ")"
And by the way, since I already have a plan, should I open up an issue in the wasmtime repo now?
Sure, please feel free to create an issue and all of us can discuss further there!
Ah, I see you already did here: https://github.com/bytecodealliance/wasmtime/issues/5862
Last updated: Dec 23 2024 at 13:07 UTC