clang 24.0.0git
CIRGenClass.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with C++ code generation of classes
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
14#include "CIRGenFunction.h"
15#include "CIRGenValue.h"
16
17#include "clang/AST/ExprCXX.h"
19#include "clang/AST/Type.h"
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.getLoc(*cgf.currSrcLoc), cgf.loadCXXThisAddress(), derivedClass,
177 baseClass, 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} // end anonymous namespace
203
204/// Gets the address of a direct base class within a complete object.
205/// This should only be used for (1) non-virtual bases or (2) virtual bases
206/// when the type is known to be complete (e.g. in complete destructors).
207///
208/// The object pointed to by 'thisAddr' is assumed to be non-null.
210 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
211 const CXXRecordDecl *base, bool baseIsVirtual) {
212 // 'thisAddr' must be a pointer (in some address space) to Derived.
213 assert(thisAddr.getElementType() == convertType(derived));
214
215 // Compute the offset of the virtual base.
216 CharUnits offset;
217 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
218 if (baseIsVirtual)
219 offset = layout.getVBaseClassOffset(base);
220 else
221 offset = layout.getBaseClassOffset(base);
222
223 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
224 offset.getQuantity(),
225 /*assumeNotNull=*/true);
226}
227
229 const CXXRecordDecl *classDecl,
230 CXXCtorInitializer *baseInit) {
231 assert(curFuncDecl && "loading 'this' without a func declaration?");
233
234 assert(baseInit->isBaseInitializer() && "Must have base initializer!");
235
236 Address thisPtr = loadCXXThisAddress();
237
238 const Type *baseType = baseInit->getBaseClass();
239 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();
240
241 bool isBaseVirtual = baseInit->isBaseVirtual();
242
243 // If the initializer for the base (other than the constructor
244 // itself) accesses 'this' in any way, we need to initialize the
245 // vtables.
247 initializeVTablePointers(loc, classDecl);
248
249 // We can pretend to be a complete class because it only matters for
250 // virtual bases, and we only do virtual bases for complete ctors.
252 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
256 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
257
258 emitAggExpr(baseInit->getInit(), aggSlot);
259
260 if (cgm.getLangOpts().Exceptions && !baseClassDecl->hasTrivialDestructor())
261 ehStack.pushCleanup<CallBaseDtor>(EHCleanup, baseClassDecl,
262 /*baseIsVirtual=*/isBaseVirtual);
263}
264
265/// This routine generates necessary code to initialize base classes and
266/// non-static data members belonging to this constructor.
268 CXXCtorType ctorType,
269 FunctionArgList &args) {
270 if (cd->isDelegatingConstructor()) {
272 return;
273 }
274
275 const CXXRecordDecl *classDecl = cd->getParent();
276
277 // Virtual base initializers aren't needed if:
278 // - This is a base ctor variant
279 // - There are no vbases
280 // - The class is abstract, so a complete object of it cannot be constructed
281 //
282 // The check for an abstract class is necessary because sema may not have
283 // marked virtual base destructors referenced.
284 bool constructVBases = ctorType != Ctor_Base &&
285 classDecl->getNumVBases() != 0 &&
286 !classDecl->isAbstract();
287 if (constructVBases &&
288 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {
289 cgm.errorNYI(cd->getSourceRange(),
290 "emitCtorPrologue: virtual base without variants");
291 return;
292 }
293
294 // Create three separate ranges for the different types of initializers.
295 auto allInits = cd->inits();
296
297 // Find the boundaries between the three groups.
298 auto virtualBaseEnd = std::find_if(
299 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {
300 return !(Init->isBaseInitializer() && Init->isBaseVirtual());
301 });
302
303 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),
304 [](const CXXCtorInitializer *Init) {
305 return !Init->isBaseInitializer();
306 });
307
308 // Create the three ranges.
309 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);
310 auto nonVirtualBaseInits =
311 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);
312 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());
313
314 const mlir::Value oldThisValue = cxxThisValue;
315
316 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {
317 if (cgm.getCodeGenOpts().StrictVTablePointers &&
318 cgm.getCodeGenOpts().OptimizationLevel > 0 &&
320 // It's OK to continue after emitting the error here. The missing code
321 // just "launders" the 'this' pointer.
322 cgm.errorNYI(cd->getSourceRange(),
323 "emitCtorPrologue: strict vtable pointers for vbase");
324 }
325 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);
326 };
327
328 // Process virtual base initializers.
329 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {
330 if (!constructVBases)
331 continue;
332 emitInitializer(virtualBaseInit);
333 }
334
336
337 // Then, non-virtual base initializers.
338 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {
339 assert(!nonVirtualBaseInit->isBaseVirtual());
340 emitInitializer(nonVirtualBaseInit);
341 }
342
343 cxxThisValue = oldThisValue;
344
346
347 // Finally, initialize class members.
349 // Classic codegen uses a special class to attempt to replace member
350 // initializers with memcpy. We could possibly defer that to the
351 // lowering or optimization phases to keep the memory accesses more
352 // explicit. For now, we don't insert memcpy at all.
354 for (CXXCtorInitializer *member : memberInits) {
355 assert(!member->isBaseInitializer());
356 assert(member->isAnyMemberInitializer() &&
357 "Delegating initializer on non-delegating constructor");
358 emitMemberInitializer(*this, cd->getParent(), member, cd, args);
359 }
360}
361
363 mlir::Location loc, CIRGenFunction &cgf, Address addr,
364 CharUnits nonVirtualOffset, mlir::Value virtualOffset,
365 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,
366 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {
367 // Assert that we have something to do.
368 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
369
370 // Compute the offset from the static and dynamic components.
371 mlir::Value baseOffset;
372 if (!nonVirtualOffset.isZero()) {
373 if (virtualOffset) {
374 mlir::Type offsetType =
375 (cgf.cgm.getTarget().getCXXABI().isItaniumFamily() &&
376 cgf.cgm.getLangOpts().RelativeCXXABIVTables)
377 ? cgf.sInt32Ty
378 : cgf.ptrDiffTy;
379 baseOffset = cgf.getBuilder().getConstInt(loc, offsetType,
380 nonVirtualOffset.getQuantity());
381 baseOffset = cgf.getBuilder().createAdd(loc, virtualOffset, baseOffset);
382 } else {
383 assert(baseValueTy && "expected base type");
384 // If no virtualOffset is present this is the final stop.
385 return cgf.getBuilder().createBaseClassAddr(
386 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),
387 assumeNotNull);
388 }
389 } else {
390 baseOffset = virtualOffset;
391 }
392
393 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,
394 // not bytes. So the pointer must be cast to a byte pointer and back.
395
396 mlir::Value ptr = addr.getPointer();
397 mlir::Type charPtrType = cgf.cgm.uInt8PtrTy;
398 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);
399 mlir::Value adjusted = cir::PtrStrideOp::create(
400 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);
401 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());
402
403 // If we have a virtual component, the alignment of the result will
404 // be relative only to the known alignment of that vbase.
405 CharUnits alignment;
406 if (virtualOffset) {
407 assert(nearestVBase && "virtual offset without vbase?");
408 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,
409 nearestVBase);
410 } else {
411 alignment = addr.getAlignment();
412 }
413 alignment = alignment.alignmentAtOffset(nonVirtualOffset);
414
415 return Address(ptr, alignment);
416}
417
419 const VPtr &vptr) {
420 // Compute the address point.
421 mlir::Value vtableAddressPoint =
422 cgm.getCXXABI().getVTableAddressPointInStructor(
423 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);
424
425 if (!vtableAddressPoint)
426 return;
427
428 // Compute where to store the address point.
429 mlir::Value virtualOffset{};
430 CharUnits nonVirtualOffset = CharUnits::Zero();
431
432 mlir::Type baseValueTy;
433 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {
434 // We need to use the virtual base offset offset because the virtual base
435 // might have a different offset in the most derived class.
436 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
437 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);
438 nonVirtualOffset = vptr.offsetFromNearestVBase;
439 } else {
440 // We can just use the base offset in the complete class.
441 nonVirtualOffset = vptr.base.getBaseOffset();
442 baseValueTy =
443 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));
444 }
445
446 // Apply the offsets.
447 Address classAddr = loadCXXThisAddress();
448 if (!nonVirtualOffset.isZero() || virtualOffset) {
450 loc, *this, classAddr, nonVirtualOffset, virtualOffset,
451 vptr.vtableClass, vptr.nearestVBase, baseValueTy);
452 }
453
454 // Finally, store the address point. Use the same CIR types as the field.
455 //
456 // vtable field is derived from `this` pointer, therefore they should be in
457 // the same addr space.
459 auto vtablePtr =
460 cir::VTableGetVPtrOp::create(builder, loc, classAddr.getPointer());
461 Address vtableField = Address(vtablePtr, classAddr.getAlignment());
462 builder.createStore(loc, vtableAddressPoint, vtableField);
465}
466
468 const CXXRecordDecl *rd) {
469 // Ignore classes without a vtable.
470 if (!rd->isDynamicClass())
471 return;
472
473 // Initialize the vtable pointers for this class and all of its bases.
474 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))
475 for (const auto &vptr : getVTablePointers(rd))
476 initializeVTablePointer(loc, vptr);
477
478 if (rd->getNumVBases())
479 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);
480}
481
484 CIRGenFunction::VPtrsVector vptrsResult;
487 /*NearestVBase=*/nullptr,
488 /*OffsetFromNearestVBase=*/CharUnits::Zero(),
489 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,
490 vptrsResult);
491 return vptrsResult;
492}
493
495 const CXXRecordDecl *nearestVBase,
496 CharUnits offsetFromNearestVBase,
497 bool baseIsNonVirtualPrimaryBase,
498 const CXXRecordDecl *vtableClass,
500 VPtrsVector &vptrs) {
501 // If this base is a non-virtual primary base the address point has already
502 // been set.
503 if (!baseIsNonVirtualPrimaryBase) {
504 // Initialize the vtable pointer for this base.
505 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};
506 vptrs.push_back(vptr);
507 }
508
509 const CXXRecordDecl *rd = base.getBase();
510
511 for (const auto &nextBase : rd->bases()) {
512 const auto *baseDecl =
513 cast<CXXRecordDecl>(nextBase.getType()->castAs<RecordType>()->getDecl())
514 ->getDefinitionOrSelf();
515
516 // Ignore classes without a vtable.
517 if (!baseDecl->isDynamicClass())
518 continue;
519
520 CharUnits baseOffset;
521 CharUnits baseOffsetFromNearestVBase;
522 bool baseDeclIsNonVirtualPrimaryBase;
523 const CXXRecordDecl *nextBaseDecl;
524
525 if (nextBase.isVirtual()) {
526 // Check if we've visited this virtual base before.
527 if (!vbases.insert(baseDecl).second)
528 continue;
529
530 const ASTRecordLayout &layout =
531 getContext().getASTRecordLayout(vtableClass);
532
533 nextBaseDecl = baseDecl;
534 baseOffset = layout.getVBaseClassOffset(baseDecl);
535 baseOffsetFromNearestVBase = CharUnits::Zero();
536 baseDeclIsNonVirtualPrimaryBase = false;
537 } else {
538 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
539
540 nextBaseDecl = nearestVBase;
541 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);
542 baseOffsetFromNearestVBase =
543 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);
544 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;
545 }
546
547 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,
548 baseOffsetFromNearestVBase,
549 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,
550 vptrs);
551 }
552}
553
555 assert(curFuncDecl && "loading 'this' without a func declaration?");
557
558 // Lazily compute CXXThisAlignment.
559 if (cxxThisAlignment.isZero()) {
560 // Just use the best known alignment for the parent.
561 // TODO: if we're currently emitting a complete-object ctor/dtor, we can
562 // always use the complete-object alignment.
563 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
564 cxxThisAlignment = cgm.getClassPointerAlignment(rd);
565 }
566
568}
569
571 Expr *init) {
572 QualType fieldType = field->getType();
573 switch (getEvaluationKind(fieldType)) {
574 case cir::TEK_Scalar:
575 if (lhs.isSimple()) {
576 emitExprAsInit(init, field, lhs, false);
577 } else {
578 RValue rhs = RValue::get(emitScalarExpr(init));
579 emitStoreThroughLValue(rhs, lhs);
580 }
581 break;
582 case cir::TEK_Complex:
583 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);
584 break;
585 case cir::TEK_Aggregate: {
591 emitAggExpr(init, slot);
592 break;
593 }
594 }
595
596 // Ensure that we destroy this object if an exception is thrown later in the
597 // constructor.
598 QualType::DestructionKind dtorKind = fieldType.isDestructedType();
599 pushEHDestroyIfNeeded(dtorKind, lhs.getAddress(), fieldType);
600}
601
603 const Expr *e, Address base, mlir::Value memberPtr,
604 const MemberPointerType *memberPtrType, LValueBaseInfo *baseInfo) {
606
607 cir::GetRuntimeMemberOp op = builder.createGetIndirectMember(
608 getLoc(e->getSourceRange()), base.getPointer(), memberPtr);
609
610 QualType memberType = memberPtrType->getPointeeType();
612 CharUnits memberAlign = cgm.getNaturalTypeAlignment(memberType, baseInfo);
613 memberAlign = cgm.getDynamicOffsetAlignment(
614 base.getAlignment(), memberPtrType->getMostRecentCXXRecordDecl(),
615 memberAlign);
616
617 return Address(op, convertTypeForMem(memberPtrType->getPointeeType()),
618 memberAlign);
619}
620
623 const CXXRecordDecl *baseDecl,
624 CharUnits expectedTargetAlign) {
625 // If the base is an incomplete type (which is, alas, possible with
626 // member pointers), be pessimistic.
627 if (!baseDecl->isCompleteDefinition())
628 return std::min(actualBaseAlign, expectedTargetAlign);
629
630 const ASTRecordLayout &baseLayout =
632 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
633
634 // If the class is properly aligned, assume the target offset is, too.
635 //
636 // This actually isn't necessarily the right thing to do --- if the
637 // class is a complete object, but it's only properly aligned for a
638 // base subobject, then the alignments of things relative to it are
639 // probably off as well. (Note that this requires the alignment of
640 // the target to be greater than the NV alignment of the derived
641 // class.)
642 //
643 // However, our approach to this kind of under-alignment can only
644 // ever be best effort; after all, we're never going to propagate
645 // alignments through variables or parameters. Note, in particular,
646 // that constructing a polymorphic type in an address that's less
647 // than pointer-aligned will generally trap in the constructor,
648 // unless we someday add some sort of attribute to change the
649 // assumed alignment of 'this'. So our goal here is pretty much
650 // just to allow the user to explicitly say that a pointer is
651 // under-aligned and then safely access its fields and vtables.
652 if (actualBaseAlign >= expectedBaseAlign)
653 return expectedTargetAlign;
654
655 // Otherwise, we might be offset by an arbitrary multiple of the
656 // actual alignment. The correct adjustment is to take the min of
657 // the two alignments.
658 return std::min(actualBaseAlign, expectedTargetAlign);
659}
660
661/// Return the best known alignment for a pointer to a virtual base,
662/// given the alignment of a pointer to the derived class.
665 const CXXRecordDecl *derivedClass,
666 const CXXRecordDecl *vbaseClass) {
667 // The basic idea here is that an underaligned derived pointer might
668 // indicate an underaligned base pointer.
669
670 assert(vbaseClass->isCompleteDefinition());
671 const ASTRecordLayout &baseLayout =
672 getASTContext().getASTRecordLayout(vbaseClass);
673 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
674
675 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
676 expectedVBaseAlign);
677}
678
679/// Emit a loop to call a particular constructor for each of several members
680/// of an array.
681///
682/// \param ctor the constructor to call for each element
683/// \param arrayType the type of the array to initialize
684/// \param arrayBegin an arrayType*
685/// \param zeroInitialize true if each element should be
686/// zero-initialized before it is constructed
689 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
690 bool zeroInitialize) {
691 QualType elementType;
692 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
693 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
694 newPointerIsChecked, zeroInitialize,
695 /*endOfInit=*/Address::invalid());
696}
697
698/// Emit a loop to call a particular constructor for each of several members
699/// of an array.
700///
701/// \param ctor the constructor to call for each element
702/// \param numElements the number of elements in the array;
703/// may be zero
704/// \param arrayBase a T*, where T is the type constructed by ctor
705/// \param zeroInitialize true if each element should be
706/// zero-initialized before it is constructed
707/// \param endOfInit if valid, an alloca holding the upper bound of an
708/// already-pushed irregular partial-array EH cleanup. When valid, the
709/// loop body will update this slot before each constructor call so the
710/// caller's cleanup covers loop-constructed elements, and no
711/// partial-destruction region is attached to the resulting
712/// cir::ArrayCtor op.
714 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
715 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize,
716 Address endOfInit) {
717 // It's legal for numElements to be zero. This can happen both
718 // dynamically, because x can be zero in 'new A[x]', and statically,
719 // because of GCC extensions that permit zero-length arrays. There
720 // are probably legitimate places where we could assume that this
721 // doesn't happen, but it's not clear that it's worth it.
722
723 // Peel any array types wrapped in the address element type down to the CIR
724 // type of a single constructed object.
725 mlir::Type elementType = arrayBase.getElementType();
726 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
727 elementType = maybeArrayTy.getElementType();
728 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
729
730 bool useDynamicArrayCtor = true;
731 uint64_t constElementCount = 0;
732 if (auto constantOp = numElements.getDefiningOp<cir::ConstantOp>()) {
733 constElementCount = CIRGenFunction::getZExtIntValueFromConstOp(constantOp);
734 if (constElementCount == 0)
735 return;
736 if (constantOp.use_empty())
737 constantOp.erase();
738 useDynamicArrayCtor = false;
739 }
740
741 // Traditional LLVM codegen emits a loop here. CIR lowers to a loop as part of
742 // LoweringPrepare.
743
744 // The alignment of the base, adjusted by the size of a single element,
745 // provides a conservative estimate of the alignment of every element.
746 // (This assumes we never start tracking offsetted alignments.)
747 //
748 // Note that these are complete objects and so we don't need to
749 // use the non-virtual size or alignment.
751 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
752 getContext().getTypeSizeInChars(type));
753
754 mlir::Location loc = getLoc(*currSrcLoc);
755
756 mlir::Value dynamicElPtr;
757 if (useDynamicArrayCtor)
758 dynamicElPtr =
759 builder.createPtrBitcast(arrayBase.getPointer(), elementType);
760
761 // When the caller has already pushed an irregular partial-array cleanup
762 // (signalled by a valid endOfInit), our loop body will keep that cleanup's
763 // upper bound up to date, so we don't need a separate per-element
764 // partial-destruction region on the cir::ArrayCtor op.
765 bool needsPartialArrayCleanup = getLangOpts().Exceptions &&
766 !ctor->getParent()->hasTrivialDestructor() &&
767 !endOfInit.isValid();
768
769 auto emitCtorBody = [&](mlir::OpBuilder &b, mlir::Location l) {
770 mlir::BlockArgument arg =
771 b.getInsertionBlock()->addArgument(ptrToElmType, l);
772 Address curAddr = Address(arg, elementType, eltAlignment);
773 // Extend the caller's irregular partial-array cleanup to cover the
774 // element we're about to construct. If this constructor throws, the
775 // cleanup will destroy every element strictly below this one.
776 if (endOfInit.isValid())
777 builder.createStore(l, arg, endOfInit);
779 if (zeroInitialize)
780 emitNullInitialization(l, curAddr, type);
781 auto currAVS = AggValueSlot::forAddr(
782 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
785 // C++ [class.temporary]p4:
786 // There are two contexts in which temporaries are destroyed at a
787 // different point than the end of the full-expression. The first context
788 // is when a default constructor is called to initialize an element of an
789 // array. If the constructor has one or more default arguments, the
790 // destruction of every temporary created in a default argument expression
791 // is sequenced before the construction of the next array element, if any.
792 {
793 RunCleanupsScope scope(*this);
795 /*ForVirtualBase=*/false,
796 /*Delegating=*/false, currAVS, e);
797 }
798 cir::YieldOp::create(b, l);
799 };
800
801 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
802 emitPartialDtorBody = nullptr;
803 auto partialDtorBuilder = [&](mlir::OpBuilder &b, mlir::Location l) {
804 mlir::BlockArgument arg =
805 b.getInsertionBlock()->addArgument(ptrToElmType, l);
806 Address curAddr = Address(arg, elementType, eltAlignment);
808 /*forVirtualBase=*/false,
809 /*delegating=*/false, curAddr, type);
810 cir::YieldOp::create(b, l);
811 };
812 if (needsPartialArrayCleanup)
813 emitPartialDtorBody = partialDtorBuilder;
814
815 if (useDynamicArrayCtor) {
816 cir::ArrayCtor::create(builder, loc, dynamicElPtr, numElements,
817 emitCtorBody, emitPartialDtorBody);
818 } else {
819 cir::ArrayType arrayTy =
820 cir::ArrayType::get(elementType, constElementCount);
821 mlir::Value arrayOp =
822 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
823 cir::ArrayCtor::create(builder, loc, arrayOp, emitCtorBody,
824 emitPartialDtorBody);
825 }
826}
827
829 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
830 const FunctionArgList &args, SourceLocation loc) {
831 CallArgList delegateArgs;
832
833 FunctionArgList::const_iterator i = args.begin(), e = args.end();
834 assert(i != e && "no parameters to constructor");
835
836 // this
837 Address thisAddr = loadCXXThisAddress();
838 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
839 ++i;
840
841 // FIXME: The location of the VTT parameter in the parameter list is specific
842 // to the Itanium ABI and shouldn't be hardcoded here.
843 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
844 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
845 return;
846 }
847
848 // Explicit arguments.
849 for (; i != e; ++i) {
850 const VarDecl *param = *i;
851 // FIXME: per-argument source location
852 emitDelegateCallArg(delegateArgs, param, loc);
853 }
854
856
857 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
858 /*Delegating=*/true, thisAddr, delegateArgs, loc);
859}
860
862 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
863 assert(assignOp->isCopyAssignmentOperator() ||
864 assignOp->isMoveAssignmentOperator());
865 const Stmt *rootS = assignOp->getBody();
866 assert(isa<CompoundStmt>(rootS) &&
867 "Body of an implicit assignment operator should be compound stmt.");
868 const auto *rootCS = cast<CompoundStmt>(rootS);
869
870 cgm.setFuncInfoAttr(cast<cir::FuncOp>(curFn), assignOp);
871
874
875 // Classic codegen uses a special class to attempt to replace member
876 // initializers with memcpy. We could possibly defer that to the
877 // lowering or optimization phases to keep the memory accesses more
878 // explicit. For now, we don't insert memcpy at all, though in some
879 // cases the AST contains a call to memcpy.
881 for (Stmt *s : rootCS->body())
882 if (emitStmt(s, /*useCurrentScope=*/true).failed())
883 cgm.errorNYI(s->getSourceRange(),
884 std::string("emitImplicitAssignmentOperatorBody: ") +
885 s->getStmtClassName());
886}
887
889 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
890 // Get the address of the call operator.
891 const CIRGenFunctionInfo &calleeFnInfo =
892 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
893 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
894 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
895
896 // Prepare the return slot.
897 const FunctionProtoType *fpt =
898 callOperator->getType()->castAs<FunctionProtoType>();
899 QualType resultType = fpt->getReturnType();
900 ReturnValueSlot returnSlot;
901 // This should also be tracking volatile, unused, and externally destructed.
903 // For aggregate returns, write the callee's result directly into the
904 // static invoker's return slot. Otherwise emitReturnOfRValue below would
905 // aggregate-copy a temporary into returnValue, which is incorrect for
906 // types without a trivial copy/move (e.g. std::string) -- and trips an
907 // assertion in emitAggregateCopy.
908 if (!resultType->isVoidType() && hasAggregateEvaluationKind(resultType))
909 returnSlot = ReturnValueSlot(returnValue);
910
911 // We don't need to separately arrange the call arguments because
912 // the call can't be variadic anyway --- it's impossible to forward
913 // variadic arguments.
914
915 // Now emit our call.
916 CIRGenCallee callee =
917 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
918 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs,
919 /*isMustTail=*/false);
920
921 // Forward the returned value through the function's return slot.
922 if (!resultType->isVoidType()) {
923 if (returnSlot.isNull() && getLangOpts().ObjCAutoRefCount &&
924 resultType->isObjCRetainableType())
925 cgm.errorNYI(callOperator->getSourceRange(),
926 "emitForwardingCallToLambda: ObjCAutoRefCount");
927 emitReturnOfRValue(getLoc(*currSrcLoc), rv, resultType);
928 } else {
929 cir::ReturnOp::create(builder, getLoc(*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 llvm::FoldingSetInsertToken InsertToken;
958 FunctionDecl *correspondingCallOpSpecialization =
959 callOpTemplate->findSpecialization(tal->asArray(), InsertToken);
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 mlir::Location mlirLoc = getLoc(loc);
1271
1272 // Computing the virtual offset requires reading the vtable, which is only
1273 // safe to do once we know the pointer isn't null. Guard the whole
1274 // computation, mirroring classic CodeGen's cast.notnull/cast.end split.
1275 if (vBase && nullCheckValue) {
1276 CharUnits alignment =
1277 cgm.getVBaseAlignment(value.getAlignment(), derived, vBase)
1278 .alignmentAtOffset(nonVirtualOffset);
1279 mlir::Type basePtrTy = builder.getPointerTo(baseValueTy);
1280 mlir::Value ptrIsNull = builder.createPtrIsNull(value.getPointer());
1281 mlir::Value result =
1282 cir::TernaryOp::create(
1283 builder, mlirLoc, ptrIsNull,
1284 [&](mlir::OpBuilder &, mlir::Location) {
1285 builder.createYield(
1286 mlirLoc, builder.getNullPtr(basePtrTy, mlirLoc).getResult());
1287 },
1288 [&](mlir::OpBuilder &, mlir::Location) {
1289 mlir::Value virtualOffset =
1290 cgm.getCXXABI().getVirtualBaseClassOffset(
1291 mlirLoc, *this, value, derived, vBase);
1293 mlirLoc, *this, value, nonVirtualOffset, virtualOffset,
1294 derived, vBase, baseValueTy, /*assumeNotNull=*/true);
1295 adjusted = adjusted.withElementType(builder, baseValueTy);
1296 builder.createYield(mlirLoc, adjusted.getPointer());
1297 })
1298 .getResult();
1299 return Address(result, baseValueTy, alignment);
1300 }
1301
1302 // Compute the virtual offset.
1303 mlir::Value virtualOffset = nullptr;
1304 if (vBase) {
1305 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
1306 mlirLoc, *this, value, derived, vBase);
1307 }
1308
1309 // Apply both offsets.
1311 mlirLoc, *this, value, nonVirtualOffset, virtualOffset, derived, vBase,
1312 baseValueTy, not nullCheckValue);
1313
1314 // Cast to the destination type.
1315 value = value.withElementType(builder, baseValueTy);
1316
1317 return value;
1318}
1319
1320// TODO(cir): this can be shared with LLVM codegen.
1323 if (!cgm.getCodeGenOpts().WholeProgramVTables)
1324 return false;
1325
1326 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1327 return true;
1328
1330
1331 return false;
1332}
1333
1334mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1335 const CXXRecordDecl *rd) {
1336 auto vtablePtr =
1337 cir::VTableGetVPtrOp::create(builder, loc, thisAddr.getPointer());
1338 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1339
1340 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1342
1343 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1344 cgm.getCodeGenOpts().StrictVTablePointers) {
1346 }
1347
1348 return vtable;
1349}
1350
1353 bool forVirtualBase,
1354 bool delegating,
1355 AggValueSlot thisAVS,
1356 const clang::CXXConstructExpr *e) {
1357 Address thisAddr = thisAVS.getAddress();
1358 QualType thisType = d->getThisType();
1359 mlir::Value thisPtr = thisAddr.getPointer();
1360
1362
1363 // If this is a trivial constructor, just emit what's needed. If this is a
1364 // union copy constructor, we must emit a memcpy, because the AST does not
1365 // model that copy.
1367 assert(e->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
1368 const Expr *arg = e->getArg(0);
1369 LValue src = emitLValue(arg);
1371 LValue dest = makeAddrLValue(thisAddr, destTy);
1372 emitAggregateCopy(dest, src, src.getType(), thisAVS.mayOverlap());
1373 return;
1374 }
1375
1376 CallArgList args;
1377 args.add(RValue::get(thisPtr), thisType);
1378
1379 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1380
1382
1383 if (auto inherited = d->getInheritedConstructor();
1384 !inherited || cgm.getTypes().inheritingCtorHasParams(inherited, type))
1385 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1386 /*ParamsToSkip=*/0);
1387
1389 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1390 e->getExprLoc());
1391}
1392
1394 const CXXConstructorDecl *d,
1395 CXXCtorType type) {
1396 // We can't forward a variadic call.
1397 if (d->isVariadic())
1398 return false;
1399
1401 // FIXME(CIR): It isn't clear to me that this is the right answer here,
1402 // classic-codegen decides the answer is 'false' if there is an inalloca
1403 // argument or if there is a param that needs destruction.
1404 // When we get an understanding of what the the calling-convention code
1405 // needs here, we should be able to replace this with either a 'return
1406 // false' or 'return true'.
1407 // Perhaps we should be checking isParamDestroyedInCallee?
1408 cgm.errorNYI(d->getSourceRange(),
1409 "canEmitDelegateCallArgs: args-destroyed-L-to-R in callee");
1410 }
1411
1412 return true;
1413}
1414
1416 const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr,
1417 bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e) {
1418
1419 CallArgList ctorArgs;
1421 thisAddr, d->getThisType()->getPointeeType())),
1422 d->getThisType());
1423
1424 if (inheritedFromVBase &&
1425 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
1426 cgm.errorNYI(e->getSourceRange(), "emitInheritedCXXConstructorCall "
1427 "inheritedFromVBase with ctor variants");
1428 return;
1429 } else if (!cxxInheritedCtorInitExprArgs.empty()) {
1430 // The inheriting constructor was inlined; just inject its arguments.
1431 assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
1432 "wrong number of parameters for inherited constructor call");
1434 ctorArgs[0] = thisArg;
1435 } else {
1436 ctorArgs.push_back(thisArg);
1437 const auto *outerCtor = cast<CXXConstructorDecl>(curCodeDecl);
1438 assert(outerCtor->getNumParams() == d->getNumParams());
1439 assert(!outerCtor->isVariadic() && "should have been inlined");
1440
1441 for (const ParmVarDecl *param : outerCtor->parameters()) {
1442 assert(getContext().hasSameUnqualifiedType(
1443 outerCtor->getParamDecl(param->getFunctionScopeIndex())->getType(),
1444 param->getType()));
1445 emitDelegateCallArg(ctorArgs, param, e->getLocation());
1446
1447 if (param->hasAttr<PassObjectSizeAttr>())
1448 cgm.errorNYI(
1449 e->getLocation(),
1450 "emitInheritedCXXConstructorCall: pass object size attr argument");
1451 }
1452 }
1453
1454 emitCXXConstructorCall(d, Ctor_Base, forVirtualBase, /*delegating=*/false,
1455 thisAddr, ctorArgs, e->getLocation());
1456}
1457
1459 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
1460 bool forVirtualBase, bool delegating, CallArgList &args) {
1461 GlobalDecl gd(d, ctorType);
1463 InlinedInheritingConstructorScope scope(*this, gd);
1464 RunCleanupsScope RunCleanups(*this);
1465
1466 // Save the arguments to be passed to the inherited constructor.
1468
1469 FunctionArgList params;
1470 QualType retTy = buildFunctionArgList(gd, params);
1471 // FIXME(cir): When we get to the !isVoidType NYI below, this probably is
1472 // going to be important. In the meantime, this is likely not really doing
1473 // anything.
1474 fnRetTy = retTy;
1475
1476 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, ctorType, forVirtualBase,
1477 delegating, args);
1478
1479 // Emit a simplified prolog. We only need to emit the implicit params.
1480 assert(args.size() >= params.size() && "too few arguments for call");
1481 for (auto [idx, arg, parm] :
1482 llvm::zip_longest(llvm::index_range{0, args.size()}, args, params)) {
1483 if (idx < params.size() && isa<ImplicitParamDecl>(*parm)) {
1484 mlir::Location parmLoc = getLoc((*parm)->getSourceRange());
1485 RValue argVal = arg->getRValue(*this, parmLoc);
1486
1487 LValue allocaVal = makeAddrLValue(
1488 createTempAlloca(convertType((*parm)->getType()),
1489 getContext().getDeclAlign(*parm), parmLoc),
1490 (*parm)->getType());
1491
1492 emitStoreThroughLValue(argVal, allocaVal, /*isInit=*/true);
1493
1494 setAddrOfLocalVar((*parm), allocaVal.getAddress());
1495 }
1496 }
1497
1498 // FIXME(cir): it isn't clear what it takes to get here with a constructor?
1499 // Leave as an NYI until we come across a reproducer.
1500 if (!retTy->isVoidType())
1501 cgm.errorNYI(d->getSourceRange(),
1502 "emitInlinedInheritingCXXConstructorCall: non-void return");
1503
1504 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
1506 emitCtorPrologue(d, ctorType, params);
1507}
1508
1510 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1511 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1512
1513 const CXXRecordDecl *crd = d->getParent();
1514
1515 // If this is a call to a trivial default constructor:
1516 // In LLVM: do nothing.
1517 // In CIR: emit as a regular call, other later passes should lower the
1518 // ctor call into trivial initialization.
1520
1521 // Note: memcpy-equivalent special members are handled in the
1522 // emitCXXConstructorCall overload that takes a CXXConstructExpr.
1523
1524 bool passPrototypeArgs = true;
1525
1526 // Check whether we can actually emit the constructor before trying to do so.
1527 if (auto inherited = d->getInheritedConstructor()) {
1528 passPrototypeArgs = getTypes().inheritingCtorHasParams(inherited, type);
1529 if (passPrototypeArgs &&
1530 !canEmitDelegateCallArgs(cgm, cgm.getASTContext(), d, type)) {
1531 emitInlinedInheritingCXXConstructorCall(loc, d, type, forVirtualBase,
1532 delegating, args);
1533 return;
1534 }
1535 }
1536
1537 // Insert any ABI-specific implicit constructor arguments.
1539 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1540 delegating, args);
1541
1542 // Emit the call.
1543 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1544 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1545 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1546 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1547 cir::CIRCallOpInterface c;
1548 emitCall(info, callee, ReturnValueSlot(), args, &c, /*isMustTail=*/false,
1549 loc);
1550
1551 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1552 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1553 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1554}
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 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:239
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:965
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:3813
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)
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void pushEHDestroyIfNeeded(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushEHDestroyIfNeeded - Push the standard destructor for the given type as an EH-only cleanup.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, SourceRange clangLoc)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
llvm::SmallVector< VPtr, 4 > VPtrsVector
void emitLambdaStaticInvokeBody(const CXXMethodDecl *md)
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
clang::ASTContext & getContext() const
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr)
Set the address of a local variable.
void emitInheritedCXXConstructorCall(const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr, bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitDelegatingCXXConstructorCall(const CXXConstructorDecl *ctor, const FunctionArgList &args)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
CharUnits getDynamicOffsetAlignment(CharUnits actualBaseAlign, const CXXRecordDecl *baseDecl, CharUnits expectedTargetAlign)
TODO: Add TBAAAccessInfo.
CharUnits getMinimumClassObjectSize(const CXXRecordDecl *cd)
Returns the minimum object size for an object of the given class type (or a class derived from it).
CharUnits getVBaseAlignment(CharUnits derivedAlign, const CXXRecordDecl *derived, const CXXRecordDecl *vbase)
Returns the assumed alignment of a virtual base of a class.
const clang::TargetInfo & getTarget() const
const clang::LangOptions & getLangOpts() const
CIRGenCXXABI & getCXXABI() const
bool inheritingCtorHasParams(const InheritedConstructor &inherited, CXXCtorType type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h: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:2642
init_iterator init_begin()
Retrieve an iterator to the first initializer.
Definition DeclCXX.h:2736
bool isDelegatingConstructor() const
Determine whether this constructor is a delegating constructor.
Definition DeclCXX.h:2792
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:2877
Represents a C++ base or member initializer.
Definition DeclCXX.h:2407
Expr * getInit() const
Get the initializer.
Definition DeclCXX.h:2609
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
Definition DeclCXX.cpp:2953
bool isAnyMemberInitializer() const
Definition DeclCXX.h:2487
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
Definition DeclCXX.h:2479
bool isIndirectMemberInitializer() const
Definition DeclCXX.h:2491
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:2553
IndirectFieldDecl * getIndirectMember() const
Definition DeclCXX.h:2561
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Definition DeclCXX.h:2533
Represents a C++ destructor within a class.
Definition DeclCXX.h:2907
const FunctionDecl * getOperatorDelete() const
Definition DeclCXX.cpp:3230
Expr * getOperatorDeleteThisArg() const
Definition DeclCXX.h:2946
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:2150
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2293
QualType getThisType() const
Return the type of the this pointer.
Definition DeclCXX.cpp:2859
QualType getFunctionObjectParameterType() const
Definition DeclCXX.h:2317
bool isMemcpyEquivalentSpecialMember(const ASTContext &Ctx) const
Returns whether this is a copy/move constructor or assignment operator that can be implemented as a m...
Definition DeclCXX.cpp:2782
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
Definition DeclCXX.cpp:2341
bool isGenericLambda() const
Determine whether this class describes a generic lambda function object (i.e.
Definition DeclCXX.cpp:1681
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
Definition DeclCXX.h:1382
base_class_range bases()
Definition DeclCXX.h:609
base_class_range vbases()
Definition DeclCXX.h:626
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1231
bool isDynamicClass() const
Definition DeclCXX.h:575
bool hasDefinition() const
Definition DeclCXX.h:562
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Definition DeclCXX.cpp:2129
CXXMethodDecl * getLambdaCallOperator() const
Retrieve the lambda call operator of the closure type if this is a closure type.
Definition DeclCXX.cpp:1744
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:624
const CXXBaseSpecifier *const * path_const_iterator
Definition Expr.h: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:3851
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:4244
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4232
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3593
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:3119
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4368
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:4608
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3868
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5398
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5802
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:4934
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:3744
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5827
QualType getPointeeType() const
Definition TypeBase.h:3762
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:9037
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9331
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:881
bool isRecordType() const
Definition TypeBase.h:8792
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)
bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init)
Check whether Init uses 'this' in a way which requires the vtable to be properly set.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
CXXDtorType
C++ destructor types.
Definition ABI.h:34
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool addressSpace()
static bool useEHCleanupForArray()
static bool aggValueSlotGC()
static bool hiddenVisibility()
static bool runCleanupsScope()
static bool 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