https://github.com/AmrDeveloper updated 
https://github.com/llvm/llvm-project/pull/154994

>From ee45be1718bf21b394a8bb0893efff1a3416853c Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Fri, 22 Aug 2025 15:34:47 +0200
Subject: [PATCH 1/2] [CIR] Upstream Re-Throw with no return

---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      | 21 +++++++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 54 +++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenCXXABI.h          |  4 +-
 clang/lib/CIR/CodeGen/CIRGenException.cpp     | 41 ++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  5 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |  2 +
 clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 50 ++++++++++++++++-
 clang/lib/CIR/CodeGen/CMakeLists.txt          |  1 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 18 +++++++
 .../Dialect/Transforms/LoweringPrepare.cpp    | 36 ++++++++++---
 clang/test/CIR/CodeGen/exceptions.cpp         | 19 +++++++
 11 files changed, 240 insertions(+), 11 deletions(-)
 create mode 100644 clang/lib/CIR/CodeGen/CIRGenException.cpp
 create mode 100644 clang/test/CIR/CodeGen/exceptions.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index d29e5687d2544..aba4615b2a7f4 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -19,7 +19,6 @@
 
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
-#include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/Location.h"
 #include "mlir/IR/Types.h"
 
@@ -313,6 +312,26 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
                         resOperands, attrs);
   }
 
+  cir::CallOp
+  createTryCallOp(mlir::Location loc,
+                  mlir::SymbolRefAttr callee = mlir::SymbolRefAttr(),
+                  mlir::Type returnType = cir::VoidType(),
+                  mlir::ValueRange operands = mlir::ValueRange(),
+                  cir::SideEffect sideEffect = cir::SideEffect::All) {
+    assert(!cir::MissingFeatures::opCallCallConv());
+    return createCallOp(loc, callee, returnType, operands);
+  }
+
+  cir::CallOp
+  createTryCallOp(mlir::Location loc, cir::FuncOp callee,
+                  mlir::ValueRange operands,
+                  cir::SideEffect sideEffect = cir::SideEffect::All) {
+    assert(!cir::MissingFeatures::opCallCallConv());
+    return createTryCallOp(loc, mlir::SymbolRefAttr::get(callee),
+                           callee.getFunctionType().getReturnType(), operands,
+                           sideEffect);
+  }
+
   
//===--------------------------------------------------------------------===//
   // Cast/Conversion Operators
   
//===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index f237642700924..708dd35694913 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3757,4 +3757,58 @@ def CIR_VAArgOp : CIR_Op<"va_arg"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// ThrowOp
+//===----------------------------------------------------------------------===//
+
+def CIR_ThrowOp : CIR_Op<"throw"> {
+  let summary = "(Re)Throws an exception";
+  let description = [{
+    Very similar to __cxa_throw:
+
+    ```
+    void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
+                     void (*dest) (void *));
+    ```
+
+    The absense of arguments for `cir.throw` means it rethrows.
+
+    For the no-rethrow version, it must have at least two operands, the RTTI
+    information, a pointer to the exception object (likely allocated via
+    `cir.cxa.allocate_exception`) and finally an optional dtor, which might
+    run as part of this operation.
+
+    Example:
+    ```mlir
+      // throw;
+      cir.throw
+
+      // if (b == 0)
+      //   throw "Division by zero condition!";
+      cir.if %cond {
+        %exception_addr = cir.alloc_exception 8 -> !cir.ptr<!void>
+        ...
+        cir.store %string_addr, %exception_addr : // Store string addr for 
"Division by zero condition!"
+        cir.throw %exception_addr : !cir.ptr<!cir.ptr<!u8i>>, @"typeinfo for 
char const*"
+    ```
+  }];
+
+  let arguments = (ins Optional<CIR_PointerType>:$exception_ptr,
+                       OptionalAttr<FlatSymbolRefAttr>:$type_info,
+                       OptionalAttr<FlatSymbolRefAttr>:$dtor);
+
+  let assemblyFormat = [{
+    ($exception_ptr^ `:` type($exception_ptr))?
+    (`,` $type_info^)?
+    (`,` $dtor^)?
+    attr-dict
+  }];
+
+  let extraClassDeclaration = [{
+    bool rethrows() { return getNumOperands() == 0; }
+  }];
+
+  let hasVerifier = 1;
+}
+
 #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h 
b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 3f1cb8363a556..104844859382c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -47,9 +47,11 @@ class CIRGenCXXABI {
   }
 
   /// Emit the ABI-specific prolog for the function
-  virtual void emitInstanceFunctionProlog(SourceLocation Loc,
+  virtual void emitInstanceFunctionProlog(SourceLocation loc,
                                           CIRGenFunction &cgf) = 0;
 
+  virtual void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) = 0;
+
   /// Get the type of the implicit "this" parameter used by a method. May 
return
   /// zero if no specific type is applicable, e.g. if the ABI expects the 
