clang: lib/CIR/CodeGen/CIRGenException.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

15

18#include "llvm/Support/SaveAndRestore.h"

19

20using namespace clang;

22

25 nullptr};

27 nullptr};

29 nullptr};

31 nullptr};

33 "__gxx_personality_sj0", nullptr};

35 "__gxx_personality_seh0", nullptr};

37 "objc_exception_throw"};

39 "__gnu_objc_personality_sj0", "objc_exception_throw"};

41 "__gnu_objc_personality_seh0", "objc_exception_throw"};

43 "__gnustep_objcxx_personality_v0", nullptr};

45 "__gnustep_objc_personality_v0", nullptr};

47 nullptr};

49 "__C_specific_handler", nullptr};

51 "__CxxFrameHandler3", nullptr};

53 "__gxx_wasm_personality_v0", nullptr};

55 nullptr};

57 nullptr};

58

61 const llvm::Triple &triple = target.getTriple();

62 if (triple.isWindowsMSVCEnvironment())

71}

72

76 const llvm::Triple &triple = target.getTriple();

77 if (triple.isWindowsMSVCEnvironment())

79

90 [[fallthrough]];

98 }

99 llvm_unreachable("bad runtime kind");

100}

101

104 const llvm::Triple &triple = target.getTriple();

105 if (triple.isWindowsMSVCEnvironment())

107 if (triple.isOSAIX())

118}

119

120

121

125 if (target.getTriple().isWindowsMSVCEnvironment())

127

129

130

133

134

135

136

141

144

145

146

150 }

151 llvm_unreachable("bad runtime kind");

152}

153

155 return triple.getArch() == llvm::Triple::x86

158}

159

166

167

170

171 if (langOpts.ObjC) {

174 }

177}

178

181

182

183

185 return get(cgf.cgm, dyn_cast_or_null(fg));

186}

187

190

191 mlir::Type i32Ty = cgm.getBuilder().getI32Type();

192 auto funcTy = cir::FuncType::get({}, i32Ty, true);

193

195 funcTy, personality.personalityFn, mlir::ArrayAttr(), true);

196

197 return personalityFn.getSymName();

198}

199

202 if (cgm.getLangOpts().OpenMPIsTargetDevice &&

203 (triple.isNVPTX() || triple.isAMDGCN())) {

204 cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");

205 return;

206 }

207

209 QualType throwType = subExpr->getType();

211 cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");

212 return;

213 }

214

215 cgm.getCXXABI().emitThrow(*this, e);

216 return;

217 }

218

219 cgm.getCXXABI().emitRethrow(*this, true);

220}

221

223

224

226

227

228

231

232

233

234

235

236

237

238

239

241 true);

242

243

245}

246

248 if (s.getTryBlock()->body_empty())

249 return mlir::LogicalResult::success();

250

251 mlir::Location loc = getLoc(s.getSourceRange());

252

253

254 mlir::OpBuilder::InsertPoint scopeIP;

255 cir::ScopeOp::create(

256 builder, loc,

257 [&](mlir::OpBuilder &b, mlir::Location loc) {

258 scopeIP = builder.saveInsertionPoint();

259 });

260

261 mlir::OpBuilder::InsertionGuard guard(builder);

262 builder.restoreInsertionPoint(scopeIP);

264 cir::YieldOp::create(builder, loc);

265 return result;

266}

267

268mlir::LogicalResult

271

272

273 const bool isTargetDevice =

274 (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));

275 if (isTargetDevice) {

276 cgm.errorNYI(

277 "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");

278 return mlir::success();

279 }

280

281 unsigned numHandlers = s.getNumHandlers();

282 mlir::Location tryLoc = getLoc(s.getBeginLoc());

283 mlir::OpBuilder::InsertPoint beginInsertTryBody;

284

285 bool hasCatchAll = false;

286 for (unsigned i = 0; i != numHandlers; ++i) {

287 hasCatchAll |= s.getHandler(i)->getExceptionDecl() == nullptr;

288 if (hasCatchAll)

289 break;

290 }

291

292

293

294

295

