Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenClass.cpp
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This contains code dealing with C++ code generation of classes9//10//===----------------------------------------------------------------------===//1112#include "CIRGenCXXABI.h"13#include "CIRGenFunction.h"1415#include "clang/AST/ExprCXX.h"16#include "clang/AST/RecordLayout.h"17#include "clang/AST/Type.h"18#include "clang/CIR/MissingFeatures.h"1920using namespace clang;21using namespace clang::CIRGen;2223/// Checks whether the given constructor is a valid subject for the24/// complete-to-base constructor delegation optimization, i.e. emitting the25/// complete constructor as a simple call to the base constructor.26bool CIRGenFunction::isConstructorDelegationValid(27const CXXConstructorDecl *ctor) {28// Currently we disable the optimization for classes with virtual bases29// because (1) the address of parameter variables need to be consistent across30// all initializers but (2) the delegate function call necessarily creates a31// second copy of the parameter variable.32//33// The limiting example (purely theoretical AFAIK):34// struct A { A(int &c) { c++; } };35// struct A : virtual A {36// B(int count) : A(count) { printf("%d\n", count); }37// };38// ...although even this example could in principle be emitted as a delegation39// since the address of the parameter doesn't escape.40if (ctor->getParent()->getNumVBases())41return false;4243// We also disable the optimization for variadic functions because it's44// impossible to "re-pass" varargs.45if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())46return false;4748// FIXME: Decide if we can do a delegation of a delegating constructor.49if (ctor->isDelegatingConstructor())50return false;5152return true;53}5455static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf,56CXXCtorInitializer *memberInit,57LValue &lhs) {58FieldDecl *field = memberInit->getAnyMember();59if (memberInit->isIndirectMemberInitializer()) {60// If we are initializing an anonymous union field, drill down to the field.61IndirectFieldDecl *indirectField = memberInit->getIndirectMember();62for (const auto *nd : indirectField->chain()) {63auto *fd = cast<clang::FieldDecl>(nd);64lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());65}66} else {67lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());68}69}7071static void emitMemberInitializer(CIRGenFunction &cgf,72const CXXRecordDecl *classDecl,73CXXCtorInitializer *memberInit,74const CXXConstructorDecl *constructor,75FunctionArgList &args) {76assert(memberInit->isAnyMemberInitializer() &&77"Mush have member initializer!");78assert(memberInit->getInit() && "Must have initializer!");7980assert(!cir::MissingFeatures::generateDebugInfo());8182// non-static data member initializers83FieldDecl *field = memberInit->getAnyMember();84QualType fieldType = field->getType();8586mlir::Value thisPtr = cgf.loadCXXThis();87QualType recordTy = cgf.getContext().getTypeDeclType(classDecl);8889// If a base constructor is being emitted, create an LValue that has the90// non-virtual alignment.91LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)92? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)93: cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);9495emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);9697// Special case: If we are in a copy or move constructor, and we are copying98// an array off PODs or classes with trivial copy constructors, ignore the AST99// and perform the copy we know is equivalent.100// FIXME: This is hacky at best... if we had a bit more explicit information101// in the AST, we could generalize it more easily.102const ConstantArrayType *array =103cgf.getContext().getAsConstantArrayType(fieldType);104if (array && constructor->isDefaulted() &&105constructor->isCopyOrMoveConstructor()) {106QualType baseElementTy = cgf.getContext().getBaseElementType(array);107// NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,108// whereas ClangIR wants to represent all object construction explicitly.109if (!baseElementTy->isRecordType()) {110cgf.cgm.errorNYI(memberInit->getSourceRange(),111"emitMemberInitializer: array of non-record type");112return;113}114}115116cgf.emitInitializerForField(field, lhs, memberInit->getInit());117}118119static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) {120const Type *baseType = baseInit->getBaseClass();121const auto *baseClassDecl =122cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getDecl());123return baseClassDecl->isDynamicClass();124}125126/// Gets the address of a direct base class within a complete object.127/// This should only be used for (1) non-virtual bases or (2) virtual bases128/// when the type is known to be complete (e.g. in complete destructors).129///130/// The object pointed to by 'thisAddr' is assumed to be non-null.131Address CIRGenFunction::getAddressOfDirectBaseInCompleteClass(132mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,133const CXXRecordDecl *base, bool baseIsVirtual) {134// 'thisAddr' must be a pointer (in some address space) to Derived.135assert(thisAddr.getElementType() == convertType(derived));136137// Compute the offset of the virtual base.138CharUnits offset;139const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);140if (baseIsVirtual)141offset = layout.getVBaseClassOffset(base);142else143offset = layout.getBaseClassOffset(base);144145return builder.createBaseClassAddr(loc, thisAddr, convertType(base),146offset.getQuantity(),147/*assumeNotNull=*/true);148}149150void CIRGenFunction::emitBaseInitializer(mlir::Location loc,151const CXXRecordDecl *classDecl,152CXXCtorInitializer *baseInit) {153assert(curFuncDecl && "loading 'this' without a func declaration?");154assert(isa<CXXMethodDecl>(curFuncDecl));155156assert(baseInit->isBaseInitializer() && "Must have base initializer!");157158Address thisPtr = loadCXXThisAddress();159160const Type *baseType = baseInit->getBaseClass();161const auto *baseClassDecl =162cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getDecl());163164bool isBaseVirtual = baseInit->isBaseVirtual();165166// If the initializer for the base (other than the constructor167// itself) accesses 'this' in any way, we need to initialize the168// vtables.169if (classDecl->isDynamicClass()) {170cgm.errorNYI(loc, "emitBaseInitializer: dynamic class");171return;172}173174// We can pretend to be a complete class because it only matters for175// virtual bases, and we only do virtual bases for complete ctors.176Address v = getAddressOfDirectBaseInCompleteClass(177loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);178assert(!cir::MissingFeatures::aggValueSlotGC());179AggValueSlot aggSlot = AggValueSlot::forAddr(180v, Qualifiers(), AggValueSlot::IsDestructed, AggValueSlot::IsNotAliased,181getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));182183emitAggExpr(baseInit->getInit(), aggSlot);184185assert(!cir::MissingFeatures::requiresCleanups());186}187188/// This routine generates necessary code to initialize base classes and189/// non-static data members belonging to this constructor.190void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,191CXXCtorType ctorType,192FunctionArgList &args) {193if (cd->isDelegatingConstructor()) {194emitDelegatingCXXConstructorCall(cd, args);195return;196}197198// If there are no member initializers, we can just return.199if (cd->getNumCtorInitializers() == 0)200return;201202const CXXRecordDecl *classDecl = cd->getParent();203204// This code doesn't use range-based iteration because we may need to emit205// code between the virtual base initializers and the non-virtual base or206// between the non-virtual base initializers and the member initializers.207CXXConstructorDecl::init_const_iterator b = cd->init_begin(),208e = cd->init_end();209210// Virtual base initializers first, if any. They aren't needed if:211// - This is a base ctor variant212// - There are no vbases213// - The class is abstract, so a complete object of it cannot be constructed214//215// The check for an abstract class is necessary because sema may not have216// marked virtual base destructors referenced.217bool constructVBases = ctorType != Ctor_Base &&218classDecl->getNumVBases() != 0 &&219!classDecl->isAbstract();220if (constructVBases) {221cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: virtual base");222return;223}224225const mlir::Value oldThisValue = cxxThisValue;226if (!constructVBases && (*b)->isBaseInitializer() && (*b)->isBaseVirtual()) {227cgm.errorNYI(cd->getSourceRange(),228"emitCtorPrologue: virtual base initializer");229return;230}231232// Handle non-virtual base initializers.233for (; b != e && (*b)->isBaseInitializer(); b++) {234assert(!(*b)->isBaseVirtual());235236if (cgm.getCodeGenOpts().StrictVTablePointers &&237cgm.getCodeGenOpts().OptimizationLevel > 0 &&238isInitializerOfDynamicClass(*b)) {239cgm.errorNYI(cd->getSourceRange(),240"emitCtorPrologue: strict vtable pointers");241return;242}243emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, *b);244}245246cxxThisValue = oldThisValue;247248if (classDecl->isDynamicClass()) {249cgm.errorNYI(cd->getSourceRange(),250"emitCtorPrologue: initialize vtable pointers");251return;252}253254// Finally, initialize class members.255FieldConstructionScope fcs(*this, loadCXXThisAddress());256// Classic codegen uses a special class to attempt to replace member257// initializers with memcpy. We could possibly defer that to the258// lowering or optimization phases to keep the memory accesses more259// explicit. For now, we don't insert memcpy at all.260assert(!cir::MissingFeatures::ctorMemcpyizer());261for (; b != e; b++) {262CXXCtorInitializer *member = (*b);263assert(!member->isBaseInitializer());264assert(member->isAnyMemberInitializer() &&265"Delegating initializer on non-delegating constructor");266emitMemberInitializer(*this, cd->getParent(), member, cd, args);267}268}269270Address CIRGenFunction::loadCXXThisAddress() {271assert(curFuncDecl && "loading 'this' without a func declaration?");272assert(isa<CXXMethodDecl>(curFuncDecl));273274// Lazily compute CXXThisAlignment.275if (cxxThisAlignment.isZero()) {276// Just use the best known alignment for the parent.277// TODO: if we're currently emitting a complete-object ctor/dtor, we can278// always use the complete-object alignment.279auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();280cxxThisAlignment = cgm.getClassPointerAlignment(rd);281}282283return Address(loadCXXThis(), cxxThisAlignment);284}285286void CIRGenFunction::emitInitializerForField(FieldDecl *field, LValue lhs,287Expr *init) {288QualType fieldType = field->getType();289switch (getEvaluationKind(fieldType)) {290case cir::TEK_Scalar:291if (lhs.isSimple())292emitExprAsInit(init, field, lhs, false);293else294cgm.errorNYI(field->getSourceRange(),295"emitInitializerForField: non-simple scalar");296break;297case cir::TEK_Complex:298cgm.errorNYI(field->getSourceRange(), "emitInitializerForField: complex");299break;300case cir::TEK_Aggregate: {301cgm.errorNYI(field->getSourceRange(), "emitInitializerForField: aggregate");302break;303}304}305306// Ensure that we destroy this object if an exception is thrown later in the307// constructor.308QualType::DestructionKind dtorKind = fieldType.isDestructedType();309(void)dtorKind;310assert(!cir::MissingFeatures::requiresCleanups());311}312313void CIRGenFunction::emitDelegateCXXConstructorCall(314const CXXConstructorDecl *ctor, CXXCtorType ctorType,315const FunctionArgList &args, SourceLocation loc) {316CallArgList delegateArgs;317318FunctionArgList::const_iterator i = args.begin(), e = args.end();319assert(i != e && "no parameters to constructor");320321// this322Address thisAddr = loadCXXThisAddress();323delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());324++i;325326// FIXME: The location of the VTT parameter in the parameter list is specific327// to the Itanium ABI and shouldn't be hardcoded here.328if (cgm.getCXXABI().needsVTTParameter(curGD)) {329cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");330return;331}332333// Explicit arguments.334for (; i != e; ++i) {335const VarDecl *param = *i;336// FIXME: per-argument source location337emitDelegateCallArg(delegateArgs, param, loc);338}339340assert(!cir::MissingFeatures::sanitizers());341342emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,343/*Delegating=*/true, thisAddr, delegateArgs, loc);344}345346void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {347const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());348assert(assignOp->isCopyAssignmentOperator() ||349assignOp->isMoveAssignmentOperator());350const Stmt *rootS = assignOp->getBody();351assert(isa<CompoundStmt>(rootS) &&352"Body of an implicit assignment operator should be compound stmt.");353const auto *rootCS = cast<CompoundStmt>(rootS);354355assert(!cir::MissingFeatures::incrementProfileCounter());356assert(!cir::MissingFeatures::runCleanupsScope());357358// Classic codegen uses a special class to attempt to replace member359// initializers with memcpy. We could possibly defer that to the360// lowering or optimization phases to keep the memory accesses more361// explicit. For now, we don't insert memcpy at all, though in some362// cases the AST contains a call to memcpy.363assert(!cir::MissingFeatures::assignMemcpyizer());364for (Stmt *s : rootCS->body())365if (emitStmt(s, /*useCurrentScope=*/true).failed())366cgm.errorNYI(s->getSourceRange(),367std::string("emitImplicitAssignmentOperatorBody: ") +368s->getStmtClassName());369}370371void CIRGenFunction::emitDelegatingCXXConstructorCall(372const CXXConstructorDecl *ctor, const FunctionArgList &args) {373assert(ctor->isDelegatingConstructor());374375Address thisPtr = loadCXXThisAddress();376377assert(!cir::MissingFeatures::objCGC());378assert(!cir::MissingFeatures::sanitizers());379AggValueSlot aggSlot = AggValueSlot::forAddr(380thisPtr, Qualifiers(), AggValueSlot::IsDestructed,381AggValueSlot::IsNotAliased, AggValueSlot::MayOverlap,382AggValueSlot::IsNotZeroed);383384emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);385386const CXXRecordDecl *classDecl = ctor->getParent();387if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {388cgm.errorNYI(ctor->getSourceRange(),389"emitDelegatingCXXConstructorCall: exception");390return;391}392}393394Address CIRGenFunction::getAddressOfBaseClass(395Address value, const CXXRecordDecl *derived,396llvm::iterator_range<CastExpr::path_const_iterator> path,397bool nullCheckValue, SourceLocation loc) {398assert(!path.empty() && "Base path should not be empty!");399400if ((*path.begin())->isVirtual()) {401// The implementation here is actually complete, but let's flag this402// as an error until the rest of the virtual base class support is in place.403cgm.errorNYI(loc, "getAddrOfBaseClass: virtual base");404return Address::invalid();405}406407// Compute the static offset of the ultimate destination within its408// allocating subobject (the virtual base, if there is one, or else409// the "complete" object that we see).410CharUnits nonVirtualOffset =411cgm.computeNonVirtualBaseClassOffset(derived, path);412413// Get the base pointer type.414mlir::Type baseValueTy = convertType((path.end()[-1])->getType());415assert(!cir::MissingFeatures::addressSpace());416417// The if statement here is redundant now, but it will be needed when we add418// support for virtual base classes.419// If there is no virtual base, use cir.base_class_addr. It takes care of420// the adjustment and the null pointer check.421if (nonVirtualOffset.isZero()) {422assert(!cir::MissingFeatures::sanitizers());423return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,424/*assumeNotNull=*/true);425}426427assert(!cir::MissingFeatures::sanitizers());428429// Apply the offset430value = builder.createBaseClassAddr(getLoc(loc), value, baseValueTy,431nonVirtualOffset.getQuantity(),432/*assumeNotNull=*/true);433434// Cast to the destination type.435value = value.withElementType(builder, baseValueTy);436437return value;438}439440void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,441clang::CXXCtorType type,442bool forVirtualBase,443bool delegating,444AggValueSlot thisAVS,445const clang::CXXConstructExpr *e) {446CallArgList args;447Address thisAddr = thisAVS.getAddress();448QualType thisType = d->getThisType();449mlir::Value thisPtr = thisAddr.getPointer();450451assert(!cir::MissingFeatures::addressSpace());452453args.add(RValue::get(thisPtr), thisType);454455// In LLVM Codegen: If this is a trivial constructor, just emit what's needed.456// If this is a union copy constructor, we must emit a memcpy, because the AST457// does not model that copy.458assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());459460const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();461462assert(!cir::MissingFeatures::opCallArgEvaluationOrder());463464emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),465/*ParamsToSkip=*/0);466467assert(!cir::MissingFeatures::sanitizers());468emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,469e->getExprLoc());470}471472void CIRGenFunction::emitCXXConstructorCall(473const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,474bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {475476const CXXRecordDecl *crd = d->getParent();477478// If this is a call to a trivial default constructor:479// In LLVM: do nothing.480// In CIR: emit as a regular call, other later passes should lower the481// ctor call into trivial initialization.482assert(!cir::MissingFeatures::isTrivialCtorOrDtor());483484assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());485486bool passPrototypeArgs = true;487488// Check whether we can actually emit the constructor before trying to do so.489if (d->getInheritedConstructor()) {490cgm.errorNYI(d->getSourceRange(),491"emitCXXConstructorCall: inherited constructor");492return;493}494495// Insert any ABI-specific implicit constructor arguments.496assert(!cir::MissingFeatures::implicitConstructorArgs());497498// Emit the call.499auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));500const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(501args, d, type, passPrototypeArgs);502CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));503cir::CIRCallOpInterface c;504emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));505506if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&507type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)508cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");509}510511512