-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setjmp
/longjmp
gives unexpected results
#21810
Comments
Can you specify exactly what you did there? |
I did this, which doesn't change anything even in Debug build. time +=
@as(c_int, @intCast(
@as(isize, @bitCast(
@as(usize, @intFromPtr(
@as(*volatile allowzero anyopaque, @ptrFromInt(@as(usize,
@bitCast(@as(isize,
c.sigsetjmp(&sigjmp_buf, 1)))))))))))); And I also tried this which doesn't work either in Debug build. @as(*volatile c_int, @ptrCast(&time)).* += c.sigsetjmp(&sigjmp_buf, 1); On a side note, separating the assignment produces the good output in Debug build. const rv = c.sigsetjmp(&sigjmp_buf, 1);
time += rv; |
The main difference I see between the two versions is that in the C code the variables in
I assume this attempt didn't work because the read of // don't access these directly
var current_storage: u32 = 2;
var largest: u32 = 2;
var time: c_int = 0;
// only access via these volatile pointers
const current_pointer: *volatile u32 = ¤t_storage;
const largest_pointer: *volatile u32 = &largest;
const time_pointer: *volatile c_int = &time;
_ = c.signal(std.posix.SIG.ALRM, alarmHandler);
_ = std.c.alarm(1);
time_pointer.* += c.sigsetjmp(&env, 1);
std.debug.print("{d: >4} Largest Prime: {d: >10}\n", .{@as(c_uint, @intCast(time_pointer.*)), largest_pointer.*});
enumeratePrimes(current_pointer, largest_pointer); If that still doesn't work, in my understanding that would be a bug. EDIT: Actually, since |
Removing all volatiles in the C code still produce good output with -O0, whatever compiler is used.
No, I tried it with std.debug.print("{d: >4} Largest Prime: {d: >10}\n", .{@as(*volatile c_int, &time).*, @as(*volatile u32, &largest).*}); About volatile pointers, it still doesn't work and I think it may be related to #21033. Side note about setjmp/longjmp, this issue is not related to these functions in particular. I used them because it's easier for a repro but the same kind of behavior can happen in an environment with non-local jump e.g. kernel interruptions. |
If you have a valid repro, please open another issue for it. |
setjmp
/longjmp
gives unexpected results
I will try to make another repro with qemu but this is still a miscompilation between zig translate-c and zig cc, it's not a question it's a bug... |
|
Translating C code into Zig code with silently/subtly different behavior is suboptimal behavior. |
How do you plan to ditch clang for #20875 then? |
@Ratakor I don't think that is necessarily related - in the plan laid out in #20875 , instead of invoking |
Zig Version
0.14.0-dev.2034+56996a280
Steps to Reproduce and Observed Behavior
I have 2 files that does the same thing, one is in C and uses volatile values, the other is in zig.
test.c:
test.zig
C code output with -O0 or -O3
Zig code output with -ODebug
Zig code output with -OReleaseFast
In zig everything gets optimized even in Debug build! and there is no way to prevent it from being optimized, I tried to cast values to volatile ptr (may have failed because of #21033), use memory barrier, etc... but nothing works.
Note that this also highlights miscompilation between zig cc and zig translate-c |> zig build-exe.
Expected Behavior
Have a way to actually prevent code to get optimized away, this is a real problem in embedded/kernel development or, for example, lightweight user space threads implementation.
The text was updated successfully, but these errors were encountered: