Odin
Odin copied to clipboard
Error slicing a list of procedures
Context
I wanted to pass a list of procedures to another procedure, but pass it as a slice:
package scratch
proc_type :: #type proc() -> (int, bool);
foos ::proc(callables: []proc_type) -> (n:int) {
is_valid : bool
for i in 0..<len(callables) {
n, is_valid = callables[i]()
}
if is_valid {
return n
}
return -1
}
bar : proc_type : proc() -> (n:int, is_valid:bool) {
return 1, true
}
main :: proc() {
procs := [3]proc_type{bar, bar, bar}
foos(procs[:]) // this causes the error
}
-
Operating System & Odin Version:
- Windows 11,
- odin version dev-2023-04:70b0ade8
-
Please paste
odin report
output: Odin: dev-2023-04:70b0ade8 OS: Windows 11 Home Basic (version: 22H2), build 22621.1555 CPU: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz RAM: 16301 MiB
Expected Behavior
I expected my code to either compile or give me a proper error message explaining why or that I can't slice a list of procedures.
Current Behavior
The compiler crashes.
Failure Information (for bugs)
D:\projects\odin\scratch>odin build .
LLVM CODE GEN FAILED FOR PROCEDURE: scratch.main
define internal void @scratch.main(i8* noalias nocapture nonnull %__.context_ptr) {
decls:
%0 = alloca [3 x void ({ i64, i8 }*, i8*)*], align 8
%1 = alloca [3 x void ({ i64, i8 }*, i8*)*], align 8
%2 = alloca { void ({ i64, i8 }*, i8*)**, i64 }, align 8
br label %entry
entry: ; preds = %decls
%3 = bitcast i8* %__.context_ptr to %runtime.Context*
%4 = bitcast [3 x void ({ i64, i8 }*, i8*)*]* %1 to i8*
call void @llvm.memset.p0i8.i64(i8* %4, i8 0, i64 24, i1 false)
%5 = bitcast [3 x void ({ i64, i8 }*, i8*)*]* %1 to i8**
store i8* bitcast ([3 x void ({ i64, i8 }*, i8*)*] [void ({ i64, i8 }*, i8*)* @scratch.bar, void ({ i64, i8 }*, i8*)* @scratch.bar, void ({ i64, i8 }*, i8*)* @
scratch.bar] to i8*), i8** %5, align 8
%6 = load [3 x void ({ i64, i8 }*, i8*)*], [3 x void ({ i64, i8 }*, i8*)*]* %1, align 8
%7 = bitcast [3 x void ({ i64, i8 }*, i8*)*]* %0 to i8**
%8 = bitcast [3 x void ({ i64, i8 }*, i8*)*] %6 to i8*
store i8* %8, i8** %7, align 8
%9 = load [3 x void ({ i64, i8 }*, i8*)*], [3 x void ({ i64, i8 }*, i8*)*]* %0, align 8
%10 = getelementptr [3 x void ({ i64, i8 }*, i8*)*], [3 x void ({ i64, i8 }*, i8*)*]* %0, i64 0, i64 0
%11 = getelementptr void ({ i64, i8 }*, i8*)*, void ({ i64, i8 }*, i8*)** %10, i64 0
%12 = getelementptr inbounds { void ({ i64, i8 }*, i8*)**, i64 }, { void ({ i64, i8 }*, i8*)**, i64 }* %2, i32 0, i32 0
%13 = bitcast void ({ i64, i8 }*, i8*)*** %12 to i8**
%14 = bitcast void ({ i64, i8 }*, i8*)** %11 to i8*
store i8* %14, i8** %13, align 8
%15 = getelementptr inbounds { void ({ i64, i8 }*, i8*)**, i64 }, { void ({ i64, i8 }*, i8*)**, i64 }* %2, i32 0, i32 1
store i64 3, i64* %15, align 8
%16 = load { void ({ i64, i8 }*, i8*)**, i64 }, { void ({ i64, i8 }*, i8*)**, i64 }* %2, align 8
%17 = bitcast %runtime.Context* %3 to i8*
%18 = call i64 @scratch.foos({ void ({ i64, i8 }*, i8*)**, i64 }* %2, i8* %17)
ret void
}
Invalid bitcast
i8* bitcast ([3 x void ({ i64, i8 }*, i8*)*] [void ({ i64, i8 }*, i8*)* @scratch.bar, void ({ i64, i8 }*, i8*)* @scratch.bar, void ({ i64, i8 }*, i8*)* @scratch.
bar] to i8*)
Invalid bitcast
%8 = bitcast [3 x void ({ i64, i8 }*, i8*)*] %6 to i8*
Steps to Reproduce
This error happens at compile time when compiling the code above.
Failure Logs
The error message above is all I got.
After playing around with this a bit more, wrapping each procedure into a struct does not cause that LLVM error:
proc_type :: #type proc() -> (int, bool);
dyn_procs :: struct {
f: proc_type,
}
foos ::proc(callables: []dyn_procs) -> (int) {
// ...
}
bar : proc_type = proc() -> (int, bool) {
return 1, true
}
main :: proc() {
procs := [3]dyn_procs{
dyn_procs{bar},
dyn_procs{bar},
dyn_procs{bar},
}
foos(procs[:])
}
So the error seems to be related to arrays of procedure types and arrays of pointers to procedure types.
I cannot replicate this bug any more.