================
@@ -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);
----------------
erichkeane wrote:
I spent a while looking at `EmitParmDecl`. I considered re-implementing it,
but it spends basically all of its time doing calling convention related stuff,
so I'm pretty well convinced that it ISN'T something we should be implementing?
It does about the 3 lines below (creating an arg and storing to it), and about
150 lines going through the decisions made for calling convention, so it seemed
useless for us.
https://github.com/llvm/llvm-project/pull/191467
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits