[CIR] Support reference type of non-record ptr in InitCatchParam - #195722
Conversation
|
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesSupport init reference type of non-record ptr type in InitCatchParam Full diff: https://github.com/llvm/llvm-project/pull/195722.diff 6 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 97d623ba5e6d9..98b631a8ad6ee 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7691,7 +7691,7 @@ def CIR_InitCatchParamOp : CIR_Op<"init_catch_param"> {
}];
let arguments = (ins
- CIR_PointerType:$exn_ptr,
+ CIR_AnyPtrOrEHTokenType:$exn_ptr,
CIR_PointerType:$param_addr,
CIR_InitCatchKind:$kind
);
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 3cc79b9796e06..11b6ff5f11d62 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -400,4 +400,15 @@ def CIR_ComparableType
let cppFunctionName = "isComparableType";
}
+//===----------------------------------------------------------------------===//
+// Exception handling token Type predicates
+//===----------------------------------------------------------------------===//
+
+def CIR_AnyEhTokenType : CIR_TypeBase<"::cir::EhTokenType", "EH Token type">;
+
+def CIR_AnyPtrOrEHTokenType
+ : AnyTypeOf<[CIR_AnyPtrType, CIR_AnyEhTokenType],
+ "any ptr or EH token type"> {
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIRTYPECONSTRAINTS_TD
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 645fae3e4404d..f1d3c33aae32c 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -370,6 +370,7 @@ struct MissingFeatures {
// Maybe only needed for Windows exception handling
static bool currentFuncletPad() { return false; }
+ static bool sizeOfUnwindException() { return false; }
};
} // namespace cir
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index 3c956801f6b52..d84c6090bd49a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -306,10 +306,15 @@ static void initCatchParam(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
CanQualType catchType =
cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
cir::InitCatchKind kind;
+ bool shouldInitFromExnDirectly = false;
// If we're catching by reference, we can just cast the object
// pointer to the appropriate pointer.
if (isa<ReferenceType>(catchType)) {
+ QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType();
+ if (const PointerType *ptr = dyn_cast<PointerType>(caughtType)) {
+ shouldInitFromExnDirectly = !ptr->getPointeeType()->isRecordType();
+ }
kind = cir::InitCatchKind::Reference;
} else {
cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
@@ -341,7 +346,8 @@ static void initCatchParam(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
mlir::Value exnPtr = callBeginCatch(cgf, ehToken, builder.getVoidPtrTy());
CIRGenFunction::AutoVarEmission var = cgf.emitAutoVarAlloca(catchParam);
- cir::InitCatchParamOp::create(builder, cgf.getLoc(loc), exnPtr,
+ mlir::Value initExnSrc = shouldInitFromExnDirectly ? ehToken : exnPtr;
+ cir::InitCatchParamOp::create(builder, cgf.getLoc(loc), initExnSrc,
var.getAllocatedAddress().getPointer(), kind);
cgf.emitAutoVarCleanups(var);
}
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index baec91de9f89c..84f495c568d3d 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -130,7 +130,7 @@ class ItaniumEHLowering : public EHABILowering {
void lowerDispatch(cir::EhDispatchOp dispatch, mlir::Value exnPtr,
mlir::Value typeId,
SmallVectorImpl<mlir::Operation *> &deadOps);
- void lowerInitCatchParam(cir::InitCatchParamOp op);
+ void lowerInitCatchParam(cir::InitCatchParamOp op, EhTokenMap &ehTokenMap);
};
/// Lower all EH operations in the module to the Itanium-specific form.
@@ -265,6 +265,14 @@ mlir::LogicalResult ItaniumEHLowering::lowerFunc(cir::FuncOp funcOp) {
for (cir::EhInitiateOp initiateOp : initiateOps)
lowerEhInitiate(initiateOp, ehTokenMap, deadOps);
+ // Lower any cir.init_catch_param ops in this function. These materialize
+ // the catch parameter local from the (already lowered) begin_catch result,
+ // and are independent of the eh_token graph traversal above.
+ SmallVector<cir::InitCatchParamOp> initCatchOps;
+ funcOp.walk([&](cir::InitCatchParamOp op) { initCatchOps.push_back(op); });
+ for (cir::InitCatchParamOp op : initCatchOps)
+ lowerInitCatchParam(op, ehTokenMap);
+
// Erase operations that were deferred during per-initiate processing
// (dispatch ops whose catch types were read by multiple initiates).
for (mlir::Operation *op : deadOps)
@@ -279,14 +287,6 @@ mlir::LogicalResult ItaniumEHLowering::lowerFunc(cir::FuncOp funcOp) {
}
}
- // Lower any cir.init_catch_param ops in this function. These materialize
- // the catch parameter local from the (already lowered) begin_catch result,
- // and are independent of the eh_token graph traversal above.
- SmallVector<cir::InitCatchParamOp> initCatchOps;
- funcOp.walk([&](cir::InitCatchParamOp op) { initCatchOps.push_back(op); });
- for (cir::InitCatchParamOp op : initCatchOps)
- lowerInitCatchParam(op);
-
return mlir::success();
}
@@ -557,7 +557,8 @@ void ItaniumEHLowering::lowerDispatch(
/// - NonTrivialCopy: copy the exception
/// object's bytes into the alloca via copy constructor.
///
-void ItaniumEHLowering::lowerInitCatchParam(cir::InitCatchParamOp op) {
+void ItaniumEHLowering::lowerInitCatchParam(cir::InitCatchParamOp op,
+ EhTokenMap &ehTokenMap) {
builder.setInsertionPoint(op);
mlir::Location loc = op.getLoc();
mlir::Value exnPtr = op.getExnPtr();
@@ -574,10 +575,19 @@ void ItaniumEHLowering::lowerInitCatchParam(cir::InitCatchParamOp op) {
if (const auto ref = mlir::dyn_cast<cir::PointerType>(elementType)) {
// When catching by reference, generally we should just ignore
// this by-value pointer and use the exception object instead.
- if (auto ptr = mlir::dyn_cast<cir::PointerType>(ref.getPointee()))
- if (!mlir::isa<cir::RecordType>(ptr.getPointee()))
- llvm_unreachable(
- "InitCatchParam: reference of pointer or non-record is NYI");
+ if (auto ptr = mlir::dyn_cast<cir::PointerType>(ref.getPointee())) {
+ if (!mlir::isa<cir::RecordType>(ptr.getPointee())) {
+ auto [exn, typeId] = ehTokenMap.lookup(exnPtr);
+
+ constexpr unsigned headerSize = 32;
+ assert(!MissingFeatures::sizeOfUnwindException());
+
+ auto index = cir::ConstantOp::create(
+ builder, loc, cir::IntAttr::get(u32Type, headerSize));
+ exnPtr =
+ cir::PtrStrideOp::create(builder, loc, exn.getType(), exn, index);
+ }
+ }
}
mlir::Value casted = cir::CastOp::create(builder, loc, elementType,
diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp
index dd9ed9d97b795..c6a191792591f 100644
--- a/clang/test/CIR/CodeGen/try-catch.cpp
+++ b/clang/test/CIR/CodeGen/try-catch.cpp
@@ -1579,7 +1579,7 @@ int init_catch_param_with_type_int_ptr() {
// OGCG: %[[RV_ADDR:.*]] = alloca i32, align 4
// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
-// OGCG: %[[C_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[X_ADDR:.*]] = alloca ptr, align 8
// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
// OGCG: to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]]
// OGCG: [[INVOKE_NORMAL]]:
@@ -1615,3 +1615,149 @@ int init_catch_param_with_type_int_ptr() {
// 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]]
+
+int init_catch_param_with_ref_to_ptr_to_non_record() {
+ int rv = 0;
+ try {
+ division();
+ } catch (int *&p) {
+ rv = *p;
+ }
+ return rv;
+}
+
+// CIR: cir.func {{.*}} @_Z46init_catch_param_with_ref_to_ptr_to_non_recordv() {{.*}} personality(@__gxx_personality_v0)
+// CIR: %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR: %[[RV_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["rv", init]
+// CIR: cir.scope {
+// CIR: %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["p", const]
+// CIR: cir.try {
+// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
+// CIR: cir.yield
+// CIR: } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%[[TOKEN:.*]]: !cir.eh_token {{.*}}) {
+// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+// CIR: cir.cleanup.scope {
+// CIR: cir.init_catch_param reference %[[TOKEN]] to %[[P_ADDR]] : !cir.eh_token, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
+// CIR: %[[TMP_P:.*]] = cir.load %[[P_ADDR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
+// CIR: %[[DEREF_P:.*]] = cir.load deref {{.*}} %[[TMP_P]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR: %[[P_VAL:.*]] = cir.load {{.*}} %[[DEREF_P]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store {{.*}} %[[P_VAL]], %[[RV_ADDR]] : !s32i, !cir.ptr<!s32i>
+// 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: }
+// CIR: %[[TMP_RV:.*]] = cir.load {{.*}} %[[RV_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store %[[TMP_RV]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.return %[[TMP_RET]] : !s32i
+
+// LLVM: define {{.*}} i32 @_Z46init_catch_param_with_ref_to_ptr_to_non_recordv() {{.*}} personality ptr @__gxx_personality_v0
+// LLVM: %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[RV_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: br label %[[TRY_SCOPE:.*]]
+// LLVM: [[TRY_SCOPE]]:
+// LLVM: br label %[[TRY_BEGIN:.*]]
+// LLVM: [[TRY_BEGIN]]:
+// LLVM: %[[CALL:.*]] = invoke noundef 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 @_ZTIPi
+// 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 @_ZTIPi)
+// 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: %[[EXN_PTR:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
+// LLVM: br label %[[CATCH_BODY:.*]]
+// LLVM: [[CATCH_BODY]]:
+// LLVM: %[[EXN_OBJ:.*]] = getelementptr i8, ptr %[[EXN_OBJ_PHI2]], i64 32
+// LLVM: store ptr %[[EXN_OBJ]], ptr %[[P_ADDR]], align 8
+// LLVM: %[[TMP_P:.*]] = load ptr, ptr %[[P_ADDR]], align 8
+// LLVM: %[[DEREF_P:.*]] = load ptr, ptr %[[TMP_P]], align 8
+// LLVM: %[[P_VAL:.*]] = load i32, ptr %[[DEREF_P]], align 4
+// LLVM: store i32 %[[P_VAL]], ptr %[[RV_ADDR]], align 4
+// 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: %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// LLVM: store i32 %[[TMP_RV]], ptr %[[RET_ADDR]], align 4
+// LLVM: %[[TMP_RET:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM: ret i32 %[[TMP_RET]]
+
+// OGCG: define {{.*}} i32 @_Z46init_catch_param_with_ref_to_ptr_to_non_recordv() {{.*}} personality ptr @__gxx_personality_v0
+// OGCG: %[[RV_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[P_ADDR:.*]] = 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 @_ZTIPi
+// 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 %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
+// 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: %[[EXN_OBJ:.*]] = getelementptr i8, ptr %[[TMP_EXCEPTION]], i32 32
+// OGCG: store ptr %[[EXN_OBJ]], ptr %[[P_ADDR]], align 8
+// OGCG: %[[TMP_P:.*]] = load ptr, ptr %[[P_ADDR]], align 8
+// OGCG: %[[DEREF_P:.*]] = load ptr, ptr %[[TMP_P]], align 8
+// OGCG: %[[P_VAL:.*]] = load i32, ptr %[[DEREF_P]], align 4
+// OGCG: store i32 %[[P_VAL]], ptr %[[RV_ADDR]], align 4
+// OGCG: call void @__cxa_end_catch()
+// OGCG: br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG: %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// OGCG: ret i32 %[[TMP_RV]]
+// 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]]
|
andykaylor
left a comment
There was a problem hiding this comment.
I think you're trying to map this too directly onto the classic codegen Itanium handling. The change you're proposing to cir.begin_catch is just a hack to make this work. We want to keep the target-independent abstractions clean and implement things in the correct place during lowering.
In this case, we should be storing the record to the exception variable's alloca during the lowering of cir.construct_catch_param and the cir.init_catch_param will be a noop for this catch type.
Let's hold off on this until I finish landing the cir.construct_catch_param. We'll need to make the copy_fn attribute optional, but otherwise, this should work.
My initial idea was that begin_catch with this change will be used only in itantium, but after you landed |
d4446aa to
d62f9db
Compare
andykaylor
left a comment
There was a problem hiding this comment.
This looks good. I have just a couple of small suggestions.
24174a6 to
7e32692
Compare
…m#195722) Support init reference type of non-record ptr type in InitCatchParam
Support init reference type of non-record ptr type in InitCatchParam