Skip to content

struct field load through underaligned pointer has incorrect alignment #14904

Closed
@andrewrk

Description

@andrewrk

Zig Version

0.11.0-dev.1969+d525ecb52

Steps to Reproduce and Observed Behavior

const std = @import("std");
const expect = std.testing.expect;

pub fn main() !void {
    var buf: [9]u8 align(4) = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    const ptr = @ptrCast(*align(1) Header, buf[1..][0..8]);
    const x = ptr.bytes_len;
    std.debug.print("x=0x{x}\n", .{x});
}

const Header = extern struct {
    tag: u32,
    bytes_len: u32,
};
$ stage3/bin/zig build-exe test3.zig -target mipsel-linux-musl
$ qemu-mipsel ./test3
Bus error (core dumped)

The problem is incorrect alignment in the LLVM IR:

const std = @import("std");

pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, start: ?usize) noreturn {
    _ = .{ msg, st, start };
    unreachable;
}

export fn entry() bool {
    doTheTest() catch return false;
    return true;
}

fn doTheTest() !void {
    var buf: [9]u8 align(4) = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    const ptr: *align(1) Header = @ptrCast(buf[1..][0..8]);
    const x = ptr.bytes_len;
    foo(x);
}

extern fn foo(u32) void;

const Header = extern struct {
    tag: u32,
    bytes_len: u32,
};
$ stage3/bin/zig build-obj test2.zig -target mipsel-linux-musl --verbose-llvm-ir -fstrip -OReleaseFast
define internal fastcc i16 @test2.doTheTest() unnamed_addr #0 {
Entry:
  %0 = alloca ptr, align 4
  %1 = alloca [9 x i8], align 4
  call void @llvm.memcpy.p0.p0.i32(ptr align 4 %1, ptr align 1 @0, i32 9, i1 false)
  %2 = getelementptr inbounds [9 x i8], ptr %1, i32 0, i32 1
  store ptr %2, ptr %0, align 4
  %3 = load ptr, ptr %0, align 4
  %4 = getelementptr inbounds [8 x i8], ptr %3, i32 0, i32 0
  %5 = getelementptr inbounds %test2.Header, ptr %4, i32 0, i32 1
  %6 = load i32, ptr %5, align 4
  call void @foo(i32 %6)
  ret i16 0
}

The problem is %6 = load i32, ptr %5, align 4 which has align 4 instead of align 1.

Side note: it is very annoying that the panic override above does not eliminate panicOutOfBounds from calling into std.debug.panicExtra and dragging in a whole lot of formatting code.

I have no evidence this is a regression, but I suspect it is.

Expected Behavior

I expect to see %6 = load i32, ptr %5, align 1 which would cause LLVM to generate machine code that did not cause a Bus Error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backend-cThe C backend (CBE) outputs C source code.bugObserved behavior contradicts documented or intended behaviorfrontendTokenization, parsing, AstGen, Sema, and Liveness.miscompilationThe compiler reports success but produces semantically incorrect code.regressionIt worked in a previous version of Zig, but stopped working.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions