Skip to content

over-eager dead-code-elimination when using @export in initializer #24067

@Sivecano

Description

@Sivecano

Zig Version

0.14.1

Steps to Reproduce and Observed Behavior

I've found that when declaring a private variable with a comptime function, DCE can be over-eager leading to it discarding wanted side-effects.

example:

fn versioned(T: type) *T {
    const vt = packed struct {
        value: T = undefined,
        version: i32,
    };

    const ns = struct{
        pub var wrapper: vt = .{.version = 1};
    };

    @export(&ns.wrapper, .{.name = "hello"});

    return &ns.wrapper.value;
}

const veri = versioned(i32);

will not actually export a symbol called "hello" since the compiler will erroneously optimize away the variable veri.
if we prevert veri from geting optimized away (by using it in on-dead code, exporting it in an api or similar), then
the symbol appears in the shared object file.

compiled using zig build-lib -dynamic

using code above:
nm -DW outputs

                 U __tls_get_addr
                 U getauxval

after adding

export fn a() void {
    veri.* = 5;
}

to the above

nm -DW outputs

                 U __tls_get_addr
00000000000e0870 T a
                 U getauxval
0000000000107118 D hello

this was tested on linux only.

Expected Behavior

don't optimize away code that has influence on compiler state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionNo questions on the issue tracker, please.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions