Hey peers,
I recently got into cranelift and feel stuck on a question:
How does one compile and use a record type in cranelift?
say I come across this and need to compile it:
struct Planet {
name: String, // just another struct
x: f32,
y: f32,
}
Thanks a lot for reading through this!
Cranelift doesn't have any types other than booleans, integers, floats and vectors. If you want to store more complex data you will need to decide on a memory layout for the data and manually store each piece in memory.
Cranelift ir is not a high level language. It is much closer to machine code executed by your cpu.
Well, I havent figured out how to create vectors either. would you help me a little by explaining?
Also thank you for the insanely quick answer. This is breathtaking
Vectors are similar. You can use imul_imm
to calculate the offset of the element in the vector. Growing it will require calling realloc
or something like that.
I see. So if I want to pass structs to functions, I need to use vectors? (a type like [u8; 64]) ?
Or do I just always use pointers?
@Nils Martel the usual way is just to use pointers
For temporary storage, if your compiler needs to build a struct in memory in order to pass it, you can add a stackslot to the function then stack_addr
to get the address
and compute addresses from that base using offsets depending on how you choose to lay out the struct
Thank you for pointing me in this direction :)
What is the usual way of requirering heap memory? Directly calling _malloc_?
It depends on how you want to build the runtime for your system! Cranelift can generate a call to any library function you like, including malloc
, or it can allocate space in the stack frame (the stackslot I mentioned above)
IMHO it's slightly unusual for a compiler to emit calls to malloc
directly; some higher-level languages that are garbage-collected would allocate some heap for temporary objects then let the GC free it, but malloc
is a lower level (in that it requires an explicit free
)
But Cranelift proper doesn't care what you call; it will happily do the call then emit loads/stores as you generate them
This is great news!
For now I'm mostly interested in native stuff, which would require libc.
The more questions I ask, the more I realize all the stuff that I do not know.
Doesn't rustc call malloc
and free
directly? (sure, the user can choose the implementation)
Also: How do I call arbitrary C libraries during compilation?
I've seen an example aclling into libc by simply emmiting some puts
function call. but I didn't found any reference about how it knew where to find the puts
function. Does it work the same way for any other c- library (maybe GTK, etc.)?
Doesn't rustc call malloc and free directly? (sure, the user can choose the implementation)
The user code does. In addition rust is not a managed language like javascript, java or wasm.
Also: How do I call arbitrary C libraries during compilation?
You can use module.declare_function("puts", Linkage::Import, &sig)
to get a reference to the puts
function. If you don't define it anywhere, it will likely resolve to the puts from libc. This works the same for any other function and any other library you link to.
This is crazy helpful, thank you :)
Last updated: Dec 23 2024 at 12:05 UTC