-
Notifications
You must be signed in to change notification settings - Fork 15k
[CIR] Upstream Re-Throw with no return #154994
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
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for the throw op without sub expression and with noreturn Issue #154992 Full diff: https://github.com/llvm/llvm-project/pull/154994.diff 11 Files Affected:
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
|
|
def CIR_ThrowOp : CIR_Op<"throw"> { | ||
let summary = "(Re)Throws an exception"; | ||
let description = [{ | ||
Very similar to __cxa_throw: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is is "very similar" or is it "equivalent"?
@@ -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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nullptr; | |
return {}; |
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, unrelated cleanups like this are discouraged. It's better to leave it until this code is being modified or add it as a separate commit.
(void)builder.createBlock(region); | ||
|
||
// This will be erased during codegen, it acts as a placeholder for the | ||
// operations to be inserted (if any) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which operations will be inserted here? It looks like any instructions following the throw will get inserted in the block created above, but it doesn't look like they go into the scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right, it's more clear when I tested it with code after throw, Thanks
if (rethrows()) | ||
return success(); | ||
|
||
if (getNumOperands() == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (getNumOperands() == 1) { | |
if (getNumOperands() != 0) { |
I don't think this will ever be 1. In fact, maybe we should check for that. We need at least type info and an exception pointer if this isn't a rethrow.
When RTTI is implemented, it might be good to add a check to verify that type_info
references valid type info, and perhaps also that dtor
, if present, references a destructor.
@@ -405,17 +405,37 @@ void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) { | |||
true); | |||
} | |||
|
|||
void LoweringPreparePass::lowerThrowOp(ThrowOp op) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this happen here rather than in LowerToLLVM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it, it was confusing that rethrow is in LP but throw in LowerToLLVM 🤔
7091a4d
to
9faf678
Compare
// if (b == 0) | ||
// throw "Division by zero condition!"; | ||
cir.if %cond { | ||
%exception_addr = cir.alloc_exception 8 -> !cir.ptr<!void> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment above mentions cir.cxa.allocate_exception
which one is true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the CIR_AllocExceptionOp
description, running a sample locally cir.alloc_exception
is the correct one. I will update the description. Thanks
let arguments = (ins Optional<CIR_PointerType>:$exception_ptr, | ||
OptionalAttr<FlatSymbolRefAttr>:$type_info, | ||
OptionalAttr<FlatSymbolRefAttr>:$dtor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let arguments = (ins Optional<CIR_PointerType>:$exception_ptr, | |
OptionalAttr<FlatSymbolRefAttr>:$type_info, | |
OptionalAttr<FlatSymbolRefAttr>:$dtor); | |
let arguments = (ins | |
Optional<CIR_PointerType>:$exception_ptr, | |
OptionalAttr<FlatSymbolRefAttr>:$type_info, | |
OptionalAttr<FlatSymbolRefAttr>:$dtor | |
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM once all existing comments are addressed (not clear if they all did)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good. I have a lot of suggestions for updating the op description, but feel free to merge after updating those.
def CIR_ThrowOp : CIR_Op<"throw"> { | ||
let summary = "(Re)Throws an exception"; | ||
let description = [{ | ||
It's equivalent __cxa_throw: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's equivalent __cxa_throw: | |
This operation is equivalent to either __cxa_throw or __cxa_rethrow, depending on the arguments. |
It's equivalent __cxa_throw: | ||
|
||
``` | ||
void __cxa_throw(void *thrown_exception, std::type_info *tinfo, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this adds any useful information. I'd remove it.
|
||
Example: | ||
```mlir | ||
// throw; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// throw; | |
// re-throw; |
cir.store %string_addr, %exception_addr : !cir.ptr<!s8i>, | ||
!cir.ptr<!cir.ptr<!s8i>> | ||
cir.throw %exception_addr : !cir.ptr<!cir.ptr<!u8i>>, | ||
@"typeinfo for char const*" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@"typeinfo for char const*" | |
@_ZTIPKc |
|
||
// if (b == 0) | ||
// throw "Division by zero condition!"; | ||
cir.if %cond { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cir.if %cond { | |
// Type info for char const* | |
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i> | |
cir.if %cond { |
7e764c3
to
22b5a33
Compare
This change adds support for the throw op without sub expression and with noreturn
Issue #154992