clang 22.0.0git
CIRGenClass.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 dealing with C++ code generation of classes
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
14#include "CIRGenFunction.h"
15#include "CIRGenValue.h"
16
18#include "clang/AST/ExprCXX.h"
20#include "clang/AST/Type.h"
22
23using namespace clang;
24using namespace clang::CIRGen;
25
26/// Checks whether the given constructor is a valid subject for the
27/// complete-to-base constructor delegation optimization, i.e. emitting the
28/// complete constructor as a simple call to the base constructor.
30 const CXXConstructorDecl *ctor) {
31 // Currently we disable the optimization for classes with virtual bases
32 // because (1) the address of parameter variables need to be consistent across
33 // all initializers but (2) the delegate function call necessarily creates a
34 // second copy of the parameter variable.
35 //
36 // The limiting example (purely theoretical AFAIK):
37 // struct A { A(int &c) { c++; } };
38 // struct A : virtual A {
39 // B(int count) : A(count) { printf("%d\n", count); }
40 // };
41 // ...although even this example could in principle be emitted as a delegation
42 // since the address of the parameter doesn't escape.
43 if (ctor->getParent()->getNumVBases())
44 return false;
45
46 // We also disable the optimization for variadic functions because it's
47 // impossible to "re-pass" varargs.
48 if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
49 return false;
50
51 // FIXME: Decide if we can do a delegation of a delegating constructor.
52 if (ctor->isDelegatingConstructor())
53 return false;
54
55 return true;
56}
57
59 CXXCtorInitializer *memberInit,
60 LValue &lhs) {
61 FieldDecl *field = memberInit->getAnyMember();
62 if (memberInit->isIndirectMemberInitializer()) {
63 // If we are initializing an anonymous union field, drill down to the field.
64 IndirectFieldDecl *indirectField = memberInit->getIndirectMember();
65 for (const auto *nd : indirectField->chain()) {
66 auto *fd = cast<clang::FieldDecl>(nd);
67 lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());
68 }
69 } else {
70 lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());
71 }
72}
73
75 const CXXRecordDecl *classDecl,
76 CXXCtorInitializer *memberInit,
77 const CXXConstructorDecl *constructor,
78 FunctionArgList &args) {
79 assert(memberInit->isAnyMemberInitializer() &&
80 "Must have member initializer!");
81 assert(memberInit->getInit() && "Must have initializer!");
82
84
85 // non-static data member initializers
86 FieldDecl *field = memberInit->getAnyMember();
87 QualType fieldType = field->getType();
88
89 mlir::Value thisPtr = cgf.loadCXXThis();
90 CanQualType recordTy = cgf.getContext().getCanonicalTagType(classDecl);
91
92 // If a base constructor is being emitted, create an LValue that has the
93 // non-virtual alignment.
94 LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)
95 ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)
96 : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);
97
98 emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);
99
100 // Special case: If we are in a copy or move constructor, and we are copying
101 // an array off PODs or classes with trivial copy constructors, ignore the AST
102 // and perform the copy we know is equivalent.
103 // FIXME: This is hacky at best... if we had a bit more explicit information
104 // in the AST, we could generalize it more easily.
105 const ConstantArrayType *array =
106 cgf.getContext().getAsConstantArrayType(fieldType);
107 if (array && constructor->isDefaulted() &&
108 constructor->isCopyOrMoveConstructor()) {
109 QualType baseElementTy = cgf.getContext().getBaseElementType(array);
110 // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
111 // whereas ClangIR wants to represent all object construction explicitly.
112 if (!baseElementTy->isRecordType()) {
113 cgf.cgm.errorNYI(memberInit->getSourceRange(),
114 "emitMemberInitializer: array of non-record type");
115 return;
116 }
117 }
118
119 cgf.emitInitializerForField(field, lhs, memberInit->getInit());
120}
121
123 const Type *baseType = baseInit->getBaseClass();
124 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
125 return baseClassDecl->isDynamicClass();
126}
127
128namespace {
129/// A visitor which checks whether an initializer uses 'this' in a
130/// way which requires the vtable to be properly set.
131struct DynamicThisUseChecker
132 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
133 using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;
134
135 bool usesThis = false;
136
137 DynamicThisUseChecker(const ASTContext &c) : super(c) {}
138
139 // Black-list all explicit and implicit references to 'this'.
140 //
141 // Do we need to worry about external references to 'this' derived
142 // from arbitrary code? If so, then anything which runs arbitrary
143 // external code might potentially access the vtable.
144 void VisitCXXThisExpr(const CXXThisExpr *e) { usesThis = true; }
145};
146} // end anonymous namespace
147
148static bool baseInitializerUsesThis(ASTContext &c, const Expr *init) {
149 DynamicThisUseChecker checker(c);
150 checker.Visit(init);
151 return checker.usesThis;
152}
153
154/// Gets the address of a direct base class within a complete object.
155/// This should only be used for (1) non-virtual bases or (2) virtual bases
156/// when the type is known to be complete (e.g. in complete destructors).
157///
158/// The object pointed to by 'thisAddr' is assumed to be non-null.
160 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
161 const CXXRecordDecl *base, bool baseIsVirtual) {
162 // 'thisAddr' must be a pointer (in some address space) to Derived.
163 assert(thisAddr.getElementType() == convertType(derived));
164
165 // Compute the offset of the virtual base.
166 CharUnits offset;
167 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
168 if (baseIsVirtual)
169 offset = layout.getVBaseClassOffset(base);
170 else
171 offset = layout.getBaseClassOffset(base);
172
173 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
174 offset.getQuantity(),
175 /*assumeNotNull=*/true);
176}
177
179 const CXXRecordDecl *classDecl,
180 CXXCtorInitializer *baseInit) {
181 assert(curFuncDecl && "loading 'this' without a func declaration?");
183
184 assert(baseInit->isBaseInitializer() && "Must have base initializer!");
185
186 Address thisPtr = loadCXXThisAddress();
187
188 const Type *baseType = baseInit->getBaseClass();
189 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
190
191 bool isBaseVirtual = baseInit->isBaseVirtual();
192
193 // If the initializer for the base (other than the constructor
194 // itself) accesses 'this' in any way, we need to initialize the
195 // vtables.
196 if (baseInitializerUsesThis(getContext(), baseInit->getInit()))
197 initializeVTablePointers(loc, classDecl);
198
199 // We can pretend to be a complete class because it only matters for
200 // virtual bases, and we only do virtual bases for complete ctors.
202 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
206 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
207
208 emitAggExpr(baseInit->getInit(), aggSlot);
209
211}
212
213/// This routine generates necessary code to initialize base classes and
214/// non-static data members belonging to this constructor.
216 CXXCtorType ctorType,
217 FunctionArgList &args) {
218 if (cd->isDelegatingConstructor()) {
220 return;
221 }
222
223 const CXXRecordDecl *classDecl = cd->getParent();
224
225 // Virtual base initializers aren't needed if:
226 // - This is a base ctor variant
227 // - There are no vbases
228 // - The class is abstract, so a complete object of it cannot be constructed
229 //
230 // The check for an abstract class is necessary because sema may not have
231 // marked virtual base destructors referenced.
232 bool constructVBases = ctorType != Ctor_Base &&
233 classDecl->getNumVBases() != 0 &&
234 !classDecl->isAbstract();
235 if (constructVBases &&
236 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
237 cgm.errorNYI(cd->getSourceRange(),
238 "emitCtorPrologue: virtual base without variants");
239 return;
240 }
241
242 // Create three separate ranges for the different types of initializers.
243 auto allInits = cd->inits();
244
245 // Find the boundaries between the three groups.
246 auto virtualBaseEnd = std::find_if(
247 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {
248 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
249 });
250
251 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),
252 [](const CXXCtorInitializer *Init) {
253 return !Init->isBaseInitializer();
254 });
255
256 // Create the three ranges.
257 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);
258 auto nonVirtualBaseInits =
259 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);
260 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());
261
262 const mlir::Value oldThisValue = cxxThisValue;
263
264 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
265 if (cgm.getCodeGenOpts().StrictVTablePointers &&
266 cgm.getCodeGenOpts().OptimizationLevel > 0 &&
267 isInitializerOfDynamicClass(baseInit)) {
268 // It's OK to continue after emitting the error here. The missing code
269 // just "launders" the 'this' pointer.
270 cgm.errorNYI(cd->getSourceRange(),
271 "emitCtorPrologue: strict vtable pointers for vbase");
272 }
273 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
274 };
275
276 // Process virtual base initializers.
277 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
278 if (!constructVBases)
279 continue;
280 emitInitializer(virtualBaseInit);
281 }
282
284
285 // Then, non-virtual base initializers.
286 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
287 assert(!nonVirtualBaseInit->isBaseVirtual());
288 emitInitializer(nonVirtualBaseInit);
289 }
290
291 cxxThisValue = oldThisValue;
292
294
295 // Finally, initialize class members.
297 // Classic codegen uses a special class to attempt to replace member
298 // initializers with memcpy. We could possibly defer that to the
299 // lowering or optimization phases to keep the memory accesses more
300 // explicit. For now, we don't insert memcpy at all.
302 for (CXXCtorInitializer *member : memberInits) {
303 assert(!member->isBaseInitializer());
304 assert(member->isAnyMemberInitializer() &&
305 "Delegating initializer on non-delegating constructor");
306 emitMemberInitializer(*this, cd->getParent(), member, cd, args);
307 }
308}
309
311 mlir::Location loc, CIRGenFunction &cgf, Address addr,
312 CharUnits nonVirtualOffset, mlir::Value virtualOffset,
313 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,
314 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {
315 // Assert that we have something to do.
316 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
317
318 // Compute the offset from the static and dynamic components.
319 mlir::Value baseOffset;
320 if (!nonVirtualOffset.isZero()) {
321 if (virtualOffset) {
322 cgf.cgm.errorNYI(
323 loc,
324 "applyNonVirtualAndVirtualOffset: virtual and non-virtual offset");
325 return Address::invalid();
326 } else {
327 assert(baseValueTy && "expected base type");
328 // If no virtualOffset is present this is the final stop.
329 return cgf.getBuilder().createBaseClassAddr(
330 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),
331 assumeNotNull);
332 }
333 } else {
334 baseOffset = virtualOffset;
335 }
336
337 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,
338 // not bytes. So the pointer must be cast to a byte pointer and back.
339
340 mlir::Value ptr = addr.getPointer();
341 mlir::Type charPtrType = cgf.cgm.UInt8PtrTy;
342 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);
343 mlir::Value adjusted = cir::PtrStrideOp::create(
344 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);
345 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());
346
347 // If we have a virtual component, the alignment of the result will
348 // be relative only to the known alignment of that vbase.
349 CharUnits alignment;
350 if (virtualOffset) {
351 assert(nearestVBase && "virtual offset without vbase?");
352 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,
353 nearestVBase);
354 } else {
355 alignment = addr.getAlignment();
356 }
357 alignment = alignment.alignmentAtOffset(nonVirtualOffset);
358
359 return Address(ptr, alignment);
360}
361
363 const VPtr &vptr) {
364 // Compute the address point.
365 mlir::Value vtableAddressPoint =
366 cgm.getCXXABI().getVTableAddressPointInStructor(
367 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
368
369 if (!vtableAddressPoint)
370 return;
371
372 // Compute where to store the address point.
373 mlir::Value virtualOffset{};
374 CharUnits nonVirtualOffset = CharUnits::Zero();
375
376 mlir::Type baseValueTy;
377 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
378 // We need to use the virtual base offset offset because the virtual base
379 // might have a different offset in the most derived class.
380 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
381 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);
382 nonVirtualOffset = vptr.offsetFromNearestVBase;
383 } else {
384 // We can just use the base offset in the complete class.
385 nonVirtualOffset = vptr.base.getBaseOffset();
386 baseValueTy =
387 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));
388 }
389
390 // Apply the offsets.
391 Address classAddr = loadCXXThisAddress();
392 if (!nonVirtualOffset.isZero() || virtualOffset) {
394 loc, *this, classAddr, nonVirtualOffset, virtualOffset,
395 vptr.vtableClass, vptr.nearestVBase, baseValueTy);
396 }
397
398 // Finally, store the address point. Use the same CIR types as the field.
399 //
400 // vtable field is derived from `this` pointer, therefore they should be in
401 // the same addr space.
403 auto vtablePtr = cir::VTableGetVPtrOp::create(
404 builder, loc, builder.getPtrToVPtrType(), classAddr.getPointer());
405 Address vtableField = Address(vtablePtr, classAddr.getAlignment());
406 builder.createStore(loc, vtableAddressPoint, vtableField);
409}
410
412 const CXXRecordDecl *rd) {
413 // Ignore classes without a vtable.
414 if (!rd->isDynamicClass())
415 return;
416
417 // Initialize the vtable pointers for this class and all of its bases.
418 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
419 for (const auto &vptr : getVTablePointers(rd))
420 initializeVTablePointer(loc, vptr);
421
422 if (rd->getNumVBases())
423 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);
424}
425
428 CIRGenFunction::VPtrsVector vptrsResult;
431 /*NearestVBase=*/nullptr,
432 /*OffsetFromNearestVBase=*/CharUnits::Zero(),
433 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,
434 vptrsResult);
435 return vptrsResult;
436}
437
439 const CXXRecordDecl *nearestVBase,
440 CharUnits offsetFromNearestVBase,
441 bool baseIsNonVirtualPrimaryBase,
442 const CXXRecordDecl *vtableClass,
444 VPtrsVector &vptrs) {
445 // If this base is a non-virtual primary base the address point has already
446 // been set.
447 if (!baseIsNonVirtualPrimaryBase) {
448 // Initialize the vtable pointer for this base.
449 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
450 vptrs.push_back(vptr);
451 }
452
453 const CXXRecordDecl *rd = base.getBase();
454
455 for (const auto &nextBase : rd->bases()) {
456 const auto *baseDecl =
458 nextBase.getType()->castAs<RecordType>()->getOriginalDecl())
459 ->getDefinitionOrSelf();
460
461 // Ignore classes without a vtable.
462 if (!baseDecl->isDynamicClass())
463 continue;
464
465 CharUnits baseOffset;
466 CharUnits baseOffsetFromNearestVBase;
467 bool baseDeclIsNonVirtualPrimaryBase;
468 const CXXRecordDecl *nextBaseDecl;
469
470 if (nextBase.isVirtual()) {
471 // Check if we've visited this virtual base before.
472 if (!vbases.insert(baseDecl).second)
473 continue;
474
475 const ASTRecordLayout &layout =
476 getContext().getASTRecordLayout(vtableClass);
477
478 nextBaseDecl = baseDecl;
479 baseOffset = layout.getVBaseClassOffset(baseDecl);
480 baseOffsetFromNearestVBase = CharUnits::Zero();
481 baseDeclIsNonVirtualPrimaryBase = false;
482 } else {
483 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
484
485 nextBaseDecl = nearestVBase;
486 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);
487 baseOffsetFromNearestVBase =
488 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);
489 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;
490 }
491
492 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,
493 baseOffsetFromNearestVBase,
494 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,
495 vptrs);
496 }
497}
498
500 assert(curFuncDecl && "loading 'this' without a func declaration?");
502
503 // Lazily compute CXXThisAlignment.
504 if (cxxThisAlignment.isZero()) {
505 // Just use the best known alignment for the parent.
506 // TODO: if we're currently emitting a complete-object ctor/dtor, we can
507 // always use the complete-object alignment.
508 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
509 cxxThisAlignment = cgm.getClassPointerAlignment(rd);
510 }
511
513}
514
516 Expr *init) {
517 QualType fieldType = field->getType();
518 switch (getEvaluationKind(fieldType)) {
519 case cir::TEK_Scalar:
520 if (lhs.isSimple()) {
521 emitExprAsInit(init, field, lhs, false);
522 } else {
523 RValue rhs = RValue::get(emitScalarExpr(init));
524 emitStoreThroughLValue(rhs, lhs);
525 }
526 break;
527 case cir::TEK_Complex:
528 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);
529 break;
530 case cir::TEK_Aggregate: {
536 emitAggExpr(init, slot);
537 break;
538 }
539 }
540
541 // Ensure that we destroy this object if an exception is thrown later in the
542 // constructor.
543 QualType::DestructionKind dtorKind = fieldType.isDestructedType();
544 (void)dtorKind;
546}
547
550 const CXXRecordDecl *baseDecl,
551 CharUnits expectedTargetAlign) {
552 // If the base is an incomplete type (which is, alas, possible with
553 // member pointers), be pessimistic.
554 if (!baseDecl->isCompleteDefinition())
555 return std::min(actualBaseAlign, expectedTargetAlign);
556
557 const ASTRecordLayout &baseLayout =
559 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
560
561 // If the class is properly aligned, assume the target offset is, too.
562 //
563 // This actually isn't necessarily the right thing to do --- if the
564 // class is a complete object, but it's only properly aligned for a
565 // base subobject, then the alignments of things relative to it are
566 // probably off as well. (Note that this requires the alignment of
567 // the target to be greater than the NV alignment of the derived
568 // class.)
569 //
570 // However, our approach to this kind of under-alignment can only
571 // ever be best effort; after all, we're never going to propagate
572 // alignments through variables or parameters. Note, in particular,
573 // that constructing a polymorphic type in an address that's less
574 // than pointer-aligned will generally trap in the constructor,
575 // unless we someday add some sort of attribute to change the
576 // assumed alignment of 'this'. So our goal here is pretty much
577 // just to allow the user to explicitly say that a pointer is
578 // under-aligned and then safely access its fields and vtables.
579 if (actualBaseAlign >= expectedBaseAlign)
580 return expectedTargetAlign;
581
582 // Otherwise, we might be offset by an arbitrary multiple of the
583 // actual alignment. The correct adjustment is to take the min of
584 // the two alignments.
585 return std::min(actualBaseAlign, expectedTargetAlign);
586}
587
588/// Return the best known alignment for a pointer to a virtual base,
589/// given the alignment of a pointer to the derived class.
592 const CXXRecordDecl *derivedClass,
593 const CXXRecordDecl *vbaseClass) {
594 // The basic idea here is that an underaligned derived pointer might
595 // indicate an underaligned base pointer.
596
597 assert(vbaseClass->isCompleteDefinition());
598 const ASTRecordLayout &baseLayout =
599 getASTContext().getASTRecordLayout(vbaseClass);
600 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
601
602 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
603 expectedVBaseAlign);
604}
605
606/// Emit a loop to call a particular constructor for each of several members
607/// of an array.
608///
609/// \param ctor the constructor to call for each element
610/// \param arrayType the type of the array to initialize
611/// \param arrayBegin an arrayType*
612/// \param zeroInitialize true if each element should be
613/// zero-initialized before it is constructed
616 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
617 bool zeroInitialize) {
618 QualType elementType;
619 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
620 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
621 newPointerIsChecked, zeroInitialize);
622}
623
624/// Emit a loop to call a particular constructor for each of several members
625/// of an array.
626///
627/// \param ctor the constructor to call for each element
628/// \param numElements the number of elements in the array;
629/// may be zero
630/// \param arrayBase a T*, where T is the type constructed by ctor
631/// \param zeroInitialize true if each element should be
632/// zero-initialized before it is constructed
634 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
635 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize) {
636 // It's legal for numElements to be zero. This can happen both
637 // dynamically, because x can be zero in 'new A[x]', and statically,
638 // because of GCC extensions that permit zero-length arrays. There
639 // are probably legitimate places where we could assume that this
640 // doesn't happen, but it's not clear that it's worth it.
641
642 auto arrayTy = mlir::cast<cir::ArrayType>(arrayBase.getElementType());
643 mlir::Type elementType = arrayTy.getElementType();
644
645 // This might be a multi-dimensional array. Find the innermost element type.
646 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
647 elementType = maybeArrayTy.getElementType();
648 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
649
650 // Optimize for a constant count.
651 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
652 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>()) {
653 // Just skip out if the constant count is zero.
654 if (constIntAttr.getUInt() == 0)
655 return;
656
657 arrayTy = cir::ArrayType::get(elementType, constIntAttr.getUInt());
658 // Otherwise, emit the check.
659 }
660
661 if (constantCount.use_empty())
662 constantCount.erase();
663 } else {
664 // Otherwise, emit the check.
665 cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");
666 }
667
668 // Tradional LLVM codegen emits a loop here. CIR lowers to a loop as part of
669 // LoweringPrepare.
670
671 // The alignment of the base, adjusted by the size of a single element,
672 // provides a conservative estimate of the alignment of every element.
673 // (This assumes we never start tracking offsetted alignments.)
674 //
675 // Note that these are complete objects and so we don't need to
676 // use the non-virtual size or alignment.
678 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
679 getContext().getTypeSizeInChars(type));
680
681 // Zero initialize the storage, if requested.
682 if (zeroInitialize)
684
685 // C++ [class.temporary]p4:
686 // There are two contexts in which temporaries are destroyed at a different
687 // point than the end of the full-expression. The first context is when a
688 // default constructor is called to initialize an element of an array.
689 // If the constructor has one or more default arguments, the destruction of
690 // every temporary created in a default argument expression is sequenced
691 // before the construction of the next array element, if any.
692 {
694
695 // Evaluate the constructor and its arguments in a regular
696 // partial-destroy cleanup.
697 if (getLangOpts().Exceptions &&
698 !ctor->getParent()->hasTrivialDestructor()) {
699 cgm.errorNYI(e->getSourceRange(), "partial array cleanups");
700 }
701
702 // Emit the constructor call that will execute for every array element.
703 mlir::Value arrayOp =
704 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
705 builder.create<cir::ArrayCtor>(
706 *currSrcLoc, arrayOp, [&](mlir::OpBuilder &b, mlir::Location loc) {
707 mlir::BlockArgument arg =
708 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
709 Address curAddr = Address(arg, elementType, eltAlignment);
711 auto currAVS = AggValueSlot::forAddr(
712 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
716 /*ForVirtualBase=*/false,
717 /*Delegating=*/false, currAVS, e);
718 builder.create<cir::YieldOp>(loc);
719 });
720 }
721}
722
724 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
725 const FunctionArgList &args, SourceLocation loc) {
726 CallArgList delegateArgs;
727
728 FunctionArgList::const_iterator i = args.begin(), e = args.end();
729 assert(i != e && "no parameters to constructor");
730
731 // this
732 Address thisAddr = loadCXXThisAddress();
733 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
734 ++i;
735
736 // FIXME: The location of the VTT parameter in the parameter list is specific
737 // to the Itanium ABI and shouldn't be hardcoded here.
738 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
739 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
740 return;
741 }
742
743 // Explicit arguments.
744 for (; i != e; ++i) {
745 const VarDecl *param = *i;
746 // FIXME: per-argument source location
747 emitDelegateCallArg(delegateArgs, param, loc);
748 }
749
751
752 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
753 /*Delegating=*/true, thisAddr, delegateArgs, loc);
754}
755
757 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
758 assert(assignOp->isCopyAssignmentOperator() ||
759 assignOp->isMoveAssignmentOperator());
760 const Stmt *rootS = assignOp->getBody();
761 assert(isa<CompoundStmt>(rootS) &&
762 "Body of an implicit assignment operator should be compound stmt.");
763 const auto *rootCS = cast<CompoundStmt>(rootS);
764
767
768 // Classic codegen uses a special class to attempt to replace member
769 // initializers with memcpy. We could possibly defer that to the
770 // lowering or optimization phases to keep the memory accesses more
771 // explicit. For now, we don't insert memcpy at all, though in some
772 // cases the AST contains a call to memcpy.
774 for (Stmt *s : rootCS->body())
775 if (emitStmt(s, /*useCurrentScope=*/true).failed())
776 cgm.errorNYI(s->getSourceRange(),
777 std::string("emitImplicitAssignmentOperatorBody: ") +
778 s->getStmtClassName());
779}
780
782 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
783 // Get the address of the call operator.
784 const CIRGenFunctionInfo &calleeFnInfo =
785 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
786 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
787 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
788
789 // Prepare the return slot.
790 const FunctionProtoType *fpt =
791 callOperator->getType()->castAs<FunctionProtoType>();
792 QualType resultType = fpt->getReturnType();
793 ReturnValueSlot returnSlot;
794
795 // We don't need to separately arrange the call arguments because
796 // the call can't be variadic anyway --- it's impossible to forward
797 // variadic arguments.
798
799 // Now emit our call.
800 CIRGenCallee callee =
801 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
802 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs);
803
804 // If necessary, copy the returned value into the slot.
805 if (!resultType->isVoidType() && returnSlot.isNull()) {
806 if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType())
807 cgm.errorNYI(callOperator->getSourceRange(),
808 "emitForwardingCallToLambda: ObjCAutoRefCount");
809 emitReturnOfRValue(*currSrcLoc, rv, resultType);
810 } else {
811 cgm.errorNYI(callOperator->getSourceRange(),
812 "emitForwardingCallToLambda: return slot is not null");
813 }
814}
815
817 const CXXRecordDecl *lambda = md->getParent();
818
819 // Start building arguments for forwarding call
820 CallArgList callArgs;
821
822 QualType lambdaType = getContext().getCanonicalTagType(lambda);
823 QualType thisType = getContext().getPointerType(lambdaType);
824 Address thisPtr =
825 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");
826 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);
827
828 // Add the rest of the parameters.
829 for (auto *param : md->parameters())
830 emitDelegateCallArg(callArgs, param, param->getBeginLoc());
831
832 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();
833 // For a generic lambda, find the corresponding call operator specialization
834 // to which the call to the static-invoker shall be forwarded.
835 if (lambda->isGenericLambda()) {
838 FunctionTemplateDecl *callOpTemplate =
840 void *InsertPos = nullptr;
841 FunctionDecl *correspondingCallOpSpecialization =
842 callOpTemplate->findSpecialization(tal->asArray(), InsertPos);
843 assert(correspondingCallOpSpecialization);
844 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
845 }
846 emitForwardingCallToLambda(callOp, callArgs);
847}
848
850 if (md->isVariadic()) {
851 // Codgen for LLVM doesn't emit code for this as well, it says:
852 // FIXME: Making this work correctly is nasty because it requires either
853 // cloning the body of the call operator or making the call operator
854 // forward.
855 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");
856 }
857
859}
860
862 QualType type) {
863 const auto *record = type->castAsCXXRecordDecl();
864 const CXXDestructorDecl *dtor = record->getDestructor();
865 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
866 // dtors which shall be removed on later CIR passes. However, only remove this
867 // assertion after we have a test case to exercise this path.
868 assert(!dtor->isTrivial());
869 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
870 /*delegating=*/false, addr, type);
871}
872
874 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
875 assert(ctor->isDelegatingConstructor());
876
877 Address thisPtr = loadCXXThisAddress();
878
885
886 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
887
888 const CXXRecordDecl *classDecl = ctor->getParent();
889 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
890 cgm.errorNYI(ctor->getSourceRange(),
891 "emitDelegatingCXXConstructorCall: exception");
892 return;
893 }
894}
895
898 bool forVirtualBase, bool delegating,
899 Address thisAddr, QualType thisTy) {
900 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
901 delegating, thisAddr, thisTy);
902}
903
904mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
905 bool delegating) {
906 if (!cgm.getCXXABI().needsVTTParameter(gd))
907 return nullptr;
908
909 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
910 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();
911
912 uint64_t subVTTIndex;
913
914 if (delegating) {
915 // If this is a delegating constructor call, just load the VTT.
916 return loadCXXVTT();
917 } else if (rd == base) {
918 // If the record matches the base, this is the complete ctor/dtor
919 // variant calling the base variant in a class with virtual bases.
920 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
921 "doing no-op VTT offset in base dtor/ctor?");
922 assert(!forVirtualBase && "Can't have same class as virtual base!");
923 subVTTIndex = 0;
924 } else {
925 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
926 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)
927 : layout.getBaseClassOffset(base);
928
929 subVTTIndex =
930 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));
931 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
932 }
933
934 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
935 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
936 // A VTT parameter was passed to the constructor, use it.
937 mlir::Value vtt = loadCXXVTT();
938 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
939 } else {
940 // We're the complete constructor, so get the VTT by name.
941 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);
942 return builder.createVTTAddrPoint(
943 loc, builder.getPointerTo(cgm.VoidPtrTy),
944 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);
945 }
946}
947
949 Address value, const CXXRecordDecl *derived,
950 llvm::iterator_range<CastExpr::path_const_iterator> path,
951 bool nullCheckValue, SourceLocation loc) {
952 assert(!path.empty() && "Base path should not be empty!");
953
954 if ((*path.begin())->isVirtual()) {
955 // The implementation here is actually complete, but let's flag this
956 // as an error until the rest of the virtual base class support is in place.
957 cgm.errorNYI(loc, "getAddrOfBaseClass: virtual base");
958 return Address::invalid();
959 }
960
961 // Compute the static offset of the ultimate destination within its
962 // allocating subobject (the virtual base, if there is one, or else
963 // the "complete" object that we see).
964 CharUnits nonVirtualOffset =
965 cgm.computeNonVirtualBaseClassOffset(derived, path);
966
967 // Get the base pointer type.
968 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
970
971 // The if statement here is redundant now, but it will be needed when we add
972 // support for virtual base classes.
973 // If there is no virtual base, use cir.base_class_addr. It takes care of
974 // the adjustment and the null pointer check.
975 if (nonVirtualOffset.isZero()) {
977 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
978 /*assumeNotNull=*/true);
979 }
980
982
983 // Apply the offset
984 value = builder.createBaseClassAddr(getLoc(loc), value, baseValueTy,
985 nonVirtualOffset.getQuantity(),
986 /*assumeNotNull=*/true);
987
988 // Cast to the destination type.
989 value = value.withElementType(builder, baseValueTy);
990
991 return value;
992}
993
994// TODO(cir): this can be shared with LLVM codegen.
997 if (!cgm.getCodeGenOpts().WholeProgramVTables)
998 return false;
999
1000 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1001 return true;
1002
1004
1005 return false;
1006}
1007
1008mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1009 const CXXRecordDecl *rd) {
1010 auto vtablePtr = cir::VTableGetVPtrOp::create(
1011 builder, loc, builder.getPtrToVPtrType(), thisAddr.getPointer());
1012 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1013
1014 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1016
1017 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1018 cgm.getCodeGenOpts().StrictVTablePointers) {
1020 }
1021
1022 return vtable;
1023}
1024
1027 bool forVirtualBase,
1028 bool delegating,
1029 AggValueSlot thisAVS,
1030 const clang::CXXConstructExpr *e) {
1031 CallArgList args;
1032 Address thisAddr = thisAVS.getAddress();
1033 QualType thisType = d->getThisType();
1034 mlir::Value thisPtr = thisAddr.getPointer();
1035
1037
1038 args.add(RValue::get(thisPtr), thisType);
1039
1040 // In LLVM Codegen: If this is a trivial constructor, just emit what's needed.
1041 // If this is a union copy constructor, we must emit a memcpy, because the AST
1042 // does not model that copy.
1044
1045 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1046
1048
1049 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1050 /*ParamsToSkip=*/0);
1051
1053 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1054 e->getExprLoc());
1055}
1056
1058 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1059 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1060
1061 const CXXRecordDecl *crd = d->getParent();
1062
1063 // If this is a call to a trivial default constructor:
1064 // In LLVM: do nothing.
1065 // In CIR: emit as a regular call, other later passes should lower the
1066 // ctor call into trivial initialization.
1068
1070
1071 bool passPrototypeArgs = true;
1072
1073 // Check whether we can actually emit the constructor before trying to do so.
1074 if (d->getInheritedConstructor()) {
1075 cgm.errorNYI(d->getSourceRange(),
1076 "emitCXXConstructorCall: inherited constructor");
1077 return;
1078 }
1079
1080 // Insert any ABI-specific implicit constructor arguments.
1082 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1083 delegating, args);
1084
1085 // Emit the call.
1086 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1087 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1088 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1089 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1090 cir::CIRCallOpInterface c;
1091 emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
1092
1093 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1094 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1095 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1096}
static bool baseInitializerUsesThis(ASTContext &c, const Expr *init)
static Address applyNonVirtualAndVirtualOffset(mlir::Location loc, CIRGenFunction &cgf, Address addr, CharUnits nonVirtualOffset, mlir::Value virtualOffset, const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase, mlir::Type baseValueTy={}, bool assumeNotNull=true)
static void emitMemberInitializer(CIRGenFunction &cgf, const CXXRecordDecl *classDecl, CXXCtorInitializer *memberInit, const CXXConstructorDecl *constructor, FunctionArgList &args)
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit)
static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf, CXXCtorInitializer *memberInit, LValue &lhs)
Defines the clang::Expr interface and subclasses for C++ expressions.
C Language Family Type Representation.
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:188
const ConstantArrayType * getAsConstantArrayType(QualType T) const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3720
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
mlir::Value getPointer() const
Definition Address.h:81
mlir::Type getElementType() const
Definition Address.h:101
static Address invalid()
Definition Address.h:66
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:109
An aggregate value slot.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
Address createBaseClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull)
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:90
A scope within which we are constructing the fields of an object which might use a CXXDefaultInitExpr...
static bool isConstructorDelegationValid(const clang::CXXConstructorDecl *ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md)
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
const clang::LangOptions & getLangOpts() const
void emitForwardingCallToLambda(const CXXMethodDecl *lambdaCallOperator, CallArgList &callArgs)
mlir::Value loadCXXThis()
Load the value for 'this'.
LValue makeNaturalAlignPointeeAddrLValue(mlir::Value v, clang::QualType t)
Given a value of type T* that may not be to a complete object, construct an l-vlaue withi the natural...
clang::CharUnits cxxThisAlignment
const clang::Decl * curFuncDecl
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void initializeVTablePointers(mlir::Location loc, const clang::CXXRecordDecl *rd)
void initializeVTablePointer(mlir::Location loc, const VPtr &vptr)
Address getAddressOfBaseClass(Address value, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue, SourceLocation loc)
void emitDelegateCXXConstructorCall(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, const FunctionArgList &args, clang::SourceLocation loc)
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl, CXXCtorInitializer *baseInit)
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...
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
VPtrsVector getVTablePointers(const clang::CXXRecordDecl *vtableClass)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
void emitCtorPrologue(const clang::CXXConstructorDecl *ctor, clang::CXXCtorType ctorType, FunctionArgList &args)
This routine generates necessary code to initialize base classes and non-static data members belongin...
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
llvm::SmallPtrSet< const clang::CXXRecordDecl *, 4 > VisitedVirtualBasesSetTy
void emitReturnOfRValue(mlir::Location loc, RValue rv, QualType ty)
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
void emitInitializerForField(clang::FieldDecl *field, LValue lhs, clang::Expr *init)
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
CIRGenBuilderTy & getBuilder()
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
llvm::SmallVector< VPtr, 4 > VPtrsVector
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
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 ...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitDelegatingCXXConstructorCall(const CXXConstructorDecl *ctor, const FunctionArgList &args)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign, const CXXRecordDecl *baseDecl, CharUnits expectedTargetAlign)
TODO: Add TBAAAccessInfo.
CharUnits getVBaseAlignment(CharUnits derivedAlign, const CXXRecordDecl *derived, const CXXRecordDecl *vbase)
Returns the assumed alignment of a virtual base of a class.
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:231
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:191
bool isSimple() 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:82
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:252
Represents a call to a C++ constructor.
Definition ExprCXX.h:1549
arg_range arguments()
Definition ExprCXX.h:1673
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1612
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
init_iterator init_begin()
Retrieve an iterator to the first initializer.
Definition DeclCXX.h:2701
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
Definition DeclCXX.h:2757
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Definition DeclCXX.cpp:3019
InheritedConstructor getInheritedConstructor() const
Get the constructor that this inheriting constructor is based on.
Definition DeclCXX.h:2842
Represents a C++ base or member initializer.
Definition DeclCXX.h:2369
Expr * getInit() const
Get the initializer.
Definition DeclCXX.h:2571
SourceRange getSourceRange() const LLVM_READONLY
Determine the source range covering the entire initializer.
Definition DeclCXX.cpp:2916
bool isAnyMemberInitializer() const
Definition DeclCXX.h:2449
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Definition DeclCXX.h:2441
bool isIndirectMemberInitializer() const
Definition DeclCXX.h:2453
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Definition DeclCXX.cpp:2896
FieldDecl * getAnyMember() const
Definition DeclCXX.h:2515
IndirectFieldDecl * getIndirectMember() const
Definition DeclCXX.h:2523
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Definition DeclCXX.h:2495
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2809
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
Definition DeclCXX.cpp:1673
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1366
base_class_range bases()
Definition DeclCXX.h:608
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1221
bool isDynamicClass() const
Definition DeclCXX.h:574
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition DeclCXX.cpp:1736
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
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 Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3758
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:830
This represents one expression.
Definition Expr.h:112
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
Represents a member of a struct/union/class.
Definition Decl.h:3157
Represents a function declaration or definition.
Definition Decl.h:1999
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4146
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4134
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2771
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2376
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3125
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4270
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2384
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4490
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5264
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5668
Declaration of a template function.
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
QualType getReturnType() const
Definition TypeBase.h:4800
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
CXXCtorType getCtorType() const
Definition GlobalDecl.h:108
const Decl * getDecl() const
Definition GlobalDecl.h:106
Represents a field injected from an anonymous union/struct into the parent scope.
Definition Decl.h:3464
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3485
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:300
A (possibly-)qualified type.
Definition TypeBase.h:937
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1545
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
Encodes a location in the source.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3809
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3544
The base class of the type hierarchy.
Definition TypeBase.h:1833
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9165
bool isRecordType() const
Definition TypeBase.h:8649
QualType getType() const
Definition Decl.h:722
Represents a variable declaration or definition.
Definition Decl.h:925
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
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.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
CXXDtorType
C++ destructor types.
Definition ABI.h:34
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool addressSpace()
static bool aggValueSlotGC()
static bool isMemcpyEquivalentSpecialMember()
static bool hiddenVisibility()
static bool runCleanupsScope()
static bool opCallArgEvaluationOrder()
static bool createInvariantGroup()
static bool isTrivialCtorOrDtor()
static bool assignMemcpyizer()
static bool ctorMemcpyizer()
static bool requiresCleanups()
static bool generateDebugInfo()
static bool incrementProfileCounter()
Similar to AddedStructorArgs, but only notes the number of additional arguments.
const clang::CXXRecordDecl * vtableClass
const clang::CXXRecordDecl * nearestVBase