296 auto tryOp = cir::TryOp::create(

297 builder, tryLoc,

298

299 [&](mlir::OpBuilder &b, mlir::Location loc) {

300 beginInsertTryBody = builder.saveInsertionPoint();

301 },

302

303 [&](mlir::OpBuilder &b, mlir::Location loc,

304 mlir::OperationState &result) {

305 mlir::OpBuilder::InsertionGuard guard(b);

306

307

308

309 unsigned numRegionsToCreate =

310 hasCatchAll ? numHandlers : numHandlers + 1;

311

312 for (unsigned i = 0; i != numRegionsToCreate; ++i) {

313 mlir::Region *region = result.addRegion();

314 builder.createBlock(region);

315 }

316 });

317

318

319 {

320 mlir::Location loc = tryOp.getLoc();

321 mlir::OpBuilder::InsertionGuard guard(builder);

322 builder.restoreInsertionPoint(beginInsertTryBody);

324 builder.getInsertionBlock()};

325

327

328

330

331

332 {

333 mlir::OpBuilder::InsertionGuard guard(builder);

335 builder.getInsertionBlock()};

336 if (emitStmt(s.getTryBlock(), true).failed())

337 return mlir::failure();

338 }

339

340

342 }

343

344 return mlir::success();

345}

346

348 bool isFnTryBlock) {

349 unsigned numHandlers = s.getNumHandlers();

351 for (unsigned i = 0; i != numHandlers; ++i) {

354 cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl");

355 return;

356 }

357

358

359 mlir::Region *handler = &tryOp.getHandlerRegions()[i];

360 catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,

361 s.getHandler(i));

362

363

364

366 cgm.errorNYI("enterCXXTryStmt: EHAsynch");

367 return;

368 }

369 }

370}

371

373 unsigned numHandlers = s.getNumHandlers();

376 cir::TryOp tryOp = curLexScope->getTry();

377

378

379 if (!catchScope.mayThrow()) {

382

383

385 for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {

386 if (handlerRegion.empty())

387 continue;

388

389 for (mlir::Block &b : handlerRegion.getBlocks())

390 eraseBlocks.push_back(&b);

391 }

392

393 for (mlir::Block *b : eraseBlocks)

394 b->erase();

395

396 tryOp.setHandlerTypesAttr({});

397 return;

398 }

399

400

401

403 catchScope.begin() + numHandlers);

404

406

407

408

409 bool doImplicitRethrow =

411

412

413

414

416 cgm.errorNYI("exitCXXTryStmt: WASM personality");

417 return;

418 }

419

420 bool hasCatchAll = false;

421 for (auto &handler : llvm::reverse(handlers)) {

422 hasCatchAll |= handler.isCatchAll();

423 mlir::Region *catchRegion = handler.region;

424 const CXXCatchStmt *catchStmt = handler.stmt;

425

426 mlir::OpBuilder::InsertionGuard guard(builder);

427 builder.setInsertionPointToStart(&catchRegion->front());

428

429

430

432

433

435 cgm.getCXXABI().emitBeginCatch(*this, catchStmt);

436

437

439

440

441 [[maybe_unused]] mlir::LogicalResult emitResult =

443 assert(emitResult.succeeded() && "failed to emit catch handler block");

444

446 cir::YieldOp::create(builder, tryOp->getLoc());

447

448

449

450

451

452

453

454

455

456

457 if (doImplicitRethrow) {

458 cgm.errorNYI("exitCXXTryStmt: doImplicitRethrow");

459 return;

460 }

461

462

464 }

465

466

467

468

469

471 cgm.errorNYI("exitCXXTryStmt: WASM personality without catch all");

472 }

473

475}

476

478 assert(ehStack.requiresCatchOrCleanup());

479 assert(cgm.getLangOpts().IgnoreExceptions &&

480 "LandingPad should not be emitted when -fignore-exceptions are in "

481 "effect.");

482

484 switch (innermostEHScope.getKind()) {

486 cgm.errorNYI("populateCatchHandlers: terminate");

487 return;

488

492

493 break;

494 }

495

496

497

498

499

500 mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();

501 if (!handlerTypesAttr || handlerTypesAttr.empty()) {

502

503 bool hasCatchAll = false;

506 ++i) {

507 switch (i->getKind()) {

509 cgm.errorNYI("emitLandingPad: Cleanup");

510 return;

511

513 cgm.errorNYI("emitLandingPad: Filter");

514 return;

515

517 cgm.errorNYI("emitLandingPad: Terminate");

518 return;

519

521 break;

522 }

523

526 llvm::make_range(catchScope.begin(), catchScope.end())) {

527 assert(handler.type.flags == 0 &&

528 "landingpads do not support catch handler flags");

529

530

531 if (handler.isCatchAll()) {

532 assert(!hasCatchAll);

533 hasCatchAll = true;

534 break;

535 }

536

537 cgm.errorNYI("emitLandingPad: non catch-all");

538 return;

539 }

