rust-lang / miri

An interpreter for Rust's mid-level intermediate representation
Apache License 2.0
4.34k stars 332 forks source link

Building a REPL on top of miri #511

Closed oli-obk closed 3 years ago

oli-obk commented 5 years ago

@technetos so the steps are essentially

  1. create a loop around the main miri code in the miri binary
  2. read some text from the user and append it to a mutable string defined outside the loop
  3. format!("fn main() { let _: &'static *const () = &std::ptr::null(); {}}}", mut_string) to create the "main.rs" that you feed to the rust evaluator
  4. the miri-hook that currently starts the evaluation will now call
    let snapshot = GlobalId { promoted: Some(0), instance: main_instance };
    let _ = tcx.const_eval(ParamEnv::empty().and(snapshot));
  5. before that you do
    tcx.const_eval = |arg| {
        if arg.value == snapshot {
            // run original miri evaluator
        } else {
            // run `const_eval_provider`
        }
    };

    (well not quite, but have a look at where const_eval_provider is used and follow the call stack up until you see how to do the overriding thing in miri)

RalfJung commented 5 years ago

Why are these crazy hacks involving the promoted necessary and what do they even do?

oli-obk commented 5 years ago

Oh I forgot, running the miri evaluator should not pop the final function, but instead "just" create a special allocation that contains all (reachable?) allocations from Memory and all other state required like block index + statement index. Returning a pointer to that allocation will cause the promoted to have that value and incremental to store all that data in the cache.

Before starting the miri evaluator the next time, we make incremental give us the old value (more hacks, yay!) and restore the state from that.

RalfJung commented 5 years ago

Wtf... you definitely are crazy.^^

theduke commented 5 years ago

I believe a moderately fast Rust REPL would do wonders for the Rust dev experience.

@oli-obk how useful and fast would a miri based repl be? Fast enough to provide utility vs eg re-running code in the playground?

Are your basic implementation suggestions from above still valid? If so I'm interested in giving this a try.

Also, could miri theoretically be used to build a debugger with breakpoints and the ability to run code at those breakpoints? (printing values, modifying local variables before continuing, ...)

oli-obk commented 5 years ago

how [..] fast would a miri based repl be?

around 100000 times slower than direct execution. Depends on the kind of things that are happening though.

Also, could miri theoretically be used to build a debugger with breakpoints and the ability to run code at those breakpoints? (printing values, modifying local variables before continuing, ...)

I has been used to build such a thing practically: https://github.com/oli-obk/priroda

We need to update it to the latest master branch though :)

nico-abram commented 5 years ago

How fast would it be compared to actually compiling the code, not just the direct execution?

BatmanAoD commented 4 years ago

I'm not sure how close this is to what you were envisioning, @oli-obk, but here's an approach aimed at making Rust usable in Jupyter notebooks: https://github.com/google/evcxr

bjorn3 commented 4 years ago

And there is going to be https://github.com/rust-lang/compiler-team/issues/213.

BatmanAoD commented 4 years ago

@bjorn3 Very cool! I did not know about that, actually.

zacps commented 3 years ago

What's the current status of this? Has it been superseded by the possibility of a cranelift backend?

ibraheemdev commented 3 years ago

Would a miri based REPL be faster than evcxr_repl? evcxr essentially writes user input to a crate and compiles that, saving previous results in a HashMap. Also, would a cranelift jit based REPL be more performant?

oli-obk commented 3 years ago

anything miri based will never be fast. But it would reduce duplication between the repl and miri since they can share lots of code.

RalfJung commented 3 years ago

I don't see why a repl would have lots of code in common with Miri?

oli-obk commented 3 years ago

well, if you do the interpretation on the MIR level, then you will end up with some sort of mir interpreter similar to the miri-engine. It could be implemented on something different (e.g. LLVM-IR) or just JIT the code, but then all the OS stuff still needs to get handled somehow, and that will probably be similar to what miri is doing.

RalfJung commented 3 years ago

Right but I don't see why a REPL would be based on interpretation, TBH.^^

oli-obk commented 3 years ago

True... So I guess we stop tracking this here and close this issue?

bjorn3 commented 3 years ago

The advantage of building a repl on top of miri is that it could run in the browser. Rustc can successfully be compiled to wasm32-wasi with a few small changes.

RalfJung commented 3 years ago

The playground can also run in the browser though... and honestly compiling and running this on a server will likely still be faster than running Miri in Wasm.^^

oli-obk commented 3 years ago

I'm going to go ahead and close this. Even if a REPL will be miri based, it's not necessary to track this here.

toothbrushes commented 2 years ago

@oli-obk is this being tracked anywhere else tho? I would love a Rust REPL, where y'all at? One idea is we could create a project, or zulip channel #project-repl

bjorn3 commented 2 years ago

Have you seen evcxr? It has both support for jupyter notebooks as well as a regular repl.