ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.37k stars 2.51k forks source link

wrong C ABI for `@alignOf(@Vector(4, f32))` on arm #12137

Open xxxbxxx opened 2 years ago

xxxbxxx commented 2 years ago

Zig Version

0.10.0-dev.3008

Steps to Reproduce

There seem to be a special case in the ABI for arm (and armeb, thumb, thumbeb) with a reduced alignment for 16-bytes vectors.

empirically: https://godbolt.org/z/ca6G58G19

but I don't know the exact rules.

Expected Behavior

@alignOf(@Vector(4, f32))==8 @alignOf(@Vector(16, i8))==8

Actual Behavior

@alignOf(@Vector(4, f32))==16 @alignOf(@Vector(16, i8))==16

andrewrk commented 2 months ago

What's wrong with the bigger alignment?

xxxbxxx commented 2 months ago

mmm I don't remember if I had a practical problem with this or not.

But more likely I stumbled upon this when investigating https://github.com/ziglang/zig/issues/12026 and trying to write a test: https://github.com/ziglang/zig/pull/12028/files

however, I reckon there will be ABI issues if sharing an extern struct with C code.

xxxbxxx commented 2 months ago

yeah, here is a test case: (but to be precise, it's a madeup exemple, not something I encountered doing usefull code - I seldom use arm anyway)

repro.c:

#include <arm_neon.h>

typedef struct {
    int a, b;
    int32x4_t vec0;
    int c;
} my_struct;

int read_value(my_struct* S) { return S->c; }

repro.zig:

const std = @import("std");

const MyStruct = extern struct {
    a: c_int,
    b: c_int,
    vec0: @Vector(4, i32),
    c: c_int,
};

extern fn read_value(s: *MyStruct) c_int;

test {
    var s: MyStruct = .{ .a = 0, .b = 0, .vec0 = .{ 0, 0, 0, 0 }, .c = 123 };
    const v = read_value(&s);
    try std.testing.expectEqual(@as(c_int, 123), v);
}

zig test -target arm-linux-musl -mcpu cortex_a9 repro.c repro.zig expected 123, found 0 1/1 repro.test_0...FAIL (TestExpectedEqual)

whereas if I move a,b after vec0, the test passes.

andrewrk commented 2 months ago

Ah, so it's a C ABI issue.

lerno commented 1 month ago

If I recall what the Clang sources say about this, is that ARM_AAPCS and ARM_AAPCS_LINUX are limited to 8 byte max alignment. For Android, AAPCS16 and APCS_GNU, there is no limit.