540

541 if (hasCatchAll)

542 break;

543 }

544

545 if (hasCatchAll) {

546 handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));

547 } else {

548 cgm.errorNYI("emitLandingPad: non catch-all");

549 return;

550 }

551

552

553 tryOp.setHandlerTypesAttr(

554 mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));

555 }

556

557

558

559

560

562}

563

564

565

566

568 cir::TryOp tryOp) {

570 cgm.errorNYI("getEHDispatchBlock: usesFuncletPads");

571 return;

572 }

573

574

576 bool mayThrow = ehScope.mayThrow();

577

578 mlir::Block *originalBlock = nullptr;

579 if (mayThrow && tryOp) {

580

581

582

583

584 cgm.errorNYI("getEHDispatchBlock: mayThrow & tryOp");

585 return;

586 }

587

588 if (!mayThrow) {

589 switch (ehScope.getKind()) {

591

592

596 mayThrow = true;

597 break;

598 }

599 cgm.errorNYI("getEHDispatchBlock: mayThrow non-catch all");

600 return;

601 }

603 cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup");

604 return;

605 }

607 cgm.errorNYI("getEHDispatchBlock: mayThrow & Filter");

608 return;

609 }

611 cgm.errorNYI("getEHDispatchBlock: mayThrow & Terminate");

612 return;

613 }

614 }

615 }

616

617 if (originalBlock) {

618 cgm.errorNYI("getEHDispatchBlock: originalBlock");

619 return;

620 }

621

623}

624

625

626

627

628

630

631

632

633

635 if (!lo.Exceptions || lo.IgnoreExceptions) {

636 if (!lo.Borland && !lo.MicrosoftExt)

637 return false;

638 cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");

639 return false;

640 }

641

642

643 if (lo.CUDA && lo.CUDAIsDevice)

644 return false;

645

646 return ehStack.requiresCatchOrCleanup();

647}

648

649

650

651

653 assert(ehStack.requiresCatchOrCleanup());

654 assert(ehStack.empty());

655

657

658

659 auto funcOp = mlir::castcir::FuncOp(curFn);

660 if (!funcOp.getPersonality())

662

663

665 cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");

666 } else {

668 }

669}

static const EHPersonality & getCXXPersonality(const TargetInfo &target, const CodeGenOptions &cgOpts)

Definition CIRGenException.cpp:102

static const EHPersonality & getCPersonality(const TargetInfo &target, const CodeGenOptions &cgOpts)

Definition CIRGenException.cpp:59

static const EHPersonality & getObjCPersonality(const TargetInfo &target, const LangOptions &langOpts, const CodeGenOptions &cgOpts)

Definition CIRGenException.cpp:73

static llvm::StringRef getPersonalityFn(CIRGenModule &cgm, const EHPersonality &personality)

Definition CIRGenException.cpp:188

static const EHPersonality & getObjCXXPersonality(const TargetInfo &target, const LangOptions &langOpts, const CodeGenOptions &cgOpts)

Determines the personality function to use when both C++ and Objective-C exceptions are being caught.

Definition CIRGenException.cpp:122

static const EHPersonality & getSEHPersonalityMSVC(const llvm::Triple &triple)

Definition CIRGenException.cpp:154

__device__ __2f16 float __ockl_bool s

Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const

Return address with different element type, a bitcast pointer, and the same alignment.

Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.

void forceCleanup()

Force the emission of cleanups now, instead of waiting until this object is destroyed.

const clang::LangOptions & getLangOpts() const

void enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp, bool isFnTryBlock=false)

Definition CIRGenException.cpp:347

void populateEHCatchRegions(EHScopeStack::stable_iterator scope, cir::TryOp tryOp)

Definition CIRGenException.cpp:567

void exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock=false)

Definition CIRGenException.cpp:372

const TargetInfo & getTarget() const

void emitAnyExprToExn(const Expr *e, Address addr)

Definition CIRGenException.cpp:222

mlir::Location getLoc(clang::SourceLocation srcLoc)

Helpers to convert Clang's SourceLocation to a MLIR Location.

void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)

Emits the code necessary to evaluate an arbitrary expression into the given memory location.

mlir::LogicalResult emitCXXTryStmtUnderScope(const clang::CXXTryStmt &s)

