Skip to content

Commit 481118d

Browse files
[CIR][CodeGen] Implement tryMarkNoThrow and update wrong test (#1664)
This PR introduces [`TryMarkNoThrow`](https://github.com/llvm/clangir/blob/6e5fa09550c98f84d017873ed3e5667fd5fd909c/clang/lib/CodeGen/CodeGenFunction.cpp#L1394). [`isInterposable`](https://github.com/llvm/clangir/blob/6e5fa09550c98f84d017873ed3e5667fd5fd909c/clang/lib/CodeGen/CodeGenFunction.cpp#L1397C10-L1397C26) isn't fully implemented and I'm not quite sure we need it? Anyway, I have introduced a missing feature `getSemanticInterposition` relevant for its completion. I have also updated an old test -- [`foo()`](https://github.com/llvm/clangir/blob/6e5fa09550c98f84d017873ed3e5667fd5fd909c/clang/test/CIR/CodeGen/try-catch-dtors.cpp#L313) should be marked as unwind/nothrow. I have compared with the original CodeGen and attached the llvm output for verification. One concern I have is if the cases I have to mimic [`mayThrow`](https://github.com/llvm/clangir/blob/6e5fa09550c98f84d017873ed3e5667fd5fd909c/llvm/lib/IR/Instruction.cpp#L1158) from the OG are enough, please let me know your thoughts.
1 parent 2afbab5 commit 481118d

File tree

7 files changed

+46
-16
lines changed

7 files changed

+46
-16
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ struct MissingFeatures {
239239
static bool emitScalarRangeCheck() { return false; }
240240
static bool stmtExprEvaluation() { return false; }
241241
static bool setCallingConv() { return false; }
242-
static bool tryMarkNoThrow() { return false; }
243242
static bool indirectBranch() { return false; }
244243
static bool escapedLocals() { return false; }
245244
static bool deferredReplacements() { return false; }
@@ -251,6 +250,7 @@ struct MissingFeatures {
251250
static bool createLaunderInvariantGroup() { return false; }
252251
static bool hipModuleCtor() { return false; }
253252
static bool checkMacOSXTriple() { return false; }
253+
static bool getSemanticInterposition() { return false; }
254254

255255
// Inline assembly
256256
static bool asmGoto() { return false; }

clang/lib/CIR/CodeGen/CIRGenCall.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ emitCallLikeOp(CIRGenFunction &CGF, mlir::Location callLoc,
381381
callLoc, directFuncOp, CIRCallArgs, callingConv, sideEffect);
382382
}
383383
callOpWithExceptions->setAttr("extra_attrs", extraFnAttrs);
384+
CGF.mayThrow = true;
384385

385386
CGF.callWithExceptionCtx = callOpWithExceptions;
386387
auto *invokeDest = CGF.getInvokeDest(tryOp);

clang/lib/CIR/CodeGen/CIRGenException.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ void CIRGenFunction::emitEHResumeBlock(bool isCleanup,
280280

281281
getBuilder().create<cir::ResumeOp>(loc, mlir::Value{}, mlir::Value{});
282282
getBuilder().restoreInsertionPoint(ip);
283+
mayThrow = true;
283284
}
284285

285286
mlir::Block *CIRGenFunction::getEHResumeBlock(bool isCleanup,

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,28 @@ static void eraseEmptyAndUnusedBlocks(cir::FuncOp fnOp) {
633633
b->erase();
634634
}
635635

636+
static bool isInterposable(cir::FuncOp fn) {
637+
if (isInterposableLinkage(fn.getLinkage()))
638+
return true;
639+
640+
assert(!cir::MissingFeatures::getSemanticInterposition());
641+
642+
return false;
643+
}
644+
645+
static void tryMarkNoThrow(CIRGenFunction &cgf, cir::FuncOp fn) {
646+
// LLVM treats 'nounwind' on a function as part of the type, so we
647+
// can't do this on functions that can be overwritten.
648+
if (isInterposable(fn) || cgf.mayThrow)
649+
return;
650+
651+
mlir::NamedAttrList extraAttrs{fn.getExtraAttrs().getElements().getValue()};
652+
auto noThrowAttr = cir::NoThrowAttr::get(&cgf.getMLIRContext());
653+
extraAttrs.set(noThrowAttr.getMnemonic(), noThrowAttr);
654+
fn.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
655+
extraAttrs.getDictionary(&cgf.getMLIRContext())));
656+
}
657+
636658
cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
637659
const CIRGenFunctionInfo &fnInfo) {
638660
assert(fn && "generating code for a null function");
@@ -779,7 +801,7 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
779801

780802
// If we haven't marked the function nothrow through other means, do a quick
781803
// pass now to see if we can.
782-
assert(!cir::MissingFeatures::tryMarkNoThrow());
804+
tryMarkNoThrow(*this, fn);
783805
}
784806

785807
eraseEmptyAndUnusedBlocks(fn);

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,10 @@ class CIRGenFunction : public CIRGenTypeCache {
512512
/// the constructor, but could be overwrriten to true if this is a coroutine.
513513
bool ShouldEmitLifetimeMarkers;
514514

515+
/// True if there are any operations in the body of the function that are
516+
/// likely to throw an exception.
517+
bool mayThrow = false;
518+
515519
using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
516520
/// This keeps track of the CIR allocas or globals for local C
517521
/// delcs.

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,7 @@ void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &CGF, bool isNoReturn) {
23032303
auto loc = *CGF.currSrcLoc;
23042304
insertThrowAndSplit(builder, loc, mlir::Value{}, mlir::FlatSymbolRefAttr{},
23052305
mlir::FlatSymbolRefAttr{});
2306+
CGF.mayThrow = true;
23062307
} else {
23072308
llvm_unreachable("NYI");
23082309
}
@@ -2369,6 +2370,8 @@ void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &CGF,
23692370
// Now throw the exception.
23702371
mlir::Location loc = CGF.getLoc(E->getSourceRange());
23712372
insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol(), dtor);
2373+
2374+
CGF.mayThrow = true;
23722375
}
23732376

