clang 24.0.0git
CIRGenDecl.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 to emit Decl nodes as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Address.h"
14#include "CIRGenCleanup.h"
16#include "CIRGenFunction.h"
17#include "EHScopeStack.h"
18#include "mlir/IR/Location.h"
19#include "clang/AST/Attr.h"
20#include "clang/AST/Attrs.inc"
21#include "clang/AST/Decl.h"
23#include "clang/AST/Expr.h"
24#include "clang/AST/ExprCXX.h"
26#include "clang/Basic/Cuda.h"
30#include "llvm/Support/SaveAndRestore.h"
31
32using namespace clang;
33using namespace clang::CIRGen;
34
35struct CallLifetimeEnd final : EHScopeStack::Cleanup {
36 // The raw alloca pointer (in the alloca address space). Mirrors classic
37 // CodeGen's CallLifetimeEnd, which stores the llvm::Value pointer rather
38 // than an Address.
39 mlir::Value addr;
40 CallLifetimeEnd(mlir::Value addr) : addr(addr) {}
41 bool isRedundantBeforeReturn() override { return true; }
42 void emit(CIRGenFunction &cgf, Flags flags) override {
43 cgf.emitLifetimeEndOp(addr.getLoc(), addr);
44 }
45};
46
49 mlir::OpBuilder::InsertPoint ip) {
50 QualType ty = d.getType();
51 assert(
54
55 mlir::Location loc = getLoc(d.getSourceRange());
56 bool nrvo =
57 getContext().getLangOpts().ElideConstructors && d.isNRVOVariable();
58
60 emission.isEscapingByRef = d.isEscapingByref();
61 if (emission.isEscapingByRef)
62 cgm.errorNYI(d.getSourceRange(),
63 "emitAutoVarAlloca: decl escaping by reference");
64
65 CharUnits alignment = getContext().getDeclAlign(&d);
66
67 // If the type is variably-modified, emit all the VLA sizes for it.
68 if (ty->isVariablyModifiedType())
70
72
73 Address address = Address::invalid();
74 if (ty->isConstantSizeType()) {
75 // If this value is an array, struct, or vector with a statically
76 // determinable constant initializer, there are optimizations we can do.
77 //
78 // TODO: We should constant-evaluate the initializer of any variable,
79 // as long as it is initialized by a constant expression. Currently,
80 // isConstantInitializer produces wrong answers for structs with
81 // reference or bitfield members, and a few other cases, and checking
82 // for POD-ness protects us from some of these.
83 if (d.getInit() &&
84 (ty->isArrayType() || ty->isRecordType() || ty->isVectorType()) &&
85 (d.isConstexpr() ||
86 ((ty.isPODType(getContext()) ||
87 getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&
89
90 // If the variable's a const type, and it's neither an NRVO
91 // candidate nor a __block variable and has no mutable members,
92 // emit it as a global instead.
93 // Exception is if a variable is located in non-constant address space
94 // in OpenCL.
95 // TODO(cir): perhaps we don't need this at all at CIR since this can
96 // be done as part of lowering down to LLVM.
97 bool needsDtor =
99 if ((!getContext().getLangOpts().OpenCL ||
101 (cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&
102 !d.isEscapingByref() &&
103 ty.isConstantStorage(getContext(), true, !needsDtor))) {
104 cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: type constant");
105 }
106 // Otherwise, tell the initialization code that we're in this case.
107 emission.isConstantAggregate = true;
108 }
109
110 // A normal fixed sized variable becomes an alloca in the entry block,
111 // unless:
112 // - it's an NRVO variable.
113 // - we are compiling OpenMP and it's an OpenMP local variable.
114 if (nrvo) {
115 // The named return value optimization: allocate this variable in the
116 // return slot, so that we can elide the copy when returning this
117 // variable (C++0x [class.copy]p34).
118 address = returnValue;
119
120 if (const RecordDecl *rd = ty->getAsRecordDecl()) {
121 if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
122 (cxxrd && !cxxrd->hasTrivialDestructor()) ||
123 rd->isNonTrivialToPrimitiveDestroy()) {
124 // In LLVM: Create a flag that is used to indicate when the NRVO was
125 // applied to this variable. Set it to zero to indicate that NRVO was
126 // not applied. For now, use the same approach for CIRGen until we can
127 // be sure it's worth doing something more aggressive.
128 cir::ConstantOp falseNVRO = builder.getFalse(loc);
129 Address nrvoFlag = createTempAlloca(falseNVRO.getType(),
130 CharUnits::One(), loc, "nrvo",
131 /*arraySize=*/nullptr);
132 assert(builder.getInsertionBlock());
133 builder.createStore(loc, falseNVRO, nrvoFlag);
134
135 // Record the NRVO flag for this variable.
136 nrvoFlags[&d] = nrvoFlag.getPointer();
137 emission.nrvoFlag = nrvoFlag.getPointer();
138 }
139 }
140 } else {
141 // A normal fixed sized variable becomes an alloca in the entry block,
142 mlir::Type allocaTy = convertTypeForMem(ty);
143 // Create the temp alloca and declare variable using it.
144 address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
145 /*arraySize=*/nullptr, /*alloca=*/nullptr, ip);
146 declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()),
147 alignment);
148 // A goto/switch that bypasses the init splits the lifetime across IR
149 // regions and miscompiles under stack coloring (PR28267). Lacking
150 // classic's per-decl bypass analysis, drop markers for the whole
151 // function if any such statement is present.
153 if (shouldEmitLifetimeMarkersForAutoVar() && haveInsertPoint()) {
155 loc, address.getUnderlyingAllocaOp().getResult());
156 }
157 }
158 } else {
159 // Non-constant size type
161 if (!didCallStackSave) {
162 // Save the stack.
163 cir::PointerType defaultTy = allocaInt8PtrTy;
165 cgm.getDataLayout().getAlignment(defaultTy, false));
166 Address stack = createTempAlloca(defaultTy, align, loc, "saved_stack");
167
168 mlir::Value v = builder.createStackSave(loc, defaultTy);
169 assert(v.getType() == allocaInt8PtrTy);
170 builder.createStore(loc, v, stack);
171
172 didCallStackSave = true;
173
174 // Push a cleanup block and restore the stack there.
175 // FIXME: in general circumstances, this should be an EH cleanup.
177 }
178
179 VlaSizePair vlaSize = getVLASize(ty);
180 mlir::Type memTy = convertTypeForMem(vlaSize.type);
181
182 // Allocate memory for the array.
183 address =
184 createTempAlloca(memTy, alignment, loc, d.getName(), vlaSize.numElts,
185 /*alloca=*/nullptr, builder.saveInsertionPoint());
186
187 // If we have debug info enabled, properly describe the VLA dimensions for
188 // this type by registering the vla size expression for each of the
189 // dimensions.
191 }
192
193 emission.addr = address;
194 setAddrOfLocalVar(&d, address);
195
196 // The lifetime marker must reference the original alloca, so peel any
197 // address-space cast back to it.
198 if (emission.useLifetimeMarkers)
199 ehStack.pushCleanup<CallLifetimeEnd>(
200 NormalEHLifetimeMarker, address.getUnderlyingAllocaOp().getResult());
201
202 return emission;
203}
204
205/// Determine whether the given initializer is trivial in the sense
206/// that it requires no code to be generated.
208 if (!init)
209 return true;
210
211 if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(init))
212 if (CXXConstructorDecl *constructor = construct->getConstructor())
213 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
214 !construct->requiresZeroInitialization())
215 return true;
216
217 return false;
218}
219
220static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d,
221 Address addr, bool isVolatile,
222 CIRGenBuilderTy &builder,
223 mlir::TypedAttr constant) {
224 mlir::Type ty = constant.getType();
225 cir::CIRDataLayout layout{cgm.getModule()};
226 uint64_t constantSize = layout.getTypeAllocSize(ty);
227 if (!constantSize)
228 return;
231
232 if (addr.getElementType() != ty)
233 addr = addr.withElementType(builder, ty);
234
235 // If the address is an alloca, set the init attribute.
236 // The address is usually and alloca, but there is at least one case where
237 // emitAutoVarInit is called from the OpenACC codegen with an address that
238 // is not an alloca.
239 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
240 if (allocaOp)
241 allocaOp.setInitAttr(mlir::UnitAttr::get(&cgm.getMLIRContext()));
242
243 // There are cases where OpenACC codegen calls emitAutoVarInit with a
244 // temporary decl that doesn't have a source range set.
245 mlir::Location loc = builder.getUnknownLoc();
246 if (d.getSourceRange().isValid())
247 loc = cgm.getLoc(d.getSourceRange());
248
249 // Emit cir.const + cir.store, preserving source-level semantics. For
250 // aggregate types (arrays, records), LoweringPrepare implements the OG
251 // optimization tiers (shouldCreateMemCpyFromGlobal, shouldUseBZeroPlusStores,
252 // shouldUseMemSetToInitialize, shouldSplitConstantStore) by transforming
253 // into cir.global + cir.get_global + cir.copy when appropriate.
254 builder.createStore(loc, builder.getConstant(loc, constant), addr);
255}
256
258 const CIRGenFunction::AutoVarEmission &emission) {
259 assert(emission.variable && "emission was not valid!");
260
261 // If this was emitted as a global constant, we're done.
262 if (emission.wasEmittedAsGlobal())
263 return;
264
265 const VarDecl &d = *emission.variable;
266
267 QualType type = d.getType();
268
269 // If this local has an initializer, emit it now.
270 const Expr *init = d.getInit();
271
272 // Initialize the variable here if it doesn't have a initializer and it is a
273 // C struct that is non-trivial to initialize or an array containing such a
274 // struct.
275 if (!init && type.isNonTrivialToPrimitiveDefaultInitialize() ==
277 cgm.errorNYI(d.getSourceRange(),
278 "emitAutoVarInit: non-trivial to default initialize");
279 return;
280 }
281
282 const Address addr = emission.addr;
283
284 // Check whether this is a byref variable that's potentially
285 // captured and moved by its own initializer. If so, we'll need to
286 // emit the initializer first, then copy into the variable.
288
289 // Note: constexpr already initializes everything correctly.
290 LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
291 (d.isConstexpr()
293 : (d.getAttr<UninitializedAttr>()
295 : getContext().getLangOpts().getTrivialAutoVarInit()));
296
297 auto initializeWhatIsTechnicallyUninitialized = [&](Address addr) {
298 if (trivialAutoVarInit ==
300 return;
301
302 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: trivial initialization");
303 };
304
305 if (isTrivialInitializer(init)) {
306 initializeWhatIsTechnicallyUninitialized(addr);
307 return;
308 }
309
310 mlir::Attribute constant;
311 if (emission.isConstantAggregate ||
313 // FIXME: Differently from LLVM we try not to emit / lower too much
314 // here for CIR since we are interested in seeing the ctor in some
315 // analysis later on. So CIR's implementation of ConstantEmitter will
316 // frequently return an empty Attribute, to signal we want to codegen
317 // some trivial ctor calls and whatnots.
319 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
320 (trivialAutoVarInit !=
322 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: constant aggregate");
323 return;
324 }
325 }
326
327 // NOTE(cir): In case we have a constant initializer, we can just emit a
328 // store. But, in CIR, we wish to retain any ctor calls, so if it is a
329 // CXX temporary object creation, we ensure the ctor call is used deferring
330 // its removal/optimization to the CIR lowering.
331 if (!constant || isa<CXXTemporaryObjectExpr>(init)) {
332 initializeWhatIsTechnicallyUninitialized(addr);
334 emitExprAsInit(init, &d, lv);
335
336 if (!emission.wasEmittedAsOffloadClause()) {
337 // In case lv has uses it means we indeed initialized something
338 // out of it while trying to build the expression, mark it as such.
339 Address addr = lv.getAddress();
340 assert(addr.isValid() && "Should have an address");
341 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
342 assert(allocaOp && "Address should come straight out of the alloca");
343
344 if (!allocaOp.use_empty())
345 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
346 }
347
348 return;
349 }
350
351 // FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.
352 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
353 assert(typedConstant && "expected typed attribute");
354 if (!emission.isConstantAggregate) {
355 // For simple scalar/complex initialization, store the value directly.
356 LValue lv = makeAddrLValue(addr, type);
357 assert(init && "expected initializer");
358 mlir::Location initLoc = getLoc(init->getSourceRange());
359 // lv.setNonGC(true);
361 RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
362 }
363
364 emitStoresForConstant(cgm, d, addr, type.isVolatileQualified(), builder,
365 typedConstant);
366}
367
369 const CIRGenFunction::AutoVarEmission &emission) {
370 const VarDecl &d = *emission.variable;
371
372 // Check the type for a cleanup.
374 emitAutoVarTypeCleanup(emission, dtorKind);
375
377
378 // Handle the cleanup attribute.
379 if (d.hasAttr<CleanupAttr>())
380 cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
381}
382
383/// Emit code and set up symbol table for a variable declaration with auto,
384/// register, or no storage class specifier. These turn into simple stack
385/// objects, globals depending on target.
391
392namespace {
393/// Finds the temporaries with a destructor that the initializer of a variable
394/// with automatic storage duration lifetime-extends. Their cleanups are pushed
395/// onto the EH stack when the initializer's full-expression ends.
396class LifetimeExtendedTemporaryFinder
397 : public RecursiveASTVisitor<LifetimeExtendedTemporaryFinder> {
398 const VarDecl &var;
401
402public:
403 explicit LifetimeExtendedTemporaryFinder(const VarDecl &var) : var(var) {}
404
405 /// The types of the temporaries that were found.
406 ArrayRef<QualType> found() const { return types; }
407
408 // Look into the semantic form of initializer lists, which holds the backing
409 // array of a std::initializer_list, and into default member initializers.
410 // The array filler of an initializer list is not visited.
411 bool shouldVisitImplicitCode() const { return true; }
412
413 /// Records the type of each temporary requiring destruction whose lifetime
414 /// is extended by \c var.
415 bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *m) {
416 if (m->getExtendingDecl() != &var ||
417 m->getStorageDuration() != SD_Automatic || !visited.insert(m).second)
418 return true;
419 // Like pushTemporaryCleanup, look at the type of the whole temporary, not
420 // at the subobject that the reference binds to.
421 SmallVector<const Expr *, 2> commaLHSs;
422 SmallVector<SubobjectAdjustment, 2> adjustments;
423 const Expr *e =
424 m->getSubExpr()->skipRValueSubobjectAdjustments(commaLHSs, adjustments);
426 types.push_back(e->getType());
427 return true;
428 }
429};
430} // namespace
431
433 const CXXRecordDecl *rd =
434 type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
435 if (!rd || rd->hasTrivialDestructor())
436 return false;
437 const auto *fpt = rd->getDestructor()->getType()->castAs<FunctionProtoType>();
438 return isUnresolvedExceptionSpec(fpt->getExceptionSpecType()) ||
439 !fpt->isNothrow();
440}
441
442SmallVector<QualType, 2>
444 const Expr *init = d.getInit();
445 if (!init)
446 return {};
447 LifetimeExtendedTemporaryFinder finder(d);
448 finder.TraverseStmt(const_cast<Expr *>(init));
449 return SmallVector<QualType, 2>(finder.found());
450}
451
453 const VarDecl &d, CapturedCleanups &condCleanup,
454 ArrayRef<QualType> extendedTemporaries) {
455 // A condition variable always has automatic storage duration, so this
456 // mirrors the auto-var path of emitVarDecl/emitAutoVarDecl. Capture the
457 // lifetime-end cleanup pushed while emitting the alloca, but emit the
458 // initializer with capturing disabled so the cleanups of its temporaries get
459 // their normal cir.cleanup.scope handling. Only the cleanups of the
460 // temporaries that it lifetime-extends are captured, when its
461 // full-expression ends. The variable's destructor cleanup is captured
462 // separately after initialization.
463 assert(d.hasLocalStorage() && "loop condition variable is not local");
464
465 // Mirror the diagnostic emitted by emitVarDecl on the automatic-storage path.
466 // A condition variable is implicitly in the private address space, so this is
467 // not expected to fire, but keep it to preserve emitVarDecl's behavior.
469 cgm.errorNYI(d.getSourceRange(),
470 "emitLoopConditionVariable: OpenCL local address space");
471
472 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
473 CIRGenFunction::AutoVarEmission emission = [&] {
474 CapturedCleanups::CaptureScope capture(condCleanup);
475 return emitAutoVarAlloca(d);
476 }();
477
478 // The condition variable's destructor is captured into the loop op's
479 // per-iteration cleanup region, which structurally spans the initializer.
480 // If the initializer throws, the variable was never constructed and its
481 // destructor must not run. Classic codegen avoids this by pushing the
482 // cleanup only after the initializer, but our deferred cleanup necessarily
483 // covers the whole condition region, so guard it with an active flag that is
484 // false while the initializer runs and set to true once construction
485 // completes. The flag is stored to on every iteration, so it also resets
486 // correctly across iterations.
487 //
488 // The temporaries that the initializer lifetime-extends are destroyed with
489 // the variable as well ([class.temporary]p6). Their cleanups are pushed when
490 // the initializer's full-expression ends, so capture them too and guard them
491 // with the same flag.
492 bool needsCleanup = d.needsDestruction(getContext()) != QualType::DK_none;
493 bool extendsTemporaries = !extendedTemporaries.empty();
494
495 // Destroy the variable first, then the temporaries in reverse order of
496 // construction. A throw would skip the remaining destructors because CFG
497 // flattening does not yet support EH paths in loop cleanup regions.
498 if (getLangOpts().Exceptions && extendsTemporaries &&
499 ((needsCleanup && destructorMayThrow(d.getType())) ||
500 (extendedTemporaries.size() > 1 &&
501 llvm::any_of(extendedTemporaries, destructorMayThrow))))
502 cgm.errorNYI(d.getSourceRange(),
503 "loop condition variable cleanup with a potentially-throwing "
504 "destructor before another destructor");
505
506 Address activeFlag = Address::invalid();
507 if (needsCleanup || extendsTemporaries) {
508 mlir::Location loc = getLoc(d.getSourceRange());
509 activeFlag = createTempAllocaWithoutCast(
510 builder.getBoolTy(), CharUnits::One(), loc, "cond.cleanup.isactive",
511 /*arraySize=*/nullptr,
512 builder.getBestAllocaInsertPoint(getCurFunctionEntryBlock()));
513 builder.createFlagStore(loc, false, activeFlag.getPointer());
514 }
515
516 EHScopeStack::stable_iterator initDepth = ehStack.stable_begin();
517 {
518 LifetimeExtensionCapture capture{&d, &condCleanup, activeFlag};
520 lifetimeExtensionCapture, extendsTemporaries ? &capture : nullptr);
521 emitAutoVarInit(emission);
522 }
523
524 // Only lifetime-extended cleanups remain after initialization. If the AST
525 // walk found no extended temporaries, these cleanups are uncaptured and wrap
526 // cir.condition in cir.cleanup.scope (e.g. for initializer-list array
527 // fillers).
528 if (!extendsTemporaries && ehStack.stable_begin() != initDepth) {
529 cgm.errorNYI(d.getSourceRange(),
530 "loop condition variable whose initializer leaves uncaptured "
531 "cleanups");
532 popCleanupBlocks(initDepth);
533 }
534#ifndef NDEBUG
535 for (auto it = ehStack.begin(), ie = ehStack.find(initDepth); it != ie; ++it)
536 assert(!cast<EHCleanupScope>(*it).getCleanupScopeOp() &&
537 "loop condition variable initializer left an uncaptured cleanup");
538#endif
539
540 if (activeFlag.isValid()) {
541 // Construction has completed, so activate the destructor cleanups.
542 mlir::Location loc = getLoc(d.getSourceRange());
543 builder.createFlagStore(loc, true, activeFlag.getPointer());
544 }
545
546 {
547 CapturedCleanups::CaptureScope capture(condCleanup);
548 emitAutoVarCleanups(emission);
549 }
550
551 if (needsCleanup)
552 initFullExprCleanupWithFlag(activeFlag);
553}
554
556 // If the declaration has external storage, don't emit it now, allow it to be
557 // emitted lazily on its first use.
558 if (d.hasExternalStorage())
559 return;
560
561 if (d.getStorageDuration() != SD_Automatic) {
562 // Static sampler variables translated to function calls.
563 if (d.getType()->isSamplerT()) {
564 // Nothing needs to be done here, but let's flag it as an error until we
565 // have a test. It requires OpenCL support.
566 cgm.errorNYI(d.getSourceRange(), "emitVarDecl: static sampler type");
567 return;
568 }
569
570 cir::GlobalLinkageKind linkage = cgm.getCIRLinkageVarDefinition(&d);
571
572 // FIXME: We need to force the emission/use of a guard variable for
573 // some variables even if we can constant-evaluate them because
574 // we can't guarantee every translation unit will constant-evaluate them.
575
576 return emitStaticVarDecl(d, linkage);
577 }
578
580 cgm.errorNYI(d.getSourceRange(), "emitVarDecl: openCL address space");
581
582 assert(d.hasLocalStorage());
583
584 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
585 return emitAutoVarDecl(d);
586}
587
588static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {
589 if (cgm.getLangOpts().CPlusPlus)
590 return cgm.getMangledName(&d).str();
591
592 // If this isn't C++, we don't need a mangled name, just a pretty one.
593 assert(!d.isExternallyVisible() && "name shouldn't matter");
594 std::string contextName;
595 const DeclContext *dc = d.getDeclContext();
596 if (auto *cd = dyn_cast<CapturedDecl>(dc))
597 dc = cast<DeclContext>(cd->getNonClosureContext());
598 if (const auto *fd = dyn_cast<FunctionDecl>(dc))
599 contextName = std::string(cgm.getMangledName(fd));
600 else if (isa<BlockDecl>(dc))
601 cgm.errorNYI(d.getSourceRange(),
602 "getStaticDeclName: block decl context for static var");
603 else if (isa<ObjCMethodDecl>(dc))
604 cgm.errorNYI(d.getSourceRange(),
605 "getStaticDeclName: ObjC decl context for static var");
606 else
607 cgm.errorNYI(d.getSourceRange(),
608 "getStaticDeclName: Unknown context for static var decl");
609
610 contextName += "." + d.getNameAsString();
611 return contextName;
612}
613
614// TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an
615// interface for all constants?
616cir::GlobalOp
618 cir::GlobalLinkageKind linkage) {
619 // In general, we don't always emit static var decls once before we reference
620 // them. It is possible to reference them before emitting the function that
621 // contains them, and it is possible to emit the containing function multiple
622 // times.
623 if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))
624 return existingGV;
625
626 QualType ty = d.getType();
627 assert(ty->isConstantSizeType() && "VLAs can't be static");
628
629 // Use the label if the variable is renamed with the asm-label extension.
630 if (d.hasAttr<AsmLabelAttr>())
631 errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");
632
633 std::string name = getStaticDeclName(*this, d);
634
635 mlir::Type lty = getTypes().convertTypeForMem(ty);
636
637 // OpenCL variables in local address space and CUDA shared
638 // variables cannot have an initializer.
639 mlir::Attribute init = nullptr;
641 d.hasAttr<CUDASharedAttr>() || d.hasAttr<LoaderUninitializedAttr>())
642 init = cir::UndefAttr::get(lty);
643 else
644 init = emitNullConstantAttr(ty);
645
646 mlir::ptr::MemorySpaceAttrInterface addrSpace =
647 getGlobalCIRAddressSpace(getGlobalVarAddressSpace(&d));
648
649 cir::GlobalOp gv =
650 builder.createVersionedGlobal(getModule(), getLoc(d.getLocation()), name,
651 lty, false, linkage, addrSpace);
653 // TODO(cir): infer visibility from linkage in global op builder.
654 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
655 gv.setInitialValueAttr(init);
656 gv.setAlignment(getASTContext().getDeclAlign(&d).getAsAlign().value());
657
658 if (supportsCOMDAT() && gv.isWeakForLinker())
659 gv.setSelfComdat();
660
661 if (d.getTLSKind())
662 setTLSMode(gv, d);
663
664 setGVProperties(gv, &d);
665
666 // The global may live in a different address space than the declared type.
667 // Users of the address cast it through castGlobalToDeclAddrSpace.
669
670 // Ensure that the static local gets initialized by making sure the parent
671 // function gets emitted eventually.
672 const Decl *dc = cast<Decl>(d.getDeclContext());
673
674 // We can't name blocks or captured statements directly, so try to emit their
675 // parents.
676 if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {
677 dc = dc->getNonClosureContext();
678 // FIXME: Ensure that global blocks get emitted.
679 if (!dc)
680 errorNYI(d.getSourceRange(), "non-closure context");
681 }
682
683 GlobalDecl gd;
684 if (const auto *cd = dyn_cast<CXXConstructorDecl>(dc))
685 gd = GlobalDecl(cd, Ctor_Base);
686 else if (const auto *dd = dyn_cast<CXXDestructorDecl>(dc))
687 gd = GlobalDecl(dd, Dtor_Base);
688 else if (const auto *fd = dyn_cast<FunctionDecl>(dc))
689 gd = GlobalDecl(fd);
690 else {
691 // Don't do anything for Obj-C method decls or global closures. We should
692 // never defer them.
693 assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");
694 }
695 if (gd.getDecl()) {
696 if (getLangOpts().OpenMPIsTargetDevice) {
697 // Disable emission of the parent function for the OpenMP device codegen.
698 // TODO(cir): Use CGOpenMPRuntime::DisableAutoDeclareTargetRAII here.
700 "OpenMP: DisableAutoDeclareTargetRAII for static local");
701 }
702 (void)getAddrOfGlobal(gd);
703 }
704
705 return gv;
706}
707
709 mlir::Attribute constAttr,
710 CharUnits align) {
711 auto functionName = [&](const DeclContext *dc) -> std::string {
712 if (const auto *fd = dyn_cast<FunctionDecl>(dc)) {
713 if (const auto *cc = dyn_cast<CXXConstructorDecl>(fd))
714 return cc->getNameAsString();
715 if (const auto *cd = dyn_cast<CXXDestructorDecl>(fd))
716 return cd->getNameAsString();
717 return std::string(getMangledName(fd));
718 } else if (const auto *om = dyn_cast<ObjCMethodDecl>(dc)) {
719 return om->getNameAsString();
720 } else if (isa<BlockDecl>(dc)) {
721 return "<block>";
722 } else if (isa<CapturedDecl>(dc)) {
723 return "<captured>";
724 } else {
725 llvm_unreachable("expected a function or method");
726 }
727 };
728
729 // Form a simple per-variable cache of these values in case we find we
730 // want to reuse them.
731 cir::GlobalOp &cacheEntry = initializerConstants[&d];
732 if (!cacheEntry || cacheEntry.getInitialValue() != constAttr) {
733 auto ty = mlir::cast<mlir::TypedAttr>(constAttr).getType();
734 bool isConstant = true;
735
736 std::string name;
737 if (d.hasGlobalStorage())
738 name = getMangledName(&d).str() + ".const";
739 else if (const DeclContext *dc = d.getParentFunctionOrMethod())
740 name = ("__const." + functionName(dc) + "." + d.getName()).str();
741 else
742 llvm_unreachable("local variable has no parent function or method");
743
745 cir::GlobalOp gv = builder.createVersionedGlobal(
746 getModule(), getLoc(d.getLocation()), name, ty, isConstant,
747 cir::GlobalLinkageKind::PrivateLinkage);
749 // TODO(cir): infer visibility from linkage in global op builder.
750 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(
751 cir::GlobalLinkageKind::PrivateLinkage));
752 gv.setInitialValueAttr(constAttr);
753 gv.setAlignment(align.getAsAlign().value());
754 // TODO(cir): Set unnamed address attribute when available in CIR
755
756 cacheEntry = gv;
757 } else if (cacheEntry.getAlignment() < align.getQuantity()) {
758 cacheEntry.setAlignment(align.getAsAlign().value());
759 }
760
761 // Create a GetGlobalOp to get a pointer to the global
763 mlir::Type eltTy = mlir::cast<mlir::TypedAttr>(constAttr).getType();
764 auto ptrTy = builder.getPointerTo(cacheEntry.getSymType());
765 mlir::Value globalPtr = cir::GetGlobalOp::create(
766 builder, getLoc(d.getLocation()), ptrTy, cacheEntry.getSymName());
767 return Address(globalPtr, eltTy, align);
768}
769
770/// Add the initializer for 'd' to the global variable that has already been
771/// created for it. If the initializer has a different type than gv does, this
772/// may free gv and return a different one. Otherwise it just returns gv.
774 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
775 ConstantEmitter emitter(*this);
776 mlir::TypedAttr init = mlir::dyn_cast_if_present<mlir::TypedAttr>(
777 emitter.tryEmitForInitializer(d));
778
779 // If constant emission failed, then this should be a C++ static
780 // initializer.
781 if (!init) {
782 if (!getLangOpts().CPlusPlus) {
783 cgm.errorNYI(d.getInit()->getSourceRange(),
784 "constant l-value expression");
785 } else if (d.hasFlexibleArrayInit(getContext())) {
786 cgm.errorNYI(d.getInit()->getSourceRange(), "flexible array initializer");
787 } else {
788 // Since we have a static initializer, this global variable can't
789 // be constant.
790 gv.setConstant(false);
791 emitCXXGuardedInit(d, gv, /*performInit*/ true);
792 gvAddr.setStaticLocal(true);
793 }
794 return gv;
795 }
796
797 // TODO(cir): There should be debug code here to assert that the decl size
798 // matches the CIR data layout type alloc size, but the code for calculating
799 // the type alloc size is not implemented yet.
801
802 // The initializer may differ in type from the global. Rewrite
803 // the global to match the initializer. (We have to do this
804 // because some types, like unions, can't be completely represented
805 // in the LLVM type system.)
806 if (gv.getSymType() != init.getType()) {
807 gv.setSymType(init.getType());
808
809 // Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),
810 // but since at this point the current block hasn't been really attached,
811 // there's no visibility into the GetGlobalOp corresponding to this Global.
812 // Given those constraints, thread in the GetGlobalOp and update it
813 // directly.
815 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
816 }
817
818 bool needsDtor =
820
821 gv.setConstant(d.getType().isConstantStorage(
822 getContext(), /*ExcludeCtor=*/true, !needsDtor));
823 gv.setInitialValueAttr(init);
824
825 emitter.finalize(gv);
826
827 if (needsDtor) {
828 // We have a constant initializer, but a nontrivial destructor. We still
829 // need to perform a guarded "initialization" in order to register the
830 // destructor.
831 emitCXXGuardedInit(d, gv, /*performInit=*/false);
832 gvAddr.setStaticLocal(true);
833 }
834
835 return gv;
836}
837
839 cir::GlobalLinkageKind linkage) {
840 // Check to see if we already have a global variable for this
841 // declaration. This can happen when double-emitting function
842 // bodies, e.g. with complete and base constructors.
843 cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);
844 // TODO(cir): we should have a way to represent global ops as values without
845 // having to emit a get global op. Sometimes these emissions are not used.
846 mlir::Value addr =
847 builder.createGetGlobal(globalOp, d.getTLSKind() != VarDecl::TLS_None);
848 auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
849 assert(getAddrOp && "expected cir::GetGlobalOp");
850
851 CharUnits alignment = getContext().getDeclAlign(&d);
852
853 // Store into LocalDeclMap before generating initializer to handle
854 // circular references.
855 mlir::Type elemTy = convertTypeForMem(d.getType());
856 setAddrOfLocalVar(&d, Address(addr, elemTy, alignment));
857
858 // We can't have a VLA here, but we can have a pointer to a VLA,
859 // even though that doesn't really make any sense.
860 // Make sure to evaluate VLA bounds now so that we have them for later.
863
864 // Save the type in case adding the initializer forces a type change.
865 mlir::Type expectedType = addr.getType();
866
867 cir::GlobalOp var = globalOp;
868
869 // Sema ensures any initializer of a CUDA __shared__ variable is a no-op.
870 bool isCudaSharedVar = getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
871 d.hasAttr<CUDASharedAttr>();
872 // If this value has an initializer, emit it.
873 if (d.getInit() && !isCudaSharedVar)
874 var = addInitializerToStaticVarDecl(d, var, getAddrOp);
875
876 var.setAlignment(alignment.getAsAlign().value());
877
878 // There are a lot of attributes that need to be handled here. Until
879 // we start to support them, we just report an error if there are any.
880 if (d.hasAttr<AnnotateAttr>())
881 cgm.addGlobalAnnotations(&d, var);
882 if (d.getAttr<PragmaClangBSSSectionAttr>())
883 cgm.errorNYI(d.getSourceRange(),
884 "emitStaticVarDecl: CIR global BSS section attribute");
885 if (d.getAttr<PragmaClangDataSectionAttr>())
886 cgm.errorNYI(d.getSourceRange(),
887 "emitStaticVarDecl: CIR global Data section attribute");
888 if (d.getAttr<PragmaClangRodataSectionAttr>())
889 cgm.errorNYI(d.getSourceRange(),
890 "emitStaticVarDecl: CIR global Rodata section attribute");
891 if (d.getAttr<PragmaClangRelroSectionAttr>())
892 cgm.errorNYI(d.getSourceRange(),
893 "emitStaticVarDecl: CIR global Relro section attribute");
894
895 if (const SectionAttr *sa = d.getAttr<SectionAttr>())
896 var.setSectionAttr(builder.getStringAttr(sa->getName()));
897
898 if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)
899 cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");
900
901 // From traditional codegen:
902 // We may have to cast the constant because of the initializer
903 // mismatch above.
904 //
905 // FIXME: It is really dangerous to store this in the map; if anyone
906 // RAUW's the GV uses of this constant will be invalid.
907 mlir::Value castedAddr =
908 builder.createBitcast(getAddrOp.getAddr(), expectedType);
909 castedAddr = cgm.castGlobalToDeclAddrSpace(castedAddr, d);
910 localDeclMap.find(&d)->second = Address(castedAddr, elemTy, alignment);
911 cgm.setStaticLocalDeclAddress(&d, var);
912
915}
916
918 bool capturedByInit) {
920
921 SourceLocRAIIObject locRAII{*this, init->getSourceRange()};
922 mlir::Value value = emitScalarExpr(init);
923 if (capturedByInit) {
924 cgm.errorNYI(init->getSourceRange(), "emitScalarInit: captured by init");
925 return;
926 }
928 emitStoreThroughLValue(RValue::get(value), lvalue, true);
929}
930
932 LValue lvalue, bool capturedByInit) {
933 SourceLocRAIIObject loc{*this, init->getSourceRange()};
934 if (capturedByInit) {
935 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
936 return;
937 }
938
939 QualType type = d->getType();
940
941 if (type->isReferenceType()) {
942 RValue rvalue = emitReferenceBindingToExpr(init);
943 if (capturedByInit)
944 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
945 emitStoreThroughLValue(rvalue, lvalue);
946 return;
947 }
949 case cir::TEK_Scalar:
950 emitScalarInit(init, lvalue);
951 return;
952 case cir::TEK_Complex: {
953 mlir::Value complex = emitComplexExpr(init);
954 if (capturedByInit)
955 cgm.errorNYI(init->getSourceRange(),
956 "emitExprAsInit: complex type captured by init");
957 mlir::Location loc = getLoc(init->getExprLoc());
958 emitStoreOfComplex(loc, complex, lvalue,
959 /*isInit*/ true);
960 return;
961 }
963 // The overlap flag here should be calculated.
965 emitAggExpr(init,
969 return;
970 }
971 llvm_unreachable("bad evaluation kind");
972}
973
974void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) {
975 switch (d.getKind()) {
976 case Decl::BuiltinTemplate:
977 case Decl::TranslationUnit:
978 case Decl::ExternCContext:
979 case Decl::Namespace:
980 case Decl::UnresolvedUsingTypename:
981 case Decl::ClassTemplateSpecialization:
982 case Decl::ClassTemplatePartialSpecialization:
983 case Decl::VarTemplateSpecialization:
984 case Decl::VarTemplatePartialSpecialization:
985 case Decl::TemplateTypeParm:
986 case Decl::UnresolvedUsingValue:
987 case Decl::NonTypeTemplateParm:
988 case Decl::CXXDeductionGuide:
989 case Decl::CXXMethod:
990 case Decl::CXXConstructor:
991 case Decl::CXXDestructor:
992 case Decl::CXXConversion:
993 case Decl::Field:
994 case Decl::MSProperty:
995 case Decl::IndirectField:
996 case Decl::ObjCIvar:
997 case Decl::ObjCAtDefsField:
998 case Decl::ParmVar:
999 case Decl::ImplicitParam:
1000 case Decl::ClassTemplate:
1001 case Decl::VarTemplate:
1002 case Decl::FunctionTemplate:
1003 case Decl::TypeAliasTemplate:
1004 case Decl::TemplateTemplateParm:
1005 case Decl::ObjCMethod:
1006 case Decl::ObjCCategory:
1007 case Decl::ObjCProtocol:
1008 case Decl::ObjCInterface:
1009 case Decl::ObjCCategoryImpl:
1010 case Decl::ObjCImplementation:
1011 case Decl::ObjCProperty:
1012 case Decl::ObjCCompatibleAlias:
1013 case Decl::PragmaComment:
1014 case Decl::PragmaDetectMismatch:
1015 case Decl::AccessSpec:
1016 case Decl::LinkageSpec:
1017 case Decl::Export:
1018 case Decl::ObjCPropertyImpl:
1019 case Decl::FileScopeAsm:
1020 case Decl::Friend:
1021 case Decl::FriendTemplate:
1022 case Decl::Block:
1023 case Decl::OutlinedFunction:
1024 case Decl::Captured:
1025 case Decl::UsingShadow:
1026 case Decl::ConstructorUsingShadow:
1027 case Decl::ObjCTypeParam:
1028 case Decl::Binding:
1029 case Decl::UnresolvedUsingIfExists:
1030 case Decl::HLSLBuffer:
1031 case Decl::HLSLRootSignature:
1032 llvm_unreachable("Declaration should not be in declstmts!");
1033
1034 case Decl::Function: // void X();
1035 case Decl::EnumConstant: // enum ? { X = ? }
1036 case Decl::ExplicitInstantiation:
1037 case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
1038 case Decl::Label: // __label__ x;
1039 case Decl::Import:
1040 case Decl::MSGuid: // __declspec(uuid("..."))
1041 case Decl::TemplateParamObject:
1042 case Decl::Empty:
1043 case Decl::Concept:
1044 case Decl::LifetimeExtendedTemporary:
1045 case Decl::RequiresExprBody:
1046 case Decl::UnnamedGlobalConstant:
1047 // None of these decls require codegen support.
1048 return;
1049
1050 case Decl::Enum: // enum X;
1051 case Decl::Record: // struct/union/class X;
1052 case Decl::CXXRecord: // struct/union/class X; [C++]
1053 case Decl::NamespaceAlias:
1054 case Decl::Using: // using X; [C++]
1055 case Decl::UsingEnum: // using enum X; [C++]
1056 case Decl::UsingDirective: // using namespace X; [C++]
1058 return;
1059 case Decl::Var:
1060 case Decl::Decomposition: {
1061 const VarDecl &vd = cast<VarDecl>(d);
1062 assert(vd.isLocalVarDecl() &&
1063 "Should not see file-scope variables inside a function!");
1064 emitVarDecl(vd);
1065 if (evaluateConditionDecl)
1067 return;
1068 }
1069 case Decl::OpenACCDeclare:
1071 return;
1072 case Decl::OpenACCRoutine:
1074 return;
1075 case Decl::OMPThreadPrivate:
1077 return;
1078 case Decl::OMPGroupPrivate:
1080 return;
1081 case Decl::OMPAllocate:
1083 return;
1084 case Decl::OMPCapturedExpr:
1086 return;
1087 case Decl::OMPRequires:
1089 return;
1090 case Decl::OMPDeclareMapper:
1092 return;
1093 case Decl::OMPDeclareReduction:
1095 return;
1096 case Decl::Typedef: // typedef int X;
1097 case Decl::TypeAlias: { // using X = int; [C++0x]
1098 QualType ty = cast<TypedefNameDecl>(d).getUnderlyingType();
1100 if (ty->isVariablyModifiedType())
1102 return;
1103 }
1104 case Decl::ImplicitConceptSpecialization:
1105 case Decl::TopLevelStmt:
1106 case Decl::UsingPack:
1107 case Decl::CXXExpansionStmt:
1108 cgm.errorNYI(d.getSourceRange(),
1109 std::string("emitDecl: unhandled decl type: ") +
1110 d.getDeclKindName());
1111 }
1112}
1113
1115 SourceLocation loc) {
1116 if (!sanOpts.has(SanitizerKind::NullabilityAssign))
1117 return;
1118
1120}
1121
1122namespace {
1123struct DestroyObject final : EHScopeStack::Cleanup {
1124 DestroyObject(Address addr, QualType type,
1125 CIRGenFunction::Destroyer *destroyer)
1126 : addr(addr), type(type), destroyer(destroyer) {
1128 }
1129
1130 Address addr;
1131 QualType type;
1132 CIRGenFunction::Destroyer *destroyer;
1133
1134 void emit(CIRGenFunction &cgf, Flags flags) override {
1136 cgf.emitDestroy(addr, type, destroyer);
1137 }
1138};
1139
1140template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup {
1141 DestroyNRVOVariable(Address addr, QualType type, mlir::Value nrvoFlag)
1142 : nrvoFlag(nrvoFlag), addr(addr), ty(type) {}
1143
1144 mlir::Value nrvoFlag;
1145 Address addr;
1146 QualType ty;
1147
1148 void emit(CIRGenFunction &cgf, Flags flags) override {
1149 // Along the exceptions path we always execute the dtor.
1150 bool nrvo = flags.isForNormalCleanup() && nrvoFlag;
1151
1152 CIRGenBuilderTy &builder = cgf.getBuilder();
1153 mlir::OpBuilder::InsertionGuard guard(builder);
1154 if (nrvo) {
1155 // If we exited via NRVO, we skip the destructor call.
1156 mlir::Location loc = addr.getPointer().getLoc();
1157 mlir::Value didNRVO = builder.createFlagLoad(loc, nrvoFlag);
1158 mlir::Value notNRVO = builder.createNot(didNRVO);
1159 cir::IfOp::create(builder, loc, notNRVO, /*withElseRegion=*/false,
1160 [&](mlir::OpBuilder &b, mlir::Location) {
1161 static_cast<Derived *>(this)->emitDestructorCall(cgf);
1162 builder.createYield(loc);
1163 });
1164 } else {
1165 static_cast<Derived *>(this)->emitDestructorCall(cgf);
1166 }
1167 }
1168
1169 virtual ~DestroyNRVOVariable() = default;
1170};
1171
1172struct DestroyNRVOVariableCXX final
1173 : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
1174 DestroyNRVOVariableCXX(Address addr, QualType type,
1175 const CXXDestructorDecl *dtor, mlir::Value nrvoFlag)
1176 : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, nrvoFlag),
1177 dtor(dtor) {}
1178
1179 const CXXDestructorDecl *dtor;
1180
1181 void emitDestructorCall(CIRGenFunction &cgf) {
1183 /*forVirtualBase=*/false,
1184 /*delegating=*/false, addr, ty);
1185 }
1186};
1187
1188struct CallStackRestore final : EHScopeStack::Cleanup {
1189 Address stack;
1190 CallStackRestore(Address stack) : stack(stack) {}
1191 bool isRedundantBeforeReturn() override { return true; }
1192 void emit(CIRGenFunction &cgf, Flags flags) override {
1193 mlir::Location loc = stack.getPointer().getLoc();
1194 mlir::Value v = cgf.getBuilder().createLoad(loc, stack);
1195 cgf.getBuilder().createStackRestore(loc, v);
1196 }
1197};
1198
1199/// A cleanup which performs a partial array destroy where the end pointer is
1200/// irregularly determined and must be loaded from a local.
1201struct IrregularPartialArrayDestroy final : EHScopeStack::Cleanup {
1202 mlir::Value arrayBegin;
1203 Address arrayEndPointer;
1204 QualType elementType;
1205 CharUnits elementAlign;
1206 CIRGenFunction::Destroyer *destroyer;
1207
1208 IrregularPartialArrayDestroy(mlir::Value arrayBegin, Address arrayEndPointer,
1209 QualType elementType, CharUnits elementAlign,
1210 CIRGenFunction::Destroyer *destroyer)
1211 : arrayBegin(arrayBegin), arrayEndPointer(arrayEndPointer),
1212 elementType(elementType), elementAlign(elementAlign),
1213 destroyer(destroyer) {}
1214
1215 void emit(CIRGenFunction &cgf, Flags flags) override {
1216 CIRGenBuilderTy &builder = cgf.getBuilder();
1217 mlir::Location loc = arrayBegin.getLoc();
1218
1219 mlir::Value arrayEnd = builder.createLoad(loc, arrayEndPointer);
1220
1221 // baseElementType gets us the final 'element' type, which should be the
1222 // RecordType, looking through any multi-dimension arrays.
1223 QualType baseElementType = cgf.getContext().getBaseElementType(elementType);
1224
1225 mlir::Type cirElementType = cgf.convertTypeForMem(baseElementType);
1226 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
1227
1228 mlir::Value begin = arrayBegin;
1229 if (baseElementType != elementType) {
1230 begin = builder.createPtrBitcast(begin, cirElementType);
1231 arrayEnd = builder.createPtrBitcast(arrayEnd, cirElementType);
1232 }
1233
1234 // The cleanup is destroying elements in reverse from arrayEnd back to
1235 // begin, but only if arrayEnd != begin (i.e. something was
1236 // constructed).
1237 mlir::Value ne =
1238 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, arrayEnd, begin);
1239 cir::IfOp::create(
1240 builder, loc, ne, /*withElseRegion=*/false,
1241 [&](mlir::OpBuilder &b, mlir::Location loc) {
1242 Address iterAddr = cgf.createTempAlloca(
1243 ptrToElmType, cgf.getPointerAlign(), loc, "__array_idx");
1244 builder.createStore(loc, arrayEnd, iterAddr);
1245 builder.createDoWhile(
1246 loc,
1247 /*condBuilder=*/
1248 [&](mlir::OpBuilder &b, mlir::Location loc) {
1249 mlir::Value cur = builder.createLoad(loc, iterAddr);
1250 mlir::Value cmp = cir::CmpOp::create(
1251 builder, loc, cir::CmpOpKind::ne, cur, begin);
1252 builder.createCondition(cmp);
1253 },
1254 /*bodyBuilder=*/
1255 [&](mlir::OpBuilder &b, mlir::Location loc) {
1256 mlir::Value cur = builder.createLoad(loc, iterAddr);
1257 cir::ConstantOp negOne = builder.getConstInt(
1258 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), -1);
1259 mlir::Value prev = cir::PtrStrideOp::create(
1260 builder, loc, ptrToElmType, cur, negOne);
1261 builder.createStore(loc, prev, iterAddr);
1262 Address elemAddr = Address(prev, cirElementType, elementAlign);
1263 destroyer(cgf, elemAddr, baseElementType);
1264 builder.createYield(loc);
1265 });
1266 builder.createYield(loc);
1267 });
1268 }
1269};
1270} // namespace
1271
1272/// Push an EH cleanup to destroy already-constructed elements of the given
1273/// array. The cleanup is deactivated when the enclosing
1274/// CleanupDeactivationScope exits.
1275///
1276/// \param elementType - the immediate element type of the array;
1277/// possibly still an array type
1279 Address arrayEndPointer,
1280 QualType elementType,
1281 CharUnits elementAlign,
1282 Destroyer *destroyer) {
1284 EHCleanup, arrayBegin, arrayEndPointer, elementType, elementAlign,
1285 destroyer);
1286}
1287
1288/// pushEHDestroyIfNeeded - Push the standard destructor for the given type as
1289/// an EH-only cleanup. If EH cleanup is not needed, just return.
1291 Address addr, QualType type) {
1292 if (!needsEHCleanup(dtorKind))
1293 return;
1294
1296 pushDestroy(EHCleanup, addr, type, getDestroyer(dtorKind));
1297}
1298
1299/// Push the standard destructor for the given type as
1300/// at least a normal cleanup.
1302 Address addr, QualType type) {
1303 assert(dtorKind && "cannot push destructor for trivial type");
1304
1305 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1306 pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind));
1307}
1308
1310 QualType type, Destroyer *destroyer) {
1311 pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
1312}
1313
1316 assert(dtorKind && "cannot push destructor for trivial type");
1317
1318 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1320 cleanupKind, addr, type, getDestroyer(dtorKind), cleanupKind & EHCleanup);
1321}
1322
1324 CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer,
1325 bool useEHCleanupForArray) {
1328 destroyer);
1329}
1330
1332 CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer,
1333 bool useEHCleanupForArray, const ValueDecl *extendingDecl) {
1334 if (isInConditionalBranch()) {
1335 cgm.errorNYI("conditional lifetime-extended destroy");
1336 return;
1337 }
1338
1339 // Add the cleanup to the EHStack. After the full-expr, this would be
1340 // deactivated before being popped from the stack.
1341 pushDestroyAndDeferDeactivation(cleanupKind, addr, type, destroyer,
1342 useEHCleanupForArray);
1343
1345
1346 pushCleanupAfterFullExpr(cleanupKind, addr, type, destroyer);
1347
1348 // A temporary that a loop condition variable extends is destroyed with the
1349 // variable at the end of each iteration, in the loop's cleanup region.
1351 extendingDecl == lifetimeExtensionCapture->extendingDecl) {
1353 entry.activeFlag = lifetimeExtensionCapture->activeFlag;
1354 entry.capturedBy = lifetimeExtensionCapture->cleanups;
1355 }
1356}
1357
1359 const PendingCleanupEntry &entry) {
1360 std::optional<CapturedCleanups::CaptureScope> capture;
1361 if (entry.capturedBy)
1362 capture.emplace(*entry.capturedBy);
1363 ehStack.pushCleanup<DestroyObject>(entry.kind, entry.addr, entry.type,
1364 entry.destroyer);
1365
1366 if (entry.activeFlag.isValid()) {
1367 EHCleanupScope &scope = cast<EHCleanupScope>(*ehStack.begin());
1368 scope.setActiveFlag(entry.activeFlag);
1370 scope.setTestFlagInEHCleanup(scope.isEHCleanup());
1371 }
1372}
1373
1374/// Destroys all the elements of the given array, beginning from last to first.
1375///
1376/// \param begin - a type* denoting the first element of the array
1377/// \param numElements - the number of elements in the array
1378/// \param elementType - the element type of the array
1379/// \param destroyer - the function to call to destroy elements
1381 mlir::Value numElements,
1382 QualType elementType,
1383 CharUnits elementAlign,
1384 Destroyer *destroyer) {
1385 assert(!elementType->isArrayType());
1386
1387 // Differently from LLVM traditional codegen, use a higher level
1388 // representation instead of lowering directly to a loop.
1389 mlir::Type cirElementType = convertTypeForMem(elementType);
1390 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
1391
1392 auto regionBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1393 mlir::BlockArgument arg =
1394 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
1395 Address curAddr = Address(arg, cirElementType, elementAlign);
1397
1398 // Perform the actual destruction there.
1399 destroyer(*this, curAddr, elementType);
1400
1401 cir::YieldOp::create(b, loc);
1402 };
1403
1404 // For a constant array size, use the static form of ArrayDtor.
1405 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
1406 uint64_t size = 0;
1407 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())
1408 size = constIntAttr.getUInt();
1409 auto arrayTy = cir::ArrayType::get(cirElementType, size);
1410 mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);
1411 cir::ArrayDtor::create(builder, getLoc(*currSrcLoc), arrayOp,
1412 regionBuilder);
1413 return;
1414 }
1415
1416 // For a dynamic array size (VLA), use the dynamic form of ArrayDtor.
1417 mlir::Value elemBegin = builder.createPtrBitcast(begin, cirElementType);
1418 cir::ArrayDtor::create(builder, getLoc(*currSrcLoc), elemBegin, numElements,
1419 regionBuilder);
1420}
1421
1422/// Immediately perform the destruction of the given object.
1423///
1424/// \param addr - the address of the object; a type*
1425/// \param type - the type of the object; if an array type, all
1426/// objects are destroyed in reverse order
1427/// \param destroyer - the function to call to destroy individual
1428/// elements
1430 Destroyer *destroyer) {
1432 if (!arrayType)
1433 return destroyer(*this, addr, type);
1434
1435 mlir::Value length = emitArrayLength(arrayType, type, addr);
1436
1437 CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement(
1438 getContext().getTypeSizeInChars(type));
1439
1440 // If the array length is constant, we can check for zero at compile time.
1441 auto constantCount = length.getDefiningOp<cir::ConstantOp>();
1442 if (constantCount) {
1443 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
1444 if (constIntAttr && constIntAttr.getUInt() == 0)
1445 return;
1446 }
1447
1448 mlir::Value begin = addr.getPointer();
1450 emitArrayDestroy(begin, length, type, elementAlign, destroyer);
1451
1452 // If the array destroy didn't use the length op, we can erase it.
1453 if (constantCount && constantCount.use_empty())
1454 constantCount.erase();
1455}
1456
1459 switch (kind) {
1460 case QualType::DK_none:
1461 llvm_unreachable("no destroyer for trivial dtor");
1463 return destroyCXXObject;
1467 cgm.errorNYI("getDestroyer: other destruction kind");
1468 return nullptr;
1469 }
1470 llvm_unreachable("Unknown DestructionKind");
1471}
1472
1474 ehStack.pushCleanup<CallStackRestore>(kind, spMem);
1475}
1476
1477/// Enter a destroy cleanup for the given local variable.
1479 const CIRGenFunction::AutoVarEmission &emission,
1480 QualType::DestructionKind dtorKind) {
1481 assert(dtorKind != QualType::DK_none);
1482
1483 // Note that for __block variables, we want to destroy the
1484 // original stack object, not the possibly forwarded object.
1485 Address addr = emission.getObjectAddress(*this);
1486
1487 const VarDecl *var = emission.variable;
1488 QualType type = var->getType();
1489
1490 CleanupKind cleanupKind = NormalAndEHCleanup;
1491 CIRGenFunction::Destroyer *destroyer = nullptr;
1492
1493 switch (dtorKind) {
1494 case QualType::DK_none:
1495 llvm_unreachable("no cleanup for trivially-destructible variable");
1496
1498 // If there's an NRVO flag on the emission, we need a different
1499 // cleanup.
1500 if (emission.nrvoFlag) {
1501 assert(!type->isArrayType());
1502 CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
1503 ehStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, type, dtor,
1504 emission.nrvoFlag);
1505 return;
1506 }
1507 // Otherwise, this is handled below.
1508 break;
1509
1513 cgm.errorNYI(var->getSourceRange(),
1514 "emitAutoVarTypeCleanup: other dtor kind");
1515 return;
1516 }
1517
1518 // If we haven't chosen a more specific destroyer, use the default.
1519 if (!destroyer)
1520 destroyer = getDestroyer(dtorKind);
1521
1523 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
1524}
1525
1527 if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
1528 for (auto *b : dd->flat_bindings())
1529 if (auto *hd = b->getHoldingVar())
1530 emitVarDecl(*hd);
1531 }
1532}
1533
1534bool CIRGenFunction::emitLifetimeStartOp(mlir::Location loc, mlir::Value addr) {
1535 if (!shouldEmitLifetimeMarkers)
1536 return false;
1537
1538 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1540 "Pointer should be in alloca address space");
1541
1542 cir::LifetimeStartOp::create(builder, loc, addr);
1543 return true;
1544}
1545
1546void CIRGenFunction::emitLifetimeEndOp(mlir::Location loc, mlir::Value addr) {
1547 if (!shouldEmitLifetimeMarkers)
1548 return;
1549
1550 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1552 "Pointer should be in alloca address space");
1553
1554 cir::LifetimeEndOp::create(builder, loc, addr);
1555}
static bool emit(llvm::SmallVectorImpl< std::byte > &Code, const T &Val)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static bool isRedundantBeforeReturn(mlir::Region &cleanupRegion)
static bool destructorMayThrow(QualType type)
static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d, Address addr, bool isVolatile, CIRGenBuilderTy &builder, mlir::TypedAttr constant)
static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d)
This file defines OpenACC nodes for declarative directives.
static constexpr bool needsDtor()
Defines the clang::Expr interface and subclasses for C++ expressions.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::PointerType getPointerTo(mlir::Type ty)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr)
Emit a load from an boolean flag variable.
llvm::TypeSize getTypeAllocSize(mlir::Type ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
const LangOptions & getLangOpts() const
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
Definition Address.h:138
bool isValid() const
Definition Address.h:77
cir::AllocaOp getUnderlyingAllocaOp() const
Return the underlying alloca for this address, if any.
Definition Address.h:152
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::StackRestoreOp createStackRestore(mlir::Location loc, mlir::Value v)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
An RAII class that suppresses cir.cleanup.scope creation for cleanups pushed onto the EH stack while ...
Captures cleanups for variables whose lifetime ends in a region owned by an enclosing op rather than ...
void emitOpenACCRoutine(const OpenACCRoutineDecl &d)
cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr)
Add the initializer for 'd' to the global variable that has already been created for it.
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
void emitAutoVarTypeCleanup(const AutoVarEmission &emission, clang::QualType::DestructionKind dtorKind)
Enter a destroy cleanup for the given local variable.
llvm::SmallVector< PendingCleanupEntry > lifetimeExtendedCleanupStack
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
mlir::Block * getCurFunctionEntryBlock()
void emitOMPRequiresDecl(const OMPRequiresDecl &d)
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
bool isTrivialInitializer(const Expr *init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void emitOpenACCDeclare(const OpenACCDeclareDecl &d)
void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Push an EH cleanup to destroy already-constructed elements of the given array.
void emitLifetimeEndOp(mlir::Location loc, mlir::Value addr)
void pushCleanupAndDeferDeactivation(CleanupKind kind, As... a)
Push a cleanup and record it for deferred deactivation.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitOMPDeclareReduction(const OMPDeclareReductionDecl &d)
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d, LValue lvalue, bool capturedByInit=false)
Emit an expression as an initializer for an object (variable, field, etc.) at the given location.
void emitCXXGuardedInit(const VarDecl &varDecl, cir::GlobalOp globalOp, bool performInit)
Emit a guarded initializer for a static local variable.
void emitLoopConditionVariable(const clang::VarDecl &d, CapturedCleanups &condCleanup, llvm::ArrayRef< QualType > extendedTemporaries)
Emit a loop's condition-variable declaration.
mlir::Value emitArrayLength(const clang::ArrayType *arrayType, QualType &baseType, Address &addr)
Computes the length of an array in elements, as well as the base element type and a properly-typed fi...
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, Address addr, QualType type)
void emitScalarInit(const clang::Expr *init, LValue lvalue, bool capturedByInit=false)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
void emitOMPAllocateDecl(const OMPAllocateDecl &d)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl &d)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
Push the standard destructor for the given type as at least a normal cleanup.
void emitVarDecl(const clang::VarDecl &d)
This method handles emission of any variable declaration inside a function, including static vars etc...
Address returnValue
The temporary alloca to hold the return value.
void emitArrayDestroy(mlir::Value begin, mlir::Value numElements, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Destroys all the elements of the given array, beginning from last to first.
void initFullExprCleanupWithFlag(Address activeFlag)
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
bool haveInsertPoint() const
True if an insertion point is defined.
void emitAutoVarInit(const AutoVarEmission &emission)
Emit the initializer for an allocated variable.
void maybeEmitDeferredVarDeclInit(const VarDecl *vd)
const LifetimeExtensionCapture * lifetimeExtensionCapture
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
void pushStackRestore(CleanupKind kind, Address spMem)
void emitAutoVarDecl(const clang::VarDecl &d)
Emit code and set up symbol table for a variable declaration with auto, register, or no storage class...
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray, const clang::ValueDecl *extendingDecl)
void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth, ArrayRef< mlir::Value * > valuesToReload={})
Takes the old cleanup stack size and emits the cleanup blocks that have been added.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
CIRGenBuilderTy & getBuilder()
bool didCallStackSave
Whether a cir.stacksave operation has been added.
void emitDecl(const clang::Decl &d, bool evaluateConditionDecl=false)
void emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
void pushPendingCleanupToEHStack(const PendingCleanupEntry &entry)
Promote a single pending cleanup entry onto the EH scope stack.
llvm::DenseMap< const VarDecl *, mlir::Value > nrvoFlags
A mapping from NRVO variables to the flags used to indicate when the NRVO has been applied to this va...
mlir::MLIRContext & getMLIRContext()
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
void pushEHDestroyIfNeeded(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroyIfNeeded - Push the standard destructor for the given type as an EH-only cleanup.
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl &d)
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl &d)
bool emitLifetimeStartOp(mlir::Location loc, mlir::Value addr)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
void pushFullExprCleanup(CleanupKind kind, As... a)
Push a cleanup to be run at the end of the current full-expression.
clang::ASTContext & getContext() const
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
void pushCleanupAfterFullExpr(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer)
Queue a cleanup to be pushed after finishing the current full-expression.
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitOMPCapturedExpr(const OMPCapturedExprDecl &d)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
static llvm::SmallVector< QualType, 2 > getLifetimeExtendedTemporariesWithDestructor(const clang::VarDecl &d)
The types of the temporaries with a destructor that the initializer of the variable d,...
Address createTempAllocaWithoutCast(mlir::Type ty, CharUnits align, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, mlir::OpBuilder::InsertPoint ip={})
This creates a alloca and inserts it into the entry block of the current region.
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void emitAutoVarCleanups(const AutoVarEmission &emission)
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
void insertGlobalSymbol(mlir::Operation *op)
llvm::DenseMap< const VarDecl *, cir::GlobalOp > initializerConstants
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
mlir::TypedAttr emitNullConstantAttr(QualType t)
void setTLSMode(mlir::Operation *op, const VarDecl &d, bool isExtendingDecl=false)
Set TLS mode for the given operation based on the given variable declaration.
const clang::LangOptions & getLangOpts() const
void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::ModuleOp getModule() const
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d)
mlir::ptr::MemorySpaceAttrInterface getGlobalCIRAddressSpace(LangAS as)
Return the CIR address space attribute for a global in as, honoring the target address space map wher...
Address createUnnamedGlobalFrom(const VarDecl &d, mlir::Attribute constAttr, CharUnits align)
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
A cleanup scope which generates the cleanup blocks lazily.
void setTestFlagInEHCleanup(bool value)
void setTestFlagInNormalCleanup(bool value)
void setActiveFlag(Address var)
Information for lazily generating a cleanup.
A saved depth on the scope stack.
Address getAddress() const
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
Represents a call to a C++ constructor.
Definition ExprCXX.h:1553
Represents a C++ constructor within a class.
Definition DeclCXX.h:2642
Represents a C++ destructor within a class.
Definition DeclCXX.h:2907
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1382
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2129
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
Definition CharUnits.h:159
static CharUnits One()
Construct a CharUnits quantity of one.
Definition CharUnits.h:55
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition CharUnits.h:184
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
const DeclContext * getParentFunctionOrMethod(bool LexicalParent=false) const
If this decl is defined inside a function/method/block it returns the corresponding DeclContext,...
Definition DeclBase.cpp:344
T * getAttr() const
Definition DeclBase.h:581
Decl * getNonClosureContext()
Find the innermost non-closure ancestor of this declaration, walking up through blocks,...
SourceLocation getLocation() const
Definition DeclBase.h:447
const char * getDeclKindName() const
Definition DeclBase.cpp:169
DeclContext * getDeclContext()
Definition DeclBase.h:456
bool hasAttr() const
Definition DeclBase.h:585
Kind getKind() const
Definition DeclBase.h:450
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
This represents one expression.
Definition Expr.h:113
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Definition Expr.cpp:85
bool isConstantInitializer(ASTContext &Ctx, bool ForRef=false, const Expr **Culprit=nullptr) const
Returns true if this expression can be emitted to IR as a constant, and thus can be used as a constan...
Definition Expr.cpp:3386
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
const Decl * getDecl() const
Definition GlobalDecl.h:115
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4999
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4991
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:5024
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:318
bool isExternallyVisible() const
Definition Decl.h:434
A (possibly-)qualified type.
Definition TypeBase.h:938
@ PDIK_Struct
The type is a struct containing a field whose type is not PCK_Trivial.
Definition TypeBase.h:1494
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8572
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1561
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1037
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
Definition Type.cpp:2916
Represents a struct/union/class.
Definition Decl.h:4464
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition Type.cpp:2645
bool isArrayType() const
Definition TypeBase.h:8782
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9366
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2881
bool isVectorType() const
Definition TypeBase.h:8822
bool isSamplerT() const
Definition TypeBase.h:8927
bool isRecordType() const
Definition TypeBase.h:8810
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1594
TLSKind getTLSKind() const
Definition Decl.cpp:2148
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2170
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2837
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1248
bool mightBeUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value might be usable in a constant expression, according to the re...
Definition Decl.cpp:2471
bool isNRVOVariable() const
Determine whether this local variable can be used with the named return value optimization (NRVO).
Definition Decl.h:1537
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2826
const Expr * getInit() const
Definition Decl.h:1392
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1239
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1191
@ TLS_None
Not a TLS variable.
Definition Decl.h:953
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1275
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1251
bool isEscapingByref() const
Indicates the capture is a __block variable that is captured by a block that can potentially escape (...
Definition Decl.cpp:2686
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
Top level wrappers for InstallAPI frontend operations.
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ SD_Automatic
Automatic storage duration (most local variables).
Definition Specifiers.h:343
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
U cast(CodeGen::Address addr)
Definition Address.h:327
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
CallLifetimeEnd(mlir::Value addr)
bool isRedundantBeforeReturn() override
void emit(CIRGenFunction &cgf, Flags flags) override
Emit the cleanup.
mlir::Value addr
static bool objCLifetime()
static bool addAutoInitAnnotation()
static bool addressSpace()
static bool emitNullabilityCheck()
static bool useEHCleanupForArray()
static bool vectorConstants()
static bool aggValueSlotMayOverlap()
static bool dtorCleanups()
static bool dataLayoutTypeAllocSize()
static bool opAllocaCaptureByInit()
static bool lifetimeMarkersBypass()
static bool opAllocaPreciseLifetime()
static bool generateDebugInfo()
bool isEscapingByRef
True if the variable is a __block variable that is captured by an escaping block.
Address addr
The address of the alloca for languages with explicit address space (e.g.
bool useLifetimeMarkers
True if lifetime op should be used.
bool isConstantAggregate
True if the variable is of aggregate type and has a constant initializer.
Address getObjectAddress(CIRGenFunction &cgf) const
Returns the address of the object within this declaration.
Set by emitLoopConditionVariable while it emits the initializer of a loop condition variable that lif...
A cleanup whose destructor call is not emitted where the cleanup is registered.
CapturedCleanups * capturedBy
If set, the cleanup is captured by this owner instead of opening a cir.cleanup.scope when it is pushe...
clang::CharUnits getPointerAlign() const
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const