brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.8 KiB · 3758284 Raw
653 lines · cpp
1//===--- CIRGenException.cpp - Emit CIR Code for C++ exceptions -*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This contains code dealing with C++ exception related code generation.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenCXXABI.h"14#include "CIRGenFunction.h"15 16#include "clang/AST/StmtVisitor.h"17#include "clang/CIR/MissingFeatures.h"18#include "llvm/Support/SaveAndRestore.h"19 20using namespace clang;21using namespace clang::CIRGen;22 23const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};24const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",25                                                 nullptr};26const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",27                                                nullptr};28const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",29                                                nullptr};30const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",31                                                    nullptr};32const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = {33    "__gxx_personality_sj0", nullptr};34const EHPersonality EHPersonality::GNU_CPlusPlus_SEH = {35    "__gxx_personality_seh0", nullptr};36const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",37                                               "objc_exception_throw"};38const EHPersonality EHPersonality::GNU_ObjC_SJLJ = {39    "__gnu_objc_personality_sj0", "objc_exception_throw"};40const EHPersonality EHPersonality::GNU_ObjC_SEH = {41    "__gnu_objc_personality_seh0", "objc_exception_throw"};42const EHPersonality EHPersonality::GNU_ObjCXX = {43    "__gnustep_objcxx_personality_v0", nullptr};44const EHPersonality EHPersonality::GNUstep_ObjC = {45    "__gnustep_objc_personality_v0", nullptr};46const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",47                                                          nullptr};48const EHPersonality EHPersonality::MSVC_C_specific_handler = {49    "__C_specific_handler", nullptr};50const EHPersonality EHPersonality::MSVC_CxxFrameHandler3 = {51    "__CxxFrameHandler3", nullptr};52const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = {53    "__gxx_wasm_personality_v0", nullptr};54const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",55                                                   nullptr};56const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",57                                                    nullptr};58 59static const EHPersonality &getCPersonality(const TargetInfo &target,60                                            const CodeGenOptions &cgOpts) {61  const llvm::Triple &triple = target.getTriple();62  if (triple.isWindowsMSVCEnvironment())63    return EHPersonality::MSVC_CxxFrameHandler3;64  if (cgOpts.hasSjLjExceptions())65    return EHPersonality::GNU_C_SJLJ;66  if (cgOpts.hasDWARFExceptions())67    return EHPersonality::GNU_C;68  if (cgOpts.hasSEHExceptions())69    return EHPersonality::GNU_C_SEH;70  return EHPersonality::GNU_C;71}72 73static const EHPersonality &getObjCPersonality(const TargetInfo &target,74                                               const LangOptions &langOpts,75                                               const CodeGenOptions &cgOpts) {76  const llvm::Triple &triple = target.getTriple();77  if (triple.isWindowsMSVCEnvironment())78    return EHPersonality::MSVC_CxxFrameHandler3;79 80  switch (langOpts.ObjCRuntime.getKind()) {81  case ObjCRuntime::FragileMacOSX:82    return getCPersonality(target, cgOpts);83  case ObjCRuntime::MacOSX:84  case ObjCRuntime::iOS:85  case ObjCRuntime::WatchOS:86    return EHPersonality::NeXT_ObjC;87  case ObjCRuntime::GNUstep:88    if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))89      return EHPersonality::GNUstep_ObjC;90    [[fallthrough]];91  case ObjCRuntime::GCC:92  case ObjCRuntime::ObjFW:93    if (cgOpts.hasSjLjExceptions())94      return EHPersonality::GNU_ObjC_SJLJ;95    if (cgOpts.hasSEHExceptions())96      return EHPersonality::GNU_ObjC_SEH;97    return EHPersonality::GNU_ObjC;98  }99  llvm_unreachable("bad runtime kind");100}101 102static const EHPersonality &getCXXPersonality(const TargetInfo &target,103                                              const CodeGenOptions &cgOpts) {104  const llvm::Triple &triple = target.getTriple();105  if (triple.isWindowsMSVCEnvironment())106    return EHPersonality::MSVC_CxxFrameHandler3;107  if (triple.isOSAIX())108    return EHPersonality::XL_CPlusPlus;109  if (cgOpts.hasSjLjExceptions())110    return EHPersonality::GNU_CPlusPlus_SJLJ;111  if (cgOpts.hasDWARFExceptions())112    return EHPersonality::GNU_CPlusPlus;113  if (cgOpts.hasSEHExceptions())114    return EHPersonality::GNU_CPlusPlus_SEH;115  if (cgOpts.hasWasmExceptions())116    return EHPersonality::GNU_Wasm_CPlusPlus;117  return EHPersonality::GNU_CPlusPlus;118}119 120/// Determines the personality function to use when both C++121/// and Objective-C exceptions are being caught.122static const EHPersonality &getObjCXXPersonality(const TargetInfo &target,123                                                 const LangOptions &langOpts,124                                                 const CodeGenOptions &cgOpts) {125  if (target.getTriple().isWindowsMSVCEnvironment())126    return EHPersonality::MSVC_CxxFrameHandler3;127 128  switch (langOpts.ObjCRuntime.getKind()) {129  // In the fragile ABI, just use C++ exception handling and hope130  // they're not doing crazy exception mixing.131  case ObjCRuntime::FragileMacOSX:132    return getCXXPersonality(target, cgOpts);133 134  // The ObjC personality defers to the C++ personality for non-ObjC135  // handlers.  Unlike the C++ case, we use the same personality136  // function on targets using (backend-driven) SJLJ EH.137  case ObjCRuntime::MacOSX:138  case ObjCRuntime::iOS:139  case ObjCRuntime::WatchOS:140    return getObjCPersonality(target, langOpts, cgOpts);141 142  case ObjCRuntime::GNUstep:143    return EHPersonality::GNU_ObjCXX;144 145  // The GCC runtime's personality function inherently doesn't support146  // mixed EH.  Use the ObjC personality just to avoid returning null.147  case ObjCRuntime::GCC:148  case ObjCRuntime::ObjFW:149    return getObjCPersonality(target, langOpts, cgOpts);150  }151  llvm_unreachable("bad runtime kind");152}153 154static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {155  return triple.getArch() == llvm::Triple::x86156             ? EHPersonality::MSVC_except_handler157             : EHPersonality::MSVC_C_specific_handler;158}159 160const EHPersonality &EHPersonality::get(CIRGenModule &cgm,161                                        const FunctionDecl *fd) {162  const llvm::Triple &triple = cgm.getTarget().getTriple();163  const LangOptions &langOpts = cgm.getLangOpts();164  const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();165  const TargetInfo &target = cgm.getTarget();166 167  // Functions using SEH get an SEH personality.168  if (fd && fd->usesSEHTry())169    return getSEHPersonalityMSVC(triple);170 171  if (langOpts.ObjC) {172    return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)173                              : getObjCPersonality(target, langOpts, cgOpts);174  }175  return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)176                            : getCPersonality(target, cgOpts);177}178 179const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) {180  const auto *fg = cgf.curCodeDecl;181  // For outlined finallys and filters, use the SEH personality in case they182  // contain more SEH. This mostly only affects finallys. Filters could183  // hypothetically use gnu statement expressions to sneak in nested SEH.184  fg = fg ? fg : cgf.curSEHParent.getDecl();185  return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));186}187 188void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {189  const llvm::Triple &triple = getTarget().getTriple();190  if (cgm.getLangOpts().OpenMPIsTargetDevice &&191      (triple.isNVPTX() || triple.isAMDGCN())) {192    cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");193    return;194  }195 196  if (const Expr *subExpr = e->getSubExpr()) {197    QualType throwType = subExpr->getType();198    if (throwType->isObjCObjectPointerType()) {199      cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");200      return;201    }202 203    cgm.getCXXABI().emitThrow(*this, e);204    return;205  }206 207  cgm.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);208}209 210void CIRGenFunction::emitAnyExprToExn(const Expr *e, Address addr) {211  // Make sure the exception object is cleaned up if there's an212  // exception during initialization.213  assert(!cir::MissingFeatures::ehCleanupScope());214 215  // __cxa_allocate_exception returns a void*;  we need to cast this216  // to the appropriate type for the object.217  mlir::Type ty = convertTypeForMem(e->getType());218  Address typedAddr = addr.withElementType(builder, ty);219 220  // From LLVM's codegen:221  // FIXME: this isn't quite right!  If there's a final unelided call222  // to a copy constructor, then according to [except.terminate]p1 we223  // must call std::terminate() if that constructor throws, because224  // technically that copy occurs after the exception expression is225  // evaluated but before the exception is caught.  But the best way226  // to handle that is to teach EmitAggExpr to do the final copy227  // differently if it can't be elided.228  emitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),229                   /*isInitializer=*/true);230 231  // Deactivate the cleanup block.232  assert(!cir::MissingFeatures::ehCleanupScope());233}234 235mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {236  if (s.getTryBlock()->body_empty())237    return mlir::LogicalResult::success();238 239  mlir::Location loc = getLoc(s.getSourceRange());240  // Create a scope to hold try local storage for catch params.241 242  mlir::OpBuilder::InsertPoint scopeIP;243  cir::ScopeOp::create(244      builder, loc,245      /*scopeBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {246        scopeIP = builder.saveInsertionPoint();247      });248 249  mlir::OpBuilder::InsertionGuard guard(builder);250  builder.restoreInsertionPoint(scopeIP);251  mlir::LogicalResult result = emitCXXTryStmtUnderScope(s);252  cir::YieldOp::create(builder, loc);253  return result;254}255 256mlir::LogicalResult257CIRGenFunction::emitCXXTryStmtUnderScope(const CXXTryStmt &s) {258  const llvm::Triple &t = getTarget().getTriple();259  // If we encounter a try statement on in an OpenMP target region offloaded to260  // a GPU, we treat it as a basic block.261  const bool isTargetDevice =262      (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));263  if (isTargetDevice) {264    cgm.errorNYI(265        "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");266    return mlir::success();267  }268 269  unsigned numHandlers = s.getNumHandlers();270  mlir::Location tryLoc = getLoc(s.getBeginLoc());271  mlir::OpBuilder::InsertPoint beginInsertTryBody;272 273  bool hasCatchAll = false;274  for (unsigned i = 0; i != numHandlers; ++i) {275    hasCatchAll |= s.getHandler(i)->getExceptionDecl() == nullptr;276    if (hasCatchAll)277      break;278  }279 280  // Create the scope to represent only the C/C++ `try {}` part. However,281  // don't populate right away. Create regions for the catch handlers,282  // but don't emit the handler bodies yet. For now, only make sure the283  // scope returns the exception information.284  auto tryOp = cir::TryOp::create(285      builder, tryLoc,286      /*tryBuilder=*/287      [&](mlir::OpBuilder &b, mlir::Location loc) {288        beginInsertTryBody = builder.saveInsertionPoint();289      },290      /*handlersBuilder=*/291      [&](mlir::OpBuilder &b, mlir::Location loc,292          mlir::OperationState &result) {293        mlir::OpBuilder::InsertionGuard guard(b);294 295        // We create an extra region for an unwind catch handler in case the296        // catch-all handler doesn't exists297        unsigned numRegionsToCreate =298            hasCatchAll ? numHandlers : numHandlers + 1;299 300        for (unsigned i = 0; i != numRegionsToCreate; ++i) {301          mlir::Region *region = result.addRegion();302          builder.createBlock(region);303        }304      });305 306  // Finally emit the body for try/catch.307  {308    mlir::Location loc = tryOp.getLoc();309    mlir::OpBuilder::InsertionGuard guard(builder);310    builder.restoreInsertionPoint(beginInsertTryBody);311    CIRGenFunction::LexicalScope tryScope{*this, loc,312                                          builder.getInsertionBlock()};313 314    tryScope.setAsTry(tryOp);315 316    // Attach the basic blocks for the catch regions.317    enterCXXTryStmt(s, tryOp);318 319    // Emit the body for the `try {}` part.320    {321      mlir::OpBuilder::InsertionGuard guard(builder);322      CIRGenFunction::LexicalScope tryBodyScope{*this, loc,323                                                builder.getInsertionBlock()};324      if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed())325        return mlir::failure();326    }327 328    // Emit catch clauses.329    exitCXXTryStmt(s);330  }331 332  return mlir::success();333}334 335void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,336                                     bool isFnTryBlock) {337  unsigned numHandlers = s.getNumHandlers();338  EHCatchScope *catchScope = ehStack.pushCatch(numHandlers);339  for (unsigned i = 0; i != numHandlers; ++i) {340    const CXXCatchStmt *catchStmt = s.getHandler(i);341    if (catchStmt->getExceptionDecl()) {342      cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl");343      return;344    }345 346    // No exception decl indicates '...', a catch-all.347    mlir::Region *handler = &tryOp.getHandlerRegions()[i];348    catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,349                           s.getHandler(i));350 351    // Under async exceptions, catch(...) needs to catch HW exception too352    // Mark scope with SehTryBegin as a SEH __try scope353    if (getLangOpts().EHAsynch) {354      cgm.errorNYI("enterCXXTryStmt: EHAsynch");355      return;356    }357  }358}359 360void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) {361  unsigned numHandlers = s.getNumHandlers();362  EHCatchScope &catchScope = cast<EHCatchScope>(*ehStack.begin());363  assert(catchScope.getNumHandlers() == numHandlers);364  cir::TryOp tryOp = curLexScope->getTry();365 366  // If the catch was not required, bail out now.367  if (!catchScope.mayThrow()) {368    catchScope.clearHandlerBlocks();369    ehStack.popCatch();370 371    // Drop all basic block from all catch regions.372    SmallVector<mlir::Block *> eraseBlocks;373    for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {374      if (handlerRegion.empty())375        continue;376 377      for (mlir::Block &b : handlerRegion.getBlocks())378        eraseBlocks.push_back(&b);379    }380 381    for (mlir::Block *b : eraseBlocks)382      b->erase();383 384    tryOp.setHandlerTypesAttr({});385    return;386  }387 388  // Copy the handler blocks off before we pop the EH stack.  Emitting389  // the handlers might scribble on this memory.390  SmallVector<EHCatchScope::Handler> handlers(catchScope.begin(),391                                              catchScope.begin() + numHandlers);392 393  ehStack.popCatch();394 395  // Determine if we need an implicit rethrow for all these catch handlers;396  // see the comment below.397  bool doImplicitRethrow =398      isFnTryBlock && isa<CXXDestructorDecl, CXXConstructorDecl>(curCodeDecl);399 400  // Wasm uses Windows-style EH instructions, but merges all catch clauses into401  // one big catchpad. So we save the old funclet pad here before we traverse402  // each catch handler.403  if (EHPersonality::get(*this).isWasmPersonality()) {404    cgm.errorNYI("exitCXXTryStmt: WASM personality");405    return;406  }407 408  bool hasCatchAll = false;409  for (auto &handler : llvm::reverse(handlers)) {410    hasCatchAll |= handler.isCatchAll();411    mlir::Region *catchRegion = handler.region;412    const CXXCatchStmt *catchStmt = handler.stmt;413 414    mlir::OpBuilder::InsertionGuard guard(builder);415    builder.setInsertionPointToStart(&catchRegion->front());416 417    // Enter a cleanup scope, including the catch variable and the418    // end-catch.419    RunCleanupsScope catchScope(*this);420 421    // Initialize the catch variable and set up the cleanups.422    assert(!cir::MissingFeatures::catchParamOp());423 424    // Emit the PGO counter increment.425    assert(!cir::MissingFeatures::incrementProfileCounter());426 427    // Perform the body of the catch.428    [[maybe_unused]] mlir::LogicalResult emitResult =429        emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);430    assert(emitResult.succeeded() && "failed to emit catch handler block");431 432    assert(!cir::MissingFeatures::catchParamOp());433    cir::YieldOp::create(builder, tryOp->getLoc());434 435    // [except.handle]p11:436    //   The currently handled exception is rethrown if control437    //   reaches the end of a handler of the function-try-block of a438    //   constructor or destructor.439 440    // It is important that we only do this on fallthrough and not on441    // return.  Note that it's illegal to put a return in a442    // constructor function-try-block's catch handler (p14), so this443    // really only applies to destructors.444    if (doImplicitRethrow) {445      cgm.errorNYI("exitCXXTryStmt: doImplicitRethrow");446      return;447    }448 449    // Fall out through the catch cleanups.450    catchScope.forceCleanup();451  }452 453  // Because in wasm we merge all catch clauses into one big catchpad, in case454  // none of the types in catch handlers matches after we test against each of455  // them, we should unwind to the next EH enclosing scope. We generate a call456  // to rethrow function here to do that.457  if (EHPersonality::get(*this).isWasmPersonality() && !hasCatchAll) {458    cgm.errorNYI("exitCXXTryStmt: WASM personality without catch all");459  }460 461  assert(!cir::MissingFeatures::incrementProfileCounter());462}463 464void CIRGenFunction::populateCatchHandlers(cir::TryOp tryOp) {465  assert(ehStack.requiresCatchOrCleanup());466  assert(!cgm.getLangOpts().IgnoreExceptions &&467         "LandingPad should not be emitted when -fignore-exceptions are in "468         "effect.");469 470  EHScope &innermostEHScope = *ehStack.find(ehStack.getInnermostEHScope());471  switch (innermostEHScope.getKind()) {472  case EHScope::Terminate:473    cgm.errorNYI("populateCatchHandlers: terminate");474    return;475 476  case EHScope::Catch:477  case EHScope::Cleanup:478  case EHScope::Filter:479    // CIR does not cache landing pads.480    break;481  }482 483  // If there's an existing TryOp, it means we got a `cir.try` scope484  // that leads to this "landing pad" creation site. Otherwise, exceptions485  // are enabled but a throwing function is called anyways (common pattern486  // with function local static initializers).487  mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();488  if (!handlerTypesAttr || handlerTypesAttr.empty()) {489    // Accumulate all the handlers in scope.490    bool hasCatchAll = false;491    llvm::SmallVector<mlir::Attribute, 4> handlerAttrs;492    for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e;493         ++i) {494      switch (i->getKind()) {495      case EHScope::Cleanup:496        cgm.errorNYI("emitLandingPad: Cleanup");497        return;498 499      case EHScope::Filter:500        cgm.errorNYI("emitLandingPad: Filter");501        return;502 503      case EHScope::Terminate:504        cgm.errorNYI("emitLandingPad: Terminate");505        return;506 507      case EHScope::Catch:508        break;509      } // end switch510 511      EHCatchScope &catchScope = cast<EHCatchScope>(*i);512      for (const EHCatchScope::Handler &handler :513           llvm::make_range(catchScope.begin(), catchScope.end())) {514        assert(handler.type.flags == 0 &&515               "landingpads do not support catch handler flags");516 517        // If this is a catch-all, register that and abort.518        if (handler.isCatchAll()) {519          assert(!hasCatchAll);520          hasCatchAll = true;521          break;522        }523 524        cgm.errorNYI("emitLandingPad: non catch-all");525        return;526      }527 528      if (hasCatchAll)529        break;530    }531 532    if (hasCatchAll) {533      handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));534    } else {535      cgm.errorNYI("emitLandingPad: non catch-all");536      return;537    }538 539    // Add final array of clauses into TryOp.540    tryOp.setHandlerTypesAttr(541        mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));542  }543 544  // In traditional LLVM codegen. this tells the backend how to generate the545  // landing pad by generating a branch to the dispatch block. In CIR,546  // this is used to populate blocks for later filing during547  // cleanup handling.548  populateEHCatchRegions(ehStack.getInnermostEHScope(), tryOp);549}550 551// Differently from LLVM traditional codegen, there are no dispatch blocks552// to look at given cir.try_call does not jump to blocks like invoke does.553// However.554void CIRGenFunction::populateEHCatchRegions(EHScopeStack::stable_iterator scope,555                                            cir::TryOp tryOp) {556  if (EHPersonality::get(*this).usesFuncletPads()) {557    cgm.errorNYI("getEHDispatchBlock: usesFuncletPads");558    return;559  }560 561  // Otherwise, we should look at the actual scope.562  EHScope &ehScope = *ehStack.find(scope);563  bool mayThrow = ehScope.mayThrow();564 565  mlir::Block *originalBlock = nullptr;566  if (mayThrow && tryOp) {567    // If the dispatch is cached but comes from a different tryOp, make sure:568    // - Populate current `tryOp` with a new dispatch block regardless.569    // - Update the map to enqueue new dispatchBlock to also get a cleanup. See570    // code at the end of the function.571    cgm.errorNYI("getEHDispatchBlock: mayThrow & tryOp");572    return;573  }574 575  if (!mayThrow) {576    switch (ehScope.getKind()) {577    case EHScope::Catch: {578      // LLVM does some optimization with branches here, CIR just keep track of579      // the corresponding calls.580      EHCatchScope &catchScope = cast<EHCatchScope>(ehScope);581      if (catchScope.getNumHandlers() == 1 &&582          catchScope.getHandler(0).isCatchAll()) {583        mayThrow = true;584        break;585      }586      cgm.errorNYI("getEHDispatchBlock: mayThrow non-catch all");587      return;588    }589    case EHScope::Cleanup: {590      cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup");591      return;592    }593    case EHScope::Filter: {594      cgm.errorNYI("getEHDispatchBlock: mayThrow & Filter");595      return;596    }597    case EHScope::Terminate: {598      cgm.errorNYI("getEHDispatchBlock: mayThrow & Terminate");599      return;600    }601    }602  }603 604  if (originalBlock) {605    cgm.errorNYI("getEHDispatchBlock: originalBlock");606    return;607  }608 609  ehScope.setMayThrow(mayThrow);610}611 612// in classic codegen this function is mapping to `isInvokeDest` previously and613// currently it's mapping to the conditions that performs early returns in614// `getInvokeDestImpl`, in CIR we need the condition to know if the EH scope may615// throw exception or now.616bool CIRGenFunction::isCatchOrCleanupRequired() {617  // If exceptions are disabled/ignored and SEH is not in use, then there is no618  // invoke destination. SEH "works" even if exceptions are off. In practice,619  // this means that C++ destructors and other EH cleanups don't run, which is620  // consistent with MSVC's behavior, except in the presence of -EHa621  const LangOptions &lo = cgm.getLangOpts();622  if (!lo.Exceptions || lo.IgnoreExceptions) {623    if (!lo.Borland && !lo.MicrosoftExt)624      return false;625    cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");626    return false;627  }628 629  // CUDA device code doesn't have exceptions.630  if (lo.CUDA && lo.CUDAIsDevice)631    return false;632 633  return ehStack.requiresCatchOrCleanup();634}635 636// In classic codegen this function is equivalent to `getInvokeDestImpl`, in637// ClangIR we don't need to return to return any landing pad, we just need to638// populate the catch handlers if they are required639void CIRGenFunction::populateCatchHandlersIfRequired(cir::TryOp tryOp) {640  assert(ehStack.requiresCatchOrCleanup());641  assert(!ehStack.empty());642 643  assert(!cir::MissingFeatures::setFunctionPersonality());644 645  // CIR does not cache landing pads.646  const EHPersonality &personality = EHPersonality::get(*this);647  if (personality.usesFuncletPads()) {648    cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");649  } else {650    populateCatchHandlers(tryOp);651  }652}653