memorysafety/rav1d

Cleanup c2rust output in cdf.rs

Closed this issue · 3 comments

  • Cleanup helper functions to take safe arguments where possible (may take raw pointers as arguments currently).
  • General cleanup of c2rust generated code in functions.
  • Restore comments from original C.
  • Replace calls to memcpy with safe Rust copy operations.

I'm exploring this, and thought I'd just convert the memcpys to safe operations. Of course, it's never that simple. Most memcpys in this file originate in a bunch of C macros.

https://code.videolan.org/videolan/dav1d/-/blob/master/src/cdf.c?ref_type=heads#L3952

#define update_cdf_1d(n1d, name) \
    do { \
        memcpy(dst->name, src->name, sizeof(dst->name)); \
        dst->name[n1d] = 0; \
    } while (0)

I assume that the rust code would, in the best case, mirror the C code as much as possible. Macros seem the way to go here. Unfortunately that doesn't quite work for the more complex invocations like

update_cdf_1d(10, dmv.comp[k].classes);

Is there some way to parse the dmv.comp[k].classes bit that I'm missing? You can parse record access just fine but array index makes it much more challenging.

macro_rules! update_cdf_1d {
    ($n1d:expr, $($name:ident).+) => {
        (*dst).$($name).+.0.copy_from_slice(&src.$($name).+.0);
        (*dst).$($name).+[$n1d] = 0;
    };
}

As an alternative, maybe a function-based approach works better?

fn update_cdf_1d<const N: usize>(src: &[u16; N], dst: &mut [u16; N], n1d: usize) {
    dst.copy_from_slice(src);
    dst[n1d] = 0;
}

...

update_cdf_1d(&src.m.filter_intra.0, &mut dst.m.filter_intra.0, 4);

maybe with a #[inline(always)] on there?

Any thoughts on the best way to clean this up?

kkysen commented

In cleaning up similar macros, I've usually turned them into Rust fns or macros. We want to keep the code similar to the C so that backporting is easy, but it doesn't have to be super close always. So your function based approach looks like a good idea. And I don't think there's a way to pass a field path (including array indexing) as a macro argument like C is doing, as you noted. Also, an #[inline(always)] is probably a good idea, too, to match the macro always being inlined, though it'll probably be inlined anyways.

Fixed by #724.