xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===--- CIRGenExprCXX.cpp - Emit CIR Code for C++ expressions ------------===//
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 // This contains code dealing with code generation of C++ expressions
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CIRGenCXXABI.h"
14*700637cbSDimitry Andric #include "CIRGenFunction.h"
15*700637cbSDimitry Andric 
16*700637cbSDimitry Andric #include "clang/AST/DeclCXX.h"
17*700637cbSDimitry Andric #include "clang/AST/ExprCXX.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 namespace {
24*700637cbSDimitry Andric struct MemberCallInfo {
25*700637cbSDimitry Andric   RequiredArgs reqArgs;
26*700637cbSDimitry Andric   // Number of prefix arguments for the call. Ignores the `this` pointer.
27*700637cbSDimitry Andric   unsigned prefixSize;
28*700637cbSDimitry Andric };
29*700637cbSDimitry Andric } // namespace
30*700637cbSDimitry Andric 
commonBuildCXXMemberOrOperatorCall(CIRGenFunction & cgf,const CXXMethodDecl * md,mlir::Value thisPtr,mlir::Value implicitParam,QualType implicitParamTy,const CallExpr * ce,CallArgList & args,CallArgList * rtlArgs)31*700637cbSDimitry Andric static MemberCallInfo commonBuildCXXMemberOrOperatorCall(
32*700637cbSDimitry Andric     CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr,
33*700637cbSDimitry Andric     mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce,
34*700637cbSDimitry Andric     CallArgList &args, CallArgList *rtlArgs) {
35*700637cbSDimitry Andric   assert(ce == nullptr || isa<CXXMemberCallExpr>(ce) ||
36*700637cbSDimitry Andric          isa<CXXOperatorCallExpr>(ce));
37*700637cbSDimitry Andric   assert(md->isInstance() &&
38*700637cbSDimitry Andric          "Trying to emit a member or operator call expr on a static method!");
39*700637cbSDimitry Andric 
40*700637cbSDimitry Andric   // Push the this ptr.
41*700637cbSDimitry Andric   const CXXRecordDecl *rd =
42*700637cbSDimitry Andric       cgf.cgm.getCXXABI().getThisArgumentTypeForMethod(md);
43*700637cbSDimitry Andric   args.add(RValue::get(thisPtr), cgf.getTypes().deriveThisType(rd, md));
44*700637cbSDimitry Andric 
45*700637cbSDimitry Andric   // If there is an implicit parameter (e.g. VTT), emit it.
46*700637cbSDimitry Andric   if (implicitParam) {
47*700637cbSDimitry Andric     args.add(RValue::get(implicitParam), implicitParamTy);
48*700637cbSDimitry Andric   }
49*700637cbSDimitry Andric 
50*700637cbSDimitry Andric   const auto *fpt = md->getType()->castAs<FunctionProtoType>();
51*700637cbSDimitry Andric   RequiredArgs required =
52*700637cbSDimitry Andric       RequiredArgs::getFromProtoWithExtraSlots(fpt, args.size());
53*700637cbSDimitry Andric   unsigned prefixSize = args.size() - 1;
54*700637cbSDimitry Andric 
55*700637cbSDimitry Andric   // Add the rest of the call args
56*700637cbSDimitry Andric   if (rtlArgs) {
57*700637cbSDimitry Andric     // Special case: if the caller emitted the arguments right-to-left already
58*700637cbSDimitry Andric     // (prior to emitting the *this argument), we're done. This happens for
59*700637cbSDimitry Andric     // assignment operators.
60*700637cbSDimitry Andric     args.addFrom(*rtlArgs);
61*700637cbSDimitry Andric   } else if (ce) {
62*700637cbSDimitry Andric     // Special case: skip first argument of CXXOperatorCall (it is "this").
63*700637cbSDimitry Andric     unsigned argsToSkip = isa<CXXOperatorCallExpr>(ce) ? 1 : 0;
64*700637cbSDimitry Andric     cgf.emitCallArgs(args, fpt, drop_begin(ce->arguments(), argsToSkip),
65*700637cbSDimitry Andric                      ce->getDirectCallee());
66*700637cbSDimitry Andric   } else {
67*700637cbSDimitry Andric     assert(
68*700637cbSDimitry Andric         fpt->getNumParams() == 0 &&
69*700637cbSDimitry Andric         "No CallExpr specified for function with non-zero number of arguments");
70*700637cbSDimitry Andric   }
71*700637cbSDimitry Andric 
72*700637cbSDimitry Andric   //  return {required, prefixSize};
73*700637cbSDimitry Andric   return {required, prefixSize};
74*700637cbSDimitry Andric }
75*700637cbSDimitry Andric 
emitCXXMemberOrOperatorMemberCallExpr(const CallExpr * ce,const CXXMethodDecl * md,ReturnValueSlot returnValue,bool hasQualifier,NestedNameSpecifier * qualifier,bool isArrow,const Expr * base)76*700637cbSDimitry Andric RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
77*700637cbSDimitry Andric     const CallExpr *ce, const CXXMethodDecl *md, ReturnValueSlot returnValue,
78*700637cbSDimitry Andric     bool hasQualifier, NestedNameSpecifier *qualifier, bool isArrow,
79*700637cbSDimitry Andric     const Expr *base) {
80*700637cbSDimitry Andric   assert(isa<CXXMemberCallExpr>(ce) || isa<CXXOperatorCallExpr>(ce));
81*700637cbSDimitry Andric 
82*700637cbSDimitry Andric   if (md->isVirtual()) {
83*700637cbSDimitry Andric     cgm.errorNYI(ce->getSourceRange(),
84*700637cbSDimitry Andric                  "emitCXXMemberOrOperatorMemberCallExpr: virtual call");
85*700637cbSDimitry Andric     return RValue::get(nullptr);
86*700637cbSDimitry Andric   }
87*700637cbSDimitry Andric 
88*700637cbSDimitry Andric   // Note on trivial assignment
89*700637cbSDimitry Andric   // --------------------------
90*700637cbSDimitry Andric   // Classic codegen avoids generating the trivial copy/move assignment operator
91*700637cbSDimitry Andric   // when it isn't necessary, choosing instead to just produce IR with an
92*700637cbSDimitry Andric   // equivalent effect. We have chosen not to do that in CIR, instead emitting
93*700637cbSDimitry Andric   // trivial copy/move assignment operators and allowing later transformations
94*700637cbSDimitry Andric   // to optimize them away if appropriate.
95*700637cbSDimitry Andric 
96*700637cbSDimitry Andric   // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
97*700637cbSDimitry Andric   // operator before the LHS.
98*700637cbSDimitry Andric   CallArgList rtlArgStorage;
99*700637cbSDimitry Andric   CallArgList *rtlArgs = nullptr;
100*700637cbSDimitry Andric   if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
101*700637cbSDimitry Andric     if (oce->isAssignmentOp()) {
102*700637cbSDimitry Andric       rtlArgs = &rtlArgStorage;
103*700637cbSDimitry Andric       emitCallArgs(*rtlArgs, md->getType()->castAs<FunctionProtoType>(),
104*700637cbSDimitry Andric                    drop_begin(ce->arguments(), 1), ce->getDirectCallee(),
105*700637cbSDimitry Andric                    /*ParamsToSkip*/ 0);
106*700637cbSDimitry Andric     }
107*700637cbSDimitry Andric   }
108*700637cbSDimitry Andric 
109*700637cbSDimitry Andric   LValue thisPtr;
110*700637cbSDimitry Andric   if (isArrow) {
111*700637cbSDimitry Andric     LValueBaseInfo baseInfo;
112*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opTBAA());
113*700637cbSDimitry Andric     Address thisValue = emitPointerWithAlignment(base, &baseInfo);
114*700637cbSDimitry Andric     thisPtr = makeAddrLValue(thisValue, base->getType(), baseInfo);
115*700637cbSDimitry Andric   } else {
116*700637cbSDimitry Andric     thisPtr = emitLValue(base);
117*700637cbSDimitry Andric   }
118*700637cbSDimitry Andric 
119*700637cbSDimitry Andric   if (isa<CXXConstructorDecl>(md)) {
120*700637cbSDimitry Andric     cgm.errorNYI(ce->getSourceRange(),
121*700637cbSDimitry Andric                  "emitCXXMemberOrOperatorMemberCallExpr: constructor call");
122*700637cbSDimitry Andric     return RValue::get(nullptr);
123*700637cbSDimitry Andric   }
124*700637cbSDimitry Andric 
125*700637cbSDimitry Andric   if ((md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion())) &&
126*700637cbSDimitry Andric       isa<CXXDestructorDecl>(md))
127*700637cbSDimitry Andric     return RValue::get(nullptr);
128*700637cbSDimitry Andric 
129*700637cbSDimitry Andric   // Compute the function type we're calling
130*700637cbSDimitry Andric   const CXXMethodDecl *calleeDecl = md;
131*700637cbSDimitry Andric   const CIRGenFunctionInfo *fInfo = nullptr;
132*700637cbSDimitry Andric   if (isa<CXXDestructorDecl>(calleeDecl)) {
133*700637cbSDimitry Andric     cgm.errorNYI(ce->getSourceRange(),
134*700637cbSDimitry Andric                  "emitCXXMemberOrOperatorMemberCallExpr: destructor call");
135*700637cbSDimitry Andric     return RValue::get(nullptr);
136*700637cbSDimitry Andric   }
137*700637cbSDimitry Andric 
138*700637cbSDimitry Andric   fInfo = &cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);
139*700637cbSDimitry Andric 
140*700637cbSDimitry Andric   mlir::Type ty = cgm.getTypes().getFunctionType(*fInfo);
141*700637cbSDimitry Andric 
142*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
143*700637cbSDimitry Andric   assert(!cir::MissingFeatures::emitTypeCheck());
144*700637cbSDimitry Andric 
145*700637cbSDimitry Andric   if (isa<CXXDestructorDecl>(calleeDecl)) {
146*700637cbSDimitry Andric     cgm.errorNYI(ce->getSourceRange(),
147*700637cbSDimitry Andric                  "emitCXXMemberOrOperatorMemberCallExpr: destructor call");
148*700637cbSDimitry Andric     return RValue::get(nullptr);
149*700637cbSDimitry Andric   }
150*700637cbSDimitry Andric 
151*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
152*700637cbSDimitry Andric   if (getLangOpts().AppleKext) {
153*700637cbSDimitry Andric     cgm.errorNYI(ce->getSourceRange(),
154*700637cbSDimitry Andric                  "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");
155*700637cbSDimitry Andric     return RValue::get(nullptr);
156*700637cbSDimitry Andric   }
157*700637cbSDimitry Andric   CIRGenCallee callee =
158*700637cbSDimitry Andric       CIRGenCallee::forDirect(cgm.getAddrOfFunction(md, ty), GlobalDecl(md));
159*700637cbSDimitry Andric 
160*700637cbSDimitry Andric   return emitCXXMemberOrOperatorCall(
161*700637cbSDimitry Andric       calleeDecl, callee, returnValue, thisPtr.getPointer(),
162*700637cbSDimitry Andric       /*ImplicitParam=*/nullptr, QualType(), ce, rtlArgs);
163*700637cbSDimitry Andric }
164*700637cbSDimitry Andric 
165*700637cbSDimitry Andric RValue
emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr * e,const CXXMethodDecl * md,ReturnValueSlot returnValue)166*700637cbSDimitry Andric CIRGenFunction::emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e,
167*700637cbSDimitry Andric                                               const CXXMethodDecl *md,
168*700637cbSDimitry Andric                                               ReturnValueSlot returnValue) {
169*700637cbSDimitry Andric   assert(md->isInstance() &&
170*700637cbSDimitry Andric          "Trying to emit a member call expr on a static method!");
171*700637cbSDimitry Andric   return emitCXXMemberOrOperatorMemberCallExpr(
172*700637cbSDimitry Andric       e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/nullptr,
173*700637cbSDimitry Andric       /*IsArrow=*/false, e->getArg(0));
174*700637cbSDimitry Andric }
175*700637cbSDimitry Andric 
emitCXXMemberOrOperatorCall(const CXXMethodDecl * md,const CIRGenCallee & callee,ReturnValueSlot returnValue,mlir::Value thisPtr,mlir::Value implicitParam,QualType implicitParamTy,const CallExpr * ce,CallArgList * rtlArgs)176*700637cbSDimitry Andric RValue CIRGenFunction::emitCXXMemberOrOperatorCall(
177*700637cbSDimitry Andric     const CXXMethodDecl *md, const CIRGenCallee &callee,
178*700637cbSDimitry Andric     ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam,
179*700637cbSDimitry Andric     QualType implicitParamTy, const CallExpr *ce, CallArgList *rtlArgs) {
180*700637cbSDimitry Andric   const auto *fpt = md->getType()->castAs<FunctionProtoType>();
181*700637cbSDimitry Andric   CallArgList args;
182*700637cbSDimitry Andric   MemberCallInfo callInfo = commonBuildCXXMemberOrOperatorCall(
183*700637cbSDimitry Andric       *this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);
184*700637cbSDimitry Andric   auto &fnInfo = cgm.getTypes().arrangeCXXMethodCall(
185*700637cbSDimitry Andric       args, fpt, callInfo.reqArgs, callInfo.prefixSize);
186*700637cbSDimitry Andric   assert((ce || currSrcLoc) && "expected source location");
187*700637cbSDimitry Andric   mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
188*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallMustTail());
189*700637cbSDimitry Andric   return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
190*700637cbSDimitry Andric }
191*700637cbSDimitry Andric 
emitCXXNewAllocSize(CIRGenFunction & cgf,const CXXNewExpr * e,unsigned minElements,mlir::Value & numElements,mlir::Value & sizeWithoutCookie)192*700637cbSDimitry Andric static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
193*700637cbSDimitry Andric                                        unsigned minElements,
194*700637cbSDimitry Andric                                        mlir::Value &numElements,
195*700637cbSDimitry Andric                                        mlir::Value &sizeWithoutCookie) {
196*700637cbSDimitry Andric   QualType type = e->getAllocatedType();
197*700637cbSDimitry Andric   mlir::Location loc = cgf.getLoc(e->getSourceRange());
198*700637cbSDimitry Andric 
199*700637cbSDimitry Andric   if (!e->isArray()) {
200*700637cbSDimitry Andric     CharUnits typeSize = cgf.getContext().getTypeSizeInChars(type);
201*700637cbSDimitry Andric     sizeWithoutCookie = cgf.getBuilder().getConstant(
202*700637cbSDimitry Andric         loc, cir::IntAttr::get(cgf.SizeTy, typeSize.getQuantity()));
203*700637cbSDimitry Andric     return sizeWithoutCookie;
204*700637cbSDimitry Andric   }
205*700637cbSDimitry Andric 
206*700637cbSDimitry Andric   cgf.cgm.errorNYI(e->getSourceRange(), "emitCXXNewAllocSize: array");
207*700637cbSDimitry Andric   return {};
208*700637cbSDimitry Andric }
209*700637cbSDimitry Andric 
storeAnyExprIntoOneUnit(CIRGenFunction & cgf,const Expr * init,QualType allocType,Address newPtr,AggValueSlot::Overlap_t mayOverlap)210*700637cbSDimitry Andric static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,
211*700637cbSDimitry Andric                                     QualType allocType, Address newPtr,
212*700637cbSDimitry Andric                                     AggValueSlot::Overlap_t mayOverlap) {
213*700637cbSDimitry Andric   // FIXME: Refactor with emitExprAsInit.
214*700637cbSDimitry Andric   switch (cgf.getEvaluationKind(allocType)) {
215*700637cbSDimitry Andric   case cir::TEK_Scalar:
216*700637cbSDimitry Andric     cgf.emitScalarInit(init, cgf.getLoc(init->getSourceRange()),
217*700637cbSDimitry Andric                        cgf.makeAddrLValue(newPtr, allocType), false);
218*700637cbSDimitry Andric     return;
219*700637cbSDimitry Andric   case cir::TEK_Complex:
220*700637cbSDimitry Andric     cgf.cgm.errorNYI(init->getSourceRange(),
221*700637cbSDimitry Andric                      "storeAnyExprIntoOneUnit: complex");
222*700637cbSDimitry Andric     return;
223*700637cbSDimitry Andric   case cir::TEK_Aggregate: {
224*700637cbSDimitry Andric     assert(!cir::MissingFeatures::aggValueSlotGC());
225*700637cbSDimitry Andric     assert(!cir::MissingFeatures::sanitizers());
226*700637cbSDimitry Andric     AggValueSlot slot = AggValueSlot::forAddr(
227*700637cbSDimitry Andric         newPtr, allocType.getQualifiers(), AggValueSlot::IsDestructed,
228*700637cbSDimitry Andric         AggValueSlot::IsNotAliased, mayOverlap, AggValueSlot::IsNotZeroed);
229*700637cbSDimitry Andric     cgf.emitAggExpr(init, slot);
230*700637cbSDimitry Andric     return;
231*700637cbSDimitry Andric   }
232*700637cbSDimitry Andric   }
233*700637cbSDimitry Andric   llvm_unreachable("bad evaluation kind");
234*700637cbSDimitry Andric }
235*700637cbSDimitry Andric 
emitNewInitializer(CIRGenFunction & cgf,const CXXNewExpr * e,QualType elementType,mlir::Type elementTy,Address newPtr,mlir::Value numElements,mlir::Value allocSizeWithoutCookie)236*700637cbSDimitry Andric static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e,
237*700637cbSDimitry Andric                                QualType elementType, mlir::Type elementTy,
238*700637cbSDimitry Andric                                Address newPtr, mlir::Value numElements,
239*700637cbSDimitry Andric                                mlir::Value allocSizeWithoutCookie) {
240*700637cbSDimitry Andric   assert(!cir::MissingFeatures::generateDebugInfo());
241*700637cbSDimitry Andric   if (e->isArray()) {
242*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "emitNewInitializer: array");
243*700637cbSDimitry Andric   } else if (const Expr *init = e->getInitializer()) {
244*700637cbSDimitry Andric     storeAnyExprIntoOneUnit(cgf, init, e->getAllocatedType(), newPtr,
245*700637cbSDimitry Andric                             AggValueSlot::DoesNotOverlap);
246*700637cbSDimitry Andric   }
247*700637cbSDimitry Andric }
248*700637cbSDimitry Andric 
249*700637cbSDimitry Andric /// Emit a call to an operator new or operator delete function, as implicitly
250*700637cbSDimitry Andric /// created by new-expressions and delete-expressions.
emitNewDeleteCall(CIRGenFunction & cgf,const FunctionDecl * calleeDecl,const FunctionProtoType * calleeType,const CallArgList & args)251*700637cbSDimitry Andric static RValue emitNewDeleteCall(CIRGenFunction &cgf,
252*700637cbSDimitry Andric                                 const FunctionDecl *calleeDecl,
253*700637cbSDimitry Andric                                 const FunctionProtoType *calleeType,
254*700637cbSDimitry Andric                                 const CallArgList &args) {
255*700637cbSDimitry Andric   cir::CIRCallOpInterface callOrTryCall;
256*700637cbSDimitry Andric   cir::FuncOp calleePtr = cgf.cgm.getAddrOfFunction(calleeDecl);
257*700637cbSDimitry Andric   CIRGenCallee callee =
258*700637cbSDimitry Andric       CIRGenCallee::forDirect(calleePtr, GlobalDecl(calleeDecl));
259*700637cbSDimitry Andric   RValue rv =
260*700637cbSDimitry Andric       cgf.emitCall(cgf.cgm.getTypes().arrangeFreeFunctionCall(args, calleeType),
261*700637cbSDimitry Andric                    callee, ReturnValueSlot(), args, &callOrTryCall);
262*700637cbSDimitry Andric 
263*700637cbSDimitry Andric   /// C++1y [expr.new]p10:
264*700637cbSDimitry Andric   ///   [In a new-expression,] an implementation is allowed to omit a call
265*700637cbSDimitry Andric   ///   to a replaceable global allocation function.
266*700637cbSDimitry Andric   ///
267*700637cbSDimitry Andric   /// We model such elidable calls with the 'builtin' attribute.
268*700637cbSDimitry Andric   assert(!cir::MissingFeatures::attributeBuiltin());
269*700637cbSDimitry Andric   return rv;
270*700637cbSDimitry Andric }
271*700637cbSDimitry Andric 
emitCXXNewExpr(const CXXNewExpr * e)272*700637cbSDimitry Andric mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {
273*700637cbSDimitry Andric   // The element type being allocated.
274*700637cbSDimitry Andric   QualType allocType = getContext().getBaseElementType(e->getAllocatedType());
275*700637cbSDimitry Andric 
276*700637cbSDimitry Andric   // 1. Build a call to the allocation function.
277*700637cbSDimitry Andric   FunctionDecl *allocator = e->getOperatorNew();
278*700637cbSDimitry Andric 
279*700637cbSDimitry Andric   // If there is a brace-initializer, cannot allocate fewer elements than inits.
280*700637cbSDimitry Andric   unsigned minElements = 0;
281*700637cbSDimitry Andric   if (e->isArray() && e->hasInitializer()) {
282*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array initializer");
283*700637cbSDimitry Andric   }
284*700637cbSDimitry Andric 
285*700637cbSDimitry Andric   mlir::Value numElements = nullptr;
286*700637cbSDimitry Andric   mlir::Value allocSizeWithoutCookie = nullptr;
287*700637cbSDimitry Andric   mlir::Value allocSize = emitCXXNewAllocSize(
288*700637cbSDimitry Andric       *this, e, minElements, numElements, allocSizeWithoutCookie);
289*700637cbSDimitry Andric   CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
290*700637cbSDimitry Andric 
291*700637cbSDimitry Andric   // Emit the allocation call.
292*700637cbSDimitry Andric   Address allocation = Address::invalid();
293*700637cbSDimitry Andric   CallArgList allocatorArgs;
294*700637cbSDimitry Andric   if (allocator->isReservedGlobalPlacementOperator()) {
295*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(),
296*700637cbSDimitry Andric                  "emitCXXNewExpr: reserved global placement operator");
297*700637cbSDimitry Andric   } else {
298*700637cbSDimitry Andric     const FunctionProtoType *allocatorType =
299*700637cbSDimitry Andric         allocator->getType()->castAs<FunctionProtoType>();
300*700637cbSDimitry Andric     unsigned paramsToSkip = 0;
301*700637cbSDimitry Andric 
302*700637cbSDimitry Andric     // The allocation size is the first argument.
303*700637cbSDimitry Andric     QualType sizeType = getContext().getSizeType();
304*700637cbSDimitry Andric     allocatorArgs.add(RValue::get(allocSize), sizeType);
305*700637cbSDimitry Andric     ++paramsToSkip;
306*700637cbSDimitry Andric 
307*700637cbSDimitry Andric     if (allocSize != allocSizeWithoutCookie) {
308*700637cbSDimitry Andric       CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.
309*700637cbSDimitry Andric       allocAlign = std::max(allocAlign, cookieAlign);
310*700637cbSDimitry Andric     }
311*700637cbSDimitry Andric 
312*700637cbSDimitry Andric     // The allocation alignment may be passed as the second argument.
313*700637cbSDimitry Andric     if (e->passAlignment()) {
314*700637cbSDimitry Andric       cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: pass alignment");
315*700637cbSDimitry Andric     }
316*700637cbSDimitry Andric 
317*700637cbSDimitry Andric     // FIXME: Why do we not pass a CalleeDecl here?
318*700637cbSDimitry Andric     emitCallArgs(allocatorArgs, allocatorType, e->placement_arguments(),
319*700637cbSDimitry Andric                  AbstractCallee(), paramsToSkip);
320*700637cbSDimitry Andric     RValue rv =
321*700637cbSDimitry Andric         emitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
322*700637cbSDimitry Andric 
323*700637cbSDimitry Andric     // Set !heapallocsite metadata on the call to operator new.
324*700637cbSDimitry Andric     assert(!cir::MissingFeatures::generateDebugInfo());
325*700637cbSDimitry Andric 
326*700637cbSDimitry Andric     // If this was a call to a global replaceable allocation function that does
327*700637cbSDimitry Andric     // not take an alignment argument, the allocator is known to produce storage
328*700637cbSDimitry Andric     // that's suitably aligned for any object that fits, up to a known
329*700637cbSDimitry Andric     // threshold. Otherwise assume it's suitably aligned for the allocated type.
330*700637cbSDimitry Andric     CharUnits allocationAlign = allocAlign;
331*700637cbSDimitry Andric     if (!e->passAlignment() &&
332*700637cbSDimitry Andric         allocator->isReplaceableGlobalAllocationFunction()) {
333*700637cbSDimitry Andric       const TargetInfo &target = cgm.getASTContext().getTargetInfo();
334*700637cbSDimitry Andric       unsigned allocatorAlign = llvm::bit_floor(std::min<uint64_t>(
335*700637cbSDimitry Andric           target.getNewAlign(), getContext().getTypeSize(allocType)));
336*700637cbSDimitry Andric       allocationAlign = std::max(
337*700637cbSDimitry Andric           allocationAlign, getContext().toCharUnitsFromBits(allocatorAlign));
338*700637cbSDimitry Andric     }
339*700637cbSDimitry Andric 
340*700637cbSDimitry Andric     mlir::Value allocPtr = rv.getValue();
341*700637cbSDimitry Andric     allocation = Address(
342*700637cbSDimitry Andric         allocPtr, mlir::cast<cir::PointerType>(allocPtr.getType()).getPointee(),
343*700637cbSDimitry Andric         allocationAlign);
344*700637cbSDimitry Andric   }
345*700637cbSDimitry Andric 
346*700637cbSDimitry Andric   // Emit a null check on the allocation result if the allocation
347*700637cbSDimitry Andric   // function is allowed to return null (because it has a non-throwing
348*700637cbSDimitry Andric   // exception spec or is the reserved placement new) and we have an
349*700637cbSDimitry Andric   // interesting initializer will be running sanitizers on the initialization.
350*700637cbSDimitry Andric   bool nullCheck = e->shouldNullCheckAllocation() &&
351*700637cbSDimitry Andric                    (!allocType.isPODType(getContext()) || e->hasInitializer());
352*700637cbSDimitry Andric   assert(!cir::MissingFeatures::exprNewNullCheck());
353*700637cbSDimitry Andric   if (nullCheck)
354*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: null check");
355*700637cbSDimitry Andric 
356*700637cbSDimitry Andric   // If there's an operator delete, enter a cleanup to call it if an
357*700637cbSDimitry Andric   // exception is thrown.
358*700637cbSDimitry Andric   if (e->getOperatorDelete() &&
359*700637cbSDimitry Andric       !e->getOperatorDelete()->isReservedGlobalPlacementOperator())
360*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");
361*700637cbSDimitry Andric 
362*700637cbSDimitry Andric   if (allocSize != allocSizeWithoutCookie)
363*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array with cookies");
364*700637cbSDimitry Andric 
365*700637cbSDimitry Andric   mlir::Type elementTy = convertTypeForMem(allocType);
366*700637cbSDimitry Andric   Address result = builder.createElementBitCast(getLoc(e->getSourceRange()),
367*700637cbSDimitry Andric                                                 allocation, elementTy);
368*700637cbSDimitry Andric 
369*700637cbSDimitry Andric   // Passing pointer through launder.invariant.group to avoid propagation of
370*700637cbSDimitry Andric   // vptrs information which may be included in previous type.
371*700637cbSDimitry Andric   // To not break LTO with different optimizations levels, we do it regardless
372*700637cbSDimitry Andric   // of optimization level.
373*700637cbSDimitry Andric   if (cgm.getCodeGenOpts().StrictVTablePointers &&
374*700637cbSDimitry Andric       allocator->isReservedGlobalPlacementOperator())
375*700637cbSDimitry Andric     cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: strict vtable pointers");
376*700637cbSDimitry Andric 
377*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
378*700637cbSDimitry Andric 
379*700637cbSDimitry Andric   emitNewInitializer(*this, e, allocType, elementTy, result, numElements,
380*700637cbSDimitry Andric                      allocSizeWithoutCookie);
381*700637cbSDimitry Andric   return result.getPointer();
382*700637cbSDimitry Andric }
383