clang 24.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
17#include "clang/AST/ExprCXX.h"
19#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
157namespace {
158/// Call the destructor for a direct base class.
159struct CallBaseDtor final : EHScopeStack::Cleanup {
160 const CXXRecordDecl *baseClass;
161 bool baseIsVirtual;
162 CallBaseDtor(const CXXRecordDecl *base, bool baseIsVirtual)
163 : baseClass(base), baseIsVirtual(baseIsVirtual) {}
164
165 void emit(CIRGenFunction &cgf, Flags flags) override {
166 const CXXRecordDecl *derivedClass =
167 cast<CXXMethodDecl>(cgf.curFuncDecl)->getParent();
168
169 const CXXDestructorDecl *d = baseClass->getDestructor();
170 // We are already inside a destructor, so presumably the object being
171 // destroyed should have the expected type.
172 QualType thisTy = d->getFunctionObjectParameterType();
173 assert(cgf.currSrcLoc && "expected source location");
175 cgf.getLoc(*cgf.currSrcLoc), cgf.loadCXXThisAddress(), derivedClass,
176 baseClass, baseIsVirtual);
177 cgf.emitCXXDestructorCall(d, Dtor_Base, baseIsVirtual,
178 /*delegating=*/false, addr, thisTy);
179 }
180};
181
182/// If the delegating constructor's body throws after the delegated-to
183/// constructor completes, destroy the object (mirrors CGClass.cpp's
184/// CallDelegatingCtorDtor).
185struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
186 const CXXDestructorDecl *dtor;
187 Address addr;
189
190 CallDelegatingCtorDtor(const CXXDestructorDecl *dtor, Address addr,
192 : dtor(dtor), addr(addr), type(type) {}
193
194 void emit(CIRGenFunction &cgf, Flags flags) override {
195 QualType thisTy = dtor->getFunctionObjectParameterType();
196 cgf.emitCXXDestructorCall(dtor, type, /*forVirtualBase=*/false,
197 /*delegating=*/true, addr, thisTy);
198 }
199};
200
201} // end anonymous namespace
202
203/// Gets the address of a direct base class within a complete object.
204/// This should only be used for (1) non-virtual bases or (2) virtual bases
205/// when the type is known to be complete (e.g. in complete destructors).
206///
207/// The object pointed to by 'thisAddr' is assumed to be non-null.
209 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
210 const CXXRecordDecl *base, bool baseIsVirtual) {
211 // 'thisAddr' must be a pointer (in some address space) to Derived.
212 assert(thisAddr.getElementType() == convertType(derived));
213
214 // Compute the offset of the virtual base.
215 CharUnits offset;
216 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
217 if (baseIsVirtual)
218 offset = layout.getVBaseClassOffset(base);
219 else
220 offset = layout.getBaseClassOffset(base);
221
222 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
223 offset.getQuantity(),
224 /*assumeNotNull=*/true);
225}
226
228 const CXXRecordDecl *classDecl,
229 CXXCtorInitializer *baseInit) {
230 assert(curFuncDecl && "loading 'this' without a func declaration?");
232
233 assert(baseInit->isBaseInitializer() && "Must have base initializer!");
234
235 Address thisPtr = loadCXXThisAddress();
236
237 const Type *baseType = baseInit->getBaseClass();
238 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
239
240 bool isBaseVirtual = baseInit->isBaseVirtual();
241
242 // If the initializer for the base (other than the constructor
243 // itself) accesses 'this' in any way, we need to initialize the
244 // vtables.
246 initializeVTablePointers(loc, classDecl);
247
248 // We can pretend to be a complete class because it only matters for
249 // virtual bases, and we only do virtual bases for complete ctors.
251 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
255 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
256
257 emitAggExpr(baseInit->getInit(), aggSlot);
258
259 if (cgm.getLangOpts().Exceptions && !baseClassDecl->hasTrivialDestructor())
260 ehStack.pushCleanup<CallBaseDtor>(EHCleanup, baseClassDecl,
261 /*baseIsVirtual=*/isBaseVirtual);
262}
263
264/// This routine generates necessary code to initialize base classes and
265/// non-static data members belonging to this constructor.
267 CXXCtorType ctorType,
268 FunctionArgList &args) {
269 if (cd->isDelegatingConstructor()) {
271 return;
272 }
273
274 const CXXRecordDecl *classDecl = cd->getParent();
275
276 // Virtual base initializers aren't needed if:
277 // - This is a base ctor variant
278 // - There are no vbases
279 // - The class is abstract, so a complete object of it cannot be constructed
280 //
281 // The check for an abstract class is necessary because sema may not have
282 // marked virtual base destructors referenced.
283 bool constructVBases = ctorType != Ctor_Base &&
284 classDecl->getNumVBases() != 0 &&
285 !classDecl->isAbstract();
286 if (constructVBases &&
287 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
288 cgm.errorNYI(cd->getSourceRange(),
289 "emitCtorPrologue: virtual base without variants");
290 return;
291 }
292
293 // Create three separate ranges for the different types of initializers.
294 auto allInits = cd->inits();
295
296 // Find the boundaries between the three groups.
297 auto virtualBaseEnd = std::find_if(
298 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {
299 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
300 });
301
302 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),
303 [](const CXXCtorInitializer *Init) {
304 return !Init->isBaseInitializer();
305 });
306
307 // Create the three ranges.
308 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);
309 auto nonVirtualBaseInits =
310 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);
311 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());
312
313 const mlir::Value oldThisValue = cxxThisValue;
314
315 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
316 if (cgm.getCodeGenOpts().StrictVTablePointers &&
317 cgm.getCodeGenOpts().OptimizationLevel > 0 &&
319 // It's OK to continue after emitting the error here. The missing code
320 // just "launders" the 'this' pointer.
321 cgm.errorNYI(cd->getSourceRange(),
322 "emitCtorPrologue: strict vtable pointers for vbase");
323 }
324 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
325 };
326
327 // Process virtual base initializers.
328 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
329 if (!constructVBases)
330 continue;
331 emitInitializer(virtualBaseInit);
332 }
333
335
336 // Then, non-virtual base initializers.
337 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
338 assert(!nonVirtualBaseInit->isBaseVirtual());
339 emitInitializer(nonVirtualBaseInit);
340 }
341
342 cxxThisValue = oldThisValue;
343
345
346 // Finally, initialize class members.
348 // Classic codegen uses a special class to attempt to replace member
349 // initializers with memcpy. We could possibly defer that to the
350 // lowering or optimization phases to keep the memory accesses more
351 // explicit. For now, we don't insert memcpy at all.
353 for (CXXCtorInitializer *member : memberInits) {
354 assert(!member->isBaseInitializer());
355 assert(member->isAnyMemberInitializer() &&
356 "Delegating initializer on non-delegating constructor");
357 emitMemberInitializer(*this, cd->getParent(), member, cd, args);
358 }
359}
360
362 mlir::Location loc, CIRGenFunction &cgf, Address addr,
363 CharUnits nonVirtualOffset, mlir::Value virtualOffset,
364 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,
365 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {
366 // Assert that we have something to do.
367 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
368
369 // Compute the offset from the static and dynamic components.
370 mlir::Value baseOffset;
371 if (!nonVirtualOffset.isZero()) {
372 if (virtualOffset) {
373 mlir::Type offsetType =
374 (cgf.cgm.getTarget().getCXXABI().isItaniumFamily() &&
375 cgf.cgm.getLangOpts().RelativeCXXABIVTables)
376 ? cgf.sInt32Ty
377 : cgf.ptrDiffTy;
378 baseOffset = cgf.getBuilder().getConstInt(loc, offsetType,
379 nonVirtualOffset.getQuantity());
380 baseOffset = cgf.getBuilder().createAdd(loc, virtualOffset, baseOffset);
381 } else {
382 assert(baseValueTy && "expected base type");
383 // If no virtualOffset is present this is the final stop.
384 return cgf.getBuilder().createBaseClassAddr(
385 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),
386 assumeNotNull);
387 }
388 } else {
389 baseOffset = virtualOffset;
390 }
391
392 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,
393 // not bytes. So the pointer must be cast to a byte pointer and back.
394
395 mlir::Value ptr = addr.getPointer();
396 mlir::Type charPtrType =
398 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);
399 mlir::Value adjusted = cir::PtrStrideOp::create(
400 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);
401 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());
402
403 // If we have a virtual component, the alignment of the result will
404 // be relative only to the known alignment of that vbase.
405 CharUnits alignment;
406 if (virtualOffset) {
407 assert(nearestVBase && "virtual offset without vbase?");
408 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,
409 nearestVBase);
410 } else {
411 alignment = addr.getAlignment();
412 }
413 alignment = alignment.alignmentAtOffset(nonVirtualOffset);
414
415 return Address(ptr, alignment);
416}
417
419 const VPtr &vptr) {
420 // Compute the address point.
421 mlir::Value vtableAddressPoint =
422 cgm.getCXXABI().getVTableAddressPointInStructor(
423 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
424
425 if (!vtableAddressPoint)
426 return;
427
428 // Compute where to store the address point.
429 mlir::Value virtualOffset{};
430 CharUnits nonVirtualOffset = CharUnits::Zero();
431
432 mlir::Type baseValueTy;
433 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
434 // We need to use the virtual base offset offset because the virtual base
435 // might have a different offset in the most derived class.
436 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
437 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);
438 nonVirtualOffset = vptr.offsetFromNearestVBase;
439 } else {
440 // We can just use the base offset in the complete class.
441 nonVirtualOffset = vptr.base.getBaseOffset();
442 baseValueTy =
443 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));
444 }
445
446 // Apply the offsets.
447 Address classAddr = loadCXXThisAddress();
448 if (!nonVirtualOffset.isZero() || virtualOffset) {
450 loc, *this, classAddr, nonVirtualOffset, virtualOffset,
451 vptr.vtableClass, vptr.nearestVBase, baseValueTy);
452 }
453
454 // Finally, store the address point. Use the same CIR types as the field.
455 //
456 // vtable field is derived from `this` pointer, therefore they should be in
457 // the same addr space.
459 auto vtablePtr =
460 cir::VTableGetVPtrOp::create(builder, loc, classAddr.getPointer());
461 Address vtableField = Address(vtablePtr, classAddr.getAlignment());
462 builder.createStore(loc, vtableAddressPoint, vtableField);
465}
466
468 const CXXRecordDecl *rd) {
469 // Ignore classes without a vtable.
470 if (!rd->isDynamicClass())
471 return;
472
473 // Initialize the vtable pointers for this class and all of its bases.
474 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
475 for (const auto &vptr : getVTablePointers(rd))
476 initializeVTablePointer(loc, vptr);
477
478 if (rd->getNumVBases())
479 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);
480}
481
484 CIRGenFunction::VPtrsVector vptrsResult;
487 /*NearestVBase=*/nullptr,
488 /*OffsetFromNearestVBase=*/CharUnits::Zero(),
489 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,
490 vptrsResult);
491 return vptrsResult;
492}
493
495 const CXXRecordDecl *nearestVBase,
496 CharUnits offsetFromNearestVBase,
497 bool baseIsNonVirtualPrimaryBase,
498 const CXXRecordDecl *vtableClass,
500 VPtrsVector &vptrs) {
501 // If this base is a non-virtual primary base the address point has already
502 // been set.
503 if (!baseIsNonVirtualPrimaryBase) {
504 // Initialize the vtable pointer for this base.
505 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
506 vptrs.push_back(vptr);
507 }
508
509 const CXXRecordDecl *rd = base.getBase();
510
511 for (const auto &nextBase : rd->bases()) {
512 const auto *baseDecl =
513 cast<CXXRecordDecl>(nextBase.getType()->castAs<RecordType>()->getDecl())
514 ->getDefinitionOrSelf();
515
516 // Ignore classes without a vtable.
517 if (!baseDecl->isDynamicClass())
518 continue;
519
520 CharUnits baseOffset;
521 CharUnits baseOffsetFromNearestVBase;
522 bool baseDeclIsNonVirtualPrimaryBase;
523 const CXXRecordDecl *nextBaseDecl;
524
525 if (nextBase.isVirtual()) {
526 // Check if we've visited this virtual base before.
527 if (!vbases.insert(baseDecl).second)
528 continue;
529
530 const ASTRecordLayout &layout =
531 getContext().getASTRecordLayout(vtableClass);
532
533 nextBaseDecl = baseDecl;
534 baseOffset = layout.getVBaseClassOffset(baseDecl);
535 baseOffsetFromNearestVBase = CharUnits::Zero();
536 baseDeclIsNonVirtualPrimaryBase = false;
537 } else {
538 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
539
540 nextBaseDecl = nearestVBase;
541 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);
542 baseOffsetFromNearestVBase =
543 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);
544 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;
545 }
546
547 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,
548 baseOffsetFromNearestVBase,
549 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,
550 vptrs);
551 }
552}
553
555 assert(curFuncDecl && "loading 'this' without a func declaration?");
557
558 // Lazily compute CXXThisAlignment.
559 if (cxxThisAlignment.isZero()) {
560 // Just use the best known alignment for the parent.
561 // TODO: if we're currently emitting a complete-object ctor/dtor, we can
562 // always use the complete-object alignment.
563 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
564 cxxThisAlignment = cgm.getClassPointerAlignment(rd);
565 }
566
568}
569
571 Expr *init) {
572 QualType fieldType = field->getType();
573 switch (getEvaluationKind(fieldType)) {
574 case cir::TEK_Scalar:
575 if (lhs.isSimple()) {
576 emitExprAsInit(init, field, lhs, false);
577 } else {
578 RValue rhs = RValue::get(emitScalarExpr(init));
579 emitStoreThroughLValue(rhs, lhs);
580 }
581 break;
582 case cir::TEK_Complex:
583 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);
584 break;
585 case cir::TEK_Aggregate: {
591 emitAggExpr(init, slot);
592 break;
593 }
594 }
595
596 // Ensure that we destroy this object if an exception is thrown later in the
597 // constructor.
598 QualType::DestructionKind dtorKind = fieldType.isDestructedType();
599 pushEHDestroyIfNeeded(dtorKind, lhs.getAddress(), fieldType);
600}
601
603 const Expr *e, Address base, mlir::Value memberPtr,
604 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo) {
606
607 cir::GetRuntimeMemberOp op = builder.createGetIndirectMember(
608 getLoc(e->getSourceRange()), base.getPointer(), memberPtr);
609
610 QualType memberType = memberPtrType->getPointeeType();
612 CharUnits memberAlign = cgm.getNaturalTypeAlignment(memberType, baseInfo);
613 memberAlign = cgm.getDynamicOffsetAlignment(
614 base.getAlignment(), memberPtrType->getMostRecentCXXRecordDecl(),
615 memberAlign);
616
617 return Address(op, convertTypeForMem(memberPtrType->getPointeeType()),
618 memberAlign);
619}
620
623 const CXXRecordDecl *baseDecl,
624 CharUnits expectedTargetAlign) {
625 // If the base is an incomplete type (which is, alas, possible with
626 // member pointers), be pessimistic.
627 if (!baseDecl->isCompleteDefinition())
628 return std::min(actualBaseAlign, expectedTargetAlign);
629
630 const ASTRecordLayout &baseLayout =
632 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
633
634 // If the class is properly aligned, assume the target offset is, too.
635 //
636 // This actually isn't necessarily the right thing to do --- if the
637 // class is a complete object, but it's only properly aligned for a
638 // base subobject, then the alignments of things relative to it are
639 // probably off as well. (Note that this requires the alignment of
640 // the target to be greater than the NV alignment of the derived
641 // class.)
642 //
643 // However, our approach to this kind of under-alignment can only
644 // ever be best effort; after all, we're never going to propagate
645 // alignments through variables or parameters. Note, in particular,
646 // that constructing a polymorphic type in an address that's less
647 // than pointer-aligned will generally trap in the constructor,
648 // unless we someday add some sort of attribute to change the
649 // assumed alignment of 'this'. So our goal here is pretty much
650 // just to allow the user to explicitly say that a pointer is
651 // under-aligned and then safely access its fields and vtables.
652 if (actualBaseAlign >= expectedBaseAlign)
653 return expectedTargetAlign;
654
655 // Otherwise, we might be offset by an arbitrary multiple of the
656 // actual alignment. The correct adjustment is to take the min of
657 // the two alignments.
658 return std::min(actualBaseAlign, expectedTargetAlign);
659}
660
661/// Return the best known alignment for a pointer to a virtual base,
662/// given the alignment of a pointer to the derived class.
665 const CXXRecordDecl *derivedClass,
666 const CXXRecordDecl *vbaseClass) {
667 // The basic idea here is that an underaligned derived pointer might
668 // indicate an underaligned base pointer.
669
670 assert(vbaseClass->isCompleteDefinition());
671 const ASTRecordLayout &baseLayout =
672 getASTContext().getASTRecordLayout(vbaseClass);
673 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
674
675 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
676 expectedVBaseAlign);
677}
678
679/// Emit a loop to call a particular constructor for each of several members
680/// of an array.
681///
682/// \param ctor the constructor to call for each element
683/// \param arrayType the type of the array to initialize
684/// \param arrayBegin an arrayType*
685/// \param zeroInitialize true if each element should be
686/// zero-initialized before it is constructed
689 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
690 bool zeroInitialize) {
691 QualType elementType;
692 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
693 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
694 newPointerIsChecked, zeroInitialize,
695 /*endOfInit=*/Address::invalid());
696}
697
698/// Emit a loop to call a particular constructor for each of several members
699/// of an array.
700///
701/// \param ctor the constructor to call for each element
702/// \param numElements the number of elements in the array;
703/// may be zero
704/// \param arrayBase a T*, where T is the type constructed by ctor
705/// \param zeroInitialize true if each element should be
706/// zero-initialized before it is constructed
707/// \param endOfInit if valid, an alloca holding the upper bound of an
708/// already-pushed irregular partial-array EH cleanup. When valid, the
709/// loop body will update this slot before each constructor call so the
710/// caller's cleanup covers loop-constructed elements, and no
711/// partial-destruction region is attached to the resulting
712/// cir::ArrayCtor op.
714 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
715 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize,
716 Address endOfInit) {
717 // It's legal for numElements to be zero. This can happen both
718 // dynamically, because x can be zero in 'new A[x]', and statically,
719 // because of GCC extensions that permit zero-length arrays. There
720 // are probably legitimate places where we could assume that this
721 // doesn't happen, but it's not clear that it's worth it.
722
723 // Peel any array types wrapped in the address element type down to the CIR
724 // type of a single constructed object.
725 mlir::Type elementType = arrayBase.getElementType();
726 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
727 elementType = maybeArrayTy.getElementType();
728 cir::PointerType ptrToElmType =
729 builder.getPointerTo(elementType, arrayBase.getAddressSpace());
730
731 bool useDynamicArrayCtor = true;
732 uint64_t constElementCount = 0;
733 if (auto constantOp = numElements.getDefiningOp<cir::ConstantOp>()) {
734 constElementCount = CIRGenFunction::getZExtIntValueFromConstOp(constantOp);
735 if (constElementCount == 0)
736 return;
737 if (constantOp.use_empty())
738 constantOp.erase();
739 useDynamicArrayCtor = false;
740 }
741
742 // Traditional LLVM codegen emits a loop here. CIR lowers to a loop as part of
743 // LoweringPrepare.
744
745 // The alignment of the base, adjusted by the size of a single element,
746 // provides a conservative estimate of the alignment of every element.
747 // (This assumes we never start tracking offsetted alignments.)
748 //
749 // Note that these are complete objects and so we don't need to
750 // use the non-virtual size or alignment.
752 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
753 getContext().getTypeSizeInChars(type));
754
755 mlir::Location loc = getLoc(*currSrcLoc);
756
757 mlir::Value dynamicElPtr;
758 if (useDynamicArrayCtor)
759 dynamicElPtr =
760 builder.createPtrBitcast(arrayBase.getPointer(), elementType);
761
762 // When the caller has already pushed an irregular partial-array cleanup
763 // (signalled by a valid endOfInit), our loop body will keep that cleanup's
764 // upper bound up to date, so we don't need a separate per-element
765 // partial-destruction region on the cir::ArrayCtor op.
766 bool needsPartialArrayCleanup = getLangOpts().Exceptions &&
767 !ctor->getParent()->hasTrivialDestructor() &&
768 !endOfInit.isValid();
769
770 auto emitCtorBody = [&](mlir::OpBuilder &b, mlir::Location l) {
771 mlir::BlockArgument arg =
772 b.getInsertionBlock()->addArgument(ptrToElmType, l);
773 Address curAddr = Address(arg, elementType, eltAlignment);
774 // Extend the caller's irregular partial-array cleanup to cover the
775 // element we're about to construct. If this constructor throws, the
776 // cleanup will destroy every element strictly below this one.
777 if (endOfInit.isValid())
778 builder.createStore(l, arg, endOfInit);
780 if (zeroInitialize)
781 emitNullInitialization(l, curAddr, type);
782 auto currAVS = AggValueSlot::forAddr(
783 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
786 // C++ [class.temporary]p4:
787 // There are two contexts in which temporaries are destroyed at a
788 // different point than the end of the full-expression. The first context
789 // is when a default constructor is called to initialize an element of an
790 // array. If the constructor has one or more default arguments, the
791 // destruction of every temporary created in a default argument expression
792 // is sequenced before the construction of the next array element, if any.
793 {
794 FullExprCleanupScope scope(*this, e);
797 /*ForVirtualBase=*/false,
798 /*Delegating=*/false, currAVS, e);
799 }
800 cir::YieldOp::create(b, l);
801 };
802
803 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
804 emitPartialDtorBody = nullptr;
805 auto partialDtorBuilder = [&](mlir::OpBuilder &b, mlir::Location l) {
806 mlir::BlockArgument arg =
807 b.getInsertionBlock()->addArgument(ptrToElmType, l);
808 Address curAddr = Address(arg, elementType, eltAlignment);
810 /*forVirtualBase=*/false,
811 /*delegating=*/false, curAddr, type);
812 cir::YieldOp::create(b, l);
813 };
814 if (needsPartialArrayCleanup)
815 emitPartialDtorBody = partialDtorBuilder;
816
817 if (useDynamicArrayCtor) {
818 cir::ArrayCtor::create(builder, loc, dynamicElPtr, numElements,
819 emitCtorBody, emitPartialDtorBody);
820 } else {
821 cir::ArrayType arrayTy =
822 cir::ArrayType::get(elementType, constElementCount);
823 mlir::Value arrayOp =
824 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
825 cir::ArrayCtor::create(builder, loc, arrayOp, emitCtorBody,
826 emitPartialDtorBody);
827 }
828}
829
831 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
832 const FunctionArgList &args, SourceLocation loc) {
833 CallArgList delegateArgs;
834
835 FunctionArgList::const_iterator i = args.begin(), e = args.end();
836 assert(i != e && "no parameters to constructor");
837
838 // this
839 Address thisAddr = loadCXXThisAddress();
840 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
841 ++i;
842
843 // FIXME: The location of the VTT parameter in the parameter list is specific
844 // to the Itanium ABI and shouldn't be hardcoded here.
845 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
846 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
847 return;
848 }
849
850 // Explicit arguments.
851 for (; i != e; ++i) {
852 const VarDecl *param = *i;
853 // FIXME: per-argument source location
854 emitDelegateCallArg(delegateArgs, param, loc);
855 }
856
858
859 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
860 /*Delegating=*/true, thisAddr, delegateArgs, loc);
861}
862
864 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
865 assert(assignOp->isCopyAssignmentOperator() ||
866 assignOp->isMoveAssignmentOperator());
867 const Stmt *rootS = assignOp->getBody();
868 assert(isa<CompoundStmt>(rootS) &&
869 "Body of an implicit assignment operator should be compound stmt.");
870 const auto *rootCS = cast<CompoundStmt>(rootS);
871
872 cgm.setFuncInfoAttr(cast<cir::FuncOp>(curFn), assignOp);
873
876
877 // Classic codegen uses a special class to attempt to replace member
878 // initializers with memcpy. We could possibly defer that to the
879 // lowering or optimization phases to keep the memory accesses more
880 // explicit. For now, we don't insert memcpy at all, though in some
881 // cases the AST contains a call to memcpy.
883 for (Stmt *s : rootCS->body())
884 if (emitStmt(s, /*useCurrentScope=*/true).failed())
885 cgm.errorNYI(s->getSourceRange(),
886 std::string("emitImplicitAssignmentOperatorBody: ") +
887 s->getStmtClassName());
888}
889
891 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
892 // Get the address of the call operator.
893 const CIRGenFunctionInfo &calleeFnInfo =
894 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
895 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
896 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
897
898 // Prepare the return slot.
899 const FunctionProtoType *fpt =
900 callOperator->getType()->castAs<FunctionProtoType>();
901 QualType resultType = fpt->getReturnType();
902 ReturnValueSlot returnSlot;
903 // This should also be tracking volatile, unused, and externally destructed.
905 // For aggregate returns, write the callee's result directly into the
906 // static invoker's return slot. Otherwise emitReturnOfRValue below would
907 // aggregate-copy a temporary into returnValue, which is incorrect for
908 // types without a trivial copy/move (e.g. std::string) -- and trips an
909 // assertion in emitAggregateCopy.
910 if (!resultType->isVoidType() && hasAggregateEvaluationKind(resultType))
911 returnSlot = ReturnValueSlot(returnValue);
912
913 // We don't need to separately arrange the call arguments because
914 // the call can't be variadic anyway --- it's impossible to forward
915 // variadic arguments.
916
917 // Now emit our call.
918 CIRGenCallee callee =
919 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
920 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs,
921 /*isMustTail=*/false);
922
923 // Forward the returned value through the function's return slot.
924 if (!resultType->isVoidType()) {
925 if (returnSlot.isNull() && getLangOpts().ObjCAutoRefCount &&
926 resultType->isObjCRetainableType())
927 cgm.errorNYI(callOperator->getSourceRange(),
928 "emitForwardingCallToLambda: ObjCAutoRefCount");
929 emitReturnOfRValue(getLoc(*currSrcLoc), rv, resultType);
930 } else {
931 cir::ReturnOp::create(builder, getLoc(*currSrcLoc));
932 }
933}
934
936 const CXXRecordDecl *lambda = md->getParent();
937
938 // Start building arguments for forwarding call
939 CallArgList callArgs;
940
941 QualType lambdaType = getContext().getCanonicalTagType(lambda);
942 QualType thisType = getContext().getPointerType(lambdaType);
943 Address thisPtr =
944 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");
945 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);
946
947 // Add the rest of the parameters.
948 for (auto *param : md->parameters())
949 emitDelegateCallArg(callArgs, param, param->getBeginLoc());
950
951 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();
952 // For a generic lambda, find the corresponding call operator specialization
953 // to which the call to the static-invoker shall be forwarded.
954 if (lambda->isGenericLambda()) {
957 FunctionTemplateDecl *callOpTemplate =
959 llvm::FoldingSetInsertToken InsertToken;
960 FunctionDecl *correspondingCallOpSpecialization =
961 callOpTemplate->findSpecialization(tal->asArray(), InsertToken);
962 assert(correspondingCallOpSpecialization);
963 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
964 }
965 emitForwardingCallToLambda(callOp, callArgs);
966}
967
969 if (md->isVariadic()) {
970 // Codgen for LLVM doesn't emit code for this as well, it says:
971 // FIXME: Making this work correctly is nasty because it requires either
972 // cloning the body of the call operator or making the call operator
973 // forward.
974 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");
975 }
976
978}
979
981 QualType type) {
982 const auto *record = type->castAsCXXRecordDecl();
983 const CXXDestructorDecl *dtor = record->getDestructor();
984 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
985 // dtors which shall be removed on later CIR passes. However, only remove this
986 // assertion after we have a test case to exercise this path.
987 assert(!dtor->isTrivial());
988 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
989 /*delegating=*/false, addr, type);
990}
991
993 if (Expr *thisArg = dd->getOperatorDeleteThisArg())
994 return emitScalarExpr(thisArg);
995 return loadCXXThis();
996}
997
998namespace {
999/// Call the operator delete associated with the current destructor.
1000struct CallDtorDelete final : EHScopeStack::Cleanup {
1001 CallDtorDelete() {}
1002
1003 void emit(CIRGenFunction &cgf, Flags flags) override {
1005 const CXXRecordDecl *classDecl = dtor->getParent();
1007 cgf.loadThisForDtorDelete(dtor),
1008 cgf.getContext().getCanonicalTagType(classDecl));
1009 }
1010};
1011
1012class DestroyField final : public EHScopeStack::Cleanup {
1013 const FieldDecl *field;
1014 CIRGenFunction::Destroyer *destroyer;
1015
1016public:
1017 DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
1018 : field(field), destroyer(destroyer) {}
1019
1020 void emit(CIRGenFunction &cgf, Flags flags) override {
1021 // Find the address of the field.
1022 Address thisValue = cgf.loadCXXThisAddress();
1023 CanQualType recordTy =
1024 cgf.getContext().getCanonicalTagType(field->getParent());
1025 LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);
1026 LValue lv = cgf.emitLValueForField(thisLV, field);
1027 assert(lv.isSimple());
1028
1030 cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);
1031 }
1032};
1033} // namespace
1034
1035/// Emit all code that comes at the end of class's destructor. This is to call
1036/// destructors on members and base classes in reverse order of their
1037/// construction.
1038///
1039/// For a deleting destructor, this pushes the cleanup that calls operator
1040/// delete. The caller handles a destroying operator delete.
1042 CXXDtorType dtorType) {
1043 assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&
1044 "Should not emit dtor epilogue for non-exported trivial dtor!");
1045
1046 // The deleting-destructor phase just needs to call the appropriate
1047 // operator delete that Sema picked up.
1048 if (dtorType == Dtor_Deleting) {
1049 assert(dd->getOperatorDelete() &&
1050 "operator delete missing - EnterDtorCleanups");
1052 // The implicit parameter of a deleting destructor is the Microsoft ABI
1053 // flag word that selects whether and which operator delete is called.
1054 assert(getTarget().getCXXABI().isMicrosoft() &&
1055 "only the Microsoft ABI passes an implicit deleting dtor param");
1056 cgm.errorNYI(dd->getSourceRange(),
1057 "deleting destructor with conditional delete: MSVC ABI");
1058
1059 } else {
1061 "destroying operator delete is handled by emitDestructorBody");
1062 ehStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
1063 }
1064 return;
1065 }
1066
1067 const CXXRecordDecl *classDecl = dd->getParent();
1068
1069 // Unions have no bases and do not call field destructors.
1070 if (classDecl->isUnion())
1071 return;
1072
1073 // The complete-destructor phase just destructs all the virtual bases.
1074 if (dtorType == Dtor_Complete) {
1076
1077 // We push them in the forward order so that they'll be popped in
1078 // the reverse order.
1079 for (const CXXBaseSpecifier &base : classDecl->vbases()) {
1080 auto *baseClassDecl = base.getType()->castAsCXXRecordDecl();
1081
1082 if (baseClassDecl->hasTrivialDestructor()) {
1083 // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
1084 // memory. For non-trival base classes the same is done in the class
1085 // destructor.
1087 } else {
1088 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1089 /*baseIsVirtual=*/true);
1090 }
1091 }
1092
1093 return;
1094 }
1095
1096 assert(dtorType == Dtor_Base);
1098
1099 // Destroy non-virtual bases.
1100 for (const CXXBaseSpecifier &base : classDecl->bases()) {
1101 // Ignore virtual bases.
1102 if (base.isVirtual())
1103 continue;
1104
1105 CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();
1106
1107 if (baseClassDecl->hasTrivialDestructor())
1109 else
1110 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1111 /*baseIsVirtual=*/false);
1112 }
1113
1115
1116 // Destroy direct fields.
1117 for (const FieldDecl *field : classDecl->fields()) {
1118 QualType type = field->getType();
1119 QualType::DestructionKind dtorKind = type.isDestructedType();
1120 if (!dtorKind)
1121 continue;
1122
1123 // Anonymous union members do not have their destructors called.
1124 const RecordType *rt = type->getAsUnionType();
1125 if (rt && rt->getDecl()->isAnonymousStructOrUnion())
1126 continue;
1127
1128 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1130 ehStack.pushCleanup<DestroyField>(cleanupKind, field,
1131 getDestroyer(dtorKind));
1132 }
1133}
1134
1136 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
1137 assert(ctor->isDelegatingConstructor());
1138
1139 Address thisPtr = loadCXXThisAddress();
1140
1147
1148 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
1149
1150 const CXXRecordDecl *classDecl = ctor->getParent();
1151 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
1152 CXXDtorType dtorType =
1153 curGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
1154 ehStack.pushCleanup<CallDelegatingCtorDtor>(
1155 EHCleanup, classDecl->getDestructor(), thisPtr, dtorType);
1156 }
1157}
1158
1161 bool forVirtualBase, bool delegating,
1162 Address thisAddr, QualType thisTy) {
1163 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
1164 delegating, thisAddr, thisTy);
1165}
1166
1167mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1168 bool delegating) {
1169 if (!cgm.getCXXABI().needsVTTParameter(gd))
1170 return nullptr;
1171
1172 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
1173 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();
1174
1175 uint64_t subVTTIndex;
1176
1177 if (delegating) {
1178 // If this is a delegating constructor call, just load the VTT.
1179 return loadCXXVTT();
1180 } else if (rd == base) {
1181 // If the record matches the base, this is the complete ctor/dtor
1182 // variant calling the base variant in a class with virtual bases.
1183 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
1184 "doing no-op VTT offset in base dtor/ctor?");
1185 assert(!forVirtualBase && "Can't have same class as virtual base!");
1186 subVTTIndex = 0;
1187 } else {
1188 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1189 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)
1190 : layout.getBaseClassOffset(base);
1191
1192 subVTTIndex =
1193 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));
1194 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
1195 }
1196
1197 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
1198 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
1199 // A VTT parameter was passed to the constructor, use it.
1200 mlir::Value vtt = loadCXXVTT();
1201 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
1202 } else {
1203 // We're the complete constructor, so get the VTT by name.
1204 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);
1205 return builder.createVTTAddrPoint(
1206 loc, builder.getPointerTo(cgm.voidPtrTy),
1207 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);
1208 }
1209}
1210
1212 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1213 llvm::iterator_range<CastExpr::path_const_iterator> path,
1214 bool nullCheckValue) {
1215 assert(!path.empty() && "Base path should not be empty!");
1216
1217 QualType derivedTy = getContext().getCanonicalTagType(derived);
1218 mlir::Type derivedValueTy = convertType(derivedTy);
1219 CharUnits nonVirtualOffset =
1220 cgm.computeNonVirtualBaseClassOffset(derived, path);
1221
1222 // Note that in OG, no offset (nonVirtualOffset.getQuantity() == 0) means it
1223 // just gives the address back. In CIR a `cir.derived_class` is created and
1224 // made into a nop later on during lowering.
1225 return builder.createDerivedClassAddr(loc, baseAddr, derivedValueTy,
1226 nonVirtualOffset.getQuantity(),
1227 /*assumeNotNull=*/!nullCheckValue);
1228}
1229
1231 Address value, const CXXRecordDecl *derived,
1232 llvm::iterator_range<CastExpr::path_const_iterator> path,
1233 bool nullCheckValue, SourceLocation loc) {
1234 assert(!path.empty() && "Base path should not be empty!");
1235
1236 CastExpr::path_const_iterator start = path.begin();
1237 const CXXRecordDecl *vBase = nullptr;
1238
1239 if ((*path.begin())->isVirtual()) {
1240 vBase = (*start)->getType()->castAsCXXRecordDecl();
1241 ++start;
1242 }
1243
1244 // Compute the static offset of the ultimate destination within its
1245 // allocating subobject (the virtual base, if there is one, or else
1246 // the "complete" object that we see).
1247 CharUnits nonVirtualOffset = cgm.computeNonVirtualBaseClassOffset(
1248 vBase ? vBase : derived, {start, path.end()});
1249
1250 // If there's a virtual step, we can sometimes "devirtualize" it.
1251 // For now, that's limited to when the derived type is final.
1252 // TODO: "devirtualize" this for accesses to known-complete objects.
1253 if (vBase && derived->hasAttr<FinalAttr>()) {
1254 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
1255 CharUnits vBaseOffset = layout.getVBaseClassOffset(vBase);
1256 nonVirtualOffset += vBaseOffset;
1257 vBase = nullptr; // we no longer have a virtual step
1258 }
1259
1260 // Get the base pointer type.
1261 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
1262
1263 // If there is no virtual base, use cir.base_class_addr. It takes care of
1264 // the adjustment and the null pointer check.
1265 if (nonVirtualOffset.isZero() && !vBase) {
1267 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
1268 /*assumeNotNull=*/true);
1269 }
1270
1272
1273 mlir::Location mlirLoc = getLoc(loc);
1274
1275 // Computing the virtual offset requires reading the vtable, which is only
1276 // safe to do once we know the pointer isn't null. Guard the whole
1277 // computation, mirroring classic CodeGen's cast.notnull/cast.end split.
1278 if (vBase && nullCheckValue) {
1279 CharUnits alignment =
1280 cgm.getVBaseAlignment(value.getAlignment(), derived, vBase)
1281 .alignmentAtOffset(nonVirtualOffset);
1282 mlir::Type basePtrTy =
1283 builder.getPointerTo(baseValueTy, value.getAddressSpace());
1284 mlir::Value ptrIsNull = builder.createPtrIsNull(value.getPointer());
1285 mlir::Value result =
1286 cir::TernaryOp::create(
1287 builder, mlirLoc, ptrIsNull,
1288 [&](mlir::OpBuilder &, mlir::Location) {
1289 builder.createYield(
1290 mlirLoc, builder.getNullPtr(basePtrTy, mlirLoc).getResult());
1291 },
1292 [&](mlir::OpBuilder &, mlir::Location) {
1293 mlir::Value virtualOffset =
1294 cgm.getCXXABI().getVirtualBaseClassOffset(
1295 mlirLoc, *this, value, derived, vBase);
1297 mlirLoc, *this, value, nonVirtualOffset, virtualOffset,
1298 derived, vBase, baseValueTy, /*assumeNotNull=*/true);
1299 adjusted = adjusted.withElementType(builder, baseValueTy);
1300 builder.createYield(mlirLoc, adjusted.getPointer());
1301 })
1302 .getResult();
1303 return Address(result, baseValueTy, alignment);
1304 }
1305
1306 // Compute the virtual offset.
1307 mlir::Value virtualOffset = nullptr;
1308 if (vBase) {
1309 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
1310 mlirLoc, *this, value, derived, vBase);
1311 }
1312
1313 // Apply both offsets.
1315 mlirLoc, *this, value, nonVirtualOffset, virtualOffset, derived, vBase,
1316 baseValueTy, not nullCheckValue);
1317
1318 // Cast to the destination type.
1319 value = value.withElementType(builder, baseValueTy);
1320
1321 return value;
1322}
1323
1324// TODO(cir): this can be shared with LLVM codegen.
1327 if (!cgm.getCodeGenOpts().WholeProgramVTables)
1328 return false;
1329
1330 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1331 return true;
1332
1334
1335 return false;
1336}
1337
1338mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1339 const CXXRecordDecl *rd) {
1340 auto vtablePtr =
1341 cir::VTableGetVPtrOp::create(builder, loc, thisAddr.getPointer());
1342 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1343
1344 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1346
1347 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1348 cgm.getCodeGenOpts().StrictVTablePointers) {
1350 }
1351
1352 return vtable;
1353}
1354
1357 bool forVirtualBase,
1358 bool delegating,
1359 AggValueSlot thisAVS,
1360 const clang::CXXConstructExpr *e) {
1361 Address thisAddr = thisAVS.getAddress();
1362 QualType thisType = d->getThisType();
1363 mlir::Value thisPtr = thisAddr.getPointer();
1364
1366
1367 // If this is a trivial constructor, just emit what's needed. If this is a
1368 // union copy constructor, we must emit a memcpy, because the AST does not
1369 // model that copy.
1371 assert(e->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
1372 const Expr *arg = e->getArg(0);
1373 LValue src = emitLValue(arg);
1375 LValue dest = makeAddrLValue(thisAddr, destTy);
1376 emitAggregateCopy(dest, src, src.getType(), thisAVS.mayOverlap());
1377 return;
1378 }
1379
1380 CallArgList args;
1381 args.add(RValue::get(thisPtr), thisType);
1382
1383 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1384
1386 ? EvaluationOrder::ForceLeftToRight
1387 : EvaluationOrder::Default;
1388
1389 if (auto inherited = d->getInheritedConstructor();
1390 !inherited || cgm.getTypes().inheritingCtorHasParams(inherited, type))
1391 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1392 /*ParamsToSkip=*/0, order);
1393
1395 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1396 e->getExprLoc());
1397}
1398
1400 const CXXConstructorDecl *d,
1401 CXXCtorType type) {
1402 // We can't forward a variadic call.
1403 if (d->isVariadic())
1404 return false;
1405
1407 // FIXME(CIR): It isn't clear to me that this is the right answer here,
1408 // classic-codegen decides the answer is 'false' if there is an inalloca
1409 // argument or if there is a param that needs destruction.
1410 // When we get an understanding of what the the calling-convention code
1411 // needs here, we should be able to replace this with either a 'return
1412 // false' or 'return true'.
1413 // Perhaps we should be checking isParamDestroyedInCallee?
1414 cgm.errorNYI(d->getSourceRange(),
1415 "canEmitDelegateCallArgs: args-destroyed-L-to-R in callee");
1416 }
1417
1418 return true;
1419}
1420
1422 const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr,
1423 bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e) {
1424
1425 CallArgList ctorArgs;
1427 thisAddr, d->getThisType()->getPointeeType())),
1428 d->getThisType());
1429
1430 if (inheritedFromVBase &&
1431 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
1432 // The base-object variant doesn't construct virtual bases, so the
1433 // inherited constructor's arguments aren't passed.
1434 ctorArgs.push_back(thisArg);
1435 } else if (!cxxInheritedCtorInitExprArgs.empty()) {
1436 // The inheriting constructor was inlined; just inject its arguments.
1437 assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
1438 "wrong number of parameters for inherited constructor call");
1440 ctorArgs[0] = thisArg;
1441 } else {
1442 ctorArgs.push_back(thisArg);
1443 const auto *outerCtor = cast<CXXConstructorDecl>(curCodeDecl);
1444 assert(outerCtor->getNumParams() == d->getNumParams());
1445 assert(!outerCtor->isVariadic() && "should have been inlined");
1446
1447 for (const ParmVarDecl *param : outerCtor->parameters()) {
1448 assert(getContext().hasSameUnqualifiedType(
1449 outerCtor->getParamDecl(param->getFunctionScopeIndex())->getType(),
1450 param->getType()));
1451 emitDelegateCallArg(ctorArgs, param, e->getLocation());
1452
1453 if (param->hasAttr<PassObjectSizeAttr>())
1454 cgm.errorNYI(
1455 e->getLocation(),
1456 "emitInheritedCXXConstructorCall: pass object size attr argument");
1457 }
1458 }
1459
1460 emitCXXConstructorCall(d, Ctor_Base, forVirtualBase, /*delegating=*/false,
1461 thisAddr, ctorArgs, e->getLocation());
1462}
1463
1465 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
1466 bool forVirtualBase, bool delegating, CallArgList &args) {
1467 GlobalDecl gd(d, ctorType);
1469 InlinedInheritingConstructorScope scope(*this, gd);
1470 RunCleanupsScope RunCleanups(*this);
1471
1472 // Save the arguments to be passed to the inherited constructor.
1474
1475 FunctionArgList params;
1476 QualType retTy = buildFunctionArgList(gd, params);
1477 // FIXME(cir): When we get to the !isVoidType NYI below, this probably is
1478 // going to be important. In the meantime, this is likely not really doing
1479 // anything.
1480 fnRetTy = retTy;
1481
1482 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, ctorType, forVirtualBase,
1483 delegating, args);
1484
1485 // Emit a simplified prolog. We only need to emit the implicit params.
1486 assert(args.size() >= params.size() && "too few arguments for call");
1487 for (auto [idx, arg, parm] :
1488 llvm::zip_longest(llvm::index_range{0, args.size()}, args, params)) {
1489 if (idx < params.size() && isa<ImplicitParamDecl>(*parm)) {
1490 mlir::Location parmLoc = getLoc((*parm)->getSourceRange());
1491 RValue argVal = arg->getRValue(*this, parmLoc);
1492
1493 LValue allocaVal = makeAddrLValue(
1494 createTempAlloca(convertType((*parm)->getType()),
1495 getContext().getDeclAlign(*parm), parmLoc),
1496 (*parm)->getType());
1497
1498 emitStoreThroughLValue(argVal, allocaVal, /*isInit=*/true);
1499
1500 setAddrOfLocalVar((*parm), allocaVal.getAddress());
1501 }
1502 }
1503
1504 // FIXME(cir): it isn't clear what it takes to get here with a constructor?
1505 // Leave as an NYI until we come across a reproducer.
1506 if (!retTy->isVoidType())
1507 cgm.errorNYI(d->getSourceRange(),
1508 "emitInlinedInheritingCXXConstructorCall: non-void return");
1509
1510 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
1512 emitCtorPrologue(d, ctorType, params);
1513}
1514
1516 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1517 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1518
1519 const CXXRecordDecl *crd = d->getParent();
1520
1521 // If this is a call to a trivial default constructor:
1522 // In LLVM: do nothing.
1523 // In CIR: emit as a regular call, other later passes should lower the
1524 // ctor call into trivial initialization.
1526
1527 // Note: memcpy-equivalent special members are handled in the
1528 // emitCXXConstructorCall overload that takes a CXXConstructExpr.
1529
1530 bool passPrototypeArgs = true;
1531
1532 // Check whether we can actually emit the constructor before trying to do so.
1533 if (auto inherited = d->getInheritedConstructor()) {
1534 passPrototypeArgs = getTypes().inheritingCtorHasParams(inherited, type);
1535 if (passPrototypeArgs &&
1536 !canEmitDelegateCallArgs(cgm, cgm.getASTContext(), d, type)) {
1537 emitInlinedInheritingCXXConstructorCall(loc, d, type, forVirtualBase,
1538 delegating, args);
1539 return;
1540 }
1541 }
1542
1543 // Insert any ABI-specific implicit constructor arguments.
1545 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1546 delegating, args);
1547
1548 // Emit the call.
1549 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1550 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1551 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1552 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1553 cir::CIRCallOpInterface c;
1554 emitCall(info, callee, ReturnValueSlot(), args, &c, /*isMustTail=*/false,
1555 loc);
1556
1557 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1558 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1559 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1560}
static bool emit(llvm::SmallVectorImpl< std::byte > &Code, const T &Val)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
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 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.
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::PointerType getPointerTo(mlir::Type ty)
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:245
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:971
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:3820
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
mlir::ptr::MemorySpaceAttrInterface getAddressSpace() const
Definition Address.h:133
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
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:138
bool isValid() const
Definition Address.h:77
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)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
Address createBaseClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
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)
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)
const TargetInfo & getTarget() const
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)
CodeGenUtils::EvaluationOrder EvaluationOrder
void initializeVTablePointer(mlir::Location loc, const VPtr &vptr)
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0, EvaluationOrder order=EvaluationOrder::Default)
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.
Address returnValue
The temporary alloca to hold the return value.
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
static bool hasAggregateEvaluationKind(clang::QualType type)
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...
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)
mlir::Value loadThisForDtorDelete(const CXXDestructorDecl *dd)
Return the pointer to pass to the operator delete of the given destructor, converted to the type of i...
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)
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
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.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, SourceRange clangLoc)
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.
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.
const clang::TargetInfo & getTarget() const
const clang::LangOptions & getLangOpts() const
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:241
Information for lazily generating a cleanup.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:195
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:262
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a call to a C++ constructor.
Definition ExprCXX.h:1553
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1696
arg_range arguments()
Definition ExprCXX.h:1677
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1616
bool isListInitialization() const
Whether this constructor call was written as list-initialization.
Definition ExprCXX.h:1635
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Definition ExprCXX.h:1693
Represents a C++ constructor within a class.
Definition DeclCXX.h:2645
init_iterator init_begin()
Retrieve an iterator to the first initializer.
Definition DeclCXX.h:2751
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
Definition DeclCXX.h:2800
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Definition DeclCXX.cpp:3069
InheritedConstructor getInheritedConstructor() const
Get the constructor that this inheriting constructor is based on.
Definition DeclCXX.h:2885
Represents a C++ base or member initializer.
Definition DeclCXX.h:2410
Expr * getInit() const
Get the initializer.
Definition DeclCXX.h:2612
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
Definition DeclCXX.cpp:2953
bool isAnyMemberInitializer() const
Definition DeclCXX.h:2490
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Definition DeclCXX.h:2482
bool isIndirectMemberInitializer() const
Definition DeclCXX.h:2494
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Definition DeclCXX.cpp:2946
FieldDecl * getAnyMember() const
Definition DeclCXX.h:2556
IndirectFieldDecl * getIndirectMember() const
Definition DeclCXX.h:2564
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Definition DeclCXX.h:2536
Represents a C++ destructor within a class.
Definition DeclCXX.h:2915
const FunctionDecl * getOperatorDelete() const
Definition DeclCXX.cpp:3230
Expr * getOperatorDeleteThisArg() const
Definition DeclCXX.h:2954
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1756
SourceLocation getLocation() const LLVM_READONLY
Definition ExprCXX.h:1809
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2153
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2296
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2859
QualType getFunctionObjectParameterType() const
Definition DeclCXX.h:2320
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:2782
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:2341
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
Definition DeclCXX.cpp:1681
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1382
base_class_range bases()
Definition DeclCXX.h:609
base_class_range vbases()
Definition DeclCXX.h:626
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1231
bool isDynamicClass() const
Definition DeclCXX.h:575
bool hasDefinition() const
Definition DeclCXX.h:562
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2129
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition DeclCXX.cpp:1744
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:624
const CXXBaseSpecifier *const * path_const_iterator
Definition Expr.h:3812
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:177
bool isZero() const
Test whether the quantity equals zero.
Definition CharUnits.h:101
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
static CharUnits One()
Construct a CharUnits quantity of one.
Definition CharUnits.h:55
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:184
static CharUnits Zero()
Construct a CharUnits quantity of zero.
Definition CharUnits.h:52
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3858
bool hasAttr() const
Definition DeclBase.h:586
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:833
This represents one expression.
Definition Expr.h:114
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
Represents a member of a struct/union/class.
Definition Decl.h:3341
Represents a function declaration or definition.
Definition Decl.h:2082
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4280
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4268
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3624
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2947
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2546
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3137
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4404
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2554
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4645
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3899
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5548
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5952
Declaration of a template function.
FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, llvm::FoldingSetInsertToken &InsertToken)
Return the specialization with the provided arguments if it exists, otherwise return the insertion po...
QualType getReturnType() const
Definition TypeBase.h:5084
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
CXXCtorType getCtorType() const
Definition GlobalDecl.h:117
const Decl * getDecl() const
Definition GlobalDecl.h:115
Represents a field injected from an anonymous union/struct into the parent scope.
Definition Decl.h:3648
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3669
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3751
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5845
QualType getPointeeType() const
Definition TypeBase.h:3769
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:303
Represents a parameter to a function.
Definition Decl.h:1832
A (possibly-)qualified type.
Definition TypeBase.h:938
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1561
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
field_range fields() const
Definition Decl.h:4709
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:343
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3999
bool isUnion() const
Definition Decl.h:4109
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:3728
bool isVoidType() const
Definition TypeBase.h:9200
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9498
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isRecordType() const
Definition TypeBase.h:8942
QualType getType() const
Definition Decl.h:725
Represents a variable declaration or definition.
Definition Decl.h:934
#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...
bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit)
Return whether BaseInit initializes a base class that is dynamic, that is, one whose vtable pointer m...
bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init)
Check whether Init uses 'this' in a way which requires the vtable to be properly set.
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
Top level wrappers for InstallAPI frontend operations.
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 createInvariantGroup()
static bool isTrivialCtorOrDtor()
static bool returnValueSlotFeatures()
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