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"
23
24using namespace clang;
25using namespace clang::CIRGen;
26
27/// Checks whether the given constructor is a valid subject for the
28/// complete-to-base constructor delegation optimization, i.e. emitting the
29/// complete constructor as a simple call to the base constructor.
31 const CXXConstructorDecl *ctor) {
32 // Currently we disable the optimization for classes with virtual bases
33 // because (1) the address of parameter variables need to be consistent across
34 // all initializers but (2) the delegate function call necessarily creates a
35 // second copy of the parameter variable.
36 //
37 // The limiting example (purely theoretical AFAIK):
38 // struct A { A(int &c) { c++; } };
39 // struct A : virtual A {
40 // B(int count) : A(count) { printf("%d\n", count); }
41 // };
42 // ...although even this example could in principle be emitted as a delegation
43 // since the address of the parameter doesn't escape.
44 if (ctor->getParent()->getNumVBases())
45 return false;
46
47 // We also disable the optimization for variadic functions because it's
48 // impossible to "re-pass" varargs.
49 if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
50 return false;
51
52 // FIXME: Decide if we can do a delegation of a delegating constructor.
53 if (ctor->isDelegatingConstructor())
54 return false;
55
56 return true;
57}
58
60 CXXCtorInitializer *memberInit,
61 LValue &lhs) {
62 FieldDecl *field = memberInit->getAnyMember();
63 if (memberInit->isIndirectMemberInitializer()) {
64 // If we are initializing an anonymous union field, drill down to the field.
65 IndirectFieldDecl *indirectField = memberInit->getIndirectMember();
66 for (const auto *nd : indirectField->chain()) {
67 auto *fd = cast<clang::FieldDecl>(nd);
68 lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());
69 }
70 } else {
71 lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());
72 }
73}
74
76 const CXXRecordDecl *classDecl,
77 CXXCtorInitializer *memberInit,
78 const CXXConstructorDecl *constructor,
79 FunctionArgList &args) {
80 assert(memberInit->isAnyMemberInitializer() &&
81 "Must have member initializer!");
82 assert(memberInit->getInit() && "Must have initializer!");
83
85
86 // non-static data member initializers
87 FieldDecl *field = memberInit->getAnyMember();
88 QualType fieldType = field->getType();
89
90 mlir::Value thisPtr = cgf.loadCXXThis();
91 CanQualType recordTy = cgf.getContext().getCanonicalTagType(classDecl);
92
93 // If a base constructor is being emitted, create an LValue that has the
94 // non-virtual alignment.
95 LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)
96 ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)
97 : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);
98
99 emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);
100
101 // Special case: If we are in a copy or move constructor, and we are copying
102 // an array off PODs or classes with trivial copy constructors, ignore the AST
103 // and perform the copy we know is equivalent.
104 // FIXME: This is hacky at best... if we had a bit more explicit information
105 // in the AST, we could generalize it more easily.
106 const ConstantArrayType *array =
107 cgf.getContext().getAsConstantArrayType(fieldType);
108 if (array && constructor->isDefaulted() &&
109 constructor->isCopyOrMoveConstructor()) {
110 QualType baseElementTy = cgf.getContext().getBaseElementType(array);
111 // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
112 // whereas ClangIR wants to represent all object construction explicitly.
113 if (!baseElementTy->isRecordType()) {
114 cgf.cgm.errorNYI(memberInit->getSourceRange(),
115 "emitMemberInitializer: array of non-record type");
116 return;
117 }
118 }
119
120 cgf.emitInitializerForField(field, lhs, memberInit->getInit());
121}
122
124 const Type *baseType = baseInit->getBaseClass();
125 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
126 return baseClassDecl->isDynamicClass();
127}
128
129namespace {
130/// Call the destructor for a direct base class.
131struct CallBaseDtor final : EHScopeStack::Cleanup {
132 const CXXRecordDecl *baseClass;
133 bool baseIsVirtual;
134 CallBaseDtor(const CXXRecordDecl *base, bool baseIsVirtual)
135 : baseClass(base), baseIsVirtual(baseIsVirtual) {}
136
137 void emit(CIRGenFunction &cgf) override {
138 const CXXRecordDecl *derivedClass =
139 cast<CXXMethodDecl>(cgf.curFuncDecl)->getParent();
140
141 const CXXDestructorDecl *d = baseClass->getDestructor();
142 // We are already inside a destructor, so presumably the object being
143 // destroyed should have the expected type.
144 QualType thisTy = d->getFunctionObjectParameterType();
145 assert(cgf.currSrcLoc && "expected source location");
146 Address addr = cgf.getAddressOfDirectBaseInCompleteClass(
147 *cgf.currSrcLoc, cgf.loadCXXThisAddress(), derivedClass, baseClass,
148 baseIsVirtual);
149 cgf.emitCXXDestructorCall(d, Dtor_Base, baseIsVirtual,
150 /*delegating=*/false, addr, thisTy);
151 }
152};
153
154/// A visitor which checks whether an initializer uses 'this' in a
155/// way which requires the vtable to be properly set.
156struct DynamicThisUseChecker
157 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
158 using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;
159
160 bool usesThis = false;
161
162 DynamicThisUseChecker(const ASTContext &c) : super(c) {}
163
164 // Black-list all explicit and implicit references to 'this'.
165 //
166 // Do we need to worry about external references to 'this' derived
167 // from arbitrary code? If so, then anything which runs arbitrary
168 // external code might potentially access the vtable.
169 void VisitCXXThisExpr(const CXXThisExpr *e) { usesThis = true; }
170};
171} // end anonymous namespace
172
173static bool baseInitializerUsesThis(ASTContext &c, const Expr *init) {
174 DynamicThisUseChecker checker(c);
175 checker.Visit(init);
176 return checker.usesThis;
177}
178
179/// Gets the address of a direct base class within a complete object.
180/// This should only be used for (1) non-virtual bases or (2) virtual bases
181/// when the type is known to be complete (e.g. in complete destructors).
182///
183/// The object pointed to by 'thisAddr' is assumed to be non-null.
185 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
186 const CXXRecordDecl *base, bool baseIsVirtual) {
187 // 'thisAddr' must be a pointer (in some address space) to Derived.
188 assert(thisAddr.getElementType() == convertType(derived));
189
190 // Compute the offset of the virtual base.
191 CharUnits offset;
192 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
193 if (baseIsVirtual)
194 offset = layout.getVBaseClassOffset(base);
195 else
196 offset = layout.getBaseClassOffset(base);
197
198 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
199 offset.getQuantity(),
200 /*assumeNotNull=*/true);
201}
202
204 const CXXRecordDecl *classDecl,
205 CXXCtorInitializer *baseInit) {
206 assert(curFuncDecl && "loading 'this' without a func declaration?");
208
209 assert(baseInit->isBaseInitializer() && "Must have base initializer!");
210
211 Address thisPtr = loadCXXThisAddress();
212
213 const Type *baseType = baseInit->getBaseClass();
214 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
215
216 bool isBaseVirtual = baseInit->isBaseVirtual();
217
218 // If the initializer for the base (other than the constructor
219 // itself) accesses 'this' in any way, we need to initialize the
220 // vtables.
221 if (baseInitializerUsesThis(getContext(), baseInit->getInit()))
222 initializeVTablePointers(loc, classDecl);
223
224 // We can pretend to be a complete class because it only matters for
225 // virtual bases, and we only do virtual bases for complete ctors.
227 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
231 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
232
233 emitAggExpr(baseInit->getInit(), aggSlot);
234
236}
237
238/// This routine generates necessary code to initialize base classes and
239/// non-static data members belonging to this constructor.
241 CXXCtorType ctorType,
242 FunctionArgList &args) {
243 if (cd->isDelegatingConstructor()) {
245 return;
246 }
247
248 const CXXRecordDecl *classDecl = cd->getParent();
249
250 // Virtual base initializers aren't needed if:
251 // - This is a base ctor variant
252 // - There are no vbases
253 // - The class is abstract, so a complete object of it cannot be constructed
254 //
255 // The check for an abstract class is necessary because sema may not have
256 // marked virtual base destructors referenced.
257 bool constructVBases = ctorType != Ctor_Base &&
258 classDecl->getNumVBases() != 0 &&
259 !classDecl->isAbstract();
260 if (constructVBases &&
261 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
262 cgm.errorNYI(cd->getSourceRange(),
263 "emitCtorPrologue: virtual base without variants");
264 return;
265 }
266
267 // Create three separate ranges for the different types of initializers.
268 auto allInits = cd->inits();
269
270 // Find the boundaries between the three groups.
271 auto virtualBaseEnd = std::find_if(
272 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {
273 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
274 });
275
276 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),
277 [](const CXXCtorInitializer *Init) {
278 return !Init->isBaseInitializer();
279 });
280
281 // Create the three ranges.
282 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);
283 auto nonVirtualBaseInits =
284 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);
285 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());
286
287 const mlir::Value oldThisValue = cxxThisValue;
288
289 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
290 if (cgm.getCodeGenOpts().StrictVTablePointers &&
291 cgm.getCodeGenOpts().OptimizationLevel > 0 &&
292 isInitializerOfDynamicClass(baseInit)) {
293 // It's OK to continue after emitting the error here. The missing code
294 // just "launders" the 'this' pointer.
295 cgm.errorNYI(cd->getSourceRange(),
296 "emitCtorPrologue: strict vtable pointers for vbase");
297 }
298 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
299 };
300
301 // Process virtual base initializers.
302 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
303 if (!constructVBases)
304 continue;
305 emitInitializer(virtualBaseInit);
306 }
307
309
310 // Then, non-virtual base initializers.
311 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
312 assert(!nonVirtualBaseInit->isBaseVirtual());
313 emitInitializer(nonVirtualBaseInit);
314 }
315
316 cxxThisValue = oldThisValue;
317
319
320 // Finally, initialize class members.
322 // Classic codegen uses a special class to attempt to replace member
323 // initializers with memcpy. We could possibly defer that to the
324 // lowering or optimization phases to keep the memory accesses more
325 // explicit. For now, we don't insert memcpy at all.
327 for (CXXCtorInitializer *member : memberInits) {
328 assert(!member->isBaseInitializer());
329 assert(member->isAnyMemberInitializer() &&
330 "Delegating initializer on non-delegating constructor");
331 emitMemberInitializer(*this, cd->getParent(), member, cd, args);
332 }
333}
334
336 mlir::Location loc, CIRGenFunction &cgf, Address addr,
337 CharUnits nonVirtualOffset, mlir::Value virtualOffset,
338 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,
339 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {
340 // Assert that we have something to do.
341 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
342
343 // Compute the offset from the static and dynamic components.
344 mlir::Value baseOffset;
345 if (!nonVirtualOffset.isZero()) {
346 if (virtualOffset) {
347 cgf.cgm.errorNYI(
348 loc,
349 "applyNonVirtualAndVirtualOffset: virtual and non-virtual offset");
350 return Address::invalid();
351 } else {
352 assert(baseValueTy && "expected base type");
353 // If no virtualOffset is present this is the final stop.
354 return cgf.getBuilder().createBaseClassAddr(
355 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),
356 assumeNotNull);
357 }
358 } else {
359 baseOffset = virtualOffset;
360 }
361
362 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,
363 // not bytes. So the pointer must be cast to a byte pointer and back.
364
365 mlir::Value ptr = addr.getPointer();
366 mlir::Type charPtrType = cgf.cgm.uInt8PtrTy;
367 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);
368 mlir::Value adjusted = cir::PtrStrideOp::create(
369 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);
370 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());
371
372 // If we have a virtual component, the alignment of the result will
373 // be relative only to the known alignment of that vbase.
374 CharUnits alignment;
375 if (virtualOffset) {
376 assert(nearestVBase && "virtual offset without vbase?");
377 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,
378 nearestVBase);
379 } else {
380 alignment = addr.getAlignment();
381 }
382 alignment = alignment.alignmentAtOffset(nonVirtualOffset);
383
384 return Address(ptr, alignment);
385}
386
388 const VPtr &vptr) {
389 // Compute the address point.
390 mlir::Value vtableAddressPoint =
391 cgm.getCXXABI().getVTableAddressPointInStructor(
392 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
393
394 if (!vtableAddressPoint)
395 return;
396
397 // Compute where to store the address point.
398 mlir::Value virtualOffset{};
399 CharUnits nonVirtualOffset = CharUnits::Zero();
400
401 mlir::Type baseValueTy;
402 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
403 // We need to use the virtual base offset offset because the virtual base
404 // might have a different offset in the most derived class.
405 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
406 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);
407 nonVirtualOffset = vptr.offsetFromNearestVBase;
408 } else {
409 // We can just use the base offset in the complete class.
410 nonVirtualOffset = vptr.base.getBaseOffset();
411 baseValueTy =
412 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));
413 }
414
415 // Apply the offsets.
416 Address classAddr = loadCXXThisAddress();
417 if (!nonVirtualOffset.isZero() || virtualOffset) {
419 loc, *this, classAddr, nonVirtualOffset, virtualOffset,
420 vptr.vtableClass, vptr.nearestVBase, baseValueTy);
421 }
422
423 // Finally, store the address point. Use the same CIR types as the field.
424 //
425 // vtable field is derived from `this` pointer, therefore they should be in
426 // the same addr space.
428 auto vtablePtr = cir::VTableGetVPtrOp::create(
429 builder, loc, builder.getPtrToVPtrType(), classAddr.getPointer());
430 Address vtableField = Address(vtablePtr, classAddr.getAlignment());
431 builder.createStore(loc, vtableAddressPoint, vtableField);
434}
435
437 const CXXRecordDecl *rd) {
438 // Ignore classes without a vtable.
439 if (!rd->isDynamicClass())
440 return;
441
442 // Initialize the vtable pointers for this class and all of its bases.
443 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
444 for (const auto &vptr : getVTablePointers(rd))
445 initializeVTablePointer(loc, vptr);
446
447 if (rd->getNumVBases())
448 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);
449}
450
453 CIRGenFunction::VPtrsVector vptrsResult;
456 /*NearestVBase=*/nullptr,
457 /*OffsetFromNearestVBase=*/CharUnits::Zero(),
458 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,
459 vptrsResult);
460 return vptrsResult;
461}
462
464 const CXXRecordDecl *nearestVBase,
465 CharUnits offsetFromNearestVBase,
466 bool baseIsNonVirtualPrimaryBase,
467 const CXXRecordDecl *vtableClass,
469 VPtrsVector &vptrs) {
470 // If this base is a non-virtual primary base the address point has already
471 // been set.
472 if (!baseIsNonVirtualPrimaryBase) {
473 // Initialize the vtable pointer for this base.
474 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
475 vptrs.push_back(vptr);
476 }
477
478 const CXXRecordDecl *rd = base.getBase();
479
480 for (const auto &nextBase : rd->bases()) {
481 const auto *baseDecl =
482 cast<CXXRecordDecl>(nextBase.getType()->castAs<RecordType>()->getDecl())
483 ->getDefinitionOrSelf();
484
485 // Ignore classes without a vtable.
486 if (!baseDecl->isDynamicClass())
487 continue;
488
489 CharUnits baseOffset;
490 CharUnits baseOffsetFromNearestVBase;
491 bool baseDeclIsNonVirtualPrimaryBase;
492 const CXXRecordDecl *nextBaseDecl;
493
494 if (nextBase.isVirtual()) {
495 // Check if we've visited this virtual base before.
496 if (!vbases.insert(baseDecl).second)
497 continue;
498
499 const ASTRecordLayout &layout =
500 getContext().getASTRecordLayout(vtableClass);
501
502 nextBaseDecl = baseDecl;
503 baseOffset = layout.getVBaseClassOffset(baseDecl);
504 baseOffsetFromNearestVBase = CharUnits::Zero();
505 baseDeclIsNonVirtualPrimaryBase = false;
506 } else {
507 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
508
509 nextBaseDecl = nearestVBase;
510 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);
511 baseOffsetFromNearestVBase =
512 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);
513 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;
514 }
515
516 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,
517 baseOffsetFromNearestVBase,
518 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,
519 vptrs);
520 }
521}
522
524 assert(curFuncDecl && "loading 'this' without a func declaration?");
526
527 // Lazily compute CXXThisAlignment.
528 if (cxxThisAlignment.isZero()) {
529 // Just use the best known alignment for the parent.
530 // TODO: if we're currently emitting a complete-object ctor/dtor, we can
531 // always use the complete-object alignment.
532 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
533 cxxThisAlignment = cgm.getClassPointerAlignment(rd);
534 }
535
537}
538
540 Expr *init) {
541 QualType fieldType = field->getType();
542 switch (getEvaluationKind(fieldType)) {
543 case cir::TEK_Scalar:
544 if (lhs.isSimple()) {
545 emitExprAsInit(init, field, lhs, false);
546 } else {
547 RValue rhs = RValue::get(emitScalarExpr(init));
548 emitStoreThroughLValue(rhs, lhs);
549 }
550 break;
551 case cir::TEK_Complex:
552 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);
553 break;
554 case cir::TEK_Aggregate: {
560 emitAggExpr(init, slot);
561 break;
562 }
563 }
564
565 // Ensure that we destroy this object if an exception is thrown later in the
566 // constructor.
567 QualType::DestructionKind dtorKind = fieldType.isDestructedType();
568 (void)dtorKind;
570}
571
574 const CXXRecordDecl *baseDecl,
575 CharUnits expectedTargetAlign) {
576 // If the base is an incomplete type (which is, alas, possible with
577 // member pointers), be pessimistic.
578 if (!baseDecl->isCompleteDefinition())
579 return std::min(actualBaseAlign, expectedTargetAlign);
580
581 const ASTRecordLayout &baseLayout =
583 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
584
585 // If the class is properly aligned, assume the target offset is, too.
586 //
587 // This actually isn't necessarily the right thing to do --- if the
588 // class is a complete object, but it's only properly aligned for a
589 // base subobject, then the alignments of things relative to it are
590 // probably off as well. (Note that this requires the alignment of
591 // the target to be greater than the NV alignment of the derived
592 // class.)
593 //
594 // However, our approach to this kind of under-alignment can only
595 // ever be best effort; after all, we're never going to propagate
596 // alignments through variables or parameters. Note, in particular,
597 // that constructing a polymorphic type in an address that's less
598 // than pointer-aligned will generally trap in the constructor,
599 // unless we someday add some sort of attribute to change the
600 // assumed alignment of 'this'. So our goal here is pretty much
601 // just to allow the user to explicitly say that a pointer is
602 // under-aligned and then safely access its fields and vtables.
603 if (actualBaseAlign >= expectedBaseAlign)
604 return expectedTargetAlign;
605
606 // Otherwise, we might be offset by an arbitrary multiple of the
607 // actual alignment. The correct adjustment is to take the min of
608 // the two alignments.
609 return std::min(actualBaseAlign, expectedTargetAlign);
610}
611
612/// Return the best known alignment for a pointer to a virtual base,
613/// given the alignment of a pointer to the derived class.
616 const CXXRecordDecl *derivedClass,
617 const CXXRecordDecl *vbaseClass) {
618 // The basic idea here is that an underaligned derived pointer might
619 // indicate an underaligned base pointer.
620
621 assert(vbaseClass->isCompleteDefinition());
622 const ASTRecordLayout &baseLayout =
623 getASTContext().getASTRecordLayout(vbaseClass);
624 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
625
626 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
627 expectedVBaseAlign);
628}
629
630/// Emit a loop to call a particular constructor for each of several members
631/// of an array.
632///
633/// \param ctor the constructor to call for each element
634/// \param arrayType the type of the array to initialize
635/// \param arrayBegin an arrayType*
636/// \param zeroInitialize true if each element should be
637/// zero-initialized before it is constructed
640 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
641 bool zeroInitialize) {
642 QualType elementType;
643 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
644 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
645 newPointerIsChecked, zeroInitialize);
646}
647
648/// Emit a loop to call a particular constructor for each of several members
649/// of an array.
650///
651/// \param ctor the constructor to call for each element
652/// \param numElements the number of elements in the array;
653/// may be zero
654/// \param arrayBase a T*, where T is the type constructed by ctor
655/// \param zeroInitialize true if each element should be
656/// zero-initialized before it is constructed
658 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
659 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize) {
660 // It's legal for numElements to be zero. This can happen both
661 // dynamically, because x can be zero in 'new A[x]', and statically,
662 // because of GCC extensions that permit zero-length arrays. There
663 // are probably legitimate places where we could assume that this
664 // doesn't happen, but it's not clear that it's worth it.
665
666 auto arrayTy = mlir::cast<cir::ArrayType>(arrayBase.getElementType());
667 mlir::Type elementType = arrayTy.getElementType();
668
669 // This might be a multi-dimensional array. Find the innermost element type.
670 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
671 elementType = maybeArrayTy.getElementType();
672 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
673
674 // Optimize for a constant count.
675 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {
676 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>()) {
677 // Just skip out if the constant count is zero.
678 if (constIntAttr.getUInt() == 0)
679 return;
680
681 arrayTy = cir::ArrayType::get(elementType, constIntAttr.getUInt());
682 // Otherwise, emit the check.
683 }
684
685 if (constantCount.use_empty())
686 constantCount.erase();
687 } else {
688 // Otherwise, emit the check.
689 cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");
690 }
691
692 // Tradional LLVM codegen emits a loop here. CIR lowers to a loop as part of
693 // LoweringPrepare.
694
695 // The alignment of the base, adjusted by the size of a single element,
696 // provides a conservative estimate of the alignment of every element.
697 // (This assumes we never start tracking offsetted alignments.)
698 //
699 // Note that these are complete objects and so we don't need to
700 // use the non-virtual size or alignment.
702 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
703 getContext().getTypeSizeInChars(type));
704
705 // Zero initialize the storage, if requested.
706 if (zeroInitialize)
708
709 // C++ [class.temporary]p4:
710 // There are two contexts in which temporaries are destroyed at a different
711 // point than the end of the full-expression. The first context is when a
712 // default constructor is called to initialize an element of an array.
713 // If the constructor has one or more default arguments, the destruction of
714 // every temporary created in a default argument expression is sequenced
715 // before the construction of the next array element, if any.
716 {
717 RunCleanupsScope scope(*this);
718
719 // Evaluate the constructor and its arguments in a regular
720 // partial-destroy cleanup.
721 if (getLangOpts().Exceptions &&
722 !ctor->getParent()->hasTrivialDestructor()) {
723 cgm.errorNYI(e->getSourceRange(), "partial array cleanups");
724 }
725
726 // Emit the constructor call that will execute for every array element.
727 mlir::Value arrayOp =
728 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
729 cir::ArrayCtor::create(
730 builder, *currSrcLoc, arrayOp,
731 [&](mlir::OpBuilder &b, mlir::Location loc) {
732 mlir::BlockArgument arg =
733 b.getInsertionBlock()->addArgument(ptrToElmType, loc);
734 Address curAddr = Address(arg, elementType, eltAlignment);
736 auto currAVS = AggValueSlot::forAddr(
737 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
741 /*ForVirtualBase=*/false,
742 /*Delegating=*/false, currAVS, e);
743 cir::YieldOp::create(builder, loc);
744 });
745 }
746}
747
749 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
750 const FunctionArgList &args, SourceLocation loc) {
751 CallArgList delegateArgs;
752
753 FunctionArgList::const_iterator i = args.begin(), e = args.end();
754 assert(i != e && "no parameters to constructor");
755
756 // this
757 Address thisAddr = loadCXXThisAddress();
758 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
759 ++i;
760
761 // FIXME: The location of the VTT parameter in the parameter list is specific
762 // to the Itanium ABI and shouldn't be hardcoded here.
763 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
764 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
765 return;
766 }
767
768 // Explicit arguments.
769 for (; i != e; ++i) {
770 const VarDecl *param = *i;
771 // FIXME: per-argument source location
772 emitDelegateCallArg(delegateArgs, param, loc);
773 }
774
776
777 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
778 /*Delegating=*/true, thisAddr, delegateArgs, loc);
779}
780
782 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
783 assert(assignOp->isCopyAssignmentOperator() ||
784 assignOp->isMoveAssignmentOperator());
785 const Stmt *rootS = assignOp->getBody();
786 assert(isa<CompoundStmt>(rootS) &&
787 "Body of an implicit assignment operator should be compound stmt.");
788 const auto *rootCS = cast<CompoundStmt>(rootS);
789
790 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), assignOp);
791
794
795 // Classic codegen uses a special class to attempt to replace member
796 // initializers with memcpy. We could possibly defer that to the
797 // lowering or optimization phases to keep the memory accesses more
798 // explicit. For now, we don't insert memcpy at all, though in some
799 // cases the AST contains a call to memcpy.
801 for (Stmt *s : rootCS->body())
802 if (emitStmt(s, /*useCurrentScope=*/true).failed())
803 cgm.errorNYI(s->getSourceRange(),
804 std::string("emitImplicitAssignmentOperatorBody: ") +
805 s->getStmtClassName());
806}
807
809 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
810 // Get the address of the call operator.
811 const CIRGenFunctionInfo &calleeFnInfo =
812 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
813 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
814 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
815
816 // Prepare the return slot.
817 const FunctionProtoType *fpt =
818 callOperator->getType()->castAs<FunctionProtoType>();
819 QualType resultType = fpt->getReturnType();
820 ReturnValueSlot returnSlot;
821
822 // We don't need to separately arrange the call arguments because
823 // the call can't be variadic anyway --- it's impossible to forward
824 // variadic arguments.
825
826 // Now emit our call.
827 CIRGenCallee callee =
828 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
829 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs);
830
831 // If necessary, copy the returned value into the slot.
832 if (!resultType->isVoidType() && returnSlot.isNull()) {
833 if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType())
834 cgm.errorNYI(callOperator->getSourceRange(),
835 "emitForwardingCallToLambda: ObjCAutoRefCount");
836 emitReturnOfRValue(*currSrcLoc, rv, resultType);
837 } else {
838 cgm.errorNYI(callOperator->getSourceRange(),
839 "emitForwardingCallToLambda: return slot is not null");
840 }
841}
842
844 const CXXRecordDecl *lambda = md->getParent();
845
846 // Start building arguments for forwarding call
847 CallArgList callArgs;
848
849 QualType lambdaType = getContext().getCanonicalTagType(lambda);
850 QualType thisType = getContext().getPointerType(lambdaType);
851 Address thisPtr =
852 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");
853 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);
854
855 // Add the rest of the parameters.
856 for (auto *param : md->parameters())
857 emitDelegateCallArg(callArgs, param, param->getBeginLoc());
858
859 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();
860 // For a generic lambda, find the corresponding call operator specialization
861 // to which the call to the static-invoker shall be forwarded.
862 if (lambda->isGenericLambda()) {
865 FunctionTemplateDecl *callOpTemplate =
867 void *InsertPos = nullptr;
868 FunctionDecl *correspondingCallOpSpecialization =
869 callOpTemplate->findSpecialization(tal->asArray(), InsertPos);
870 assert(correspondingCallOpSpecialization);
871 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
872 }
873 emitForwardingCallToLambda(callOp, callArgs);
874}
875
877 if (md->isVariadic()) {
878 // Codgen for LLVM doesn't emit code for this as well, it says:
879 // FIXME: Making this work correctly is nasty because it requires either
880 // cloning the body of the call operator or making the call operator
881 // forward.
882 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");
883 }
884
886}
887
889 QualType type) {
890 const auto *record = type->castAsCXXRecordDecl();
891 const CXXDestructorDecl *dtor = record->getDestructor();
892 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
893 // dtors which shall be removed on later CIR passes. However, only remove this
894 // assertion after we have a test case to exercise this path.
895 assert(!dtor->isTrivial());
896 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
897 /*delegating=*/false, addr, type);
898}
899
900namespace {
901mlir::Value loadThisForDtorDelete(CIRGenFunction &cgf,
902 const CXXDestructorDecl *dd) {
903 if (Expr *thisArg = dd->getOperatorDeleteThisArg())
904 return cgf.emitScalarExpr(thisArg);
905 return cgf.loadCXXThis();
906}
907
908/// Call the operator delete associated with the current destructor.
909struct CallDtorDelete final : EHScopeStack::Cleanup {
910 CallDtorDelete() {}
911
912 void emit(CIRGenFunction &cgf) override {
913 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(cgf.curFuncDecl);
914 const CXXRecordDecl *classDecl = dtor->getParent();
916 loadThisForDtorDelete(cgf, dtor),
917 cgf.getContext().getCanonicalTagType(classDecl));
918 }
919};
920
921class DestroyField final : public EHScopeStack::Cleanup {
922 const FieldDecl *field;
923 CIRGenFunction::Destroyer *destroyer;
924
925public:
926 DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
927 : field(field), destroyer(destroyer) {}
928
929 void emit(CIRGenFunction &cgf) override {
930 // Find the address of the field.
931 Address thisValue = cgf.loadCXXThisAddress();
932 CanQualType recordTy =
933 cgf.getContext().getCanonicalTagType(field->getParent());
934 LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);
935 LValue lv = cgf.emitLValueForField(thisLV, field);
936 assert(lv.isSimple());
937
939 cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);
940 }
941};
942} // namespace
943
944/// Emit all code that comes at the end of class's destructor. This is to call
945/// destructors on members and base classes in reverse order of their
946/// construction.
947///
948/// For a deleting destructor, this also handles the case where a destroying
949/// operator delete completely overrides the definition.
951 CXXDtorType dtorType) {
952 assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&
953 "Should not emit dtor epilogue for non-exported trivial dtor!");
954
955 // The deleting-destructor phase just needs to call the appropriate
956 // operator delete that Sema picked up.
957 if (dtorType == Dtor_Deleting) {
958 assert(dd->getOperatorDelete() &&
959 "operator delete missing - EnterDtorCleanups");
961 cgm.errorNYI(dd->getSourceRange(), "deleting destructor with vtt");
962 } else {
964 cgm.errorNYI(dd->getSourceRange(),
965 "deleting destructor with destroying operator delete");
966 } else {
967 ehStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
968 }
969 }
970 return;
971 }
972
973 const CXXRecordDecl *classDecl = dd->getParent();
974
975 // Unions have no bases and do not call field destructors.
976 if (classDecl->isUnion())
977 return;
978
979 // The complete-destructor phase just destructs all the virtual bases.
980 if (dtorType == Dtor_Complete) {
982
983 // We push them in the forward order so that they'll be popped in
984 // the reverse order.
985 for (const CXXBaseSpecifier &base : classDecl->vbases()) {
986 auto *baseClassDecl = base.getType()->castAsCXXRecordDecl();
987
988 if (baseClassDecl->hasTrivialDestructor()) {
989 // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
990 // memory. For non-trival base classes the same is done in the class
991 // destructor.
993 } else {
994 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
995 /*baseIsVirtual=*/true);
996 }
997 }
998
999 return;
1000 }
1001
1002 assert(dtorType == Dtor_Base);
1004
1005 // Destroy non-virtual bases.
1006 for (const CXXBaseSpecifier &base : classDecl->bases()) {
1007 // Ignore virtual bases.
1008 if (base.isVirtual())
1009 continue;
1010
1011 CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();
1012
1013 if (baseClassDecl->hasTrivialDestructor())
1015 else
1016 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1017 /*baseIsVirtual=*/false);
1018 }
1019
1021
1022 // Destroy direct fields.
1023 for (const FieldDecl *field : classDecl->fields()) {
1024 QualType type = field->getType();
1025 QualType::DestructionKind dtorKind = type.isDestructedType();
1026 if (!dtorKind)
1027 continue;
1028
1029 // Anonymous union members do not have their destructors called.
1030 const RecordType *rt = type->getAsUnionType();
1031 if (rt && rt->getDecl()->isAnonymousStructOrUnion())
1032 continue;
1033
1034 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1036 ehStack.pushCleanup<DestroyField>(cleanupKind, field,
1037 getDestroyer(dtorKind));
1038 }
1039}
1040
1042 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
1043 assert(ctor->isDelegatingConstructor());
1044
1045 Address thisPtr = loadCXXThisAddress();
1046
1053
1054 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
1055
1056 const CXXRecordDecl *classDecl = ctor->getParent();
1057 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
1058 cgm.errorNYI(ctor->getSourceRange(),
1059 "emitDelegatingCXXConstructorCall: exception");
1060 return;
1061 }
1062}
1063
1066 bool forVirtualBase, bool delegating,
1067 Address thisAddr, QualType thisTy) {
1068 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
1069 delegating, thisAddr, thisTy);
1070}
1071
1072mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1073 bool delegating) {
1074 if (!cgm.getCXXABI().needsVTTParameter(gd))
1075 return nullptr;
1076
1077 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
1078 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();
1079
1080 uint64_t subVTTIndex;
1081
1082 if (delegating) {
1083 // If this is a delegating constructor call, just load the VTT.
1084 return loadCXXVTT();
1085 } else if (rd == base) {
1086 // If the record matches the base, this is the complete ctor/dtor
1087 // variant calling the base variant in a class with virtual bases.
1088 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
1089 "doing no-op VTT offset in base dtor/ctor?");
1090 assert(!forVirtualBase && "Can't have same class as virtual base!");
1091 subVTTIndex = 0;
1092 } else {
1093 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1094 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)
1095 : layout.getBaseClassOffset(base);
1096
1097 subVTTIndex =
1098 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));
1099 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
1100 }
1101
1102 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
1103 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
1104 // A VTT parameter was passed to the constructor, use it.
1105 mlir::Value vtt = loadCXXVTT();
1106 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
1107 } else {
1108 // We're the complete constructor, so get the VTT by name.
1109 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);
1110 return builder.createVTTAddrPoint(
1111 loc, builder.getPointerTo(cgm.voidPtrTy),
1112 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);
1113 }
1114}
1115
1117 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1118 llvm::iterator_range<CastExpr::path_const_iterator> path,
1119 bool nullCheckValue) {
1120 assert(!path.empty() && "Base path should not be empty!");
1121
1122 QualType derivedTy = getContext().getCanonicalTagType(derived);
1123 mlir::Type derivedValueTy = convertType(derivedTy);
1124 CharUnits nonVirtualOffset =
1125 cgm.computeNonVirtualBaseClassOffset(derived, path);
1126
1127 // Note that in OG, no offset (nonVirtualOffset.getQuantity() == 0) means it
1128 // just gives the address back. In CIR a `cir.derived_class` is created and
1129 // made into a nop later on during lowering.
1130 return builder.createDerivedClassAddr(loc, baseAddr, derivedValueTy,
1131 nonVirtualOffset.getQuantity(),
1132 /*assumeNotNull=*/!nullCheckValue);
1133}
1134
1136 Address value, const CXXRecordDecl *derived,
1137 llvm::iterator_range<CastExpr::path_const_iterator> path,
1138 bool nullCheckValue, SourceLocation loc) {
1139 assert(!path.empty() && "Base path should not be empty!");
1140
1141 CastExpr::path_const_iterator start = path.begin();
1142 const CXXRecordDecl *vBase = nullptr;
1143
1144 if ((*path.begin())->isVirtual()) {
1145 vBase = (*start)->getType()->castAsCXXRecordDecl();
1146 ++start;
1147 }
1148
1149 // Compute the static offset of the ultimate destination within its
1150 // allocating subobject (the virtual base, if there is one, or else
1151 // the "complete" object that we see).
1152 CharUnits nonVirtualOffset = cgm.computeNonVirtualBaseClassOffset(
1153 vBase ? vBase : derived, {start, path.end()});
1154
1155 // If there's a virtual step, we can sometimes "devirtualize" it.
1156 // For now, that's limited to when the derived type is final.
1157 // TODO: "devirtualize" this for accesses to known-complete objects.
1158 if (vBase && derived->hasAttr<FinalAttr>()) {
1159 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
1160 CharUnits vBaseOffset = layout.getVBaseClassOffset(vBase);
1161 nonVirtualOffset += vBaseOffset;
1162 vBase = nullptr; // we no longer have a virtual step
1163 }
1164
1165 // Get the base pointer type.
1166 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
1168
1169 // If there is no virtual base, use cir.base_class_addr. It takes care of
1170 // the adjustment and the null pointer check.
1171 if (nonVirtualOffset.isZero() && !vBase) {
1173 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
1174 /*assumeNotNull=*/true);
1175 }
1176
1178
1179 // Compute the virtual offset.
1180 mlir::Value virtualOffset = nullptr;
1181 if (vBase) {
1182 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
1183 getLoc(loc), *this, value, derived, vBase);
1184 }
1185
1186 // Apply both offsets.
1188 getLoc(loc), *this, value, nonVirtualOffset, virtualOffset, derived,
1189 vBase, baseValueTy, not nullCheckValue);
1190
1191 // Cast to the destination type.
1192 value = value.withElementType(builder, baseValueTy);
1193
1194 return value;
1195}
1196
1197// TODO(cir): this can be shared with LLVM codegen.
1200 if (!cgm.getCodeGenOpts().WholeProgramVTables)
1201 return false;
1202
1203 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1204 return true;
1205
1207
1208 return false;
1209}
1210
1211mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1212 const CXXRecordDecl *rd) {
1213 auto vtablePtr = cir::VTableGetVPtrOp::create(
1214 builder, loc, builder.getPtrToVPtrType(), thisAddr.getPointer());
1215 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1216
1217 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1219
1220 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1221 cgm.getCodeGenOpts().StrictVTablePointers) {
1223 }
1224
1225 return vtable;
1226}
1227
1230 bool forVirtualBase,
1231 bool delegating,
1232 AggValueSlot thisAVS,
1233 const clang::CXXConstructExpr *e) {
1234 CallArgList args;
1235 Address thisAddr = thisAVS.getAddress();
1236 QualType thisType = d->getThisType();
1237 mlir::Value thisPtr = thisAddr.getPointer();
1238
1240
1241 args.add(RValue::get(thisPtr), thisType);
1242
1243 // In LLVM Codegen: If this is a trivial constructor, just emit what's needed.
1244 // If this is a union copy constructor, we must emit a memcpy, because the AST
1245 // does not model that copy.
1247
1248 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1249
1251
1252 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1253 /*ParamsToSkip=*/0);
1254
1256 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1257 e->getExprLoc());
1258}
1259
1261 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1262 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1263
1264 const CXXRecordDecl *crd = d->getParent();
1265
1266 // If this is a call to a trivial default constructor:
1267 // In LLVM: do nothing.
1268 // In CIR: emit as a regular call, other later passes should lower the
1269 // ctor call into trivial initialization.
1271
1273
1274 bool passPrototypeArgs = true;
1275
1276 // Check whether we can actually emit the constructor before trying to do so.
1277 if (d->getInheritedConstructor()) {
1278 cgm.errorNYI(d->getSourceRange(),
1279 "emitCXXConstructorCall: inherited constructor");
1280 return;
1281 }
1282
1283 // Insert any ABI-specific implicit constructor arguments.
1285 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1286 delegating, args);
1287
1288 // Emit the call.
1289 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1290 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1291 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1292 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1293 cir::CIRCallOpInterface c;
1294 emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
1295
1296 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1297 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1298 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1299}
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 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:220
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:3722
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:90
mlir::Type getElementType() const
Definition Address.h:117
static Address invalid()
Definition Address.h:69
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
Definition Address.h:130
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...
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...
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...
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
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)
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)
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)
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...
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.
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)
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 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:233
Information for lazily generating a cleanup.
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:83
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:254
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
arg_range arguments()
Definition ExprCXX.h:1672
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1611
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
const FunctionDecl * getOperatorDelete() const
Definition DeclCXX.h:2904
Expr * getOperatorDeleteThisArg() const
Definition DeclCXX.h:2912
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
QualType getFunctionObjectParameterType() const
Definition DeclCXX.h:2279
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
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
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
const CXXBaseSpecifier *const * path_const_iterator
Definition Expr.h:3677
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:3760
bool hasAttr() const
Definition DeclBase.h:577
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:273
Represents a member of a struct/union/class.
Definition Decl.h:3160
Represents a function declaration or definition.
Definition Decl.h:2000
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4199
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4187
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3545
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3127
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4323
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2385
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4543
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5254
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5658
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:4790
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:3467
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3488
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
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
field_range fields() const
Definition Decl.h:4515
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:338
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3812
bool isUnion() const
Definition Decl.h:3922
A template argument list.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3547
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:9158
bool isRecordType() const
Definition TypeBase.h:8642
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.
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_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 ehCleanupFlags()
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