Issue 126365
Summary Clang Interpreter (clang::IncrementalCompilerBuilder) Crashes on MinGW-w64 When Executing Exception-Throwing IR Function
Labels clang
Assignees
Reporter ikappaki
    Hi,

I'm debugging an issue on MinGW-w64 in a project that uses `clang::IncrementalCompilerBuilder`. The problem occurs when calling an IR function that throws an exception, causing the program to crash.

Could this be an issue with calling an exception-throwing function from an IR module using `clang::IncrementalCompilerBuilder` on `MinGW-w64`? Or is it perhaps that am I missing something in my setup?

I was able to reproduce the issue in a minimal example outside the project:

- The crash does not occur when using `llvm::ExecutionEngine`.
- The issue only happens on Windows (`MinGW-w64`) and not on Linux.

```
$ clang --version
clang version 19.1.6
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: D:/local/msys64/clang64/bin
```

To reproduce, 
1. install the `msys2` development environment locally, 
2. Open up the MSYS2 CLANG64 Shell
3. Install clang:
```shell
pacman -S clang64/mingw-w64-clang-x86_64-clang
```
4. Compile the program
```shell
clang++ -o issue issue.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -g -Wl,--export-all-symbols -fexceptions -lclang-cpp
```
5. Run the program.  Observe the difference between the two execution methods: 
- `:EXECUTION-ENGINE` works fine, catches the exception
- `:INTERPRETER` crashes when exception is thrown
```shell
$ ./issue.exe


:EXECUTION-ENGINE

; ModuleID = 'direct-module'
source_filename = "direct-module"
target triple = "x86_64-w64-windows-gnu"

declare void @exception_throw()

define void @wrapper() {
entry:
  call void @exception_throw()
  ret void
}
:wrapper-calling...
:throwing-exception...
:exception-caught
:done


:INTERPRETER

; ModuleID = 'interpreter-module'
source_filename = "interpreter-module"
target triple = "x86_64-w64-windows-gnu"

declare void @exception_throw()

define void @wrapper() {
entry:
  call void @exception_throw()
  ret void
}
:wrapper-calling...
:throwing-exception...
;;; <program crashed>
```

Debugger trace:

```sh
$ lldb issue
(lldb) target create "issue"
Current executable set to 'issue.exe' (x86_64).
(lldb) run
(lldb) Process 49264 launched: 'issue.exe' (x86_64)
Process 49264 stopped
* thread #1, stop reason = Exception 0x20474343 encountered at address 0x7ffd04c2fb4c
    frame #0: 0x00007ffd04c2fb4c KernelBase.dll`RaiseException + 108
KernelBase.dll`RaiseException:
-> 0x7ffd04c2fb4c <+108>: nopl   (%rax,%rax)
    0x7ffd04c2fb51 <+113>: movq 0xc0(%rsp), %rcx
    0x7ffd04c2fb59 <+121>: xorq   %rsp, %rcx
 0x7ffd04c2fb5c <+124>: callq  0x7ffd04c80a40 ; SetProtectedPolicy + 112
(lldb) bt
* thread #1, stop reason = Exception 0x20474343 encountered at address 0x7ffd04c2fb4c
  * frame #0: 0x00007ffd04c2fb4c KernelBase.dll`RaiseException + 108
    frame #1: 0x00007ffc59ad2bf0 libc++.dll`_Unwind_RaiseException + 128
    frame #2: 0x00007ffc59af70aa libc++.dll`__cxa_throw + 58
    frame #3: 0x00007ff616ce13ff issue.exe`::exception_throw() at issue.cpp:19:5
    frame #4: 0x000001bdb2e10010
    frame #5: 0x00007ff616ce133c issue.exe`__tmainCRTStartup at crtexe.c:266:15
    frame #6: 0x00007ff616ce1396 issue.exe`mainCRTStartup at crtexe.c:186:9
    frame #7: 0x00007ffd0639259d kernel32.dll`BaseThreadInitThunk + 29
    frame #8: 0x00007ffd078eaf38 ntdll.dll`RtlUserThreadStart + 40
(lldb)

```


On Linux, compiling and running the same program does not cause a crash:
```sh

$ clang --version
clang version 19.1.5
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /nix/store/wrkvgny73b9lbjbkvm21k34kqnj4qsrn-clang-19.1.5/bin

$ clang++ -o issue issue.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -g -fexceptions -lclang-cpp -Xlinker -export-dynamic

$ ./issue

:EXECUTION-ENGINE

; ModuleID = 'direct-module'
source_filename = "direct-module"
target triple = "x86_64-unknown-linux-gnu"

declare void @exception_throw()

