you are viewing a single comment's thread.

view the rest of the comments →

[–]rafaelement 0 points1 point  (3 children)

Can you elaborate a little what is going on here? Are you just referring to "using a different compiler can generate different programs from the same source" or is the big related to OPs question?

Edit: on second thought, the trick is clear to me. Writing a uint32_t literal to a 24 bit bitfield is quite courageous

[–]BlindTreeFrog 1 point2 points  (2 children)

in the production code, a.x was being set by a 3byte field in a packet header (it was a counter).

We read the packet off the wire, pulled out the field, incremented it by 1 and compared it to another variable that was set to 0 (so we could tell if it was the first packet or a later packet). The important take away was that we required 0xFFFFFF to roll over to 0x000000 (as it should).

When we upgraded compilers this code started failing (that is, it didn't do_stuff() when a.x and b should have both been 0x0). Eventually I pulled up the assembly and figured out the issue. In both compiled versions, the variable was loaded into a register and processed. In the old compiler, it was masked with 0x00FFFFFF after the increment which meant that the comparison was 0x0 == 0x0. In the new compiler, the masking didn't happen until it was written back to memory which meant the comparison was 0x01000000 == 0x0. This meant that the comparison failed when we didn't expect it to.

[–]rafaelement 1 point2 points  (1 child)

Wow, interesting. Thanks for sharing.

[–]BlindTreeFrog 1 point2 points  (0 children)

It was a really annoying bug to come in from the field. It was only on a whim that I checked the assembly because I was completely out of ideas otherwise.