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