#stores to allowzero 0 pointer not emitted?

1 messages · Page 1 of 1 (latest)

gritty ember
#

zig build-obj source.zig -target riscv32-freestanding-none -femit-asm -fstrip -O ReleaseSmall

export fn store_hello() void {
    inline for("Hello, World", 0..) |c, i|
        @intToPtr([*]allowzero u8, 1)[i] = c;
}

correctly generates:

store_hello:
    li    a0, 72
    sb    a0, 1(zero)
    li    a0, 101
    sb    a0, 2(zero)
    li    a0, 108
    sb    a0, 3(zero)
    sb    a0, 4(zero)
    li    a1, 111
    sb    a1, 5(zero)
    li    a2, 44
    sb    a2, 6(zero)
    li    a2, 32
    sb    a2, 7(zero)
    li    a2, 87
    sb    a2, 8(zero)
    sb    a1, 9(zero)
    li    a1, 114
    sb    a1, 10(zero)
    sb    a0, 11(zero)
    li    a0, 100
    sb    a0, 12(zero)
    ret

But this code:

export fn store_hello() void {
    inline for("Hello, World", 0..) |c, i|
        @intToPtr([*]allowzero u8, 0)[i] = c;
}

generates nothing. When adding volatile, it does work, but volatile shouldn't be required since it's already allowzero, right?

cinder helm
#

seems to work if you remove inline

#

also if you use @memcpy

#

though I guess that wouldn't unroll it as you'd want

#

seems to be consistent across architectures, release modes, and OSs

#

might be worth an issue

gritty ember
#

sure thing

#

yeah it just works without inline nevermind, I spoke too soon:

    for("Hello, World", 0..) |c, i|
        @intToPtr([*]allowzero u8, 0)[i] = c;

still generates nothing

#

that's so strange

#

~~this segfaults the compiler?

export fn store_hello() void {
    @memcpy(@intToPtr([*]allowzero u8, 0), "Hello, World");
}
```~~
not anymore?
compact spade
gritty ember
#

and here I am building LLVM to get a debug build, smh my head

feral linden
#

volatile shouldn't be required since it's already allowzero, right?
Allowzero only means 0 is a valid address for the pointer type, not that all reads/writes must be side effects. The latter is what volatile is for.

gritty ember
gritty ember
feral linden
# gritty ember in C, dereferencing pointers casted from compile-time-known integers with the va...

Pointers casted from any address that doesn't have active provenance (regardless of allowzero) cannot be read or written from soundly (without side effect ops like asm/volatile).

A pointer has active provenance if its in the range of a stack/global/tls/other compiler-known storage, or it comes from a side-effect operation like asm/extern/volatile/(dynamic-dispatch to the extent of compiler visibility)

gritty ember
gritty ember
# feral linden Pointers casted from any address that doesn't have active provenance (regardless...

I understand the provenance requirement now, but isn't requiring volatile here still an issue, since volatile also requires that any operation on the pointed-to object is a side effect? Here's an example: https://godbolt.org/z/14P6qME37

feral linden
# gritty ember I understand the provenance requirement now, but isn't requiring `volatile` here...

volatile is only required for reading/writing with the pointer. It can be stored normally until then (similar to how a pointer can be undefined until it needs to be used), at which point youd ptrCast it to volatile.

For your example, yes volatile prohibits auto(not manual)-vectorization as that can remove reads/writes which would otherwise be there with volatile (i.e. the compiler could "auto vectorize" this x.* = 10; f(); x.* += 5 into this f(); x.* = 15 if the first write (or f()) isnt a side effect locally).

gritty ember