odin-lang / Odin

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

Compiler crashes for unions in unions: "Illegal instruction (core dumped)" #3820

Closed tadeohepperle closed 4 days ago

tadeohepperle commented 4 days ago

Context

    Odin:    dev-2024-06:f1779c85d
    OS:      Manjaro Linux, Linux 6.1.80-1-MANJARO
    CPU:     12th Gen Intel(R) Core(TM) i7-1260P
    RAM:     31806 MiB
    Backend: LLVM 14.0.6

Behavior

Putting a union into another union, causes compiler crashes:

Example 1:

import "core:fmt"
main :: proc() {
    Error :: enum {
        One,
        Two,
    }
    MergedError :: union {
        union {
            string,
        },
        Error,
    }
    m: MergedError = "hello"
    fmt.print(m)
}

Output:

src/llvm_backend_const.cpp(696): Assertion Failure: `is_type_string(original_type)` 
Illegal instruction (core dumped)

Example 2 (similar error):

import "core:fmt"
main :: proc() {
    Error1 :: union {
        i32,
    }
    Error2 :: enum {
        One,
        Two,
    }
    MergedError :: union {
        Error1,
        Error2,
    }
    m: MergedError = 1
    fmt.print(m)
}

Output:

LLVM CODE GEN FAILED FOR PROCEDURE: o2.main
define internal void @o2.main(i8* noalias nocapture nonnull %__.context_ptr) {
decls:
  %m = alloca %o2.main.MergedError-2, align 8
  %0 = alloca %o2.main.MergedError-2, align 8
  %1 = alloca { %..any*, i64 }, align 8
  %2 = alloca [1 x %..any], align 8
  %3 = alloca %..any, align 8
  br label %entry

entry:                                            ; preds = %decls
  %4 = bitcast i8* %__.context_ptr to %runtime.Context*
  %5 = bitcast %o2.main.MergedError-2* %0 to i8*
  call void @llvm.memset.p0i8.i64(i8* %5, i8 0, i64 16, i1 false)
  %6 = bitcast %o2.main.MergedError-2* %0 to %_internal.Error1-1*
  store i1 true, %_internal.Error1-1* %6, align 1
  %7 = getelementptr inbounds %o2.main.MergedError-2, %o2.main.MergedError-2* %0, i32 0, i32 1
  store i64 1, i64* %7, align 8
  %8 = load %o2.main.MergedError-2, %o2.main.MergedError-2* %0, align 8
  store %o2.main.MergedError-2 %8, %o2.main.MergedError-2* %m, align 8
  %9 = load %o2.main.MergedError-2, %o2.main.MergedError-2* %m, align 8
  %10 = bitcast { %..any*, i64 }* %1 to i8*
  call void @llvm.memset.p0i8.i64(i8* %10, i8 0, i64 16, i1 false)
  %11 = bitcast [1 x %..any]* %2 to i8*
  call void @llvm.memset.p0i8.i64(i8* %11, i8 0, i64 16, i1 false)
  %12 = getelementptr [1 x %..any], [1 x %..any]* %2, i64 0, i64 0
  %13 = bitcast %..any* %3 to i8*
  call void @llvm.memset.p0i8.i64(i8* %13, i8 0, i64 16, i1 false)
  %14 = bitcast %o2.main.MergedError-2* %m to i8*
  %15 = getelementptr inbounds %..any, %..any* %3, i32 0, i32 0
  %16 = getelementptr inbounds %..any, %..any* %3, i32 0, i32 1
  store i8* %14, i8** %15, align 8
  store i64 3674937295934324745, i64* %16, align 8
  %17 = load %..any, %..any* %3, align 8
  store %..any %17, %..any* %12, align 8
  %18 = getelementptr [1 x %..any], [1 x %..any]* %2, i64 0, i64 0
  %19 = getelementptr inbounds { %..any*, i64 }, { %..any*, i64 }* %1, i32 0, i32 0
  store %..any* %18, %..any** %19, align 8
  %20 = getelementptr inbounds { %..any*, i64 }, { %..any*, i64 }* %1, i32 0, i32 1
  store i64 1, i64* %20, align 8
  %21 = load { %..any*, i64 }, { %..any*, i64 }* %1, align 8
  %22 = bitcast %runtime.Context* %4 to i8*
  %23 = call i64 @fmt.print({ %..any*, i64 } %21, %..string { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @"csbs$e0", i64 0, i64 0), i64 1 }, i1 zeroext true, i8* %22)
  ret void
}

Stored value type does not match pointer operand type!
  store i1 true, %_internal.Error1-1* %6, align 1
Kelimion commented 4 days ago
Odin:    dev-2024-06:9f8b84c21
OS:      Windows 10 Professional (version: 22H2), build 19045.4529
CPU:     AMD Ryzen 9 5950X 16-Core Processor
RAM:     65444 MiB
Backend: LLVM 17.0.1

Confirmed the first one. Second doesn't raise a compiler error and the print statement prints nil.

Kelimion commented 4 days ago

Can't replicate the 2nd bug on Linux (same Odin commit) with the LLVM 18.1.3 backend either.

gingerBill commented 4 days ago

I fixed example 1 but not 2, and I need to redo this.