| 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 | |
| 16 | #include "clang/AST/ExprCXX.h" |
| 17 | #include "clang/AST/RecordLayout.h" |
| 18 | #include "clang/AST/Type.h" |
| 19 | #include "clang/CIR/MissingFeatures.h" |
| 20 | |
| 21 | using namespace clang; |
| 22 | using namespace clang::CIRGen; |
| 23 | |
| 24 | /// Checks whether the given constructor is a valid subject for the |
| 25 | /// complete-to-base constructor delegation optimization, i.e. emitting the |
| 26 | /// complete constructor as a simple call to the base constructor. |
| 27 | bool CIRGenFunction::isConstructorDelegationValid( |
| 28 | const CXXConstructorDecl *ctor) { |
| 29 | // Currently we disable the optimization for classes with virtual bases |
| 30 | // because (1) the address of parameter variables need to be consistent across |
| 31 | // all initializers but (2) the delegate function call necessarily creates a |
| 32 | // second copy of the parameter variable. |
| 33 | // |
| 34 | // The limiting example (purely theoretical AFAIK): |
| 35 | // struct A { A(int &c) { c++; } }; |
| 36 | // struct A : virtual A { |
| 37 | // B(int count) : A(count) { printf("%d\n", count); } |
| 38 | // }; |
| 39 | // ...although even this example could in principle be emitted as a delegation |
| 40 | // since the address of the parameter doesn't escape. |
| 41 | if (ctor->getParent()->getNumVBases()) |
| 42 | return false; |
| 43 | |
| 44 | // We also disable the optimization for variadic functions because it's |
| 45 | // impossible to "re-pass" varargs. |
| 46 | if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic()) |
| 47 | return false; |
| 48 | |
| 49 | // FIXME: Decide if we can do a delegation of a delegating constructor. |
| 50 | if (ctor->isDelegatingConstructor()) |
| 51 | return false; |
| 52 | |
| 53 | return true; |
| 54 | } |
| 55 | |
| 56 | static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf, |
| 57 | CXXCtorInitializer *memberInit, |
| 58 | LValue &lhs) { |
| 59 | FieldDecl *field = memberInit->getAnyMember(); |
| 60 | if (memberInit->isIndirectMemberInitializer()) { |
| 61 | // If we are initializing an anonymous union field, drill down to the field. |
| 62 | IndirectFieldDecl *indirectField = memberInit->getIndirectMember(); |
| 63 | for (const auto *nd : indirectField->chain()) { |
| 64 | auto *fd = cast<clang::FieldDecl>(Val: nd); |
| 65 | lhs = cgf.emitLValueForFieldInitialization(base: lhs, field: fd, fieldName: fd->getName()); |
| 66 | } |
| 67 | } else { |
| 68 | lhs = cgf.emitLValueForFieldInitialization(base: lhs, field, fieldName: field->getName()); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | static void emitMemberInitializer(CIRGenFunction &cgf, |
| 73 | const CXXRecordDecl *classDecl, |
| 74 | CXXCtorInitializer *memberInit, |
| 75 | const CXXConstructorDecl *constructor, |
| 76 | FunctionArgList &args) { |
| 77 | assert(memberInit->isAnyMemberInitializer() && |
| 78 | "Mush have member initializer!" ); |
| 79 | assert(memberInit->getInit() && "Must have initializer!" ); |
| 80 | |
| 81 | assert(!cir::MissingFeatures::generateDebugInfo()); |
| 82 | |
| 83 | // non-static data member initializers |
| 84 | FieldDecl *field = memberInit->getAnyMember(); |
| 85 | QualType fieldType = field->getType(); |
| 86 | |
| 87 | mlir::Value thisPtr = cgf.loadCXXThis(); |
| 88 | QualType recordTy = cgf.getContext().getTypeDeclType(Decl: classDecl); |
| 89 | |
| 90 | // If a base constructor is being emitted, create an LValue that has the |
| 91 | // non-virtual alignment. |
| 92 | LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base) |
| 93 | ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy) |
| 94 | : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy); |
| 95 | |
| 96 | emitLValueForAnyFieldInitialization(cgf, memberInit, lhs); |
| 97 | |
| 98 | // Special case: If we are in a copy or move constructor, and we are copying |
| 99 | // an array off PODs or classes with trivial copy constructors, ignore the AST |
| 100 | // and perform the copy we know is equivalent. |
| 101 | // FIXME: This is hacky at best... if we had a bit more explicit information |
| 102 | // in the AST, we could generalize it more easily. |
| 103 | const ConstantArrayType *array = |
| 104 | cgf.getContext().getAsConstantArrayType(T: fieldType); |
| 105 | if (array && constructor->isDefaulted() && |
| 106 | constructor->isCopyOrMoveConstructor()) { |
| 107 | QualType baseElementTy = cgf.getContext().getBaseElementType(VAT: array); |
| 108 | // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable, |
| 109 | // whereas ClangIR wants to represent all object construction explicitly. |
| 110 | if (!baseElementTy->isRecordType()) { |
| 111 | cgf.cgm.errorNYI(memberInit->getSourceRange(), |
| 112 | "emitMemberInitializer: array of non-record type" ); |
| 113 | return; |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | cgf.emitInitializerForField(field, lhs, init: memberInit->getInit()); |
| 118 | } |
| 119 | |
| 120 | static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) { |
| 121 | const Type *baseType = baseInit->getBaseClass(); |
| 122 | const auto *baseClassDecl = |
| 123 | cast<CXXRecordDecl>(Val: baseType->castAs<RecordType>()->getDecl()); |
| 124 | return baseClassDecl->isDynamicClass(); |
| 125 | } |
| 126 | |
| 127 | /// Gets the address of a direct base class within a complete object. |
| 128 | /// This should only be used for (1) non-virtual bases or (2) virtual bases |
| 129 | /// when the type is known to be complete (e.g. in complete destructors). |
| 130 | /// |
| 131 | /// The object pointed to by 'thisAddr' is assumed to be non-null. |
| 132 | Address CIRGenFunction::getAddressOfDirectBaseInCompleteClass( |
| 133 | mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived, |
| 134 | const CXXRecordDecl *base, bool baseIsVirtual) { |
| 135 | // 'thisAddr' must be a pointer (in some address space) to Derived. |
| 136 | assert(thisAddr.getElementType() == convertType(derived)); |
| 137 | |
| 138 | // Compute the offset of the virtual base. |
| 139 | CharUnits offset; |
| 140 | const ASTRecordLayout &layout = getContext().getASTRecordLayout(D: derived); |
| 141 | if (baseIsVirtual) |
| 142 | offset = layout.getVBaseClassOffset(VBase: base); |
| 143 | else |
| 144 | offset = layout.getBaseClassOffset(Base: base); |
| 145 | |
| 146 | return builder.createBaseClassAddr(loc, thisAddr, convertType(base), |
| 147 | offset.getQuantity(), |
| 148 | /*assumeNotNull=*/true); |
| 149 | } |
| 150 | |
| 151 | void CIRGenFunction::emitBaseInitializer(mlir::Location loc, |
| 152 | const CXXRecordDecl *classDecl, |
| 153 | CXXCtorInitializer *baseInit) { |
| 154 | assert(curFuncDecl && "loading 'this' without a func declaration?" ); |
| 155 | assert(isa<CXXMethodDecl>(curFuncDecl)); |
| 156 | |
| 157 | assert(baseInit->isBaseInitializer() && "Must have base initializer!" ); |
| 158 | |
| 159 | Address thisPtr = loadCXXThisAddress(); |
| 160 | |
| 161 | const Type *baseType = baseInit->getBaseClass(); |
| 162 | const auto *baseClassDecl = |
| 163 | cast<CXXRecordDecl>(Val: baseType->castAs<RecordType>()->getDecl()); |
| 164 | |
| 165 | bool isBaseVirtual = baseInit->isBaseVirtual(); |
| 166 | |
| 167 | // If the initializer for the base (other than the constructor |
| 168 | // itself) accesses 'this' in any way, we need to initialize the |
| 169 | // vtables. |
| 170 | if (classDecl->isDynamicClass()) { |
| 171 | cgm.errorNYI(loc, "emitBaseInitializer: dynamic class" ); |
| 172 | return; |
| 173 | } |
| 174 | |
| 175 | // We can pretend to be a complete class because it only matters for |
| 176 | // virtual bases, and we only do virtual bases for complete ctors. |
| 177 | Address v = getAddressOfDirectBaseInCompleteClass( |
| 178 | loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual); |
| 179 | assert(!cir::MissingFeatures::aggValueSlotGC()); |
| 180 | AggValueSlot aggSlot = AggValueSlot::forAddr( |
| 181 | addr: v, quals: Qualifiers(), isDestructed: AggValueSlot::IsDestructed, isAliased: AggValueSlot::IsNotAliased, |
| 182 | mayOverlap: getOverlapForBaseInit(rd: classDecl, baseRD: baseClassDecl, isVirtual: isBaseVirtual)); |
| 183 | |
| 184 | emitAggExpr(e: baseInit->getInit(), slot: aggSlot); |
| 185 | |
| 186 | assert(!cir::MissingFeatures::requiresCleanups()); |
| 187 | } |
| 188 | |
| 189 | /// This routine generates necessary code to initialize base classes and |
| 190 | /// non-static data members belonging to this constructor. |
| 191 | void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd, |
| 192 | CXXCtorType ctorType, |
| 193 | FunctionArgList &args) { |
| 194 | if (cd->isDelegatingConstructor()) { |
| 195 | emitDelegatingCXXConstructorCall(ctor: cd, args); |
| 196 | return; |
| 197 | } |
| 198 | |
| 199 | // If there are no member initializers, we can just return. |
| 200 | if (cd->getNumCtorInitializers() == 0) |
| 201 | return; |
| 202 | |
| 203 | const CXXRecordDecl *classDecl = cd->getParent(); |
| 204 | |
| 205 | // This code doesn't use range-based iteration because we may need to emit |
| 206 | // code between the virtual base initializers and the non-virtual base or |
| 207 | // between the non-virtual base initializers and the member initializers. |
| 208 | CXXConstructorDecl::init_const_iterator b = cd->init_begin(), |
| 209 | e = cd->init_end(); |
| 210 | |
| 211 | // Virtual base initializers first, if any. They aren't needed if: |
| 212 | // - This is a base ctor variant |
| 213 | // - There are no vbases |
| 214 | // - The class is abstract, so a complete object of it cannot be constructed |
| 215 | // |
| 216 | // The check for an abstract class is necessary because sema may not have |
| 217 | // marked virtual base destructors referenced. |
| 218 | bool constructVBases = ctorType != Ctor_Base && |
| 219 | classDecl->getNumVBases() != 0 && |
| 220 | !classDecl->isAbstract(); |
| 221 | if (constructVBases) { |
| 222 | cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: virtual base" ); |
| 223 | return; |
| 224 | } |
| 225 | |
| 226 | const mlir::Value oldThisValue = cxxThisValue; |
| 227 | if (!constructVBases && (*b)->isBaseInitializer() && (*b)->isBaseVirtual()) { |
| 228 | cgm.errorNYI(cd->getSourceRange(), |
| 229 | "emitCtorPrologue: virtual base initializer" ); |
| 230 | return; |
| 231 | } |
| 232 | |
| 233 | // Handle non-virtual base initializers. |
| 234 | for (; b != e && (*b)->isBaseInitializer(); b++) { |
| 235 | assert(!(*b)->isBaseVirtual()); |
| 236 | |
| 237 | if (cgm.getCodeGenOpts().StrictVTablePointers && |
| 238 | cgm.getCodeGenOpts().OptimizationLevel > 0 && |
| 239 | isInitializerOfDynamicClass(baseInit: *b)) { |
| 240 | cgm.errorNYI(cd->getSourceRange(), |
| 241 | "emitCtorPrologue: strict vtable pointers" ); |
| 242 | return; |
| 243 | } |
| 244 | emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, *b); |
| 245 | } |
| 246 | |
| 247 | cxxThisValue = oldThisValue; |
| 248 | |
| 249 | if (classDecl->isDynamicClass()) { |
| 250 | cgm.errorNYI(cd->getSourceRange(), |
| 251 | "emitCtorPrologue: initialize vtable pointers" ); |
| 252 | return; |
| 253 | } |
| 254 | |
| 255 | // Finally, initialize class members. |
| 256 | FieldConstructionScope fcs(*this, loadCXXThisAddress()); |
| 257 | // Classic codegen uses a special class to attempt to replace member |
| 258 | // initializers with memcpy. We could possibly defer that to the |
| 259 | // lowering or optimization phases to keep the memory accesses more |
| 260 | // explicit. For now, we don't insert memcpy at all. |
| 261 | assert(!cir::MissingFeatures::ctorMemcpyizer()); |
| 262 | for (; b != e; b++) { |
| 263 | CXXCtorInitializer *member = (*b); |
| 264 | assert(!member->isBaseInitializer()); |
| 265 | assert(member->isAnyMemberInitializer() && |
| 266 | "Delegating initializer on non-delegating constructor" ); |
| 267 | emitMemberInitializer(cgf&: *this, classDecl: cd->getParent(), memberInit: member, constructor: cd, args); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | Address CIRGenFunction::loadCXXThisAddress() { |
| 272 | assert(curFuncDecl && "loading 'this' without a func declaration?" ); |
| 273 | assert(isa<CXXMethodDecl>(curFuncDecl)); |
| 274 | |
| 275 | // Lazily compute CXXThisAlignment. |
| 276 | if (cxxThisAlignment.isZero()) { |
| 277 | // Just use the best known alignment for the parent. |
| 278 | // TODO: if we're currently emitting a complete-object ctor/dtor, we can |
| 279 | // always use the complete-object alignment. |
| 280 | auto rd = cast<CXXMethodDecl>(Val: curFuncDecl)->getParent(); |
| 281 | cxxThisAlignment = cgm.getClassPointerAlignment(rd); |
| 282 | } |
| 283 | |
| 284 | return Address(loadCXXThis(), cxxThisAlignment); |
| 285 | } |
| 286 | |
| 287 | void CIRGenFunction::emitInitializerForField(FieldDecl *field, LValue lhs, |
| 288 | Expr *init) { |
| 289 | QualType fieldType = field->getType(); |
| 290 | switch (getEvaluationKind(type: fieldType)) { |
| 291 | case cir::TEK_Scalar: |
| 292 | if (lhs.isSimple()) |
| 293 | emitExprAsInit(init, d: field, lvalue: lhs, capturedByInit: false); |
| 294 | else |
| 295 | cgm.errorNYI(field->getSourceRange(), |
| 296 | "emitInitializerForField: non-simple scalar" ); |
| 297 | break; |
| 298 | case cir::TEK_Complex: |
| 299 | cgm.errorNYI(field->getSourceRange(), "emitInitializerForField: complex" ); |
| 300 | break; |
| 301 | case cir::TEK_Aggregate: { |
| 302 | cgm.errorNYI(field->getSourceRange(), "emitInitializerForField: aggregate" ); |
| 303 | break; |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | // Ensure that we destroy this object if an exception is thrown later in the |
| 308 | // constructor. |
| 309 | QualType::DestructionKind dtorKind = fieldType.isDestructedType(); |
| 310 | (void)dtorKind; |
| 311 | assert(!cir::MissingFeatures::requiresCleanups()); |
| 312 | } |
| 313 | |
| 314 | void CIRGenFunction::emitDelegateCXXConstructorCall( |
| 315 | const CXXConstructorDecl *ctor, CXXCtorType ctorType, |
| 316 | const FunctionArgList &args, SourceLocation loc) { |
| 317 | CallArgList delegateArgs; |
| 318 | |
| 319 | FunctionArgList::const_iterator i = args.begin(), e = args.end(); |
| 320 | assert(i != e && "no parameters to constructor" ); |
| 321 | |
| 322 | // this |
| 323 | Address thisAddr = loadCXXThisAddress(); |
| 324 | delegateArgs.add(RValue::rvalue: get(thisAddr.getPointer()), type: (*i)->getType()); |
| 325 | ++i; |
| 326 | |
| 327 | // FIXME: The location of the VTT parameter in the parameter list is specific |
| 328 | // to the Itanium ABI and shouldn't be hardcoded here. |
| 329 | if (cgm.getCXXABI().needsVTTParameter(gd: curGD)) { |
| 330 | cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter" ); |
| 331 | return; |
| 332 | } |
| 333 | |
| 334 | // Explicit arguments. |
| 335 | for (; i != e; ++i) { |
| 336 | const VarDecl *param = *i; |
| 337 | // FIXME: per-argument source location |
| 338 | emitDelegateCallArg(args&: delegateArgs, param, loc); |
| 339 | } |
| 340 | |
| 341 | assert(!cir::MissingFeatures::sanitizers()); |
| 342 | |
| 343 | emitCXXConstructorCall(d: ctor, type: ctorType, /*ForVirtualBase=*/forVirtualBase: false, |
| 344 | /*Delegating=*/delegating: true, thisAddr, args&: delegateArgs, loc); |
| 345 | } |
| 346 | |
| 347 | void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) { |
| 348 | const auto *assignOp = cast<CXXMethodDecl>(Val: curGD.getDecl()); |
| 349 | assert(assignOp->isCopyAssignmentOperator() || |
| 350 | assignOp->isMoveAssignmentOperator()); |
| 351 | const Stmt *rootS = assignOp->getBody(); |
| 352 | assert(isa<CompoundStmt>(rootS) && |
| 353 | "Body of an implicit assignment operator should be compound stmt." ); |
| 354 | const auto *rootCS = cast<CompoundStmt>(Val: rootS); |
| 355 | |
| 356 | assert(!cir::MissingFeatures::incrementProfileCounter()); |
| 357 | assert(!cir::MissingFeatures::runCleanupsScope()); |
| 358 | |
| 359 | // Classic codegen uses a special class to attempt to replace member |
| 360 | // initializers with memcpy. We could possibly defer that to the |
| 361 | // lowering or optimization phases to keep the memory accesses more |
| 362 | // explicit. For now, we don't insert memcpy at all, though in some |
| 363 | // cases the AST contains a call to memcpy. |
| 364 | assert(!cir::MissingFeatures::assignMemcpyizer()); |
| 365 | for (Stmt *s : rootCS->body()) |
| 366 | if (emitStmt(s, /*useCurrentScope=*/true).failed()) |
| 367 | cgm.errorNYI(s->getSourceRange(), |
| 368 | std::string("emitImplicitAssignmentOperatorBody: " ) + |
| 369 | s->getStmtClassName()); |
| 370 | } |
| 371 | |
| 372 | void CIRGenFunction::emitDelegatingCXXConstructorCall( |
| 373 | const CXXConstructorDecl *ctor, const FunctionArgList &args) { |
| 374 | assert(ctor->isDelegatingConstructor()); |
| 375 | |
| 376 | Address thisPtr = loadCXXThisAddress(); |
| 377 | |
| 378 | assert(!cir::MissingFeatures::objCGC()); |
| 379 | assert(!cir::MissingFeatures::sanitizers()); |
| 380 | AggValueSlot aggSlot = AggValueSlot::forAddr( |
| 381 | addr: thisPtr, quals: Qualifiers(), isDestructed: AggValueSlot::IsDestructed, |
| 382 | isAliased: AggValueSlot::IsNotAliased, mayOverlap: AggValueSlot::MayOverlap, |
| 383 | isZeroed: AggValueSlot::IsNotZeroed); |
| 384 | |
| 385 | emitAggExpr(e: ctor->init_begin()[0]->getInit(), slot: aggSlot); |
| 386 | |
| 387 | const CXXRecordDecl *classDecl = ctor->getParent(); |
| 388 | if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) { |
| 389 | cgm.errorNYI(ctor->getSourceRange(), |
| 390 | "emitDelegatingCXXConstructorCall: exception" ); |
| 391 | return; |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | Address CIRGenFunction::getAddressOfBaseClass( |
| 396 | Address value, const CXXRecordDecl *derived, |
| 397 | llvm::iterator_range<CastExpr::path_const_iterator> path, |
| 398 | bool nullCheckValue, SourceLocation loc) { |
| 399 | assert(!path.empty() && "Base path should not be empty!" ); |
| 400 | |
| 401 | if ((*path.begin())->isVirtual()) { |
| 402 | // The implementation here is actually complete, but let's flag this |
| 403 | // as an error until the rest of the virtual base class support is in place. |
| 404 | cgm.errorNYI(loc, "getAddrOfBaseClass: virtual base" ); |
| 405 | return Address::invalid(); |
| 406 | } |
| 407 | |
| 408 | // Compute the static offset of the ultimate destination within its |
| 409 | // allocating subobject (the virtual base, if there is one, or else |
| 410 | // the "complete" object that we see). |
| 411 | CharUnits nonVirtualOffset = |
| 412 | cgm.computeNonVirtualBaseClassOffset(derivedClass: derived, path); |
| 413 | |
| 414 | // Get the base pointer type. |
| 415 | mlir::Type baseValueTy = convertType((path.end()[-1])->getType()); |
| 416 | assert(!cir::MissingFeatures::addressSpace()); |
| 417 | |
| 418 | // The if statement here is redundant now, but it will be needed when we add |
| 419 | // support for virtual base classes. |
| 420 | // If there is no virtual base, use cir.base_class_addr. It takes care of |
| 421 | // the adjustment and the null pointer check. |
| 422 | if (nonVirtualOffset.isZero()) { |
| 423 | assert(!cir::MissingFeatures::sanitizers()); |
| 424 | return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0, |
| 425 | /*assumeNotNull=*/true); |
| 426 | } |
| 427 | |
| 428 | assert(!cir::MissingFeatures::sanitizers()); |
| 429 | |
| 430 | // Apply the offset |
| 431 | value = builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, |
| 432 | nonVirtualOffset.getQuantity(), |
| 433 | /*assumeNotNull=*/true); |
| 434 | |
| 435 | // Cast to the destination type. |
| 436 | value = value.withElementType(builder, baseValueTy); |
| 437 | |
| 438 | return value; |
| 439 | } |
| 440 | |
| 441 | void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d, |
| 442 | clang::CXXCtorType type, |
| 443 | bool forVirtualBase, |
| 444 | bool delegating, |
| 445 | AggValueSlot thisAVS, |
| 446 | const clang::CXXConstructExpr *e) { |
| 447 | CallArgList args; |
| 448 | Address thisAddr = thisAVS.getAddress(); |
| 449 | QualType thisType = d->getThisType(); |
| 450 | mlir::Value thisPtr = thisAddr.getPointer(); |
| 451 | |
| 452 | assert(!cir::MissingFeatures::addressSpace()); |
| 453 | |
| 454 | args.add(RValue::rvalue: get(thisPtr), type: thisType); |
| 455 | |
| 456 | // In LLVM Codegen: If this is a trivial constructor, just emit what's needed. |
| 457 | // If this is a union copy constructor, we must emit a memcpy, because the AST |
| 458 | // does not model that copy. |
| 459 | assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember()); |
| 460 | |
| 461 | const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>(); |
| 462 | |
| 463 | assert(!cir::MissingFeatures::opCallArgEvaluationOrder()); |
| 464 | |
| 465 | emitCallArgs(args, prototype: fpt, argRange: e->arguments(), callee: e->getConstructor(), |
| 466 | /*ParamsToSkip=*/paramsToSkip: 0); |
| 467 | |
| 468 | assert(!cir::MissingFeatures::sanitizers()); |
| 469 | emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args, |
| 470 | loc: e->getExprLoc()); |
| 471 | } |
| 472 | |
| 473 | void CIRGenFunction::emitCXXConstructorCall( |
| 474 | const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase, |
| 475 | bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) { |
| 476 | |
| 477 | const CXXRecordDecl *crd = d->getParent(); |
| 478 | |
| 479 | // If this is a call to a trivial default constructor: |
| 480 | // In LLVM: do nothing. |
| 481 | // In CIR: emit as a regular call, other later passes should lower the |
| 482 | // ctor call into trivial initialization. |
| 483 | assert(!cir::MissingFeatures::isTrivialCtorOrDtor()); |
| 484 | |
| 485 | assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember()); |
| 486 | |
| 487 | bool passPrototypeArgs = true; |
| 488 | |
| 489 | // Check whether we can actually emit the constructor before trying to do so. |
| 490 | if (d->getInheritedConstructor()) { |
| 491 | cgm.errorNYI(d->getSourceRange(), |
| 492 | "emitCXXConstructorCall: inherited constructor" ); |
| 493 | return; |
| 494 | } |
| 495 | |
| 496 | // Insert any ABI-specific implicit constructor arguments. |
| 497 | assert(!cir::MissingFeatures::implicitConstructorArgs()); |
| 498 | |
| 499 | // Emit the call. |
| 500 | auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type)); |
| 501 | const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall( |
| 502 | args, d, ctorKind: type, passProtoArgs: passPrototypeArgs); |
| 503 | CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type)); |
| 504 | cir::CIRCallOpInterface c; |
| 505 | emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc)); |
| 506 | |
| 507 | if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() && |
| 508 | type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers) |
| 509 | cgm.errorNYI(d->getSourceRange(), "vtable assumption loads" ); |
| 510 | } |
| 511 | |