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

Proposal: Link-time initialization of globals #9512

Open
N00byEdge opened this issue Aug 3, 2021 · 1 comment
Open

Proposal: Link-time initialization of globals #9512

N00byEdge opened this issue Aug 3, 2021 · 1 comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@N00byEdge
Copy link
Contributor

N00byEdge commented Aug 3, 2021

I believe there should be a concept of link-time initialization of global variables. There is for example a boot protocol called stivale2 that reads a structure straight from one of your ELF sections, and traverses a linked list of tags (pointers encoded as integers) in your memory before jumping to the entry point:

In C:

static uint8_t stack[4096];

__attribute__((section(".stivale2hdr"), used))
static struct stivale2_header stivale_hdr = {
    .entry_point = &_entry,
    .stack = (uintptr_t)stack + sizeof(stack),
    .flags = (1 << 1) | (1 << 2),
    .tags = (uintptr_t)&framebuffer_hdr_tag
};

static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = {
    .tag = {
        .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
        .next = (uint64_t)&terminal_hdr_tag
    },
    .framebuffer_width  = 0,
    .framebuffer_height = 0,
    .framebuffer_bpp    = 0
};

// ...

If you attempt to do the same thing in Zig, you're hit with something akin to "unable to evaluate constant expression" if you just have a single pointer-to-int conversion within any of your globals.

I propose that instead the link time pointers are tagged as exactly that, "link time known", so that you actually trigger the error only if you access them within a comptime context.

The workaround for now is to declare these structs in C and linking the C file to your executable, or implementing the creation of these structs in the linker script, none of which have access to zig comptime values, or to get access to zig constants through inline assembly:

export fn stivale_hdr() linksection(".stivale2hdr") callconv(.Naked) void {
    @setRuntimeSafety(false);
    asm volatile(
        \\ .quad stivale2Entry
        \\ .quad stack + %[stack_size]
        \\ .quad 6 // flags
        \\ .quad first_tag
        :
        : [stack_size] "i" (@sizeOf(stack))
    )
    unreachable;
}
@N00byEdge N00byEdge changed the title Link-time initialization of globals Proposal: Link-time initialization of globals Aug 3, 2021
ominitay added a commit to ominitay/zigvale that referenced this issue Aug 23, 2021
To workaround Zig limitation.
See: ziglang/zig#9512
@matu3ba
Copy link
Contributor

matu3ba commented Nov 16, 2021

As I understand it to make this reliable, this would require 1. adjusting the memory model in #6396 and comptime memory model #9646 to have a value for "initialize this value at link time" and 2. the linker speak to error out, if it cant fill at emitting the binary/lib (or represent that state, but thats even more complexity)

Alternatively, no guarantee for initialization may be given. However, this could introduce silent failures, ie when there are default values.

@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Nov 20, 2021
@andrewrk andrewrk added this to the 0.10.0 milestone Nov 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

3 participants