Skip to content

[clang-repl] Segfault on assignment when JIT compiling with -O1 or above #95581

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

Closed
jeaye opened this issue Jun 14, 2024 · 7 comments · Fixed by #98138
Closed

[clang-repl] Segfault on assignment when JIT compiling with -O1 or above #95581

jeaye opened this issue Jun 14, 2024 · 7 comments · Fixed by #98138
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@jeaye
Copy link

jeaye commented Jun 14, 2024

Hi folks. I've been working with @vgvassilev to identify an issue with Clang/LLVM 19. Currently running on Vassil's branch here: #94166

NOTE: This issue does not exist in LLVM 18 (1118c2e).

I have a minimal repro case shown below. It works with -O0, but crashes with -O1 or higher.

The C++ source

struct box {
  box() = default;
  box(int *const data) : data{data} {}

  int *data{};
};

box foo() {
  box ret;
  /* The assignment here causes the crash. Using direct initialization works.
   * With -O0, this compiles and works. With -O1 or above, it dies. */
  ret = new int{};
  return ret;
}

The repro steps

❯ ./build/bin/clang-repl -Xcc -O1
clang-repl> #include "foo.hpp"
Segmentation fault (core dumped)

The backtrace

#0  0x0000555558b9e025 in clang::CodeGen::CodeGenTypes::ConvertRecordDeclType(clang::RecordDecl const*) ()
#1  0x0000555558b9ef2b in clang::CodeGen::CodeGenTypes::getCGRecordLayout(clang::RecordDecl const*) ()
#2  0x0000555558b9ab87 in clang::CodeGen::CodeGenTBAA::CollectFields(unsigned long, clang::QualType, llvm::SmallVectorImpl<llvm::MDBuilder::TBAAStructField>&, bool) ()
#3  0x0000555558b9b358 in clang::CodeGen::CodeGenTBAA::getTBAAStructInfo(clang::QualType) ()
#4  0x00005555589a6853 in clang::CodeGen::CodeGenFunction::EmitAggregateCopy(clang::CodeGen::LValue, clang::CodeGen::LValue, clang::QualType, clang::CodeGen::AggValueSlot::Overlap_t, bool) ()
#5  0x00005555589bc204 in clang::CodeGen::CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(clang::CallExpr const*, clang::CXXMethodDecl const*, clang::CodeGen::ReturnValueSlot, bool, clang::NestedNameSpecifier*, bool, clang::Expr const*) ()
#6  0x00005555589bd268 in clang::CodeGen::CodeGenFunction::EmitCXXOperatorMemberCallExpr(clang::CXXOperatorCallExpr const*, clang::CXXMethodDecl const*, clang::CodeGen::ReturnValueSlot) ()
#7  0x00005555589955bd in clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) ()
#8  0x0000555558995700 in clang::CodeGen::CodeGenFunction::EmitCallExprLValue(clang::CallExpr const*) ()
#9  0x000055555899597e in clang::CodeGen::CodeGenFunction::EmitLValueHelper(clang::Expr const*, clang::CodeGen::KnownNonNull_t) ()
#10 0x00005555589963d4 in clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr const*, clang::CodeGen::KnownNonNull_t) ()
#11 0x0000555558995d0d in clang::CodeGen::CodeGenFunction::EmitLValueHelper(clang::Expr const*, clang::CodeGen::KnownNonNull_t) ()
#12 0x0000555558994070 in clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) ()
#13 0x0000555558ab0d92 in clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) ()
#14 0x0000555558ab7ef9 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) ()
#15 0x0000555558b14cdc in clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) ()
#16 0x0000555558b2672f in clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) ()
#17 0x0000555558b6a44a in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) ()
#18 0x0000555558b664bc in clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) ()
#19 0x0000555558b66d5b in clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) ()
#20 0x0000555558b6e1b7 in clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) [clone .part.0] ()
#21 0x0000555558896d81 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) ()
#22 0x00005555588719e7 in clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) ()
#23 0x000055555834df3f in clang::IncrementalASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef) ()
#24 0x0000555558351424 in clang::IncrementalParser::ParseOrWrapTopLevelDecl() ()
#25 0x000055555835225d in clang::IncrementalParser::Parse(llvm::StringRef) ()
#26 0x0000555558342568 in clang::Interpreter::ParseAndExecute(llvm::StringRef, clang::Value*) ()
#27 0x0000555556333495 in main ()

