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
