Hello again! It seems that store
on r_ptr
here has been used wrong. It gives a SEGFAULT. Where am I wrong?
https://codeberg.org/farooqkz/wakegp/src/branch/master/src/compiler.rs#L159
https://codeberg.org/farooqkz/wakegp/src/branch/master/src/compiler.rs#L163
r_ptr
comes from the second argument of the function(see this and this). The offset is calculated by the index(r0
) multiplied by size of each element in the array(https://codeberg.org/farooqkz/wakegp/src/branch/master/src/compiler.rs#L188).
Thanks in advance!
The problem was that I had to map a memory and make it executable. I still have other questions. Should I ask here or open a new topic?
Asking here is fine. Won't get around to answering any questions today (CET) though.
I cannot find brnz
in the docs which is used here:
https://github.com/Rodrigodd/bf-compiler/blob/master/cranelift-jit/src/main.rs#L219
I basically doing an fcmp
, if it's true, there will be a jump, either backward or forward within the function(jump offsets are guarrented to be always inside my function). If it's false, there won't be any jump.
Furthermore, for forward jumps, how can I jump to an address which I've yet to write the instructions for? I mean if I don't have instructions yet, how do I get the jump address?
Edit: nvm this. There is an example in the bf compiler repository.
hmm it seems that repo is using an ancient version of cranelift :)
There is br_if
and br_table
. The first accepts arguments for both the true
and else/false
cases which does not match in my use case. The latter seems more like it, but I'm unsure if I can do backward jumps with it.
Clif ir uses basic blocks rather than extended basic blocks, so every branch instruction is always jumps to another block and must be the last instruction in the block. In the backend a jump to the block immediately following the current block will be optimized away though.
brz/brnz no longer exist and have been replaced by br_if when we moved from extended basic blocks to basic blocks.
Can you please post an example on how to use do a simple if else statement like in C with cranelift?
Here's an example of the use of brif
in Wasmtime's translation to CLIF: https://github.com/bytecodealliance/wasmtime/blob/66910067642ce2ddf5509845306508f89a24fc9e/crates/cranelift/src/func_environ.rs#L913
note the "continuation block" -- that's a common idiom, if you have what is logically a "one-way branch" (if condition, go somewhere else)
and note you can create blocks so you have their labels for targets before you fill them in
Thanks!
Hello. I've got time to get back to this. A question. If I just want to continue execution in the else
, I should put the rest of the program and the continue block. right?
More on details, I've got a function. It executes sequentially and then returns one of memory cells at the end. I want to return a constant(-1.0f32) early if a condition is met. Let me know if there is a better approach.
Bump
Sorry, it's hard to help you debug your implementation without actually diving into it (and in general I don't have time to dive into others' projects and help them debug). The abstraction that Cranelift provides is hopefully clear: blocks, and jumps between them. How you map your control flow to that is up to you
Thanks. But I still don't know how to use brif
. If I want to continue execution, should I create a new block for the rest of instructions and make it else
block?
I mean there is a then
block which is my code I want to execute. But if the condition is not met, there is else
block. What the else
block would be? the continuation of the instructions? And then should I create new blocks whenever there is a condition as continuation block?
If you have something like if (cond) { foo... } else { bar... } rest...
in source code you can lower this to clif ir like
block0:
brif cond, block1, block2
block1:
foo...
jump block3
block2:
bar...
jump block3
block3:
rest...
I have if (cond) { foo } rest...
so I was right it seems. Everytime a condition comes, I should create a new block for the rest
In this example, what is usage of null block? https://github.com/bytecodealliance/wasmtime/blob/66910067642ce2ddf5509845306508f89a24fc9e/crates/cranelift/src/func_environ.rs#L902
But if the condition is not met, there is
else
block. What theelse
block would be? the continuation of the instructions? And then should I create new blocks whenever there is a condition as continuation block?
Yes, exactly; to get a deeper understanding of this, it might be good to read about basic blocks and control-flow graphs. These are the fundamental compiler concepts at play here.
Specifically, the semantics of brif
are if (condition) goto then_block; else goto else_block;
. That's fully general and you can translate whatever control-flow you need into that, but as you note, you may need to create an arbitrary number of blocks.
In this example, what is usage of null block? https://github.com/bytecodealliance/wasmtime/blob/66910067642ce2ddf5509845306508f89a24fc9e/crates/cranelift/src/func_environ.rs#L902
Here we are getting into the specifics of Wasmtime's internal representations, but in that code, null_block
is the else-target of a brif
a few lines below, and is branched to if value
is false. Specifically here it is testing if an entry in a table is null or not (so all-zeroes is "false" to brif
and branches to null_block
).
Thanks
Last updated: Feb 28 2025 at 03:10 UTC