1316 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This contains code dealing with C++ code generation of classes10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenCXXABI.h"14#include "CIRGenFunction.h"15#include "CIRGenValue.h"16 17#include "clang/AST/EvaluatedExprVisitor.h"18#include "clang/AST/ExprCXX.h"19#include "clang/AST/RecordLayout.h"20#include "clang/AST/Type.h"21#include "clang/CIR/Dialect/IR/CIRDialect.h"22#include "clang/CIR/MissingFeatures.h"23 24using namespace clang;25using namespace clang::CIRGen;26 27/// Checks whether the given constructor is a valid subject for the28/// complete-to-base constructor delegation optimization, i.e. emitting the29/// complete constructor as a simple call to the base constructor.30bool CIRGenFunction::isConstructorDelegationValid(31 const CXXConstructorDecl *ctor) {32 // Currently we disable the optimization for classes with virtual bases33 // because (1) the address of parameter variables need to be consistent across34 // all initializers but (2) the delegate function call necessarily creates a35 // second copy of the parameter variable.36 //37 // The limiting example (purely theoretical AFAIK):38 // struct A { A(int &c) { c++; } };39 // struct A : virtual A {40 // B(int count) : A(count) { printf("%d\n", count); }41 // };42 // ...although even this example could in principle be emitted as a delegation43 // since the address of the parameter doesn't escape.44 if (ctor->getParent()->getNumVBases())45 return false;46 47 // We also disable the optimization for variadic functions because it's48 // impossible to "re-pass" varargs.49 if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())50 return false;51 52 // FIXME: Decide if we can do a delegation of a delegating constructor.53 if (ctor->isDelegatingConstructor())54 return false;55 56 return true;57}58 59static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf,60 CXXCtorInitializer *memberInit,61 LValue &lhs) {62 FieldDecl *field = memberInit->getAnyMember();63 if (memberInit->isIndirectMemberInitializer()) {64 // If we are initializing an anonymous union field, drill down to the field.65 IndirectFieldDecl *indirectField = memberInit->getIndirectMember();66 for (const auto *nd : indirectField->chain()) {67 auto *fd = cast<clang::FieldDecl>(nd);68 lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());69 }70 } else {71 lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());72 }73}74 75static void emitMemberInitializer(CIRGenFunction &cgf,76 const CXXRecordDecl *classDecl,77 CXXCtorInitializer *memberInit,78 const CXXConstructorDecl *constructor,79 FunctionArgList &args) {80 assert(memberInit->isAnyMemberInitializer() &&81 "Must have member initializer!");82 assert(memberInit->getInit() && "Must have initializer!");83 84 assert(!cir::MissingFeatures::generateDebugInfo());85 86 // non-static data member initializers87 FieldDecl *field = memberInit->getAnyMember();88 QualType fieldType = field->getType();89 90 mlir::Value thisPtr = cgf.loadCXXThis();91 CanQualType recordTy = cgf.getContext().getCanonicalTagType(classDecl);92 93 // If a base constructor is being emitted, create an LValue that has the94 // non-virtual alignment.95 LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)96 ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)97 : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);98 99 emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);100 101 // Special case: If we are in a copy or move constructor, and we are copying102 // an array off PODs or classes with trivial copy constructors, ignore the AST103 // and perform the copy we know is equivalent.104 // FIXME: This is hacky at best... if we had a bit more explicit information105 // in the AST, we could generalize it more easily.106 const ConstantArrayType *array =107 cgf.getContext().getAsConstantArrayType(fieldType);108 if (array && constructor->isDefaulted() &&109 constructor->isCopyOrMoveConstructor()) {110 QualType baseElementTy = cgf.getContext().getBaseElementType(array);111 // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,112 // whereas ClangIR wants to represent all object construction explicitly.113 if (!baseElementTy->isRecordType()) {114 unsigned srcArgIndex =115 cgf.cgm.getCXXABI().getSrcArgforCopyCtor(constructor, args);116 cir::LoadOp srcPtr = cgf.getBuilder().createLoad(117 cgf.getLoc(memberInit->getSourceLocation()),118 cgf.getAddrOfLocalVar(args[srcArgIndex]));119 LValue thisRhslv = cgf.makeNaturalAlignAddrLValue(srcPtr, recordTy);120 LValue src = cgf.emitLValueForFieldInitialization(thisRhslv, field,121 field->getName());122 123 // Copy the aggregate.124 cgf.emitAggregateCopy(lhs, src, fieldType,125 cgf.getOverlapForFieldInit(field),126 lhs.isVolatileQualified());127 // Ensure that we destroy the objects if an exception is thrown later in128 // the constructor.129 QualType::DestructionKind dtorKind = fieldType.isDestructedType();130 assert(!cgf.needsEHCleanup(dtorKind) &&131 "Arrays of non-record types shouldn't need EH cleanup");132 return;133 }134 }135 136 cgf.emitInitializerForField(field, lhs, memberInit->getInit());137}138 139static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) {140 const Type *baseType = baseInit->getBaseClass();141 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();142 return baseClassDecl->isDynamicClass();143}144 145namespace {146/// Call the destructor for a direct base class.147struct CallBaseDtor final : EHScopeStack::Cleanup {148 const CXXRecordDecl *baseClass;149 bool baseIsVirtual;150 CallBaseDtor(const CXXRecordDecl *base, bool baseIsVirtual)151 : baseClass(base), baseIsVirtual(baseIsVirtual) {}152 153 void emit(CIRGenFunction &cgf) override {154 const CXXRecordDecl *derivedClass =155 cast<CXXMethodDecl>(cgf.curFuncDecl)->getParent();156 157 const CXXDestructorDecl *d = baseClass->getDestructor();158 // We are already inside a destructor, so presumably the object being159 // destroyed should have the expected type.160 QualType thisTy = d->getFunctionObjectParameterType();161 assert(cgf.currSrcLoc && "expected source location");162 Address addr = cgf.getAddressOfDirectBaseInCompleteClass(163 *cgf.currSrcLoc, cgf.loadCXXThisAddress(), derivedClass, baseClass,164 baseIsVirtual);165 cgf.emitCXXDestructorCall(d, Dtor_Base, baseIsVirtual,166 /*delegating=*/false, addr, thisTy);167 }168};169 170/// A visitor which checks whether an initializer uses 'this' in a171/// way which requires the vtable to be properly set.172struct DynamicThisUseChecker173 : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {174 using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;175 176 bool usesThis = false;177 178 DynamicThisUseChecker(const ASTContext &c) : super(c) {}179 180 // Black-list all explicit and implicit references to 'this'.181 //182 // Do we need to worry about external references to 'this' derived183 // from arbitrary code? If so, then anything which runs arbitrary184 // external code might potentially access the vtable.185 void VisitCXXThisExpr(const CXXThisExpr *e) { usesThis = true; }186};187} // end anonymous namespace188 189static bool baseInitializerUsesThis(ASTContext &c, const Expr *init) {190 DynamicThisUseChecker checker(c);191 checker.Visit(init);192 return checker.usesThis;193}194 195/// Gets the address of a direct base class within a complete object.196/// This should only be used for (1) non-virtual bases or (2) virtual bases197/// when the type is known to be complete (e.g. in complete destructors).198///199/// The object pointed to by 'thisAddr' is assumed to be non-null.200Address CIRGenFunction::getAddressOfDirectBaseInCompleteClass(201 mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,202 const CXXRecordDecl *base, bool baseIsVirtual) {203 // 'thisAddr' must be a pointer (in some address space) to Derived.204 assert(thisAddr.getElementType() == convertType(derived));205 206 // Compute the offset of the virtual base.207 CharUnits offset;208 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);209 if (baseIsVirtual)210 offset = layout.getVBaseClassOffset(base);211 else212 offset = layout.getBaseClassOffset(base);213 214 return builder.createBaseClassAddr(loc, thisAddr, convertType(base),215 offset.getQuantity(),216 /*assumeNotNull=*/true);217}218 219void CIRGenFunction::emitBaseInitializer(mlir::Location loc,220 const CXXRecordDecl *classDecl,221 CXXCtorInitializer *baseInit) {222 assert(curFuncDecl && "loading 'this' without a func declaration?");223 assert(isa<CXXMethodDecl>(curFuncDecl));224 225 assert(baseInit->isBaseInitializer() && "Must have base initializer!");226 227 Address thisPtr = loadCXXThisAddress();228 229 const Type *baseType = baseInit->getBaseClass();230 const auto *baseClassDecl = baseType->castAsCXXRecordDecl();231 232 bool isBaseVirtual = baseInit->isBaseVirtual();233 234 // If the initializer for the base (other than the constructor235 // itself) accesses 'this' in any way, we need to initialize the236 // vtables.237 if (baseInitializerUsesThis(getContext(), baseInit->getInit()))238 initializeVTablePointers(loc, classDecl);239 240 // We can pretend to be a complete class because it only matters for241 // virtual bases, and we only do virtual bases for complete ctors.242 Address v = getAddressOfDirectBaseInCompleteClass(243 loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);244 assert(!cir::MissingFeatures::aggValueSlotGC());245 AggValueSlot aggSlot = AggValueSlot::forAddr(246 v, Qualifiers(), AggValueSlot::IsDestructed, AggValueSlot::IsNotAliased,247 getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));248 249 emitAggExpr(baseInit->getInit(), aggSlot);250 251 assert(!cir::MissingFeatures::requiresCleanups());252}253 254/// This routine generates necessary code to initialize base classes and255/// non-static data members belonging to this constructor.256void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,257 CXXCtorType ctorType,258 FunctionArgList &args) {259 if (cd->isDelegatingConstructor()) {260 emitDelegatingCXXConstructorCall(cd, args);261 return;262 }263 264 const CXXRecordDecl *classDecl = cd->getParent();265 266 // Virtual base initializers aren't needed if:267 // - This is a base ctor variant268 // - There are no vbases269 // - The class is abstract, so a complete object of it cannot be constructed270 //271 // The check for an abstract class is necessary because sema may not have272 // marked virtual base destructors referenced.273 bool constructVBases = ctorType != Ctor_Base &&274 classDecl->getNumVBases() != 0 &&275 !classDecl->isAbstract();276 if (constructVBases &&277 !cgm.getTarget().getCXXABI().hasConstructorVariants()) {278 cgm.errorNYI(cd->getSourceRange(),279 "emitCtorPrologue: virtual base without variants");280 return;281 }282 283 // Create three separate ranges for the different types of initializers.284 auto allInits = cd->inits();285 286 // Find the boundaries between the three groups.287 auto virtualBaseEnd = std::find_if(288 allInits.begin(), allInits.end(), [](const CXXCtorInitializer *Init) {289 return !(Init->isBaseInitializer() && Init->isBaseVirtual());290 });291 292 auto nonVirtualBaseEnd = std::find_if(virtualBaseEnd, allInits.end(),293 [](const CXXCtorInitializer *Init) {294 return !Init->isBaseInitializer();295 });296 297 // Create the three ranges.298 auto virtualBaseInits = llvm::make_range(allInits.begin(), virtualBaseEnd);299 auto nonVirtualBaseInits =300 llvm::make_range(virtualBaseEnd, nonVirtualBaseEnd);301 auto memberInits = llvm::make_range(nonVirtualBaseEnd, allInits.end());302 303 const mlir::Value oldThisValue = cxxThisValue;304 305 auto emitInitializer = [&](CXXCtorInitializer *baseInit) {306 if (cgm.getCodeGenOpts().StrictVTablePointers &&307 cgm.getCodeGenOpts().OptimizationLevel > 0 &&308 isInitializerOfDynamicClass(baseInit)) {309 // It's OK to continue after emitting the error here. The missing code310 // just "launders" the 'this' pointer.311 cgm.errorNYI(cd->getSourceRange(),312 "emitCtorPrologue: strict vtable pointers for vbase");313 }314 emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, baseInit);315 };316 317 // Process virtual base initializers.318 for (CXXCtorInitializer *virtualBaseInit : virtualBaseInits) {319 if (!constructVBases)320 continue;321 emitInitializer(virtualBaseInit);322 }323 324 assert(!cir::MissingFeatures::msabi());325 326 // Then, non-virtual base initializers.327 for (CXXCtorInitializer *nonVirtualBaseInit : nonVirtualBaseInits) {328 assert(!nonVirtualBaseInit->isBaseVirtual());329 emitInitializer(nonVirtualBaseInit);330 }331 332 cxxThisValue = oldThisValue;333 334 initializeVTablePointers(getLoc(cd->getBeginLoc()), classDecl);335 336 // Finally, initialize class members.337 FieldConstructionScope fcs(*this, loadCXXThisAddress());338 // Classic codegen uses a special class to attempt to replace member339 // initializers with memcpy. We could possibly defer that to the340 // lowering or optimization phases to keep the memory accesses more341 // explicit. For now, we don't insert memcpy at all.342 assert(!cir::MissingFeatures::ctorMemcpyizer());343 for (CXXCtorInitializer *member : memberInits) {344 assert(!member->isBaseInitializer());345 assert(member->isAnyMemberInitializer() &&346 "Delegating initializer on non-delegating constructor");347 emitMemberInitializer(*this, cd->getParent(), member, cd, args);348 }349}350 351static Address applyNonVirtualAndVirtualOffset(352 mlir::Location loc, CIRGenFunction &cgf, Address addr,353 CharUnits nonVirtualOffset, mlir::Value virtualOffset,354 const CXXRecordDecl *derivedClass, const CXXRecordDecl *nearestVBase,355 mlir::Type baseValueTy = {}, bool assumeNotNull = true) {356 // Assert that we have something to do.357 assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);358 359 // Compute the offset from the static and dynamic components.360 mlir::Value baseOffset;361 if (!nonVirtualOffset.isZero()) {362 if (virtualOffset) {363 cgf.cgm.errorNYI(364 loc,365 "applyNonVirtualAndVirtualOffset: virtual and non-virtual offset");366 return Address::invalid();367 } else {368 assert(baseValueTy && "expected base type");369 // If no virtualOffset is present this is the final stop.370 return cgf.getBuilder().createBaseClassAddr(371 loc, addr, baseValueTy, nonVirtualOffset.getQuantity(),372 assumeNotNull);373 }374 } else {375 baseOffset = virtualOffset;376 }377 378 // Apply the base offset. cir.ptr_stride adjusts by a number of elements,379 // not bytes. So the pointer must be cast to a byte pointer and back.380 381 mlir::Value ptr = addr.getPointer();382 mlir::Type charPtrType = cgf.cgm.uInt8PtrTy;383 mlir::Value charPtr = cgf.getBuilder().createBitcast(ptr, charPtrType);384 mlir::Value adjusted = cir::PtrStrideOp::create(385 cgf.getBuilder(), loc, charPtrType, charPtr, baseOffset);386 ptr = cgf.getBuilder().createBitcast(adjusted, ptr.getType());387 388 // If we have a virtual component, the alignment of the result will389 // be relative only to the known alignment of that vbase.390 CharUnits alignment;391 if (virtualOffset) {392 assert(nearestVBase && "virtual offset without vbase?");393 alignment = cgf.cgm.getVBaseAlignment(addr.getAlignment(), derivedClass,394 nearestVBase);395 } else {396 alignment = addr.getAlignment();397 }398 alignment = alignment.alignmentAtOffset(nonVirtualOffset);399 400 return Address(ptr, alignment);401}402 403void CIRGenFunction::initializeVTablePointer(mlir::Location loc,404 const VPtr &vptr) {405 // Compute the address point.406 mlir::Value vtableAddressPoint =407 cgm.getCXXABI().getVTableAddressPointInStructor(408 *this, vptr.vtableClass, vptr.base, vptr.nearestVBase);409 410 if (!vtableAddressPoint)411 return;412 413 // Compute where to store the address point.414 mlir::Value virtualOffset{};415 CharUnits nonVirtualOffset = CharUnits::Zero();416 417 mlir::Type baseValueTy;418 if (cgm.getCXXABI().isVirtualOffsetNeededForVTableField(*this, vptr)) {419 // We need to use the virtual base offset offset because the virtual base420 // might have a different offset in the most derived class.421 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(422 loc, *this, loadCXXThisAddress(), vptr.vtableClass, vptr.nearestVBase);423 nonVirtualOffset = vptr.offsetFromNearestVBase;424 } else {425 // We can just use the base offset in the complete class.426 nonVirtualOffset = vptr.base.getBaseOffset();427 baseValueTy =428 convertType(getContext().getCanonicalTagType(vptr.base.getBase()));429 }430 431 // Apply the offsets.432 Address classAddr = loadCXXThisAddress();433 if (!nonVirtualOffset.isZero() || virtualOffset) {434 classAddr = applyNonVirtualAndVirtualOffset(435 loc, *this, classAddr, nonVirtualOffset, virtualOffset,436 vptr.vtableClass, vptr.nearestVBase, baseValueTy);437 }438 439 // Finally, store the address point. Use the same CIR types as the field.440 //441 // vtable field is derived from `this` pointer, therefore they should be in442 // the same addr space.443 assert(!cir::MissingFeatures::addressSpace());444 auto vtablePtr = cir::VTableGetVPtrOp::create(445 builder, loc, builder.getPtrToVPtrType(), classAddr.getPointer());446 Address vtableField = Address(vtablePtr, classAddr.getAlignment());447 builder.createStore(loc, vtableAddressPoint, vtableField);448 assert(!cir::MissingFeatures::opTBAA());449 assert(!cir::MissingFeatures::createInvariantGroup());450}451 452void CIRGenFunction::initializeVTablePointers(mlir::Location loc,453 const CXXRecordDecl *rd) {454 // Ignore classes without a vtable.455 if (!rd->isDynamicClass())456 return;457 458 // Initialize the vtable pointers for this class and all of its bases.459 if (cgm.getCXXABI().doStructorsInitializeVPtrs(rd))460 for (const auto &vptr : getVTablePointers(rd))461 initializeVTablePointer(loc, vptr);462 463 if (rd->getNumVBases())464 cgm.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, rd);465}466 467CIRGenFunction::VPtrsVector468CIRGenFunction::getVTablePointers(const CXXRecordDecl *vtableClass) {469 CIRGenFunction::VPtrsVector vptrsResult;470 VisitedVirtualBasesSetTy vbases;471 getVTablePointers(BaseSubobject(vtableClass, CharUnits::Zero()),472 /*NearestVBase=*/nullptr,473 /*OffsetFromNearestVBase=*/CharUnits::Zero(),474 /*BaseIsNonVirtualPrimaryBase=*/false, vtableClass, vbases,475 vptrsResult);476 return vptrsResult;477}478 479void CIRGenFunction::getVTablePointers(BaseSubobject base,480 const CXXRecordDecl *nearestVBase,481 CharUnits offsetFromNearestVBase,482 bool baseIsNonVirtualPrimaryBase,483 const CXXRecordDecl *vtableClass,484 VisitedVirtualBasesSetTy &vbases,485 VPtrsVector &vptrs) {486 // If this base is a non-virtual primary base the address point has already487 // been set.488 if (!baseIsNonVirtualPrimaryBase) {489 // Initialize the vtable pointer for this base.490 VPtr vptr = {base, nearestVBase, offsetFromNearestVBase, vtableClass};491 vptrs.push_back(vptr);492 }493 494 const CXXRecordDecl *rd = base.getBase();495 496 for (const auto &nextBase : rd->bases()) {497 const auto *baseDecl =498 cast<CXXRecordDecl>(nextBase.getType()->castAs<RecordType>()->getDecl())499 ->getDefinitionOrSelf();500 501 // Ignore classes without a vtable.502 if (!baseDecl->isDynamicClass())503 continue;504 505 CharUnits baseOffset;506 CharUnits baseOffsetFromNearestVBase;507 bool baseDeclIsNonVirtualPrimaryBase;508 const CXXRecordDecl *nextBaseDecl;509 510 if (nextBase.isVirtual()) {511 // Check if we've visited this virtual base before.512 if (!vbases.insert(baseDecl).second)513 continue;514 515 const ASTRecordLayout &layout =516 getContext().getASTRecordLayout(vtableClass);517 518 nextBaseDecl = baseDecl;519 baseOffset = layout.getVBaseClassOffset(baseDecl);520 baseOffsetFromNearestVBase = CharUnits::Zero();521 baseDeclIsNonVirtualPrimaryBase = false;522 } else {523 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);524 525 nextBaseDecl = nearestVBase;526 baseOffset = base.getBaseOffset() + layout.getBaseClassOffset(baseDecl);527 baseOffsetFromNearestVBase =528 offsetFromNearestVBase + layout.getBaseClassOffset(baseDecl);529 baseDeclIsNonVirtualPrimaryBase = layout.getPrimaryBase() == baseDecl;530 }531 532 getVTablePointers(BaseSubobject(baseDecl, baseOffset), nextBaseDecl,533 baseOffsetFromNearestVBase,534 baseDeclIsNonVirtualPrimaryBase, vtableClass, vbases,535 vptrs);536 }537}538 539Address CIRGenFunction::loadCXXThisAddress() {540 assert(curFuncDecl && "loading 'this' without a func declaration?");541 assert(isa<CXXMethodDecl>(curFuncDecl));542 543 // Lazily compute CXXThisAlignment.544 if (cxxThisAlignment.isZero()) {545 // Just use the best known alignment for the parent.546 // TODO: if we're currently emitting a complete-object ctor/dtor, we can547 // always use the complete-object alignment.548 auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();549 cxxThisAlignment = cgm.getClassPointerAlignment(rd);550 }551 552 return Address(loadCXXThis(), cxxThisAlignment);553}554 555void CIRGenFunction::emitInitializerForField(FieldDecl *field, LValue lhs,556 Expr *init) {557 QualType fieldType = field->getType();558 switch (getEvaluationKind(fieldType)) {559 case cir::TEK_Scalar:560 if (lhs.isSimple()) {561 emitExprAsInit(init, field, lhs, false);562 } else {563 RValue rhs = RValue::get(emitScalarExpr(init));564 emitStoreThroughLValue(rhs, lhs);565 }566 break;567 case cir::TEK_Complex:568 emitComplexExprIntoLValue(init, lhs, /*isInit=*/true);569 break;570 case cir::TEK_Aggregate: {571 assert(!cir::MissingFeatures::aggValueSlotGC());572 assert(!cir::MissingFeatures::sanitizers());573 AggValueSlot slot = AggValueSlot::forLValue(574 lhs, AggValueSlot::IsDestructed, AggValueSlot::IsNotAliased,575 getOverlapForFieldInit(field), AggValueSlot::IsNotZeroed);576 emitAggExpr(init, slot);577 break;578 }579 }580 581 // Ensure that we destroy this object if an exception is thrown later in the582 // constructor.583 QualType::DestructionKind dtorKind = fieldType.isDestructedType();584 (void)dtorKind;585 assert(!cir::MissingFeatures::requiresCleanups());586}587 588CharUnits589CIRGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign,590 const CXXRecordDecl *baseDecl,591 CharUnits expectedTargetAlign) {592 // If the base is an incomplete type (which is, alas, possible with593 // member pointers), be pessimistic.594 if (!baseDecl->isCompleteDefinition())595 return std::min(actualBaseAlign, expectedTargetAlign);596 597 const ASTRecordLayout &baseLayout =598 getASTContext().getASTRecordLayout(baseDecl);599 CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();600 601 // If the class is properly aligned, assume the target offset is, too.602 //603 // This actually isn't necessarily the right thing to do --- if the604 // class is a complete object, but it's only properly aligned for a605 // base subobject, then the alignments of things relative to it are606 // probably off as well. (Note that this requires the alignment of607 // the target to be greater than the NV alignment of the derived608 // class.)609 //610 // However, our approach to this kind of under-alignment can only611 // ever be best effort; after all, we're never going to propagate612 // alignments through variables or parameters. Note, in particular,613 // that constructing a polymorphic type in an address that's less614 // than pointer-aligned will generally trap in the constructor,615 // unless we someday add some sort of attribute to change the616 // assumed alignment of 'this'. So our goal here is pretty much617 // just to allow the user to explicitly say that a pointer is618 // under-aligned and then safely access its fields and vtables.619 if (actualBaseAlign >= expectedBaseAlign)620 return expectedTargetAlign;621 622 // Otherwise, we might be offset by an arbitrary multiple of the623 // actual alignment. The correct adjustment is to take the min of624 // the two alignments.625 return std::min(actualBaseAlign, expectedTargetAlign);626}627 628/// Return the best known alignment for a pointer to a virtual base,629/// given the alignment of a pointer to the derived class.630clang::CharUnits631CIRGenModule::getVBaseAlignment(CharUnits actualDerivedAlign,632 const CXXRecordDecl *derivedClass,633 const CXXRecordDecl *vbaseClass) {634 // The basic idea here is that an underaligned derived pointer might635 // indicate an underaligned base pointer.636 637 assert(vbaseClass->isCompleteDefinition());638 const ASTRecordLayout &baseLayout =639 getASTContext().getASTRecordLayout(vbaseClass);640 CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();641 642 return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,643 expectedVBaseAlign);644}645 646/// Emit a loop to call a particular constructor for each of several members647/// of an array.648///649/// \param ctor the constructor to call for each element650/// \param arrayType the type of the array to initialize651/// \param arrayBegin an arrayType*652/// \param zeroInitialize true if each element should be653/// zero-initialized before it is constructed654void CIRGenFunction::emitCXXAggrConstructorCall(655 const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType,656 Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,657 bool zeroInitialize) {658 QualType elementType;659 mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);660 emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,661 newPointerIsChecked, zeroInitialize);662}663 664/// Emit a loop to call a particular constructor for each of several members665/// of an array.666///667/// \param ctor the constructor to call for each element668/// \param numElements the number of elements in the array;669/// may be zero670/// \param arrayBase a T*, where T is the type constructed by ctor671/// \param zeroInitialize true if each element should be672/// zero-initialized before it is constructed673void CIRGenFunction::emitCXXAggrConstructorCall(674 const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,675 const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize) {676 // It's legal for numElements to be zero. This can happen both677 // dynamically, because x can be zero in 'new A[x]', and statically,678 // because of GCC extensions that permit zero-length arrays. There679 // are probably legitimate places where we could assume that this680 // doesn't happen, but it's not clear that it's worth it.681 682 auto arrayTy = mlir::cast<cir::ArrayType>(arrayBase.getElementType());683 mlir::Type elementType = arrayTy.getElementType();684 685 // This might be a multi-dimensional array. Find the innermost element type.686 while (auto maybeArrayTy = mlir::dyn_cast<cir::ArrayType>(elementType))687 elementType = maybeArrayTy.getElementType();688 cir::PointerType ptrToElmType = builder.getPointerTo(elementType);689 690 // Optimize for a constant count.691 if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {692 if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>()) {693 // Just skip out if the constant count is zero.694 if (constIntAttr.getUInt() == 0)695 return;696 697 arrayTy = cir::ArrayType::get(elementType, constIntAttr.getUInt());698 // Otherwise, emit the check.699 }700 701 if (constantCount.use_empty())702 constantCount.erase();703 } else {704 // Otherwise, emit the check.705 cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");706 }707 708 // Tradional LLVM codegen emits a loop here. CIR lowers to a loop as part of709 // LoweringPrepare.710 711 // The alignment of the base, adjusted by the size of a single element,712 // provides a conservative estimate of the alignment of every element.713 // (This assumes we never start tracking offsetted alignments.)714 //715 // Note that these are complete objects and so we don't need to716 // use the non-virtual size or alignment.717 CanQualType type = getContext().getCanonicalTagType(ctor->getParent());718 CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(719 getContext().getTypeSizeInChars(type));720 721 // Zero initialize the storage, if requested.722 if (zeroInitialize)723 emitNullInitialization(*currSrcLoc, arrayBase, type);724 725 // C++ [class.temporary]p4:726 // There are two contexts in which temporaries are destroyed at a different727 // point than the end of the full-expression. The first context is when a728 // default constructor is called to initialize an element of an array.729 // If the constructor has one or more default arguments, the destruction of730 // every temporary created in a default argument expression is sequenced731 // before the construction of the next array element, if any.732 {733 RunCleanupsScope scope(*this);734 735 // Evaluate the constructor and its arguments in a regular736 // partial-destroy cleanup.737 if (getLangOpts().Exceptions &&738 !ctor->getParent()->hasTrivialDestructor()) {739 cgm.errorNYI(e->getSourceRange(), "partial array cleanups");740 }741 742 // Emit the constructor call that will execute for every array element.743 mlir::Value arrayOp =744 builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);745 cir::ArrayCtor::create(746 builder, *currSrcLoc, arrayOp,747 [&](mlir::OpBuilder &b, mlir::Location loc) {748 mlir::BlockArgument arg =749 b.getInsertionBlock()->addArgument(ptrToElmType, loc);750 Address curAddr = Address(arg, elementType, eltAlignment);751 assert(!cir::MissingFeatures::sanitizers());752 auto currAVS = AggValueSlot::forAddr(753 curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,754 AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap,755 AggValueSlot::IsNotZeroed);756 emitCXXConstructorCall(ctor, Ctor_Complete,757 /*ForVirtualBase=*/false,758 /*Delegating=*/false, currAVS, e);759 cir::YieldOp::create(builder, loc);760 });761 }762}763 764void CIRGenFunction::emitDelegateCXXConstructorCall(765 const CXXConstructorDecl *ctor, CXXCtorType ctorType,766 const FunctionArgList &args, SourceLocation loc) {767 CallArgList delegateArgs;768 769 FunctionArgList::const_iterator i = args.begin(), e = args.end();770 assert(i != e && "no parameters to constructor");771 772 // this773 Address thisAddr = loadCXXThisAddress();774 delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());775 ++i;776 777 // FIXME: The location of the VTT parameter in the parameter list is specific778 // to the Itanium ABI and shouldn't be hardcoded here.779 if (cgm.getCXXABI().needsVTTParameter(curGD)) {780 cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");781 return;782 }783 784 // Explicit arguments.785 for (; i != e; ++i) {786 const VarDecl *param = *i;787 // FIXME: per-argument source location788 emitDelegateCallArg(delegateArgs, param, loc);789 }790 791 assert(!cir::MissingFeatures::sanitizers());792 793 emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,794 /*Delegating=*/true, thisAddr, delegateArgs, loc);795}796 797void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {798 const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());799 assert(assignOp->isCopyAssignmentOperator() ||800 assignOp->isMoveAssignmentOperator());801 const Stmt *rootS = assignOp->getBody();802 assert(isa<CompoundStmt>(rootS) &&803 "Body of an implicit assignment operator should be compound stmt.");804 const auto *rootCS = cast<CompoundStmt>(rootS);805 806 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), assignOp);807 808 assert(!cir::MissingFeatures::incrementProfileCounter());809 assert(!cir::MissingFeatures::runCleanupsScope());810 811 // Classic codegen uses a special class to attempt to replace member812 // initializers with memcpy. We could possibly defer that to the813 // lowering or optimization phases to keep the memory accesses more814 // explicit. For now, we don't insert memcpy at all, though in some815 // cases the AST contains a call to memcpy.816 assert(!cir::MissingFeatures::assignMemcpyizer());817 for (Stmt *s : rootCS->body())818 if (emitStmt(s, /*useCurrentScope=*/true).failed())819 cgm.errorNYI(s->getSourceRange(),820 std::string("emitImplicitAssignmentOperatorBody: ") +821 s->getStmtClassName());822}823 824void CIRGenFunction::emitForwardingCallToLambda(825 const CXXMethodDecl *callOperator, CallArgList &callArgs) {826 // Get the address of the call operator.827 const CIRGenFunctionInfo &calleeFnInfo =828 cgm.getTypes().arrangeCXXMethodDeclaration(callOperator);829 cir::FuncOp calleePtr = cgm.getAddrOfFunction(830 GlobalDecl(callOperator), cgm.getTypes().getFunctionType(calleeFnInfo));831 832 // Prepare the return slot.833 const FunctionProtoType *fpt =834 callOperator->getType()->castAs<FunctionProtoType>();835 QualType resultType = fpt->getReturnType();836 ReturnValueSlot returnSlot;837 838 // We don't need to separately arrange the call arguments because839 // the call can't be variadic anyway --- it's impossible to forward840 // variadic arguments.841 842 // Now emit our call.843 CIRGenCallee callee =844 CIRGenCallee::forDirect(calleePtr, GlobalDecl(callOperator));845 RValue rv = emitCall(calleeFnInfo, callee, returnSlot, callArgs);846 847 // If necessary, copy the returned value into the slot.848 if (!resultType->isVoidType() && returnSlot.isNull()) {849 if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType())850 cgm.errorNYI(callOperator->getSourceRange(),851 "emitForwardingCallToLambda: ObjCAutoRefCount");852 emitReturnOfRValue(*currSrcLoc, rv, resultType);853 } else {854 cgm.errorNYI(callOperator->getSourceRange(),855 "emitForwardingCallToLambda: return slot is not null");856 }857}858 859void CIRGenFunction::emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md) {860 const CXXRecordDecl *lambda = md->getParent();861 862 // Start building arguments for forwarding call863 CallArgList callArgs;864 865 QualType lambdaType = getContext().getCanonicalTagType(lambda);866 QualType thisType = getContext().getPointerType(lambdaType);867 Address thisPtr =868 createMemTemp(lambdaType, getLoc(md->getSourceRange()), "unused.capture");869 callArgs.add(RValue::get(thisPtr.getPointer()), thisType);870 871 // Add the rest of the parameters.872 for (auto *param : md->parameters())873 emitDelegateCallArg(callArgs, param, param->getBeginLoc());874 875 const CXXMethodDecl *callOp = lambda->getLambdaCallOperator();876 // For a generic lambda, find the corresponding call operator specialization877 // to which the call to the static-invoker shall be forwarded.878 if (lambda->isGenericLambda()) {879 assert(md->isFunctionTemplateSpecialization());880 const TemplateArgumentList *tal = md->getTemplateSpecializationArgs();881 FunctionTemplateDecl *callOpTemplate =882 callOp->getDescribedFunctionTemplate();883 void *InsertPos = nullptr;884 FunctionDecl *correspondingCallOpSpecialization =885 callOpTemplate->findSpecialization(tal->asArray(), InsertPos);886 assert(correspondingCallOpSpecialization);887 callOp = cast<CXXMethodDecl>(correspondingCallOpSpecialization);888 }889 emitForwardingCallToLambda(callOp, callArgs);890}891 892void CIRGenFunction::emitLambdaStaticInvokeBody(const CXXMethodDecl *md) {893 if (md->isVariadic()) {894 // Codgen for LLVM doesn't emit code for this as well, it says:895 // FIXME: Making this work correctly is nasty because it requires either896 // cloning the body of the call operator or making the call operator897 // forward.898 cgm.errorNYI(md->getSourceRange(), "emitLambdaStaticInvokeBody: variadic");899 }900 901 emitLambdaDelegatingInvokeBody(md);902}903 904void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,905 QualType type) {906 const auto *record = type->castAsCXXRecordDecl();907 const CXXDestructorDecl *dtor = record->getDestructor();908 // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial909 // dtors which shall be removed on later CIR passes. However, only remove this910 // assertion after we have a test case to exercise this path.911 assert(!dtor->isTrivial());912 cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,913 /*delegating=*/false, addr, type);914}915 916namespace {917mlir::Value loadThisForDtorDelete(CIRGenFunction &cgf,918 const CXXDestructorDecl *dd) {919 if (Expr *thisArg = dd->getOperatorDeleteThisArg())920 return cgf.emitScalarExpr(thisArg);921 return cgf.loadCXXThis();922}923 924/// Call the operator delete associated with the current destructor.925struct CallDtorDelete final : EHScopeStack::Cleanup {926 CallDtorDelete() {}927 928 void emit(CIRGenFunction &cgf) override {929 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(cgf.curFuncDecl);930 const CXXRecordDecl *classDecl = dtor->getParent();931 cgf.emitDeleteCall(dtor->getOperatorDelete(),932 loadThisForDtorDelete(cgf, dtor),933 cgf.getContext().getCanonicalTagType(classDecl));934 }935};936 937class DestroyField final : public EHScopeStack::Cleanup {938 const FieldDecl *field;939 CIRGenFunction::Destroyer *destroyer;940 941public:942 DestroyField(const FieldDecl *field, CIRGenFunction::Destroyer *destroyer)943 : field(field), destroyer(destroyer) {}944 945 void emit(CIRGenFunction &cgf) override {946 // Find the address of the field.947 Address thisValue = cgf.loadCXXThisAddress();948 CanQualType recordTy =949 cgf.getContext().getCanonicalTagType(field->getParent());950 LValue thisLV = cgf.makeAddrLValue(thisValue, recordTy);951 LValue lv = cgf.emitLValueForField(thisLV, field);952 assert(lv.isSimple());953 954 assert(!cir::MissingFeatures::ehCleanupFlags());955 cgf.emitDestroy(lv.getAddress(), field->getType(), destroyer);956 }957};958} // namespace959 960/// Emit all code that comes at the end of class's destructor. This is to call961/// destructors on members and base classes in reverse order of their962/// construction.963///964/// For a deleting destructor, this also handles the case where a destroying965/// operator delete completely overrides the definition.966void CIRGenFunction::enterDtorCleanups(const CXXDestructorDecl *dd,967 CXXDtorType dtorType) {968 assert((!dd->isTrivial() || dd->hasAttr<DLLExportAttr>()) &&969 "Should not emit dtor epilogue for non-exported trivial dtor!");970 971 // The deleting-destructor phase just needs to call the appropriate972 // operator delete that Sema picked up.973 if (dtorType == Dtor_Deleting) {974 assert(dd->getOperatorDelete() &&975 "operator delete missing - EnterDtorCleanups");976 if (cxxStructorImplicitParamValue) {977 cgm.errorNYI(dd->getSourceRange(), "deleting destructor with vtt");978 } else {979 if (dd->getOperatorDelete()->isDestroyingOperatorDelete()) {980 cgm.errorNYI(dd->getSourceRange(),981 "deleting destructor with destroying operator delete");982 } else {983 ehStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);984 }985 }986 return;987 }988 989 const CXXRecordDecl *classDecl = dd->getParent();990 991 // Unions have no bases and do not call field destructors.992 if (classDecl->isUnion())993 return;994 995 // The complete-destructor phase just destructs all the virtual bases.996 if (dtorType == Dtor_Complete) {997 assert(!cir::MissingFeatures::sanitizers());998 999 // We push them in the forward order so that they'll be popped in1000 // the reverse order.1001 for (const CXXBaseSpecifier &base : classDecl->vbases()) {1002 auto *baseClassDecl = base.getType()->castAsCXXRecordDecl();1003 1004 if (baseClassDecl->hasTrivialDestructor()) {1005 // Under SanitizeMemoryUseAfterDtor, poison the trivial base class1006 // memory. For non-trival base classes the same is done in the class1007 // destructor.1008 assert(!cir::MissingFeatures::sanitizers());1009 } else {1010 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,1011 /*baseIsVirtual=*/true);1012 }1013 }1014 1015 return;1016 }1017 1018 assert(dtorType == Dtor_Base);1019 assert(!cir::MissingFeatures::sanitizers());1020 1021 // Destroy non-virtual bases.1022 for (const CXXBaseSpecifier &base : classDecl->bases()) {1023 // Ignore virtual bases.1024 if (base.isVirtual())1025 continue;1026 1027 CXXRecordDecl *baseClassDecl = base.getType()->getAsCXXRecordDecl();1028 1029 if (baseClassDecl->hasTrivialDestructor())1030 assert(!cir::MissingFeatures::sanitizers());1031 else1032 ehStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, baseClassDecl,1033 /*baseIsVirtual=*/false);1034 }1035 1036 assert(!cir::MissingFeatures::sanitizers());1037 1038 // Destroy direct fields.1039 for (const FieldDecl *field : classDecl->fields()) {1040 QualType type = field->getType();1041 QualType::DestructionKind dtorKind = type.isDestructedType();1042 if (!dtorKind)1043 continue;1044 1045 // Anonymous union members do not have their destructors called.1046 const RecordType *rt = type->getAsUnionType();1047 if (rt && rt->getDecl()->isAnonymousStructOrUnion())1048 continue;1049 1050 CleanupKind cleanupKind = getCleanupKind(dtorKind);1051 assert(!cir::MissingFeatures::ehCleanupFlags());1052 ehStack.pushCleanup<DestroyField>(cleanupKind, field,1053 getDestroyer(dtorKind));1054 }1055}1056 1057void CIRGenFunction::emitDelegatingCXXConstructorCall(1058 const CXXConstructorDecl *ctor, const FunctionArgList &args) {1059 assert(ctor->isDelegatingConstructor());1060 1061 Address thisPtr = loadCXXThisAddress();1062 1063 assert(!cir::MissingFeatures::objCGC());1064 assert(!cir::MissingFeatures::sanitizers());1065 AggValueSlot aggSlot = AggValueSlot::forAddr(1066 thisPtr, Qualifiers(), AggValueSlot::IsDestructed,1067 AggValueSlot::IsNotAliased, AggValueSlot::MayOverlap,1068 AggValueSlot::IsNotZeroed);1069 1070 emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);1071 1072 const CXXRecordDecl *classDecl = ctor->getParent();1073 if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {1074 cgm.errorNYI(ctor->getSourceRange(),1075 "emitDelegatingCXXConstructorCall: exception");1076 return;1077 }1078}1079 1080void CIRGenFunction::emitCXXDestructorCall(const CXXDestructorDecl *dd,1081 CXXDtorType type,1082 bool forVirtualBase, bool delegating,1083 Address thisAddr, QualType thisTy) {1084 cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,1085 delegating, thisAddr, thisTy);1086}1087 1088mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,1089 bool delegating) {1090 if (!cgm.getCXXABI().needsVTTParameter(gd))1091 return nullptr;1092 1093 const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();1094 const CXXRecordDecl *base = cast<CXXMethodDecl>(gd.getDecl())->getParent();1095 1096 uint64_t subVTTIndex;1097 1098 if (delegating) {1099 // If this is a delegating constructor call, just load the VTT.1100 return loadCXXVTT();1101 } else if (rd == base) {1102 // If the record matches the base, this is the complete ctor/dtor1103 // variant calling the base variant in a class with virtual bases.1104 assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&1105 "doing no-op VTT offset in base dtor/ctor?");1106 assert(!forVirtualBase && "Can't have same class as virtual base!");1107 subVTTIndex = 0;1108 } else {1109 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);1110 CharUnits baseOffset = forVirtualBase ? layout.getVBaseClassOffset(base)1111 : layout.getBaseClassOffset(base);1112 1113 subVTTIndex =1114 cgm.getVTables().getSubVTTIndex(rd, BaseSubobject(base, baseOffset));1115 assert(subVTTIndex != 0 && "Sub-VTT index must be greater than zero!");1116 }1117 1118 mlir::Location loc = cgm.getLoc(rd->getBeginLoc());1119 if (cgm.getCXXABI().needsVTTParameter(curGD)) {1120 // A VTT parameter was passed to the constructor, use it.1121 mlir::Value vtt = loadCXXVTT();1122 return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);1123 } else {1124 // We're the complete constructor, so get the VTT by name.1125 cir::GlobalOp vtt = cgm.getVTables().getAddrOfVTT(rd);1126 return builder.createVTTAddrPoint(1127 loc, builder.getPointerTo(cgm.voidPtrTy),1128 mlir::FlatSymbolRefAttr::get(vtt.getSymNameAttr()), subVTTIndex);1129 }1130}1131 1132Address CIRGenFunction::getAddressOfDerivedClass(1133 mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived,1134 llvm::iterator_range<CastExpr::path_const_iterator> path,1135 bool nullCheckValue) {1136 assert(!path.empty() && "Base path should not be empty!");1137 1138 QualType derivedTy = getContext().getCanonicalTagType(derived);1139 mlir::Type derivedValueTy = convertType(derivedTy);1140 CharUnits nonVirtualOffset =1141 cgm.computeNonVirtualBaseClassOffset(derived, path);1142 1143 // Note that in OG, no offset (nonVirtualOffset.getQuantity() == 0) means it1144 // just gives the address back. In CIR a `cir.derived_class` is created and1145 // made into a nop later on during lowering.1146 return builder.createDerivedClassAddr(loc, baseAddr, derivedValueTy,1147 nonVirtualOffset.getQuantity(),1148 /*assumeNotNull=*/!nullCheckValue);1149}1150 1151Address CIRGenFunction::getAddressOfBaseClass(1152 Address value, const CXXRecordDecl *derived,1153 llvm::iterator_range<CastExpr::path_const_iterator> path,1154 bool nullCheckValue, SourceLocation loc) {1155 assert(!path.empty() && "Base path should not be empty!");1156 1157 CastExpr::path_const_iterator start = path.begin();1158 const CXXRecordDecl *vBase = nullptr;1159 1160 if ((*path.begin())->isVirtual()) {1161 vBase = (*start)->getType()->castAsCXXRecordDecl();1162 ++start;1163 }1164 1165 // Compute the static offset of the ultimate destination within its1166 // allocating subobject (the virtual base, if there is one, or else1167 // the "complete" object that we see).1168 CharUnits nonVirtualOffset = cgm.computeNonVirtualBaseClassOffset(1169 vBase ? vBase : derived, {start, path.end()});1170 1171 // If there's a virtual step, we can sometimes "devirtualize" it.1172 // For now, that's limited to when the derived type is final.1173 // TODO: "devirtualize" this for accesses to known-complete objects.1174 if (vBase && derived->hasAttr<FinalAttr>()) {1175 const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);1176 CharUnits vBaseOffset = layout.getVBaseClassOffset(vBase);1177 nonVirtualOffset += vBaseOffset;1178 vBase = nullptr; // we no longer have a virtual step1179 }1180 1181 // Get the base pointer type.1182 mlir::Type baseValueTy = convertType((path.end()[-1])->getType());1183 assert(!cir::MissingFeatures::addressSpace());1184 1185 // If there is no virtual base, use cir.base_class_addr. It takes care of1186 // the adjustment and the null pointer check.1187 if (nonVirtualOffset.isZero() && !vBase) {1188 assert(!cir::MissingFeatures::sanitizers());1189 return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,1190 /*assumeNotNull=*/true);1191 }1192 1193 assert(!cir::MissingFeatures::sanitizers());1194 1195 // Compute the virtual offset.1196 mlir::Value virtualOffset = nullptr;1197 if (vBase) {1198 virtualOffset = cgm.getCXXABI().getVirtualBaseClassOffset(1199 getLoc(loc), *this, value, derived, vBase);1200 }1201 1202 // Apply both offsets.1203 value = applyNonVirtualAndVirtualOffset(1204 getLoc(loc), *this, value, nonVirtualOffset, virtualOffset, derived,1205 vBase, baseValueTy, not nullCheckValue);1206 1207 // Cast to the destination type.1208 value = value.withElementType(builder, baseValueTy);1209 1210 return value;1211}1212 1213// TODO(cir): this can be shared with LLVM codegen.1214bool CIRGenFunction::shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd) {1215 assert(!cir::MissingFeatures::hiddenVisibility());1216 if (!cgm.getCodeGenOpts().WholeProgramVTables)1217 return false;1218 1219 if (cgm.getCodeGenOpts().VirtualFunctionElimination)1220 return true;1221 1222 assert(!cir::MissingFeatures::sanitizers());1223 1224 return false;1225}1226 1227mlir::Value CIRGenFunction::getVTablePtr(mlir::Location loc, Address thisAddr,1228 const CXXRecordDecl *rd) {1229 auto vtablePtr = cir::VTableGetVPtrOp::create(1230 builder, loc, builder.getPtrToVPtrType(), thisAddr.getPointer());1231 Address vtablePtrAddr = Address(vtablePtr, thisAddr.getAlignment());1232 1233 auto vtable = builder.createLoad(loc, vtablePtrAddr);1234 assert(!cir::MissingFeatures::opTBAA());1235 1236 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&1237 cgm.getCodeGenOpts().StrictVTablePointers) {1238 assert(!cir::MissingFeatures::createInvariantGroup());1239 }1240 1241 return vtable;1242}1243 1244void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,1245 clang::CXXCtorType type,1246 bool forVirtualBase,1247 bool delegating,1248 AggValueSlot thisAVS,1249 const clang::CXXConstructExpr *e) {1250 CallArgList args;1251 Address thisAddr = thisAVS.getAddress();1252 QualType thisType = d->getThisType();1253 mlir::Value thisPtr = thisAddr.getPointer();1254 1255 assert(!cir::MissingFeatures::addressSpace());1256 1257 args.add(RValue::get(thisPtr), thisType);1258 1259 // In LLVM Codegen: If this is a trivial constructor, just emit what's needed.1260 // If this is a union copy constructor, we must emit a memcpy, because the AST1261 // does not model that copy.1262 assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());1263 1264 const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();1265 1266 assert(!cir::MissingFeatures::opCallArgEvaluationOrder());1267 1268 emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),1269 /*ParamsToSkip=*/0);1270 1271 assert(!cir::MissingFeatures::sanitizers());1272 emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,1273 e->getExprLoc());1274}1275 1276void CIRGenFunction::emitCXXConstructorCall(1277 const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,1278 bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {1279 1280 const CXXRecordDecl *crd = d->getParent();1281 1282 // If this is a call to a trivial default constructor:1283 // In LLVM: do nothing.1284 // In CIR: emit as a regular call, other later passes should lower the1285 // ctor call into trivial initialization.1286 assert(!cir::MissingFeatures::isTrivialCtorOrDtor());1287 1288 assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());1289 1290 bool passPrototypeArgs = true;1291 1292 // Check whether we can actually emit the constructor before trying to do so.1293 if (d->getInheritedConstructor()) {1294 cgm.errorNYI(d->getSourceRange(),1295 "emitCXXConstructorCall: inherited constructor");1296 return;1297 }1298 1299 // Insert any ABI-specific implicit constructor arguments.1300 CIRGenCXXABI::AddedStructorArgCounts extraArgs =1301 cgm.getCXXABI().addImplicitConstructorArgs(*this, d, type, forVirtualBase,1302 delegating, args);1303 1304 // Emit the call.1305 auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));1306 const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(1307 args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);1308 CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));1309 cir::CIRCallOpInterface c;1310 emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));1311 1312 if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&1313 type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)1314 cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");1315}1316