FractalFir / rustc_codegen_clr

This rust compiler backend(module) emmits valid CIL (.NET IR), enabling you to use Rust in .NET projects.
MIT License
1.56k stars 35 forks source link

Support for drops #8

Closed karashiiro closed 7 months ago

karashiiro commented 1 year ago

I was reading the code and noticed that drops aren't implemented yet. Are there any known complexities there that have prevented that from being done? Hoping to look into that as a starting point.

I think it's akin to a using statement, which gets compiled to a simple .try {} finally {}, but implementing drops that way that requires keeping track of scopes, and I can't tell if the existing codegen does that or not.

FractalFir commented 1 year ago

I did not handle drops because it required a bit of research into getting the proper drop function. The newest commit includes code that finds this drop glue, but does not yet do anything with it.

Rust drops are a bit like a using statement, but there is far more complexity to them. Stack unwinding is a whole beast of its own, and will be something left untouched until far, far, much later. The current strategy for panics (Rust equivalent of exceptions) is assuming that they won't happen, and if they do, then the program should abort. Catching panics is very uncommon in rust code, since they are supposed to be used only for fatal errors. Most rust programs use the Result type for non-fatal error, and it already works.

Calling the drop function is also quite a bit of work, even tough most of the complexity revolves around things that are not yet supported anyway.

Drops are probably one of the harder places to start with.

The project is currently quite hard to get into (due to lack of documentation), but here are some things which should be a bit easier:

  1. functions ptr_set_op and deref_op in place.rs. They get a type as an input and return the CIL op required to either store a value in it, or get the value behind the pointer. It currently supports a fraction of the types, and may require adding new opcodes inside cil_op.rs to add functionality.
  2. Writing tests - this is the easiest part, albeit most boring.
  3. The opt module - It is responsible for cleaning up the CIL and optimizing it. As you could probably tell by looking at the .il files, there is still a lot of room for optimizations. This one involves taking a look at the CIL, identifying a common pattern of operations, and replacing it automatically with a more optimal one.
  4. Implementing operations involving 128-bit integers - currently, you can't cast from/to and preform any arithmetic operations on 128 bit ints, since doing each different operation on them involves a different call. You can find relevant code in binops.rs and casts.rs. This is pretty boring, but could be a good starting point.
karashiiro commented 1 year ago

I'm thinking I'll look into that pointer deref one, it seems the most immediately important out of all of them. I'll make a new issue for questions on that once I have some.

I've already read through most of the codebase (and parts of MIR) while debugging #6/#7 and I think I understand how it fits together, so I'm mostly focused on what the biggest gaps are today. The opt thing sounds interesting, but realistically I think that's the least-relevant piece right now, and the most likely to change as more instructions are supported.

Tests are always important, but I'm not sure how much of this can be meaningfully tested beyond E2E tests, and we have plenty of those already. I'll have to look at cranelift at some point to see what sorts of unit testing they do.

Regarding the 128-bit arithmetic thing, how common is that in the ecosystem? I imagine it's mostly used in cryptographic libraries (which are important to support) but not too much outside of that.

FractalFir commented 1 year ago

Added some WIP support for trivial drops in 82ee5c26ac2d6bb0a3515c1f6029bd596566f582. Drop trait implementations currently can't compile and instead throw, but they are called.

FractalFir commented 9 months ago

Drops now work in most cases (not for trait objects, which are not supported at all yet).