llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> Implement the reference type of record ptr in initCatchParam --- Full diff: https://github.com/llvm/llvm-project/pull/185214.diff 2 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp (+74-4) - (modified) clang/test/CIR/CodeGen/try-catch.cpp (+127) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index b347c15e888a0..ef2c57c7ce327 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -586,6 +586,10 @@ class CIRGenItaniumRTTIBuilder { /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c. void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd); + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used + /// for pointer types. + void buildPointerTypeInfo(mlir::Location loc, QualType pointeeTy); + public: CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm) : cgm(cgm), cxxABI(abi) {} @@ -1467,7 +1471,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo( break; case Type::Pointer: - cgm.errorNYI("buildTypeInfo: Pointer"); + buildPointerTypeInfo(loc, cast<PointerType>(ty)->getPointeeType()); break; case Type::MemberPointer: @@ -1597,6 +1601,55 @@ mlir::Value CIRGenItaniumCXXABI::emitTypeid(CIRGenFunction &cgf, QualType srcTy, cgf.getPointerAlign()); } +/// Compute the flags for a __pbase_type_info, and remove the corresponding +/// pieces from \p Type. +static unsigned extractPBaseFlags(ASTContext &ctx, QualType &type) { + unsigned flags = 0; + + if (type.isConstQualified()) + flags |= PTI_Const; + if (type.isVolatileQualified()) + flags |= PTI_Volatile; + if (type.isRestrictQualified()) + flags |= PTI_Restrict; + type = type.getUnqualifiedType(); + + // Itanium C++ ABI 2.9.5p7: + // When the abi::__pbase_type_info is for a direct or indirect pointer to an + // incomplete class type, the incomplete target type flag is set. + if (containsIncompleteClassType(type)) + flags |= PTI_Incomplete; + + if (auto *proto = type->getAs<FunctionProtoType>()) { + if (proto->isNothrow()) { + flags |= PTI_Noexcept; + type = ctx.getFunctionTypeWithExceptionSpec(type, EST_None); + } + } + + return flags; +} + +/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, +/// used for pointer types. +void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc, + QualType pointeeTy) { + // Itanium C++ ABI 2.9.5p7: + // __flags is a flag word describing the cv-qualification and other + // attributes of the type pointed to + unsigned flags = extractPBaseFlags(cgm.getASTContext(), pointeeTy); + mlir::Type unsignedIntLTy = + cgm.getTypes().convertType(cgm.getASTContext().UnsignedIntTy); + fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags)); + + // Itanium C++ ABI 2.9.5p7: + // __pointee is a pointer to the std::type_info derivation for the + // unqualified type being pointed to. + mlir::Attribute pointeeTypeInfo = + CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, pointeeTy); + fields.push_back(pointeeTypeInfo); +} + mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty) { return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty); @@ -2441,9 +2494,26 @@ static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, // We have no way to tell the personality function that we're // catching by reference, so if we're catching a pointer, // __cxa_begin_catch will actually return that pointer by value. - if (isa<PointerType>(caughtType)) { - cgf.cgm.errorNYI(loc, "initCatchParam: catching a pointer"); - return; + if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) { + QualType pointeeType = pt->getPointeeType(); + // When catching by reference, generally we should just ignore + // this by-value pointer and use the exception object instead. + if (!pointeeType->isRecordType()) { + cgf.cgm.errorNYI(loc, + "initCatchParam: catching a pointer of non-record"); + } else { + // Pull the pointer for the reference type off. + mlir::Type ptrTy = cgf.convertTypeForMem(caughtType); + + // Create the temporary and write the adjusted pointer into it. + Address exnPtrTmp = cgf.createTempAlloca( + ptrTy, cgf.getPointerAlign(), cgf.getLoc(loc), "exn.byref.tmp"); + mlir::Value casted = cgf.getBuilder().createBitcast(adjustedExn, ptrTy); + cgf.getBuilder().createStore(cgf.getLoc(loc), casted, exnPtrTmp); + + // Bind the reference to the temporary. + adjustedExn = exnPtrTmp.emitRawPointer(); + } } mlir::Value exnCast = diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp index a9ad38a56715d..0d82fd70d0da8 100644 --- a/clang/test/CIR/CodeGen/try-catch.cpp +++ b/clang/test/CIR/CodeGen/try-catch.cpp @@ -996,3 +996,130 @@ void cleanup_inside_try_body() { // OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXCEPTION]]) // OGCG: call void @__cxa_end_catch() // OGCG: br label %[[TRY_CONT]] + +struct Record { + int x; + int y; +}; + +void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() { + try { + division(); + } catch (Record *&ref_ptr) { + } +} + +// CIR: cir.func {{.*}} @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev(){{.*}} personality(@__gxx_personality_v0) { +// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>, ["ref_ptr", const] +// CIR: %[[EXN_BYREF_TMP:.*]] = cir.alloca !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>>, ["exn.byref.tmp"] +// CIR: cir.try { +// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef}) +// CIR: cir.yield +// CIR: } catch [type #cir.global_view<@_ZTIP6Record> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token {{.*}}) { +// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!rec_Record>>) +// CIR: cir.cleanup.scope { +// CIR: %[[EXN_PTR_REC_PTR:.*]] = cir.cast bitcast %[[EXN_PTR]] : !cir.ptr<!cir.ptr<!rec_Record>> -> !cir.ptr<!rec_Record> +// CIR: cir.store {{.*}} %[[EXN_PTR_REC_PTR]], %[[EXN_BYREF_TMP]] : !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>> +// CIR: cir.store {{.*}} %[[EXN_BYREF_TMP]], %[[E_ADDR]] : !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>> +// CIR: cir.yield +// CIR: } cleanup all { +// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token +// CIR: cir.yield +// CIR: } +// CIR: cir.yield +// CIR: } unwind (%{{.*}}: !cir.eh_token {{.*}}) { +// CIR: cir.resume %{{.*}} : !cir.eh_token +// CIR: } +// CIR: } + +// LLVM: define {{.*}} void @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev() {{.*}} personality ptr @__gxx_personality_v0 +// LLVM: %[[E_ADDR:.*]] = alloca ptr +// LLVM: %[[EXN_BYREF_TMP:.*]] = alloca ptr +// LLVM: br label %[[TRY_SCOPE:.*]] +// LLVM: [[TRY_SCOPE]]: +// LLVM: br label %[[TRY_BEGIN:.*]] +// LLVM: [[TRY_BEGIN]]: +// LLVM: invoke i32 @_Z8divisionv() +// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]] +// LLVM: [[INVOKE_CONT:.*]]: +// LLVM: br label %[[TRY_CONT:.*]] +// LLVM: [[LANDING_PAD]]: +// LLVM: %[[LP:.*]] = landingpad { ptr, i32 } +// LLVM: catch ptr @_ZTIP6Record +// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0 +// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1 +// LLVM: br label %[[CATCH:.*]] +// LLVM: [[CATCH]]: +// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ] +// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ] +// LLVM: br label %[[DISPATCH:.*]] +// LLVM: [[DISPATCH]]: +// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ] +// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ] +// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIP6Record) +// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]] +// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]] +// LLVM: [[BEGIN_CATCH]]: +// LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] +// LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] +// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]]) +// LLVM: br label %[[CATCH_BODY:.*]] +// LLVM: [[CATCH_BODY]]: +// LLVM: store ptr %[[TOKEN]], ptr %[[EXN_BYREF_TMP]], align 8 +// LLVM: store ptr %[[EXN_BYREF_TMP]], ptr %[[E_ADDR]], align 8 +// LLVM: br label %[[END_CATCH:.*]] +// LLVM: [[END_CATCH]]: +// LLVM: call void @__cxa_end_catch() +// LLVM: br label %[[END_DISPATCH:.*]] +// LLVM: [[END_DISPATCH]]: +// LLVM: br label %[[END_TRY:.*]] +// LLVM: [[END_TRY]]: +// LLVM: br label %[[TRY_CONT:.*]] +// LLVM: [[RESUME]]: +// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ] +// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ] +// LLVM: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0 +// LLVM: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1 +// LLVM: resume { ptr, i32 } %[[EXCEPTION_INFO]] +// LLVM: [[TRY_CONT]]: +// LLVM: br label %[[DONE:.*]] +// LLVM: [[DONE]]: +// LLVM: ret void + +// OGCG: define {{.*}} void @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev() {{.*}} personality ptr @__gxx_personality_v0 +// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[E_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[EXN_BYREF_TMP:.*]] = alloca ptr, align 8 +// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv() +// OGCG: to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]] +// OGCG: [[INVOKE_NORMAL]]: +// OGCG: br label %[[TRY_CONT:.*]] +// OGCG: [[INVOKE_UNWIND]]: +// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 } +// OGCG: catch ptr @_ZTIP6Record +// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0 +// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1 +// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: br label %[[CATCH_DISPATCH:.*]] +// OGCG: [[CATCH_DISPATCH]]: +// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %ehselector.slot, align 4 +// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIP6Record) +// OGCG: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]] +// OGCG: br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[EH_RESUME:.*]] +// OGCG: [[CATCH_EXCEPTION]]: +// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]]) +// OGCG: store ptr %[[BEGIN_CATCH]], ptr %[[EXN_BYREF_TMP]], align 8 +// OGCG: store ptr %[[EXN_BYREF_TMP]], ptr %[[E_ADDR]], align 8 +// OGCG: call void @__cxa_end_catch() +// OGCG: br label %[[TRY_CONT]] +// OGCG: [[TRY_CONT]]: +// OGCG: ret void +// OGCG: [[EH_RESUME]]: +// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8 +// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4 +// OGCG: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[TMP_EXCEPTION]], 0 +// OGCG: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1 +// OGCG: resume { ptr, i32 } %[[EXCEPTION_INFO]] `````````` </details> https://github.com/llvm/llvm-project/pull/185214 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