Environment details

  • OS: Ubuntu 24.04 (distrobox)
  • LLVM commit: 0b3fc78
@EugeneZelenko EugeneZelenko added clang-tools-extra crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Jun 14, 2024
@jeaye jeaye changed the title Segfault on assignment when JIT compiling with -O1 or above [clang-replSegfault on assignment when JIT compiling with -O1 or above Jun 14, 2024
@jeaye jeaye changed the title [clang-replSegfault on assignment when JIT compiling with -O1 or above [clang-repl] Segfault on assignment when JIT compiling with -O1 or above Jun 14, 2024
@vgvassilev
Copy link
Contributor

Is there a way to bisect it on your side?

@jeaye
Copy link
Author

jeaye commented Jun 16, 2024

Yeah, I'll work on that and report back.

@jeaye
Copy link
Author

jeaye commented Jun 22, 2024

... Several hours of compilation later ...

I've bisected to find the commit (d2a9df2) which introduces the crash. Based on the stack trace, the diff looks very relevant. Author: @fhahn (Florian, would you mind please taking a look and providing your input?)

d2a9df2c8ffd21fd52fbd8199a191d10078f41af is the first bad commit
commit d2a9df2c8ffd21fd52fbd8199a191d10078f41af
Author: Florian Hahn <[email protected]>
Date:   Tue Feb 27 20:09:54 2024 +0000

    [TBAA] Handle bitfields when generating !tbaa.struct metadata. (#82922)

    At the moment, clang generates what I believe are incorrect !tbaa.struct
    fields for named bitfields. At the moment, the base type size is used
    for named bifields (e.g. sizeof(int)) instead of the bifield width per
    field. This results in overalpping fields in !tbaa.struct metadata.

    This causes incorrect results when extracting individual copied fields
    from !tbaa.struct as in added in dc85719d5.

    This patch fixes that by skipping by combining adjacent bitfields
    in fields with correct sizes.

    Fixes https://github.com/llvm/llvm-project/issues/82586

 clang/lib/CodeGen/CodeGenModule.cpp |  4 ++--
 clang/lib/CodeGen/CodeGenTBAA.cpp   | 44 +++++++++++++++++++++++++++----------
 clang/lib/CodeGen/CodeGenTBAA.h     |  7 ++++--
 clang/test/CodeGen/tbaa-struct.cpp  |  6 ++---
 4 files changed, 43 insertions(+), 18 deletions(-)

In case the full bisect log is useful, I've included it below.

I compared `release/18.x` against Vassil's `fix-pch` branch to find this.
❯ git bisect log
git bisect start
# status: waiting for both good and bad commits
# bad: [0b3fc785ecb7b751ff67b7d972e033a95a45738f] Address comments
git bisect bad 0b3fc785ecb7b751ff67b7d972e033a95a45738f
# status: waiting for good commit(s), bad commit known
# good: [1118c2e05e67a36ed8ca250524525cdb66a55256] [libcxx][libcxxabi] Fix build for OpenBSD (#92186)
git bisect good 1118c2e05e67a36ed8ca250524525cdb66a55256
# good: [93248729cfae82a5ca2323d4a8e15aa3b9b9c707] [RISCV][MC] Split tests for A into Zaamo and Zalrsc parts
git bisect good 93248729cfae82a5ca2323d4a8e15aa3b9b9c707
# bad: [05dc5d927bc5f0eeadd277a5e31b04399415f9d0] [libc] add statvfs/fstatvfs (#86169)
git bisect bad 05dc5d927bc5f0eeadd277a5e31b04399415f9d0
# good: [7bb08ee8260c825eb5af4824bc62f73155b4b592] [mlir][Transforms][NFC] Decouple `ConversionPatternRewriterImpl` from `ConversionPatternRewriter` (#82333)
git bisect good 7bb08ee8260c825eb5af4824bc62f73155b4b592
# bad: [d2353ae00c3b0b0e9a9b93578e9bb067f699f193] [utils/TableGen/X86CompressEVEXTablesEmitter.cpp] Make sure the tablegen output for the `checkPredicate` function is deterministic (#84533)
git bisect bad d2353ae00c3b0b0e9a9b93578e9bb067f699f193
# bad: [732a5cba8c739ed40a7280b5d74ca717910c2c4c] Revert "Reapply "[mlir-query] Add function extraction feature to mlir-query""
git bisect bad 732a5cba8c739ed40a7280b5d74ca717910c2c4c
# bad: [1f74f5f48bc9e1091602163ac925c807d70706e1] [flang] Fix flang build after #83132 (#83253)
git bisect bad 1f74f5f48bc9e1091602163ac925c807d70706e1
# good: [dc06d75ab27b4dcae2940fc386fadd06f70faffe] Revert "[RemoveDIs] Print non-intrinsic debug info in textual IR output (#79281)"
git bisect good dc06d75ab27b4dcae2940fc386fadd06f70faffe
# good: [ed35ad18ae7b5e61c24b63c22028ee0d1ba10e19] [RemoveDIs][DebugInfo] Add DPValue checks to the verifier, prepare DPValue for parsing support (#79810)
git bisect good ed35ad18ae7b5e61c24b63c22028ee0d1ba10e19
# bad: [001e18c816736602e3ad1c5dc6259143455610ea] [NFC] clang-format SROA.cpp
git bisect bad 001e18c816736602e3ad1c5dc6259143455610ea
# good: [40ba1f60e9f4b186d71272d4bc23b5af6204244d] [clang] Update -Wformat warnings for fixed-point format specifiers (#82855)
git bisect good 40ba1f60e9f4b186d71272d4bc23b5af6204244d
# bad: [1d1186de34c55149be336068bf312e8f755dca37] [llvm-exegesis] Add loop-register snippet annotation (#82873)
git bisect bad 1d1186de34c55149be336068bf312e8f755dca37
# good: [fd4204464905be198b158a0f30e5c06cc4ce3686] [libc] Re-Enable GPU tests and fix math exception handling (#83172)
git bisect good fd4204464905be198b158a0f30e5c06cc4ce3686
# bad: [d2a9df2c8ffd21fd52fbd8199a191d10078f41af] [TBAA] Handle bitfields when generating !tbaa.struct metadata. (#82922)
git bisect bad d2a9df2c8ffd21fd52fbd8199a191d10078f41af
# good: [0d1f95760b07a31293ccc82086306833326b70a4] [mlir][sparse] support type conversion from batched sparse tensors to… (#83163)
git bisect good 0d1f95760b07a31293ccc82086306833326b70a4
# first bad commit: [d2a9df2c8ffd21fd52fbd8199a191d10078f41af] [TBAA] Handle bitfields when generating !tbaa.struct metadata. (#82922)

@fhahn
Copy link
Contributor

fhahn commented Jun 23, 2024

Sure I'd be happy to take a look! I managed to reproduce this on macOS, but I am not sure how to get a standalone reproducer for a unit test?

@jeaye
Copy link
Author

jeaye commented Jun 27, 2024

Sure I'd be happy to take a look! I managed to reproduce this on macOS, but I am not sure how to get a standalone reproducer for a unit test?

Nice! Thanks for giving it a go locally. I'm not familiar with Clang/LLVM dev at all, but I know the tests are kept over here: https://github.com/llvm/llvm-project/tree/main/clang/test/Interpreter

I'm pretty sure each of those .cpp files has some RUN commands in it which are interpreted as commands to compile and run the file. For example: https://github.com/llvm/llvm-project/blob/main/clang/test/Interpreter/inline-virtual.cpp

Following that, I've made one which reproduces the error (using the test case I included in this ticket):

diff --git a/clang/test/Interpreter/assigment-with-implicit-ctor.cpp b/clang/test/Interpreter/assigment-with-implicit-ctor.cpp
new file mode 100644
index 000000000000..24cea8ec1a4b
--- /dev/null
+++ b/clang/test/Interpreter/assigment-with-implicit-ctor.cpp
@@ -0,0 +1,13 @@
+// REQUIRES: host-supports-jit
+// UNSUPPORTED: system-aix
+//
+// RUN: cat %s | clang-repl | FileCheck %s
+// RUN: cat %s | clang-repl -Xcc -O2 | FileCheck %s
+
+struct box { box() = default; box(int *const data) : data{data} {} int *data{}; };
+
+box foo() { box ret; ret = new int{}; return ret; }
+
+extern "C" int printf(const char *, ...);
+printf("good");
+// CHECK: good

I'm not sure how they're normally executed, but I've found you can run all clang tests with make clang-test or you can run just the interpreter tests with something like:

⬢ [Docker] ~/projects/third-party/llvm-project/build on fix-pch at 02:54:43
❯ ./bin/llvm-lit -j1 -v ../clang/test/Interpreter

Hopefully that helps. If you're able to look into the fix for this, I'd very much appreciate it.

@jeaye
Copy link
Author

jeaye commented Jul 5, 2024

Hi @fhahn! Is there any chance you've had some time to look into this crash? Or perhaps if you have some ideas you can share for anyone else who might look into this?

vgvassilev added a commit to vgvassilev/llvm-project that referenced this issue Jul 9, 2024
…lation.

In incremental compilation clang works with multiple `llvm::Module`s. Our
current approach is to create a CodeGenModule entity for every new module
request (via StartModule). However, some of the state such as the mangle context
needs to be preserved to keep the original semantics in the ever-growing TU.

Fixes: llvm#95581.
vgvassilev added a commit to vgvassilev/llvm-project that referenced this issue Jul 9, 2024
…lation.

In incremental compilation clang works with multiple `llvm::Module`s. Our
current approach is to create a CodeGenModule entity for every new module
request (via StartModule). However, some of the state such as the mangle context
needs to be preserved to keep the original semantics in the ever-growing TU.

Fixes: llvm#95581.
vgvassilev added a commit to vgvassilev/llvm-project that referenced this issue Jul 9, 2024
…lation.

In incremental compilation clang works with multiple `llvm::Module`s. Our
current approach is to create a CodeGenModule entity for every new module
request (via StartModule). However, some of the state such as the mangle context
needs to be preserved to keep the original semantics in the ever-growing TU.

Fixes: llvm#95581.
vgvassilev added a commit to vgvassilev/llvm-project that referenced this issue Jul 18, 2024
…lation.

In incremental compilation clang works with multiple `llvm::Module`s. Our
current approach is to create a CodeGenModule entity for every new module
request (via StartModule). However, some of the state such as the mangle context
needs to be preserved to keep the original semantics in the ever-growing TU.

Fixes: llvm#95581.
@EugeneZelenko EugeneZelenko added clang:codegen IR generation bugs: mangling, exceptions, etc. and removed clang-tools-extra labels Aug 21, 2024
@llvmbot
Copy link
Member

llvmbot commented Aug 21, 2024

@llvm/issue-subscribers-clang-codegen

Author: Jeaye Wilkerson (jeaye)

Hi folks. I've been working with @vgvassilev to identify an issue with Clang/LLVM 19. Currently running on Vassil's branch here: https://github.com//pull/94166

NOTE: This issue does not exist in LLVM 18 (1118c2e).

I have a minimal repro case shown below. It works with -O0, but crashes with -O1 or higher.

The C++ source

struct box {
  box() = default;
  box(int *const data) : data{data} {}

  int *data{};
};

box foo() {
  box ret;
  /* The assignment here causes the crash. Using direct initialization works.
   * With -O0, this compiles and works. With -O1 or above, it dies. */
  ret = new int{};
  return ret;
}

The repro steps

❯ ./build/bin/clang-repl -Xcc -O1
clang-repl&gt; #include "foo.hpp"
Segmentation fault (core dumped)

The backtrace

#<!-- -->0  0x0000555558b9e025 in clang::CodeGen::CodeGenTypes::ConvertRecordDeclType(clang::RecordDecl const*) ()
#<!-- -->1  0x0000555558b9ef2b in clang::CodeGen::CodeGenTypes::getCGRecordLayout(clang::RecordDecl const*) ()
#<!-- -->2  0x0000555558b9ab87 in clang::CodeGen::CodeGenTBAA::CollectFields(unsigned long, clang::QualType, llvm::SmallVectorImpl&lt;llvm::MDBuilder::TBAAStructField&gt;&amp;, bool) ()
#<!-- -->3  0x0000555558b9b358 in clang::CodeGen::CodeGenTBAA::getTBAAStructInfo(clang::QualType) ()
#<!-- -->4  0x00005555589a6853 in clang::CodeGen::CodeGenFunction::EmitAggregateCopy(clang::CodeGen::LValue, clang::CodeGen::LValue, clang::QualType, clang::CodeGen::AggValueSlot::Overlap_t, bool) ()
#<!-- -->5  0x00005555589bc204 in clang::CodeGen::CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(clang::CallExpr const*, clang::CXXMethodDecl const*, clang::CodeGen::ReturnValueSlot, bool, clang::NestedNameSpecifier*, bool, clang::Expr const*) ()
#<!-- -->6  0x00005555589bd268 in clang::CodeGen::CodeGenFunction::EmitCXXOperatorMemberCallExpr(clang::CXXOperatorCallExpr const*, clang::CXXMethodDecl const*, clang::CodeGen::ReturnValueSlot) ()
#<!-- -->7  0x00005555589955bd in clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) ()
#<!-- -->8  0x0000555558995700 in clang::CodeGen::CodeGenFunction::EmitCallExprLValue(clang::CallExpr const*) ()
#<!-- -->9  0x000055555899597e in clang::CodeGen::CodeGenFunction::EmitLValueHelper(clang::Expr const*, clang::CodeGen::KnownNonNull_t) ()
#<!-- -->10 0x00005555589963d4 in clang::CodeGen::CodeGenFunction::EmitLValue(clang::Expr const*, clang::CodeGen::KnownNonNull_t) ()
#<!-- -->11 0x0000555558995d0d in clang::CodeGen::CodeGenFunction::EmitLValueHelper(clang::Expr const*, clang::CodeGen::KnownNonNull_t) ()
#<!-- -->12 0x0000555558994070 in clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) ()
#<!-- -->13 0x0000555558ab0d92 in clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef&lt;clang::Attr const*&gt;) ()
#<!-- -->14 0x0000555558ab7ef9 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&amp;, bool, clang::CodeGen::AggValueSlot) ()
#<!-- -->15 0x0000555558b14cdc in clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) ()
#<!-- -->16 0x0000555558b2672f in clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&amp;) ()
#<!-- -->17 0x0000555558b6a44a in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) ()
#<!-- -->18 0x0000555558b664bc in clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) ()
#<!-- -->19 0x0000555558b66d5b in clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) ()
#<!-- -->20 0x0000555558b6e1b7 in clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) [clone .part.0] ()
#<!-- -->21 0x0000555558896d81 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) ()
#<!-- -->22 0x00005555588719e7 in clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) ()
#<!-- -->23 0x000055555834df3f in clang::IncrementalASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef) ()
#<!-- -->24 0x0000555558351424 in clang::IncrementalParser::ParseOrWrapTopLevelDecl() ()
#<!-- -->25 0x000055555835225d in clang::IncrementalParser::Parse(llvm::StringRef) ()
#<!-- -->26 0x0000555558342568 in clang::Interpreter::ParseAndExecute(llvm::StringRef, clang::Value*) ()
#<!-- -->27 0x0000555556333495 in main ()

Environment details

  • OS: Ubuntu 24.04 (distrobox)
  • LLVM commit: 0b3fc78

cjdb pushed a commit to cjdb/llvm-project that referenced this issue Aug 23, 2024
…lation. (llvm#98138)

In incremental compilation clang works with multiple `llvm::Module`s.
Our current approach is to create a CodeGenModule entity for every new
module request (via StartModule). However, some of the state such as the
mangle context needs to be preserved to keep the original semantics in
the ever-growing TU.

Fixes: llvm#95581.

cc: @jeaye
llvmbot pushed a commit to llvmbot/llvm-project that referenced this issue Oct 11, 2024
…lation. (llvm#98138)

In incremental compilation clang works with multiple `llvm::Module`s.
Our current approach is to create a CodeGenModule entity for every new
module request (via StartModule). However, some of the state such as the
mangle context needs to be preserved to keep the original semantics in
the ever-growing TU.

Fixes: llvm#95581.

cc: @jeaye
(cherry picked from commit 6c62ad4)
tru pushed a commit to llvmbot/llvm-project that referenced this issue Oct 15, 2024
…lation. (llvm#98138)

In incremental compilation clang works with multiple `llvm::Module`s.
Our current approach is to create a CodeGenModule entity for every new
module request (via StartModule). However, some of the state such as the
mangle context needs to be preserved to keep the original semantics in
the ever-growing TU.

Fixes: llvm#95581.

cc: @jeaye
(cherry picked from commit 6c62ad4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
@fhahn @jeaye @vgvassilev @EugeneZelenko @llvmbot and others