Stream: general

Topic: Compiling structs to cranelift IR


view this post on Zulip Nils Martel (Aug 09 2021 at 16:38):

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!

view this post on Zulip bjorn3 (Aug 09 2021 at 16:40):

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.

view this post on Zulip bjorn3 (Aug 09 2021 at 16:41):

Cranelift ir is not a high level language. It is much closer to machine code executed by your cpu.

view this post on Zulip Nils Martel (Aug 09 2021 at 17:02):

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

view this post on Zulip bjorn3 (Aug 09 2021 at 17:04):

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.

view this post on Zulip Nils Martel (Aug 09 2021 at 17:12):

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?

view this post on Zulip Chris Fallin (Aug 09 2021 at 17:15):

@Nils Martel the usual way is just to use pointers

view this post on Zulip Chris Fallin (Aug 09 2021 at 17:15):

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

view this post on Zulip Chris Fallin (Aug 09 2021 at 17:15):

and compute addresses from that base using offsets depending on how you choose to lay out the struct

view this post on Zulip Nils Martel (Aug 09 2021 at 17:16):

Thank you for pointing me in this direction :)

What is the usual way of requirering heap memory? Directly calling _malloc_?

view this post on Zulip Chris Fallin (Aug 09 2021 at 17:17):

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)

view this post on Zulip Chris Fallin (Aug 09 2021 at 17:18):

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)

view this post on Zulip Chris Fallin (Aug 09 2021 at 17:18):

But Cranelift proper doesn't care what you call; it will happily do the call then emit loads/stores as you generate them

view this post on Zulip Nils Martel (Aug 09 2021 at 17:21):

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.)?

view this post on Zulip bjorn3 (Aug 09 2021 at 17:24):

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.

view this post on Zulip Nils Martel (Aug 09 2021 at 17:27):

This is crazy helpful, thank you :)


Last updated: Dec 23 2024 at 12:05 UTC