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 /*endOfInit=*/Address::invalid());
724}
725
726/// Emit a loop to call a particular constructor for each of several members
727/// of an array.
728///
729/// \param ctor the constructor to call for each element
730/// \param numElements the number of elements in the array;
731/// may be zero
732/// \param arrayBase a T*, where T is the type constructed by ctor
733/// \param zeroInitialize true if each element should be
734/// zero-initialized before it is constructed
735/// \param endOfInit if valid, an alloca holding the upper bound of an
736/// already-pushed irregular partial-array EH cleanup. When valid, the
737/// loop body will update this slot before each constructor call so the
738/// caller's cleanup covers loop-constructed elements, and no
739/// partial-destruction region is attached to the resulting
740/// cir::ArrayCtor op.
742 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
743 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize,
744 Address endOfInit) {
745 // It's legal for numElements to be zero. This can happen both
746 // dynamically, because x can be zero in 'new A[x]', and statically,
747 // because of GCC extensions that permit zero-length arrays. There
748 // are probably legitimate places where we could assume that this
749 // doesn't happen, but it's not clear that it's worth it.
750
751 // Peel any array types wrapped in the address element type down to the CIR
752 // type of a single constructed object.
753 mlir::Type elementType = arrayBase.getElementType();
754 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))
755 elementType = maybeArrayTy.getElementType();
756 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
757
758 bool useDynamicArrayCtor = true;
759 uint64_t constElementCount = 0;
760 if (auto constantOp = numElements.getDefiningOp<cir::ConstantOp>()) {
761 constElementCount = CIRGenFunction::getZExtIntValueFromConstOp(constantOp);
762 if (constElementCount == 0)
763 return;
764 if (constantOp.use_empty())
765 constantOp.erase();
766 useDynamicArrayCtor = false;
767 }
768
769 // Traditional LLVM codegen emits a loop here. CIR lowers to a loop as part of
770 // LoweringPrepare.
771
772 // The alignment of the base, adjusted by the size of a single element,
773 // provides a conservative estimate of the alignment of every element.
774 // (This assumes we never start tracking offsetted alignments.)
775 //
776 // Note that these are complete objects and so we don't need to
777 // use the non-virtual size or alignment.
779 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
780 getContext().getTypeSizeInChars(type));
781
782 mlir::Location loc = *currSrcLoc;
783
784 mlir::Value dynamicElPtr;
785 if (useDynamicArrayCtor)
786 dynamicElPtr =
787 builder.createPtrBitcast(arrayBase.getPointer(), elementType);
788
789 // C++ [class.temporary]p4:
790 // There are two contexts in which temporaries are destroyed at a different
791 // point than the end of the full-expression. The first context is when a
792 // default constructor is called to initialize an element of an array.
793 // If the constructor has one or more default arguments, the destruction of
794 // every temporary created in a default argument expression is sequenced
795 // before the construction of the next array element, if any.
796 {
797 RunCleanupsScope scope(*this);
798
799 // When the caller has already pushed an irregular partial-array cleanup
800 // (signalled by a valid endOfInit), our loop body will keep that cleanup's
801 // upper bound up to date, so we don't need a separate per-element
802 // partial-destruction region on the cir::ArrayCtor op.
803 bool needsPartialArrayCleanup =
804 getLangOpts().Exceptions &&
805 !ctor->getParent()->hasTrivialDestructor() && !endOfInit.isValid();
806
807 auto emitCtorBody = [&](mlir::OpBuilder &b, mlir::Location l) {
808 mlir::BlockArgument arg =
809 b.getInsertionBlock()->addArgument(ptrToElmType, l);
810 Address curAddr = Address(arg, elementType, eltAlignment);
811 // Extend the caller's irregular partial-array cleanup to cover the
812 // element we're about to construct. If this constructor throws, the
813 // cleanup will destroy every element strictly below this one.
814 if (endOfInit.isValid())
815 builder.createStore(l, arg, endOfInit);
817 if (zeroInitialize)
818 emitNullInitialization(l, curAddr, type);
819 auto currAVS = AggValueSlot::forAddr(
820 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
824 /*ForVirtualBase=*/false,
825 /*Delegating=*/false, currAVS, e);
826 cir::YieldOp::create(b, l);
827 };
828
829 llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>
830 emitPartialDtorBody = nullptr;
831 auto partialDtorBuilder = [&](mlir::OpBuilder &b, mlir::Location l) {
832 mlir::BlockArgument arg =
833 b.getInsertionBlock()->addArgument(ptrToElmType, l);
834 Address curAddr = Address(arg, elementType, eltAlignment);
836 /*forVirtualBase=*/false,
837 /*delegating=*/false, curAddr, type);
838 cir::YieldOp::create(b, l);
839 };
840 if (needsPartialArrayCleanup)
841 emitPartialDtorBody = partialDtorBuilder;
842
843 if (useDynamicArrayCtor) {
844 cir::ArrayCtor::create(builder, loc, dynamicElPtr, numElements,
845 emitCtorBody, emitPartialDtorBody);
846 } else {
847 cir::ArrayType arrayTy =
848 cir::ArrayType::get(elementType, constElementCount);
849 mlir::Value arrayOp =
850 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
851 cir::ArrayCtor::create(builder, loc, arrayOp, emitCtorBody,
852 emitPartialDtorBody);
853 }
854 }
855}
856
858 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
859 const FunctionArgList &args, SourceLocation loc) {
860 CallArgList delegateArgs;
861
862 FunctionArgList::const_iterator i = args.begin(), e = args.end();
863 assert(i != e && "no parameters to constructor");
864
865 // this
866 Address thisAddr = loadCXXThisAddress();
867 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
868 ++i;
869
870 // FIXME: The location of the VTT parameter in the parameter list is specific
871 // to the Itanium ABI and shouldn't be hardcoded here.
872 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
873 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
874 return;
875 }
876
877 // Explicit arguments.
878 for (; i != e; ++i) {
879 const VarDecl *param = *i;
880 // FIXME: per-argument source location
881 emitDelegateCallArg(delegateArgs, param, loc);
882 }
883
885
886 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
887 /*Delegating=*/true, thisAddr, delegateArgs, loc);
888}
889
891 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
892 assert(assignOp->isCopyAssignmentOperator() ||
893 assignOp->isMoveAssignmentOperator());
894 const Stmt *rootS = assignOp->getBody();
895 assert(isa<CompoundStmt>(rootS) &&
896 "Body of an implicit assignment operator should be compound stmt.");
897 const auto *rootCS = cast<CompoundStmt>(rootS);
898
899 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), assignOp);
900
903
904 // Classic codegen uses a special class to attempt to replace member
905 // initializers with memcpy. We could possibly defer that to the
906 // lowering or optimization phases to keep the memory accesses more
907 // explicit. For now, we don't insert memcpy at all, though in some
908 // cases the AST contains a call to memcpy.
910 for (Stmt *s : rootCS->body())
911 if (emitStmt(s, /*useCurrentScope=*/true).failed())
912 cgm.errorNYI(s->getSourceRange(),
913 std::string("emitImplicitAssignmentOperatorBody: ") +
914 s->getStmtClassName());
915}
916
918 const CXXMethodDecl *callOperator, CallArgList &callArgs) {
919 // Get the address of the call operator.
920 const CIRGenFunctionInfo &calleeFnInfo =
921 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);
922 cir::FuncOp calleePtr = cgm.getAddrOfFunction(
923 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));
924
925 // Prepare the return slot.
926 const FunctionProtoType *fpt =
927 callOperator->getType()->castAs<FunctionProtoType>();
928 QualType resultType = fpt->getReturnType();
929 ReturnValueSlot returnSlot;
930 // This should also be tracking volatile, unused, and externally destructed.
932 // For aggregate returns, write the callee's result directly into the
933 // static invoker's return slot. Otherwise emitReturnOfRValue below would
934 // aggregate-copy a temporary into returnValue, which is incorrect for
935 // types without a trivial copy/move (e.g. std::string) -- and trips an
936 // assertion in emitAggregateCopy.
937 if (!resultType->isVoidType() && hasAggregateEvaluationKind(resultType))
938 returnSlot = ReturnValueSlot(returnValue);
939
940 // We don't need to separately arrange the call arguments because
941 // the call can't be variadic anyway --- it's impossible to forward
942 // variadic arguments.
943
944 // Now emit our call.
945 CIRGenCallee callee =
946 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));
947 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs);
948
949 // Forward the returned value through the function's return slot.
950 if (!resultType->isVoidType()) {
951 if (returnSlot.isNull() && getLangOpts().ObjCAutoRefCount &&
952 resultType->isObjCRetainableType())
953 cgm.errorNYI(callOperator->getSourceRange(),
954 "emitForwardingCallToLambda: ObjCAutoRefCount");
955 emitReturnOfRValue(*currSrcLoc, rv, resultType);
956 } else {
957 cir::ReturnOp::create(builder, *currSrcLoc);
958 }
959}
960
962 const CXXRecordDecl *lambda = md->getParent();
963
964 // Start building arguments for forwarding call
965 CallArgList callArgs;
966
967 QualType lambdaType = getContext().getCanonicalTagType(lambda);
968 QualType thisType = getContext().getPointerType(lambdaType);
969 Address thisPtr =
970 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");
971 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);
972
973 // Add the rest of the parameters.
974 for (auto *param : md->parameters())
975 emitDelegateCallArg(callArgs, param, param->getBeginLoc());
976
977 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();
978 // For a generic lambda, find the corresponding call operator specialization
979 // to which the call to the static-invoker shall be forwarded.
980 if (lambda->isGenericLambda()) {
983 FunctionTemplateDecl *callOpTemplate =
985 void *InsertPos = nullptr;
986 FunctionDecl *correspondingCallOpSpecialization =
987 callOpTemplate->findSpecialization(tal->asArray(), InsertPos);
988 assert(correspondingCallOpSpecialization);
989 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);
990 }
991 emitForwardingCallToLambda(callOp, callArgs);
992}
993
995 if (md->isVariadic()) {
996 // Codgen for LLVM doesn't emit code for this as well, it says:
997 // FIXME: Making this work correctly is nasty because it requires either
998 // cloning the body of the call operator or making the call operator
999 // forward.
1000 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");
1001 }
1002
1004}
1005
1007 QualType type) {
1008 const auto *record = type->castAsCXXRecordDecl();
1009 const CXXDestructorDecl *dtor = record->getDestructor();
1010 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
1011 // dtors which shall be removed on later CIR passes. However, only remove this
1012 // assertion after we have a test case to exercise this path.
1013 assert(!dtor->isTrivial());
1014 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
1015 /*delegating=*/false, addr, type);
1016}
1017
1018namespace {
1019mlir::Value loadThisForDtorDelete(CIRGenFunction &cgf,
1020 const CXXDestructorDecl *dd) {
1021 if (Expr *thisArg = dd->getOperatorDeleteThisArg())
1022 return cgf.emitScalarExpr(thisArg);
1023 return cgf.loadCXXThis();
1024}
1025
1026/// Call the operator delete associated with the current destructor.
1027struct CallDtorDelete final : EHScopeStack::Cleanup {
1028 CallDtorDelete() {}
1029
1030 void emit(CIRGenFunction &cgf, Flags flags) override {
1031 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(cgf.curFuncDecl);
1032 const CXXRecordDecl *classDecl = dtor->getParent();
1034 loadThisForDtorDelete(cgf, dtor),
1035 cgf.getContext().getCanonicalTagType(classDecl));
1036 }
1037};
1038
1039class DestroyField final : public EHScopeStack::Cleanup {
1040 const FieldDecl *field;
1041 CIRGenFunction::Destroyer *destroyer;
1042
1043public:
1044 DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)
1045 : field(field), destroyer(destroyer) {}
1046
1047 void emit(CIRGenFunction &cgf, Flags flags) override {
1048 // Find the address of the field.
1049 Address thisValue = cgf.loadCXXThisAddress();
1050 CanQualType recordTy =
1051 cgf.getContext().getCanonicalTagType(field->getParent());
1052 LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);
1053 LValue lv = cgf.emitLValueForField(thisLV, field);
1054 assert(lv.isSimple());
1055
1057 cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);
1058 }
1059};
1060} // namespace
1061
1062/// Emit all code that comes at the end of class's destructor. This is to call
1063/// destructors on members and base classes in reverse order of their
1064/// construction.
1065///
1066/// For a deleting destructor, this also handles the case where a destroying
1067/// operator delete completely overrides the definition.
1069 CXXDtorType dtorType) {
1070 assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&
1071 "Should not emit dtor epilogue for non-exported trivial dtor!");
1072
1073 // The deleting-destructor phase just needs to call the appropriate
1074 // operator delete that Sema picked up.
1075 if (dtorType == Dtor_Deleting) {
1076 assert(dd->getOperatorDelete() &&
1077 "operator delete missing - EnterDtorCleanups");
1079 cgm.errorNYI(dd->getSourceRange(), "deleting destructor with vtt");
1080 } else {
1082 cgm.errorNYI(dd->getSourceRange(),
1083 "deleting destructor with destroying operator delete");
1084 } else {
1085 ehStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
1086 }
1087 }
1088 return;
1089 }
1090
1091 const CXXRecordDecl *classDecl = dd->getParent();
1092
1093 // Unions have no bases and do not call field destructors.
1094 if (classDecl->isUnion())
1095 return;
1096
1097 // The complete-destructor phase just destructs all the virtual bases.
1098 if (dtorType == Dtor_Complete) {
1100
1101 // We push them in the forward order so that they'll be popped in
1102 // the reverse order.
1103 for (const CXXBaseSpecifier &base : classDecl->vbases()) {
1104 auto *baseClassDecl = base.getType()->castAsCXXRecordDecl();
1105
1106 if (baseClassDecl->hasTrivialDestructor()) {
1107 // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
1108 // memory. For non-trival base classes the same is done in the class
1109 // destructor.
1111 } else {
1112 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1113 /*baseIsVirtual=*/true);
1114 }
1115 }
1116
1117 return;
1118 }
1119
1120 assert(dtorType == Dtor_Base);
1122
1123 // Destroy non-virtual bases.
1124 for (const CXXBaseSpecifier &base : classDecl->bases()) {
1125 // Ignore virtual bases.
1126 if (base.isVirtual())
1127 continue;
1128
1129 CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();
1130
1131 if (baseClassDecl->hasTrivialDestructor())
1133 else
1134 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,
1135 /*baseIsVirtual=*/false);
1136 }
1137
1139
1140 // Destroy direct fields.
1141 for (const FieldDecl *field : classDecl->fields()) {
1142 QualType type = field->getType();
1143 QualType::DestructionKind dtorKind = type.isDestructedType();
1144 if (!dtorKind)
1145 continue;
1146
1147 // Anonymous union members do not have their destructors called.
1148 const RecordType *rt = type->getAsUnionType();
1149 if (rt && rt->getDecl()->isAnonymousStructOrUnion())
1150 continue;
1151
1152 CleanupKind cleanupKind = getCleanupKind(dtorKind);
1154 ehStack.pushCleanup<DestroyField>(cleanupKind, field,
1155 getDestroyer(dtorKind));
1156 }
1157}
1158
1160 const CXXConstructorDecl *ctor, const FunctionArgList &args) {
1161 assert(ctor->isDelegatingConstructor());
1162
1163 Address thisPtr = loadCXXThisAddress();
1164
1171
1172 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
1173
1174 const CXXRecordDecl *classDecl = ctor->getParent();
1175 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
1176 CXXDtorType dtorType =
1177 curGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
1178 ehStack.pushCleanup<CallDelegatingCtorDtor>(
1179 EHCleanup, classDecl->getDestructor(), thisPtr, dtorType);
1180 }
1181}
1182
1185 bool forVirtualBase, bool delegating,
1186 Address thisAddr, QualType thisTy) {
1187 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
1188 delegating, thisAddr, thisTy);
1189}
1190
1191mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
1192 bool delegating) {
1193 if (!cgm.getCXXABI().needsVTTParameter(gd))
1194 return nullptr;
1195
1196 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
1197 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();
1198
1199 uint64_t subVTTIndex;
1200
1201 if (delegating) {
1202 // If this is a delegating constructor call, just load the VTT.
1203 return loadCXXVTT();
1204 } else if (rd == base) {
1205 // If the record matches the base, this is the complete ctor/dtor
1206 // variant calling the base variant in a class with virtual bases.
1207 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
1208 "doing no-op VTT offset in base dtor/ctor?");
1209 assert(!forVirtualBase && "Can't have same class as virtual base!");
1210 subVTTIndex = 0;
1211 } else {
1212 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1213 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)
1214 : layout.getBaseClassOffset(base);
1215
1216 subVTTIndex =
1217 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));
1218 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
1219 }
1220
1221 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
1222 if (cgm.getCXXABI().needsVTTParameter(curGD)) {
1223 // A VTT parameter was passed to the constructor, use it.
1224 mlir::Value vtt = loadCXXVTT();
1225 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
1226 } else {
1227 // We're the complete constructor, so get the VTT by name.
1228 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);
1229 return builder.createVTTAddrPoint(
1230 loc, builder.getPointerTo(cgm.voidPtrTy),
1231 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);
1232 }
1233}
1234
1236 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,
1237 llvm::iterator_range<CastExpr::path_const_iterator> path,
1238 bool nullCheckValue) {
1239 assert(!path.empty() && "Base path should not be empty!");
1240
1241 QualType derivedTy = getContext().getCanonicalTagType(derived);
1242 mlir::Type derivedValueTy = convertType(derivedTy);
1243 CharUnits nonVirtualOffset =
1244 cgm.computeNonVirtualBaseClassOffset(derived, path);
1245
1246 // Note that in OG, no offset (nonVirtualOffset.getQuantity() == 0) means it
1247 // just gives the address back. In CIR a `cir.derived_class` is created and
1248 // made into a nop later on during lowering.
1249 return builder.createDerivedClassAddr(loc, baseAddr, derivedValueTy,
1250 nonVirtualOffset.getQuantity(),
1251 /*assumeNotNull=*/!nullCheckValue);
1252}
1253
1255 Address value, const CXXRecordDecl *derived,
1256 llvm::iterator_range<CastExpr::path_const_iterator> path,
1257 bool nullCheckValue, SourceLocation loc) {
1258 assert(!path.empty() && "Base path should not be empty!");
1259
1260 CastExpr::path_const_iterator start = path.begin();
1261 const CXXRecordDecl *vBase = nullptr;
1262
1263 if ((*path.begin())->isVirtual()) {
1264 vBase = (*start)->getType()->castAsCXXRecordDecl();
1265 ++start;
1266 }
1267
1268 // Compute the static offset of the ultimate destination within its
1269 // allocating subobject (the virtual base, if there is one, or else
1270 // the "complete" object that we see).
1271 CharUnits nonVirtualOffset = cgm.computeNonVirtualBaseClassOffset(
1272 vBase ? vBase : derived, {start, path.end()});
1273
1274 // If there's a virtual step, we can sometimes "devirtualize" it.
1275 // For now, that's limited to when the derived type is final.
1276 // TODO: "devirtualize" this for accesses to known-complete objects.
1277 if (vBase && derived->hasAttr<FinalAttr>()) {
1278 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
1279 CharUnits vBaseOffset = layout.getVBaseClassOffset(vBase);
1280 nonVirtualOffset += vBaseOffset;
1281 vBase = nullptr; // we no longer have a virtual step
1282 }
1283
1284 // Get the base pointer type.
1285 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
1287
1288 // If there is no virtual base, use cir.base_class_addr. It takes care of
1289 // the adjustment and the null pointer check.
1290 if (nonVirtualOffset.isZero() && !vBase) {
1292 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
1293 /*assumeNotNull=*/true);
1294 }
1295
1297
1298 // Compute the virtual offset.
1299 mlir::Value virtualOffset = nullptr;
1300 if (vBase) {
1301 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(
1302 getLoc(loc), *this, value, derived, vBase);
1303 }
1304
1305 // Apply both offsets.
1307 getLoc(loc), *this, value, nonVirtualOffset, virtualOffset, derived,
1308 vBase, baseValueTy, not nullCheckValue);
1309
1310 // Cast to the destination type.
1311 value = value.withElementType(builder, baseValueTy);
1312
1313 return value;
1314}
1315
1316// TODO(cir): this can be shared with LLVM codegen.
1319 if (!cgm.getCodeGenOpts().WholeProgramVTables)
1320 return false;
1321
1322 if (cgm.getCodeGenOpts().VirtualFunctionElimination)
1323 return true;
1324
1326
1327 return false;
1328}
1329
1330mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,
1331 const CXXRecordDecl *rd) {
1332 auto vtablePtr =
1333 cir::VTableGetVPtrOp::create(builder, loc, thisAddr.getPointer());
1334 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());
1335
1336 auto vtable = builder.createLoad(loc, vtablePtrAddr);
1338
1339 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1340 cgm.getCodeGenOpts().StrictVTablePointers) {
1342 }
1343
1344 return vtable;
1345}
1346
1349 bool forVirtualBase,
1350 bool delegating,
1351 AggValueSlot thisAVS,
1352 const clang::CXXConstructExpr *e) {
1353 Address thisAddr = thisAVS.getAddress();
1354 QualType thisType = d->getThisType();
1355 mlir::Value thisPtr = thisAddr.getPointer();
1356
1358
1359 // If this is a trivial constructor, just emit what's needed. If this is a
1360 // union copy constructor, we must emit a memcpy, because the AST does not
1361 // model that copy.
1363 assert(e->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
1364 const Expr *arg = e->getArg(0);
1365 LValue src = emitLValue(arg);
1367 LValue dest = makeAddrLValue(thisAddr, destTy);
1368 emitAggregateCopy(dest, src, src.getType(), thisAVS.mayOverlap());
1369 return;
1370 }
1371
1372 CallArgList args;
1373 args.add(RValue::get(thisPtr), thisType);
1374
1375 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
1376
1378
1379 if (auto inherited = d->getInheritedConstructor();
1380 !inherited || cgm.getTypes().inheritingCtorHasParams(inherited, type))
1381 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
1382 /*ParamsToSkip=*/0);
1383
1385 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
1386 e->getExprLoc());
1387}
1388
1390 const CXXConstructorDecl *d,
1391 CXXCtorType type) {
1392 // We can't forward a variadic call.
1393 if (d->isVariadic())
1394 return false;
1395
1397 // FIXME(CIR): It isn't clear to me that this is the right answer here,
1398 // classic-codegen decides the answer is 'false' if there is an inalloca
1399 // argument or if there is a param that needs destruction.
1400 // When we get an understanding of what the the calling-convention code
1401 // needs here, we should be able to replace this with either a 'return
1402 // false' or 'return true'.
1403 // Perhaps we should be checking isParamDestroyedInCallee?
1404 cgm.errorNYI(d->getSourceRange(),
1405 "canEmitDelegateCallArgs: args-destroyed-L-to-R in callee");
1406 }
1407
1408 return true;
1409}
1410
1412 const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr,
1413 bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e) {
1414
1415 CallArgList ctorArgs;
1417 thisAddr, d->getThisType()->getPointeeType())),
1418 d->getThisType());
1419
1420 if (inheritedFromVBase &&
1421 cgm.getTarget().getCXXABI().hasConstructorVariants()) {
1422 cgm.errorNYI(e->getSourceRange(), "emitInheritedCXXConstructorCall "
1423 "inheritedFromVBase with ctor variants");
1424 return;
1425 } else if (!cxxInheritedCtorInitExprArgs.empty()) {
1426 // The inheriting constructor was inlined; just inject its arguments.
1427 assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
1428 "wrong number of parameters for inherited constructor call");
1430 ctorArgs[0] = thisArg;
1431 } else {
1432 ctorArgs.push_back(thisArg);
1433 const auto *outerCtor = cast<CXXConstructorDecl>(curCodeDecl);
1434 assert(outerCtor->getNumParams() == d->getNumParams());
1435 assert(!outerCtor->isVariadic() && "should have been inlined");
1436
1437 for (const ParmVarDecl *param : outerCtor->parameters()) {
1438 assert(getContext().hasSameUnqualifiedType(
1439 outerCtor->getParamDecl(param->getFunctionScopeIndex())->getType(),
1440 param->getType()));
1441 emitDelegateCallArg(ctorArgs, param, e->getLocation());
1442
1443 if (param->hasAttr<PassObjectSizeAttr>())
1444 cgm.errorNYI(
1445 e->getLocation(),
1446 "emitInheritedCXXConstructorCall: pass object size attr argument");
1447 }
1448 }
1449
1450 emitCXXConstructorCall(d, Ctor_Base, forVirtualBase, /*delegating=*/false,
1451 thisAddr, ctorArgs, e->getLocation());
1452}
1453
1455 SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
1456 bool forVirtualBase, bool delegating, CallArgList &args) {
1457 GlobalDecl gd(d, ctorType);
1459 InlinedInheritingConstructorScope scope(*this, gd);
1460 RunCleanupsScope RunCleanups(*this);
1461
1462 // Save the arguments to be passed to the inherited constructor.
1464
1465 FunctionArgList params;
1466 QualType retTy = buildFunctionArgList(gd, params);
1467 // FIXME(cir): When we get to the !isVoidType NYI below, this probably is
1468 // going to be important. In the meantime, this is likely not really doing
1469 // anything.
1470 fnRetTy = retTy;
1471
1472 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, ctorType, forVirtualBase,
1473 delegating, args);
1474
1475 // Emit a simplified prolog. We only need to emit the implicit params.
1476 assert(args.size() >= params.size() && "too few arguments for call");
1477 for (auto [idx, arg, parm] :
1478 llvm::zip_longest(llvm::index_range{0, args.size()}, args, params)) {
1479 if (idx < params.size() && isa<ImplicitParamDecl>(*parm)) {
1480 mlir::Location parmLoc = getLoc((*parm)->getSourceRange());
1481 RValue argVal = arg->getRValue(*this, parmLoc);
1482
1483 LValue allocaVal = makeAddrLValue(
1484 createTempAlloca(convertType((*parm)->getType()),
1485 getContext().getDeclAlign(*parm), parmLoc),
1486 (*parm)->getType());
1487
1488 emitStoreThroughLValue(argVal, allocaVal, /*isInit=*/true);
1489
1490 setAddrOfLocalVar((*parm), allocaVal.getAddress());
1491 }
1492 }
1493
1494 // FIXME(cir): it isn't clear what it takes to get here with a constructor?
1495 // Leave as an NYI until we come across a reproducer.
1496 if (!retTy->isVoidType())
1497 cgm.errorNYI(d->getSourceRange(),
1498 "emitInlinedInheritingCXXConstructorCall: non-void return");
1499
1500 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
1502 emitCtorPrologue(d, ctorType, params);
1503}
1504
1506 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
1507 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
1508
1509 const CXXRecordDecl *crd = d->getParent();
1510
1511 // If this is a call to a trivial default constructor:
1512 // In LLVM: do nothing.
1513 // In CIR: emit as a regular call, other later passes should lower the
1514 // ctor call into trivial initialization.
1516
1517 // Note: memcpy-equivalent special members are handled in the
1518 // emitCXXConstructorCall overload that takes a CXXConstructExpr.
1519
1520 bool passPrototypeArgs = true;
1521
1522 // Check whether we can actually emit the constructor before trying to do so.
1523 if (auto inherited = d->getInheritedConstructor()) {
1524 passPrototypeArgs = getTypes().inheritingCtorHasParams(inherited, type);
1525 if (passPrototypeArgs &&
1526 !canEmitDelegateCallArgs(cgm, cgm.getASTContext(), d, type)) {
1527 emitInlinedInheritingCXXConstructorCall(loc, d, type, forVirtualBase,
1528 delegating, args);
1529 return;
1530 }
1531 }
1532
1533 // Insert any ABI-specific implicit constructor arguments.
1535 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,
1536 delegating, args);
1537
1538 // Emit the call.
1539 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
1540 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
1541 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
1542 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
1543 cir::CIRCallOpInterface c;
1544 emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
1545
1546 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
1547 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
1548 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
1549}
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:229
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:926
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:3784
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)
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.
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...
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:3067
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:2951
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:2944
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:3218
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:2857
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:2780
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:2339
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:2127
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:3822
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:282
Represents a member of a struct/union/class.
Definition Decl.h:3182
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:4179
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4167
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3525
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:3107
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4303
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:4543
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3800
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5369
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5773
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:4905
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:3489
ArrayRef< NamedDecl * > chain() const
Definition Decl.h:3510
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3715
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5618
QualType getPointeeType() const
Definition TypeBase.h:3733
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:1560
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
field_range fields() const
Definition Decl.h:4550
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:3840
bool isUnion() const
Definition Decl.h:3950
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:3569
The base class of the type hierarchy.
Definition TypeBase.h:1875
bool isVoidType() const
Definition TypeBase.h:9048
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9342
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:8809
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 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