-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Segfault in mlir-translate --mlir-to-llvmir
with LLVM 16
#63832
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
Comments
@llvm/issue-subscribers-mlir |
The IR unfortunately does not parse at HEAD anymore so I can't try to see if it is already fixed easily:
|
mlir-translate
.mlir-translate --mlir-to-llvmir
with LLVM 16
According to the docs, an indirect |
Translating a test program from LLVM IR to MLIR generates an indirect call without the first type either: define void @main(ptr %0) {
call void %0()
ret void
} module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<i64, dense<[32, 64]> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>>} {
llvm.func @main(%arg0: !llvm.ptr) {
llvm.call %arg0() : () -> ()
llvm.return
}
} This one doesn't crash, but it still can't be translated back to LLVM IR: |
We modified our compiler so that it doesn't generate that indirect call and it still crashes so we know it's not that (or at least not only that). The new program that crashes module attributes {llvm.data_layout = ""} {
llvm.func @cairo_native__libfunc__starknet__get_block_hash(!llvm.ptr<struct<packed (i1, array<39 x i8>)>>, !llvm.ptr, !llvm.ptr<i64>, i64) attributes {sym_visibility = "private"}
llvm.func @"hello_starknet::hello_starknet::main"(%arg0: i64, %arg1: !llvm.ptr) -> !llvm.struct<(i64, ptr, struct<()>)> attributes {llvm.emit_c_interface, sym_visibility = "public"} {
%0 = llvm.mlir.constant(true) : i1
%1 = llvm.mlir.constant(false) : i1
%2 = llvm.mlir.constant(0 : i64) : i64
%3 = llvm.mlir.constant(1 : i64) : i64
%4 = llvm.alloca %3 x !llvm.struct<packed (i1, array<39 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr<struct<packed (i1, array<39 x i8>)>>
%5 = llvm.alloca %3 x i64 {alignment = 8 : i64} : (i64) -> !llvm.ptr<i64>
%6 = llvm.alloca %3 x !llvm.struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>, array<16 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr<struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>, array<16 x i8>)>>
%7 = llvm.alloca %3 x !llvm.struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>, array<16 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr<struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>, array<16 x i8>)>>
%8 = llvm.getelementptr %arg1[0] : (!llvm.ptr) -> !llvm.ptr<ptr>
%9 = llvm.load %8 : !llvm.ptr<ptr>
llvm.store %arg0, %5 : !llvm.ptr<i64>
llvm.call @cairo_native__libfunc__starknet__get_block_hash(%4, %9, %5, %2) : (!llvm.ptr<struct<packed (i1, array<39 x i8>)>>, !llvm.ptr, !llvm.ptr<i64>, i64) -> ()
%10 = llvm.load %4 : !llvm.ptr<struct<packed (i1, array<39 x i8>)>>
%11 = llvm.extractvalue %10[0] : !llvm.struct<packed (i1, array<39 x i8>)>
%12 = llvm.getelementptr %4[8] : (!llvm.ptr<struct<packed (i1, array<39 x i8>)>>) -> !llvm.ptr<i252>
%13 = llvm.load %12 : !llvm.ptr<i252>
%14 = llvm.getelementptr %4[8] : (!llvm.ptr<struct<packed (i1, array<39 x i8>)>>) -> !llvm.ptr<struct<(ptr<i252>, i32, i32)>>
%15 = llvm.load %14 : !llvm.ptr<struct<(ptr<i252>, i32, i32)>>
%16 = llvm.load %5 : !llvm.ptr<i64>
llvm.cond_br %11, ^bb1(%13 : i252), ^bb2(%15 : !llvm.struct<(ptr<i252>, i32, i32)>)
^bb1(%17: i252): // pred: ^bb0
%18 = llvm.mlir.undef : !llvm.struct<packed (i1, array<7 x i8>, i252)>
%19 = llvm.insertvalue %1, %18[0] : !llvm.struct<packed (i1, array<7 x i8>, i252)>
%20 = llvm.insertvalue %17, %19[2] : !llvm.struct<packed (i1, array<7 x i8>, i252)>
%21 = llvm.bitcast %7 : !llvm.ptr<struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>, array<16 x i8>)>> to !llvm.ptr<struct<packed (i1, array<7 x i8>, i252)>>
llvm.store %20, %21 {alignment = 8 : i64} : !llvm.ptr<struct<packed (i1, array<7 x i8>, i252)>>
llvm.br ^bb3(%16, %arg1 : i64, !llvm.ptr)
^bb2(%22: !llvm.struct<(ptr<i252>, i32, i32)>): // pred: ^bb0
%23 = llvm.mlir.undef : !llvm.struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>)>
%24 = llvm.insertvalue %0, %23[0] : !llvm.struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>)>
%25 = llvm.insertvalue %22, %24[2] : !llvm.struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>)>
%26 = llvm.bitcast %6 : !llvm.ptr<struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>, array<16 x i8>)>> to !llvm.ptr<struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>)>>
llvm.store %25, %26 {alignment = 8 : i64} : !llvm.ptr<struct<packed (i1, array<7 x i8>, struct<(ptr<i252>, i32, i32)>)>>
llvm.br ^bb3(%16, %arg1 : i64, !llvm.ptr)
^bb3(%27: i64, %28: !llvm.ptr): // 2 preds: ^bb1, ^bb2
%29 = llvm.mlir.undef : !llvm.struct<()>
%30 = llvm.mlir.undef : !llvm.struct<(i64, ptr, struct<()>)>
%31 = llvm.insertvalue %27, %30[0] : !llvm.struct<(i64, ptr, struct<()>)>
%32 = llvm.insertvalue %28, %31[1] : !llvm.struct<(i64, ptr, struct<()>)>
%33 = llvm.insertvalue %29, %32[2] : !llvm.struct<(i64, ptr, struct<()>)>
llvm.return %33 : !llvm.struct<(i64, ptr, struct<()>)>
}
llvm.func @"_mlir_ciface_hello_starknet::hello_starknet::main"(%arg0: !llvm.ptr<struct<(i64, ptr, struct<()>)>>, %arg1: i64, %arg2: !llvm.ptr) attributes {llvm.emit_c_interface, sym_visibility = "public"} {
%0 = llvm.call @"hello_starknet::hello_starknet::main"(%arg1, %arg2) : (i64, !llvm.ptr) -> !llvm.struct<(i64, ptr, struct<()>)>
llvm.store %0, %arg0 : !llvm.ptr<struct<(i64, ptr, struct<()>)>>
llvm.return
}
} |
I've been playing with the code above and I've found that the operation which causes the crash is A minimal example that crashes: llvm.func @main(%0 : !llvm.ptr) -> !llvm.ptr<ptr> {
%1 = llvm.getelementptr %0[0] : (!llvm.ptr) -> !llvm.ptr<ptr>
llvm.return %1 : !llvm.ptr<ptr>
} A minimal example that doesn't crash: llvm.func @main(%0 : !llvm.ptr) -> !llvm.ptr {
%1 = llvm.getelementptr %0[0] { elem_type = !llvm.ptr } : (!llvm.ptr) -> !llvm.ptr
llvm.return %1 : !llvm.ptr
} I'm aware that LLVM wants to remove non-opaque pointers but afaik that is in LLVM, and not MLIR. Since |
As was correctly pointed out by @azteca1998, the element type for a `llvm.getelementptr` was only read when using an attribute and not when using a type. As pointed out in #63832 (comment), the translation to LLVM would work for ```mlir llvm.func @main(%0 : !llvm.ptr) -> !llvm.ptr { %1 = llvm.getelementptr %0[0] { elem_type = !llvm.ptr } : (!llvm.ptr) -> !llvm.ptr llvm.return %1 : !llvm.ptr } ``` but not for ```mlir llvm.func @main(%0 : !llvm.ptr) -> !llvm.ptr<ptr> { %1 = llvm.getelementptr %0[0] : (!llvm.ptr) -> !llvm.ptr<ptr> llvm.return %1 : !llvm.ptr<ptr> } ``` This was caused by the `LLVM_GEPOp` builder only reading the type from the attribute (`{ elem_type = !llvm.ptr }`), but not from the pointer type (`!llvm.ptr<ptr>`). Fixes #63832. EDIT: During review Markus Böck pointed out that this bugfix adds new functionality for typed pointers, but this functionality shouldn't be there in the first place. In response, Oleksandr "Alex" Zinenko pointed out that this is okay for now since the typed pointers will be removed in an upcoming release anyway, so it's best to merge this PR and spend time on the removal instead.
LLVM version
LLVM 16.0.6 in both Linux and Mac OS.
MLIR input
Stack trace after crashing
Stack trace in Linux (LLVM debug info available)
Stack trace in Mac OS (no LLVM debug info available)
The text was updated successfully, but these errors were encountered: