Skip to content

Commit

Permalink
[CIR][CIRGen][Exceptions] Prep work for using cir.try_call outside ci…
Browse files Browse the repository at this point in the history
…r.try

The final destination here is to support cir.try_calls that are not within a
`try {}` statement in C++.  This only affect untested paths that will
assert a bit later than before, testcase coming soon.
  • Loading branch information
bcardosolopes committed Feb 13, 2024
1 parent d39eb48 commit a2b7b65
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 10 deletions.
54 changes: 53 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/SaveAndRestore.h"

#include "CIRGenCleanup.h"
#include "CIRGenFunction.h"

Expand Down Expand Up @@ -159,6 +161,7 @@ void CIRGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
auto *EHEntry = Scope.getCachedEHDispatchBlock();
assert(Scope.hasEHBranches() == (EHEntry != nullptr));
bool RequiresEHCleanup = (EHEntry != nullptr);
EHScopeStack::stable_iterator EHParent = Scope.getEnclosingEHScope();

// Check the three conditions which might require a normal cleanup:

Expand Down Expand Up @@ -270,7 +273,50 @@ void CIRGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {

// Emit the EH cleanup if required.
if (RequiresEHCleanup) {
llvm_unreachable("NYI");
// FIXME(cir): should we guard insertion point here?
auto *NextAction = getEHDispatchBlock(EHParent);
(void)NextAction;

// Push a terminate scope or cleanupendpad scope around the potentially
// throwing cleanups. For funclet EH personalities, the cleanupendpad models
// program termination when cleanups throw.
bool PushedTerminate = false;
SaveAndRestore RestoreCurrentFuncletPad(CurrentFuncletPad);
mlir::Operation *CPI = nullptr;

const EHPersonality &Personality = EHPersonality::get(*this);
if (Personality.usesFuncletPads()) {
llvm_unreachable("NYI");
}

// Non-MSVC personalities need to terminate when an EH cleanup throws.
if (!Personality.isMSVCPersonality()) {
EHStack.pushTerminate();
PushedTerminate = true;
} else if (IsEHa && getInvokeDest()) {
llvm_unreachable("NYI");
}

// We only actually emit the cleanup code if the cleanup is either
// active or was used before it was deactivated.
if (EHActiveFlag.isValid() || IsActive) {
cleanupFlags.setIsForEHCleanup();
buildCleanup(*this, Fn, cleanupFlags, EHActiveFlag);
}

// In LLVM traditional codegen, here's where it branches off to
// NextAction.
if (CPI)
llvm_unreachable("NYI");

// Leave the terminate scope.
if (PushedTerminate)
EHStack.popTerminate();

// FIXME(cir): LLVM traditional codegen tries to simplify some of the
// codegen here. Once we are further down with EH support revisit whether we
// need to this during lowering.
assert(!UnimplementedFeature::simplifyCleanupEntry());
}
}

Expand Down Expand Up @@ -470,3 +516,9 @@ EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) {
InnermostEHScope = stable_begin();
return scope;
}