23742377
mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(

clang/test/CIR/CodeGen/try-catch-dtors.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -324,22 +324,21 @@ void bar() {
324324
// CIR-LABEL: @_Z3barv
325325
// CIR: %[[V0:.*]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["a"] {alignment = 1 : i64}
326326
// CIR: %[[V1:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init] {alignment = 4 : i64}
327-
// CIR: %[[V2:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["tmp.try.call.res"] {alignment = 4 : i64}
328-
// CIR: cir.try synthetic cleanup {
329-
// CIR: %[[V4:.*]] = cir.call exception @_Z3foov() : () -> !s32i cleanup {
330-
// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr<!rec_A>) -> () extra(#fn_attr)
331-
// CIR: cir.yield
332-
// CIR: }
333-
// CIR: cir.store{{.*}} %[[V4]], %[[V2]] : !s32i, !cir.ptr<!s32i>
334-
// CIR: cir.yield
335-
// CIR: } catch [#cir.unwind {
336-
// CIR: cir.resume
337-
// CIR: }]
338-
// CIR: %[[V3:.*]] = cir.load{{.*}} %[[V2]] : !cir.ptr<!s32i>, !s32i
339-
// CIR: cir.store{{.*}} %[[V3]], %[[V1]] : !s32i, !cir.ptr<!s32i>
340-
// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr<!rec_A>) -> () extra(#fn_attr)
327+
// CIR: %[[V2:.*]] = cir.call @_Z3foov() : () -> !s32i
328+
// CIR: cir.store align(4) %[[V2]], %[[V1]] : !s32i, !cir.ptr<!s32i>
329+
// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr<!rec_A>) -> ()
341330
// CIR: cir.return
342331

332+
// LLVM: ; Function Attrs: noinline nounwind optnone
333+
// LLVM-NEXT: _Z3foo
334+
// LLVM: @_Z3barv()
335+
// LLVM: %[[V1:.*]] = alloca %struct.A, i64 1, align 1
336+
// LLVM: %[[V2:.*]] = alloca i32, i64 1, align 4
337+
// LLVM: %[[V3:.*]] = call i32 @_Z3foov()
338+
// LLVM: store i32 %[[V3]], ptr %[[V2]], align 4
339+
// LLVM: call void @_ZN1AD2Ev(ptr %[[V1]])
340+
// LLVM: ret void
341+
343342
class C {
344343
public:
345344
~C();

0 commit comments

Comments
 (0)