================
@@ -1344,14 +1344,134 @@ void CIRGenFunction::emitCXXConstructorCall(const
clang::CXXConstructorDecl *d,
assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
- emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
- /*ParamsToSkip=*/0);
+ if (auto inherited = d->getInheritedConstructor();
+ !inherited || cgm.getTypes().inheritingCtorHasParams(inherited, type))
+ emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+ /*ParamsToSkip=*/0);
assert(!cir::MissingFeatures::sanitizers());
emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
e->getExprLoc());
}
+static bool canEmitDelegateCallArgs(CIRGenModule &cgm, ASTContext &ctx,
+ const CXXConstructorDecl *d,
+ CXXCtorType type) {
+ // We can't forward a variadic call.
+ if (d->isVariadic())
+ return false;
+
+ if (ctx.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+ // If the parameters are callee-cleanup, it's not safe to forward.
+ if (llvm::any_of(d->parameters(), [&ctx](const ParmVarDecl *param) {
+ return param->needsDestruction(ctx);
+ }))
+ return false;
+
+ // FIXME(CIR): It isn't clear to me that this is the right answer here,
+ // classic-codegen decides the answer is 'false' if there is an inalloca
+ // argument. What our default should be in this case, or what we want to
do.
+ // When we get an understanding of what the the calling-convention code
+ // needs here, we should be able to replace this with either a 'return
+ // false' or 'return true'.
+ cgm.errorNYI(d->getSourceRange(),
+ "canEmitDelegateCallArgs: args-destroyed-L-to-R in callee");
+ }
+
+ return true;
+}
+
+void CIRGenFunction::emitInheritedCXXConstructorCall(
+ const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr,
+ bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e) {
+
+ CallArgList ctorArgs;
+ CallArg thisArg(RValue::get(getAsNaturalPointerTo(
+ thisAddr, d->getThisType()->getPointeeType())),
+ d->getThisType());
+
+ if (inheritedFromVBase &&
+ cgm.getTarget().getCXXABI().hasConstructorVariants()) {
+ cgm.errorNYI(
+ e->getSourceRange(),
+ "emitInheritedCXXConstructorCall inheritedFromVBasewith ctor
variants");
+ return;
+ } else if (!cxxInheritedCtorInitExprArgs.empty()) {
+ // The inheriting constructor was inlined; just inject its arguments.
+ assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
+ "wrong number of parameters for inherited constructor call");
+ ctorArgs = cxxInheritedCtorInitExprArgs;
+ ctorArgs[0] = thisArg;
+ } else {
+ ctorArgs.push_back(thisArg);
+ const auto *outerCtor = cast<CXXConstructorDecl>(curCodeDecl);
+ assert(outerCtor->getNumParams() == d->getNumParams());
+ assert(!outerCtor->isVariadic() && "should have been inlined");
+
+ for (const ParmVarDecl *param : outerCtor->parameters()) {
+ assert(getContext().hasSameUnqualifiedType(
+ outerCtor->getParamDecl(param->getFunctionScopeIndex())->getType(),
+ param->getType()));
+ emitDelegateCallArg(ctorArgs, param, e->getLocation());
+
+ if (param->hasAttr<PassObjectSizeAttr>())
+ cgm.errorNYI(
+ e->getLocation(),
+ "emitInheritedCXXConstructorCall: pass object size attr argument");
+ }
+ }
+
+ emitCXXConstructorCall(d, Ctor_Base, forVirtualBase, /*delegating=*/false,
+ thisAddr, ctorArgs, e->getLocation());
+}
+
+void CIRGenFunction::emitInlinedInheritingCXXConstructorCall(
+ SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
+ bool forVirtualBase, bool delegating, CallArgList &args) {
+ GlobalDecl gd(d, ctorType);
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ assert(!cir::MissingFeatures::runCleanupsScope());
+ InlinedInheritingConstructorScope scope(*this, gd);
+
+ // Save the arguments to be passed to the inherited constructor.
+ cxxInheritedCtorInitExprArgs = args;
+
+ FunctionArgList params;
+ QualType retTy = buildFunctionArgList(gd, params);
+
+ cgm.getCXXABI().addImplicitConstructorArgs(*this, d, ctorType,
forVirtualBase,
+ delegating, args);
+
+ // Emit a simplified prolog. We only need to emit the implicit params.
+ assert(args.size() >= params.size() && "too few arguments for call");
+ for (auto [idx, arg, parm] :
+ llvm::zip_longest(llvm::index_range{0, args.size()}, args, params)) {
+ if (idx < params.size() && isa<ImplicitParamDecl>(*parm)) {
+ mlir::Location parmLoc = getLoc((*parm)->getSourceRange());
+ RValue argVal = arg->getRValue(*this, parmLoc);
----------------
andykaylor wrote:
I see classic codegen calls `EmitParmDecl` here, which we haven't implemented.
Is that overkill for this purpose?
https://github.com/llvm/llvm-project/pull/191467
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits