odin-lang / Odin

Odin Programming Language
https://odin-lang.org
BSD 3-Clause "New" or "Revised" License
6.17k stars 550 forks source link

Swizzling arrays into longer arrays sometimes results in a segfault #3691

Closed Beefster09 closed 1 month ago

Beefster09 commented 1 month ago

Context

For instance, swizzling a [2]f32] into a [4]f32] using array.xyxy will sometimes result in a segfault at runtime.

Useful information to add to a bug report:

    Odin:    dev-2024-06:fcfc1cb97
    OS:      Linux Mint 21, Linux 5.15.0-106-generic
    CPU:     Intel(R) Core(TM) i3-1005G1 CPU @ 1.20GHz
    RAM:     7745 MiB
    Backend: LLVM 17.0.6

Expected Behavior

array.xyxy where array is 2 elements long should result in a 4-element array with the original array repeated twice.

Current Behavior

Segfault

Failure Information (for bugs)

My code looks something like this: (irrelevant details stripped out)

SPRITESHEET_SIZE :: 128

make_quad_with_uvs :: proc(src, dest, size: [2]f32, scale: f32) -> [8][2]f32 {
    // dest := dest
    rect := dest.xyxy  // segfault here
    rect.zw += size * scale

    // src := src
    uvs := src.xyxy  // the segfault happens here if you shadow the proc arguments where commented
    uvs.zw += size
    uvs /= SPRITESHEET_SIZE
    uvs += color_page.xyxy

    uv_tl := uvs.xy
    uv_tr := uvs.zy
    uv_br := uvs.zw
    uv_bl := uvs.xw

    return {
        rect.xy,
        rect.zy,
        rect.zw,
        rect.xw,
        uv_tl,
        uv_tr,
        uv_br,
        uv_bl,
    }
}

I did not test this snippet, but it should be trivial to try in a program

Beefster09 commented 1 month ago

I was not able to reproduce this on my Windows setup.

Might be a Linux-only bug. Possibly only LLVM 17

Feoramund commented 1 month ago

I had to comment out the uvs += color_page.xyxy line in your snippet, but I can confirm that this is causing a segfault on Linux.

Odin:    dev-2024-06:1f4cfd52f
OS:      Arch Linux, Linux 6.9.3-arch1-1
CPU:     12th Gen Intel(R) Core(TM) i7-12700K
RAM:     31913 MiB
Backend: LLVM 17.0.6
Feoramund commented 1 month ago

I've narrowed this down to:

package qw

import "core:fmt"

q :: proc (src: [2]f32, f: f32) {
    rect := src.xyxy
    fmt.println(rect)
}

main :: proc() {
    a: [2]f32 = {1,3}
    q(a, 1.5)
}

Removing the f argument from the q proc makes it work again. From a look at what assembly instruction it's segfaulting on, I'm guessing there's some stack corruption going on here, if I might be so bold.

Kelimion commented 1 month ago

Seems plausible that it's stack corruption. Does this occur at o:minimal as well as o:speed, or only at specific optimization levels?

Feoramund commented 1 month ago

Speed, size, and aggressive all work fine. None, minimal, and unspecified all cause the segfault.

Kelimion commented 1 month ago

The thick plottens!