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