"this"
   /// parameter to point to some artificial offset in a complete object due to
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp 
b/clang/lib/CIR/CodeGen/CIRGenException.cpp
new file mode 100644
index 0000000000000..7fcb39a2b74c4
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -0,0 +1,41 @@
+//===--- CIRGenException.cpp - Emit CIR Code for C++ exceptions -*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ exception related code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenCXXABI.h"
+#include "CIRGenFunction.h"
+
+#include "clang/AST/StmtVisitor.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {
+  const llvm::Triple &triple = getTarget().getTriple();
+  if (cgm.getLangOpts().OpenMPIsTargetDevice &&
+      (triple.isNVPTX() || triple.isAMDGCN())) {
+    cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
+    return;
+  }
+
+  if (const Expr *subExpr = e->getSubExpr()) {
+    QualType throwType = subExpr->getType();
+    if (throwType->isObjCObjectPointerType()) {
+      cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");
+      return;
+    } else {
+      cgm.errorNYI("emitCXXThrowExpr with subExpr");
+      return;
+    }
+  } else {
+    cgm.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
+  }
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index f6b2c88f2cfb4..d4efd046f7474 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -657,6 +657,11 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
     return cgf.emitCXXNewExpr(e);
   }
 
+  mlir::Value VisitCXXThrowExpr(const CXXThrowExpr *e) {
+    cgf.emitCXXThrowExpr(e);
+    return nullptr;
+  }
+
   /// Emit a conversion from the specified type to the specified destination
   /// type, both of which are CIR scalar types.
   /// TODO: do we need ScalarConversionOpts here? Should be done in another
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 0ef8e7b7fbcac..af08bd465b2d2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1140,6 +1140,8 @@ class CIRGenFunction : public CIRGenTypeCache {
 
   RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr);
 
+  void emitCXXThrowExpr(const CXXThrowExpr *e);
+
   void emitCtorPrologue(const clang::CXXConstructorDecl *ctor,
                         clang::CXXCtorType ctorType, FunctionArgList &args);
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 347656b5f6488..283376188267f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -56,6 +56,8 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
                           bool delegating, Address thisAddr,
                           QualType thisTy) override;
 
+  void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
+
   bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
                               CXXDtorType dt) const override {
     // Itanium does not emit any destructor variant as an inline thunk.
@@ -123,7 +125,7 @@ void 
CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
 // Find out how to cirgen the complete destructor and constructor
 namespace {
 enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
-}
+} // namespace
 
 static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
                                      const CXXMethodDecl *md) {
@@ -289,6 +291,52 @@ void CIRGenItaniumCXXABI::emitDestructorCall(
                             vttTy, nullptr);
 }
 
