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 / In LLVM: Create a flag that is used to indicate when the NRVO was
103 / applied to this variable. Set it to zero to indicate that NRVO was
104 / not applied. For now, use the same approach for CIRGen until we can
105 / be sure it's worth doing something more aggressive.
106 cir::ConstantOp falseNVRO = builder.getFalse(loc);
107 Address nrvoFlag = createTempAlloca(falseNVRO.getType(),
108 CharUnits::One(), loc, "nrvo",
109 /*arraySize=*/nullptr);
110 assert(builder.getInsertionBlock());
111 builder.createStore(loc, falseNVRO, nrvoFlag);
112
113 / Record the NRVO flag for this variable.
114 nrvoFlags[&d] = nrvoFlag.getPointer();
115 emission.nrvoFlag = nrvoFlag.getPointer();
116 }
117 }
118 } else {
119 / A normal fixed sized variable becomes an alloca in the entry block,
120 mlir::Type allocaTy = convertTypeForMem(ty);
121 / Create the temp alloca and declare variable using it.
122 address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
123 /*arraySize=*/nullptr, /*alloca=*/nullptr, ip);
124 declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()),
125 alignment);
126 }
127 } else {
128 / Non-constant size type
130 if (!didCallStackSave) {
131 / Save the stack.
132 cir::PointerType defaultTy = allocaInt8PtrTy;
134 cgm.getDataLayout().getAlignment(defaultTy, false));
135 Address stack = createTempAlloca(defaultTy, align, loc, "saved_stack");
136
137 mlir::Value v = builder.createStackSave(loc, defaultTy);
138 assert(v.getType() == allocaInt8PtrTy);
139 builder.createStore(loc, v, stack);
140
141 didCallStackSave = true;
142
143 / Push a cleanup block and restore the stack there.
144 / FIXME: in general circumstances, this should be an EH cleanup.
146 }
147
148 VlaSizePair vlaSize = getVLASize(ty);
149 mlir::Type memTy = convertTypeForMem(vlaSize.type);
150
151 / Allocate memory for the array.
152 address =
153 createTempAlloca(memTy, alignment, loc, d.getName(), vlaSize.numElts,
154 /*alloca=*/nullptr, builder.saveInsertionPoint());
155
156 / If we have debug info enabled, properly describe the VLA dimensions for
157 / this type by registering the vla size expression for each of the
158 / dimensions.
160 }
161
162 emission.addr = address;
163 setAddrOfLocalVar(&d, address);
164
165 return emission;
166}
167
168/ Determine whether the given initializer is trivial in the sense
169/ that it requires no code to be generated.
171 if (!init)
172 return true;
173
174 if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(init))
175 if (CXXConstructorDecl *constructor = construct->getConstructor())
176 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
177 !construct->requiresZeroInitialization())
178 return true;
179
180 return false;
181}
182
183static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d,
184 Address addr, bool isVolatile,
185 CIRGenBuilderTy &builder,
186 mlir::TypedAttr constant) {
187 mlir::Type ty = constant.getType();
188 cir::CIRDataLayout layout{cgm.getModule()};
189 uint64_t constantSize = layout.getTypeAllocSize(ty);
190 if (!constantSize)
191 return;
198 / In CIR we want to emit a store for the whole thing, later lowering
199 / prepare to LLVM should unwrap this into the best policy (see asserts
200 / above).
201 /
202 / FIXME(cir): This is closer to memcpy behavior but less optimal, instead of
203 / copy from a global, we just create a cir.const out of it.
204
205 if (addr.getElementType() != ty)
206 addr = addr.withElementType(builder, ty);
207
208 / If the address is an alloca, set the init attribute.
209 / The address is usually and alloca, but there is at least one case where
210 / emitAutoVarInit is called from the OpenACC codegen with an address that
211 / is not an alloca.
212 auto allocaOp = addr.getDefiningOp<cir::AllocaOp>();
213 if (allocaOp)
214 allocaOp.setInitAttr(mlir::UnitAttr::get(&cgm.getMLIRContext()));
215
216 / There are cases where OpenACC codegen calls emitAutoVarInit with a
217 / temporary decl that doesn't have a source range set.
218 mlir::Location loc = builder.getUnknownLoc();
219 if (d.getSourceRange().isValid())
220 loc = cgm.getLoc(d.getSourceRange());
221 builder.createStore(loc, builder.getConstant(loc, constant), addr);
222}
223
225 const CIRGenFunction::AutoVarEmission &emission) {
226 assert(emission.variable && "emission was not valid!");
227
228 / If this was emitted as a global constant, we're done.
229 if (emission.wasEmittedAsGlobal())
230 return;
231
232 const VarDecl &d = *emission.variable;
233
234 QualType type = d.getType();
235
236 / If this local has an initializer, emit it now.
237 const Expr *init = d.getInit();
238
239 / Initialize the variable here if it doesn't have a initializer and it is a
240 / C struct that is non-trivial to initialize or an array containing such a
241 / struct.
242 if (!init && type.isNonTrivialToPrimitiveDefaultInitialize() ==
244 cgm.errorNYI(d.getSourceRange(),
245 "emitAutoVarInit: non-trivial to default initialize");
246 return;
247 }
248
249 const Address addr = emission.addr;
250
251 / Check whether this is a byref variable that's potentially
252 / captured and moved by its own initializer. If so, we'll need to
253 / emit the initializer first, then copy into the variable.
255
256 / Note: constexpr already initializes everything correctly.
257 LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
258 (d.isConstexpr()
260 : (d.getAttr<UninitializedAttr>()
262 : getContext().getLangOpts().getTrivialAutoVarInit()));
263
264 auto initializeWhatIsTechnicallyUninitialized = [&](Address addr) {
265 if (trivialAutoVarInit ==
267 return;
268
269 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: trivial initialization");
270 };
271
272 if (isTrivialInitializer(init)) {
273 initializeWhatIsTechnicallyUninitialized(addr);
274 return;
275 }
276
277 mlir::Attribute constant;
278 if (emission.isConstantAggregate ||
280 / FIXME: Differently from LLVM we try not to emit / lower too much
281 / here for CIR since we are interested in seeing the ctor in some
282 / analysis later on. So CIR's implementation of ConstantEmitter will
283 / frequently return an empty Attribute, to signal we want to codegen
284 / some trivial ctor calls and whatnots.
286 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
287 (trivialAutoVarInit !=
289 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: constant aggregate");
290 return;
291 }
292 }
293
294 / NOTE(cir): In case we have a constant initializer, we can just emit a
295 / store. But, in CIR, we wish to retain any ctor calls, so if it is a
296 / CXX temporary object creation, we ensure the ctor call is used deferring
297 / its removal/optimization to the CIR lowering.
298 if (!constant || isa<CXXTemporaryObjectExpr>(init)) {
299 initializeWhatIsTechnicallyUninitialized(addr);
301 emitExprAsInit(init, &d, lv);
302
303 if (!emission.wasEmittedAsOffloadClause()) {
304 / In case lv has uses it means we indeed initialized something
305 / out of it while trying to build the expression, mark it as such.
306 mlir::Value val = lv.getAddress().getPointer();
307 assert(val && "Should have an address");
308 auto allocaOp = val.getDefiningOp<cir::AllocaOp>();
309 assert(allocaOp && "Address should come straight out of the alloca");
310
311 if (!allocaOp.use_empty())
312 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
313 }
314
315 return;
316 }
317
318 / FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.
319 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
320 assert(typedConstant && "expected typed attribute");
321 if (!emission.isConstantAggregate) {
322 / For simple scalar/complex initialization, store the value directly.
323 LValue lv = makeAddrLValue(addr, type);
324 assert(init && "expected initializer");
325 mlir::Location initLoc = getLoc(init->getSourceRange());
326 / lv.setNonGC(true);
328 RValue::get(builder.getConstant(initLoc, typedConstant)), lv);
329 }
330
331 emitStoresForConstant(cgm, d, addr, type.isVolatileQualified(), builder,
332 typedConstant);
333}
334
336 const CIRGenFunction::AutoVarEmission &emission) {
337 const VarDecl &d = *emission.variable;
338
339 / Check the type for a cleanup.
341 emitAutoVarTypeCleanup(emission, dtorKind);
342
344
345 / Handle the cleanup attribute.
346 if (d.hasAttr<CleanupAttr>())
347 cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
348}
349
350/ Emit code and set up symbol table for a variable declaration with auto,
351/ register, or no storage class specifier. These turn into simple stack
352/ objects, globals depending on target.
358
360 / If the declaration has external storage, don't emit it now, allow it to be
361 / emitted lazily on its first use.
362 if (d.hasExternalStorage())
363 return;
364
365 if (d.getStorageDuration() != SD_Automatic) {
366 / Static sampler variables translated to function calls.
367 if (d.getType()->isSamplerT()) {
368 / Nothing needs to be done here, but let's flag it as an error until we
369 / have a test. It requires OpenCL support.
370 cgm.errorNYI(d.getSourceRange(), "emitVarDecl static sampler type");
371 return;
372 }
373
374 cir::GlobalLinkageKind linkage =
375 cgm.getCIRLinkageVarDefinition(&d, /*IsConstant=*/false);
376
377 / FIXME: We need to force the emission/use of a guard variable for
378 / some variables even if we can constant-evaluate them because
379 / we can't guarantee every translation unit will constant-evaluate them.
380
381 return emitStaticVarDecl(d, linkage);
382 }
383
385 cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");
386
387 assert(d.hasLocalStorage());
388
389 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
390 return emitAutoVarDecl(d);
391}
392
393static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {
394 if (cgm.getLangOpts().CPlusPlus)
395 return cgm.getMangledName(&d).str();
396
397 / If this isn't C++, we don't need a mangled name, just a pretty one.
398 assert(!d.isExternallyVisible() && "name shouldn't matter");
399 std::string contextName;
400 const DeclContext *dc = d.getDeclContext();
401 if (auto *cd = dyn_cast<CapturedDecl>(dc))
402 dc = cast<DeclContext>(cd->getNonClosureContext());
403 if (const auto *fd = dyn_cast<FunctionDecl>(dc))
404 contextName = std::string(cgm.getMangledName(fd));
405 else if (isa<BlockDecl>(dc))
406 cgm.errorNYI(d.getSourceRange(), "block decl context for static var");
407 else if (isa<ObjCMethodDecl>(dc))
408 cgm.errorNYI(d.getSourceRange(), "ObjC decl context for static var");
409 else
410 cgm.errorNYI(d.getSourceRange(), "Unknown context for static var decl");
411
412 contextName += "." + d.getNameAsString();
413 return contextName;
414}
415
416/ TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an
417/ interface for all constants?
418cir::GlobalOp
420 cir::GlobalLinkageKind linkage) {
421 / In general, we don't always emit static var decls once before we reference
422 / them. It is possible to reference them before emitting the function that
423 / contains them, and it is possible to emit the containing function multiple
424 / times.
425 if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))
426 return existingGV;
427
428 QualType ty = d.getType();
429 assert(ty->isConstantSizeType() && "VLAs can't be static");
430
431 / Use the label if the variable is renamed with the asm-label extension.
432 if (d.hasAttr<AsmLabelAttr>())
433 errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");
434
435 std::string name = getStaticDeclName(*this, d);
436
437 mlir::Type lty = getTypes().convertTypeForMem(ty);
439
440 if (d.hasAttr<LoaderUninitializedAttr>() || d.hasAttr<CUDASharedAttr>())
442 "getOrCreateStaticVarDecl: LoaderUninitializedAttr");
444
445 mlir::Attribute init = builder.getZeroInitAttr(convertType(ty));
446
447 cir::GlobalOp gv = builder.createVersionedGlobal(
448 getModule(), getLoc(d.getLocation()), name, lty, false, linkage);
449 / TODO(cir): infer visibility from linkage in global op builder.
450 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
451 gv.setInitialValueAttr(init);
452 gv.setAlignment(getASTContext().getDeclAlign(&d).getAsAlign().value());
453
454 if (supportsCOMDAT() && gv.isWeakForLinker())
455 gv.setComdat(true);
456
457 if (d.getTLSKind())
458 errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: TLS");
459
460 setGVProperties(gv, &d);
461
462 / OG checks if the expected address space, denoted by the type, is the
463 / same as the actual address space indicated by attributes. If they aren't
464 / the same, an addrspacecast is emitted when this variable is accessed.
465 / In CIR however, cir.get_global already carries that information in
466 / !cir.ptr type - if this global is in OpenCL local address space, then its
467 / type would be !cir.ptr<..., addrspace(offload_local)>. Therefore we don't
468 / need an explicit address space cast in CIR: they will get emitted when
469 / lowering to LLVM IR.
470
471 / Ensure that the static local gets initialized by making sure the parent
472 / function gets emitted eventually.
473 const Decl *dc = cast<Decl>(d.getDeclContext());
474
475 / We can't name blocks or captured statements directly, so try to emit their
476 / parents.
477 if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {
478 dc = dc->getNonClosureContext();
479 / FIXME: Ensure that global blocks get emitted.
480 if (!dc)
481 errorNYI(d.getSourceRange(), "non-closure context");
482 }
483
484 GlobalDecl gd;
486 errorNYI(d.getSourceRange(), "C++ constructors static var context");
487 else if (isa<CXXDestructorDecl>(dc))
488 errorNYI(d.getSourceRange(), "C++ destructors static var context");
489 else if (const auto *fd = dyn_cast<FunctionDecl>(dc))
490 gd = GlobalDecl(fd);
491 else {
492 / Don't do anything for Obj-C method decls or global closures. We should
493 / never defer them.
494 assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");
495 }
497 / Disable emission of the parent function for the OpenMP device codegen.
498 errorNYI(d.getSourceRange(), "OpenMP");
499 }
500
501 return gv;
502}
503
504/ Add the initializer for 'd' to the global variable that has already been
505/ created for it. If the initializer has a different type than gv does, this
506/ may free gv and return a different one. Otherwise it just returns gv.
508 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
509 ConstantEmitter emitter(*this);
510 mlir::TypedAttr init =
511 mlir::cast<mlir::TypedAttr>(emitter.tryEmitForInitializer(d));
512
513 / If constant emission failed, then this should be a C++ static
514 / initializer.
515 if (!init) {
516 cgm.errorNYI(d.getSourceRange(), "static var without initializer");
517 return gv;
518 }
519
520 / TODO(cir): There should be debug code here to assert that the decl size
521 / matches the CIR data layout type alloc size, but the code for calculating
522 / the type alloc size is not implemented yet.
524
525 / The initializer may differ in type from the global. Rewrite
526 / the global to match the initializer. (We have to do this
527 / because some types, like unions, can't be completely represented
528 / in the LLVM type system.)
529 if (gv.getSymType() != init.getType()) {
530 gv.setSymType(init.getType());
531
532 / Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),
533 / but since at this point the current block hasn't been really attached,
534 / there's no visibility into the GetGlobalOp corresponding to this Global.
535 / Given those constraints, thread in the GetGlobalOp and update it
536 / directly.
538 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
539 }
540
541 bool needsDtor =
543
544 gv.setConstant(d.getType().isConstantStorage(
545 getContext(), /*ExcludeCtor=*/true, !needsDtor));
546 gv.setInitialValueAttr(init);
547
548 emitter.finalize(gv);
549
550 if (needsDtor) {
551 / We have a constant initializer, but a nontrivial destructor. We still
552 / need to perform a guarded "initialization" in order to register the
553 / destructor.
554 cgm.errorNYI(d.getSourceRange(), "C++ guarded init");
555 }
556
557 return gv;
558}
559
561 cir::GlobalLinkageKind linkage) {
562 / Check to see if we already have a global variable for this
563 / declaration. This can happen when double-emitting function
564 / bodies, e.g. with complete and base constructors.
565 cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);
566 / TODO(cir): we should have a way to represent global ops as values without
567 / having to emit a get global op. Sometimes these emissions are not used.
568 mlir::Value addr = builder.createGetGlobal(globalOp);
569 auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();
570 assert(getAddrOp && "expected cir::GetGlobalOp");
571
572 CharUnits alignment = getContext().getDeclAlign(&d);
573
574 / Store into LocalDeclMap before generating initializer to handle
575 / circular references.
576 mlir::Type elemTy = convertTypeForMem(d.getType());
577 setAddrOfLocalVar(&d, Address(addr, elemTy, alignment));
578
579 / We can't have a VLA here, but we can have a pointer to a VLA,
580 / even though that doesn't really make any sense.
581 / Make sure to evaluate VLA bounds now so that we have them for later.
582 if (d.getType()->isVariablyModifiedType()) {
583 cgm.errorNYI(d.getSourceRange(),
584 "emitStaticVarDecl: variably modified type");
585 }
586
587 / Save the type in case adding the initializer forces a type change.
588 mlir::Type expectedType = addr.getType();
589
590 cir::GlobalOp var = globalOp;
591
593
594 / If this value has an initializer, emit it.
595 if (d.getInit())
596 var = addInitializerToStaticVarDecl(d, var, getAddrOp);
597
598 var.setAlignment(alignment.getAsAlign().value());
599
600 / There are a lot of attributes that need to be handled here. Until
601 / we start to support them, we just report an error if there are any.
602 if (d.hasAttrs())
603 cgm.errorNYI(d.getSourceRange(), "static var with attrs");
604
605 if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)
606 cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");
607
608 / From traditional codegen:
609 / We may have to cast the constant because of the initializer
610 / mismatch above.
611 /
612 / FIXME: It is really dangerous to store this in the map; if anyone
613 / RAUW's the GV uses of this constant will be invalid.
614 mlir::Value castedAddr =
615 builder.createBitcast(getAddrOp.getAddr(), expectedType);
616 localDeclMap.find(&d)->second = Address(castedAddr, elemTy, alignment);
617 cgm.setStaticLocalDeclAddress(&d, var);
618
621}
622
623void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
624 LValue lvalue, bool capturedByInit) {
626
627 SourceLocRAIIObject locRAII{*this, loc};
628 mlir::Value value = emitScalarExpr(init);
629 if (capturedByInit) {
630 cgm.errorNYI(init->getSourceRange(), "emitScalarInit: captured by init");
631 return;
632 }
634 emitStoreThroughLValue(RValue::get(value), lvalue, true);
635}
636
638 LValue lvalue, bool capturedByInit) {
639 SourceLocRAIIObject loc{*this, getLoc(init->getSourceRange())};
640 if (capturedByInit) {
641 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
642 return;
643 }
644
645 QualType type = d->getType();
646
647 if (type->isReferenceType()) {
648 RValue rvalue = emitReferenceBindingToExpr(init);
649 if (capturedByInit)
650 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
651 emitStoreThroughLValue(rvalue, lvalue);
652 return;
653 }
655 case cir::TEK_Scalar:
656 emitScalarInit(init, getLoc(d->getSourceRange()), lvalue);
657 return;
658 case cir::TEK_Complex: {
659 mlir::Value complex = emitComplexExpr(init);
660 if (capturedByInit)
661 cgm.errorNYI(init->getSourceRange(),
662 "emitExprAsInit: complex type captured by init");
663 mlir::Location loc = getLoc(init->getExprLoc());
664 emitStoreOfComplex(loc, complex, lvalue,
665 /*isInit*/ true);
666 return;
667 }
669 / The overlap flag here should be calculated.
671 emitAggExpr(init,
675 return;
676 }
677 llvm_unreachable("bad evaluation kind");
678}
679
680void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) {
681 switch (d.getKind()) {
682 case Decl::BuiltinTemplate:
683 case Decl::TranslationUnit:
684 case Decl::ExternCContext:
685 case Decl::Namespace:
686 case Decl::UnresolvedUsingTypename:
687 case Decl::ClassTemplateSpecialization:
688 case Decl::ClassTemplatePartialSpecialization:
689 case Decl::VarTemplateSpecialization:
690 case Decl::VarTemplatePartialSpecialization:
691 case Decl::TemplateTypeParm:
692 case Decl::UnresolvedUsingValue:
693 case Decl::NonTypeTemplateParm:
694 case Decl::CXXDeductionGuide:
695 case Decl::CXXMethod:
696 case Decl::CXXConstructor:
697 case Decl::CXXDestructor:
698 case Decl::CXXConversion:
699 case Decl::Field:
700 case Decl::MSProperty:
701 case Decl::IndirectField:
702 case Decl::ObjCIvar:
703 case Decl::ObjCAtDefsField:
704 case Decl::ParmVar:
705 case Decl::ImplicitParam:
706 case Decl::ClassTemplate:
707 case Decl::VarTemplate:
708 case Decl::FunctionTemplate:
709 case Decl::TypeAliasTemplate:
710 case Decl::TemplateTemplateParm:
711 case Decl::ObjCMethod:
712 case Decl::ObjCCategory:
713 case Decl::ObjCProtocol:
714 case Decl::ObjCInterface:
715 case Decl::ObjCCategoryImpl:
716 case Decl::ObjCImplementation:
717 case Decl::ObjCProperty:
718 case Decl::ObjCCompatibleAlias:
719 case Decl::PragmaComment:
720 case Decl::PragmaDetectMismatch:
721 case Decl::AccessSpec:
722 case Decl::LinkageSpec:
723 case Decl::Export:
724 case Decl::ObjCPropertyImpl:
725 case Decl::FileScopeAsm:
726 case Decl::Friend:
727 case Decl::FriendTemplate:
728 case Decl::Block:
729 case Decl::OutlinedFunction:
730 case Decl::Captured:
731 case Decl::UsingShadow:
732 case Decl::ConstructorUsingShadow:
733 case Decl::ObjCTypeParam:
734 case Decl::Binding:
735 case Decl::UnresolvedUsingIfExists:
736 case Decl::HLSLBuffer:
737 case Decl::HLSLRootSignature:
738 llvm_unreachable("Declaration should not be in declstmts!");
739
740 case Decl::Function: / void X();
741 case Decl::EnumConstant: / enum ? { X = ? }
742 case Decl::StaticAssert: / static_assert(X, ""); [C++0x]
743 case Decl::Label: / __label__ x;
744 case Decl::Import:
745 case Decl::MSGuid: / __declspec(uuid("..."))
746 case Decl::TemplateParamObject:
747 case Decl::OMPThreadPrivate:
748 case Decl::OMPGroupPrivate:
749 case Decl::OMPAllocate:
750 case Decl::OMPCapturedExpr:
751 case Decl::OMPRequires:
752 case Decl::Empty:
753 case Decl::Concept:
754 case Decl::LifetimeExtendedTemporary:
755 case Decl::RequiresExprBody:
756 case Decl::UnnamedGlobalConstant:
757 / None of these decls require codegen support.
758 return;
759
760 case Decl::Enum: / enum X;
761 case Decl::Record: / struct/union/class X;
762 case Decl::CXXRecord: / struct/union/class X; [C++]
763 case Decl::NamespaceAlias:
764 case Decl::Using: / using X; [C++]
765 case Decl::UsingEnum: / using enum X; [C++]
766 case Decl::UsingDirective: / using namespace X; [C++]
768 return;
769 case Decl::Var:
770 case Decl::Decomposition: {
771 const VarDecl &vd = cast<VarDecl>(d);
772 assert(vd.isLocalVarDecl() &&
773 "Should not see file-scope variables inside a function!");
774 emitVarDecl(vd);
775 if (evaluateConditionDecl)
777 return;
778 }
779 case Decl::OpenACCDeclare:
781 return;
782 case Decl::OpenACCRoutine:
784 return;
785 case Decl::Typedef: / typedef int X;
786 case Decl::TypeAlias: { / using X = int; [C++0x]
787 QualType ty = cast<TypedefNameDecl>(d).getUnderlyingType();
789 if (ty->isVariablyModifiedType())
790 cgm.errorNYI(d.getSourceRange(), "emitDecl: variably modified type");
791 return;
792 }
793 case Decl::ImplicitConceptSpecialization:
794 case Decl::TopLevelStmt:
795 case Decl::UsingPack:
796 case Decl::OMPDeclareMapper:
797 case Decl::OMPDeclareReduction:
798 cgm.errorNYI(d.getSourceRange(),
799 std::string("emitDecl: unhandled decl type: ") +
800 d.getDeclKindName());
801 }
802}
803
805 SourceLocation loc) {
806 if (!sanOpts.has(SanitizerKind::NullabilityAssign))
807 return;
808
810}
811
812namespace {
813struct DestroyObject final : EHScopeStack::Cleanup {
814 DestroyObject(Address addr, QualType type,
815 CIRGenFunction::Destroyer *destroyer)
816 : addr(addr), type(type), destroyer(destroyer) {
818 }
819
820 Address addr;
822 CIRGenFunction::Destroyer *destroyer;
823
824 void emit(CIRGenFunction &cgf, Flags flags) override {
826 cgf.emitDestroy(addr, type, destroyer);
827 }
828};
829
830template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup {
831 DestroyNRVOVariable(Address addr, QualType type, mlir::Value nrvoFlag)
832 : nrvoFlag(nrvoFlag), addr(addr), ty(type) {}
833
834 mlir::Value nrvoFlag;
835 Address addr;
836 QualType ty;
837
838 void emit(CIRGenFunction &cgf, Flags flags) override {
839 / Along the exceptions path we always execute the dtor.
840 bool nrvo = flags.isForNormalCleanup() && nrvoFlag;
841
842 CIRGenBuilderTy &builder = cgf.getBuilder();
843 mlir::OpBuilder::InsertionGuard guard(builder);
844 if (nrvo) {
845 / If we exited via NRVO, we skip the destructor call.
846 mlir::Location loc = addr.getPointer().getLoc();
847 mlir::Value didNRVO = builder.createFlagLoad(loc, nrvoFlag);
848 mlir::Value notNRVO = builder.createNot(didNRVO);
849 cir::IfOp::create(builder, loc, notNRVO, /*withElseRegion=*/false,
850 [&](mlir::OpBuilder &b, mlir::Location) {
851 static_cast<Derived *>(this)->emitDestructorCall(cgf);
852 builder.createYield(loc);
853 });
854 } else {
855 static_cast<Derived *>(this)->emitDestructorCall(cgf);
856 }
857 }
858
859 virtual ~DestroyNRVOVariable() = default;
860};
861
862struct DestroyNRVOVariableCXX final
863 : DestroyNRVOVariable<DestroyNRVOVariableCXX> {
864 DestroyNRVOVariableCXX(Address addr, QualType type,
865 const CXXDestructorDecl *dtor, mlir::Value nrvoFlag)
866 : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, nrvoFlag),
867 dtor(dtor) {}
868
869 const CXXDestructorDecl *dtor;
870
871 void emitDestructorCall(CIRGenFunction &cgf) {
873 /*forVirtualBase=*/false,
874 /*delegating=*/false, addr, ty);
875 }
876};
877
878struct CallStackRestore final : EHScopeStack::Cleanup {
879 Address stack;
880 CallStackRestore(Address stack) : stack(stack) {}
881 void emit(CIRGenFunction &cgf, Flags flags) override {
882 mlir::Location loc = stack.getPointer().getLoc();
883 mlir::Value v = cgf.getBuilder().createLoad(loc, stack);
884 cgf.getBuilder().createStackRestore(loc, v);
885 }
886};
887} / namespace
888
889/ Push the standard destructor for the given type as
890/ at least a normal cleanup.
892 Address addr, QualType type) {
893 assert(dtorKind && "cannot push destructor for trivial type");
894
895 CleanupKind cleanupKind = getCleanupKind(dtorKind);
896 pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind));
897}
898
900 QualType type, Destroyer *destroyer) {
901 pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
902}
903
904/ Destroys all the elements of the given array, beginning from last to first.
905/ The array cannot be zero-length.
906/
907/ \param begin - a type* denoting the first element of the array
908/ \param numElements - the number of elements in the array
909/ \param elementType - the element type of the array
910/ \param destroyer - the function to call to destroy elements
911void CIRGenFunction::emitArrayDestroy(mlir::Value begin,
912 mlir::Value numElements,
913 QualType elementType,
914 CharUnits elementAlign,
915 Destroyer *destroyer) {
916 assert(!elementType->isArrayType());
917
918 / Differently from LLVM traditional codegen, use a higher level
919 / representation instead of lowering directly to a loop.
920 mlir::Type cirElementType = convertTypeForMem(elementType);
921 cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);
922
923 uint64_t size = 0;
924
925 / Optimize for a constant array size.
926 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
927 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())
928 size = constIntAttr.getUInt();
929 } else {
930 cgm.errorNYI(begin.getDefiningOp()->getLoc(),
931 "dynamic-length array expression");
932 }
933
934 auto arrayTy = cir::ArrayType::get(cirElementType, size);
935 mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);
936
937 / Emit the dtor call that will execute for every array element.
938 cir::ArrayDtor::create(
939 builder, *currSrcLoc, arrayOp,
940 [&](mlir::OpBuilder &b, mlir::Location loc) {
941 auto arg = b.getInsertionBlock()->addArgument(ptrToElmType, loc);
942 Address curAddr = Address(arg, cirElementType, elementAlign);
944
945 / Perform the actual destruction there.
946 destroyer(*this, curAddr, elementType);
947
948 cir::YieldOp::create(builder, loc);
949 });
950}
951
952/ Immediately perform the destruction of the given object.
953/
954/ \param addr - the address of the object; a type*
955/ \param type - the type of the object; if an array type, all
956/ objects are destroyed in reverse order
957/ \param destroyer - the function to call to destroy individual
958/ elements
960 Destroyer *destroyer) {
962 if (!arrayType)
963 return destroyer(*this, addr, type);
964
965 mlir::Value length = emitArrayLength(arrayType, type, addr);
966
967 CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement(
968 getContext().getTypeSizeInChars(type));
969
970 auto constantCount = length.getDefiningOp<cir::ConstantOp>();
971 if (!constantCount) {
973 cgm.errorNYI("emitDestroy: variable length array");
974 return;
975 }
976
977 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
978 / If it's constant zero, we can just skip the entire thing.
979 if (constIntAttr && constIntAttr.getUInt() == 0)
980 return;
981
982 mlir::Value begin = addr.getPointer();
984 emitArrayDestroy(begin, length, type, elementAlign, destroyer);
985
986 / If the array destroy didn't use the length op, we can erase it.
987 if (constantCount.use_empty())
988 constantCount.erase();
989}
990
993 switch (kind) {
995 llvm_unreachable("no destroyer for trivial dtor");
997 return destroyCXXObject;
1001 cgm.errorNYI("getDestroyer: other destruction kind");
1002 return nullptr;
1003 }
1004 llvm_unreachable("Unknown DestructionKind");
1005}
1006
1008 ehStack.pushCleanup<CallStackRestore>(kind, spMem);
1009}
1010
1011/ Enter a destroy cleanup for the given local variable.
1013 const CIRGenFunction::AutoVarEmission &emission,
1014 QualType::DestructionKind dtorKind) {
1015 assert(dtorKind != QualType::DK_none);
1016
1017 / Note that for __block variables, we want to destroy the
1018 / original stack object, not the possibly forwarded object.
1019 Address addr = emission.getObjectAddress(*this);
1020
1021 const VarDecl *var = emission.variable;
1022 QualType type = var->getType();
1023
1024 CleanupKind cleanupKind = NormalAndEHCleanup;
1025 CIRGenFunction::Destroyer *destroyer = nullptr;
1026
1027 switch (dtorKind) {
1028 case QualType::DK_none:
1029 llvm_unreachable("no cleanup for trivially-destructible variable");
1030
1032 / If there's an NRVO flag on the emission, we need a different
1033 / cleanup.
1034 if (emission.nrvoFlag) {
1035 assert(!type->isArrayType());
1036 CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
1037 ehStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, type, dtor,
1038 emission.nrvoFlag);
1039 return;
1040 }
1041 / Otherwise, this is handled below.
1042 break;
1043
1047 cgm.errorNYI(var->getSourceRange(),
1048 "emitAutoVarTypeCleanup: other dtor kind");
1049 return;
1050 }
1051
1052 / If we haven't chosen a more specific destroyer, use the default.
1053 if (!destroyer)
1054 destroyer = getDestroyer(dtorKind);
1055
1057 ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
1058}
1059
1061 if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {
1062 for (auto *b : dd->flat_bindings())
1063 if (auto *hd = b->getHoldingVar())
1064 emitVarDecl(*hd);
1065 }
1066}
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)
mlir::Value createNot(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:930
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:90
mlir::Type getElementType() const
Definition Address.h:117
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:130
mlir::Operation * getDefiningOp() const
Get the operation which defines this address.
Definition Address.h:133
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.
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.
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 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
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
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: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:3343
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:4321
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
TLSKind getTLSKind() const
Definition Decl.cpp:2175
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2197
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:2493
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:2858
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:2705
@ 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
@ 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 addAutoInitAnnotation()
static bool addressSpace()
static bool emitNullabilityCheck()
static bool useEHCleanupForArray()
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

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant