clang 22.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
14#include "CIRGenFunction.h"
15#include "mlir/IR/Location.h"
16#include "clang/AST/Attr.h"
17#include "clang/AST/Decl.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExprCXX.h"
22
23using namespace clang;
24using namespace clang::CIRGen;
25
28 mlir::OpBuilder::InsertPoint ip) {
29 QualType ty = d.getType();
31 cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: address space");
32
33 mlir::Location loc = getLoc(d.getSourceRange());
34 bool nrvo =
35 getContext().getLangOpts().ElideConstructors && d.isNRVOVariable();
36
38 emission.isEscapingByRef = d.isEscapingByref();
39 if (emission.isEscapingByRef)
40 cgm.errorNYI(d.getSourceRange(),
41 "emitAutoVarDecl: decl escaping by reference");
42
43 CharUnits alignment = getContext().getDeclAlign(&d);
44
45 // If the type is variably-modified, emit all the VLA sizes for it.
46 if (ty->isVariablyModifiedType())
48
50
51 Address address = Address::invalid();
52 if (ty->isConstantSizeType()) {
53 // If this value is an array, struct, or vector with a statically
54 // determinable constant initializer, there are optimizations we can do.
55 //
56 // TODO: We should constant-evaluate the initializer of any variable,
57 // as long as it is initialized by a constant expression. Currently,
58 // isConstantInitializer produces wrong answers for structs with
59 // reference or bitfield members, and a few other cases, and checking
60 // for POD-ness protects us from some of these.
61 if (d.getInit() &&
62 (ty->isArrayType() || ty->isRecordType() || ty->isVectorType()) &&
63 (d.isConstexpr() ||
64 ((ty.isPODType(getContext()) ||
65 getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&
66 d.getInit()->isConstantInitializer(getContext(), false)))) {
67
68 // If the variable's a const type, and it's neither an NRVO
69 // candidate nor a __block variable and has no mutable members,
70 // emit it as a global instead.
71 // Exception is if a variable is located in non-constant address space
72 // in OpenCL.
73 // TODO(cir): perhaps we don't need this at all at CIR since this can
74 // be done as part of lowering down to LLVM.
75 bool needsDtor =
77 if ((!getContext().getLangOpts().OpenCL ||
79 (cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&
80 !d.isEscapingByref() &&
81 ty.isConstantStorage(getContext(), true, !needsDtor))) {
82 cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: type constant");
83 }
84 // Otherwise, tell the initialization code that we're in this case.
85 emission.isConstantAggregate = true;
86 }
87
88 // A normal fixed sized variable becomes an alloca in the entry block,
89 // unless:
90 // - it's an NRVO variable.
91 // - we are compiling OpenMP and it's an OpenMP local variable.
92 if (nrvo) {
93 // The named return value optimization: allocate this variable in the
94 // return slot, so that we can elide the copy when returning this
95 // variable (C++0x [class.copy]p34).
96 address = returnValue;
97
98 if (const RecordDecl *rd = ty->getAsRecordDecl()) {
99 if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
100 (cxxrd && !cxxrd->hasTrivialDestructor()) ||
101 rd->isNonTrivialToPrimitiveDestroy())
102 cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: set NRVO flag");
103 }
104 } else {
105 // A normal fixed sized variable becomes an alloca in the entry block,
106 mlir::Type allocaTy = convertTypeForMem(ty);
107 // Create the temp alloca and declare variable using it.
108 address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
109 /*arraySize=*/nullptr, /*alloca=*/nullptr, ip);
110 declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()),
111 alignment);
112 }
113 } else {
114 // Non-constant size type
116 if (!didCallStackSave) {
117 // Save the stack.
118 cir::PointerType defaultTy = allocaInt8PtrTy;
120 cgm.getDataLayout().getAlignment(defaultTy, false));
121 Address stack = createTempAlloca(defaultTy, align, loc, "saved_stack");
122
123 mlir::Value v = builder.createStackSave(loc, defaultTy);
124 assert(v.getType() == allocaInt8PtrTy);
125 builder.createStore(loc, v, stack);
126
127 didCallStackSave = true;
128
129 // Push a cleanup block and restore the stack there.
130 // FIXME: in general circumstances, this should be an EH cleanup.
132 }
133
134 VlaSizePair vlaSize = getVLASize(ty);
135 mlir::Type memTy = convertTypeForMem(vlaSize.type);
136
137 // Allocate memory for the array.
138 address =
139 createTempAlloca(memTy, alignment, loc, d.getName(), vlaSize.numElts,
140 /*alloca=*/nullptr, builder.saveInsertionPoint());
141
142 // If we have debug info enabled, properly describe the VLA dimensions for
143 // this type by registering the vla size expression for each of the
144 // dimensions.
146 }
147
148 emission.addr = address;
149 setAddrOfLocalVar(&d, address);
150
151 return emission;
152}
153
154/// Determine whether the given initializer is trivial in the sense
155/// that it requires no code to be generated.
157 if (!init)
158 return true;
159
160 if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(init))
161 if (CXXConstructorDecl *constructor = construct->getConstructor())
162 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
163 !construct->requiresZeroInitialization())
164 return true;
165
166 return false;
167}
168
169static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d,
170 Address addr, bool isVolatile,
171 CIRGenBuilderTy &builder,
172 mlir::TypedAttr constant) {
173 mlir::Type ty = constant.getType();
174 cir::CIRDataLayout layout{cgm.getModule()};
175 uint64_t constantSize = layout.getTypeAllocSize(ty);
176 if (!constantSize)
177 return;
184 // In CIR we want to emit a store for the whole thing, later lowering
185 // prepare to LLVM should unwrap this into the best policy (see asserts
186 // above).
187 //
188 // FIXME(cir): This is closer to memcpy behavior but less optimal, instead of
189 // copy from a global, we just create a cir.const out of it.
190
191 if (addr.getElementType() != ty)
192 addr = addr.withElementType(builder, ty);
193
194 // If the address is an alloca, set the init attribute.
195 // The address is usually and alloca, but there is at least one case where
196 // emitAutoVarInit is called from the OpenACC codegen with an address that
197 // is not an alloca.
198 auto allocaOp = addr.getDefiningOp<cir::AllocaOp>();
199 if (allocaOp)
200 allocaOp.setInitAttr(mlir::UnitAttr::get(&cgm.getMLIRContext()));
201
202 // There are cases where OpenACC codegen calls emitAutoVarInit with a
203 // temporary decl that doesn't have a source range set.
204 mlir::Location loc = builder.getUnknownLoc();
205 if (d.getSourceRange().isValid())
206 loc = cgm.getLoc(d.getSourceRange());
207 builder.createStore(loc, builder.getConstant(loc, constant), addr);
208}
209
211 const CIRGenFunction::AutoVarEmission &emission) {
212 assert(emission.variable && "emission was not valid!");
213
214 // If this was emitted as a global constant, we're done.
215 if (emission.wasEmittedAsGlobal())
216 return;
217
218 const VarDecl &d = *emission.variable;
219
220 QualType type = d.getType();
221
222 // If this local has an initializer, emit it now.
223 const Expr *init = d.getInit();
224
225 // Initialize the variable here if it doesn't have a initializer and it is a
226 // C struct that is non-trivial to initialize or an array containing such a
227 // struct.
228 if (!init && type.isNonTrivialToPrimitiveDefaultInitialize() ==
230 cgm.errorNYI(d.getSourceRange(),
231 "emitAutoVarInit: non-trivial to default initialize");
232 return;
233 }
234
235 const Address addr = emission.addr;
236
237 // Check whether this is a byref variable that's potentially
238 // captured and moved by its own initializer. If so, we'll need to
239 // emit the initializer first, then copy into the variable.
241
242 // Note: constexpr already initializes everything correctly.
243 LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
244 (d.isConstexpr()
246 : (d.getAttr<UninitializedAttr>()
248 : getContext().getLangOpts().getTrivialAutoVarInit()));
249
250 auto initializeWhatIsTechnicallyUninitialized = [&](Address addr) {
251 if (trivialAutoVarInit ==
253 return;
254
255 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: trivial initialization");
256 };
257
258 if (isTrivialInitializer(init)) {
259 initializeWhatIsTechnicallyUninitialized(addr);
260 return;
261 }
262
263 mlir::Attribute constant;
264 if (emission.isConstantAggregate ||
266 // FIXME: Differently from LLVM we try not to emit / lower too much
267 // here for CIR since we are interested in seeing the ctor in some
268 // analysis later on. So CIR's implementation of ConstantEmitter will
269 // frequently return an empty Attribute, to signal we want to codegen
270 // some trivial ctor calls and whatnots.
272 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
273 (trivialAutoVarInit !=
275 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: constant aggregate");
276 return;
277 }
278 }
279
280 // NOTE(cir): In case we have a constant initializer, we can just emit a
281 // store. But, in CIR, we wish to retain any ctor calls, so if it is a
282 // CXX temporary object creation, we ensure the ctor call is used deferring
283 // its removal/optimization to the CIR lowering.
284 if (!constant || isa<CXXTemporaryObjectExpr>(init)) {
285 initializeWhatIsTechnicallyUninitialized(addr);
287 emitExprAsInit(init, &d, lv);
288
289 if (!emission.wasEmittedAsOffloadClause()) {
290 // In case lv has uses it means we indeed initialized something
291 // out of it while trying to build the expression, mark it as such.
292 mlir::Value val = lv.getAddress().getPointer();
293 assert(val && "Should have an address");
294 auto allocaOp = val.getDefiningOp<cir::AllocaOp>();
295 assert(allocaOp && "Address should come straight out of the alloca");
296
297 if (!allocaOp.use_empty())
298 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
299 }
300
301 return;
302 }
303
304 // FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.
305 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
306 assert(typedConstant && "expected typed attribute");
307 if (!emission.isConstantAggregate) {
308 // For simple scalar/complex initialization, store the value directly.
309 LValue lv = makeAddrLValue(addr, type);
310 assert(init && "expected initializer");
311 mlir::Location initLoc = getLoc(init->getSourceRange());
312 // lv.setNonGC(true);
314 RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
315 }
316
317 emitStoresForConstant(cgm, d, addr, type.isVolatileQualified(), builder,
318 typedConstant);
319}
320
322 const CIRGenFunction::AutoVarEmission &emission) {
323 const VarDecl &d = *emission.variable;
324
325 // Check the type for a cleanup.
327 emitAutoVarTypeCleanup(emission, dtorKind);
328
330
331 // Handle the cleanup attribute.
332 if (d.hasAttr<CleanupAttr>())
333 cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
334}
335
336/// Emit code and set up symbol table for a variable declaration with auto,
337/// register, or no storage class specifier. These turn into simple stack
338/// objects, globals depending on target.
344
346 // If the declaration has external storage, don't emit it now, allow it to be
347 // emitted lazily on its first use.
348 if (d.hasExternalStorage())
349 return;
350
351 if (d.getStorageDuration() != SD_Automatic) {
352 // Static sampler variables translated to function calls.
353 if (d.getType()->isSamplerT()) {
354 // Nothing needs to be done here, but let's flag it as an error until we
355 // have a test. It requires OpenCL support.
356 cgm.errorNYI(d.getSourceRange(), "emitVarDecl static sampler type");
357 return;
358 }
359
360 cir::GlobalLinkageKind linkage =
361 cgm.getCIRLinkageVarDefinition(&d, /*IsConstant=*/false);
362
363 // FIXME: We need to force the emission/use of a guard variable for
364 // some variables even if we can constant-evaluate them because
365 // we can't guarantee every translation unit will constant-evaluate them.
366
367 return emitStaticVarDecl(d, linkage);
368 }
369
371 cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");
372
373 assert(d.hasLocalStorage());
374
375 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
376 return emitAutoVarDecl(d);
377}
378
379static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {
380 if (cgm.getLangOpts().CPlusPlus)
381 return cgm.getMangledName(&d).str();
382
383 // If this isn't C++, we don't need a mangled name, just a pretty one.
384 assert(!d.isExternallyVisible() && "name shouldn't matter");
385 std::string contextName;
386 const DeclContext *dc = d.getDeclContext();
387 if (auto *cd = dyn_cast<CapturedDecl>(dc))
388 dc = cast<DeclContext>(cd->getNonClosureContext());
389 if (const auto *fd = dyn_cast<FunctionDecl>(dc))
390 contextName = std::string(cgm.getMangledName(fd));
391 else if (isa<BlockDecl>(dc))
392 cgm.errorNYI(d.getSourceRange(), "block decl context for static var");
393 else if (isa<ObjCMethodDecl>(dc))
394 cgm.errorNYI(d.getSourceRange(), "ObjC decl context for static var");
395 else
396 cgm.errorNYI(d.getSourceRange(), "Unknown context for static var decl");
397
398 contextName += "." + d.getNameAsString();
399 return contextName;
400}
401
402// TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an
403// interface for all constants?
404cir::GlobalOp
406 cir::GlobalLinkageKind linkage) {
407 // In general, we don't always emit static var decls once before we reference
408 // them. It is possible to reference them before emitting the function that
409 // contains them, and it is possible to emit the containing function multiple
410 // times.
411 if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))
412 return existingGV;
413
414 QualType ty = d.getType();
415 assert(ty->isConstantSizeType() && "VLAs can't be static");
416
417 // Use the label if the variable is renamed with the asm-label extension.
418 if (d.hasAttr<AsmLabelAttr>())
419 errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");
420
421 std::string name = getStaticDeclName(*this, d);
422
423 mlir::Type lty = getTypes().convertTypeForMem(ty);
425
426 if (d.hasAttr<LoaderUninitializedAttr>() || d.hasAttr<CUDASharedAttr>())
428 "getOrCreateStaticVarDecl: LoaderUninitializedAttr");
430
431 mlir::Attribute init = builder.getZeroInitAttr(convertType(ty));
432
433 cir::GlobalOp gv = builder.createVersionedGlobal(
434 getModule(), getLoc(d.getLocation()), name, lty, false, linkage);
435 // TODO(cir): infer visibility from linkage in global op builder.
436 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
437 gv.setInitialValueAttr(init);
438 gv.setAlignment(getASTContext().getDeclAlign(&d).getAsAlign().value());
439
440 if (supportsCOMDAT() && gv.isWeakForLinker())
441 gv.setComdat(true);
442
444
445 setGVProperties(gv, &d);
446
447 // OG checks if the expected address space, denoted by the type, is the
448 // same as the actual address space indicated by attributes. If they aren't
449 // the same, an addrspacecast is emitted when this variable is accessed.
450 // In CIR however, cir.get_global already carries that information in
451 // !cir.ptr type - if this global is in OpenCL local address space, then its
452 // type would be !cir.ptr<..., addrspace(offload_local)>. Therefore we don't
453 // need an explicit address space cast in CIR: they will get emitted when
454 // lowering to LLVM IR.
455
456 // Ensure that the static local gets initialized by making sure the parent
457 // function gets emitted eventually.
458 const Decl *dc = cast<Decl>(d.getDeclContext());
459
460 // We can't name blocks or captured statements directly, so try to emit their
461 // parents.
462 if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {
463 dc = dc->getNonClosureContext();
464 // FIXME: Ensure that global blocks get emitted.
465 if (!dc)
466 errorNYI(d.getSourceRange(), "non-closure context");
467 }
468
469 GlobalDecl gd;
471 errorNYI(d.getSourceRange(), "C++ constructors static var context");
472 else if (isa<CXXDestructorDecl>(dc))
473 errorNYI(d.getSourceRange(), "C++ destructors static var context");
474 else if (const auto *fd = dyn_cast<FunctionDecl>(dc))
475 gd = GlobalDecl(fd);
476 else {
477 // Don't do anything for Obj-C method decls or global closures. We should
478 // never defer them.
479 assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");
480 }
482 // Disable emission of the parent function for the OpenMP device codegen.
483 errorNYI(d.getSourceRange(), "OpenMP");
484 }
485
486 return gv;
487}
488
489/// Add the initializer for 'd' to the global variable that has already been
490/// created for it. If the initializer has a different type than gv does, this
491/// may free gv and return a different one. Otherwise it just returns gv.
493 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
494 ConstantEmitter emitter(*this);
495 mlir::TypedAttr init =
496 mlir::cast<mlir::TypedAttr>(emitter.tryEmitForInitializer(d));
497
498 // If constant emission failed, then this should be a C++ static
499 // initializer.
500 if (!init) {
501 cgm.errorNYI(d.getSourceRange(), "static var without initializer");
502 return gv;
503 }
504
505 // TODO(cir): There should be debug code here to assert that the decl size
506 // matches the CIR data layout type alloc size, but the code for calculating
507 // the type alloc size is not implemented yet.
509
510 // The initializer may differ in type from the global. Rewrite
511 // the global to match the initializer. (We have to do this
512 // because some types, like unions, can't be completely represented
513 // in the LLVM type system.)
514 if (gv.getSymType() != init.getType()) {
515 gv.setSymType(init.getType());
516
517 // Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),
518 // but since at this point the current block hasn't been really attached,
519 // there's no visibility into the GetGlobalOp corresponding to this Global.
520 // Given those constraints, thread in the GetGlobalOp and update it
521 // directly.
523 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
524 }
525
526 bool needsDtor =
528
529 gv.setConstant(d.getType().isConstantStorage(
530 getContext(), /*ExcludeCtor=*/true, !needsDtor));
531 gv.setInitialValueAttr(init);
532
533 emitter.finalize(gv);
534
535 if (needsDtor) {
536 // We have a constant initializer, but a nontrivial destructor. We still
537 // need to perform a guarded "initialization" in order to register the
538 // destructor.
539 cgm.errorNYI(d.getSourceRange(), "C++ guarded init");
540 }
541
542 return gv;
543}
544
546 cir::GlobalLinkageKind linkage) {
547 // Check to see if we already have a global variable for this
548 // declaration. This can happen when double-emitting function
549 // bodies, e.g. with complete and base constructors.
550 cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);
551 // TODO(cir): we should have a way to represent global ops as values without
552 // having to emit a get global op. Sometimes these emissions are not used.
553 mlir::Value addr = builder.createGetGlobal(globalOp);
554 auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
555 assert(getAddrOp && "expected cir::GetGlobalOp");
556
557 CharUnits alignment = getContext().getDeclAlign(&d);
558
559 // Store into LocalDeclMap before generating initializer to handle
560 // circular references.
561 mlir::Type elemTy = convertTypeForMem(d.getType());
562 setAddrOfLocalVar(&d, Address(addr, elemTy, alignment));
563
564 // We can't have a VLA here, but we can have a pointer to a VLA,
565 // even though that doesn't really make any sense.
566 // Make sure to evaluate VLA bounds now so that we have them for later.
567 if (d.getType()->isVariablyModifiedType()) {
568 cgm.errorNYI(d.getSourceRange(),
569 "emitStaticVarDecl: variably modified type");
570 }
571
572 // Save the type in case adding the initializer forces a type change.
573 mlir::Type expectedType = addr.getType();
574
575 cir::GlobalOp var = globalOp;
576
578
579 // If this value has an initializer, emit it.
580 if (d.getInit())
581 var = addInitializerToStaticVarDecl(d, var, getAddrOp);
582
583 var.setAlignment(alignment.getAsAlign().value());
584
585 // There are a lot of attributes that need to be handled here. Until
586 // we start to support them, we just report an error if there are any.
587 if (d.hasAttrs())
588 cgm.errorNYI(d.getSourceRange(), "static var with attrs");
589
590 if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)
591 cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");
592
593 // From traditional codegen:
594 // We may have to cast the constant because of the initializer
595 // mismatch above.
596 //
597 // FIXME: It is really dangerous to store this in the map; if anyone
598 // RAUW's the GV uses of this constant will be invalid.
599 mlir::Value castedAddr =
600 builder.createBitcast(getAddrOp.getAddr(), expectedType);
601 localDeclMap.find(&d)->second = Address(castedAddr, elemTy, alignment);
602 cgm.setStaticLocalDeclAddress(&d, var);
603
606}
607
608void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
609 LValue lvalue, bool capturedByInit) {
611
612 SourceLocRAIIObject locRAII{*this, loc};
613 mlir::Value value = emitScalarExpr(init);
614 if (capturedByInit) {
615 cgm.errorNYI(init->getSourceRange(), "emitScalarInit: captured by init");
616 return;
617 }
619 emitStoreThroughLValue(RValue::get(value), lvalue, true);
620}
621
623 LValue lvalue, bool capturedByInit) {
624 SourceLocRAIIObject loc{*this, getLoc(init->getSourceRange())};
625 if (capturedByInit) {
626 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
627 return;
628 }
629
630 QualType type = d->getType();
631
632 if (type->isReferenceType()) {
633 RValue rvalue = emitReferenceBindingToExpr(init);
634 if (capturedByInit)
635 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
636 emitStoreThroughLValue(rvalue, lvalue);
637 return;
638 }
640 case cir::TEK_Scalar:
641 emitScalarInit(init, getLoc(d->getSourceRange()), lvalue);
642 return;
643 case cir::TEK_Complex: {
644 mlir::Value complex = emitComplexExpr(init);
645 if (capturedByInit)
646 cgm.errorNYI(init->getSourceRange(),
647 "emitExprAsInit: complex type captured by init");
648 mlir::Location loc = getLoc(init->getExprLoc());
649 emitStoreOfComplex(loc, complex, lvalue,
650 /*isInit*/ true);
651 return;
652 }
654 // The overlap flag here should be calculated.
656 emitAggExpr(init,
660 return;
661 }
662 llvm_unreachable("bad evaluation kind");
663}
664
665void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) {
666 switch (d.getKind()) {
667 case Decl::BuiltinTemplate:
668 case Decl::TranslationUnit:
669 case Decl::ExternCContext:
670 case Decl::Namespace:
671 case Decl::UnresolvedUsingTypename:
672 case Decl::ClassTemplateSpecialization:
673 case Decl::ClassTemplatePartialSpecialization:
674 case Decl::VarTemplateSpecialization:
675 case Decl::VarTemplatePartialSpecialization:
676 case Decl::TemplateTypeParm:
677 case Decl::UnresolvedUsingValue:
678 case Decl::NonTypeTemplateParm:
679 case Decl::CXXDeductionGuide:
680 case Decl::CXXMethod:
681 case Decl::CXXConstructor:
682 case Decl::CXXDestructor:
683 case Decl::CXXConversion:
684 case Decl::Field:
685 case Decl::MSProperty:
686 case Decl::IndirectField:
687 case Decl::ObjCIvar:
688 case Decl::ObjCAtDefsField:
689 case Decl::ParmVar:
690 case Decl::ImplicitParam:
691 case Decl::ClassTemplate:
692 case Decl::VarTemplate:
693 case Decl::FunctionTemplate:
694 case Decl::TypeAliasTemplate:
695 case Decl::TemplateTemplateParm:
696 case Decl::ObjCMethod:
697 case Decl::ObjCCategory:
698 case Decl::ObjCProtocol:
699 case Decl::ObjCInterface:
700 case Decl::ObjCCategoryImpl:
701 case Decl::ObjCImplementation:
702 case Decl::ObjCProperty:
703 case Decl::ObjCCompatibleAlias:
704 case Decl::PragmaComment:
705 case Decl::PragmaDetectMismatch:
706 case Decl::AccessSpec:
707 case Decl::LinkageSpec:
708 case Decl::Export:
709 case Decl::ObjCPropertyImpl:
710 case Decl::FileScopeAsm:
711 case Decl::Friend:
712 case Decl::FriendTemplate:
713 case Decl::Block:
714 case Decl::OutlinedFunction:
715 case Decl::Captured:
716 case Decl::UsingShadow:
717 case Decl::ConstructorUsingShadow:
718 case Decl::ObjCTypeParam:
719 case Decl::Binding:
720 case Decl::UnresolvedUsingIfExists:
721 case Decl::HLSLBuffer:
722 case Decl::HLSLRootSignature:
723 llvm_unreachable("Declaration should not be in declstmts!");
724
725 case Decl::Function: // void X();
726 case Decl::EnumConstant: // enum ? { X = ? }
727 case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
728 case Decl::Label: // __label__ x;
729 case Decl::Import:
730 case Decl::MSGuid: // __declspec(uuid("..."))
731 case Decl::TemplateParamObject:
732 case Decl::OMPThreadPrivate:
733 case Decl::OMPGroupPrivate:
734 case Decl::OMPAllocate:
735 case Decl::OMPCapturedExpr:
736 case Decl::OMPRequires:
737 case Decl::Empty:
738 case Decl::Concept:
739 case Decl::LifetimeExtendedTemporary:
740 case Decl::RequiresExprBody:
741 case Decl::UnnamedGlobalConstant:
742 // None of these decls require codegen support.
743 return;
744
745 case Decl::Enum: // enum X;
746 case Decl::Record: // struct/union/class X;
747 case Decl::CXXRecord: // struct/union/class X; [C++]
748 case Decl::NamespaceAlias:
749 case Decl::Using: // using X; [C++]
750 case Decl::UsingEnum: // using enum X; [C++]
751 case Decl::UsingDirective: // using namespace X; [C++]
753 return;
754 case Decl::Var:
755 case Decl::Decomposition: {
756 const VarDecl &vd = cast<VarDecl>(d);
757 assert(vd.isLocalVarDecl() &&
758 "Should not see file-scope variables inside a function!");
759 emitVarDecl(vd);
760 if (evaluateConditionDecl)
762 return;
763 }
764 case Decl::OpenACCDeclare:
766 return;
767 case Decl::OpenACCRoutine:
769 return;
770 case Decl::Typedef: // typedef int X;
771 case Decl::TypeAlias: { // using X = int; [C++0x]
772 QualType ty = cast<TypedefNameDecl>(d).getUnderlyingType();
774 if (ty->isVariablyModifiedType())
775 cgm.errorNYI(d.getSourceRange(), "emitDecl: variably modified type");
776 return;
777 }
778 case Decl::ImplicitConceptSpecialization:
779 case Decl::TopLevelStmt:
780 case Decl::UsingPack:
781 case Decl::OMPDeclareMapper:
782 case Decl::OMPDeclareReduction:
783 cgm.errorNYI(d.getSourceRange(),
784 std::string("emitDecl: unhandled decl type: ") +
785 d.getDeclKindName());
786 }
787}
788
790 SourceLocation loc) {
791 if (!sanOpts.has(SanitizerKind::NullabilityAssign))
792 return;
793
795}
796
797namespace {
798struct DestroyObject final : EHScopeStack::Cleanup {
799 DestroyObject(Address addr, QualType type,
800 CIRGenFunction::Destroyer *destroyer)
801 : addr(addr), type(type), destroyer(destroyer) {}
802
803 Address addr;
805 CIRGenFunction::Destroyer *destroyer;
806
807 void emit(CIRGenFunction &cgf) override {
808 cgf.emitDestroy(addr, type, destroyer);
809 }
810};
811
812struct CallStackRestore final : EHScopeStack::Cleanup {
813 Address stack;
814 CallStackRestore(Address stack) : stack(stack) {}
815 void emit(CIRGenFunction &cgf) override {
816 mlir::Location loc = stack.getPointer().getLoc();
817 mlir::Value v = cgf.getBuilder().createLoad(loc, stack);
818 cgf.getBuilder().createStackRestore(loc, v);
819 }
820};
821} // namespace
822
823/// Push the standard destructor for the given type as
824/// at least a normal cleanup.
826 Address addr, QualType type) {
827 assert(dtorKind && "cannot push destructor for trivial type");
828
829 CleanupKind cleanupKind = getCleanupKind(dtorKind);
830 pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind));
831}
832
834 QualType type, Destroyer *destroyer) {
835 pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
836}
837
838/// Destroys all the elements of the given array, beginning from last to first.
839/// The array cannot be zero-length.
840///
841/// \param begin - a type* denoting the first element of the array
842/// \param numElements - the number of elements in the array
843/// \param elementType - the element type of the array
844/// \param destroyer - the function to call to destroy elements
845void CIRGenFunction::emitArrayDestroy(mlir::Value begin,
846 mlir::Value numElements,
847 QualType elementType,
848 CharUnits elementAlign,
849 Destroyer *destroyer) {
850 assert(!elementType->isArrayType());
851
852 // Differently from LLVM traditional codegen, use a higher level
853 // representation instead of lowering directly to a loop.
854 mlir::Type cirElementType = convertTypeForMem(elementType);
855 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
856
857 uint64_t size = 0;
858
859 // Optimize for a constant array size.
860 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
861 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())
862 size = constIntAttr.getUInt();
863 } else {
864 cgm.errorNYI(begin.getDefiningOp()->getLoc(),
865 "dynamic-length array expression");
866 }
867
868 auto arrayTy = cir::ArrayType::get(cirElementType, size);
869 mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);
870
871 // Emit the dtor call that will execute for every array element.
872 cir::ArrayDtor::create(
873 builder, *currSrcLoc, arrayOp,
874 [&](mlir::OpBuilder &b, mlir::Location loc) {
875 auto arg = b.getInsertionBlock()->addArgument(ptrToElmType, loc);
876 Address curAddr = Address(arg, cirElementType, elementAlign);
878
879 // Perform the actual destruction there.
880 destroyer(*this, curAddr, elementType);
881
882 cir::YieldOp::create(builder, loc);
883 });
884}
885
886/// Immediately perform the destruction of the given object.
887///
888/// \param addr - the address of the object; a type*
889/// \param type - the type of the object; if an array type, all
890/// objects are destroyed in reverse order
891/// \param destroyer - the function to call to destroy individual
892/// elements
894 Destroyer *destroyer) {
896 if (!arrayType)
897 return destroyer(*this, addr, type);
898
899 mlir::Value length = emitArrayLength(arrayType, type, addr);
900
901 CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement(
902 getContext().getTypeSizeInChars(type));
903
904 auto constantCount = length.getDefiningOp<cir::ConstantOp>();
905 if (!constantCount) {
907 cgm.errorNYI("emitDestroy: variable length array");
908 return;
909 }
910
911 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
912 // If it's constant zero, we can just skip the entire thing.
913 if (constIntAttr && constIntAttr.getUInt() == 0)
914 return;
915
916 mlir::Value begin = addr.getPointer();
917 emitArrayDestroy(begin, length, type, elementAlign, destroyer);
918
919 // If the array destroy didn't use the length op, we can erase it.
920 if (constantCount.use_empty())
921 constantCount.erase();
922}
923
926 switch (kind) {
928 llvm_unreachable("no destroyer for trivial dtor");
930 return destroyCXXObject;
934 cgm.errorNYI("getDestroyer: other destruction kind");
935 return nullptr;
936 }
937 llvm_unreachable("Unknown DestructionKind");
938}
939
941 ehStack.pushCleanup<CallStackRestore>(kind, spMem);
942}
943
944/// Enter a destroy cleanup for the given local variable.
946 const CIRGenFunction::AutoVarEmission &emission,
947 QualType::DestructionKind dtorKind) {
948 assert(dtorKind != QualType::DK_none);
949
950 // Note that for __block variables, we want to destroy the
951 // original stack object, not the possibly forwarded object.
952 Address addr = emission.getObjectAddress(*this);
953
954 const VarDecl *var = emission.variable;
955 QualType type = var->getType();
956
957 CleanupKind cleanupKind = NormalAndEHCleanup;
958 CIRGenFunction::Destroyer *destroyer = nullptr;
959
960 switch (dtorKind) {
962 llvm_unreachable("no cleanup for trivially-destructible variable");
963
965 // If there's an NRVO flag on the emission, we need a different
966 // cleanup.
967 if (emission.nrvoFlag) {
968 cgm.errorNYI(var->getSourceRange(), "emitAutoVarTypeCleanup: NRVO");
969 return;
970 }
971 // Otherwise, this is handled below.
972 break;
973
977 cgm.errorNYI(var->getSourceRange(),
978 "emitAutoVarTypeCleanup: other dtor kind");
979 return;
980 }
981
982 // If we haven't chosen a more specific destroyer, use the default.
983 if (!destroyer)
984 destroyer = getDestroyer(dtorKind);
985
987 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
988}
989
991 if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
992 for (auto *b : dd->flat_bindings())
993 if (auto *hd = b->getHoldingVar())
994 emitVarDecl(*hd);
995 }
996}
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.
__device__ __2f16 b
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
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:926
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:3722
mlir::Value getPointer() const
Definition Address.h:84
mlir::Type getElementType() const
Definition Address.h:111
static Address invalid()
Definition Address.h:69
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:124
mlir::Operation * getDefiningOp() const
Get the operation which defines this address.
Definition Address.h:127
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
cir::StackRestoreOp createStackRestore(mlir::Location loc, mlir::Value v)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
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,...
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)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
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.
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.
CleanupKind getCleanupKind(QualType::DestructionKind kind)
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 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...
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.
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.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
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 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 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 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
mlir::Type convertType(clang::QualType type)
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
const clang::LangOptions & getLangOpts() const
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()
cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d)
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.
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:1548
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
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
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:1449
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
Decl * getNonClosureContext()
Find the innermost non-closure ancestor of this declaration, walking up through blocks,...
SourceLocation getLocation() const
Definition DeclBase.h:439
const char * getDeclKindName() const
Definition DeclBase.cpp:169
DeclContext * getDeclContext()
Definition DeclBase.h:448
bool hasAttr() const
Definition DeclBase.h:577
Kind getKind() const
Definition DeclBase.h:442
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
This represents one expression.
Definition Expr.h:112
bool isConstantInitializer(ASTContext &Ctx, bool ForRef, const Expr **Culprit=nullptr) const
isConstantInitializer - Returns true if this expression can be emitted to IR as a constant,...
Definition Expr.cpp:3342
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
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:937
@ PDIK_Struct
The type is a struct containing a field whose type is not PCK_Trivial.
Definition TypeBase.h:1478
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8404
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1036
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
Definition Type.cpp:2694
Represents a struct/union/class.
Definition Decl.h:4312
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:338
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:2425
bool isArrayType() const
Definition TypeBase.h:8614
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2800
bool isVectorType() const
Definition TypeBase.h:8654
bool isSamplerT() const
Definition TypeBase.h:8749
bool isRecordType() const
Definition TypeBase.h:8642
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:926
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1569
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2195
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:2491
bool isNRVOVariable() const
Determine whether this local variable can be used with the named return value optimization (NRVO).
Definition Decl.h:1512
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2856
const Expr * getInit() const
Definition Decl.h:1368
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1217
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1184
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1253
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1229
bool isEscapingByref() const
Indicates the capture is a __block variable that is captured by a block that can potentially escape (...
Definition Decl.cpp:2703
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ 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
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ SD_Automatic
Automatic storage duration (most local variables).
Definition Specifiers.h:341
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 addAutoInitAnnotation()
static bool addressSpace()
static bool emitNullabilityCheck()
static bool ehCleanupFlags()
static bool opGlobalThreadLocal()
static bool vectorConstants()
static bool aggValueSlotMayOverlap()
static bool shouldSplitConstantStore()
static bool shouldUseMemSetToInitialize()
static bool dtorCleanups()
static bool shouldUseBZeroPlusStoresToInitialize()
static bool shouldCreateMemCpyFromGlobal()
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.
cir::PointerType allocaInt8PtrTy
void* in alloca address space