jasonwhite / syscalls

Raw Linux system calls for Rust.
Other
110 stars 14 forks source link

[Emulator] Not able to create SysnoMap for Multi Arch using Syscalls::arch::Sysno #48

Open umarfarook882 opened 8 months ago

umarfarook882 commented 8 months ago

Sample Code

let mut map = SysnoMap::<fn() -> i32>::new();
let sys_no = syscalls::x86::Sysno::from(0x10);
map.insert(sys_no, || 1);

Error: expected enum `syscalls::Sysno`, found enum `syscalls::x86::Sysno

jasonwhite commented 8 months ago

Yeah, this is unfortunate. The reason for this essentially boils down to Rust missing const fn in traits (as well as other restrictions around const).

Ideally, the SysnoSet and SysnoMap struct definitions would look something like this:

pub struct SysnoSet<S: SysnoExt = Sysno> {
    data: [usize; S::TABLE_SIZE],
}

pub struct SysnoMap<V, S: SysnoExt = Sysno> {
    // ...
}

the impl of this version of SysnoSet will need to have this vital function:

impl<S: SysnoExt> SysnoSet<S> {
    const fn get_idx_mask(sysno: S) -> (usize, usize) {
        let bit = (sysno.id() as usize) - (S::first().id() as usize);
        (bit / Self::WORD_WIDTH, 1 << (bit % Self::WORD_WIDTH))
    }
}

In order for this to work, we'd need to define SysnoExt like this:

trait SysnoExt {
    // [other stuff]...

    // Doesn't compile:
    const fn id(&self) -> u32;
}

but that doesn't work because Rust doesn't support const fn in traits. Efforts to support this also seem to be a long way off.

const fn in traits wouldn't be needed if SysnoSet and SysnoMap wasn't needed in const contexts, but it has been pretty useful to have (e.g., global static initialization).


An alternative implementation could be to use a macro to stamp out an implementation for each architecture, like this:

I think this is acceptable until const fn in traits exists.