Hey.
I am trying to use packed structs to model memory mapped peripherals, but am getting some really weird results with the generated code. I am compiling for thumb-freestanding-none.
I have reproduced it here in godbolt. To me it looks like the compiler is generating a store for each bitfield within the packed struct.
I expected the packed structs backed by a u32 would hide this behavior?
I guess my questions are:
- Is this expected behavior? Is it just not possible to use volatile packed structs?
- What is the recommended way for modeling memory mapped peripherals? I was really hoping these bitfields would be a replacement for having separate enumerations/definitions for each bit.
Welcome to the @Lambosaurus!
That’s really interesting - I was just playing around with your example to see what other code we can generate just to try some different stuff. Probably won’t solve your problem, but I just wanted to play around with it.
I get very minimal assembly by casting the packed struct to a u32 first - you can also directly assign to that field with essentially the same results. I’m not saying the cast is a good idea, it’s just interesting. The struct assignment hits all of those fields. I think @andrewrk is probably the right person to look at this.
Thanks Andrew.
Good to know at least I’m not crazy.
For now I think I’m going to use a wrapper struct that provides inline functions to provide the typing. See the last example here. This generates the right instructions, but is a bit of a letdown for conciseness - especially in the read-modify-write scenario.
Let me know if anyone else has a smarter solution than this, (or a fix would be nice).
Have you tried removing -fstrip from your compile flags? If I change to ReleaseFast and remove -fstrip, here’s what I get:
store_by_struct:
movw r0, #4140
movs r1, #2
movt r0, #16386
str r1, [r0]
bx lr
store_by_u32:
movw r0, #4144
movs r1, #2
movt r0, #16386
str r1, [r0]
bx lr
store_by_register32:
movw r0, #4148
movs r1, #4
movt r0, #16386
str r1, [r0]
bx lr
Looks like it’s actually something to do with -fstrip and ReleaseSmall. I’m still getting the same results if I add -fstrip back to ReleaseFast, and on ReleaseSmall I get your original results either way.
Interesting find. Thanks for looking into this.
I suspect the correlation is because -fstrip automatically happens on ReleaseSmall.
Removing debug symbols is an absolute requirement for me. I cannot budge on -fstrip / ReleaseSmall. My targets have 8K flash, and I have a lot of functionality to jam in there.
Hopefully this helps narrow down the underlying issue at least.
To confirm the relationship between this issue and -fstrip
. When optimizing for ReleaseSmall, the issue disappears when you set -fno-strip
(which prevents the small release stripping symbols by default).
I think you have enough information at this point to open an issue on github. That’s the next place I would go now that things are narrowed down: Issues · ziglang/zig · GitHub
If you get a response, please share it back to the forum so we can help people in the future with this issue 
1 Like
As an update to anyone following this thread, @Lambosaurus created an issue on github and it was added to the 0.13.0 milestones (AKA: Resolve or postpone these issues before releasing 0.13.0).
It may be a bit before a decision is made on this, but it’s being investigated!
1 Like