xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenCall.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // These classes wrap the information about a call or function definition used
10*700637cbSDimitry Andric // to handle ABI compliancy.
11*700637cbSDimitry Andric //
12*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
13*700637cbSDimitry Andric 
14*700637cbSDimitry Andric #include "CIRGenCall.h"
15*700637cbSDimitry Andric #include "CIRGenCXXABI.h"
16*700637cbSDimitry Andric #include "CIRGenFunction.h"
17*700637cbSDimitry Andric #include "CIRGenFunctionInfo.h"
18*700637cbSDimitry Andric #include "clang/CIR/MissingFeatures.h"
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric using namespace clang;
21*700637cbSDimitry Andric using namespace clang::CIRGen;
22*700637cbSDimitry Andric 
23*700637cbSDimitry Andric CIRGenFunctionInfo *
create(CanQualType resultType,llvm::ArrayRef<CanQualType> argTypes,RequiredArgs required)24*700637cbSDimitry Andric CIRGenFunctionInfo::create(CanQualType resultType,
25*700637cbSDimitry Andric                            llvm::ArrayRef<CanQualType> argTypes,
26*700637cbSDimitry Andric                            RequiredArgs required) {
27*700637cbSDimitry Andric   // The first slot allocated for arg type slot is for the return value.
28*700637cbSDimitry Andric   void *buffer = operator new(
29*700637cbSDimitry Andric       totalSizeToAlloc<CanQualType>(argTypes.size() + 1));
30*700637cbSDimitry Andric 
31*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoParamInfo());
32*700637cbSDimitry Andric 
33*700637cbSDimitry Andric   CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
34*700637cbSDimitry Andric 
35*700637cbSDimitry Andric   fi->required = required;
36*700637cbSDimitry Andric   fi->numArgs = argTypes.size();
37*700637cbSDimitry Andric 
38*700637cbSDimitry Andric   fi->getArgTypes()[0] = resultType;
39*700637cbSDimitry Andric   std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());
40*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
41*700637cbSDimitry Andric 
42*700637cbSDimitry Andric   return fi;
43*700637cbSDimitry Andric }
44*700637cbSDimitry Andric 
getFunctionType(const CIRGenFunctionInfo & fi)45*700637cbSDimitry Andric cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
46*700637cbSDimitry Andric   mlir::Type resultType = convertType(fi.getReturnType());
47*700637cbSDimitry Andric   SmallVector<mlir::Type, 8> argTypes;
48*700637cbSDimitry Andric   argTypes.reserve(fi.getNumRequiredArgs());
49*700637cbSDimitry Andric 
50*700637cbSDimitry Andric   for (const CanQualType &argType : fi.requiredArguments())
51*700637cbSDimitry Andric     argTypes.push_back(convertType(argType));
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric   return cir::FuncType::get(argTypes,
54*700637cbSDimitry Andric                             (resultType ? resultType : builder.getVoidTy()),
55*700637cbSDimitry Andric                             fi.isVariadic());
56*700637cbSDimitry Andric }
57*700637cbSDimitry Andric 
prepareConcreteCallee(CIRGenFunction & cgf) const58*700637cbSDimitry Andric CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
59*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallVirtual());
60*700637cbSDimitry Andric   return *this;
61*700637cbSDimitry Andric }
62*700637cbSDimitry Andric 
emitAggregateStore(mlir::Value value,Address dest)63*700637cbSDimitry Andric void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
64*700637cbSDimitry Andric   // In classic codegen:
65*700637cbSDimitry Andric   // Function to store a first-class aggregate into memory. We prefer to
66*700637cbSDimitry Andric   // store the elements rather than the aggregate to be more friendly to
67*700637cbSDimitry Andric   // fast-isel.
68*700637cbSDimitry Andric   // In CIR codegen:
69*700637cbSDimitry Andric   // Emit the most simple cir.store possible (e.g. a store for a whole
70*700637cbSDimitry Andric   // record), which can later be broken down in other CIR levels (or prior
71*700637cbSDimitry Andric   // to dialect codegen).
72*700637cbSDimitry Andric 
73*700637cbSDimitry Andric   // Stored result for the callers of this function expected to be in the same
74*700637cbSDimitry Andric   // scope as the value, don't make assumptions about current insertion point.
75*700637cbSDimitry Andric   mlir::OpBuilder::InsertionGuard guard(builder);
76*700637cbSDimitry Andric   builder.setInsertionPointAfter(value.getDefiningOp());
77*700637cbSDimitry Andric   builder.createStore(*currSrcLoc, value, dest);
78*700637cbSDimitry Andric }
79*700637cbSDimitry Andric 
addAttributesFromFunctionProtoType(CIRGenBuilderTy & builder,mlir::NamedAttrList & attrs,const FunctionProtoType * fpt)80*700637cbSDimitry Andric static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder,
81*700637cbSDimitry Andric                                                mlir::NamedAttrList &attrs,
82*700637cbSDimitry Andric                                                const FunctionProtoType *fpt) {
83*700637cbSDimitry Andric   if (!fpt)
84*700637cbSDimitry Andric     return;
85*700637cbSDimitry Andric 
86*700637cbSDimitry Andric   if (!isUnresolvedExceptionSpec(fpt->getExceptionSpecType()) &&
87*700637cbSDimitry Andric       fpt->isNothrow())
88*700637cbSDimitry Andric     attrs.set(cir::CIRDialect::getNoThrowAttrName(),
89*700637cbSDimitry Andric               mlir::UnitAttr::get(builder.getContext()));
90*700637cbSDimitry Andric }
91*700637cbSDimitry Andric 
92*700637cbSDimitry Andric /// Construct the CIR attribute list of a function or call.
constructAttributeList(CIRGenCalleeInfo calleeInfo,mlir::NamedAttrList & attrs)93*700637cbSDimitry Andric void CIRGenModule::constructAttributeList(CIRGenCalleeInfo calleeInfo,
94*700637cbSDimitry Andric                                           mlir::NamedAttrList &attrs) {
95*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCallConv());
96*700637cbSDimitry Andric   auto sideEffect = cir::SideEffect::All;
97*700637cbSDimitry Andric 
98*700637cbSDimitry Andric   addAttributesFromFunctionProtoType(getBuilder(), attrs,
99*700637cbSDimitry Andric                                      calleeInfo.getCalleeFunctionProtoType());
100*700637cbSDimitry Andric 
101*700637cbSDimitry Andric   const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
102*700637cbSDimitry Andric 
103*700637cbSDimitry Andric   if (targetDecl) {
104*700637cbSDimitry Andric     if (targetDecl->hasAttr<NoThrowAttr>())
105*700637cbSDimitry Andric       attrs.set(cir::CIRDialect::getNoThrowAttrName(),
106*700637cbSDimitry Andric                 mlir::UnitAttr::get(&getMLIRContext()));
107*700637cbSDimitry Andric 
108*700637cbSDimitry Andric     if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
109*700637cbSDimitry Andric       addAttributesFromFunctionProtoType(
110*700637cbSDimitry Andric           getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
111*700637cbSDimitry Andric       assert(!cir::MissingFeatures::opCallAttrs());
112*700637cbSDimitry Andric     }
113*700637cbSDimitry Andric 
114*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallAttrs());
115*700637cbSDimitry Andric 
116*700637cbSDimitry Andric     // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
117*700637cbSDimitry Andric     if (targetDecl->hasAttr<ConstAttr>()) {
118*700637cbSDimitry Andric       // gcc specifies that 'const' functions have greater restrictions than
119*700637cbSDimitry Andric       // 'pure' functions, so they also cannot have infinite loops.
120*700637cbSDimitry Andric       sideEffect = cir::SideEffect::Const;
121*700637cbSDimitry Andric     } else if (targetDecl->hasAttr<PureAttr>()) {
122*700637cbSDimitry Andric       // gcc specifies that 'pure' functions cannot have infinite loops.
123*700637cbSDimitry Andric       sideEffect = cir::SideEffect::Pure;
124*700637cbSDimitry Andric     }
125*700637cbSDimitry Andric 
126*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallAttrs());
127*700637cbSDimitry Andric   }
128*700637cbSDimitry Andric 
129*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallAttrs());
130*700637cbSDimitry Andric 
131*700637cbSDimitry Andric   attrs.set(cir::CIRDialect::getSideEffectAttrName(),
132*700637cbSDimitry Andric             cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
133*700637cbSDimitry Andric }
134*700637cbSDimitry Andric 
135*700637cbSDimitry Andric /// Returns the canonical formal type of the given C++ method.
getFormalType(const CXXMethodDecl * md)136*700637cbSDimitry Andric static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) {
137*700637cbSDimitry Andric   return md->getType()
138*700637cbSDimitry Andric       ->getCanonicalTypeUnqualified()
139*700637cbSDimitry Andric       .getAs<FunctionProtoType>();
140*700637cbSDimitry Andric }
141*700637cbSDimitry Andric 
142*700637cbSDimitry Andric /// Adds the formal parameters in FPT to the given prefix. If any parameter in
143*700637cbSDimitry Andric /// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
144*700637cbSDimitry Andric /// TODO(cir): this should be shared with LLVM codegen
appendParameterTypes(const CIRGenTypes & cgt,SmallVectorImpl<CanQualType> & prefix,CanQual<FunctionProtoType> fpt)145*700637cbSDimitry Andric static void appendParameterTypes(const CIRGenTypes &cgt,
146*700637cbSDimitry Andric                                  SmallVectorImpl<CanQualType> &prefix,
147*700637cbSDimitry Andric                                  CanQual<FunctionProtoType> fpt) {
148*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallExtParameterInfo());
149*700637cbSDimitry Andric   // Fast path: don't touch param info if we don't need to.
150*700637cbSDimitry Andric   if (!fpt->hasExtParameterInfos()) {
151*700637cbSDimitry Andric     prefix.append(fpt->param_type_begin(), fpt->param_type_end());
152*700637cbSDimitry Andric     return;
153*700637cbSDimitry Andric   }
154*700637cbSDimitry Andric 
155*700637cbSDimitry Andric   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
156*700637cbSDimitry Andric }
157*700637cbSDimitry Andric 
158*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeCXXStructorDeclaration(GlobalDecl gd)159*700637cbSDimitry Andric CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
160*700637cbSDimitry Andric   auto *md = cast<CXXMethodDecl>(gd.getDecl());
161*700637cbSDimitry Andric 
162*700637cbSDimitry Andric   llvm::SmallVector<CanQualType, 16> argTypes;
163*700637cbSDimitry Andric   argTypes.push_back(deriveThisType(md->getParent(), md));
164*700637cbSDimitry Andric 
165*700637cbSDimitry Andric   bool passParams = true;
166*700637cbSDimitry Andric 
167*700637cbSDimitry Andric   if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
168*700637cbSDimitry Andric     // A base class inheriting constructor doesn't get forwarded arguments
169*700637cbSDimitry Andric     // needed to construct a virtual base (or base class thereof)
170*700637cbSDimitry Andric     if (cd->getInheritedConstructor())
171*700637cbSDimitry Andric       cgm.errorNYI(cd->getSourceRange(),
172*700637cbSDimitry Andric                    "arrangeCXXStructorDeclaration: inheriting constructor");
173*700637cbSDimitry Andric   }
174*700637cbSDimitry Andric 
175*700637cbSDimitry Andric   CanQual<FunctionProtoType> fpt = getFormalType(md);
176*700637cbSDimitry Andric 
177*700637cbSDimitry Andric   if (passParams)
178*700637cbSDimitry Andric     appendParameterTypes(*this, argTypes, fpt);
179*700637cbSDimitry Andric 
180*700637cbSDimitry Andric   assert(!cir::MissingFeatures::implicitConstructorArgs());
181*700637cbSDimitry Andric 
182*700637cbSDimitry Andric   RequiredArgs required =
183*700637cbSDimitry Andric       (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
184*700637cbSDimitry Andric                                       : RequiredArgs::All);
185*700637cbSDimitry Andric 
186*700637cbSDimitry Andric   CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
187*700637cbSDimitry Andric                            : theCXXABI.hasMostDerivedReturn(gd)
188*700637cbSDimitry Andric                                ? astContext.VoidPtrTy
189*700637cbSDimitry Andric                                : astContext.VoidTy;
190*700637cbSDimitry Andric 
191*700637cbSDimitry Andric   assert(!theCXXABI.hasThisReturn(gd) &&
192*700637cbSDimitry Andric          "Please send PR with a test and remove this");
193*700637cbSDimitry Andric 
194*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
195*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
196*700637cbSDimitry Andric 
197*700637cbSDimitry Andric   return arrangeCIRFunctionInfo(resultType, argTypes, required);
198*700637cbSDimitry Andric }
199*700637cbSDimitry Andric 
200*700637cbSDimitry Andric /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
201*700637cbSDimitry Andric /// qualification. Either or both of `rd` and `md` may be null. A null `rd`
202*700637cbSDimitry Andric /// indicates that there is no meaningful 'this' type, and a null `md` can occur
203*700637cbSDimitry Andric /// when calling a method pointer.
deriveThisType(const CXXRecordDecl * rd,const CXXMethodDecl * md)204*700637cbSDimitry Andric CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,
205*700637cbSDimitry Andric                                         const CXXMethodDecl *md) {
206*700637cbSDimitry Andric   QualType recTy;
207*700637cbSDimitry Andric   if (rd) {
208*700637cbSDimitry Andric     recTy = getASTContext().getTagDeclType(rd)->getCanonicalTypeInternal();
209*700637cbSDimitry Andric   } else {
210*700637cbSDimitry Andric     // This can happen with the MS ABI. It shouldn't need anything more than
211*700637cbSDimitry Andric     // setting recTy to VoidTy here, but we're flagging it for now because we
212*700637cbSDimitry Andric     // don't have the full handling implemented.
213*700637cbSDimitry Andric     cgm.errorNYI("deriveThisType: no record decl");
214*700637cbSDimitry Andric     recTy = getASTContext().VoidTy;
215*700637cbSDimitry Andric   }
216*700637cbSDimitry Andric 
217*700637cbSDimitry Andric   if (md)
218*700637cbSDimitry Andric     recTy = getASTContext().getAddrSpaceQualType(
219*700637cbSDimitry Andric         recTy, md->getMethodQualifiers().getAddressSpace());
220*700637cbSDimitry Andric   return getASTContext().getPointerType(CanQualType::CreateUnsafe(recTy));
221*700637cbSDimitry Andric }
222*700637cbSDimitry Andric 
223*700637cbSDimitry Andric /// Arrange the CIR function layout for a value of the given function type, on
224*700637cbSDimitry Andric /// top of any implicit parameters already stored.
225*700637cbSDimitry Andric static const CIRGenFunctionInfo &
arrangeCIRFunctionInfo(CIRGenTypes & cgt,SmallVectorImpl<CanQualType> & prefix,CanQual<FunctionProtoType> fpt)226*700637cbSDimitry Andric arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix,
227*700637cbSDimitry Andric                        CanQual<FunctionProtoType> fpt) {
228*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
229*700637cbSDimitry Andric   RequiredArgs required =
230*700637cbSDimitry Andric       RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size());
231*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallExtParameterInfo());
232*700637cbSDimitry Andric   appendParameterTypes(cgt, prefix, fpt);
233*700637cbSDimitry Andric   CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
234*700637cbSDimitry Andric   return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
235*700637cbSDimitry Andric }
236*700637cbSDimitry Andric 
emitDelegateCallArg(CallArgList & args,const VarDecl * param,SourceLocation loc)237*700637cbSDimitry Andric void CIRGenFunction::emitDelegateCallArg(CallArgList &args,
238*700637cbSDimitry Andric                                          const VarDecl *param,
239*700637cbSDimitry Andric                                          SourceLocation loc) {
240*700637cbSDimitry Andric   // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
241*700637cbSDimitry Andric   // We need to turn that into an r-value suitable for emitCall
242*700637cbSDimitry Andric   Address local = getAddrOfLocalVar(param);
243*700637cbSDimitry Andric 
244*700637cbSDimitry Andric   QualType type = param->getType();
245*700637cbSDimitry Andric 
246*700637cbSDimitry Andric   if (type->getAsCXXRecordDecl()) {
247*700637cbSDimitry Andric     cgm.errorNYI(param->getSourceRange(),
248*700637cbSDimitry Andric                  "emitDelegateCallArg: record argument");
249*700637cbSDimitry Andric     return;
250*700637cbSDimitry Andric   }
251*700637cbSDimitry Andric 
252*700637cbSDimitry Andric   // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
253*700637cbSDimitry Andric   // argument needs to be the original pointer.
254*700637cbSDimitry Andric   if (type->isReferenceType()) {
255*700637cbSDimitry Andric     args.add(
256*700637cbSDimitry Andric         RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
257*700637cbSDimitry Andric         type);
258*700637cbSDimitry Andric   } else if (getLangOpts().ObjCAutoRefCount) {
259*700637cbSDimitry Andric     cgm.errorNYI(param->getSourceRange(),
260*700637cbSDimitry Andric                  "emitDelegateCallArg: ObjCAutoRefCount");
261*700637cbSDimitry Andric     // For the most part, we just need to load the alloca, except that aggregate
262*700637cbSDimitry Andric     // r-values are actually pointers to temporaries.
263*700637cbSDimitry Andric   } else {
264*700637cbSDimitry Andric     args.add(convertTempToRValue(local, type, loc), type);
265*700637cbSDimitry Andric   }
266*700637cbSDimitry Andric 
267*700637cbSDimitry Andric   // Deactivate the cleanup for the callee-destructed param that was pushed.
268*700637cbSDimitry Andric   assert(!cir::MissingFeatures::thunks());
269*700637cbSDimitry Andric   if (type->isRecordType() &&
270*700637cbSDimitry Andric       type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
271*700637cbSDimitry Andric       param->needsDestruction(getContext())) {
272*700637cbSDimitry Andric     cgm.errorNYI(param->getSourceRange(),
273*700637cbSDimitry Andric                  "emitDelegateCallArg: callee-destructed param");
274*700637cbSDimitry Andric   }
275*700637cbSDimitry Andric }
276*700637cbSDimitry Andric 
277*700637cbSDimitry Andric static const CIRGenFunctionInfo &
arrangeFreeFunctionLikeCall(CIRGenTypes & cgt,CIRGenModule & cgm,const CallArgList & args,const FunctionType * fnType)278*700637cbSDimitry Andric arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
279*700637cbSDimitry Andric                             const CallArgList &args,
280*700637cbSDimitry Andric                             const FunctionType *fnType) {
281*700637cbSDimitry Andric 
282*700637cbSDimitry Andric   RequiredArgs required = RequiredArgs::All;
283*700637cbSDimitry Andric 
284*700637cbSDimitry Andric   if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
285*700637cbSDimitry Andric     if (proto->isVariadic())
286*700637cbSDimitry Andric       required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
287*700637cbSDimitry Andric     if (proto->hasExtParameterInfos())
288*700637cbSDimitry Andric       cgm.errorNYI("call to functions with extra parameter info");
289*700637cbSDimitry Andric   } else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(
290*700637cbSDimitry Andric                  cast<FunctionNoProtoType>(fnType)))
291*700637cbSDimitry Andric     cgm.errorNYI("call to function without a prototype");
292*700637cbSDimitry Andric 
293*700637cbSDimitry Andric   SmallVector<CanQualType, 16> argTypes;
294*700637cbSDimitry Andric   for (const CallArg &arg : args)
295*700637cbSDimitry Andric     argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
296*700637cbSDimitry Andric 
297*700637cbSDimitry Andric   CanQualType retType = fnType->getReturnType()
298*700637cbSDimitry Andric                             ->getCanonicalTypeUnqualified()
299*700637cbSDimitry Andric                             .getUnqualifiedType();
300*700637cbSDimitry Andric 
301*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
302*700637cbSDimitry Andric   return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
303*700637cbSDimitry Andric }
304*700637cbSDimitry Andric 
305*700637cbSDimitry Andric /// Arrange a call to a C++ method, passing the given arguments.
306*700637cbSDimitry Andric ///
307*700637cbSDimitry Andric /// passProtoArgs indicates whether `args` has args for the parameters in the
308*700637cbSDimitry Andric /// given CXXConstructorDecl.
arrangeCXXConstructorCall(const CallArgList & args,const CXXConstructorDecl * d,CXXCtorType ctorKind,bool passProtoArgs)309*700637cbSDimitry Andric const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
310*700637cbSDimitry Andric     const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
311*700637cbSDimitry Andric     bool passProtoArgs) {
312*700637cbSDimitry Andric 
313*700637cbSDimitry Andric   // FIXME: Kill copy.
314*700637cbSDimitry Andric   llvm::SmallVector<CanQualType, 16> argTypes;
315*700637cbSDimitry Andric   for (const auto &arg : args)
316*700637cbSDimitry Andric     argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
317*700637cbSDimitry Andric 
318*700637cbSDimitry Andric   assert(!cir::MissingFeatures::implicitConstructorArgs());
319*700637cbSDimitry Andric   // +1 for implicit this, which should always be args[0]
320*700637cbSDimitry Andric   unsigned totalPrefixArgs = 1;
321*700637cbSDimitry Andric 
322*700637cbSDimitry Andric   CanQual<FunctionProtoType> fpt = getFormalType(d);
323*700637cbSDimitry Andric   RequiredArgs required =
324*700637cbSDimitry Andric       passProtoArgs
325*700637cbSDimitry Andric           ? RequiredArgs::getFromProtoWithExtraSlots(fpt, totalPrefixArgs)
326*700637cbSDimitry Andric           : RequiredArgs::All;
327*700637cbSDimitry Andric 
328*700637cbSDimitry Andric   GlobalDecl gd(d, ctorKind);
329*700637cbSDimitry Andric   if (theCXXABI.hasThisReturn(gd))
330*700637cbSDimitry Andric     cgm.errorNYI(d->getSourceRange(),
331*700637cbSDimitry Andric                  "arrangeCXXConstructorCall: hasThisReturn");
332*700637cbSDimitry Andric   if (theCXXABI.hasMostDerivedReturn(gd))
333*700637cbSDimitry Andric     cgm.errorNYI(d->getSourceRange(),
334*700637cbSDimitry Andric                  "arrangeCXXConstructorCall: hasMostDerivedReturn");
335*700637cbSDimitry Andric   CanQualType resultType = astContext.VoidTy;
336*700637cbSDimitry Andric 
337*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
338*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
339*700637cbSDimitry Andric 
340*700637cbSDimitry Andric   return arrangeCIRFunctionInfo(resultType, argTypes, required);
341*700637cbSDimitry Andric }
342*700637cbSDimitry Andric 
343*700637cbSDimitry Andric /// Arrange a call to a C++ method, passing the given arguments.
344*700637cbSDimitry Andric ///
345*700637cbSDimitry Andric /// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
346*700637cbSDimitry Andric /// does not count `this`.
arrangeCXXMethodCall(const CallArgList & args,const FunctionProtoType * proto,RequiredArgs required,unsigned numPrefixArgs)347*700637cbSDimitry Andric const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXMethodCall(
348*700637cbSDimitry Andric     const CallArgList &args, const FunctionProtoType *proto,
349*700637cbSDimitry Andric     RequiredArgs required, unsigned numPrefixArgs) {
350*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallExtParameterInfo());
351*700637cbSDimitry Andric   assert(numPrefixArgs + 1 <= args.size() &&
352*700637cbSDimitry Andric          "Emitting a call with less args than the required prefix?");
353*700637cbSDimitry Andric 
354*700637cbSDimitry Andric   // FIXME: Kill copy.
355*700637cbSDimitry Andric   llvm::SmallVector<CanQualType, 16> argTypes;
356*700637cbSDimitry Andric   for (const CallArg &arg : args)
357*700637cbSDimitry Andric     argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
358*700637cbSDimitry Andric 
359*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
360*700637cbSDimitry Andric   return arrangeCIRFunctionInfo(proto->getReturnType()
361*700637cbSDimitry Andric                                     ->getCanonicalTypeUnqualified()
362*700637cbSDimitry Andric                                     .getUnqualifiedType(),
363*700637cbSDimitry Andric                                 argTypes, required);
364*700637cbSDimitry Andric }
365*700637cbSDimitry Andric 
366*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeFreeFunctionCall(const CallArgList & args,const FunctionType * fnType)367*700637cbSDimitry Andric CIRGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
368*700637cbSDimitry Andric                                      const FunctionType *fnType) {
369*700637cbSDimitry Andric   return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
370*700637cbSDimitry Andric }
371*700637cbSDimitry Andric 
372*700637cbSDimitry Andric /// Arrange the argument and result information for a declaration or definition
373*700637cbSDimitry Andric /// of the given C++ non-static member function. The member function must be an
374*700637cbSDimitry Andric /// ordinary function, i.e. not a constructor or destructor.
375*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeCXXMethodDeclaration(const CXXMethodDecl * md)376*700637cbSDimitry Andric CIRGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *md) {
377*700637cbSDimitry Andric   assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
378*700637cbSDimitry Andric   assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
379*700637cbSDimitry Andric 
380*700637cbSDimitry Andric   auto prototype =
381*700637cbSDimitry Andric       md->getType()->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();
382*700637cbSDimitry Andric   assert(!cir::MissingFeatures::cudaSupport());
383*700637cbSDimitry Andric 
384*700637cbSDimitry Andric   if (md->isInstance()) {
385*700637cbSDimitry Andric     // The abstract case is perfectly fine.
386*700637cbSDimitry Andric     auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
387*700637cbSDimitry Andric     return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
388*700637cbSDimitry Andric   }
389*700637cbSDimitry Andric 
390*700637cbSDimitry Andric   return arrangeFreeFunctionType(prototype);
391*700637cbSDimitry Andric }
392*700637cbSDimitry Andric 
393*700637cbSDimitry Andric /// Arrange the argument and result information for a call to an unknown C++
394*700637cbSDimitry Andric /// non-static member function of the given abstract type. (A null RD means we
395*700637cbSDimitry Andric /// don't have any meaningful "this" argument type, so fall back to a generic
396*700637cbSDimitry Andric /// pointer type). The member fucntion must be an ordinary function, i.e. not a
397*700637cbSDimitry Andric /// constructor or destructor.
398*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeCXXMethodType(const CXXRecordDecl * rd,const FunctionProtoType * fpt,const CXXMethodDecl * md)399*700637cbSDimitry Andric CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
400*700637cbSDimitry Andric                                   const FunctionProtoType *fpt,
401*700637cbSDimitry Andric                                   const CXXMethodDecl *md) {
402*700637cbSDimitry Andric   llvm::SmallVector<CanQualType, 16> argTypes;
403*700637cbSDimitry Andric 
404*700637cbSDimitry Andric   // Add the 'this' pointer.
405*700637cbSDimitry Andric   argTypes.push_back(deriveThisType(rd, md));
406*700637cbSDimitry Andric 
407*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
408*700637cbSDimitry Andric   return ::arrangeCIRFunctionInfo(
409*700637cbSDimitry Andric       *this, argTypes,
410*700637cbSDimitry Andric       fpt->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
411*700637cbSDimitry Andric }
412*700637cbSDimitry Andric 
413*700637cbSDimitry Andric /// Arrange the argument and result information for the declaration or
414*700637cbSDimitry Andric /// definition of the given function.
415*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeFunctionDeclaration(const FunctionDecl * fd)416*700637cbSDimitry Andric CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl *fd) {
417*700637cbSDimitry Andric   if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
418*700637cbSDimitry Andric     if (md->isInstance())
419*700637cbSDimitry Andric       return arrangeCXXMethodDeclaration(md);
420*700637cbSDimitry Andric 
421*700637cbSDimitry Andric   CanQualType funcTy = fd->getType()->getCanonicalTypeUnqualified();
422*700637cbSDimitry Andric 
423*700637cbSDimitry Andric   assert(isa<FunctionType>(funcTy));
424*700637cbSDimitry Andric   // TODO: setCUDAKernelCallingConvention
425*700637cbSDimitry Andric   assert(!cir::MissingFeatures::cudaSupport());
426*700637cbSDimitry Andric 
427*700637cbSDimitry Andric   // When declaring a function without a prototype, always use a non-variadic
428*700637cbSDimitry Andric   // type.
429*700637cbSDimitry Andric   if (CanQual<FunctionNoProtoType> noProto =
430*700637cbSDimitry Andric           funcTy.getAs<FunctionNoProtoType>()) {
431*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
432*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallFnInfoOpts());
433*700637cbSDimitry Andric     return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
434*700637cbSDimitry Andric                                   RequiredArgs::All);
435*700637cbSDimitry Andric   }
436*700637cbSDimitry Andric 
437*700637cbSDimitry Andric   return arrangeFreeFunctionType(funcTy.castAs<FunctionProtoType>());
438*700637cbSDimitry Andric }
439*700637cbSDimitry Andric 
440*700637cbSDimitry Andric static cir::CIRCallOpInterface
emitCallLikeOp(CIRGenFunction & cgf,mlir::Location callLoc,cir::FuncType indirectFuncTy,mlir::Value indirectFuncVal,cir::FuncOp directFuncOp,const SmallVectorImpl<mlir::Value> & cirCallArgs,const mlir::NamedAttrList & attrs)441*700637cbSDimitry Andric emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
442*700637cbSDimitry Andric                cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
443*700637cbSDimitry Andric                cir::FuncOp directFuncOp,
444*700637cbSDimitry Andric                const SmallVectorImpl<mlir::Value> &cirCallArgs,
445*700637cbSDimitry Andric                const mlir::NamedAttrList &attrs) {
446*700637cbSDimitry Andric   CIRGenBuilderTy &builder = cgf.getBuilder();
447*700637cbSDimitry Andric 
448*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallSurroundingTry());
449*700637cbSDimitry Andric   assert(!cir::MissingFeatures::invokeOp());
450*700637cbSDimitry Andric 
451*700637cbSDimitry Andric   assert(builder.getInsertionBlock() && "expected valid basic block");
452*700637cbSDimitry Andric 
453*700637cbSDimitry Andric   cir::CallOp op;
454*700637cbSDimitry Andric   if (indirectFuncTy) {
455*700637cbSDimitry Andric     // TODO(cir): Set calling convention for indirect calls.
456*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallCallConv());
457*700637cbSDimitry Andric     op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
458*700637cbSDimitry Andric                                       cirCallArgs, attrs);
459*700637cbSDimitry Andric   } else {
460*700637cbSDimitry Andric     op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);
461*700637cbSDimitry Andric   }
462*700637cbSDimitry Andric 
463*700637cbSDimitry Andric   return op;
464*700637cbSDimitry Andric }
465*700637cbSDimitry Andric 
466*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt)467*700637cbSDimitry Andric CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt) {
468*700637cbSDimitry Andric   SmallVector<CanQualType, 16> argTypes;
469*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
470*700637cbSDimitry Andric   return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
471*700637cbSDimitry Andric }
472*700637cbSDimitry Andric 
473*700637cbSDimitry Andric const CIRGenFunctionInfo &
arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt)474*700637cbSDimitry Andric CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
475*700637cbSDimitry Andric   CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
476*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallFnInfoOpts());
477*700637cbSDimitry Andric   return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
478*700637cbSDimitry Andric }
479*700637cbSDimitry Andric 
emitCall(const CIRGenFunctionInfo & funcInfo,const CIRGenCallee & callee,ReturnValueSlot returnValue,const CallArgList & args,cir::CIRCallOpInterface * callOp,mlir::Location loc)480*700637cbSDimitry Andric RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
481*700637cbSDimitry Andric                                 const CIRGenCallee &callee,
482*700637cbSDimitry Andric                                 ReturnValueSlot returnValue,
483*700637cbSDimitry Andric                                 const CallArgList &args,
484*700637cbSDimitry Andric                                 cir::CIRCallOpInterface *callOp,
485*700637cbSDimitry Andric                                 mlir::Location loc) {
486*700637cbSDimitry Andric   QualType retTy = funcInfo.getReturnType();
487*700637cbSDimitry Andric   cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
488*700637cbSDimitry Andric 
489*700637cbSDimitry Andric   SmallVector<mlir::Value, 16> cirCallArgs(args.size());
490*700637cbSDimitry Andric 
491*700637cbSDimitry Andric   assert(!cir::MissingFeatures::emitLifetimeMarkers());
492*700637cbSDimitry Andric 
493*700637cbSDimitry Andric   // Translate all of the arguments as necessary to match the CIR lowering.
494*700637cbSDimitry Andric   for (auto [argNo, arg, canQualArgType] :
495*700637cbSDimitry Andric        llvm::enumerate(args, funcInfo.argTypes())) {
496*700637cbSDimitry Andric 
497*700637cbSDimitry Andric     // Insert a padding argument to ensure proper alignment.
498*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallPaddingArgs());
499*700637cbSDimitry Andric 
500*700637cbSDimitry Andric     mlir::Type argType = convertType(canQualArgType);
501*700637cbSDimitry Andric     if (!mlir::isa<cir::RecordType>(argType)) {
502*700637cbSDimitry Andric       mlir::Value v;
503*700637cbSDimitry Andric       if (arg.isAggregate())
504*700637cbSDimitry Andric         cgm.errorNYI(loc, "emitCall: aggregate call argument");
505*700637cbSDimitry Andric       v = arg.getKnownRValue().getValue();
506*700637cbSDimitry Andric 
507*700637cbSDimitry Andric       // We might have to widen integers, but we should never truncate.
508*700637cbSDimitry Andric       if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
509*700637cbSDimitry Andric         cgm.errorNYI(loc, "emitCall: widening integer call argument");
510*700637cbSDimitry Andric 
511*700637cbSDimitry Andric       // If the argument doesn't match, perform a bitcast to coerce it. This
512*700637cbSDimitry Andric       // can happen due to trivial type mismatches.
513*700637cbSDimitry Andric       // TODO(cir): When getFunctionType is added, assert that this isn't
514*700637cbSDimitry Andric       // needed.
515*700637cbSDimitry Andric       assert(!cir::MissingFeatures::opCallBitcastArg());
516*700637cbSDimitry Andric       cirCallArgs[argNo] = v;
517*700637cbSDimitry Andric     } else {
518*700637cbSDimitry Andric       Address src = Address::invalid();
519*700637cbSDimitry Andric       if (!arg.isAggregate())
520*700637cbSDimitry Andric         cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
521*700637cbSDimitry Andric       else
522*700637cbSDimitry Andric         src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
523*700637cbSDimitry Andric                               : arg.getKnownRValue().getAggregateAddress();
524*700637cbSDimitry Andric 
525*700637cbSDimitry Andric       // Fast-isel and the optimizer generally like scalar values better than
526*700637cbSDimitry Andric       // FCAs, so we flatten them if this is safe to do for this argument.
527*700637cbSDimitry Andric       auto argRecordTy = cast<cir::RecordType>(argType);
528*700637cbSDimitry Andric       mlir::Type srcTy = src.getElementType();
529*700637cbSDimitry Andric       // FIXME(cir): get proper location for each argument.
530*700637cbSDimitry Andric       mlir::Location argLoc = loc;
531*700637cbSDimitry Andric 
532*700637cbSDimitry Andric       // If the source type is smaller than the destination type of the
533*700637cbSDimitry Andric       // coerce-to logic, copy the source value into a temp alloca the size
534*700637cbSDimitry Andric       // of the destination type to allow loading all of it. The bits past
535*700637cbSDimitry Andric       // the source value are left undef.
536*700637cbSDimitry Andric       // FIXME(cir): add data layout info and compare sizes instead of
537*700637cbSDimitry Andric       // matching the types.
538*700637cbSDimitry Andric       //
539*700637cbSDimitry Andric       // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
540*700637cbSDimitry Andric       // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
541*700637cbSDimitry Andric       // if (SrcSize < DstSize) {
542*700637cbSDimitry Andric       assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
543*700637cbSDimitry Andric       if (srcTy != argRecordTy) {
544*700637cbSDimitry Andric         cgm.errorNYI(loc, "emitCall: source type does not match argument type");
545*700637cbSDimitry Andric       } else {
546*700637cbSDimitry Andric         // FIXME(cir): this currently only runs when the types are exactly the
547*700637cbSDimitry Andric         // same, but should be when alloc sizes are the same, fix this as soon
548*700637cbSDimitry Andric         // as datalayout gets introduced.
549*700637cbSDimitry Andric         assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
550*700637cbSDimitry Andric       }
551*700637cbSDimitry Andric 
552*700637cbSDimitry Andric       // assert(NumCIRArgs == STy.getMembers().size());
553*700637cbSDimitry Andric       // In LLVMGen: Still only pass the struct without any gaps but mark it
554*700637cbSDimitry Andric       // as such somehow.
555*700637cbSDimitry Andric       //
556*700637cbSDimitry Andric       // In CIRGen: Emit a load from the "whole" struct,
557*700637cbSDimitry Andric       // which shall be broken later by some lowering step into multiple
558*700637cbSDimitry Andric       // loads.
559*700637cbSDimitry Andric       assert(!cir::MissingFeatures::lowerAggregateLoadStore());
560*700637cbSDimitry Andric       cirCallArgs[argNo] = builder.createLoad(argLoc, src);
561*700637cbSDimitry Andric     }
562*700637cbSDimitry Andric   }
563*700637cbSDimitry Andric 
564*700637cbSDimitry Andric   const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
565*700637cbSDimitry Andric   mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
566*700637cbSDimitry Andric 
567*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallInAlloca());
568*700637cbSDimitry Andric 
569*700637cbSDimitry Andric   mlir::NamedAttrList attrs;
570*700637cbSDimitry Andric   StringRef funcName;
571*700637cbSDimitry Andric   if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
572*700637cbSDimitry Andric     funcName = calleeFuncOp.getName();
573*700637cbSDimitry Andric 
574*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCallConv());
575*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallAttrs());
576*700637cbSDimitry Andric   cgm.constructAttributeList(callee.getAbstractInfo(), attrs);
577*700637cbSDimitry Andric 
578*700637cbSDimitry Andric   assert(!cir::MissingFeatures::invokeOp());
579*700637cbSDimitry Andric 
580*700637cbSDimitry Andric   cir::FuncType indirectFuncTy;
581*700637cbSDimitry Andric   mlir::Value indirectFuncVal;
582*700637cbSDimitry Andric   cir::FuncOp directFuncOp;
583*700637cbSDimitry Andric   if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
584*700637cbSDimitry Andric     directFuncOp = fnOp;
585*700637cbSDimitry Andric   } else {
586*700637cbSDimitry Andric     [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
587*700637cbSDimitry Andric         calleePtr->getResultTypes();
588*700637cbSDimitry Andric     [[maybe_unused]] auto funcPtrTy =
589*700637cbSDimitry Andric         mlir::dyn_cast<cir::PointerType>(resultTypes.front());
590*700637cbSDimitry Andric     assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
591*700637cbSDimitry Andric            "expected pointer to function");
592*700637cbSDimitry Andric 
593*700637cbSDimitry Andric     indirectFuncTy = cirFuncTy;
594*700637cbSDimitry Andric     indirectFuncVal = calleePtr->getResult(0);
595*700637cbSDimitry Andric   }
596*700637cbSDimitry Andric 
597*700637cbSDimitry Andric   mlir::Location callLoc = loc;
598*700637cbSDimitry Andric   cir::CIRCallOpInterface theCall =
599*700637cbSDimitry Andric       emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
600*700637cbSDimitry Andric                      cirCallArgs, attrs);
601*700637cbSDimitry Andric 
602*700637cbSDimitry Andric   if (callOp)
603*700637cbSDimitry Andric     *callOp = theCall;
604*700637cbSDimitry Andric 
605*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallMustTail());
606*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallReturn());
607*700637cbSDimitry Andric 
608*700637cbSDimitry Andric   mlir::Type retCIRTy = convertType(retTy);
609*700637cbSDimitry Andric   if (isa<cir::VoidType>(retCIRTy))
610*700637cbSDimitry Andric     return getUndefRValue(retTy);
611*700637cbSDimitry Andric   switch (getEvaluationKind(retTy)) {
612*700637cbSDimitry Andric   case cir::TEK_Aggregate: {
613*700637cbSDimitry Andric     Address destPtr = returnValue.getValue();
614*700637cbSDimitry Andric 
615*700637cbSDimitry Andric     if (!destPtr.isValid())
616*700637cbSDimitry Andric       destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
617*700637cbSDimitry Andric 
618*700637cbSDimitry Andric     mlir::ResultRange results = theCall->getOpResults();
619*700637cbSDimitry Andric     assert(results.size() <= 1 && "multiple returns from a call");
620*700637cbSDimitry Andric 
621*700637cbSDimitry Andric     SourceLocRAIIObject loc{*this, callLoc};
622*700637cbSDimitry Andric     emitAggregateStore(results[0], destPtr);
623*700637cbSDimitry Andric     return RValue::getAggregate(destPtr);
624*700637cbSDimitry Andric   }
625*700637cbSDimitry Andric   case cir::TEK_Scalar: {
626*700637cbSDimitry Andric     mlir::ResultRange results = theCall->getOpResults();
627*700637cbSDimitry Andric     assert(results.size() == 1 && "unexpected number of returns");
628*700637cbSDimitry Andric 
629*700637cbSDimitry Andric     // If the argument doesn't match, perform a bitcast to coerce it. This
630*700637cbSDimitry Andric     // can happen due to trivial type mismatches.
631*700637cbSDimitry Andric     if (results[0].getType() != retCIRTy)
632*700637cbSDimitry Andric       cgm.errorNYI(loc, "bitcast on function return value");
633*700637cbSDimitry Andric 
634*700637cbSDimitry Andric     mlir::Region *region = builder.getBlock()->getParent();
635*700637cbSDimitry Andric     if (region != theCall->getParentRegion())
636*700637cbSDimitry Andric       cgm.errorNYI(loc, "function calls with cleanup");
637*700637cbSDimitry Andric 
638*700637cbSDimitry Andric     return RValue::get(results[0]);
639*700637cbSDimitry Andric   }
640*700637cbSDimitry Andric   case cir::TEK_Complex:
641*700637cbSDimitry Andric     cgm.errorNYI(loc, "unsupported evaluation kind of function call result");
642*700637cbSDimitry Andric     return getUndefRValue(retTy);
643*700637cbSDimitry Andric   }
644*700637cbSDimitry Andric   llvm_unreachable("Invalid evaluation kind");
645*700637cbSDimitry Andric }
646*700637cbSDimitry Andric 
emitCallArg(CallArgList & args,const clang::Expr * e,clang::QualType argType)647*700637cbSDimitry Andric void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
648*700637cbSDimitry Andric                                  clang::QualType argType) {
649*700637cbSDimitry Andric   assert(argType->isReferenceType() == e->isGLValue() &&
650*700637cbSDimitry Andric          "reference binding to unmaterialized r-value!");
651*700637cbSDimitry Andric 
652*700637cbSDimitry Andric   if (e->isGLValue()) {
653*700637cbSDimitry Andric     assert(e->getObjectKind() == OK_Ordinary);
654*700637cbSDimitry Andric     return args.add(emitReferenceBindingToExpr(e), argType);
655*700637cbSDimitry Andric   }
656*700637cbSDimitry Andric 
657*700637cbSDimitry Andric   bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
658*700637cbSDimitry Andric 
659*700637cbSDimitry Andric   // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
660*700637cbSDimitry Andric   // However, we still have to push an EH-only cleanup in case we unwind before
661*700637cbSDimitry Andric   // we make it to the call.
662*700637cbSDimitry Andric   if (argType->isRecordType() &&
663*700637cbSDimitry Andric       argType->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
664*700637cbSDimitry Andric     assert(!cir::MissingFeatures::msabi());
665*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
666*700637cbSDimitry Andric   }
667*700637cbSDimitry Andric 
668*700637cbSDimitry Andric   if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
669*700637cbSDimitry Andric       cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
670*700637cbSDimitry Andric     LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
671*700637cbSDimitry Andric     assert(lv.isSimple());
672*700637cbSDimitry Andric     args.addUncopiedAggregate(lv, argType);
673*700637cbSDimitry Andric     return;
674*700637cbSDimitry Andric   }
675*700637cbSDimitry Andric 
676*700637cbSDimitry Andric   args.add(emitAnyExprToTemp(e), argType);
677*700637cbSDimitry Andric }
678*700637cbSDimitry Andric 
getVarArgType(const Expr * arg)679*700637cbSDimitry Andric QualType CIRGenFunction::getVarArgType(const Expr *arg) {
680*700637cbSDimitry Andric   // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
681*700637cbSDimitry Andric   // implicitly widens null pointer constants that are arguments to varargs
682*700637cbSDimitry Andric   // functions to pointer-sized ints.
683*700637cbSDimitry Andric   if (!getTarget().getTriple().isOSWindows())
684*700637cbSDimitry Andric     return arg->getType();
685*700637cbSDimitry Andric 
686*700637cbSDimitry Andric   assert(!cir::MissingFeatures::msabi());
687*700637cbSDimitry Andric   cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
688*700637cbSDimitry Andric   return arg->getType();
689*700637cbSDimitry Andric }
690*700637cbSDimitry Andric 
691*700637cbSDimitry Andric /// Similar to emitAnyExpr(), however, the result will always be accessible
692*700637cbSDimitry Andric /// even if no aggregate location is provided.
emitAnyExprToTemp(const Expr * e)693*700637cbSDimitry Andric RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) {
694*700637cbSDimitry Andric   AggValueSlot aggSlot = AggValueSlot::ignored();
695*700637cbSDimitry Andric 
696*700637cbSDimitry Andric   if (hasAggregateEvaluationKind(e->getType()))
697*700637cbSDimitry Andric     aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
698*700637cbSDimitry Andric                             getCounterAggTmpAsString());
699*700637cbSDimitry Andric 
700*700637cbSDimitry Andric   return emitAnyExpr(e, aggSlot);
701*700637cbSDimitry Andric }
702*700637cbSDimitry Andric 
emitCallArgs(CallArgList & args,PrototypeWrapper prototype,llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,AbstractCallee callee,unsigned paramsToSkip)703*700637cbSDimitry Andric void CIRGenFunction::emitCallArgs(
704*700637cbSDimitry Andric     CallArgList &args, PrototypeWrapper prototype,
705*700637cbSDimitry Andric     llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
706*700637cbSDimitry Andric     AbstractCallee callee, unsigned paramsToSkip) {
707*700637cbSDimitry Andric   llvm::SmallVector<QualType, 16> argTypes;
708*700637cbSDimitry Andric 
709*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallCallConv());
710*700637cbSDimitry Andric 
711*700637cbSDimitry Andric   // First, if a prototype was provided, use those argument types.
712*700637cbSDimitry Andric   bool isVariadic = false;
713*700637cbSDimitry Andric   if (prototype.p) {
714*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallObjCMethod());
715*700637cbSDimitry Andric 
716*700637cbSDimitry Andric     const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
717*700637cbSDimitry Andric     isVariadic = fpt->isVariadic();
718*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallCallConv());
719*700637cbSDimitry Andric     argTypes.assign(fpt->param_type_begin() + paramsToSkip,
720*700637cbSDimitry Andric                     fpt->param_type_end());
721*700637cbSDimitry Andric   }
722*700637cbSDimitry Andric 
723*700637cbSDimitry Andric   // If we still have any arguments, emit them using the type of the argument.
724*700637cbSDimitry Andric   for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
725*700637cbSDimitry Andric     argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
726*700637cbSDimitry Andric   assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
727*700637cbSDimitry Andric 
728*700637cbSDimitry Andric   // We must evaluate arguments from right to left in the MS C++ ABI, because
729*700637cbSDimitry Andric   // arguments are destroyed left to right in the callee. As a special case,
730*700637cbSDimitry Andric   // there are certain language constructs taht require left-to-right
731*700637cbSDimitry Andric   // evaluation, and in those cases we consider the evaluation order requirement
732*700637cbSDimitry Andric   // to trump the "destruction order is reverse construction order" guarantee.
733*700637cbSDimitry Andric   auto leftToRight = true;
734*700637cbSDimitry Andric   assert(!cir::MissingFeatures::msabi());
735*700637cbSDimitry Andric 
736*700637cbSDimitry Andric   auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
737*700637cbSDimitry Andric                                          RValue emittedArg) {
738*700637cbSDimitry Andric     if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
739*700637cbSDimitry Andric       return;
740*700637cbSDimitry Andric     auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
741*700637cbSDimitry Andric     if (!ps)
742*700637cbSDimitry Andric       return;
743*700637cbSDimitry Andric 
744*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opCallImplicitObjectSizeArgs());
745*700637cbSDimitry Andric     cgm.errorNYI("emit implicit object size for call arg");
746*700637cbSDimitry Andric   };
747*700637cbSDimitry Andric 
748*700637cbSDimitry Andric   // Evaluate each argument in the appropriate order.
749*700637cbSDimitry Andric   size_t callArgsStart = args.size();
750*700637cbSDimitry Andric   for (size_t i = 0; i != argTypes.size(); ++i) {
751*700637cbSDimitry Andric     size_t idx = leftToRight ? i : argTypes.size() - i - 1;
752*700637cbSDimitry Andric     CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
753*700637cbSDimitry Andric     size_t initialArgSize = args.size();
754*700637cbSDimitry Andric 
755*700637cbSDimitry Andric     emitCallArg(args, *currentArg, argTypes[idx]);
756*700637cbSDimitry Andric 
757*700637cbSDimitry Andric     // In particular, we depend on it being the last arg in Args, and the
758*700637cbSDimitry Andric     // objectsize bits depend on there only being one arg if !LeftToRight.
759*700637cbSDimitry Andric     assert(initialArgSize + 1 == args.size() &&
760*700637cbSDimitry Andric            "The code below depends on only adding one arg per emitCallArg");
761*700637cbSDimitry Andric     (void)initialArgSize;
762*700637cbSDimitry Andric 
763*700637cbSDimitry Andric     // Since pointer argument are never emitted as LValue, it is safe to emit
764*700637cbSDimitry Andric     // non-null argument check for r-value only.
765*700637cbSDimitry Andric     if (!args.back().hasLValue()) {
766*700637cbSDimitry Andric       RValue rvArg = args.back().getKnownRValue();
767*700637cbSDimitry Andric       assert(!cir::MissingFeatures::sanitizers());
768*700637cbSDimitry Andric       maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
769*700637cbSDimitry Andric     }
770*700637cbSDimitry Andric 
771*700637cbSDimitry Andric     if (!leftToRight)
772*700637cbSDimitry Andric       std::reverse(args.begin() + callArgsStart, args.end());
773*700637cbSDimitry Andric   }
774*700637cbSDimitry Andric }
775