Hi all, I am trying to implement a brainfuck jit in cranelift. I cannot figure out how to implement the tape. I have basic compiler knowledge (implemented a few toy interpreted languages). This is my first time attempting jit. Any help is appreciated.
Brainfuck clasically works with a 30_000 cell tape and 1 byte cells. As such you could allocate a 30_000 byte buffer and pass a pointer to this to the jitted code as argument. Next you can have the current tape location as argument and return value. Then you can then use iadd to add the buffer address and tape location to get the cell address and finally load.i8 and store.i8 to load and store the current cell.
You will probably want to do bound checking to ensure that the brainfuck code doesn't go out out of the 30_000 cell bound.
Would it be possible to allocate the buffer inside cranelift? I also want to compile it using cranelift-object.
From what I can currently tell, I would have to use DataContent to declare data in the module. I'm not sure how i would use it afterward though.
Yes, on unix you can call malloc and on windows I believe it is VirtualAlloc or something like that.
For dynamic allocation that is.
If you want a single static tape, you can use module.declare_data + module.define_data to define the tape and then module.declare_data_in_func followed by builder.ins().symbol_value(global) to get the address of the tape.
Trying to load from the tape address gives an error.
let tape_addr = builder.ins().symbol_value(int, tape);
let load = builder.ins().load(
types::I8,
MemFlags::new(),
tape_addr,
Offset32::new(0),
);
terminated by signal SIGSEGV (Address boundary error)
How did you define the tape?
let tape_id = {
self.data_ctx.define_zeroinit(30_000);
let id = self
.module
.declare_data("tape", Linkage::Local, true, false)
.unwrap();
self.module.define_data(id, &self.data_ctx).unwrap();
self.data_ctx.clear();
id
};
let tape = self.module.declare_data_in_func(tape_id, &mut builder.func);
Did you call module.finalize_definitions() before calling the jitted function?
aye
let id = self
.module
.declare_function("main", Linkage::Export, &self.ctx.func.signature)
.unwrap();
self.module.define_function(id, &mut self.ctx).unwrap();
self.module.clear_context(&mut self.ctx);
self.module.finalize_definitions();
let code = self.module.get_finalized_function(id);
Weird. No idea what is going on. Sorry.
Could it be is_pic
on a Mac M1 (aarch64)? Do we have a specific error for that, or do we just crash?
@Mensch272 Is there a small sharable snippet that we could test locally?
I think we crash with a descriptive message ("PLT is currently only supported on x86_64"), so its probably not that.
I'm running fedora 36 with selinux-fix. I'll create a new project and share it here.
Thanks! :heart:
I created a new rust project using cargo, and copied the code from my previous project. The new project builds and runs correctly. The old project still throws the same error even after running cargo clean
. Suffice it to say I am extremely confused. I will try to see if I can replicate the error.
Mensch272 has marked this topic as resolved.
Last updated: Dec 23 2024 at 12:05 UTC