Zig Version
0.17.0-dev.224+c166c49b1
Steps to Reproduce and Observed Behavior
Consider the minimal example:
pubconstRegister=packedstruct(u8){a:u4=0,b:u4=1,};constgpio:*volatileRegister=@ptrFromInt(0x0123);pubfnmain()void{gpio.*=.{.b=2,};}
Compile with zig build-exe -femit-llvm-ir=out.ll example.zig:
; Function Attrs: nounwind uwtable
define internal fastcc void @example.main(ptr nonnull %0) unnamed_addr #6 align 1 !dbg !89551 {
Entry:
%1 = load i8, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
%2 = zext i4 -1 to i8, !dbg !89552
%3 = shl i8 %2, 4, !dbg !89552
%4 = xor i8 %3, -1, !dbg !89552
%5 = and i8 %1, %4, !dbg !89552
%6 = zext i4 2 to i8, !dbg !89552
%7 = shl i8 %6, 4, !dbg !89552
%8 = or i8 %7, %5, !dbg !89552
store volatile i8 %8, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
%9 = load i8, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
%10 = zext i4 -1 to i8, !dbg !89552
%11 = shl i8 %10, 0, !dbg !89552
%12 = xor i8 %11, -1, !dbg !89552
%13 = and i8 %9, %12, !dbg !89552
%14 = zext i4 0 to i8, !dbg !89552
%15 = shl i8 %14, 0, !dbg !89552
%16 = or i8 %15, %13, !dbg !89552
store volatile i8 %16, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
ret void, !dbg !89552
}
Expected Behavior
As you can see, there are 2 volatile writes. There should only be 1. Curiously, if I remove .b = 2, from the above, the following correct code is output:
; Function Attrs: nounwind uwtable
define internal fastcc void @example.main(ptr nonnull %0) unnamed_addr #6 align 1 !dbg !89551 {
Entry:
store volatile i8 16, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
ret void, !dbg !89552
}
Curiously, the below also works as expected:
pubfnmain()void{consttmp:Register=.{.b=2,};gpio.*=tmp;}
; Function Attrs: nounwind uwtable
define internal fastcc void @example.main(ptr nonnull %0) unnamed_addr #6 align 1 !dbg !89551 {
Entry:
#dbg_declare(ptr @__anon_32774, !89552, !DIExpression(), !89553)
store volatile i8 32, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89554
ret void, !dbg !89554
}
### Zig Version
0.17.0-dev.224+c166c49b1
### Steps to Reproduce and Observed Behavior
Consider the minimal example:
```zig
pub const Register = packed struct(u8) {
a: u4 = 0,
b: u4 = 1,
};
const gpio: *volatile Register = @ptrFromInt(0x0123);
pub fn main() void {
gpio.* = .{
.b = 2,
};
}
```
Compile with `zig build-exe -femit-llvm-ir=out.ll example.zig`:
```llvm
; Function Attrs: nounwind uwtable
define internal fastcc void @example.main(ptr nonnull %0) unnamed_addr #6 align 1 !dbg !89551 {
Entry:
%1 = load i8, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
%2 = zext i4 -1 to i8, !dbg !89552
%3 = shl i8 %2, 4, !dbg !89552
%4 = xor i8 %3, -1, !dbg !89552
%5 = and i8 %1, %4, !dbg !89552
%6 = zext i4 2 to i8, !dbg !89552
%7 = shl i8 %6, 4, !dbg !89552
%8 = or i8 %7, %5, !dbg !89552
store volatile i8 %8, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
%9 = load i8, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
%10 = zext i4 -1 to i8, !dbg !89552
%11 = shl i8 %10, 0, !dbg !89552
%12 = xor i8 %11, -1, !dbg !89552
%13 = and i8 %9, %12, !dbg !89552
%14 = zext i4 0 to i8, !dbg !89552
%15 = shl i8 %14, 0, !dbg !89552
%16 = or i8 %15, %13, !dbg !89552
store volatile i8 %16, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
ret void, !dbg !89552
}
```
### Expected Behavior
As you can see, there are 2 volatile writes. There should only be 1. Curiously, if I remove `.b = 2,` from the above, the following correct code is output:
```llvm
; Function Attrs: nounwind uwtable
define internal fastcc void @example.main(ptr nonnull %0) unnamed_addr #6 align 1 !dbg !89551 {
Entry:
store volatile i8 16, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89552
ret void, !dbg !89552
}
```
Curiously, the below also works as expected:
```zig
pub fn main() void {
const tmp: Register = .{
.b = 2,
};
gpio.* = tmp;
}
```
```llvm
; Function Attrs: nounwind uwtable
define internal fastcc void @example.main(ptr nonnull %0) unnamed_addr #6 align 1 !dbg !89551 {
Entry:
#dbg_declare(ptr @__anon_32774, !89552, !DIExpression(), !89553)
store volatile i8 32, ptr inttoptr (i64 291 to ptr), align 1, !dbg !89554
ret void, !dbg !89554
}
```