void EHScopeStack::pushTerminate() {
char *Buffer = allocate(EHTerminateScope::getSize());
new (Buffer) EHTerminateScope(InnermostEHScope);
InnermostEHScope = stable_begin();
}
47 changes: 42 additions & 5 deletions clang/lib/CIR/CodeGen/CIRGenException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ mlir::Operation *CIRGenFunction::buildLandingPad() {
EHScope &innermostEHScope = *EHStack.find(EHStack.getInnermostEHScope());
switch (innermostEHScope.getKind()) {
case EHScope::Terminate:
llvm_unreachable("NYI");
return getTerminateLandingPad();

case EHScope::Catch:
case EHScope::Cleanup:
Expand All @@ -635,7 +635,38 @@ mlir::Operation *CIRGenFunction::buildLandingPad() {
// are enabled but a throwing function is called anyways.
auto catchOp = currLexScope->getExceptionInfo().catchOp;
if (!catchOp) {
llvm_unreachable("NYI");
auto loc = *currSrcLoc;
auto ehPtrTy = mlir::cir::PointerType::get(
getBuilder().getContext(),
getBuilder().getType<::mlir::cir::ExceptionInfoType>());

mlir::Value exceptionAddr;
{
// Get a new alloca within the current scope.
mlir::OpBuilder::InsertionGuard guard(builder);
exceptionAddr = buildAlloca(
"__exception_ptr", ehPtrTy, loc, CharUnits::One(),
builder.getBestAllocaInsertPoint(builder.getInsertionBlock()));
}

{
// Insert catch at the end of the block, and place the insert pointer
// back to where it was.
mlir::OpBuilder::InsertionGuard guard(builder);
auto exceptionPtr =
builder.create<mlir::cir::LoadOp>(loc, ehPtrTy, exceptionAddr);
catchOp = builder.create<mlir::cir::CatchOp>(
loc, exceptionPtr,
[&](mlir::OpBuilder &b, mlir::Location loc,
mlir::OperationState &result) {
// There's no source code level catch here, create one region for
// the resume block.
mlir::OpBuilder::InsertionGuard guard(b);
auto *r = result.addRegion();
builder.createBlock(r);
});
}
currLexScope->setExceptionInfo({exceptionAddr, catchOp});
}

{
Expand All @@ -660,7 +691,7 @@ mlir::Operation *CIRGenFunction::buildLandingPad() {
switch (I->getKind()) {
case EHScope::Cleanup:
// If we have a cleanup, remember that.
llvm_unreachable("NYI");
hasCleanup = (hasCleanup || cast<EHCleanupScope>(*I).isEHCleanup());
continue;

case EHScope::Filter: {
Expand Down Expand Up @@ -717,7 +748,8 @@ mlir::Operation *CIRGenFunction::buildLandingPad() {

// Otherwise, signal that we at least have cleanups.
} else if (hasCleanup) {
llvm_unreachable("NYI");
// FIXME(cir): figure out whether and how we need this in CIR.
assert(!UnimplementedFeature::setLandingPadCleanup());
}

assert((clauses.size() > 0 || hasCleanup) && "CatchOp has no clauses!");
Expand Down Expand Up @@ -782,7 +814,8 @@ CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
}

case EHScope::Cleanup:
llvm_unreachable("NYI");
assert(!UnimplementedFeature::setLandingPadCleanup());
dispatchBlock = currLexScope->getOrCreateCleanupBlock(builder);
break;

case EHScope::Filter:
Expand Down Expand Up @@ -850,3 +883,7 @@ mlir::Operation *CIRGenFunction::getInvokeDestImpl() {

return LP;
}

mlir::Operation *CIRGenFunction::getTerminateLandingPad() {
llvm_unreachable("NYI");
}
3 changes: 3 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,9 @@ class CIRGenFunction : public CIRGenTypeCache {
return false;
}

/// Return a landing pad that just calls terminate.
mlir::Operation *getTerminateLandingPad();

/// Emit code to compute the specified expression,
/// ignoring the result.
void buildIgnoredExpr(const clang::Expr *E);
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/CIR/CodeGen/UnimplementedFeatureGuarding.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ struct UnimplementedFeature {
static bool variablyModifiedTypeEmission() { return false; }
static bool buildLValueAlignmentAssumption() { return false; }
static bool buildDerivedToBaseCastForDevirt() { return false; }
static bool emitStartEHSpec() { return false; }
static bool emitEndEHSpec() { return false; }
static bool emitFunctionEpilog() { return false; }

// Data layout
Expand Down Expand Up @@ -110,6 +108,14 @@ struct UnimplementedFeature {
static bool fastMathFlags() { return false; }
static bool fastMathFuncAttributes() { return false; }

// Exception handling
static bool setLandingPadCleanup() { return false; }
static bool isSEHTryScope() { return false; }
static bool ehStack() { return false; }
static bool emitStartEHSpec() { return false; }
static bool emitEndEHSpec() { return false; }
static bool simplifyCleanupEntry() { return false; }

// Type qualifiers.
static bool atomicTypes() { return false; }
static bool volatileTypes() { return false; }
Expand All @@ -128,7 +134,6 @@ struct UnimplementedFeature {
static bool openMP() { return false; }
static bool openMPRuntime() { return false; }
static bool openMPTarget() { return false; }
static bool ehStack() { return false; }
static bool isVarArg() { return false; }
static bool setNonGC() { return false; }
static bool volatileLoadOrStore() { return false; }
Expand All @@ -151,7 +156,6 @@ struct UnimplementedFeature {
static bool exceptions() { return false; }
static bool metaDataNode() { return false; }
static bool emitDeclMetadata() { return false; }
static bool isSEHTryScope() { return false; }
static bool emitScalarRangeCheck() { return false; }
static bool stmtExprEvaluation() { return false; }
static bool setCallingConv() { return false; }
Expand Down

0 comments on commit a2b7b65

Please sign in to comment.