Skip to content
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

Compiler discards const stack variable declarations and generates segfaulting code #19011

Open
Mikastiv opened this issue Feb 20, 2024 · 3 comments
Labels
backend-llvm The LLVM backend outputs an LLVM IR Module. bug Observed behavior contradicts documented or intended behavior miscompilation The compiler reports success but produces semantically incorrect code.
Milestone

Comments

@Mikastiv
Copy link
Sponsor

Zig Version

0.12.0-dev.2811+3cafb9655

Steps to Reproduce and Observed Behavior

I'm on Windows 10

The code pasted below will segfault on try vertices.append(v0); in one of the ArrayList grows. This seems to be related to parameter-reference-optimization because the code will pass the arguments by pointer, which will be freed when it's time to copy them. The strange thing here is that by changing the variable declarations from const to var, the generated code is now correct and passes the arguments by value. There is also another workaround where we call try vertices.appendSlice(&.{ v0, v1 }); This happens in both debug and release fast

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();

    const allocator = gpa.allocator();
    // Using arena allocator also is a workaround
    // const allocator = arena.allocator();

    var vertices = std.ArrayList([3]f32).init(allocator);
    defer vertices.deinit();

    for (0..1000) |i| {
        if (i > 2) {
            // Generates segfault
            const v0 = vertices.items[vertices.items.len - 3];
            const v1 = vertices.items[vertices.items.len - 1];
            try vertices.append(v0);
            try vertices.append(v1);

            // 1st workaround
            // var v0 = vertices.items[vertices.items.len - 3];
            // var v1 = vertices.items[vertices.items.len - 1];
            // _ = &v0;
            // _ = &v1;
            // try vertices.append(v0);
            // try vertices.append(v1);

            // 2nd workaround
            // const v0 = vertices.items[vertices.items.len - 3];
            // const v1 = vertices.items[vertices.items.len - 1];
            // try vertices.appendSlice(&.{ v0, v1 });
        }

        try vertices.append(.{ 0, 0, 0 });
    }

    std.log.err("count: {d}", .{vertices.items.len});
}

Expected Behavior

No segfault in the generated code

@Mikastiv Mikastiv added the bug Observed behavior contradicts documented or intended behavior label Feb 20, 2024
@Mikastiv
Copy link
Sponsor Author

Potential duplicates #5973, #5455

@Vexu Vexu added the backend-llvm The LLVM backend outputs an LLVM IR Module. label Feb 20, 2024
@Vexu Vexu added this to the 0.13.0 milestone Feb 20, 2024
@Vexu
Copy link
Member

Vexu commented Feb 20, 2024

Using -fno-llvm -fno-lld doesn't segfault so this is likely caused by an optimization in the LLVM backend.

@jacobly0
Copy link
Member

v0 is passed by reference to the actual element in the items slice, which is invalidated by the array list resize, causing the actual append to crash.

@Vexu Vexu added the miscompilation The compiler reports success but produces semantically incorrect code. label May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend-llvm The LLVM backend outputs an LLVM IR Module. bug Observed behavior contradicts documented or intended behavior miscompilation The compiler reports success but produces semantically incorrect code.
Projects
None yet
Development

No branches or pull requests

3 participants