Passing array to function using initializer syntax leads to crash
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 624
- Forks
- 170
- PR merge metrics
- No merged PRs in 30d
Description
This issue is about passing an array to a function using initializer syntax. If a function takes an array argument and I pass it an initializer list that I cast to an array, then `cgeist` crashes while trying to convert the argument to an array.
Here is a minimal example of the problem:
```
$ cat arraycall.c
int f(int a[], int i){
return a[i];
}
int g(){
return f(((int []){0,1,2}),2);
}
```
When I run `cgeist` on this program here is the output that I see (which is a crash):
```
$ ../mlir-build/bin/cgeist -S --function=* ./arraycall.c -o arraycall.mlir
cgeist: /home/blucia/cvsandbox/riptools/extern/Polygeist/tools/cgeist/Lib/clang-mlir.cc:1635: ValueCategory MLIRScanner::CommonArrayToPointer(mlir::Location, ValueCategory): Assertion `scalar.val' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: ../mlir-build/bin/cgeist -S --function=* ./arraycall.c -o arraycall.mlir -opaque-pointers=0
1. parser at end of file
#0 0x00007f59d0084b94 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
#1 0x00007f59d0082344 SignalHandler(int) Signals.cpp:0:0
#2 0x00007f59cfac3090 (/lib/x86_64-linux-gnu/libc.so.6+0x43090)
#3 0x00007f59cfac300b raise /build/glibc-SzIz7B/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
#4 0x00007f59cfaa2859 abort /build/glibc-SzIz7B/glibc-2.31/stdlib/abort.c:81:7
#5 0x00007f59cfaa2729 get_sysdep_segment_value /build/glibc-SzIz7B/glibc-2.31/intl/loadmsgcat.c:509:8
#6 0x00007f59cfaa2729 _nl_load_domain /build/glibc-SzIz7B/glibc-2.31/intl/loadmsgcat.c:970:34
#7 0x00007f59cfab3fd6 (/lib/x86_64-linux-gnu/libc.so.6+0x33fd6)
#8 0x0000560cf414a302 MLIRScanner::CommonArrayToPointer(mlir::Location, ValueCategory) (../mlir-build/bin/cgeist+0x3d302)
#9 0x0000560cf4181c37 MLIRScanner::VisitCastExpr(clang::CastExpr*) (../mlir-build/bin/cgeist+0x74c37)
#10 0x0000560cf41c96ea MLIRScanner::VisitCallExpr(clang::CallExpr*) (../mlir-build/bin/cgeist+0xbc6ea)
#11 0x0000560cf41a0aaf MLIRScanner::VisitReturnStmt(clang::ReturnStmt*) (../mlir-build/bin/cgeist+0x93aaf)
#12 0x0000560cf41a0624 MLIRScanner::VisitCompoundStmt(clang::CompoundStmt*) (../mlir-build/bin/cgeist+0x93624)
#13 0x0000560cf418cc02 MLIRScanner::init(mlir::func::FuncOp, clang::FunctionDecl const*) (../mlir-build/bin/cgeist+0x7fc02)
#14 0x0000560cf418e392 MLIRASTConsumer::run() (../mlir-build/bin/cgeist+0x81392)
#15 0x00007f59cd83bb75 clang::ParseAST(clang::Sema&, bool, bool) (/home/blucia/cvsandbox/riptools/mlir-build/bin/../lib/../lib/libclangParse.so.16git+0x39b75)
#16 0x00007f59d33e1b79 clang::FrontendAction::Execute() (/home/blucia/cvsandbox/riptools/mlir-build/bin/../lib/libclangFrontend.so.16git+0x14cb79)
#17 0x0000560cf413a5d8 main (../mlir-build/bin/cgeist+0x2d5d8)
#18 0x00007f59cfaa4083 __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:342:3
#19 0x0000560cf413d61e _start (../mlir-build/bin/cgeist+0x3061e)
Aborted
```
Compiling with `clang` works:
```
$ ../mlir-build/bin/clang -S -emit-llvm -o arraycall.llvm arraycall.c
$
```
And the resulting LLVM IR seems reasonable (notice the `alloca` of the array at the start of g()):
```
$ cat arraycall.llvm
; ModuleID = 'arraycall.c'
source_filename = "arraycall.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @f(ptr noundef %a, i32 noundef %i) #0 {
entry:
%a.addr = alloca ptr, align 8
%i.addr = alloca i32, align 4
store ptr %a, ptr %a.addr, align 8
store i32 %i, ptr %i.addr, align 4
%0 = load ptr, ptr %a.addr, align 8
%1 = load i32, ptr %i.addr, align 4
%idxprom = sext i32 %1 to i64
%arrayidx = getelementptr inbounds i32, ptr %0, i64 %idxprom
%2 = load i32, ptr %arrayidx, align 4
ret i32 %2
}
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @g() #0 {
entry:
%.compoundliteral = alloca [3 x i32], align 4
%arrayinit.begin = getelementptr inbounds [3 x i32], ptr %.compoundliteral, i64 0, i64 0
store i32 0, ptr %arrayinit.begin, align 4
%arrayinit.element = getelementptr inbounds i32, ptr %arrayinit.begin, i64 1
store i32 1, ptr %arrayinit.element, align 4
%arrayinit.element1 = getelementptr inbounds i32, ptr %arrayinit.element, i64 1
store i32 2, ptr %arrayinit.element1, align 4
%arraydecay = getelementptr inbounds [3 x i32], ptr %.compoundliteral, i64 0, i64 0
%call = call i32 @f(ptr noundef %arraydecay, i32 noundef 2)
ret i32 %call
}
attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"clang version 16.0.0 (https://github.com/llvm/llvm-project.git cbc378ecb87e3f31dd5aff91f2a621d500640412)"}
```
That code runs correctly when I compile all the way to executable using `gcc` and `clang`.
I tried commenting out the failing assertion (and the one immediately after it) to see if I could recklessly get the code to go through without crashing, but unfortunately, that didn't work and I stopped following that thread.
The expected behavior for this program would be to stack allocate (i.e., `alloca`) the argument array in `g()`, just before the call to `f()`, although I'm not sure what that looks like in terms of `memref`.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the crash with the arraycall.c example using the cgeist command shown, then inspect CommonArrayToPointer in clang-mlir.cc around line 1635 and its callers in VisitCastExpr and VisitCallExpr. Done means the example no longer crashes and produces the expected stack-allocated array argument before calling f().
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100