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