Definition CIRGenException.cpp:269

mlir::Operation * curFn

The current function or global initializer that is generated code for.

EHScopeStack ehStack

Tracks function scope overall cleanup handling.

void populateCatchHandlersIfRequired(cir::TryOp tryOp)

Definition CIRGenException.cpp:652

mlir::Type convertTypeForMem(QualType t)

const clang::Decl * curCodeDecl

This is the inner-most code context, which includes blocks.

mlir::MLIRContext & getMLIRContext()

mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s)

Definition CIRGenException.cpp:247

void emitCXXThrowExpr(const CXXThrowExpr *e)

Definition CIRGenException.cpp:200

bool isCatchOrCleanupRequired()

Definition CIRGenException.cpp:629

LexicalScope * curLexScope

void populateCatchHandlers(cir::TryOp tryOp)

Definition CIRGenException.cpp:477

mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})

This class organizes the cross-function state that is used while generating CIR code.

cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::ArrayAttr={}, bool isLocal=false, bool assumeConvergent=false)

CIRGenBuilderTy & getBuilder()

const clang::TargetInfo & getTarget() const

const clang::CodeGenOptions & getCodeGenOpts() const

const clang::LangOptions & getLangOpts() const

A scope which attempts to handle some, possibly all, types of exceptions.

const Handler & getHandler(unsigned i) const

unsigned getNumHandlers() const

void setHandler(unsigned i, CatchTypeInfo type, mlir::Region *region, const CXXCatchStmt *stmt)

void clearHandlerBlocks()

A non-stable pointer into the scope stack.

A saved depth on the scope stack.

A protected scope for zero-cost EH handling.

void setMayThrow(bool mayThrow)

CXXCatchStmt - This represents a C++ catch block.

Stmt * getHandlerBlock() const

VarDecl * getExceptionDecl() const

A C++ throw-expression (C++ [except.throw]).

const Expr * getSubExpr() const

CXXTryStmt - A C++ try block, including all handlers.

CodeGenOptions - Track various options which control how the code is optimized and passed to the back...

bool hasDWARFExceptions() const

bool hasWasmExceptions() const

bool hasSjLjExceptions() const

bool hasSEHExceptions() const

This represents one expression.

Represents a function declaration or definition.

bool usesSEHTry() const

Indicates the function uses __try.

const Decl * getDecl() const

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

clang::ObjCRuntime ObjCRuntime

const VersionTuple & getVersion() const

@ MacOSX

'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...

@ FragileMacOSX

'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...

@ GNUstep

'gnustep' is the modern non-fragile GNUstep runtime.

@ ObjFW

'objfw' is the Objective-C runtime included in ObjFW

@ iOS

'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...

@ GCC

'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI

@ WatchOS

'watchos' is a variant of iOS for Apple's watchOS.

A (possibly-)qualified type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

Exposes information about the current target.

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

bool isObjCObjectPointerType() const

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

U cast(CodeGen::Address addr)

static bool ehCleanupScope()

static bool catchParamOp()

static bool currentFuncletPad()

static bool incrementProfileCounter()

Represents a scope, including function bodies, compound statements, and the substatements of if/while...

void setAsTry(cir::TryOp op)

The exceptions personality for a function.

bool usesFuncletPads() const

Does this personality use landingpads or the family of pad instructions designed to form funclets?

static const EHPersonality XL_CPlusPlus

static const EHPersonality GNU_ObjC_SJLJ

static const EHPersonality ZOS_CPlusPlus

static const EHPersonality GNUstep_ObjC

const char * personalityFn

static const EHPersonality MSVC_CxxFrameHandler3

static const EHPersonality MSVC_C_specific_handler

static const EHPersonality GNU_CPlusPlus_SEH

static const EHPersonality GNU_ObjC

static const EHPersonality GNU_CPlusPlus_SJLJ

static const EHPersonality GNU_C_SJLJ

static const EHPersonality GNU_C

static const EHPersonality NeXT_ObjC

static const EHPersonality & get(CIRGenModule &cgm, const clang::FunctionDecl *fd)

Definition CIRGenException.cpp:160

static const EHPersonality GNU_CPlusPlus

static const EHPersonality GNU_ObjCXX

static const EHPersonality GNU_C_SEH

static const EHPersonality MSVC_except_handler

static const EHPersonality GNU_ObjC_SEH

static const EHPersonality GNU_Wasm_CPlusPlus