llvm / llvm/Polygeist

Passing array to function using initializer syntax leads to crash

Open
#340 0 comments 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.