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(.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(.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