-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviormiscompilationThe compiler reports success but produces semantically incorrect code.The compiler reports success but produces semantically incorrect code.
Milestone
Description
const spi_tdr = packed struct {
unused1: u7,
lastxfr: u1,
unused2: u4,
pcs: u4,
td: u16,
};
export fn entry(ptr: *volatile spi_tdr) void {
var tmp = ptr.*;
tmp.lastxfr = 1;
ptr.* = tmp;
}
generates
define void @entry(%spi_tdr* nonnull) #2 !dbg !80 {
Entry:
%ptr = alloca %spi_tdr*, align 8
%tmp = alloca %spi_tdr, align 1
store %spi_tdr* %0, %spi_tdr** %ptr, align 8
call void @llvm.dbg.declare(metadata %spi_tdr** %ptr, metadata !96, metadata !DIExpression()), !dbg !100
%1 = load %spi_tdr*, %spi_tdr** %ptr, align 8, !dbg !101
%2 = bitcast %spi_tdr* %1 to i8*, !dbg !102
%3 = bitcast %spi_tdr* %tmp to i8*, !dbg !102
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %3, i8* align 1 %2, i64 4, i1 false), !dbg !102
call void @llvm.dbg.declare(metadata %spi_tdr* %tmp, metadata !97, metadata !DIExpression()), !dbg !102
%4 = getelementptr inbounds %spi_tdr, %spi_tdr* %tmp, i32 0, i32 0, !dbg !103
%5 = load i8, i8* %4, align 1, !dbg !105
%6 = and i8 %5, 127, !dbg !105
%7 = or i8 -128, %6, !dbg !105
store i8 %7, i8* %4, align 1, !dbg !105
%8 = load %spi_tdr*, %spi_tdr** %ptr, align 8, !dbg !106
%9 = bitcast %spi_tdr* %tmp to i8*, !dbg !107
%10 = bitcast %spi_tdr* %8 to i8*, !dbg !107
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %10, i8* align 1 %9, i64 4, i1 true), !dbg !107
ret void, !dbg !108
}
The problem here is call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %3, i8* align 1 %2, i64 4, i1 false), !dbg !102
and specifically the last arg i1 false
. That's a non-volatile load.
This load should be volatile.
Arguably Zig should generate a ptrcast from the struct pointer to a pointer to u32 since that is <= register size, but if LLVM is doing the same thing when lowering memcpys - which it appears to be doing - then it's fine just to set the volatile bit.
We don't really have a way to test this other than pattern-matching the resulting LLVM IR, so I think we'll have to add some tests that do that. I already need something like that for #1682.
Metadata
Metadata
Assignees
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviormiscompilationThe compiler reports success but produces semantically incorrect code.The compiler reports success but produces semantically incorrect code.