+// The idea here is creating a separate block for the throw with an
+// `UnreachableOp` as the terminator. So, we branch from the current block
+// to the throw block and create a block for the remaining operations.
+static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
+                                mlir::Value exceptionPtr = {},
+                                mlir::FlatSymbolRefAttr typeInfo = {},
+                                mlir::FlatSymbolRefAttr dtor = {}) {
+  mlir::Block *currentBlock = builder.getInsertionBlock();
+  mlir::Region *region = currentBlock->getParent();
+
+  if (currentBlock->empty()) {
+    cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
+    cir::UnreachableOp::create(builder, loc);
+  } else {
+    mlir::Block *throwBlock = builder.createBlock(region);
+
+    cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
+    cir::UnreachableOp::create(builder, loc);
+
+    builder.setInsertionPointToEnd(currentBlock);
+    cir::BrOp::create(builder, loc, throwBlock);
+  }
+
+  (void)builder.createBlock(region);
+
+  // This will be erased during codegen, it acts as a placeholder for the
+  // operations to be inserted (if any)
+  cir::ScopeOp::create(builder, loc, /*scopeBuilder=*/
+                       [&](mlir::OpBuilder &b, mlir::Location loc) {
+                         b.create<cir::YieldOp>(loc);
+                       });
+}
+
+void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
+  // void __cxa_rethrow();
+
+  if (isNoReturn) {
+    CIRGenBuilderTy &builder = cgf.getBuilder();
+    assert(cgf.currSrcLoc && "expected source location");
+    mlir::Location loc = *cgf.currSrcLoc;
+    insertThrowAndSplit(builder, loc);
+  } else {
+    cgm.errorNYI("emitRethrow with isNoReturn false");
+  }
+}
+
 CIRGenCXXABI *clang::CIRGen::CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) {
   switch (cgm.getASTContext().getCXXABIKind()) {
   case TargetCXXABI::GenericItanium:
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt 
b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 7366446a33c6e..6d7072ad18696 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -20,6 +20,7 @@ add_clang_library(clangCIR
   CIRGenBuiltin.cpp
   CIRGenDecl.cpp
   CIRGenDeclOpenACC.cpp
+  CIRGenException.cpp
   CIRGenExpr.cpp
   CIRGenExprAggregate.cpp
   CIRGenExprComplex.cpp
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 167b970cdda12..ea39db64622bc 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2646,6 +2646,24 @@ ParseResult cir::InlineAsmOp::parse(OpAsmParser &parser,
   return mlir::success();
 }
 
+//===----------------------------------------------------------------------===//
+// ThrowOp
+//===----------------------------------------------------------------------===//
+
+mlir::LogicalResult cir::ThrowOp::verify() {
+  // For the no-rethrow version, it must have at least the exception pointer.
+  if (rethrows())
+    return success();
+
+  if (getNumOperands() == 1) {
+    if (getTypeInfo())
+      return success();
+    return emitOpError() << "'type_info' symbol attribute missing";
+  }
+
+  return failure();
+}
+
 
//===----------------------------------------------------------------------===//
 // TableGen'd op method definitions
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 66260eb36e002..8f192eae3926b 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -8,7 +8,6 @@
 
 #include "PassDetail.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/CharUnits.h"
 #include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIROpsEnums.h"
@@ -31,6 +30,7 @@ struct LoweringPreparePass : public 
LoweringPrepareBase<LoweringPreparePass> {
   void lowerUnaryOp(cir::UnaryOp op);
   void lowerArrayDtor(cir::ArrayDtor op);
   void lowerArrayCtor(cir::ArrayCtor op);
+  void lowerThrowOp(ThrowOp op);
 
   cir::FuncOp buildRuntimeFunction(
       mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc,
@@ -405,17 +405,37 @@ void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor 
op) {
                              true);
 }
 
+void LoweringPreparePass::lowerThrowOp(ThrowOp op) {
+  if (op.rethrows()) {
+    CIRBaseBuilderTy builder(getContext());
+    auto voidTy = cir::VoidType::get(builder.getContext());
+    auto fnType = cir::FuncType::get({}, voidTy);
+
+    builder.setInsertionPointToStart(&mlirModule.getBodyRegion().front());
+    FuncOp f =
+        buildRuntimeFunction(builder, "__cxa_rethrow", op.getLoc(), fnType);
+
+    builder.setInsertionPointAfter(op.getOperation());
+    cir::CallOp call = builder.createTryCallOp(op.getLoc(), f, {});
+
+    op->replaceAllUsesWith(call);
+    op->erase();
+  }
+}
+
 void LoweringPreparePass::runOnOp(mlir::Operation *op) {
   if (auto arrayCtor = dyn_cast<ArrayCtor>(op))
     lowerArrayCtor(arrayCtor);
   else if (auto arrayDtor = dyn_cast<cir::ArrayDtor>(op))
     lowerArrayDtor(arrayDtor);
-  else if (auto cast = mlir::dyn_cast<cir::CastOp>(op))
-    lowerCastOp(cast);
-  else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op))
-    lowerComplexMulOp(complexMul);
-  else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op))
-    lowerUnaryOp(unary);
+  else if (auto castOp = mlir::dyn_cast<cir::CastOp>(op))
+    lowerCastOp(castOp);
+  else if (auto complexMulOp = mlir::dyn_cast<cir::ComplexMulOp>(op))
+    lowerComplexMulOp(complexMulOp);
+  else if (auto unaryOp = mlir::dyn_cast<cir::UnaryOp>(op))
+    lowerUnaryOp(unaryOp);
+  else if (auto throwOp = mlir::dyn_cast<cir::ThrowOp>(op))
+    lowerThrowOp(throwOp);
 }
 
 void LoweringPreparePass::runOnOperation() {
@@ -427,7 +447,7 @@ void LoweringPreparePass::runOnOperation() {
 
   op->walk([&](mlir::Operation *op) {
     if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp,
-                  cir::ComplexMulOp, cir::UnaryOp>(op))
+                  cir::ComplexMulOp, cir::UnaryOp, cir::ThrowOp>(op))
       opsToTransform.push_back(op);
   });
 
diff --git a/clang/test/CIR/CodeGen/exceptions.cpp 
b/clang/test/CIR/CodeGen/exceptions.cpp
new file mode 100644
index 0000000000000..a1a87bcb2f393
--- /dev/null
+++ b/clang/test/CIR/CodeGen/exceptions.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-fcxx-exceptions -fexceptions -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+void foo() {
+  throw;
+}
+
+// CIR: cir.call @__cxa_rethrow() : () -> ()
+// CIR: cir.unreachable
+
+// LLVM: call void @__cxa_rethrow()
+// LLVM: unreachable
+
+// OGCG: call void @__cxa_rethrow()
+// OGCG: unreachable

>From 2a38b830a1646a233773f1f5e00d63ba35ef2c70 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Fri, 22 Aug 2025 20:46:26 +0200
Subject: [PATCH 2/2] Rename test file to throws to be alligned with incubator
 for now

---
 clang/test/CIR/CodeGen/{exceptions.cpp => throws.cpp} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename clang/test/CIR/CodeGen/{exceptions.cpp => throws.cpp} (100%)

diff --git a/clang/test/CIR/CodeGen/exceptions.cpp 
b/clang/test/CIR/CodeGen/throws.cpp
similarity index 100%
rename from clang/test/CIR/CodeGen/exceptions.cpp
rename to clang/test/CIR/CodeGen/throws.cpp

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

Reply via email to