FlorenceOS / newton

BSD Zero Clause License
20 stars 4 forks source link

Emit custom machine code #9

Open N00byEdge opened 1 year ago

N00byEdge commented 1 year ago

Something like the following:

fn fun() void {
    var local: u64 = undefined;
    @emit(.{
        .init = .{
            .rax = 4,
            .rcx = 5,
        },
        .bytes = .{1, 2, 3, 4},
        .clobbers = .{.rcx, .rdx},
        .post = {
            local = @fetch(.rax);
        },
    });
}
48cf commented 1 year ago

maybe breaking it down into 2/3 separate builtins would be a better idea? i.e. @register which would allow for getting/setting the register's value and the @emit which would let you emit custom code + mark clobbered registers? i feel like implementing a builtin with so many user values might be a bit of a hassle... also the first builtin i proposed would be nice for writing isr routines ;^) you could get all the registers easily without a redundant @emit expression

example usage of @register and @emit with my proposed changes, this example should perform a linux write syscall and retrieve the return value to a local variable:

@register(.rax) = 1;
@register(.rdi) = 0;
@register(.rsi) = @ptr_to_int("Hello world!".&);
@register(.rdx) = 12;
@emit(.{0x0f, 0x05}, .{.rax});
const result = @register(.rax);
N00byEdge commented 1 year ago

Uh, what I don't like about that is that we don't have a way to know that the inputs depend on the register assignments and that the outputs depends on the @emit which means things could start to break with optimizations (the register assignments can be optimized out, reordered to after the asm or whatever).

What you sent above is the IR that will be generated (but with some dependencies) anyways.

48cf commented 1 year ago

good point, its very possible that you explained it to me already like this but i just forgot, what about making @register and @emit volatile? or would that screw with optimizations too much?

N00byEdge commented 1 year ago

Yes, that would prevent a lot of optimizations like being able to remove an unused, non-volatile @emit statement or an unused @register result.