clang 23.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"
23
24using namespace clang;
25using namespace clang::CIRGen;
26
27/// Return the smallest possible amount of storage that might be allocated
28/// starting from the beginning of an object of a particular class.
29///
30/// This may be smaller than sizeof(RD) if RD has virtual base classes.
32 if (!rd->hasDefinition())
33 return CharUnits::One();
34
35 auto &layout = getASTContext().getASTRecordLayout(rd);
36
37 // If the class is final, then we know that the pointer points to an
38 // object of that type and can use the full alignment.
39 if (rd->isEffectivelyFinal())
40 return layout.getSize();
41
42 // Otherwise, we have to assume it could be a subclass.
43 return std::max(layout.getNonVirtualSize(), CharUnits::One());
44}
45
46/// Checks whether the given constructor is a valid subject for the
47/// complete-to-base constructor delegation optimization, i.e. emitting the
48/// complete constructor as a simple call to the base constructor.
50 const CXXConstructorDecl *ctor) {
51 // Currently we disable the optimization for classes with virtual bases
52 // because (1) the address of parameter variables need to be consistent across
53 // all initializers but (2) the delegate function call necessarily creates a
54 // second copy of the parameter variable.
55 //
56 // The limiting example (purely theoretical AFAIK):
57 // struct A { A(int &c) { c++; } };
58 // struct A : virtual A {
59 // B(int count) : A(count) { printf("%d\n", count); }
60 // };
61 // ...although even this example could in principle be emitted as a delegation
62 // since the address of the parameter doesn't escape.
63 if (ctor->getParent()->getNumVBases())
64 return false;
65
66 // We also disable the optimization for variadic functions because it's
67 // impossible to "re-pass" varargs.
68 if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
69 return false;
70
71 // FIXME: Decide if we can do a delegation of a delegating constructor.
72 if (ctor->isDelegatingConstructor())
73 return false;
74
75 return true;
76}
77
79 CXXCtorInitializer *memberInit,
80 LValue &lhs) {
81 FieldDecl *field = memberInit->getAnyMember();
82 if (memberInit->isIndirectMemberInitializer()) {
83 // If we are initializing an anonymous union field, drill down to the field.
84 IndirectFieldDecl *indirectField = memberInit->getIndirectMember();
85 for (const auto *nd : indirectField->chain()) {
86 auto *fd = cast<clang::FieldDecl>(nd);
87 lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());
88 }
89 } else {
90 lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());
91 }
92}
93
95 const CXXRecordDecl *classDecl,
96 CXXCtorInitializer *memberInit,
97 const CXXConstructorDecl *constructor,
98 FunctionArgList &args) {
99 assert(memberInit->isAnyMemberInitializer() &&
100 "Must have member initializer!");
101 assert(memberInit->getInit() && "Must have initializer!");
102
104
105 // non-static data member initializers
106 FieldDecl *field = memberInit->getAnyMember();
107 QualType fieldType = field->getType();
108
109 mlir::Value thisPtr = cgf.loadCXXThis();
110 CanQualType recordTy = cgf.getContext().getCanonicalTagType(classDecl);
111
112 // If a base constructor is being emitted, create an LValue that has the
113 // non-virtual alignment.
114 LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)
115 ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)
116 : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);
117
118 emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);
119
120 // Special case: If we are in a copy or move constructor, and we are copying
121 // an array off PODs or classes with trivial copy constructors, ignore the AST
122 // and perform the copy we know is equivalent.
123 // FIXME: This is hacky at best... if we had a bit more explicit information
124 // in the AST, we could generalize it more easily.
125 const ConstantArrayType *array =
126 cgf.getContext().getAsConstantArrayType(fieldType);
127 if (array && constructor->isDefaulted() &&
128 constructor->isCopyOrMoveConstructor()) {
129 QualType baseElementTy = cgf.getContext().getBaseElementType(array);
130 // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
131 // whereas ClangIR wants to represent all object construction explicitly.
132 if (!baseElementTy->isRecordType()) {
133 unsigned srcArgIndex =
134 cgf.cgm.getCXXABI().getSrcArgforCopyCtor(constructor, args);
135 cir::LoadOp srcPtr = cgf.getBuilder().createLoad(
136 cgf.getLoc(memberInit->getSourceLocation()),
137 cgf.getAddrOfLocalVar(args[srcArgIndex]));
138 LValue thisRhslv = cgf.makeNaturalAlignAddrLValue(srcPtr, recordTy);
139 LValue src = cgf.emitLValueForFieldInitialization(thisRhslv, field,
140 field->getName());
141
142 // Copy the aggregate.
143 cgf.emitAggregateCopy(lhs, src, fieldType,
144 cgf.getOverlapForFieldInit(field),
145 lhs.isVolatileQualified());
146 // Ensure that we destroy the objects if an exception is thrown later in
147 // the constructor.
148 assert(!cgf.needsEHCleanup(fieldType.isDestructedType()) &&
149 "Arrays of non-record types shouldn't need EH cleanup");
150 return;
151 }
152 }
153
154 cgf.emitInitializerForField(field, lhs, memberInit->getInit());
155}
156
158 const Type *baseType = baseInit->getBaseClass();
159 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
160 return baseClassDecl->isDynamicClass();
161}
162
163namespace {
164/// Call the destructor for a direct base class.
165struct CallBaseDtor final : EHScopeStack::Cleanup {
166 const CXXRecordDecl *baseClass;
167 bool baseIsVirtual;
168 CallBaseDtor(const CXXRecordDecl *base, bool baseIsVirtual)
169 : baseClass(base), baseIsVirtual(baseIsVirtual) {}
170
171 void emit(CIRGenFunction &cgf, Flags flags) override {
172 const CXXRecordDecl *derivedClass =
173 cast<CXXMethodDecl>(cgf.curFuncDecl)->getParent();
174
175 const CXXDestructorDecl *d = baseClass->getDestructor();
176 // We are already inside a destructor, so presumably the object being
177 // destroyed should have the expected type.
178 QualType thisTy = d->getFunctionObjectParameterType();
179 assert(cgf.currSrcLoc && "expected source location");
181 *cgf.currSrcLoc, cgf.loadCXXThisAddress(), derivedClass, baseClass,
182 baseIsVirtual);
183 cgf.emitCXXDestructorCall(d, Dtor_Base, baseIsVirtual,
184 /*delegating=*/false, addr, thisTy);
185 }
186};
187
188/// If the delegating constructor's body throws after the delegated-to
189/// constructor completes, destroy the object (mirrors CGClass.cpp's
190/// CallDelegatingCtorDtor).
191struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
192 const CXXDestructorDecl *dtor;
193 Address addr;
195
196 CallDelegatingCtorDtor(const CXXDestructorDecl *dtor, Address addr,
198 : dtor(dtor), addr(addr), type(type) {}
199
200 void emit(CIRGenFunction &cgf, Flags flags) override {
201 QualType thisTy = dtor->getFunctionObjectParameterType();
202 cgf.emitCXXDestructorCall(dtor, type, /*forVirtualBase=*/false,
203 /*delegating=*/true, addr, thisTy);
204 }
205};
206
207/// A visitor which checks whether an initializer uses 'this' in a
208/// way which requires the vtable to be properly set.
209struct DynamicThisUseChecker
210 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
211 using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;
212
213 bool usesThis = false;
214
215 DynamicThisUseChecker(const ASTContext &c) : super(c) {}
216
217 // Black-list all explicit and implicit references to 'this'.
218 //
219 // Do we need to worry about external references to 'this' derived
220 // from arbitrary code? If so, then anything which runs arbitrary
221 // external code might potentially access the vtable.
222 void VisitCXXThisExpr(const CXXThisExpr *e) { usesThis = true; }
223};
224} // end anonymous namespace
225
226static bool baseInitializerUsesThis(ASTContext &c, const Expr *init) {
227 DynamicThisUseChecker checker(c);
228 checker.Visit(init);
229 return checker.usesThis;
230}
231
232/// Gets the address of a direct base class within a complete object.
233/// This should only be used for (1) non-virtual bases or (2) virtual bases
234/// when the type is known to be complete (e.g. in complete destructors).
235///
236/// The object pointed to by 'thisAddr' is assumed to be non-null.
238 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
239 const CXXRecordDecl *base, bool baseIsVirtual) {
240 // 'thisAddr' must be a pointer (in some address space) to Derived.
241 assert(thisAddr.getElementType() == convertType(derived));
242
243 // Compute the offset of the virtual base.
244 CharUnits offset;
245 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
246 if (baseIsVirtual)
247 offset = layout.getVBaseClassOffset(base);
248 else
249 offset = layout.getBaseClassOffset(base);
250
251 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
252 offset.getQuantity(),
253 /*assumeNotNull=*/true);
254}
255
257 const CXXRecordDecl *classDecl,
258 CXXCtorInitializer *baseInit) {
259 assert(curFuncDecl && "loading 'this' without a func declaration?");
261
262 assert(baseInit->isBaseInitializer() && "Must have base initializer!");
263
264 Address thisPtr = loadCXXThisAddress();
265
266 const Type *baseType = baseInit->getBaseClass();
267 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
268
269 bool isBaseVirtual = baseInit->isBaseVirtual();
270
271 // If the initializer for the base (other than the constructor
272 // itself) accesses 'this' in any way, we need to initialize the
273 // vtables.
274 if (baseInitializerUsesThis(getContext(), baseInit->getInit()))
275 initializeVTablePointers(loc, classDecl);
276
277 // We can pretend to be a complete class because it only matters for
278 // virtual bases, and we only do virtual bases for complete ctors.
280 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
284 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
285
286 emitAggExpr(baseInit->getInit(), aggSlot);
287
288 if (cgm.getLangOpts().Exceptions && !baseClassDecl->hasTrivialDestructor())
289 ehStack.pushCleanup<CallBaseDtor>(EHCleanup, baseClassDecl,
290 /*baseIsVirtual=*/isBaseVirtual);
291}
292
293/// This routine generates necessary code to initialize base classes and
294/// non-static data members belonging to this constructor.
296 CXXCtorType ctorType,
297 FunctionArgList &args) {
298 if (cd->isDelegatingConstructor()) {
300 return;
301 }
302
303 const CXXRecordDecl *classDecl = cd->getParent();
304
305 // Virtual base initializers aren't needed if:
306 // - This is a base ctor variant
307 // - There are no vbases
308 // - The class is abstract, so a complete object of it cannot be constructed
309 //
310 // The check for an abstract class is necessary because sema may not have
311 // marked virtual base destructors referenced.
312 bool constructVBases = ctorType != Ctor_Base &&
313 classDecl->getNumVBases() != 0 &&
314 !classDecl->isAbstract();
315 if (constructVBases &&
316 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
317 cgm.errorNYI(cd->getSourceRange(),
318 "emitCtorPrologue: virtual base without variants");
319 return;
320 }
321
322 // Create three separate ranges for the different types of initializers.
323 auto allInits = cd->inits();
324
325 // Find the boundaries between the three groups.
326 auto virtualBaseEnd = std::find_if(
327 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {
328 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
329 });
330
331 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),
332 [](const CXXCtorInitializer *Init) {
333 return !Init->isBaseInitializer();
334 });
335
336 // Create the three ranges.
337 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);
338 auto nonVirtualBaseInits =
339 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);
340 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());
341
342 const mlir::Value oldThisValue = cxxThisValue;
343
344 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
345 if (cgm.getCodeGenOpts().StrictVTablePointers &&
346 cgm.getCodeGenOpts().OptimizationLevel > 0 &&
347 isInitializerOfDynamicClass(baseInit)) {
348 // It's OK to continue after emitting the error here. The missing code
349 // just "launders" the 'this' pointer.
350 cgm.errorNYI(cd->getSourceRange(),
351 "emitCtorPrologue: strict vtable pointers for vbase");
352 }
353 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
354 };
355
356 // Process virtual base initializers.
357 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
358 if (!constructVBases)
359 continue;
360 emitInitializer(virtualBaseInit);
361 }
362
364
365 // Then, non-virtual base initializers.
366 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
367 assert(!nonVirtualBaseInit->isBaseVirtual());
368 emitInitializer(nonVirtualBaseInit);
369 }
370
371 cxxThisValue = oldThisValue;
372
374
375 // Finally, initialize class members.
377 // Classic codegen uses a special class to attempt to replace member
378 // initializers with memcpy. We could possibly defer that to the
379 // lowering or optimization phases to keep the memory accesses more
380 // explicit. For now, we don't insert memcpy at all.
382 for (CXXCtorInitializer *member : memberInits) {
383 assert(!member->isBaseInitializer());
384 assert(member->isAnyMemberInitializer() &&
385 "Delegating initializer on non-delegating constructor");
386 emitMemberInitializer(*this, cd->getParent(), member, cd, args);
387 }
388}
389
391 mlir::Location loc, CIRGenFunction &cgf, Address addr,
392 CharUnits nonVirtualOffset, mlir::Value virtualOffset,
393 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,
394 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {
395 // Assert that we have something to do.
396 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
397
398 // Compute the offset from the static and dynamic components.
399 mlir::Value baseOffset;
400 if (!nonVirtualOffset.isZero()) {
401 if (virtualOffset) {
402 cgf.cgm.errorNYI(
403 loc,
404 "applyNonVirtualAndVirtualOffset: virtual and non-virtual offset");
405 return Address::invalid();
406 } else {
407 assert(baseValueTy && "expected base type");
408 // If no virtualOffset is present this is the final stop.
409 return cgf.getBuilder().createBaseClassAddr(
410 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),
411 assumeNotNull);
412 }
413 } else {
414 baseOffset = virtualOffset;
415 }
416
417 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,
418 // not bytes. So the pointer must be cast to a byte pointer and back.
419
420 mlir::Value ptr = addr.getPointer();
421 mlir::Type charPtrType = cgf.cgm.uInt8PtrTy;
422 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);
423 mlir::Value adjusted = cir::PtrStrideOp::create(
424 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);
425 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());
426
427 // If we have a virtual component, the alignment of the result will
428 // be relative only to the known alignment of that vbase.
429 CharUnits alignment;
430 if (virtualOffset) {
431 assert(nearestVBase && "virtual offset without vbase?");
432 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,
433 nearestVBase);
434 } else {
435 alignment = addr.getAlignment();
436 }
437 alignment = alignment.alignmentAtOffset(nonVirtualOffset);
438
439 return Address(ptr, alignment);
440}
441
443 const VPtr &vptr) {
444 // Compute the address point.
445 mlir::Value vtableAddressPoint =
446 cgm.getCXXABI().getVTableAddressPointInStructor(
447 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
448
449 if (!vtableAddressPoint)
450 return;
451
452 // Compute where to store the address point.
453 mlir::Value virtualOffset{};
454 CharUnits nonVirtualOffset = CharUnits::Zero();
455
456 mlir::Type baseValueTy;
457 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
458 // We need to use the virtual base offset offset because the virtual base
459 // might have a different offset in the most derived class.
460 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
461 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);
462 nonVirtualOffset = vptr.offsetFromNearestVBase;
463 } else {
464 // We can just use the base offset in the complete class.
465 nonVirtualOffset = vptr.base.getBaseOffset();
466 baseValueTy =
467 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));
468 }
469
470 // Apply the offsets.
471 Address classAddr = loadCXXThisAddress();
472 if (!nonVirtualOffset.isZero() || virtualOffset) {
474 loc, *this, classAddr, nonVirtualOffset, virtualOffset,
475 vptr.vtableClass, vptr.nearestVBase, baseValueTy);
476 }
477
478 // Finally, store the address point. Use the same CIR types as the field.
479 //
480 // vtable field is derived from `this` pointer, therefore they should be in
481 // the same addr space.
483 auto vtablePtr =
484 cir::VTableGetVPtrOp::create(builder, loc, classAddr.getPointer());
485 Address vtableField = Address(vtablePtr, classAddr.getAlignment());
486 builder.createStore(loc, vtableAddressPoint, vtableField);
489}
490
492 const CXXRecordDecl *rd) {
493 // Ignore classes without a vtable.
494 if (!rd->isDynamicClass())
495 return;
496
497 // Initialize the vtable pointers for this class and all of its bases.
498 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
499 for (const auto &vptr : getVTablePointers(rd))
500 initializeVTablePointer(loc, vptr);
501
502 if (rd->getNumVBases())
503 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);
504}
505
508 CIRGenFunction::VPtrsVector vptrsResult;
511 /*NearestVBase=*/nullptr,
512 /*OffsetFromNearestVBase=*/CharUnits::Zero(),
513 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,
514 vptrsResult);
515 return vptrsResult;
516}
517
519 const CXXRecordDecl *nearestVBase,
520 CharUnits offsetFromNearestVBase,
521 bool baseIsNonVirtualPrimaryBase,
522 const CXXRecordDecl *vtableClass,
524 VPtrsVector &vptrs) {
525 // If this base is a non-virtual primary base the address point has already
526 // been set.
527 if (!baseIsNonVirtualPrimaryBase) {
528 // Initialize the vtable pointer for this base.
529 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
530 vptrs.push_back(vptr);
531 }
532
533 const CXXRecordDecl *rd = base.getBase();
534
535 for (const auto &nextBase : rd->bases()) {
536 const auto *baseDecl =
537 cast<CXXRecordDecl>(nextBase.getType()->castAs<RecordType>()->getDecl())
538 ->getDefinitionOrSelf();
539
540 // Ignore classes without a vtable.
541 if (!baseDecl->isDynamicClass())
542 continue;
543
544 CharUnits baseOffset;
545 CharUnits baseOffsetFromNearestVBase;
546 bool baseDeclIsNonVirtualPrimaryBase;
547 const CXXRecordDecl *nextBaseDecl;
548
549 if (nextBase.isVirtual()) {
550 // Check if we've visited this virtual base before.
551 if (!vbases.insert(baseDecl).second)
552 continue;
553
554 const ASTRecordLayout &layout =
555 getContext().getASTRecordLayout(vtableClass);
556
557 nextBaseDecl = baseDecl;
558 baseOffset = layout.getVBaseClassOffset(baseDecl);
559 baseOffsetFromNearestVBase = CharUnits::Zero();
560 baseDeclIsNonVirtualPrimaryBase = false;
561 } else {
562 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
563
564 nextBaseDecl = nearestVBase;
565 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);
566 baseOffsetFromNearestVBase =
567 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);
568 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;
569 }
570
571 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,
572 baseOffsetFromNearestVBase,
573 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,
574 vptrs);
575 }
576}
577
579 assert(curFuncDecl && "loading 'this' without a func declaration?");
581
582 // Lazily compute CXXThisAlignment.
583 if (cxxThisAlignment.isZero()) {
584 // Just use the best known alignment for the parent.
585 // TODO: if we're currently emitting a complete-object ctor/dtor, we can
586 // always use the complete-object alignment.
587 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
588 cxxThisAlignment = cgm.getClassPointerAlignment(rd);
589 }
590
592}
593
595 Expr *init) {
596 QualType fieldType = field->getType();
597 switch (getEvaluationKind(fieldType)) {
598 case cir::TEK_Scalar:
599 if (lhs.isSimple()) {
600 emitExprAsInit(init, field, lhs, false);
601 } else {
602 RValue rhs = RValue::get(emitScalarExpr(init));
603 emitStoreThroughLValue(rhs, lhs);
604 }
605 break;
606 case cir::TEK_Complex:
607 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);
608 break;
609 case cir::TEK_Aggregate: {
615 emitAggExpr(init, slot);
616 break;
617 }
618 }
619
620 // Ensure that we destroy this object if an exception is thrown later in the
621 // constructor.
622 QualType::DestructionKind dtorKind = fieldType.isDestructedType();
623 pushEHDestroyIfNeeded(dtorKind, lhs.getAddress(), fieldType);
624}
625
627 const Expr *e, Address base, mlir::Value memberPtr,
628 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo) {
630
631 cir::GetRuntimeMemberOp op = builder.createGetIndirectMember(
632 getLoc(e->getSourceRange()), base.getPointer(), memberPtr);
633
634 QualType memberType = memberPtrType->getPointeeType();
636 CharUnits memberAlign = cgm.getNaturalTypeAlignment(memberType, baseInfo);
637 memberAlign = cgm.getDynamicOffsetAlignment(
638 base.getAlignment(), memberPtrType->getMostRecentCXXRecordDecl(),
639 memberAlign);
640
641 return Address(op, convertTypeForMem(memberPtrType->getPointeeType()),
642 memberAlign);
643}
644
647 const CXXRecordDecl *baseDecl,
648 CharUnits expectedTargetAlign) {
649 // If the base is an incomplete type (which is, alas, possible with
650 // member pointers), be pessimistic.
651 if (!baseDecl->isCompleteDefinition())
652 return std::min(actualBaseAlign, expectedTargetAlign);
653
654 const ASTRecordLayout &baseLayout =
656 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
657
658 // If the class is properly aligned, assume the target offset is, too.
659 //
660 // This actually isn't necessarily the right thing to do --- if the
661 // class is a complete object, but it's only properly aligned for a
662 // base subobject, then the alignments of things relative to it are
663 // probably off as well. (Note that this requires the alignment of
664 // the target to be greater than the NV alignment of the derived
665 // class.)
666 //
667 // However, our approach to this kind of under-alignment can only
668 // ever be best effort; after all, we're never going to propagate
669 // alignments through variables or parameters. Note, in particular,
670 // that constructing a polymorphic type in an address that's less
671 // than pointer-aligned will generally trap in the constructor,
672 // unless we someday add some sort of attribute to change the
673 // assumed alignment of 'this'. So our goal here is pretty much
674 // just to allow the user to explicitly say that a pointer is
675 // under-aligned and then safely access its fields and vtables.
676 if (actualBaseAlign >= expectedBaseAlign)
677 return expectedTargetAlign;
678
679 // Otherwise, we might be offset by an arbitrary multiple of the
680 // actual alignment. The correct adjustment is to take the min of
681 // the two alignments.
682 return std::min(actualBaseAlign, expectedTargetAlign);
683}
684
685/// Return the best known alignment for a pointer to a virtual base,
686/// given the alignment of a pointer to the derived class.
689 const CXXRecordDecl *derivedClass,
690 const CXXRecordDecl *vbaseClass) {
691 // The basic idea here is that an underaligned derived pointer might
692 // indicate an underaligned base pointer.
693
694 assert(vbaseClass->isCompleteDefinition());
695 const ASTRecordLayout &baseLayout =
696 getASTContext().getASTRecordLayout(vbaseClass);
697 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
698
699 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
700 expectedVBaseAlign);
701}
702
703/// Emit a loop to call a particular constructor for each of several members
704/// of an array.
705///
706/// \param ctor the constructor to call for each element
707/// \param arrayType the type of the array to initialize
708/// \param arrayBegin an arrayType*
709/// \param zeroInitialize true if each element should be
710/// zero-initialized before it is constructed
713 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
714 bool zeroInitialize) {
715 QualType elementType;
716 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
717 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
718 newPointerIsChecked, zeroInitialize);
719}
720
721/// Emit a loop to call a particular constructor for each of several members
722/// of an array.
723///
724/// \param ctor the constructor to call for each element
725/// \param numElements the number of elements in the array;
726/// may be zero
727/// \param arrayBase a T*, where T is the type constructed by ctor
728/// \param zeroInitialize true if each element should be
729/// zero-initialized before it is constructed
731 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
732 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize) {
733 // It's legal for numElements to be zero. This can happen both
734 // dynamically, because x can be zero in 'new A[x]', and statically,
735 // because of GCC extensions that permit zero-length arrays. There
736 // are probably legitimate places where we could assume that this
737 // doesn't happen, but it's not clear that it's worth it.
738
739 // Peel any array types wrapped in the address element type down to the CIR
740 // type of a single constructed object.
741 mlir::Type elementType = arrayBase.getElementType();
742 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
743 elementType = maybeArrayTy.getElementType();
744 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
745
746 bool useDynamicArrayCtor = true;
747 uint64_t constElementCount = 0;
748 if (auto constantOp = numElements.getDefiningOp<cir::ConstantOp>()) {
749 constElementCount = CIRGenFunction::getZExtIntValueFromConstOp(constantOp);
750 if (constElementCount == 0)
751 return;
752 if (constantOp.use_empty())
753 constantOp.erase();
754 useDynamicArrayCtor = false;
755 }
756
757 // Traditional LLVM codegen emits a loop here. CIR lowers to a loop as part of
758 // LoweringPrepare.
759
760 // The alignment of the base, adjusted by the size of a single element,
761 // provides a conservative estimate of the alignment of every element.
762 // (This assumes we never start tracking offsetted alignments.)
763 //
764 // Note that these are complete objects and so we don't need to
765 // use the non-virtual size or alignment.
767 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
768 getContext().getTypeSizeInChars(type));
769
770 mlir::Location loc = *currSrcLoc;
771
772 mlir::Value dynamicElPtr;
773 if (useDynamicArrayCtor)
774 dynamicElPtr =
775 builder.createPtrBitcast(arrayBase.getPointer(), elementType);
776
777 // C++ [class.temporary]p4:
778 // There are two contexts in which temporaries are destroyed at a different
779 // point than the end of the full-expression. The first context is when a
780 // default constructor is called to initialize an element of an array.
781 // If the constructor has one or more default arguments, the destruction of
782 // every temporary created in a default argument expression is sequenced
783 // before the construction of the next array element, if any.
784 {
785 RunCleanupsScope scope(*this);
786
787 bool needsPartialArrayCleanup =
788 getLangOpts().Exceptions && !ctor->getParent()->hasTrivialDestructor();
789
790 auto emitCtorBody = [&](mlir::OpBuilder &b, mlir::Location l) {
791 mlir::BlockArgument arg =
792 b.getInsertionBlock()->addArgument(ptrToElmType, l);
793 Address curAddr = Address(arg, elementType, eltAlignment);
795 if (zeroInitialize)
796 emitNullInitialization(l, curAddr, type);
797 auto currAVS = AggValueSlot::forAddr(
798 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
802 /*ForVirtualBase=*/false,
803 /*Delegating=*/false, currAVS, e);
804 cir::YieldOp::create(b, l);
805 };
806
807 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
808 emitPartialDtorBody = nullptr;
809 auto partialDtorBuilder = [&](mlir::OpBuilder &b, mlir::Location l) {
810 mlir::BlockArgument arg =
811 b.getInsertionBlock()->addArgument(ptrToElmType, l);
812 Address curAddr = Address(arg, elementType, eltAlignment);
814 /*forVirtualBase=*/false,
815 /*delegating=*/false, curAddr, type);
816 cir::YieldOp::create(b, l);
817 };
818 if (needsPartialArrayCleanup)
819 emitPartialDtorBody = partialDtorBuilder;
820
821 if (useDynamicArrayCtor) {
822 cir::ArrayCtor::create(builder, loc, dynamicElPtr, numElements,
823 emitCtorBody, emitPartialDtorBody);
824 } else {
825 cir::ArrayType arrayTy =
826 cir::ArrayType::get(elementType, constElementCount);
827 mlir::Value arrayOp =
828 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
829 cir::ArrayCtor::create(builder, loc, arrayOp, emitCtorBody,
830 emitPartialDtorBody);
831 }
832 }
833}
834
836 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
837 const FunctionArgList &args, SourceLocation loc) {
838 CallArgList delegateArgs;
839
840 FunctionArgList::const_iterator i = args.begin(), e = args.end();
841 assert(i != e && "no parameters to constructor");
842
843 // this
844 Address thisAddr = loadCXXThisAddress();
845 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
846 ++i;
847
848 // FIXME: The location of the VTT parameter in the parameter list is specific
849 // to the Itanium ABI and shouldn't be hardcoded here.
850 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
851 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
852 return;
853 }
854
855 // Explicit arguments.
856 for (; i != e; ++i) {
857 const VarDecl *param = *i;
858 // FIXME: per-argument source location
859 emitDelegateCallArg(delegateArgs, param, loc);
860 }
861
863
864 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
865 /*Delegating=*/true, thisAddr, delegateArgs, loc);
866}
867
869 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
870 assert(assignOp->isCopyAssignmentOperator() ||
871 assignOp->isMoveAssignmentOperator());
872 const Stmt *rootS = assignOp->getBody();
873 assert(isa<CompoundStmt>(rootS) &&
874 "Body of an implicit assignment operator should be compound stmt.");
875 const auto *rootCS = cast<CompoundStmt>(rootS);
876
877 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), assignOp);
878
881
882 // Classic codegen uses a special class to attempt to replace member
883 // initializers with memcpy. We could possibly defer that to the
884 // lowering or optimization phases to keep the memory accesses more
885 // explicit. For now, we don't insert memcpy at all, though in some
886 // cases the AST contains a call to memcpy.
888 for (Stmt *s : rootCS->body())
889 if (emitStmt(s, /*useCurrentScope=*/true).failed())
890 cgm.errorNYI(s->getSourceRange(),
891 std::string("emitImplicitAssignmentOperatorBody: ") +
892 s->getStmtClassName());
893}
894
896 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
897 // Get the address of the call operator.
898 const CIRGenFunctionInfo &calleeFnInfo =
899 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
900 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
901 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
902
903 // Prepare the return slot.
904 const FunctionProtoType *fpt =
905 callOperator->getType()->castAs<FunctionProtoType>();
906 QualType resultType = fpt->getReturnType();
907 ReturnValueSlot returnSlot;
908
909 // We don't need to separately arrange the call arguments because
910 // the call can't be variadic anyway --- it's impossible to forward
911 // variadic arguments.
912
913 // Now emit our call.
914 CIRGenCallee callee =
915 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
916 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs);
917
918 // If necessary, copy the returned value into the slot.
919 if (!resultType->isVoidType() && returnSlot.isNull()) {
920 if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType())
921 cgm.errorNYI(callOperator->getSourceRange(),
922 "emitForwardingCallToLambda: ObjCAutoRefCount");
923 emitReturnOfRValue(*currSrcLoc, rv, resultType);
924 } else {
925 cgm.errorNYI(callOperator->getSourceRange(),
926 "emitForwardingCallToLambda: return slot is not null");
927 }
928}
929
931 const CXXRecordDecl *lambda = md->getParent();
932
933 // Start building arguments for forwarding call
934 CallArgList callArgs;
935
936 QualType lambdaType = getContext().getCanonicalTagType(lambda);
937 QualType thisType = getContext().getPointerType(lambdaType);
938 Address thisPtr =
939 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");
940 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);
941
942 // Add the rest of the parameters.
943 for (auto *param : md->parameters())
944 emitDelegateCallArg(callArgs, param, param->getBeginLoc());
945
946 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();
947 // For a generic lambda, find the corresponding call operator specialization
948 // to which the call to the static-invoker shall be forwarded.
949 if (lambda->isGenericLambda()) {
952 FunctionTemplateDecl *callOpTemplate =
954 void *InsertPos = nullptr;
955 FunctionDecl *correspondingCallOpSpecialization =
956 callOpTemplate->findSpecialization(tal->asArray(), InsertPos);
957 assert(correspondingCallOpSpecialization);
958 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
959 }
960 emitForwardingCallToLambda(callOp, callArgs);
961}
962
964 if (md->isVariadic()) {
965 // Codgen for LLVM doesn't emit code for this as well, it says:
966 // FIXME: Making this work correctly is nasty because it requires either
967 // cloning the body of the call operator or making the call operator
968 // forward.
969 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");
970 }
971
973}
974
976 QualType type) {
977 const auto *record = type->castAsCXXRecordDecl();
978 const CXXDestructorDecl *dtor = record->getDestructor();
979 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
980 // dtors which shall be removed on later CIR passes. However, only remove this
981 // assertion after we have a test case to exercise this path.
982 assert(!dtor->isTrivial());
983 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
984 /*delegating=*/false, addr, type);
985}
986
987namespace {
988mlir::Value loadThisForDtorDelete(CIRGenFunction &cgf,
989 const CXXDestructorDecl *dd) {
990 if (Expr *thisArg = dd->getOperatorDeleteThisArg())
991 return cgf.emitScalarExpr(thisArg);
992 return cgf.loadCXXThis();
993}
994
995/// Call the operator delete associated with the current destructor.
996struct CallDtorDelete final : EHScopeStack::Cleanup {
997 CallDtorDelete() {}
998
999 void emit(CIRGenFunction &cgf, Flags flags) override {
1000 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(cgf.curFuncDecl);
1001 const CXXRecordDecl *classDecl = dtor->getParent();
1003 loadThisForDtorDelete(cgf, dtor),
1004 cgf.getContext().getCanonicalTagType(classDecl));
1005 }
1006};
1007
1008class DestroyField final : public EHScopeStack::Cleanup {
1009 const FieldDecl *field;
1010 CIRGenFunction::Destroyer *destroyer;
1011
1012public:
1013 DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
1014 : field(field), destroyer(destroyer) {}
1015
1016 void emit(CIRGenFunction &cgf, Flags flags) override {
1017 // Find the address of the field.
1018 Address thisValue = cgf.loadCXXThisAddress();
1019 CanQualType recordTy =
1020 cgf.getContext().getCanonicalTagType(field->getParent());
1021 LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);
1022 LValue lv = cgf.emitLValueForField(thisLV, field);
1023 assert(lv.isSimple());
1024
1026 cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);
1027 }
1028};
1029} // namespace
1030
1031/// Emit all code that comes at the end of class's destructor. This is to call
1032/// destructors on members and base classes in reverse order of their
1033/// construction.
1034///
1035/// For a deleting destructor, this also handles the case where a destroying
1036/// operator delete completely overrides the definition.
1038 CXXDtorType dtorType) {
1039 assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&
1040 "Should not emit dtor epilogue for non-exported trivial dtor!");
1041
1042 // The deleting-destructor phase just needs to call the appropriate
1043 // operator delete that Sema picked up.
1044 if (dtorType == Dtor_Deleting) {
1045 assert(dd->getOperatorDelete() &&
1046 "operator delete missing - EnterDtorCleanups");
1048 cgm.errorNYI(dd->getSourceRange(), "deleting destructor with vtt");
1049 } else {
1051 cgm.errorNYI(dd->getSourceRange(),
1052 "deleting destructor with destroying operator delete");
1053 } else {
1054 ehStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
1055 }
1056 }
1057 return;
1058 }
1059
1060 const CXXRecordDecl *classDecl = dd->getParent();
1061
1062 // Unions have no bases and do not call field destructors.
1063 if (classDecl->isUnion())
1064 return;
1065
1066 // The complete-destructor phase just destructs all the virtual bases.
1067 if (dtorType == Dtor_Complete) {
1069
1070 // We push them in the forward order so that they'll be popped in
1071 // the reverse order.
1072 for (const CXXBaseSpecifier &base : classDecl->vbases()) {
1073 auto *baseClassDecl = base.getType()->castAsCXXRecordDecl();
1074
1075 if (baseClassDecl->hasTrivialDestructor()) {
1076 // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
1077 // memory. For non-trival base classes the same is done in the class
1078 // destructor.
1080 } else {
1081 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1082 /*baseIsVirtual=*/true);
1083 }
1084 }
1085
1086 return;
1087 }
1088
1089 assert(dtorType == Dtor_Base);
1091
1092 // Destroy non-virtual bases.
1093 for (const CXXBaseSpecifier &base : classDecl->bases()) {
1094 // Ignore virtual bases.
1095 if (base.isVirtual())
1096 continue;
1097
1098 CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();
1099
1100 if (baseClassDecl->hasTrivialDestructor())
1102 else
1103 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1104 /*baseIsVirtual=*/false);
1105 }
1106
1108
1109 // Destroy direct fields.
1110 for (const FieldDecl *field : classDecl->fields()) {
1111 QualType type = field->getType();
1112 QualType::DestructionKind dtorKind = type.isDestructedType();
1113 if (!dtorKind)
1114 continue;
1115
1116 // Anonymous union members do not have their destructors called.
1117 const RecordType *rt = type->getAsUnionType();
1118 if (rt && rt->getDecl()->isAnonymousStructOrUnion())
1119 continue;
1120
1121 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1123 ehStack.pushCleanup<DestroyField>(cleanupKind, field,
1124 getDestroyer(dtorKind));
1125 }
1126}
1127
1129 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
1130 assert(ctor->isDelegatingConstructor());
1131
1132 Address thisPtr = loadCXXThisAddress();
1133
1140
1141 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
1142
1143 const CXXRecordDecl *classDecl = ctor->getParent();
1144 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
1145 CXXDtorType dtorType =
1146 curGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
1147 ehStack.pushCleanup<CallDelegatingCtorDtor>(
1148 EHCleanup, classDecl->getDestructor(), thisPtr, dtorType);
1149 }
1150}
1151
1154 bool forVirtualBase, bool delegating,
1155 Address thisAddr, QualType thisTy) {
1156 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
1157 delegating, thisAddr, thisTy);
1158}
1159
1160mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1161 bool delegating) {
1162 if (!cgm.getCXXABI().needsVTTParameter(gd))
1163 return nullptr;
1164
1165 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
1166 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();
1167
1168 uint64_t subVTTIndex;
1169
1170 if (delegating) {
1171 // If this is a delegating constructor call, just load the VTT.
1172 return loadCXXVTT();
1173 } else if (rd == base) {
1174 // If the record matches the base, this is the complete ctor/dtor
1175 // variant calling the base variant in a class with virtual bases.
1176 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
1177 "doing no-op VTT offset in base dtor/ctor?");
1178 assert(!forVirtualBase && "Can't have same class as virtual base!");
1179 subVTTIndex = 0;
1180 } else {
1181 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1182 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)
1183 : layout.getBaseClassOffset(base);
1184
1185 subVTTIndex =
1186 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));
1187 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
1188 }
1189
1190 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
1191 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
1192 // A VTT parameter was passed to the constructor, use it.
1193 mlir::Value vtt = loadCXXVTT();
1194 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
1195 } else {
1196 // We're the complete constructor, so get the VTT by name.
1197 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);
1198 return builder.createVTTAddrPoint(
1199 loc, builder.getPointerTo(cgm.voidPtrTy),
1200 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);
1201 }
1202}
1203
1205 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1206 llvm::iterator_range<CastExpr::path_const_iterator> path,
1207 bool nullCheckValue) {
1208 assert(!path.empty() && "Base path should not be empty!");
1209
1210 QualType derivedTy = getContext().getCanonicalTagType(derived);
1211 mlir::Type derivedValueTy = convertType(derivedTy);
1212 CharUnits nonVirtualOffset =
1213 cgm.computeNonVirtualBaseClassOffset(derived, path);
1214
1215 // Note that in OG, no offset (nonVirtualOffset.getQuantity() == 0) means it
1216 // just gives the address back. In CIR a `cir.derived_class` is created and
1217 // made into a nop later on during lowering.
1218 return builder.createDerivedClassAddr(loc, baseAddr, derivedValueTy,
1219 nonVirtualOffset.getQuantity(),
1220 /*assumeNotNull=*/!nullCheckValue);
1221}
1222
1224 Address value, const CXXRecordDecl *derived,
1225 llvm::iterator_range<CastExpr::path_const_iterator> path,
1226 bool nullCheckValue, SourceLocation loc) {
1227 assert(!path.empty() && "Base path should not be empty!");
1228
1229 CastExpr::path_const_iterator start = path.begin();
1230 const CXXRecordDecl *vBase = nullptr;
1231
1232 if ((*path.begin())->isVirtual()) {
1233 vBase = (*start)->getType()->castAsCXXRecordDecl();
1234 ++start;
1235 }
1236
1237 // Compute the static offset of the ultimate destination within its
1238 // allocating subobject (the virtual base, if there is one, or else
1239 // the "complete" object that we see).
1240 CharUnits nonVirtualOffset = cgm.computeNonVirtualBaseClassOffset(
1241 vBase ? vBase : derived, {start, path.end()});
1242
1243 // If there's a virtual step, we can sometimes "devirtualize" it.
1244 // For now, that's limited to when the derived type is final.
1245 // TODO: "devirtualize" this for accesses to known-complete objects.
1246 if (vBase && derived->hasAttr<FinalAttr>()) {
1247 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
1248 CharUnits vBaseOffset = layout.getVBaseClassOffset(vBase);
1249 nonVirtualOffset += vBaseOffset;
1250 vBase = nullptr; // we no longer have a virtual step
1251 }
1252
1253 // Get the base pointer type.
1254 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
1256
1257 // If there is no virtual base, use cir.base_class_addr. It takes care of
1258 // the adjustment and the null pointer check.
1259 if (nonVirtualOffset.isZero() && !vBase) {
1261 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
1262 /*assumeNotNull=*/true);
1263 }
1264
1266
1267 // Compute the virtual offset.
1268 mlir::Value virtualOffset = nullptr;
1269 if (vBase) {
1270 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
1271 getLoc(loc), *this, value, derived, vBase);
1272 }
1273
1274 // Apply both offsets.
1276 getLoc(loc), *this, value, nonVirtualOffset, virtualOffset, derived,
1277 vBase, baseValueTy, not nullCheckValue);
1278
1279 // Cast to the destination type.
1280 value = value.withElementType(builder, baseValueTy);
1281
1282 return value;
1283}
1284
1285// TODO(cir): this can be shared with LLVM codegen.
1288 if (!cgm.getCodeGenOpts().WholeProgramVTables)
1289 return false;
1290
1291 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1292 return true;
1293
1295
1296 return false;
1297}
1298
1299mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1300 const CXXRecordDecl *rd) {
1301 auto vtablePtr =
1302 cir::VTableGetVPtrOp::create(builder, loc, thisAddr.getPointer());
1303 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1304
1305 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1307
1308 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1309 cgm.getCodeGenOpts().StrictVTablePointers) {
1311 }
1312
1313 return vtable;
1314}
1315
1318 bool forVirtualBase,
1319 bool delegating,
1320 AggValueSlot thisAVS,
1321 const clang::CXXConstructExpr *e) {
1322 Address thisAddr = thisAVS.getAddress();
1323 QualType thisType = d->getThisType();
1324 mlir::Value thisPtr = thisAddr.getPointer();
1325
1327
1328 // If this is a trivial constructor, just emit what's needed. If this is a
1329 // union copy constructor, we must emit a memcpy, because the AST does not
1330 // model that copy.
1332 assert(e->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
1333 const Expr *arg = e->getArg(0);
1334 LValue src = emitLValue(arg);
1336 LValue dest = makeAddrLValue(thisAddr, destTy);
1337 emitAggregateCopy(dest, src, src.getType(), thisAVS.mayOverlap());
1338 return;
1339 }
1340
1341 CallArgList args;
1342 args.add(RValue::get(thisPtr), thisType);
1343
1344 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1345
1347
1348 if (auto inherited = d->getInheritedConstructor();
1349 !inherited || cgm.getTypes().inheritingCtorHasParams(inherited, type))
1350 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1351 /*ParamsToSkip=*/0);
1352
1354 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1355 e->getExprLoc());
1356}
1357
1359 const CXXConstructorDecl *d,
1360 CXXCtorType type) {
1361 // We can't forward a variadic call.
1362 if (d->isVariadic())
1363 return false;
1364
1366 // FIXME(CIR): It isn't clear to me that this is the right answer here,
1367 // classic-codegen decides the answer is 'false' if there is an inalloca
1368 // argument or if there is a param that needs destruction.
1369 // When we get an understanding of what the the calling-convention code
1370 // needs here, we should be able to replace this with either a 'return
1371 // false' or 'return true'.
1372 // Perhaps we should be checking isParamDestroyedInCallee?
1373 cgm.errorNYI(d->getSourceRange(),
1374 "canEmitDelegateCallArgs: args-destroyed-L-to-R in callee");
1375 }
1376
1377 return true;
1378}
1379
1381 const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr,
1382 bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e) {
1383
1384 CallArgList ctorArgs;
1386 thisAddr, d->getThisType()->getPointeeType())),
1387 d->getThisType());
1388
1389 if (inheritedFromVBase &&
1390 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
1391 cgm.errorNYI(e->getSourceRange(), "emitInheritedCXXConstructorCall "
1392 "inheritedFromVBase with ctor variants");
1393 return;
1394 } else if (!cxxInheritedCtorInitExprArgs.empty()) {
1395 // The inheriting constructor was inlined; just inject its arguments.
1396 assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
1397 "wrong number of parameters for inherited constructor call");
1399 ctorArgs[0] = thisArg;
1400 } else {
1401 ctorArgs.push_back(thisArg);
1402 const auto *outerCtor = cast<CXXConstructorDecl>(curCodeDecl);
1403 assert(outerCtor->getNumParams() == d->getNumParams());
1404 assert(!outerCtor->isVariadic() && "should have been inlined");
1405
1406 for (const ParmVarDecl *param : outerCtor->parameters()) {
1407 assert(getContext().hasSameUnqualifiedType(
1408 outerCtor->getParamDecl(param->getFunctionScopeIndex())->getType(),
1409 param->getType()));
1410 emitDelegateCallArg(ctorArgs, param, e->getLocation());
1411
1412 if (param->hasAttr<PassObjectSizeAttr>())
1413 cgm.errorNYI(
1414 e->getLocation(),
1415 "emitInheritedCXXConstructorCall: pass object size attr argument");
1416 }
1417 }
1418
1419 emitCXXConstructorCall(d, Ctor_Base, forVirtualBase, /*delegating=*/false,
1420 thisAddr, ctorArgs, e->getLocation());
1421}
1422
1424 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
1425 bool forVirtualBase, bool delegating, CallArgList &args) {
1426 GlobalDecl gd(d, ctorType);
1428 InlinedInheritingConstructorScope scope(*this, gd);
1429 RunCleanupsScope RunCleanups(*this);
1430
1431 // Save the arguments to be passed to the inherited constructor.
1433
1434 FunctionArgList params;
1435 QualType retTy = buildFunctionArgList(gd, params);
1436 // FIXME(cir): When we get to the !isVoidType NYI below, this probably is
1437 // going to be important. In the meantime, this is likely not really doing
1438 // anything.
1439 fnRetTy = retTy;
1440
1441 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, ctorType, forVirtualBase,
1442 delegating, args);
1443
1444 // Emit a simplified prolog. We only need to emit the implicit params.
1445 assert(args.size() >= params.size() && "too few arguments for call");
1446 for (auto [idx, arg, parm] :
1447 llvm::zip_longest(llvm::index_range{0, args.size()}, args, params)) {
1448 if (idx < params.size() && isa<ImplicitParamDecl>(*parm)) {
1449 mlir::Location parmLoc = getLoc((*parm)->getSourceRange());
1450 RValue argVal = arg->getRValue(*this, parmLoc);
1451
1452 LValue allocaVal = makeAddrLValue(
1453 createTempAlloca(convertType((*parm)->getType()),
1454 getContext().getDeclAlign(*parm), parmLoc),
1455 (*parm)->getType());
1456
1457 emitStoreThroughLValue(argVal, allocaVal, /*isInit=*/true);
1458
1459 setAddrOfLocalVar((*parm), allocaVal.getAddress());
1460 }
1461 }
1462
1463 // FIXME(cir): it isn't clear what it takes to get here with a constructor?
1464 // Leave as an NYI until we come across a reproducer.
1465 if (!retTy->isVoidType())
1466 cgm.errorNYI(d->getSourceRange(),
1467 "emitInlinedInheritingCXXConstructorCall: non-void return");
1468
1469 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
1471 emitCtorPrologue(d, ctorType, params);
1472}
1473
1475 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1476 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1477
1478 const CXXRecordDecl *crd = d->getParent();
1479
1480 // If this is a call to a trivial default constructor:
1481 // In LLVM: do nothing.
1482 // In CIR: emit as a regular call, other later passes should lower the
1483 // ctor call into trivial initialization.
1485
1486 // Note: memcpy-equivalent special members are handled in the
1487 // emitCXXConstructorCall overload that takes a CXXConstructExpr.
1488
1489 bool passPrototypeArgs = true;
1490
1491 // Check whether we can actually emit the constructor before trying to do so.
1492 if (auto inherited = d->getInheritedConstructor()) {
1493 passPrototypeArgs = getTypes().inheritingCtorHasParams(inherited, type);
1494 if (passPrototypeArgs &&
1495 !canEmitDelegateCallArgs(cgm, cgm.getASTContext(), d, type)) {
1496 emitInlinedInheritingCXXConstructorCall(loc, d, type, forVirtualBase,
1497 delegating, args);
1498 return;
1499 }
1500 }
1501
1502 // Insert any ABI-specific implicit constructor arguments.
1504 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1505 delegating, args);
1506
1507 // Emit the call.
1508 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1509 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1510 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1511 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1512 cir::CIRCallOpInterface c;
1513 emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
1514
1515 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1516 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1517 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1518}
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 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 bool canEmitDelegateCallArgs(CIRGenModule &cgm, ASTContext &ctx, const CXXConstructorDecl *d, CXXCtorType type)
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:226
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.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:917
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getSize() const
getSize - Get the record size in characters.
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:3772
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:96
mlir::Type getElementType() const
Definition Address.h:123
static Address invalid()
Definition Address.h:74
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:136
An aggregate value slot.
Overlap_t mayOverlap() const
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)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &args) const =0
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:92
A scope within which we are constructing the fields of an object which might use a CXXDefaultInitExpr...
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
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...
Address emitCXXMemberDataPointerAddress(const Expr *e, Address base, mlir::Value memberPtr, const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo)
CIRGenTypes & getTypes() const
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,...
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...
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
const clang::Decl * curFuncDecl
void emitInlinedInheritingCXXConstructorCall(SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType, bool forVirtualBase, bool delegating, CallArgList &args)
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
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)
CleanupKind getCleanupKind(QualType::DestructionKind kind)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
CallArgList cxxInheritedCtorInitExprArgs
The values of function arguments to use when evaluating CXXInheritedCtorInitExprs within this context...
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void enterDtorCleanups(const CXXDestructorDecl *dtor, CXXDtorType type)
Enter the cleanups necessary to complete the given phase of destruction for a destructor.
void emitImplicitAssignmentOperatorBody(FunctionArgList &args)
static int64_t getZExtIntValueFromConstOp(mlir::Value val)
Get zero-extended integer from a mlir::Value that is an int constant or a constant op.
mlir::Type convertTypeForMem(QualType t)
clang::QualType buildFunctionArgList(clang::GlobalDecl gd, 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 getAsNaturalPointerTo(Address addr, QualType pointeeType)
void emitInitializerForField(clang::FieldDecl *field, LValue lhs, clang::Expr *init)
LValue emitLValueForField(LValue base, const clang::FieldDecl *field)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
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 emitDestroy(Address addr, QualType type, Destroyer *destroyer)
Immediately perform the destruction of the given object.
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void pushEHDestroyIfNeeded(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroyIfNeeded - Push the standard destructor for the given type as an EH-only cleanup.
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)
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 setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
void emitInheritedCXXConstructorCall(const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr, bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e)
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)
This class organizes the cross-function state that is used while generating CIR code.
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 getMinimumClassObjectSize(const CXXRecordDecl *cd)
Returns the minimum object size for an object of the given class type (or a class derived from it).
CharUnits getVBaseAlignment(CharUnits derivedAlign, const CXXRecordDecl *derived, const CXXRecordDecl *vbase)
Returns the assumed alignment of a virtual base of a class.
CIRGenCXXABI & getCXXABI() const
bool inheritingCtorHasParams(const InheritedConstructor &inherited, CXXCtorType type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:239
Information for lazily generating a cleanup.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:193
Address getAddress() const
clang::QualType getType() const
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:83
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:260
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a call to a C++ constructor.
Definition ExprCXX.h:1552
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1695
arg_range arguments()
Definition ExprCXX.h:1676
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1615
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Definition ExprCXX.h:1692
Represents a C++ constructor within a class.
Definition DeclCXX.h:2624
init_iterator init_begin()
Retrieve an iterator to the first initializer.
Definition DeclCXX.h:2721
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
Definition DeclCXX.h:2777
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Definition DeclCXX.cpp:3071
InheritedConstructor getInheritedConstructor() const
Get the constructor that this inheriting constructor is based on.
Definition DeclCXX.h:2862
Represents a C++ base or member initializer.
Definition DeclCXX.h:2389
Expr * getInit() const
Get the initializer.
Definition DeclCXX.h:2591
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
Definition DeclCXX.cpp:2955
bool isAnyMemberInitializer() const
Definition DeclCXX.h:2469
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Definition DeclCXX.h:2461
bool isIndirectMemberInitializer() const
Definition DeclCXX.h:2473
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Definition DeclCXX.cpp:2948
FieldDecl * getAnyMember() const
Definition DeclCXX.h:2535
IndirectFieldDecl * getIndirectMember() const
Definition DeclCXX.h:2543
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Definition DeclCXX.h:2515
Represents a C++ destructor within a class.
Definition DeclCXX.h:2889
const FunctionDecl * getOperatorDelete() const
Definition DeclCXX.cpp:3222
Expr * getOperatorDeleteThisArg() const
Definition DeclCXX.h:2928
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1755
SourceLocation getLocation() const LLVM_READONLY
Definition ExprCXX.h:1808
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2275
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2861
QualType getFunctionObjectParameterType() const
Definition DeclCXX.h:2299
bool isMemcpyEquivalentSpecialMember(const ASTContext &Ctx) const
Returns whether this is a copy/move constructor or assignment operator that can be implemented as a m...
Definition DeclCXX.cpp:2784
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
Definition DeclCXX.cpp:2343
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
Definition DeclCXX.cpp:1679
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1372
base_class_range bases()
Definition DeclCXX.h:608
base_class_range vbases()
Definition DeclCXX.h:625
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1221
bool isDynamicClass() const
Definition DeclCXX.h:574
bool hasDefinition() const
Definition DeclCXX.h:561
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2131
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition DeclCXX.cpp:1742
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
const CXXBaseSpecifier *const * path_const_iterator
Definition Expr.h:3746
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
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 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:3810
bool hasAttr() const
Definition DeclBase.h:585
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
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:277
Represents a member of a struct/union/class.
Definition Decl.h:3175
Represents a function declaration or definition.
Definition Decl.h:2015
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4207
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4195
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3553
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2789
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2392
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3135
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4331
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2400
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4551
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3828
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5357
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5761
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:4893
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:3482
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3503
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3703
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5535
QualType getPointeeType() const
Definition TypeBase.h:3721
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
Represents a parameter to a function.
Definition Decl.h:1805
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:1551
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
field_range fields() const
Definition Decl.h:4545
Encodes a location in the source.
Stmt - This represents one statement.
Definition Stmt.h:86
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3833
bool isUnion() const
Definition Decl.h:3943
bool areArgsDestroyedLeftToRightInCallee() const
Are arguments to a call destroyed left to right in the callee?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3562
The base class of the type hierarchy.
Definition TypeBase.h:1866
bool isVoidType() const
Definition TypeBase.h:9034
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9328
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
bool isRecordType() const
Definition TypeBase.h:8795
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
#define not
Definition iso646.h:22
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
The JSON file list parser is used to communicate input to InstallAPI.
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_Base
Base object dtor.
Definition ABI.h:37
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool addressSpace()
static bool useEHCleanupForArray()
static bool aggValueSlotGC()
static bool hiddenVisibility()
static bool runCleanupsScope()
static bool opCallArgEvaluationOrder()
static bool createInvariantGroup()
static bool isTrivialCtorOrDtor()
static bool assignMemcpyizer()
static bool ctorMemcpyizer()
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