-
-
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
illegal instruction inserted #8386
Comments
two instances of this pattern: the memory of var buf: [2]ast.Node.Index = undefined;
break :blk tree.containerDeclTwo(&buf, decl_addr); and that same pattern also appears in |
Hmm let me try allocating that, but I dont think that explains the illegal instruction. |
Ok, that fixes one of the problems, but now I still get an illegal instruction. 133c133,134
< const cd = getContainer(node_datas[decl_addr].rhs);
---
> var buf: [2]u32 = undefined;
> const cd = getContainer(node_datas[decl_addr].rhs, &buf);
238c239
< fn getContainer(decl_addr: ast.Node.Index) ?ast.full.ContainerDecl {
---
> fn getContainer(decl_addr: ast.Node.Index, buf: *[2]ast.Node.Index) ?ast.full.ContainerDecl {
251,252c252
< var buf: [2]ast.Node.Index = undefined;
< break :blk tree.containerDeclTwo(&buf, decl_addr);
---
> break :blk tree.containerDeclTwo(buf, decl_addr);
256,257c256
< var buf: [2]ast.Node.Index = undefined;
< break :blk tree.taggedUnionTwo(&buf, decl_addr);
---
> break :blk tree.taggedUnionTwo(buf, decl_addr);
|
Here is it in gdb:
Seems like something is inserting an illegal instruction:
|
reduction for the illegal hardware instruction: const std = @import("std");
pub fn main() !void {
const sig: []const u8 = undefined;
_ = try std.heap.c_allocator.dupe(u8, sig);
} |
Ah, yep, this is UB since the len is undefined. I assume the illegal instruction comes from our equivalent of |
It only triggers in ReleaseSafe, not debug though. This is what is confusing me? pub fn copy(comptime T: type, dest: []T, source: []const T) void {
// TODO instead of manually doing this check for the whole array
// and turning off runtime safety, the compiler should detect loops like
// this and automatically omit safety checks for loops
@setRuntimeSafety(false);
assert(dest.len >= source.len);
for (source) |s, i|
dest[i] = s;
} |
The optimizer needs to see a lot of code to realize that this is UB. Neither function on its own is UB, only the combination is. In ReleaseSafe, |
Should the assert be before the setRuntimeSafety so that this is caught? |
That's unrelated, this is not a debug check that the zig compiler inserts. It's inserted by LLVM which is recognizing that a code path triggers unconditional UB. |
yeah looks like llvm is doing its thing. I put the trigger code into an exported fn and this is OReleaseSafe ; Function Attrs: nobuiltin nounwind readnone sspstrong
define void @foobar() local_unnamed_addr #0 !dbg !850 {
UnwrapErrOk:
ret void, !dbg !857
} |
Yeah, ultimately the loop in |
Ah I see, is there anything we can do in zig to make this easier to catch and not depend on llvm? |
one point of confusion, I just took the simple reduction and overwrote zig's standard panic handler... no more illegal instruction: pub fn panic(msg: []const u8, error_return_trace: ?*@import("builtin").StackTrace) noreturn {
while (true) {}
} |
#63 exists but in practice this will be very hard, maybe impossible in some cases when pointers are involved. We can handle a lot of cases though, including this one probably. |
First of all, sorry for the big test case, I had a very hard time reducing it down.
This test case fails:
with:
We can see that member is in fact bogus:
Note: running in ReleaseSafe mode produces illegal instruction?????
I am confused out of my mind. I think this is probably a miscompilation or of not a bug in std.zig.ast.
Note: commenting out these two sections fixes it:
The text was updated successfully, but these errors were encountered: