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"
25#include "clang/Basic/Cuda.h"
29
30using namespace clang;
31using namespace clang::CIRGen;
32
33struct CallLifetimeEnd final : EHScopeStack::Cleanup {
34 // The raw alloca pointer (in the alloca address space). Mirrors classic
35 // CodeGen's CallLifetimeEnd, which stores the llvm::Value pointer rather
36 // than an Address.
37 mlir::Value addr;
38 CallLifetimeEnd(mlir::Value addr) : addr(addr) {}
39 void emit(CIRGenFunction &cgf, Flags flags) override {
40 cgf.emitLifetimeEndOp(addr.getLoc(), addr);
41 }
42};
43
46 mlir::OpBuilder::InsertPoint ip) {
47 QualType ty = d.getType();
48 assert(
51
52 mlir::Location loc = getLoc(d.getSourceRange());
53 bool nrvo =
54 getContext().getLangOpts().ElideConstructors && d.isNRVOVariable();
55
57 emission.isEscapingByRef = d.isEscapingByref();
58 if (emission.isEscapingByRef)
59 cgm.errorNYI(d.getSourceRange(),
60 "emitAutoVarAlloca: decl escaping by reference");
61
62 CharUnits alignment = getContext().getDeclAlign(&d);
63
64 // If the type is variably-modified, emit all the VLA sizes for it.
65 if (ty->isVariablyModifiedType())
67
69
70 Address address = Address::invalid();
71 if (ty->isConstantSizeType()) {
72 // If this value is an array, struct, or vector with a statically
73 // determinable constant initializer, there are optimizations we can do.
74 //
75 // TODO: We should constant-evaluate the initializer of any variable,
76 // as long as it is initialized by a constant expression. Currently,
77 // isConstantInitializer produces wrong answers for structs with
78 // reference or bitfield members, and a few other cases, and checking
79 // for POD-ness protects us from some of these.
80 if (d.getInit() &&
81 (ty->isArrayType() || ty->isRecordType() || ty->isVectorType()) &&
82 (d.isConstexpr() ||
83 ((ty.isPODType(getContext()) ||
84 getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&
86
87 // If the variable's a const type, and it's neither an NRVO
88 // candidate nor a __block variable and has no mutable members,
89 // emit it as a global instead.
90 // Exception is if a variable is located in non-constant address space
91 // in OpenCL.
92 // TODO(cir): perhaps we don't need this at all at CIR since this can
93 // be done as part of lowering down to LLVM.
94 bool needsDtor =
96 if ((!getContext().getLangOpts().OpenCL ||
98 (cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&
99 !d.isEscapingByref() &&
100 ty.isConstantStorage(getContext(), true, !needsDtor))) {
101 cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: type constant");
102 }
103 // Otherwise, tell the initialization code that we're in this case.
104 emission.isConstantAggregate = true;
105 }
106
107 // A normal fixed sized variable becomes an alloca in the entry block,
108 // unless:
109 // - it's an NRVO variable.
110 // - we are compiling OpenMP and it's an OpenMP local variable.
111 if (nrvo) {
112 // The named return value optimization: allocate this variable in the
113 // return slot, so that we can elide the copy when returning this
114 // variable (C++0x [class.copy]p34).
115 address = returnValue;
116
117 if (const RecordDecl *rd = ty->getAsRecordDecl()) {
118 if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
119 (cxxrd && !cxxrd->hasTrivialDestructor()) ||
120 rd->isNonTrivialToPrimitiveDestroy()) {
121 // In LLVM: Create a flag that is used to indicate when the NRVO was
122 // applied to this variable. Set it to zero to indicate that NRVO was
123 // not applied. For now, use the same approach for CIRGen until we can
124 // be sure it's worth doing something more aggressive.
125 cir::ConstantOp falseNVRO = builder.getFalse(loc);
126 Address nrvoFlag = createTempAlloca(falseNVRO.getType(),
127 CharUnits::One(), loc, "nrvo",
128 /*arraySize=*/nullptr);
129 assert(builder.getInsertionBlock());
130 builder.createStore(loc, falseNVRO, nrvoFlag);
131
132 // Record the NRVO flag for this variable.
133 nrvoFlags[&d] = nrvoFlag.getPointer();
134 emission.nrvoFlag = nrvoFlag.getPointer();
135 }
136 }
137 } else {
138 // A normal fixed sized variable becomes an alloca in the entry block,
139 mlir::Type allocaTy = convertTypeForMem(ty);
140 // Create the temp alloca and declare variable using it.
141 address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
142 /*arraySize=*/nullptr, /*alloca=*/nullptr, ip);
143 declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()),
144 alignment);
145 // A goto/switch that bypasses the init splits the lifetime across IR
146 // regions and miscompiles under stack coloring (PR28267). Lacking
147 // classic's per-decl bypass analysis, drop markers for the whole
148 // function if any such statement is present.
150 if (shouldEmitLifetimeMarkersForAutoVar() && haveInsertPoint()) {
152 loc, address.getUnderlyingAllocaOp().getResult());
153 }
154 }
155 } else {
156 // Non-constant size type
158 if (!didCallStackSave) {
159 // Save the stack.
160 cir::PointerType defaultTy = allocaInt8PtrTy;
162 cgm.getDataLayout().getAlignment(defaultTy, false));
163 Address stack = createTempAlloca(defaultTy, align, loc, "saved_stack");
164
165 mlir::Value v = builder.createStackSave(loc, defaultTy);
166 assert(v.getType() == allocaInt8PtrTy);
167 builder.createStore(loc, v, stack);
168
169 didCallStackSave = true;
170
171 // Push a cleanup block and restore the stack there.
172 // FIXME: in general circumstances, this should be an EH cleanup.
174 }
175
176 VlaSizePair vlaSize = getVLASize(ty);
177 mlir::Type memTy = convertTypeForMem(vlaSize.type);
178
179 // Allocate memory for the array.
180 address =
181 createTempAlloca(memTy, alignment, loc, d.getName(), vlaSize.numElts,
182 /*alloca=*/nullptr, builder.saveInsertionPoint());
183
184 // If we have debug info enabled, properly describe the VLA dimensions for
185 // this type by registering the vla size expression for each of the
186 // dimensions.
188 }
189
190 emission.addr = address;
191 setAddrOfLocalVar(&d, address);
192
193 // The lifetime marker must reference the original alloca, so peel any
194 // address-space cast back to it.
195 if (emission.useLifetimeMarkers)
196 ehStack.pushCleanup<CallLifetimeEnd>(
197 NormalEHLifetimeMarker, address.getUnderlyingAllocaOp().getResult());
198
199 return emission;
200}
201
202/// Determine whether the given initializer is trivial in the sense
203/// that it requires no code to be generated.
205 if (!init)
206 return true;
207
208 if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(init))
209 if (CXXConstructorDecl *constructor = construct->getConstructor())
210 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
211 !construct->requiresZeroInitialization())
212 return true;
213
214 return false;
215}
216
217static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d,
218 Address addr, bool isVolatile,
219 CIRGenBuilderTy &builder,
220 mlir::TypedAttr constant) {
221 mlir::Type ty = constant.getType();
222 cir::CIRDataLayout layout{cgm.getModule()};
223 uint64_t constantSize = layout.getTypeAllocSize(ty);
224 if (!constantSize)
225 return;
228
229 if (addr.getElementType() != ty)
230 addr = addr.withElementType(builder, ty);
231
232 // If the address is an alloca, set the init attribute.
233 // The address is usually and alloca, but there is at least one case where
234 // emitAutoVarInit is called from the OpenACC codegen with an address that
235 // is not an alloca.
236 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
237 if (allocaOp)
238 allocaOp.setInitAttr(mlir::UnitAttr::get(&cgm.getMLIRContext()));
239
240 // There are cases where OpenACC codegen calls emitAutoVarInit with a
241 // temporary decl that doesn't have a source range set.
242 mlir::Location loc = builder.getUnknownLoc();
243 if (d.getSourceRange().isValid())
244 loc = cgm.getLoc(d.getSourceRange());
245
246 // Emit cir.const + cir.store, preserving source-level semantics. For
247 // aggregate types (arrays, records), LoweringPrepare implements the OG
248 // optimization tiers (shouldCreateMemCpyFromGlobal, shouldUseBZeroPlusStores,
249 // shouldUseMemSetToInitialize, shouldSplitConstantStore) by transforming
250 // into cir.global + cir.get_global + cir.copy when appropriate.
251 builder.createStore(loc, builder.getConstant(loc, constant), addr);
252}
253
255 const CIRGenFunction::AutoVarEmission &emission) {
256 assert(emission.variable && "emission was not valid!");
257
258 // If this was emitted as a global constant, we're done.
259 if (emission.wasEmittedAsGlobal())
260 return;
261
262 const VarDecl &d = *emission.variable;
263
264 QualType type = d.getType();
265
266 // If this local has an initializer, emit it now.
267 const Expr *init = d.getInit();
268
269 // Initialize the variable here if it doesn't have a initializer and it is a
270 // C struct that is non-trivial to initialize or an array containing such a
271 // struct.
272 if (!init && type.isNonTrivialToPrimitiveDefaultInitialize() ==
274 cgm.errorNYI(d.getSourceRange(),
275 "emitAutoVarInit: non-trivial to default initialize");
276 return;
277 }
278
279 const Address addr = emission.addr;
280
281 // Check whether this is a byref variable that's potentially
282 // captured and moved by its own initializer. If so, we'll need to
283 // emit the initializer first, then copy into the variable.
285
286 // Note: constexpr already initializes everything correctly.
287 LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
288 (d.isConstexpr()
290 : (d.getAttr<UninitializedAttr>()
292 : getContext().getLangOpts().getTrivialAutoVarInit()));
293
294 auto initializeWhatIsTechnicallyUninitialized = [&](Address addr) {
295 if (trivialAutoVarInit ==
297 return;
298
299 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: trivial initialization");
300 };
301
302 if (isTrivialInitializer(init)) {
303 initializeWhatIsTechnicallyUninitialized(addr);
304 return;
305 }
306
307 mlir::Attribute constant;
308 if (emission.isConstantAggregate ||
310 // FIXME: Differently from LLVM we try not to emit / lower too much
311 // here for CIR since we are interested in seeing the ctor in some
312 // analysis later on. So CIR's implementation of ConstantEmitter will
313 // frequently return an empty Attribute, to signal we want to codegen
314 // some trivial ctor calls and whatnots.
316 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
317 (trivialAutoVarInit !=
319 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: constant aggregate");
320 return;
321 }
322 }
323
324 // NOTE(cir): In case we have a constant initializer, we can just emit a
325 // store. But, in CIR, we wish to retain any ctor calls, so if it is a
326 // CXX temporary object creation, we ensure the ctor call is used deferring
327 // its removal/optimization to the CIR lowering.
328 if (!constant || isa<CXXTemporaryObjectExpr>(init)) {
329 initializeWhatIsTechnicallyUninitialized(addr);
331 emitExprAsInit(init, &d, lv);
332
333 if (!emission.wasEmittedAsOffloadClause()) {
334 // In case lv has uses it means we indeed initialized something
335 // out of it while trying to build the expression, mark it as such.
336 Address addr = lv.getAddress();
337 assert(addr.isValid() && "Should have an address");
338 cir::AllocaOp allocaOp = addr.getUnderlyingAllocaOp();
339 assert(allocaOp && "Address should come straight out of the alloca");
340
341 if (!allocaOp.use_empty())
342 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
343 }
344
345 return;
346 }
347
348 // FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.
349 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
350 assert(typedConstant && "expected typed attribute");
351 if (!emission.isConstantAggregate) {
352 // For simple scalar/complex initialization, store the value directly.
353 LValue lv = makeAddrLValue(addr, type);
354 assert(init && "expected initializer");
355 mlir::Location initLoc = getLoc(init->getSourceRange());
356 // lv.setNonGC(true);
358 RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
359 }
360
361 emitStoresForConstant(cgm, d, addr, type.isVolatileQualified(), builder,
362 typedConstant);
363}
364
366 const CIRGenFunction::AutoVarEmission &emission) {
367 const VarDecl &d = *emission.variable;
368
369 // Check the type for a cleanup.
371 emitAutoVarTypeCleanup(emission, dtorKind);
372
374
375 // Handle the cleanup attribute.
376 if (d.hasAttr<CleanupAttr>())
377 cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
378}
379
380/// Emit code and set up symbol table for a variable declaration with auto,
381/// register, or no storage class specifier. These turn into simple stack
382/// objects, globals depending on target.
388
390 const VarDecl &d, DeferredLoopConditionCleanup &condCleanup) {
391 // A condition variable always has automatic storage duration, so this
392 // mirrors the auto-var path of emitVarDecl/emitAutoVarDecl. Capture the
393 // lifetime-end cleanup pushed while emitting the alloca, but emit the
394 // initializer with capturing disabled so its own cleanups get their normal
395 // cir.cleanup.scope handling. The variable's destructor cleanup is captured
396 // separately after initialization.
397 assert(d.hasLocalStorage() && "loop condition variable is not local");
398
399 // Mirror the diagnostic emitted by emitVarDecl on the automatic-storage path.
400 // A condition variable is implicitly in the private address space, so this is
401 // not expected to fire, but keep it to preserve emitVarDecl's behavior.
403 cgm.errorNYI(d.getSourceRange(),
404 "emitLoopConditionVariable: OpenCL local address space");
405
406 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
407 CIRGenFunction::AutoVarEmission emission = [&] {
409 return emitAutoVarAlloca(d);
410 }();
411
412 // The condition variable's destructor is captured into the loop op's
413 // per-iteration cleanup region, which structurally spans the initializer.
414 // If the initializer throws, the variable was never constructed and its
415 // destructor must not run. Classic codegen avoids this by pushing the
416 // cleanup only after the initializer, but our deferred cleanup necessarily
417 // covers the whole condition region, so guard it with an active flag that is
418 // false while the initializer runs and set to true once construction
419 // completes. The flag is stored to on every iteration, so it also resets
420 // correctly across iterations.
421 bool needsCleanup = d.needsDestruction(getContext()) != QualType::DK_none;
422 Address activeFlag = Address::invalid();
423 if (needsCleanup) {
424 mlir::Location loc = getLoc(d.getSourceRange());
425 activeFlag = createTempAllocaWithoutCast(
426 builder.getBoolTy(), CharUnits::One(), loc, "cond.cleanup.isactive",
427 /*arraySize=*/nullptr,
428 builder.getBestAllocaInsertPoint(getCurFunctionEntryBlock()));
429 builder.createFlagStore(loc, false, activeFlag.getPointer());
430 }
431
432 emitAutoVarInit(emission);
433
434 if (needsCleanup) {
435 // Construction has completed, so activate the destructor cleanup.
436 mlir::Location loc = getLoc(d.getSourceRange());
437 builder.createFlagStore(loc, true, activeFlag.getPointer());
438 }
439
440 {
442 emitAutoVarCleanups(emission);
443 }
444
445 if (needsCleanup)
446 initFullExprCleanupWithFlag(activeFlag);
447}
448
450 // If the declaration has external storage, don't emit it now, allow it to be
451 // emitted lazily on its first use.
452 if (d.hasExternalStorage())
453 return;
454
455 if (d.getStorageDuration() != SD_Automatic) {
456 // Static sampler variables translated to function calls.
457 if (d.getType()->isSamplerT()) {
458 // Nothing needs to be done here, but let's flag it as an error until we
459 // have a test. It requires OpenCL support.
460 cgm.errorNYI(d.getSourceRange(), "emitVarDecl: static sampler type");
461 return;
462 }
463
464 cir::GlobalLinkageKind linkage = cgm.getCIRLinkageVarDefinition(&d);
465
466 // FIXME: We need to force the emission/use of a guard variable for
467 // some variables even if we can constant-evaluate them because
468 // we can't guarantee every translation unit will constant-evaluate them.
469
470 return emitStaticVarDecl(d, linkage);
471 }
472
474 cgm.errorNYI(d.getSourceRange(), "emitVarDecl: openCL address space");
475
476 assert(d.hasLocalStorage());
477
478 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
479 return emitAutoVarDecl(d);
480}
481
482static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {
483 if (cgm.getLangOpts().CPlusPlus)
484 return cgm.getMangledName(&d).str();
485
486 // If this isn't C++, we don't need a mangled name, just a pretty one.
487 assert(!d.isExternallyVisible() && "name shouldn't matter");
488 std::string contextName;
489 const DeclContext *dc = d.getDeclContext();
490 if (auto *cd = dyn_cast<CapturedDecl>(dc))
491 dc = cast<DeclContext>(cd->getNonClosureContext());
492 if (const auto *fd = dyn_cast<FunctionDecl>(dc))
493 contextName = std::string(cgm.getMangledName(fd));
494 else if (isa<BlockDecl>(dc))
495 cgm.errorNYI(d.getSourceRange(),
496 "getStaticDeclName: block decl context for static var");
497 else if (isa<ObjCMethodDecl>(dc))
498 cgm.errorNYI(d.getSourceRange(),
499 "getStaticDeclName: ObjC decl context for static var");
500 else
501 cgm.errorNYI(d.getSourceRange(),
502 "getStaticDeclName: Unknown context for static var decl");
503
504 contextName += "." + d.getNameAsString();
505 return contextName;
506}
507
508// TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an
509// interface for all constants?
510cir::GlobalOp
512 cir::GlobalLinkageKind linkage) {
513 // In general, we don't always emit static var decls once before we reference
514 // them. It is possible to reference them before emitting the function that
515 // contains them, and it is possible to emit the containing function multiple
516 // times.
517 if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))
518 return existingGV;
519
520 QualType ty = d.getType();
521 assert(ty->isConstantSizeType() && "VLAs can't be static");
522
523 // Use the label if the variable is renamed with the asm-label extension.
524 if (d.hasAttr<AsmLabelAttr>())
525 errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");
526
527 std::string name = getStaticDeclName(*this, d);
528
529 mlir::Type lty = getTypes().convertTypeForMem(ty);
531
532 // OpenCL variables in local address space and CUDA shared
533 // variables cannot have an initializer.
534 mlir::Attribute init = nullptr;
536 d.hasAttr<CUDASharedAttr>() || d.hasAttr<LoaderUninitializedAttr>())
537 init = cir::UndefAttr::get(lty);
538 else
539 init = builder.getZeroInitAttr(convertType(ty));
540
541 cir::GlobalOp gv = builder.createVersionedGlobal(
542 getModule(), getLoc(d.getLocation()), name, lty, false, linkage);
544 // TODO(cir): infer visibility from linkage in global op builder.
545 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
546 gv.setInitialValueAttr(init);
547 gv.setAlignment(getASTContext().getDeclAlign(&d).getAsAlign().value());
548
549 if (supportsCOMDAT() && gv.isWeakForLinker())
550 gv.setComdat(true);
551
552 if (d.getTLSKind())
553 setTLSMode(gv, d);
554
555 setGVProperties(gv, &d);
556
557 // OG checks if the expected address space, denoted by the type, is the
558 // same as the actual address space indicated by attributes. If they aren't
559 // the same, an addrspacecast is emitted when this variable is accessed.
560 // In CIR however, cir.get_global already carries that information in
561 // !cir.ptr type - if this global is in OpenCL local address space, then its
562 // type would be !cir.ptr<..., addrspace(offload_local)>. Therefore we don't
563 // need an explicit address space cast in CIR: they will get emitted when
564 // lowering to LLVM IR.
565
567
568 // Ensure that the static local gets initialized by making sure the parent
569 // function gets emitted eventually.
570 const Decl *dc = cast<Decl>(d.getDeclContext());
571
572 // We can't name blocks or captured statements directly, so try to emit their
573 // parents.
574 if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {
575 dc = dc->getNonClosureContext();
576 // FIXME: Ensure that global blocks get emitted.
577 if (!dc)
578 errorNYI(d.getSourceRange(), "non-closure context");
579 }
580
581 GlobalDecl gd;
582 if (const auto *cd = dyn_cast<CXXConstructorDecl>(dc))
583 gd = GlobalDecl(cd, Ctor_Base);
584 else if (const auto *dd = dyn_cast<CXXDestructorDecl>(dc))
585 gd = GlobalDecl(dd, Dtor_Base);
586 else if (const auto *fd = dyn_cast<FunctionDecl>(dc))
587 gd = GlobalDecl(fd);
588 else {
589 // Don't do anything for Obj-C method decls or global closures. We should
590 // never defer them.
591 assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");
592 }
593 if (gd.getDecl()) {
594 if (getLangOpts().OpenMPIsTargetDevice) {
595 // Disable emission of the parent function for the OpenMP device codegen.
596 // TODO(cir): Use CGOpenMPRuntime::DisableAutoDeclareTargetRAII here.
598 "OpenMP: DisableAutoDeclareTargetRAII for static local");
599 }
600 (void)getAddrOfGlobal(gd);
601 }
602
603 return gv;
604}
605
607 mlir::Attribute constAttr,
608 CharUnits align) {
609 auto functionName = [&](const DeclContext *dc) -> std::string {
610 if (const auto *fd = dyn_cast<FunctionDecl>(dc)) {
611 if (const auto *cc = dyn_cast<CXXConstructorDecl>(fd))
612 return cc->getNameAsString();
613 if (const auto *cd = dyn_cast<CXXDestructorDecl>(fd))
614 return cd->getNameAsString();
615 return std::string(getMangledName(fd));
616 } else if (const auto *om = dyn_cast<ObjCMethodDecl>(dc)) {
617 return om->getNameAsString();
618 } else if (isa<BlockDecl>(dc)) {
619 return "<block>";
620 } else if (isa<CapturedDecl>(dc)) {
621 return "<captured>";
622 } else {
623 llvm_unreachable("expected a function or method");
624 }
625 };
626
627 // Form a simple per-variable cache of these values in case we find we
628 // want to reuse them.
629 cir::GlobalOp &cacheEntry = initializerConstants[&d];
630 if (!cacheEntry || cacheEntry.getInitialValue() != constAttr) {
631 auto ty = mlir::cast<mlir::TypedAttr>(constAttr).getType();
632 bool isConstant = true;
633
634 std::string name;
635 if (d.hasGlobalStorage())
636 name = getMangledName(&d).str() + ".const";
637 else if (const DeclContext *dc = d.getParentFunctionOrMethod())
638 name = ("__const." + functionName(dc) + "." + d.getName()).str();
639 else
640 llvm_unreachable("local variable has no parent function or method");
641
643 cir::GlobalOp gv = builder.createVersionedGlobal(
644 getModule(), getLoc(d.getLocation()), name, ty, isConstant,
645 cir::GlobalLinkageKind::PrivateLinkage);
647 // TODO(cir): infer visibility from linkage in global op builder.
648 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(
649 cir::GlobalLinkageKind::PrivateLinkage));
650 gv.setInitialValueAttr(constAttr);
651 gv.setAlignment(align.getAsAlign().value());
652 // TODO(cir): Set unnamed address attribute when available in CIR
653
654 cacheEntry = gv;
655 } else if (cacheEntry.getAlignment() < align.getQuantity()) {
656 cacheEntry.setAlignment(align.getAsAlign().value());
657 }
658
659 // Create a GetGlobalOp to get a pointer to the global
661 mlir::Type eltTy = mlir::cast<mlir::TypedAttr>(constAttr).getType();
662 auto ptrTy = builder.getPointerTo(cacheEntry.getSymType());
663 mlir::Value globalPtr = cir::GetGlobalOp::create(
664 builder, getLoc(d.getLocation()), ptrTy, cacheEntry.getSymName());
665 return Address(globalPtr, eltTy, align);
666}
667
668/// Add the initializer for 'd' to the global variable that has already been
669/// created for it. If the initializer has a different type than gv does, this
670/// may free gv and return a different one. Otherwise it just returns gv.
672 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
673 ConstantEmitter emitter(*this);
674 mlir::TypedAttr init = mlir::dyn_cast_if_present<mlir::TypedAttr>(
675 emitter.tryEmitForInitializer(d));
676
677 // If constant emission failed, then this should be a C++ static
678 // initializer.
679 if (!init) {
680 if (!getLangOpts().CPlusPlus) {
681 cgm.errorNYI(d.getInit()->getSourceRange(),
682 "constant l-value expression");
683 } else if (d.hasFlexibleArrayInit(getContext())) {
684 cgm.errorNYI(d.getInit()->getSourceRange(), "flexible array initializer");
685 } else {
686 // Since we have a static initializer, this global variable can't
687 // be constant.
688 gv.setConstant(false);
689 emitCXXGuardedInit(d, gv, /*performInit*/ true);
690 gvAddr.setStaticLocal(true);
691 }
692 return gv;
693 }
694
695 // TODO(cir): There should be debug code here to assert that the decl size
696 // matches the CIR data layout type alloc size, but the code for calculating
697 // the type alloc size is not implemented yet.
699
700 // The initializer may differ in type from the global. Rewrite
701 // the global to match the initializer. (We have to do this
702 // because some types, like unions, can't be completely represented
703 // in the LLVM type system.)
704 if (gv.getSymType() != init.getType()) {
705 gv.setSymType(init.getType());
706
707 // Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),
708 // but since at this point the current block hasn't been really attached,
709 // there's no visibility into the GetGlobalOp corresponding to this Global.
710 // Given those constraints, thread in the GetGlobalOp and update it
711 // directly.
713 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
714 }
715
716 bool needsDtor =
718
719 gv.setConstant(d.getType().isConstantStorage(
720 getContext(), /*ExcludeCtor=*/true, !needsDtor));
721 gv.setInitialValueAttr(init);
722
723 emitter.finalize(gv);
724
725 if (needsDtor) {
726 // We have a constant initializer, but a nontrivial destructor. We still
727 // need to perform a guarded "initialization" in order to register the
728 // destructor.
729 emitCXXGuardedInit(d, gv, /*performInit=*/false);
730 gvAddr.setStaticLocal(true);
731 }
732
733 return gv;
734}
735
737 cir::GlobalLinkageKind linkage) {
738 // Check to see if we already have a global variable for this
739 // declaration. This can happen when double-emitting function
740 // bodies, e.g. with complete and base constructors.
741 cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);
742 // TODO(cir): we should have a way to represent global ops as values without
743 // having to emit a get global op. Sometimes these emissions are not used.
744 mlir::Value addr =
745 builder.createGetGlobal(globalOp, d.getTLSKind() != VarDecl::TLS_None);
746 auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
747 assert(getAddrOp && "expected cir::GetGlobalOp");
748
749 CharUnits alignment = getContext().getDeclAlign(&d);
750
751 // Store into LocalDeclMap before generating initializer to handle
752 // circular references.
753 mlir::Type elemTy = convertTypeForMem(d.getType());
754 setAddrOfLocalVar(&d, Address(addr, elemTy, alignment));
755
756 // We can't have a VLA here, but we can have a pointer to a VLA,
757 // even though that doesn't really make any sense.
758 // Make sure to evaluate VLA bounds now so that we have them for later.
761
762 // Save the type in case adding the initializer forces a type change.
763 mlir::Type expectedType = addr.getType();
764
765 cir::GlobalOp var = globalOp;
766
768
769 // If this value has an initializer, emit it.
770 if (d.getInit())
771 var = addInitializerToStaticVarDecl(d, var, getAddrOp);
772
773 var.setAlignment(alignment.getAsAlign().value());
774
775 // There are a lot of attributes that need to be handled here. Until
776 // we start to support them, we just report an error if there are any.
777 if (d.hasAttr<AnnotateAttr>())
778 cgm.addGlobalAnnotations(&d, var);
779 if (d.getAttr<PragmaClangBSSSectionAttr>())
780 cgm.errorNYI(d.getSourceRange(),
781 "emitStaticVarDecl: CIR global BSS section attribute");
782 if (d.getAttr<PragmaClangDataSectionAttr>())
783 cgm.errorNYI(d.getSourceRange(),
784 "emitStaticVarDecl: CIR global Data section attribute");
785 if (d.getAttr<PragmaClangRodataSectionAttr>())
786 cgm.errorNYI(d.getSourceRange(),
787 "emitStaticVarDecl: CIR global Rodata section attribute");
788 if (d.getAttr<PragmaClangRelroSectionAttr>())
789 cgm.errorNYI(d.getSourceRange(),
790 "emitStaticVarDecl: CIR global Relro section attribute");
791
792 if (const SectionAttr *sa = d.getAttr<SectionAttr>())
793 var.setSectionAttr(builder.getStringAttr(sa->getName()));
794
795 if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)
796 cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");
797
798 // From traditional codegen:
799 // We may have to cast the constant because of the initializer
800 // mismatch above.
801 //
802 // FIXME: It is really dangerous to store this in the map; if anyone
803 // RAUW's the GV uses of this constant will be invalid.
804 mlir::Value castedAddr =
805 builder.createBitcast(getAddrOp.getAddr(), expectedType);
806 localDeclMap.find(&d)->second = Address(castedAddr, elemTy, alignment);
807 cgm.setStaticLocalDeclAddress(&d, var);
808
811}
812
813void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
814 LValue lvalue, bool capturedByInit) {
816
817 SourceLocRAIIObject locRAII{*this, loc};
818 mlir::Value value = emitScalarExpr(init);
819 if (capturedByInit) {
820 cgm.errorNYI(init->getSourceRange(), "emitScalarInit: captured by init");
821 return;
822 }
824 emitStoreThroughLValue(RValue::get(value), lvalue, true);
825}
826
828 LValue lvalue, bool capturedByInit) {
829 SourceLocRAIIObject loc{*this, getLoc(init->getSourceRange())};
830 if (capturedByInit) {
831 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
832 return;
833 }
834
835 QualType type = d->getType();
836
837 if (type->isReferenceType()) {
838 RValue rvalue = emitReferenceBindingToExpr(init);
839 if (capturedByInit)
840 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
841 emitStoreThroughLValue(rvalue, lvalue);
842 return;
843 }
845 case cir::TEK_Scalar:
846 emitScalarInit(init, getLoc(d->getSourceRange()), lvalue);
847 return;
848 case cir::TEK_Complex: {
849 mlir::Value complex = emitComplexExpr(init);
850 if (capturedByInit)
851 cgm.errorNYI(init->getSourceRange(),
852 "emitExprAsInit: complex type captured by init");
853 mlir::Location loc = getLoc(init->getExprLoc());
854 emitStoreOfComplex(loc, complex, lvalue,
855 /*isInit*/ true);
856 return;
857 }
859 // The overlap flag here should be calculated.
861 emitAggExpr(init,
865 return;
866 }
867 llvm_unreachable("bad evaluation kind");
868}
869
870void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) {
871 switch (d.getKind()) {
872 case Decl::BuiltinTemplate:
873 case Decl::TranslationUnit:
874 case Decl::ExternCContext:
875 case Decl::Namespace:
876 case Decl::UnresolvedUsingTypename:
877 case Decl::ClassTemplateSpecialization:
878 case Decl::ClassTemplatePartialSpecialization:
879 case Decl::VarTemplateSpecialization:
880 case Decl::VarTemplatePartialSpecialization:
881 case Decl::TemplateTypeParm:
882 case Decl::UnresolvedUsingValue:
883 case Decl::NonTypeTemplateParm:
884 case Decl::CXXDeductionGuide:
885 case Decl::CXXMethod:
886 case Decl::CXXConstructor:
887 case Decl::CXXDestructor:
888 case Decl::CXXConversion:
889 case Decl::Field:
890 case Decl::MSProperty:
891 case Decl::IndirectField:
892 case Decl::ObjCIvar:
893 case Decl::ObjCAtDefsField:
894 case Decl::ParmVar:
895 case Decl::ImplicitParam:
896 case Decl::ClassTemplate:
897 case Decl::VarTemplate:
898 case Decl::FunctionTemplate:
899 case Decl::TypeAliasTemplate:
900 case Decl::TemplateTemplateParm:
901 case Decl::ObjCMethod:
902 case Decl::ObjCCategory:
903 case Decl::ObjCProtocol:
904 case Decl::ObjCInterface:
905 case Decl::ObjCCategoryImpl:
906 case Decl::ObjCImplementation:
907 case Decl::ObjCProperty:
908 case Decl::ObjCCompatibleAlias:
909 case Decl::PragmaComment:
910 case Decl::PragmaDetectMismatch:
911 case Decl::AccessSpec:
912 case Decl::LinkageSpec:
913 case Decl::Export:
914 case Decl::ObjCPropertyImpl:
915 case Decl::FileScopeAsm:
916 case Decl::Friend:
917 case Decl::FriendTemplate:
918 case Decl::Block:
919 case Decl::OutlinedFunction:
920 case Decl::Captured:
921 case Decl::UsingShadow:
922 case Decl::ConstructorUsingShadow:
923 case Decl::ObjCTypeParam:
924 case Decl::Binding:
925 case Decl::UnresolvedUsingIfExists:
926 case Decl::HLSLBuffer:
927 case Decl::HLSLRootSignature:
928 llvm_unreachable("Declaration should not be in declstmts!");
929
930 case Decl::Function: // void X();
931 case Decl::EnumConstant: // enum ? { X = ? }
932 case Decl::ExplicitInstantiation:
933 case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
934 case Decl::Label: // __label__ x;
935 case Decl::Import:
936 case Decl::MSGuid: // __declspec(uuid("..."))
937 case Decl::TemplateParamObject:
938 case Decl::Empty:
939 case Decl::Concept:
940 case Decl::LifetimeExtendedTemporary:
941 case Decl::RequiresExprBody:
942 case Decl::UnnamedGlobalConstant:
943 // None of these decls require codegen support.
944 return;
945
946 case Decl::Enum: // enum X;
947 case Decl::Record: // struct/union/class X;
948 case Decl::CXXRecord: // struct/union/class X; [C++]
949 case Decl::NamespaceAlias:
950 case Decl::Using: // using X; [C++]
951 case Decl::UsingEnum: // using enum X; [C++]
952 case Decl::UsingDirective: // using namespace X; [C++]
954 return;
955 case Decl::Var:
956 case Decl::Decomposition: {
957 const VarDecl &vd = cast<VarDecl>(d);
958 assert(vd.isLocalVarDecl() &&
959 "Should not see file-scope variables inside a function!");
960 emitVarDecl(vd);
961 if (evaluateConditionDecl)
963 return;
964 }
965 case Decl::OpenACCDeclare:
967 return;
968 case Decl::OpenACCRoutine:
970 return;
971 case Decl::OMPThreadPrivate:
973 return;
974 case Decl::OMPGroupPrivate:
976 return;
977 case Decl::OMPAllocate:
979 return;
980 case Decl::OMPCapturedExpr:
982 return;
983 case Decl::OMPRequires:
985 return;
986 case Decl::OMPDeclareMapper:
988 return;
989 case Decl::OMPDeclareReduction:
991 return;
992 case Decl::Typedef: // typedef int X;
993 case Decl::TypeAlias: { // using X = int; [C++0x]
994 QualType ty = cast<TypedefNameDecl>(d).getUnderlyingType();
996 if (ty->isVariablyModifiedType())
998 return;
999 }
1000 case Decl::ImplicitConceptSpecialization:
1001 case Decl::TopLevelStmt:
1002 case Decl::UsingPack:
1003 case Decl::CXXExpansionStmt:
1004 cgm.errorNYI(d.getSourceRange(),
1005 std::string("emitDecl: unhandled decl type: ") +
1006 d.getDeclKindName());
1007 }
1008}
1009
1011 SourceLocation loc) {
1012 if (!sanOpts.has(SanitizerKind::NullabilityAssign))
1013 return;
1014
1016}
1017
1018namespace {
1019struct DestroyObject final : EHScopeStack::Cleanup {
1020 DestroyObject(Address addr, QualType type,
1021 CIRGenFunction::Destroyer *destroyer)
1022 : addr(addr), type(type), destroyer(destroyer) {
1024 }
1025
1026 Address addr;
1027 QualType type;
1028 CIRGenFunction::Destroyer *destroyer;
1029
1030 void emit(CIRGenFunction &cgf, Flags flags) override {
1032 cgf.emitDestroy(addr, type, destroyer);
1033 }
1034};
1035
1036template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup {
1037 DestroyNRVOVariable(Address addr, QualType type, mlir::Value nrvoFlag)
1038 : nrvoFlag(nrvoFlag), addr(addr), ty(type) {}
1039
1040 mlir::Value nrvoFlag;
1041 Address addr;
1042 QualType ty;
1043
1044 void emit(CIRGenFunction &cgf, Flags flags) override {
1045 // Along the exceptions path we always execute the dtor.
1046 bool nrvo = flags.isForNormalCleanup() && nrvoFlag;
1047
1048 CIRGenBuilderTy &builder = cgf.getBuilder();
1049 mlir::OpBuilder::InsertionGuard guard(builder);
1050 if (nrvo) {
1051 // If we exited via NRVO, we skip the destructor call.
1052 mlir::Location loc = addr.getPointer().getLoc();
1053 mlir::Value didNRVO = builder.createFlagLoad(loc, nrvoFlag);
1054 mlir::Value notNRVO = builder.createNot(didNRVO);
1055 cir::IfOp::create(builder, loc, notNRVO, /*withElseRegion=*/false,
1056 [&](mlir::OpBuilder &b, mlir::Location) {
1057 static_cast<Derived *>(this)->emitDestructorCall(cgf);
1058 builder.createYield(loc);
1059 });
1060 } else {
1061 static_cast<Derived *>(this)->emitDestructorCall(cgf);
1062 }
1063 }
1064
1065 virtual ~DestroyNRVOVariable() = default;
1066};
1067
1068struct DestroyNRVOVariableCXX final
1069 : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
1070 DestroyNRVOVariableCXX(Address addr, QualType type,
1071 const CXXDestructorDecl *dtor, mlir::Value nrvoFlag)
1072 : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, nrvoFlag),
1073 dtor(dtor) {}
1074
1075 const CXXDestructorDecl *dtor;
1076
1077 void emitDestructorCall(CIRGenFunction &cgf) {
1079 /*forVirtualBase=*/false,
1080 /*delegating=*/false, addr, ty);
1081 }
1082};
1083
1084struct CallStackRestore final : EHScopeStack::Cleanup {
1085 Address stack;
1086 CallStackRestore(Address stack) : stack(stack) {}
1087 void emit(CIRGenFunction &cgf, Flags flags) override {
1088 mlir::Location loc = stack.getPointer().getLoc();
1089 mlir::Value v = cgf.getBuilder().createLoad(loc, stack);
1090 cgf.getBuilder().createStackRestore(loc, v);
1091 }
1092};
1093
1094/// A cleanup which performs a partial array destroy where the end pointer is
1095/// irregularly determined and must be loaded from a local.
1096struct IrregularPartialArrayDestroy final : EHScopeStack::Cleanup {
1097 mlir::Value arrayBegin;
1098 Address arrayEndPointer;
1099 QualType elementType;
1100 CharUnits elementAlign;
1101 CIRGenFunction::Destroyer *destroyer;
1102
1103 IrregularPartialArrayDestroy(mlir::Value arrayBegin, Address arrayEndPointer,
1104 QualType elementType, CharUnits elementAlign,
1105 CIRGenFunction::Destroyer *destroyer)
1106 : arrayBegin(arrayBegin), arrayEndPointer(arrayEndPointer),
1107 elementType(elementType), elementAlign(elementAlign),
1108 destroyer(destroyer) {}
1109
1110 void emit(CIRGenFunction &cgf, Flags flags) override {
1111 CIRGenBuilderTy &builder = cgf.getBuilder();
1112 mlir::Location loc = arrayBegin.getLoc();
1113
1114 mlir::Value arrayEnd = builder.createLoad(loc, arrayEndPointer);
1115
1116 // baseElementType gets us the final 'element' type, which should be the
1117 // RecordType, looking through any multi-dimension arrays.
1118 QualType baseElementType = cgf.getContext().getBaseElementType(elementType);
1119
1120 mlir::Type cirElementType = cgf.convertTypeForMem(baseElementType);
1121 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
1122
1123 mlir::Value begin = arrayBegin;
1124 if (baseElementType != elementType) {
1125 begin = builder.createPtrBitcast(begin, cirElementType);
1126 arrayEnd = builder.createPtrBitcast(arrayEnd, cirElementType);
1127 }
1128
1129 // The cleanup is destroying elements in reverse from arrayEnd back to
1130 // begin, but only if arrayEnd != begin (i.e. something was
1131 // constructed).
1132 mlir::Value ne =
1133 cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne, arrayEnd, begin);
1134 cir::IfOp::create(
1135 builder, loc, ne, /*withElseRegion=*/false,
1136 [&](mlir::OpBuilder &b, mlir::Location loc) {
1137 Address iterAddr = cgf.createTempAlloca(
1138 ptrToElmType, cgf.getPointerAlign(), loc, "__array_idx");
1139 builder.createStore(loc, arrayEnd, iterAddr);
1140 builder.createDoWhile(
1141 loc,
1142 /*condBuilder=*/
1143 [&](mlir::OpBuilder &b, mlir::Location loc) {
1144 mlir::Value cur = builder.createLoad(loc, iterAddr);
1145 mlir::Value cmp = cir::CmpOp::create(
1146 builder, loc, cir::CmpOpKind::ne, cur, begin);
1147 builder.createCondition(cmp);
1148 },
1149 /*bodyBuilder=*/
1150 [&](mlir::OpBuilder &b, mlir::Location loc) {
1151 mlir::Value cur = builder.createLoad(loc, iterAddr);
1152 cir::ConstantOp negOne = builder.getConstInt(
1153 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), -1);
1154 mlir::Value prev = cir::PtrStrideOp::create(
1155 builder, loc, ptrToElmType, cur, negOne);
1156 builder.createStore(loc, prev, iterAddr);
1157 Address elemAddr = Address(prev, cirElementType, elementAlign);
1158 destroyer(cgf, elemAddr, baseElementType);
1159 builder.createYield(loc);
1160 });
1161 builder.createYield(loc);
1162 });
1163 }
1164};
1165} // namespace
1166
1167/// Push an EH cleanup to destroy already-constructed elements of the given
1168/// array. The cleanup may be popped with deactivateCleanupBlock or
1169/// popCleanupBlock.
1170///
1171/// \param elementType - the immediate element type of the array;
1172/// possibly still an array type
1174 Address arrayEndPointer,
1175 QualType elementType,
1176 CharUnits elementAlign,
1177 Destroyer *destroyer) {
1178 ehStack.pushCleanup<IrregularPartialArrayDestroy>(
1179 EHCleanup, arrayBegin, arrayEndPointer, elementType, elementAlign,
1180 destroyer);
1181}
1182
1183/// pushEHDestroyIfNeeded - Push the standard destructor for the given type as
1184/// an EH-only cleanup. If EH cleanup is not needed, just return.
1186 Address addr, QualType type) {
1187 if (!needsEHCleanup(dtorKind))
1188 return;
1189
1191 pushDestroy(EHCleanup, addr, type, getDestroyer(dtorKind));
1192}
1193
1194/// Push the standard destructor for the given type as
1195/// at least a normal cleanup.
1197 Address addr, QualType type) {
1198 assert(dtorKind && "cannot push destructor for trivial type");
1199
1200 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1201 pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind));
1202}
1203
1205 QualType type, Destroyer *destroyer) {
1206 pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
1207}
1208
1211 assert(dtorKind && "cannot push destructor for trivial type");
1212
1213 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1215 cleanupKind, addr, type, getDestroyer(dtorKind), cleanupKind & EHCleanup);
1216}
1217
1219 CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer,
1220 bool useEHCleanupForArray) {
1223 destroyer);
1224}
1225
1227 Address addr, QualType type,
1228 Destroyer *destroyer,
1229 bool useEHCleanupForArray) {
1230 if (isInConditionalBranch()) {
1231 cgm.errorNYI("conditional lifetime-extended destroy");
1232 return;
1233 }
1234
1235 // Add the cleanup to the EHStack. After the full-expr, this would be
1236 // deactivated before being popped from the stack.
1237 pushDestroyAndDeferDeactivation(cleanupKind, addr, type, destroyer,
1238 useEHCleanupForArray);
1239
1241
1242 pushCleanupAfterFullExpr(cleanupKind, addr, type, destroyer);
1243}
1244
1246 const PendingCleanupEntry &entry) {
1247 ehStack.pushCleanup<DestroyObject>(entry.kind, entry.addr, entry.type,
1248 entry.destroyer);
1249
1250 if (entry.activeFlag.isValid()) {
1251 EHCleanupScope &scope = cast<EHCleanupScope>(*ehStack.begin());
1252 scope.setActiveFlag(entry.activeFlag);
1254 scope.setTestFlagInEHCleanup(scope.isEHCleanup());
1255 }
1256}
1257
1258/// Destroys all the elements of the given array, beginning from last to first.
1259///
1260/// \param begin - a type* denoting the first element of the array
1261/// \param numElements - the number of elements in the array
1262/// \param elementType - the element type of the array
1263/// \param destroyer - the function to call to destroy elements
1265 mlir::Value numElements,
1266 QualType elementType,
1267 CharUnits elementAlign,
1268 Destroyer *destroyer) {
1269 assert(!elementType->isArrayType());
1270
1271 // Differently from LLVM traditional codegen, use a higher level
1272 // representation instead of lowering directly to a loop.
1273 mlir::Type cirElementType = convertTypeForMem(elementType);
1274 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
1275
1276 auto regionBuilder = [&](mlir::OpBuilder &b, mlir::Location loc) {
1277 mlir::BlockArgument arg =
1278 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
1279 Address curAddr = Address(arg, cirElementType, elementAlign);
1281
1282 // Perform the actual destruction there.
1283 destroyer(*this, curAddr, elementType);
1284
1285 cir::YieldOp::create(b, loc);
1286 };
1287
1288 // For a constant array size, use the static form of ArrayDtor.
1289 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
1290 uint64_t size = 0;
1291 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())
1292 size = constIntAttr.getUInt();
1293 auto arrayTy = cir::ArrayType::get(cirElementType, size);
1294 mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);
1295 cir::ArrayDtor::create(builder, *currSrcLoc, arrayOp, regionBuilder);
1296 return;
1297 }
1298
1299 // For a dynamic array size (VLA), use the dynamic form of ArrayDtor.
1300 mlir::Value elemBegin = builder.createPtrBitcast(begin, cirElementType);
1301 cir::ArrayDtor::create(builder, *currSrcLoc, elemBegin, numElements,
1302 regionBuilder);
1303}
1304
1305/// Immediately perform the destruction of the given object.
1306///
1307/// \param addr - the address of the object; a type*
1308/// \param type - the type of the object; if an array type, all
1309/// objects are destroyed in reverse order
1310/// \param destroyer - the function to call to destroy individual
1311/// elements
1313 Destroyer *destroyer) {
1315 if (!arrayType)
1316 return destroyer(*this, addr, type);
1317
1318 mlir::Value length = emitArrayLength(arrayType, type, addr);
1319
1320 CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement(
1321 getContext().getTypeSizeInChars(type));
1322
1323 // If the array length is constant, we can check for zero at compile time.
1324 auto constantCount = length.getDefiningOp<cir::ConstantOp>();
1325 if (constantCount) {
1326 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
1327 if (constIntAttr && constIntAttr.getUInt() == 0)
1328 return;
1329 }
1330
1331 mlir::Value begin = addr.getPointer();
1333 emitArrayDestroy(begin, length, type, elementAlign, destroyer);
1334
1335 // If the array destroy didn't use the length op, we can erase it.
1336 if (constantCount && constantCount.use_empty())
1337 constantCount.erase();
1338}
1339
1342 switch (kind) {
1343 case QualType::DK_none:
1344 llvm_unreachable("no destroyer for trivial dtor");
1346 return destroyCXXObject;
1350 cgm.errorNYI("getDestroyer: other destruction kind");
1351 return nullptr;
1352 }
1353 llvm_unreachable("Unknown DestructionKind");
1354}
1355
1357 ehStack.pushCleanup<CallStackRestore>(kind, spMem);
1358}
1359
1360/// Enter a destroy cleanup for the given local variable.
1362 const CIRGenFunction::AutoVarEmission &emission,
1363 QualType::DestructionKind dtorKind) {
1364 assert(dtorKind != QualType::DK_none);
1365
1366 // Note that for __block variables, we want to destroy the
1367 // original stack object, not the possibly forwarded object.
1368 Address addr = emission.getObjectAddress(*this);
1369
1370 const VarDecl *var = emission.variable;
1371 QualType type = var->getType();
1372
1373 CleanupKind cleanupKind = NormalAndEHCleanup;
1374 CIRGenFunction::Destroyer *destroyer = nullptr;
1375
1376 switch (dtorKind) {
1377 case QualType::DK_none:
1378 llvm_unreachable("no cleanup for trivially-destructible variable");
1379
1381 // If there's an NRVO flag on the emission, we need a different
1382 // cleanup.
1383 if (emission.nrvoFlag) {
1384 assert(!type->isArrayType());
1385 CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
1386 ehStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, type, dtor,
1387 emission.nrvoFlag);
1388 return;
1389 }
1390 // Otherwise, this is handled below.
1391 break;
1392
1396 cgm.errorNYI(var->getSourceRange(),
1397 "emitAutoVarTypeCleanup: other dtor kind");
1398 return;
1399 }
1400
1401 // If we haven't chosen a more specific destroyer, use the default.
1402 if (!destroyer)
1403 destroyer = getDestroyer(dtorKind);
1404
1406 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
1407}
1408
1410 if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
1411 for (auto *b : dd->flat_bindings())
1412 if (auto *hd = b->getHoldingVar())
1413 emitVarDecl(*hd);
1414 }
1415}
1416
1417bool CIRGenFunction::emitLifetimeStartOp(mlir::Location loc, mlir::Value addr) {
1418 if (!shouldEmitLifetimeMarkers)
1419 return false;
1420
1421 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1423 "Pointer should be in alloca address space");
1424
1425 cir::LifetimeStartOp::create(builder, loc, addr);
1426 return true;
1427}
1428
1429void CIRGenFunction::emitLifetimeEndOp(mlir::Location loc, mlir::Value addr) {
1430 if (!shouldEmitLifetimeMarkers)
1431 return;
1432
1433 assert(mlir::cast<cir::PointerType>(addr.getType()).getAddrSpace() ==
1435 "Pointer should be in alloca address space");
1436
1437 cir::LifetimeEndOp::create(builder, loc, addr);
1438}
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 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
Definition ASTContext.h:985
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:3836
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:157
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 a loop's condition variable so that they can be emitted into the loop op's per-...
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.
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 emitLoopConditionVariable(const clang::VarDecl &d, DeferredLoopConditionCleanup &condCleanup)
Emit a loop's condition-variable declaration.
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.
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)
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.
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
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)
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...
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)
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.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
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 ...
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
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)
mlir::Type convertType(clang::QualType type)
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)
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)
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.
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:1552
Represents a C++ constructor within a class.
Definition DeclCXX.h:2641
Represents a C++ destructor within a class.
Definition DeclCXX.h:2906
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
Definition CharUnits.h:189
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
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:214
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
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
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:3380
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
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
const Decl * getDecl() const
Definition GlobalDecl.h:115
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:8627
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:2820
Represents a struct/union/class.
Definition Decl.h:4460
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:2549
bool isArrayType() const
Definition TypeBase.h:8837
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2877
bool isVectorType() const
Definition TypeBase.h:8877
bool isSamplerT() const
Definition TypeBase.h:8982
bool isRecordType() const
Definition TypeBase.h:8865
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:2150
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2172
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2834
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:2468
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:2823
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:2683
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
@ SD_Automatic
Automatic storage duration (most local variables).
Definition Specifiers.h:340
@ 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)
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 cudaSupport()
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.
A cleanup entry that will be promoted onto the EH scope stack at a later point.
clang::CharUnits getPointerAlign() const
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const