define void @wrapper() {
entry:
  call void @exception_throw()
  ret void
}
:wrapper-calling...
:throwing-exception...
:exception-caught
:done


:INTERPRETER

; ModuleID = 'interpreter-module'
source_filename = "interpreter-module"
target triple = "x86_64-unknown-linux-gnu"

declare void @exception_throw()

define void @wrapper() {
entry:
  call void @exception_throw()
  ret void
}
:wrapper-calling...
:throwing-exception...
:exception-caught
:done
```


The full source code demonstrating the issue is below. It defines an IR module where a function `exception_throw()` throws an exception. The function is executed both via `llvm::ExecutionEngine` (which catches the exception) and `clang::Interpreter` (which crashes).

`issue.cpp`
```c++
#include <clang/Interpreter/Interpreter.h>
#include <clang/Frontend/CompilerInstance.h>

#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/TargetParser/Host.h>

#include <iostream>

extern "C" {

  void exception_throw() {
    std::cout << ":throwing-exception...\n";
 throw "issue";
  }

}

std::unique_ptr<llvm::Module> moduleMake(llvm::LLVMContext& context, const std::string& moduleName) {
 std::unique_ptr<llvm::Module> module = std::make_unique<llvm::Module>(moduleName, context);
  llvm::IRBuilder<> builder(context);

 module->setTargetTriple(llvm::sys::getDefaultTargetTriple());

  auto const voidFnType(llvm::FunctionType::get(builder.getVoidTy(), {}, false));

 auto excThrowFn(module->getOrInsertFunction("exception_throw", voidFnType));
  auto excThrowFunc = llvm::cast<llvm::Function>(excThrowFn.getCallee());

  llvm::Function *wrapperFunc = llvm::Function::Create(voidFnType, llvm::Function::ExternalLinkage, "wrapper", *module);
  llvm::BasicBlock *wrapperBB = llvm::BasicBlock::Create(context, "entry", wrapperFunc);
 builder.SetInsertPoint(wrapperBB);
  builder.CreateCall(excThrowFunc);
 builder.CreateRetVoid();

  module->print(llvm::errs(), nullptr);

 return module;
}

void runInterpreter() {
  std::cout << "\n\n:INTERPRETER\n\n";

  std::unique_ptr<llvm::LLVMContext> context = std::make_unique<llvm::LLVMContext>();
  std::unique_ptr<llvm::Module> module = moduleMake(*context, "interpreter-module");

 clang::IncrementalCompilerBuilder compilerBuilder;
  std::vector<char const *> args{};
  // std::vector<char const *> args{"-fexception", "-funwind-tables", "-g" "-lclang-cpp"};
  // compilerBuilder.SetCompilerArgs(args);
 std::unique_ptr<clang::CompilerInstance> compilerInstance(llvm::cantFail(compilerBuilder.CreateCpp()));
 compilerInstance->LoadRequestedPlugins();

 std::unique_ptr<clang::Interpreter> interpreter =
 llvm::cantFail(clang::Interpreter::create(std::move(compilerInstance)));

 llvm::orc::LLJIT& jit(interpreter->getExecutionEngine().get());


 llvm::cantFail(jit.addIRModule(llvm::orc::ThreadSafeModule{ std::move(module), std::move(context) }));
 llvm::cantFail(jit.initialize(jit.getMainJITDylib()));


  auto sym = jit.lookup("wrapper");
  auto funcPtr = sym->toPtr<void(*)()>();
 assert(funcPtr);

  try {
      std::cout << ":wrapper-calling...\n";
 funcPtr();
    }
  catch(...) {
      std::cout << ":exception-caught\n";
    }
  std::cout << ":done\n";
}

void runExecutionEngine() {
  std::cout << "\n\n:EXECUTION-ENGINE\n\n";
 llvm::LLVMContext context;
  std::unique_ptr<llvm::Module> module = moduleMake(context, "direct-module");

  std::string errStr;
 llvm::ExecutionEngine *engine = llvm::EngineBuilder(std::move(module)).setErrorStr(&errStr).create();
  if (!engine) {
    std::cerr << "Error: " << errStr << std::endl;
 return;
  }

  llvm::Function* wrapperFunc = engine->FindFunctionNamed("wrapper");
  assert(wrapperFunc);
 std::vector<llvm::GenericValue> noArgs;
  try {
    std::cout << ":wrapper-calling...\n";
    engine->runFunction(wrapperFunc, noArgs);
 }
  catch (...) {
      std::cout << ":exception-caught\n";
    }
 std::cout << ":done\n";
}

int main() {
 llvm::InitializeNativeTarget();
 llvm::InitializeNativeTargetAsmPrinter();
    
  runExecutionEngine();
 
  runInterpreter();
  return 0;
}
```

Thanks
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to