-
Notifications
You must be signed in to change notification settings - Fork 7
Vtable Instance Support #308
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
base: main
Are you sure you want to change the base?
Conversation
Definitions of `sizeof`, `alignof` & `opaque`
|
Quick response before looking at this more in-depth:
|
|
Thanks for the discussion! Yes, I think to re-compose the logic of initialising the global variables is a more systematic approach. That could be another PR on this, haha. As there might be additional complexity as to what to globalize and what should remain local. E.g., if we have While on the other hand, it would also be suitable for this specific case to handle vtable instances to be simpler -- we may do this via a more radical optimization -- i.e., by inlining the locals and optimizing the As for the second case, I'm rather curious about whether we actually should keep the compiler error, as |
|
Ah, no, I was then reminded by my notes on this case that theoretically, we should not have to use an additional function (i.e., As internally, Rust has the same restriction as C that it will need to compute everything at compile time and load the compile-time constant as the final target value in runtime. So, theoretically, we can ask Charon to ask Rustc to compute the final value, which, by a simple simplification, should simplify everything to leaving only the address-taking expressions for us to globalize, e.g., |
|
So, for the optimizations, do you think radically do inlining in at least the globals is acceptable? Or, how would you view the potential risk? Especially, I cannot see the problem of turning all |
ok sounds good -- then in that case the plan is
the way we have done these things historically is to emit a
|
|
Thanks for the discussion! We agree with the first point. As for the second, the |
|
You could implement it with a macro that uses |
|
Sure, will try, thanks! |
|
Updated, I guess this is what you mean? |
|
Yes. Thanks! |
|
OK, we then further refined the problem, and added the generics to globals (see the latest two commits). But then Krml complains that: | DGlobal (_, lid, n, t, _) ->
assert (n = 0);
{ env with globals = M.add lid t env.globals }This is in Krml, so we are not sure if it is a fundamental problem. Could you please have a look? FYI, we are testing against the example: fn use_debug(_d : &dyn std::fmt::Debug) {}
fn main() { use_debug(&&1) }With the Charon branch in https://github.com/ssyram/charon/tree/tmp-empty-drop -- this branch now generates an empty stub for the |
|
I will have a look, thank you. Can globals have const generics in Rust? |
|
I think so, but should have a test to confirm if Rust itself has. Anyway, the generated LLBC will indeed have global with CGs. This is because the vtable instance will have the same generic params as the impl environment. But if this is a tough fix, we can ignore that and simply work on type parameters only. As I guess there is no use of vtable instances with CG in our urgent need. |
|
This diff in krml seems to be enough for your example to go through: after that, your example fails with I believe this is because the references to the vtable have a name that is different from the vtable declaration; you also need to make sure references to the (now-polymorphic!) vtable are under an Hope this unblocks you -- let me know how far you get! Cheers. |
|
Thanks for this! We've tried the method, but we then found that it is more complicated than conceived that we will need to collect the Out of curiosity, I'm not sure that for example, in line 1887 of this PR, is this substitution a correct way or we should recover the |
|
Is the vtable type a parameterized data type T<'a> and instances have type T? If so, yes, ETApp is necessary because it will trigger monomorphization |
This reverts commit 5fa9ee8.
|
@protz Thanks for the help on the typedef struct dyn_trait_Trait__vtable__s
{
size_t size;
size_t align;
void (*drop)(Eurydice_dst_ref_mut_dd x0);
void (*method_method)(Eurydice_dst_ref_mut_dd x0);
core_marker_MetaSized__vtable_ *super_trait_0;
}
dyn_trait_Trait__vtable_;
dyn_trait_Trait__vtable_
dyn_trait__dyn_trait__Trait_for_i32___vtable_ =
{
.size = Eurydice_sizeof(int32_t, size_t), .align = Eurydice_alignof(int32_t, size_t),
.drop = dyn_trait__vtable_drop_shim__92, .method_method = dyn_trait_method__vtable_method__92,
.super_trait_0 = Eurydice_opaque("missing supertrait vtable",
core_marker_MetaSized__vtable_ *,
core_marker_MetaSized__vtable_ *)
};Basically we need this #define Eurydice_opaque(reason, t, _) *((t *)KRML_HOST_MALLOC(sizeof(t)))will cause Currently I'm using #define Eurydice_opaque(reason, t, _) (t)0which can pass the test for this |
|
I don't have a better idea. Is it giving you a compiler warning, or is it working ok? |
It's working for now. Then I just keep it as is |
Continuing from #259, we propose another PR to support vtable instances, specifically generating concrete vtable pointers. Currently, Eurydice only supports generating vtable structs but not their instances.
We added a test by renaming
dyn_trait_struct_typetodyn_traitand included a test case withuse_trait(&100), which involves casting&i32to&dyn Trait.Charon currently lacks proper implementation for the
dropfield in vtable instances and implicit implementations. The latter is unavoidable since every vtable requiresT: MetaSized, which relies on an implicit implementation. To address this, we introduced a comprehensive placeholder forOpaquevalues via a new built-in functionEurydice::opaque<T>(reason: char*) : T. This should resolve currently unhandled cases.For the
dropfield, we temporarily implemented a Charon version that generates a placeholder value. Therefore, this PR can only be merged afterdropis properly implemented, and it would be preferable to wait until implicit implementations are complete. The temporary version we used is https://github.com/ssyram/charon/tree/tmp-empty-drop.However, two issues remain even after Charon is fully prepared:
Vtable Instance Initialisation
The primary concern involves the generated code for vtable instances. Currently, we produce:
This code is incompatible with C compilers because the initializations of
_vtable__local_2anddyn_trait__dyn_trait__Trait_for_i32___vtable_involve non-constant expressions. The only viable solution is to aggressively inline local variables, particularly within global variables.Opaque handling
Also, the implementation of
opaquenow also raises compiler complaints:error: indirection of non-volatile null pointer will be deleted. I'm not sure if this is a problem -- I guess it should raise compilation complain as opaque itself is not acceptable for code compilation.