-
Notifications
You must be signed in to change notification settings - Fork 229
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
Module does not hold reference to context #27
Comments
Thanks for your report! Oh, yep, that's a problem. A problem we have here is that the LLVM api manipulates opaque pointers to start with, which means that using |
Great catch! I was unaware of this issue. I think we should be able to hand out I'll get to work on the |
Would you mind providing some simple examples of how to reproduce this issue? They'll be super helpful as test cases. Thanks! |
Sure, the most simple test case would look something like this: fn main() {
let module = {
let context = Context::create();
context.create_module("test")
};
// do something with module here
} Currently, this code will trigger undefined behaviour (on my macbook it spits out "an unknown error occured"). |
One library that also fixes this by using You should consider using |
One last note after thinking about this for a while.
In my compiler for example, I have a struct that looks something like this: pub struct LLVMBuilder {
ctx: Context,
module: Module,
builder: Builder,
} Would this even be possible with &Builder, that is owned by the Context? |
I believe LLVM does support multithreading, but it isn't on my radar to support anytime soon. I see it as a way advanced feature that will likely have its own set of complications. I did create a ticket for it here, though: #28 I think it should be straightforward to convert any That's a great point.
|
@nicokoch So I'm having trouble reproducing this for builder: let builder = {
let context = Context::create();
context.create_builder()
};
builder.build_unreachable(); but there is no invalid memory access as far as I can tell. Tests pass fine (though I know that's not a perfect validation) Are you seeing otherwise on your system? |
I can test again on monday, I haven't really investigated in the builder situation yet. |
For the builder it doesn't crash on my machine either. Nonetheless, even if no invalid memory access occurs, it doesn't mean it cannot occur under any environment.
Yes, Rc does allocate, my bad. |
Yeah, I agree but I would feel better about the builder fix if there was some way to verify it works. |
There is! Just add a println! inside the drop implementation and verify that Context's drop is always called after Builder's drop (for example with the code snippet from earlier) |
I'm not convinced builders are as tied to the hip to their context as modules are. You suggested verifying the context dropped after builder: let context = Context::create();
let builder = context.create_builder();
drop(builder);
drop(context); but that did not yield any invalid memory access either. For example using the builder with a context other than the one it was created with (and the original destroyed) works fine: let builder = {
let context = Context::create();
context.create_builder()
// Original Context drops fine
};
// Builder continues to function with different context
let context = Context::create();
let module = context.create_module("my_mod");
let void_type = context.void_type();
let fn_type = void_type.fn_type(&[], false);
let fn_value = module.add_function("my_fn", &fn_type, None);
let entry = fn_value.append_basic_block("entry");
builder.position_at_end(&entry);
builder.build_unreachable();
module.print_to_string();
// Prints: "; ModuleID = \'my_mod\'\n\ndefine void @my_fn() {\nentry:\n unreachable\n}\n");
// 2nd Context drops fine
// Builds drops fine This is looking like a |
I noticed a major design flaw in the current implementation of modules.
The module needs to hold a reference to the context it was created in. Otherwise it's possible to drop the context before dropping the module, which will result in undefined behaviour.
I just ran into the error in a toy compiler I'm building.
The same also applies to
Builder
and itsContext
.The easiest way to implement this is probably by having a member
Rc<Context>
inModule
andBuilder
The text was updated successfully, but these errors were encountered: