llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: AZero13 (AZero13)

<details>
<summary>Changes</summary>

On 32-bit x86 targets using the Microsoft C++ ABI, `_CxxThrowException` 
requires the `__stdcall` (`x86_stdcallcc`) calling convention. While 
`MicrosoftCXXABI::getThrowFn()` correctly set this calling convention on the 
function declaration, the generated LLVM IR `call` instructions were 
incorrectly emitted using the default `__cdecl` calling convention. This 
mismatch corrupted the stack (since `stdcall` requires the callee to clean up 
arguments, but `cdecl` expects the caller to do it), leading to crashes when 
throwing exceptions.

Fixes #<!-- -->158302

---
Full diff: https://github.com/llvm/llvm-project/pull/222200.diff


2 Files Affected:

- (modified) clang/lib/CodeGen/CGCall.cpp (+15-3) 
- (added) clang/test/CodeGenCXX/microsoft-abi-throw-stdcall.cpp (+13) 


``````````diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 1221829871b9f..50e6403846259 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -5487,15 +5487,22 @@ void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(
   SmallVector<llvm::OperandBundleDef, 1> BundleList =
       getBundlesForFunclet(callee.getCallee());
 
+  llvm::CallingConv::ID CC;
+  // Get the calling convention from the callee if it's a function.
+  if (auto *Fn = dyn_cast<llvm::Function>(callee.getCallee()))
+    CC = Fn->getCallingConv();
+  else
+    CC = getRuntimeCC();
+
   if (getInvokeDest()) {
     llvm::InvokeInst *invoke = Builder.CreateInvoke(
         callee, getUnreachableBlock(), getInvokeDest(), args, BundleList);
     invoke->setDoesNotReturn();
-    invoke->setCallingConv(getRuntimeCC());
+    invoke->setCallingConv(CC);
   } else {
     llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList);
     call->setDoesNotReturn();
-    call->setCallingConv(getRuntimeCC());
+    call->setCallingConv(CC);
     Builder.CreateUnreachable();
   }
 }
@@ -5513,7 +5520,12 @@ 
CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee,
                                          ArrayRef<llvm::Value *> args,
                                          const Twine &name) {
   llvm::CallBase *call = EmitCallOrInvoke(callee, args, name);
-  call->setCallingConv(getRuntimeCC());
+  llvm::CallingConv::ID CC;
+  if (auto *Fn = dyn_cast<llvm::Function>(callee.getCallee()))
+    CC = Fn->getCallingConv();
+  else
+    CC = getRuntimeCC();
+  call->setCallingConv(CC);
   return call;
 }
 
diff --git a/clang/test/CodeGenCXX/microsoft-abi-throw-stdcall.cpp 
b/clang/test/CodeGenCXX/microsoft-abi-throw-stdcall.cpp
new file mode 100644
index 0000000000000..fa4e33b5a018d
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-throw-stdcall.cpp
@@ -0,0 +1,13 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-windows-msvc19.0.0 
-fcxx-exceptions -fms-extensions -fexceptions | FileCheck %s
+
+struct MyException {};
+// CHECK-LABEL: @f(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_MYEXCEPTION:%.*]], align 1
+// CHECK-NEXT:    call x86_stdcallcc void @_CxxThrowException(ptr [[TMP]], ptr 
@"_TI1?AUMyException@@") #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:    unreachable
+//
+extern "C" void f() {
+  throw MyException();
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/222200
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to