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