clang 23.0.0git
CIRGenException.cpp
Go to the documentation of this file.
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-exception
6//
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#include "mlir/IR/Block.h"
16#include "mlir/IR/Location.h"
17
19#include "llvm/Support/SaveAndRestore.h"
20
21using namespace clang;
22using namespace clang::CIRGen;
23
24const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};
25const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",
26 nullptr};
27const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",
28 nullptr};
29const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",
30 nullptr};
31const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",
32 nullptr};
34 "__gxx_personality_sj0", nullptr};
36 "__gxx_personality_seh0", nullptr};
37const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",
38 "objc_exception_throw"};
40 "__gnu_objc_personality_sj0", "objc_exception_throw"};
42 "__gnu_objc_personality_seh0", "objc_exception_throw"};
44 "__gnustep_objcxx_personality_v0", nullptr};
46 "__gnustep_objc_personality_v0", nullptr};
47const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",
48 nullptr};
50 "__C_specific_handler", nullptr};
52 "__CxxFrameHandler3", nullptr};
54 "__gxx_wasm_personality_v0", nullptr};
55const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
56 nullptr};
57const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
58 nullptr};
59
60static const EHPersonality &getCPersonality(const TargetInfo &target,
61 const CodeGenOptions &cgOpts) {
62 const llvm::Triple &triple = target.getTriple();
63 if (triple.isWindowsMSVCEnvironment())
65 if (cgOpts.hasSjLjExceptions())
67 if (cgOpts.hasDWARFExceptions())
69 if (cgOpts.hasSEHExceptions())
72}
73
74static const EHPersonality &getObjCPersonality(const TargetInfo &target,
75 const LangOptions &langOpts,
76 const CodeGenOptions &cgOpts) {
77 const llvm::Triple &triple = target.getTriple();
78 if (triple.isWindowsMSVCEnvironment())
80
81 switch (langOpts.ObjCRuntime.getKind()) {
83 return getCPersonality(target, cgOpts);
89 if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
91 [[fallthrough]];
94 if (cgOpts.hasSjLjExceptions())
96 if (cgOpts.hasSEHExceptions())
99 }
100 llvm_unreachable("bad runtime kind");
101}
102
103static const EHPersonality &getCXXPersonality(const TargetInfo &target,
104 const CodeGenOptions &cgOpts) {
105 const llvm::Triple &triple = target.getTriple();
106 if (triple.isWindowsMSVCEnvironment())
108 if (triple.isOSAIX())
110 if (cgOpts.hasSjLjExceptions())
112 if (cgOpts.hasDWARFExceptions())
114 if (cgOpts.hasSEHExceptions())
116 if (cgOpts.hasWasmExceptions())
119}
120
121/// Determines the personality function to use when both C++
122/// and Objective-C exceptions are being caught.
124 const LangOptions &langOpts,
125 const CodeGenOptions &cgOpts) {
126 if (target.getTriple().isWindowsMSVCEnvironment())
128
129 switch (langOpts.ObjCRuntime.getKind()) {
130 // In the fragile ABI, just use C++ exception handling and hope
131 // they're not doing crazy exception mixing.
133 return getCXXPersonality(target, cgOpts);
134
135 // The ObjC personality defers to the C++ personality for non-ObjC
136 // handlers. Unlike the C++ case, we use the same personality
137 // function on targets using (backend-driven) SJLJ EH.
139 case ObjCRuntime::iOS:
141 return getObjCPersonality(target, langOpts, cgOpts);
142
145
146 // The GCC runtime's personality function inherently doesn't support
147 // mixed EH. Use the ObjC personality just to avoid returning null.
148 case ObjCRuntime::GCC:
150 return getObjCPersonality(target, langOpts, cgOpts);
151 }
152 llvm_unreachable("bad runtime kind");
153}
154
155static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {
156 return triple.getArch() == llvm::Triple::x86
159}
160
162 const FunctionDecl *fd) {
163 const llvm::Triple &triple = cgm.getTarget().getTriple();
164 const LangOptions &langOpts = cgm.getLangOpts();
165 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
166 const TargetInfo &target = cgm.getTarget();
167
168 // Functions using SEH get an SEH personality.
169 if (fd && fd->usesSEHTry())
170 return getSEHPersonalityMSVC(triple);
171
172 if (langOpts.ObjC) {
173 return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)
174 : getObjCPersonality(target, langOpts, cgOpts);
175 }
176 return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)
177 : getCPersonality(target, cgOpts);
178}
179
181 const auto *fg = cgf.curCodeDecl;
182 // For outlined finallys and filters, use the SEH personality in case they
183 // contain more SEH. This mostly only affects finallys. Filters could
184 // hypothetically use gnu statement expressions to sneak in nested SEH.
185 fg = fg ? fg : cgf.curSEHParent.getDecl();
186 return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
187}
188
189static llvm::StringRef getPersonalityFn(CIRGenModule &cgm,
190 const EHPersonality &personality) {
191 // Create the personality function type: i32 (...)
192 mlir::Type i32Ty = cgm.getBuilder().getI32Type();
193 auto funcTy = cir::FuncType::get({}, i32Ty, /*isVarArg=*/true);
194
195 cir::FuncOp personalityFn = cgm.createRuntimeFunction(
196 funcTy, personality.personalityFn, {}, /*isLocal=*/true);
197
198 return personalityFn.getSymName();
199}
200
202 const llvm::Triple &triple = getTarget().getTriple();
203 if (cgm.getLangOpts().OpenMPIsTargetDevice &&
204 (triple.isNVPTX() || triple.isAMDGCN())) {
205 cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
206 return;
207 }
208
209 if (const Expr *subExpr = e->getSubExpr()) {
210 QualType throwType = subExpr->getType();
211 if (throwType->isObjCObjectPointerType()) {
212 cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");
213 return;
214 }
215
216 cgm.getCXXABI().emitThrow(*this, e);
217 return;
218 }
219
220 cgm.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
221}
222
224 // Make sure the exception object is cleaned up if there's an
225 // exception during initialization.
227
228 // __cxa_allocate_exception returns a void*; we need to cast this
229 // to the appropriate type for the object.
230 mlir::Type ty = convertTypeForMem(e->getType());
231 Address typedAddr = addr.withElementType(builder, ty);
232
233 // From LLVM's codegen:
234 // FIXME: this isn't quite right! If there's a final unelided call
235 // to a copy constructor, then according to [except.terminate]p1 we
236 // must call std::terminate() if that constructor throws, because
237 // technically that copy occurs after the exception expression is
238 // evaluated but before the exception is caught. But the best way
239 // to handle that is to teach EmitAggExpr to do the final copy
240 // differently if it can't be elided.
241 emitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),
242 /*isInitializer=*/true);
243
244 // Deactivate the cleanup block.
246}
247
249 const CXXCatchStmt *catchStmt, SmallVector<mlir::Attribute> &handlerAttrs) {
250 mlir::Location catchLoc = getLoc(catchStmt->getBeginLoc());
251
252 if (catchStmt->getExceptionDecl()) {
253 // FIXME: Dropping the reference type on the type into makes it
254 // impossible to correctly implement catch-by-reference
255 // semantics for pointers. Unfortunately, this is what all
256 // existing compilers do, and it's not clear that the standard
257 // personality routine is capable of doing this right. See C++ DR 388:
258 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
259 Qualifiers caughtTypeQuals;
260 QualType caughtType = cgm.getASTContext().getUnqualifiedArrayType(
261 catchStmt->getCaughtType().getNonReferenceType(), caughtTypeQuals);
262 if (caughtType->isObjCObjectPointerType()) {
263 cgm.errorNYI("addCatchHandlerAttr: caughtType ObjCObjectPointerType");
264 return;
265 }
266
267 CatchTypeInfo typeInfo = cgm.getCXXABI().getAddrOfCXXCatchHandlerType(
268 catchLoc, caughtType, catchStmt->getCaughtType());
269 handlerAttrs.push_back(typeInfo.rtti);
270 } else {
271 // No exception decl indicates '...', a catch-all.
272 handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
273 }
274}
275
276namespace {
277struct CallEndCatch final : EHScopeStack::Cleanup {
278 CallEndCatch(mlir::Value catchToken) : catchToken(catchToken) {}
279 mlir::Value catchToken;
280
281 void emit(CIRGenFunction &cgf, Flags flags) override {
282 cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken);
283 cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc);
284 }
285};
286} // namespace
287
288static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken,
289 mlir::Type exnPtrTy) {
290 auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext());
291 auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(),
292 cgf.getBuilder().getUnknownLoc(),
293 catchTokenTy, exnPtrTy, ehToken);
294
295 cgf.ehStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup,
296 beginCatch.getCatchToken());
297
298 return beginCatch.getExnPtr();
299}
300
301/// A "special initializer" callback for initializing a catch
302/// parameter during catch initialization.
304 mlir::Value ehToken, const VarDecl &catchParam,
305 SourceLocation loc) {
306 CanQualType catchType =
307 cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
308 cir::InitCatchKind kind;
309
310 // If we're catching by reference, we can just cast the object
311 // pointer to the appropriate pointer.
312 if (isa<ReferenceType>(catchType)) {
313 kind = cir::InitCatchKind::Reference;
314 } else {
315 cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
316 if (tek == cir::TEK_Aggregate) {
317 assert(isa<RecordType>(catchType) && "unexpected catch type!");
318 const Expr *copyExpr = catchParam.getInit();
319 kind = !copyExpr ? cir::InitCatchKind::TrivialCopy
320 : cir::InitCatchKind::NonTrivialCopy;
321 } else {
322 // Scalars and complexes.
323 if (catchType->hasPointerRepresentation()) {
324 switch (catchType.getQualifiers().getObjCLifetime()) {
327 kind = cir::InitCatchKind::Objc;
328 break;
329
333 kind = cir::InitCatchKind::Pointer;
334 break;
335 }
336 } else {
337 kind = cir::InitCatchKind::Scalar;
338 }
339 }
340 }
341
342 mlir::Value exnPtr = callBeginCatch(cgf, ehToken, builder.getVoidPtrTy());
344 cir::InitCatchParamOp::create(builder, cgf.getLoc(loc), exnPtr,
345 var.getAllocatedAddress().getPointer(), kind);
346 cgf.emitAutoVarCleanups(var);
347}
348
349/// Begins a catch statement by initializing the catch variable and
350/// calling __cxa_begin_catch.
352 mlir::Value ehToken) {
353 // We have to be very careful with the ordering of cleanups here:
354 // C++ [except.throw]p4:
355 // The destruction [of the exception temporary] occurs
356 // immediately after the destruction of the object declared in
357 // the exception-declaration in the handler.
358 //
359 // So the precise ordering is:
360 // 1. Construct catch variable.
361 // 2. begin_catch
362 // 3. Enter CallEndCatch cleanup
363 // 4. Enter dtor cleanup
364 //
365 VarDecl *catchParam = catchStmt->getExceptionDecl();
366 if (!catchParam) {
367 callBeginCatch(*this, ehToken, builder.getVoidPtrTy());
368 return;
369 }
370
371 // Emit the local. Make sure the alloca's superseed the current scope, since
372 // these are going to be consumed by `cir.catch`, which is not within the
373 // current scope.
374 initCatchParam(*this, builder, ehToken, *catchParam,
375 catchStmt->getBeginLoc());
376}
377
378mlir::LogicalResult
380 cxxTryBodyEmitter &bodyCallback) {
381 mlir::Location loc = getLoc(s.getSourceRange());
382
383 // Create a scope to hold try local storage for catch params.
384 mlir::OpBuilder::InsertPoint scopeIP;
385 cir::ScopeOp::create(
386 builder, loc,
387 /*scopeBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
388 scopeIP = builder.saveInsertionPoint();
389 });
390
391 // Set personality function if not already set
392 auto funcOp = mlir::cast<cir::FuncOp>(curFn);
393 if (!funcOp.getPersonality())
394 funcOp.setPersonality(getPersonalityFn(cgm, EHPersonality::get(*this)));
395
396 mlir::OpBuilder::InsertionGuard guard(builder);
397 builder.restoreInsertionPoint(scopeIP);
398
399 const llvm::Triple &t = getTarget().getTriple();
400 // If we encounter a try statement on in an OpenMP target region offloaded
401 // to a GPU, we treat it as a basic block.
402 const bool isTargetDevice =
403 (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
404 if (isTargetDevice) {
405 cgm.errorNYI("emitCXXTryStmt: OpenMP target region offloaded to GPU");
406 return mlir::success();
407 }
408
409 mlir::Location tryLoc = getLoc(s.getBeginLoc());
410 SmallVector<mlir::Attribute> handlerAttrs;
411
412 CIRGenFunction::LexicalScope tryBodyScope{*this, tryLoc,
413 builder.getInsertionBlock()};
414
415 if (getLangOpts().EHAsynch) {
416 cgm.errorNYI("enterCXXTryStmt: EHAsynch");
417 return mlir::failure();
418 }
419
420 // Create the try operation.
421 mlir::LogicalResult tryRes = mlir::success();
422 auto tryOp = cir::TryOp::create(
423 builder, tryLoc,
424 /*tryBuilder=*/
425 [&](mlir::OpBuilder &b, mlir::Location loc) {
426 // Create a RunCleanupsScope that allows us to apply any cleanups that
427 // are created for statements within the try body before exiting the
428 // try body.
429 RunCleanupsScope tryBodyCleanups(*this);
430 if (bodyCallback(*this).failed())
431 tryRes = mlir::failure();
432 tryBodyCleanups.forceCleanup();
433 cir::YieldOp::create(builder, loc);
434 },
435 /*handlersBuilder=*/
436 [&](mlir::OpBuilder &b, mlir::Location loc,
437 mlir::OperationState &result) {
438 mlir::OpBuilder::InsertionGuard guard(b);
439 bool hasCatchAll = false;
440 unsigned numHandlers = s.getNumHandlers();
441 mlir::Type ehTokenTy = cir::EhTokenType::get(&getMLIRContext());
442 for (unsigned i = 0; i != numHandlers; ++i) {
443 const CXXCatchStmt *catchStmt = s.getHandler(i);
444 if (!catchStmt->getExceptionDecl())
445 hasCatchAll = true;
446 mlir::Region *region = result.addRegion();
447 builder.createBlock(region, /*insertPt=*/{}, {ehTokenTy}, {loc});
448 addCatchHandlerAttr(catchStmt, handlerAttrs);
449 }
450 if (!hasCatchAll) {
451 // Create unwind region.
452 mlir::Region *region = result.addRegion();
453 mlir::Block *unwindBlock =
454 builder.createBlock(region, /*insertPt=*/{}, {ehTokenTy}, {loc});
455 cir::ResumeOp::create(builder, loc, unwindBlock->getArgument(0));
456 handlerAttrs.push_back(cir::UnwindAttr::get(&getMLIRContext()));
457 }
458 });
459
460 if (tryRes.failed())
461 return mlir::failure();
462
463 // Add final array of clauses into TryOp.
464 tryOp.setHandlerTypesAttr(
465 mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
466
467 // Emit the catch handler bodies. This has to be done after the try op is
468 // created and in place so that we can find the insertion point for the
469 // catch parameter alloca.
470 unsigned numHandlers = s.getNumHandlers();
471 for (unsigned i = 0; i != numHandlers; ++i) {
472 const CXXCatchStmt *catchStmt = s.getHandler(i);
473 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
474 mlir::Location handlerLoc = getLoc(catchStmt->getCatchLoc());
475
476 mlir::OpBuilder::InsertionGuard guard(builder);
477 builder.setInsertionPointToStart(&handler->front());
478
479 // Get the !cir.eh_token block argument from the handler region.
480 mlir::Value ehToken = handler->front().getArgument(0);
481
482 // Enter a cleanup scope, including the catch variable and the
483 // end-catch.
484 RunCleanupsScope handlerScope(*this);
485
486 // Initialize the catch variable.
487 // TODO(cir): Move this out of CXXABI.
489 emitBeginCatch(catchStmt, ehToken);
490
491 // Emit the PGO counter increment.
493
494 // Perform the body of the catch.
495 [[maybe_unused]] mlir::LogicalResult emitResult =
496 emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
497 assert(emitResult.succeeded() && "failed to emit catch handler block");
498
499 // [except.handle]p11:
500 // The currently handled exception is rethrown if control
501 // reaches the end of a handler of the function-try-block of a
502 // constructor or destructor.
503
504 // TODO(cir): Handle implicit rethrow?
505
506 // Fall out through the catch cleanups.
507 handlerScope.forceCleanup();
508
509 mlir::Block *block = &handler->getBlocks().back();
510 if (block->empty() ||
511 !block->back().hasTrait<mlir::OpTrait::IsTerminator>()) {
512 mlir::OpBuilder::InsertionGuard guard(builder);
513 builder.setInsertionPointToEnd(block);
514 builder.createYield(handlerLoc);
515 }
516 }
517
518 return mlir::success();
519}
520
521mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
522 if (s.getTryBlock()->body_empty())
523 return mlir::LogicalResult::success();
524
525 struct simpleTryBodyEmitter final : cxxTryBodyEmitter {
526 const clang::CXXTryStmt &s;
527 simpleTryBodyEmitter(const clang::CXXTryStmt &s) : s(s) {}
528
529 mlir::LogicalResult operator()(CIRGenFunction &cgf) override {
530 return cgf.emitStmt(s.getTryBlock(), /*useCurrentScope=*/true);
531 }
532 ~simpleTryBodyEmitter() override = default;
533 };
534
535 simpleTryBodyEmitter emitter{s};
536
537 return emitCXXTryStmt(s, emitter);
538}
539
540// in classic codegen this function is mapping to `isInvokeDest` previously
541// and currently it's mapping to the conditions that performs early returns in
542// `getInvokeDestImpl`, in CIR we need the condition to know if the EH scope
543// may throw exception or now.
545 // If exceptions are disabled/ignored and SEH is not in use, then there is
546 // no invoke destination. SEH "works" even if exceptions are off. In
547 // practice, this means that C++ destructors and other EH cleanups don't
548 // run, which is consistent with MSVC's behavior, except in the presence of
549 // -EHa
550 const LangOptions &lo = cgm.getLangOpts();
551 if (!lo.Exceptions || lo.IgnoreExceptions) {
552 if (!lo.Borland && !lo.MicrosoftExt)
553 return false;
554 cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");
555 return false;
556 }
557
558 // CUDA device code doesn't have exceptions.
559 if (lo.CUDA && lo.CUDAIsDevice)
560 return false;
561
562 return ehStack.requiresCatchOrCleanup();
563}
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static const EHPersonality & getCXXPersonality(const TargetInfo &target, const CodeGenOptions &cgOpts)
static const EHPersonality & getCPersonality(const TargetInfo &target, const CodeGenOptions &cgOpts)
static const EHPersonality & getObjCPersonality(const TargetInfo &target, const LangOptions &langOpts, const CodeGenOptions &cgOpts)
static llvm::StringRef getPersonalityFn(CIRGenModule &cgm, const EHPersonality &personality)
static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, mlir::Type exnPtrTy)
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.
static void initCatchParam(CIRGenFunction &cgf, CIRGenBuilderTy &builder, mlir::Value ehToken, const VarDecl &catchParam, SourceLocation loc)
A "special initializer" callback for initializing a catch parameter during catch initialization.
static const EHPersonality & getSEHPersonalityMSVC(const llvm::Triple &triple)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
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(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
const clang::LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
void addCatchHandlerAttr(const CXXCatchStmt *catchStmt, SmallVector< mlir::Attribute > &handlerAttrs)
void emitAnyExprToExn(const Expr *e, Address addr)
void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken)
Begins a catch statement by initializing the catch variable and calling __cxa_begin_catch.
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::Operation * curFn
The current function or global initializer that is generated code for.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::Type convertTypeForMem(QualType t)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
void emitCXXThrowExpr(const CXXThrowExpr *e)
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void emitAutoVarCleanups(const AutoVarEmission &emission)
This class organizes the cross-function state that is used while generating CIR code.
clang::ASTContext & getASTContext() const
CIRGenBuilderTy & getBuilder()
const clang::TargetInfo & getTarget() const
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
Information for lazily generating a cleanup.
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:28
SourceLocation getCatchLoc() const
Definition StmtCXX.h:48
Stmt * getHandlerBlock() const
Definition StmtCXX.h:51
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtCXX.h:43
VarDecl * getExceptionDecl() const
Definition StmtCXX.h:49
QualType getCaughtType() const
Definition StmtCXX.cpp:19
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1212
const Expr * getSubExpr() const
Definition ExprCXX.h:1232
CXXTryStmt - A C++ try block, including all handlers.
Definition StmtCXX.h:69
Qualifiers getQualifiers() const
Retrieve all qualifiers.
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.
Definition Expr.h:112
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2018
bool usesSEHTry() const
Indicates the function uses __try.
Definition Decl.h:2536
const Decl * getDecl() const
Definition GlobalDecl.h:106
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
Kind getKind() const
Definition ObjCRuntime.h:77
const VersionTuple & getVersion() const
Definition ObjCRuntime.h:78
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
Definition ObjCRuntime.h:35
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
Definition ObjCRuntime.h:40
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
Definition ObjCRuntime.h:56
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
Definition ObjCRuntime.h:59
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
Definition ObjCRuntime.h:45
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
Definition ObjCRuntime.h:53
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
Definition ObjCRuntime.h:49
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8476
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8621
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:361
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:354
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:350
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:364
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:367
ObjCLifetime getObjCLifetime() const
Definition TypeBase.h:545
Encodes a location in the source.
Exposes information about the current target.
Definition TargetInfo.h:227
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isObjCObjectPointerType() const
Definition TypeBase.h:8852
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:924
const Expr * getInit() const
Definition Decl.h:1381
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
static bool ehCleanupScope()
static bool currentFuncletPad()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...
The exceptions personality for a function.
static const EHPersonality XL_CPlusPlus
static const EHPersonality GNU_ObjC_SJLJ
static const EHPersonality ZOS_CPlusPlus
static const EHPersonality GNUstep_ObjC
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)
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