clang 23.0.0git
CIRGenExprCXX.cpp
Go to the documentation of this file.
1//===--- CIRGenExprCXX.cpp - Emit CIR Code for C++ expressions ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with code generation of C++ expressions
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
15#include "CIRGenFunction.h"
16
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/ExprCXX.h"
21
22using namespace clang;
23using namespace clang::CIRGen;
24
25namespace {
26struct MemberCallInfo {
27 RequiredArgs reqArgs;
28 // Number of prefix arguments for the call. Ignores the `this` pointer.
29 unsigned prefixSize;
30};
31} // namespace
32
34 CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr,
35 mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce,
36 CallArgList &args, CallArgList *rtlArgs) {
37 assert(ce == nullptr || isa<CXXMemberCallExpr>(ce) ||
39 assert(md->isInstance() &&
40 "Trying to emit a member or operator call expr on a static method!");
41
42 // Push the this ptr.
43 const CXXRecordDecl *rd =
45 args.add(RValue::get(thisPtr), cgf.getTypes().deriveThisType(rd, md));
46
47 // If there is an implicit parameter (e.g. VTT), emit it.
48 if (implicitParam) {
49 args.add(RValue::get(implicitParam), implicitParamTy);
50 }
51
52 const auto *fpt = md->getType()->castAs<FunctionProtoType>();
53 RequiredArgs required =
55 unsigned prefixSize = args.size() - 1;
56
57 // Add the rest of the call args
58 if (rtlArgs) {
59 // Special case: if the caller emitted the arguments right-to-left already
60 // (prior to emitting the *this argument), we're done. This happens for
61 // assignment operators.
62 args.addFrom(*rtlArgs);
63 } else if (ce) {
64 // Special case: skip first argument of CXXOperatorCall (it is "this").
65 unsigned argsToSkip = isa<CXXOperatorCallExpr>(ce) ? 1 : 0;
66 cgf.emitCallArgs(args, fpt, drop_begin(ce->arguments(), argsToSkip),
67 ce->getDirectCallee());
68 } else {
69 assert(
70 fpt->getNumParams() == 0 &&
71 "No CallExpr specified for function with non-zero number of arguments");
72 }
73
74 // return {required, prefixSize};
75 return {required, prefixSize};
76}
77
81 const BinaryOperator *bo =
83 const Expr *baseExpr = bo->getLHS();
84 const Expr *memFnExpr = bo->getRHS();
85
86 const auto *mpt = memFnExpr->getType()->castAs<MemberPointerType>();
87 const auto *fpt = mpt->getPointeeType()->castAs<FunctionProtoType>();
88
89 // Emit the 'this' pointer.
90 Address thisAddr = Address::invalid();
91 if (bo->getOpcode() == BO_PtrMemI)
92 thisAddr = emitPointerWithAlignment(baseExpr);
93 else
94 thisAddr = emitLValue(baseExpr).getAddress();
95
97
98 // Get the member function pointer.
99 mlir::Value memFnPtr = emitScalarExpr(memFnExpr);
100
101 // Resolve the member function pointer to the actual callee and adjust the
102 // "this" pointer for call.
103 mlir::Location loc = getLoc(ce->getExprLoc());
104 auto [/*mlir::Value*/ calleePtr, /*mlir::Value*/ adjustedThis] =
105 builder.createGetMethod(loc, memFnPtr, thisAddr.getPointer());
106
107 // Prepare the call arguments.
108 CallArgList argsList;
109 argsList.add(RValue::get(adjustedThis), getContext().VoidPtrTy);
110 emitCallArgs(argsList, fpt, ce->arguments());
111
113
114 // Build the call.
115 CIRGenCallee callee(fpt, calleePtr.getDefiningOp());
117 return emitCall(cgm.getTypes().arrangeCXXMethodCall(argsList, fpt, required,
118 /*PrefixSize=*/0),
119 callee, returnValue, argsList, nullptr, loc);
120}
121
124 bool hasQualifier, NestedNameSpecifier qualifier, bool isArrow,
125 const Expr *base) {
127
128 // Compute the object pointer.
129 bool canUseVirtualCall = md->isVirtual() && !hasQualifier;
130 const CXXMethodDecl *devirtualizedMethod = nullptr;
132
133 // Note on trivial assignment
134 // --------------------------
135 // Classic codegen avoids generating the trivial copy/move assignment operator
136 // when it isn't necessary, choosing instead to just produce IR with an
137 // equivalent effect. We have chosen not to do that in CIR, instead emitting
138 // trivial copy/move assignment operators and allowing later transformations
139 // to optimize them away if appropriate.
140
141 // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
142 // operator before the LHS.
143 CallArgList rtlArgStorage;
144 CallArgList *rtlArgs = nullptr;
145 if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
146 if (oce->isAssignmentOp()) {
147 rtlArgs = &rtlArgStorage;
148 emitCallArgs(*rtlArgs, md->getType()->castAs<FunctionProtoType>(),
149 drop_begin(ce->arguments(), 1), ce->getDirectCallee(),
150 /*ParamsToSkip*/ 0);
151 }
152 }
153
154 LValue thisPtr;
155 if (isArrow) {
156 LValueBaseInfo baseInfo;
158 Address thisValue = emitPointerWithAlignment(base, &baseInfo);
159 thisPtr = makeAddrLValue(thisValue, base->getType(), baseInfo);
160 } else {
161 thisPtr = emitLValue(base);
162 }
163
164 if (isa<CXXConstructorDecl>(md)) {
165 cgm.errorNYI(ce->getSourceRange(),
166 "emitCXXMemberOrOperatorMemberCallExpr: constructor call");
167 return RValue::get(nullptr);
168 }
169
170 if ((md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion())) &&
172 return RValue::get(nullptr);
173
174 // Compute the function type we're calling
175 const CXXMethodDecl *calleeDecl =
176 devirtualizedMethod ? devirtualizedMethod : md;
177 const CIRGenFunctionInfo *fInfo = nullptr;
178 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl))
179 fInfo = &cgm.getTypes().arrangeCXXStructorDeclaration(
181 else
182 fInfo = &cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);
183
184 cir::FuncType ty = cgm.getTypes().getFunctionType(*fInfo);
185
188
189 // C++ [class.virtual]p12:
190 // Explicit qualification with the scope operator (5.1) suppresses the
191 // virtual call mechanism.
192 //
193 // We also don't emit a virtual call if the base expression has a record type
194 // because then we know what the type is.
195 bool useVirtualCall = canUseVirtualCall && !devirtualizedMethod;
196
197 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl)) {
198 assert(ce->arg_begin() == ce->arg_end() &&
199 "Destructor shouldn't have explicit parameters");
200 assert(returnValue.isNull() && "Destructor shouldn't have return value");
201 if (useVirtualCall) {
202 cgm.getCXXABI().emitVirtualDestructorCall(*this, dtor, Dtor_Complete,
203 thisPtr.getAddress(),
205 } else {
206 GlobalDecl globalDecl(dtor, Dtor_Complete);
207 CIRGenCallee callee;
209 if (!devirtualizedMethod) {
211 cgm.getAddrOfCXXStructor(globalDecl, fInfo, ty), globalDecl);
212 } else {
213 cgm.errorNYI(ce->getSourceRange(), "devirtualized destructor call");
214 return RValue::get(nullptr);
215 }
216
217 QualType thisTy =
218 isArrow ? base->getType()->getPointeeType() : base->getType();
219 // CIRGen does not pass CallOrInvoke here (different from OG LLVM codegen)
220 // because in practice it always null even in OG.
221 emitCXXDestructorCall(globalDecl, callee, thisPtr.getPointer(), thisTy,
222 /*implicitParam=*/nullptr,
223 /*implicitParamTy=*/QualType(), ce);
224 }
225 return RValue::get(nullptr);
226 }
227
228 CIRGenCallee callee;
229 if (useVirtualCall) {
230 callee = CIRGenCallee::forVirtual(ce, md, thisPtr.getAddress(), ty);
231 } else {
233 if (getLangOpts().AppleKext) {
234 cgm.errorNYI(ce->getSourceRange(),
235 "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");
236 return RValue::get(nullptr);
237 }
238
239 callee = CIRGenCallee::forDirect(cgm.getAddrOfFunction(calleeDecl, ty),
240 GlobalDecl(calleeDecl));
241 }
242
243 if (md->isVirtual()) {
244 Address newThisAddr =
245 cgm.getCXXABI().adjustThisArgumentForVirtualFunctionCall(
246 *this, calleeDecl, thisPtr.getAddress(), useVirtualCall);
247 thisPtr.setAddress(newThisAddr);
248 }
249
251 calleeDecl, callee, returnValue, thisPtr.getPointer(),
252 /*ImplicitParam=*/nullptr, QualType(), ce, rtlArgs);
253}
254
255RValue
257 const CXXMethodDecl *md,
259 assert(md->isInstance() &&
260 "Trying to emit a member call expr on a static method!");
262 e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt,
263 /*IsArrow=*/false, e->getArg(0));
264}
265
267 const CXXMethodDecl *md, const CIRGenCallee &callee,
268 ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam,
269 QualType implicitParamTy, const CallExpr *ce, CallArgList *rtlArgs) {
270 const auto *fpt = md->getType()->castAs<FunctionProtoType>();
271 CallArgList args;
272 MemberCallInfo callInfo = commonBuildCXXMemberOrOperatorCall(
273 *this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);
274 auto &fnInfo = cgm.getTypes().arrangeCXXMethodCall(
275 args, fpt, callInfo.reqArgs, callInfo.prefixSize);
276 assert((ce || currSrcLoc) && "expected source location");
277 mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
279 return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
280}
281
283 Address destPtr,
284 const CXXRecordDecl *base) {
285 if (base->isEmpty())
286 return;
287
288 const ASTRecordLayout &layout = cgf.getContext().getASTRecordLayout(base);
289 CharUnits nvSize = layout.getNonVirtualSize();
290
291 // We cannot simply zero-initialize the entire base sub-object if vbptrs are
292 // present, they are initialized by the most derived class before calling the
293 // constructor.
295 stores.emplace_back(CharUnits::Zero(), nvSize);
296
297 // Each store is split by the existence of a vbptr.
298 // TODO(cir): This only needs handling for the MS CXXABI.
300
301 // If the type contains a pointer to data member we can't memset it to zero.
302 // Instead, create a null constant and copy it to the destination.
303 // TODO: there are other patterns besides zero that we can usefully memset,
304 // like -1, which happens to be the pattern used by member-pointers.
305 // TODO: isZeroInitializable can be over-conservative in the case where a
306 // virtual base contains a member pointer.
307 mlir::TypedAttr nullConstantForBase = cgf.cgm.emitNullConstantForBase(base);
308 if (!cgf.getBuilder().isNullValue(nullConstantForBase)) {
309 cgf.cgm.errorNYI(
310 base->getSourceRange(),
311 "emitNullBaseClassInitialization: base constant is not null");
312 } else {
313 // Otherwise, just memset the whole thing to zero. This is legal
314 // because in LLVM, all default initializers (other than the ones we just
315 // handled above) are guaranteed to have a bit pattern of all zeros.
316 // TODO(cir): When the MS CXXABI is supported, we will need to iterate over
317 // `stores` and create a separate memset for each one. For now, we know that
318 // there will only be one store and it will begin at offset zero, so that
319 // simplifies this code considerably.
320 assert(stores.size() == 1 && "Expected only one store");
321 assert(stores[0].first == CharUnits::Zero() &&
322 "Expected store to begin at offset zero");
323 CIRGenBuilderTy builder = cgf.getBuilder();
324 mlir::Location loc = cgf.getLoc(base->getBeginLoc());
325 builder.createStore(loc, builder.getConstant(loc, nullConstantForBase),
326 destPtr);
327 }
328}
329
331 AggValueSlot dest) {
332 assert(!dest.isIgnored() && "Must have a destination!");
333 const CXXConstructorDecl *cd = e->getConstructor();
334
335 // If we require zero initialization before (or instead of) calling the
336 // constructor, as can be the case with a non-user-provided default
337 // constructor, emit the zero initialization now, unless destination is
338 // already zeroed.
339 if (e->requiresZeroInitialization() && !dest.isZeroed()) {
340 switch (e->getConstructionKind()) {
344 e->getType());
345 break;
349 cd->getParent());
350 break;
351 }
352 }
353
354 // If this is a call to a trivial default constructor, do nothing.
355 if (cd->isTrivial() && cd->isDefaultConstructor())
356 return;
357
358 // Elide the constructor if we're constructing from a temporary
359 if (getLangOpts().ElideConstructors && e->isElidable()) {
360 // FIXME: This only handles the simplest case, where the source object is
361 // passed directly as the first argument to the constructor. This
362 // should also handle stepping through implicit casts and conversion
363 // sequences which involve two steps, with a conversion operator
364 // follwed by a converting constructor.
365 const Expr *srcObj = e->getArg(0);
366 assert(srcObj->isTemporaryObject(getContext(), cd->getParent()));
367 assert(
368 getContext().hasSameUnqualifiedType(e->getType(), srcObj->getType()));
369 emitAggExpr(srcObj, dest);
370 return;
371 }
372
373 if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {
375 emitCXXAggrConstructorCall(cd, arrayType, dest.getAddress(), e, false);
376 } else {
377
379 bool forVirtualBase = false;
380 bool delegating = false;
381
382 switch (e->getConstructionKind()) {
385 break;
387 // We should be emitting a constructor; GlobalDecl will assert this
388 type = curGD.getCtorType();
389 delegating = true;
390 break;
392 forVirtualBase = true;
393 [[fallthrough]];
395 type = Ctor_Base;
396 break;
397 }
398
399 emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);
400 }
401}
402
404 const CXXNewExpr *e) {
405 if (!e->isArray())
406 return CharUnits::Zero();
407
408 // No cookie is required if the operator new[] being used is the
409 // reserved placement operator new[].
411 return CharUnits::Zero();
412
413 return cgf.cgm.getCXXABI().getArrayCookieSize(e);
414}
415
416static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
417 unsigned minElements,
418 mlir::Value &numElements,
419 mlir::Value &sizeWithoutCookie) {
421 mlir::Location loc = cgf.getLoc(e->getSourceRange());
422
423 if (!e->isArray()) {
425 sizeWithoutCookie = cgf.getBuilder().getConstant(
426 loc, cir::IntAttr::get(cgf.sizeTy, typeSize.getQuantity()));
427 return sizeWithoutCookie;
428 }
429
430 // The width of size_t.
431 unsigned sizeWidth = cgf.cgm.getDataLayout().getTypeSizeInBits(cgf.sizeTy);
432
433 // The number of elements can be have an arbitrary integer type;
434 // essentially, we need to multiply it by a constant factor, add a
435 // cookie size, and verify that the result is representable as a
436 // size_t. That's just a gloss, though, and it's wrong in one
437 // important way: if the count is negative, it's an error even if
438 // the cookie size would bring the total size >= 0.
439 //
440 // If the array size is constant, Sema will have prevented negative
441 // values and size overflow.
442
443 // Compute the constant factor.
444 llvm::APInt arraySizeMultiplier(sizeWidth, 1);
445 while (const ConstantArrayType *cat =
447 type = cat->getElementType();
448 arraySizeMultiplier *= cat->getSize();
449 }
450
452 llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity());
453 typeSizeMultiplier *= arraySizeMultiplier;
454
455 // Figure out the cookie size.
456 llvm::APInt cookieSize(sizeWidth,
457 calculateCookiePadding(cgf, e).getQuantity());
458
459 // This will be a size_t.
460 mlir::Value size;
461
462 // Emit the array size expression.
463 // We multiply the size of all dimensions for NumElements.
464 // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
465 const Expr *arraySize = *e->getArraySize();
466 mlir::Attribute constNumElements =
467 ConstantEmitter(cgf.cgm, &cgf)
468 .emitAbstract(arraySize, arraySize->getType());
469 if (constNumElements) {
470 // Get an APInt from the constant
471 const llvm::APInt &count =
472 mlir::cast<cir::IntAttr>(constNumElements).getValue();
473
474 [[maybe_unused]] unsigned numElementsWidth = count.getBitWidth();
475 bool hasAnyOverflow = false;
476
477 // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as
478 // overflow, but that should never happen. The size argument is implicitly
479 // cast to a size_t, so it can never be negative and numElementsWidth will
480 // always equal sizeWidth.
481 assert(!count.isNegative() && "Expected non-negative array size");
482 assert(numElementsWidth == sizeWidth &&
483 "Expected a size_t array size constant");
484
485 // Okay, compute a count at the right width.
486 llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);
487
488 // Scale numElements by that. This might overflow, but we don't
489 // care because it only overflows if allocationSize does too, and
490 // if that overflows then we shouldn't use this.
491 // This emits a constant that may not be used, but we can't tell here
492 // whether it will be needed or not.
493 numElements =
494 cgf.getBuilder().getConstInt(loc, adjustedCount * arraySizeMultiplier);
495
496 // Compute the size before cookie, and track whether it overflowed.
497 bool overflow;
498 llvm::APInt allocationSize =
499 adjustedCount.umul_ov(typeSizeMultiplier, overflow);
500
501 // Sema prevents us from hitting this case
502 assert(!overflow && "Overflow in array allocation size");
503
504 // Add in the cookie, and check whether it's overflowed.
505 if (cookieSize != 0) {
506 // Save the current size without a cookie. This shouldn't be
507 // used if there was overflow
508 sizeWithoutCookie = cgf.getBuilder().getConstInt(
509 loc, allocationSize.zextOrTrunc(sizeWidth));
510
511 allocationSize = allocationSize.uadd_ov(cookieSize, overflow);
512 hasAnyOverflow |= overflow;
513 }
514
515 // On overflow, produce a -1 so operator new will fail
516 if (hasAnyOverflow) {
517 size =
518 cgf.getBuilder().getConstInt(loc, llvm::APInt::getAllOnes(sizeWidth));
519 } else {
520 size = cgf.getBuilder().getConstInt(loc, allocationSize);
521 }
522 } else {
523 // TODO: Handle the variable size case
524 cgf.cgm.errorNYI(e->getSourceRange(),
525 "emitCXXNewAllocSize: variable array size");
526 }
527
528 if (cookieSize == 0)
529 sizeWithoutCookie = size;
530 else
531 assert(sizeWithoutCookie && "didn't set sizeWithoutCookie?");
532
533 return size;
534}
535
536static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,
537 QualType allocType, Address newPtr,
538 AggValueSlot::Overlap_t mayOverlap) {
539 // FIXME: Refactor with emitExprAsInit.
540 switch (cgf.getEvaluationKind(allocType)) {
541 case cir::TEK_Scalar:
542 cgf.emitScalarInit(init, cgf.getLoc(init->getSourceRange()),
543 cgf.makeAddrLValue(newPtr, allocType), false);
544 return;
545 case cir::TEK_Complex:
546 cgf.emitComplexExprIntoLValue(init, cgf.makeAddrLValue(newPtr, allocType),
547 /*isInit*/ true);
548 return;
549 case cir::TEK_Aggregate: {
553 newPtr, allocType.getQualifiers(), AggValueSlot::IsDestructed,
555 cgf.emitAggExpr(init, slot);
556 return;
557 }
558 }
559 llvm_unreachable("bad evaluation kind");
560}
561
563 const CXXNewExpr *e, QualType elementType, mlir::Type elementTy,
564 Address beginPtr, mlir::Value numElements,
565 mlir::Value allocSizeWithoutCookie) {
566 // If we have a type with trivial initialization and no initializer,
567 // there's nothing to do.
568 if (!e->hasInitializer())
569 return;
570
571 unsigned initListElements = 0;
572
573 const Expr *init = e->getInitializer();
574 const InitListExpr *ile = dyn_cast<InitListExpr>(init);
575 if (ile) {
576 cgm.errorNYI(ile->getSourceRange(), "emitNewArrayInitializer: init list");
577 return;
578 }
579
580 // If all elements have already been initialized, skip any further
581 // initialization.
582 auto constOp = mlir::dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
583 if (constOp) {
584 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constOp.getValue());
585 // Just skip out if the constant count is zero.
586 if (constIntAttr && constIntAttr.getUInt() <= initListElements)
587 return;
588 }
589
590 assert(init && "have trailing elements to initialize but no initializer");
591
592 // If this is a constructor call, try to optimize it out, and failing that
593 // emit a single loop to initialize all remaining elements.
594 if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) {
595 CXXConstructorDecl *ctor = cce->getConstructor();
596 if (ctor->isTrivial()) {
597 // If new expression did not specify value-initialization, then there
598 // is no initialization.
599 if (!cce->requiresZeroInitialization())
600 return;
601
602 cgm.errorNYI(cce->getSourceRange(),
603 "emitNewArrayInitializer: trivial ctor zero-init");
604 return;
605 }
606
607 cgm.errorNYI(cce->getSourceRange(),
608 "emitNewArrayInitializer: ctor initializer");
609 return;
610 }
611
612 cgm.errorNYI(init->getSourceRange(),
613 "emitNewArrayInitializer: unsupported initializer");
614 return;
615}
616
618 QualType elementType, mlir::Type elementTy,
619 Address newPtr, mlir::Value numElements,
620 mlir::Value allocSizeWithoutCookie) {
622 if (e->isArray()) {
623 cgf.emitNewArrayInitializer(e, elementType, elementTy, newPtr, numElements,
624 allocSizeWithoutCookie);
625 } else if (const Expr *init = e->getInitializer()) {
626 storeAnyExprIntoOneUnit(cgf, init, e->getAllocatedType(), newPtr,
628 }
629}
630
632 GlobalDecl dtor, const CIRGenCallee &callee, mlir::Value thisVal,
633 QualType thisTy, mlir::Value implicitParam, QualType implicitParamTy,
634 const CallExpr *ce) {
635 const CXXMethodDecl *dtorDecl = cast<CXXMethodDecl>(dtor.getDecl());
636
637 assert(!thisTy.isNull());
638 assert(thisTy->getAsCXXRecordDecl() == dtorDecl->getParent() &&
639 "Pointer/Object mixup");
640
642
643 CallArgList args;
644 commonBuildCXXMemberOrOperatorCall(*this, dtorDecl, thisVal, implicitParam,
645 implicitParamTy, ce, args, nullptr);
646 assert((ce || dtor.getDecl()) && "expected source location provider");
648 return emitCall(cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee,
649 ReturnValueSlot(), args, nullptr,
650 ce ? getLoc(ce->getExprLoc())
651 : getLoc(dtor.getDecl()->getSourceRange()));
652}
653
656 QualType destroyedType = expr->getDestroyedType();
657 if (destroyedType.hasStrongOrWeakObjCLifetime()) {
659 cgm.errorNYI(expr->getExprLoc(),
660 "emitCXXPseudoDestructorExpr: Objective-C lifetime is NYI");
661 } else {
662 // C++ [expr.pseudo]p1:
663 // The result shall only be used as the operand for the function call
664 // operator (), and the result of such a call has type void. The only
665 // effect is the evaluation of the postfix-expression before the dot or
666 // arrow.
667 emitIgnoredExpr(expr->getBase());
668 }
669
670 return RValue::get(nullptr);
671}
672
673/// Emit a call to an operator new or operator delete function, as implicitly
674/// created by new-expressions and delete-expressions.
676 const FunctionDecl *calleeDecl,
677 const FunctionProtoType *calleeType,
678 const CallArgList &args) {
679 cir::CIRCallOpInterface callOrTryCall;
680 cir::FuncOp calleePtr = cgf.cgm.getAddrOfFunction(calleeDecl);
681 CIRGenCallee callee =
682 CIRGenCallee::forDirect(calleePtr, GlobalDecl(calleeDecl));
683 RValue rv =
684 cgf.emitCall(cgf.cgm.getTypes().arrangeFreeFunctionCall(args, calleeType),
685 callee, ReturnValueSlot(), args, &callOrTryCall);
686
687 /// C++1y [expr.new]p10:
688 /// [In a new-expression,] an implementation is allowed to omit a call
689 /// to a replaceable global allocation function.
690 ///
691 /// We model such elidable calls with the 'builtin' attribute.
693 return rv;
694}
695
697 const CallExpr *callExpr,
699 CallArgList args;
700 emitCallArgs(args, type, callExpr->arguments());
701 // Find the allocation or deallocation function that we're calling.
702 ASTContext &astContext = getContext();
703 assert(op == OO_New || op == OO_Delete);
705
706 clang::DeclContextLookupResult lookupResult =
707 astContext.getTranslationUnitDecl()->lookup(name);
708 for (const auto *decl : lookupResult) {
709 if (const auto *funcDecl = dyn_cast<FunctionDecl>(decl)) {
710 if (astContext.hasSameType(funcDecl->getType(), QualType(type, 0))) {
711 if (sanOpts.has(SanitizerKind::AllocToken)) {
712 // TODO: Set !alloc_token metadata.
714 cgm.errorNYI("Alloc token sanitizer not yet supported!");
715 }
716
717 // Emit the call to operator new/delete.
718 return emitNewDeleteCall(*this, funcDecl, type, args);
719 }
720 }
721 }
722
723 llvm_unreachable("predeclared global operator new/delete is missing");
724}
725
726namespace {
727/// Calls the given 'operator delete' on a single object.
728struct CallObjectDelete final : EHScopeStack::Cleanup {
729 mlir::Value ptr;
730 const FunctionDecl *operatorDelete;
731 QualType elementType;
732
733 CallObjectDelete(mlir::Value ptr, const FunctionDecl *operatorDelete,
734 QualType elementType)
735 : ptr(ptr), operatorDelete(operatorDelete), elementType(elementType) {}
736
737 void emit(CIRGenFunction &cgf, Flags flags) override {
738 cgf.emitDeleteCall(operatorDelete, ptr, elementType);
739 }
740};
741} // namespace
742
743/// Emit the code for deleting a single object.
745 Address ptr, QualType elementType) {
746 // C++11 [expr.delete]p3:
747 // If the static type of the object to be deleted is different from its
748 // dynamic type, the static type shall be a base class of the dynamic type
749 // of the object to be deleted and the static type shall have a virtual
750 // destructor or the behavior is undefined.
752
753 const FunctionDecl *operatorDelete = de->getOperatorDelete();
754 assert(!operatorDelete->isDestroyingOperatorDelete());
755
756 // Find the destructor for the type, if applicable. If the
757 // destructor is virtual, we'll just emit the vcall and return.
758 const CXXDestructorDecl *dtor = nullptr;
759 if (const auto *rd = elementType->getAsCXXRecordDecl()) {
760 if (rd->hasDefinition() && !rd->hasTrivialDestructor()) {
761 dtor = rd->getDestructor();
762
763 if (dtor->isVirtual()) {
765 cgf.cgm.getCXXABI().emitVirtualObjectDelete(cgf, de, ptr, elementType,
766 dtor);
767 return;
768 }
769 }
770 }
771
772 // Make sure that we call delete even if the dtor throws.
773 // This doesn't have to a conditional cleanup because we're going
774 // to pop it off in a second.
775 cgf.ehStack.pushCleanup<CallObjectDelete>(
776 NormalAndEHCleanup, ptr.getPointer(), operatorDelete, elementType);
777
778 if (dtor) {
780 /*ForVirtualBase=*/false,
781 /*Delegating=*/false, ptr, elementType);
782 } else if (elementType.getObjCLifetime()) {
784 cgf.cgm.errorNYI(de->getSourceRange(), "emitObjectDelete: ObjCLifetime");
785 }
786
787 // In traditional LLVM codegen null checks are emitted to save a delete call.
788 // In CIR we optimize for size by default, the null check should be added into
789 // this function callers.
791
792 cgf.popCleanupBlock();
793}
794
796 const Expr *arg = e->getArgument();
798
799 // Null check the pointer.
800 //
801 // We could avoid this null check if we can determine that the object
802 // destruction is trivial and doesn't require an array cookie; we can
803 // unconditionally perform the operator delete call in that case. For now, we
804 // assume that deleted pointers are null rarely enough that it's better to
805 // keep the branch. This might be worth revisiting for a -O0 code size win.
806 //
807 // CIR note: emit the code size friendly by default for now, such as mentioned
808 // in `emitObjectDelete`.
810 QualType deleteTy = e->getDestroyedType();
811
812 // A destroying operator delete overrides the entire operation of the
813 // delete expression.
815 cgm.errorNYI(e->getSourceRange(),
816 "emitCXXDeleteExpr: destroying operator delete");
817 return;
818 }
819
820 // We might be deleting a pointer to array.
821 deleteTy = getContext().getBaseElementType(deleteTy);
822 ptr = ptr.withElementType(builder, convertTypeForMem(deleteTy));
823
824 if (e->isArrayForm() &&
825 cgm.getASTContext().getTargetInfo().emitVectorDeletingDtors(
826 cgm.getASTContext().getLangOpts())) {
827 cgm.errorNYI(e->getSourceRange(),
828 "emitCXXDeleteExpr: emitVectorDeletingDtors");
829 }
830
831 if (e->isArrayForm()) {
833 cgm.errorNYI(e->getSourceRange(), "emitCXXDeleteExpr: array delete");
834 return;
835 } else {
836 emitObjectDelete(*this, e, ptr, deleteTy);
837 }
838}
839
841 // The element type being allocated.
843
844 // 1. Build a call to the allocation function.
845 FunctionDecl *allocator = e->getOperatorNew();
846
847 // If there is a brace-initializer, cannot allocate fewer elements than inits.
848 unsigned minElements = 0;
849
850 mlir::Value numElements = nullptr;
851 mlir::Value allocSizeWithoutCookie = nullptr;
852 mlir::Value allocSize = emitCXXNewAllocSize(
853 *this, e, minElements, numElements, allocSizeWithoutCookie);
854 CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
855
856 // Emit the allocation call.
857 Address allocation = Address::invalid();
858 CallArgList allocatorArgs;
859 if (allocator->isReservedGlobalPlacementOperator()) {
860 // If the allocator is a global placement operator, just
861 // "inline" it directly.
862 assert(e->getNumPlacementArgs() == 1);
863 const Expr *arg = *e->placement_arguments().begin();
864
865 LValueBaseInfo baseInfo;
866 allocation = emitPointerWithAlignment(arg, &baseInfo);
867
868 // The pointer expression will, in many cases, be an opaque void*.
869 // In these cases, discard the computed alignment and use the
870 // formal alignment of the allocated type.
872 allocation = allocation.withAlignment(allocAlign);
873
874 // Set up allocatorArgs for the call to operator delete if it's not
875 // the reserved global operator.
876 if (e->getOperatorDelete() &&
878 cgm.errorNYI(e->getSourceRange(),
879 "emitCXXNewExpr: reserved placement new with delete");
880 }
881 } else {
882 const FunctionProtoType *allocatorType =
883 allocator->getType()->castAs<FunctionProtoType>();
884 unsigned paramsToSkip = 0;
885
886 // The allocation size is the first argument.
887 QualType sizeType = getContext().getSizeType();
888 allocatorArgs.add(RValue::get(allocSize), sizeType);
889 ++paramsToSkip;
890
891 if (allocSize != allocSizeWithoutCookie) {
892 CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.
893 allocAlign = std::max(allocAlign, cookieAlign);
894 }
895
896 // The allocation alignment may be passed as the second argument.
897 if (e->passAlignment()) {
898 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: pass alignment");
899 }
900
901 // FIXME: Why do we not pass a CalleeDecl here?
902 emitCallArgs(allocatorArgs, allocatorType, e->placement_arguments(),
903 AbstractCallee(), paramsToSkip);
904 RValue rv =
905 emitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
906
907 // Set !heapallocsite metadata on the call to operator new.
909
910 // If this was a call to a global replaceable allocation function that does
911 // not take an alignment argument, the allocator is known to produce storage
912 // that's suitably aligned for any object that fits, up to a known
913 // threshold. Otherwise assume it's suitably aligned for the allocated type.
914 CharUnits allocationAlign = allocAlign;
915 if (!e->passAlignment() &&
916 allocator->isReplaceableGlobalAllocationFunction()) {
917 const TargetInfo &target = cgm.getASTContext().getTargetInfo();
918 unsigned allocatorAlign = llvm::bit_floor(std::min<uint64_t>(
919 target.getNewAlign(), getContext().getTypeSize(allocType)));
920 allocationAlign = std::max(
921 allocationAlign, getContext().toCharUnitsFromBits(allocatorAlign));
922 }
923
924 mlir::Value allocPtr = rv.getValue();
925 allocation = Address(
926 allocPtr, mlir::cast<cir::PointerType>(allocPtr.getType()).getPointee(),
927 allocationAlign);
928 }
929
930 // Emit a null check on the allocation result if the allocation
931 // function is allowed to return null (because it has a non-throwing
932 // exception spec or is the reserved placement new) and we have an
933 // interesting initializer will be running sanitizers on the initialization.
934 bool nullCheck = e->shouldNullCheckAllocation() &&
935 (!allocType.isPODType(getContext()) || e->hasInitializer());
937 if (nullCheck)
938 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: null check");
939
940 // If there's an operator delete, enter a cleanup to call it if an
941 // exception is thrown.
942 if (e->getOperatorDelete() &&
944 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");
945
946 if (allocSize != allocSizeWithoutCookie) {
947 assert(e->isArray());
948 allocation = cgm.getCXXABI().initializeArrayCookie(
949 *this, allocation, numElements, e, allocType);
950 }
951
952 mlir::Type elementTy;
953 if (e->isArray()) {
954 // For array new, use the allocated type to handle multidimensional arrays
955 // correctly
956 elementTy = convertTypeForMem(e->getAllocatedType());
957 } else {
958 elementTy = convertTypeForMem(allocType);
959 }
960 Address result = builder.createElementBitCast(getLoc(e->getSourceRange()),
961 allocation, elementTy);
962
963 // Passing pointer through launder.invariant.group to avoid propagation of
964 // vptrs information which may be included in previous type.
965 // To not break LTO with different optimizations levels, we do it regardless
966 // of optimization level.
967 if (cgm.getCodeGenOpts().StrictVTablePointers &&
968 allocator->isReservedGlobalPlacementOperator())
969 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: strict vtable pointers");
970
972
973 emitNewInitializer(*this, e, allocType, elementTy, result, numElements,
974 allocSizeWithoutCookie);
975 return result.getPointer();
976}
977
979 mlir::Value ptr, QualType deleteTy) {
981
982 const auto *deleteFTy = deleteFD->getType()->castAs<FunctionProtoType>();
983 CallArgList deleteArgs;
984
985 UsualDeleteParams params = deleteFD->getUsualDeleteParams();
986 auto paramTypeIt = deleteFTy->param_type_begin();
987
988 // Pass std::type_identity tag if present
990 cgm.errorNYI(deleteFD->getSourceRange(),
991 "emitDeleteCall: type aware delete");
992
993 // Pass the pointer itself.
994 QualType argTy = *paramTypeIt++;
995 mlir::Value deletePtr =
996 builder.createBitcast(ptr.getLoc(), ptr, convertType(argTy));
997 deleteArgs.add(RValue::get(deletePtr), argTy);
998
999 // Pass the std::destroying_delete tag if present.
1000 if (params.DestroyingDelete)
1001 cgm.errorNYI(deleteFD->getSourceRange(),
1002 "emitDeleteCall: destroying delete");
1003
1004 // Pass the size if the delete function has a size_t parameter.
1005 if (params.Size) {
1006 QualType sizeType = *paramTypeIt++;
1007 CharUnits deleteTypeSize = getContext().getTypeSizeInChars(deleteTy);
1008 assert(mlir::isa<cir::IntType>(convertType(sizeType)) &&
1009 "expected cir::IntType");
1010 cir::ConstantOp size = builder.getConstInt(
1011 *currSrcLoc, convertType(sizeType), deleteTypeSize.getQuantity());
1012
1013 deleteArgs.add(RValue::get(size), sizeType);
1014 }
1015
1016 // Pass the alignment if the delete function has an align_val_t parameter.
1017 if (isAlignedAllocation(params.Alignment))
1018 cgm.errorNYI(deleteFD->getSourceRange(),
1019 "emitDeleteCall: aligned allocation");
1020
1021 assert(paramTypeIt == deleteFTy->param_type_end() &&
1022 "unknown parameter to usual delete function");
1023
1024 // Emit the call to delete.
1025 emitNewDeleteCall(*this, deleteFD, deleteFTy, deleteArgs);
1026}
1027
1029 mlir::Location loc, QualType destTy) {
1030 mlir::Type destCIRTy = cgf.convertType(destTy);
1031 assert(mlir::isa<cir::PointerType>(destCIRTy) &&
1032 "result of dynamic_cast should be a ptr");
1033
1034 if (!destTy->isPointerType()) {
1035 mlir::Region *currentRegion = cgf.getBuilder().getBlock()->getParent();
1036 /// C++ [expr.dynamic.cast]p9:
1037 /// A failed cast to reference type throws std::bad_cast
1038 cgf.cgm.getCXXABI().emitBadCastCall(cgf, loc);
1039
1040 // The call to bad_cast will terminate the current block. Create a new block
1041 // to hold any follow up code.
1042 cgf.getBuilder().createBlock(currentRegion, currentRegion->end());
1043 }
1044
1045 return cgf.getBuilder().getNullPtr(destCIRTy, loc);
1046}
1047
1049 const CXXDynamicCastExpr *dce) {
1050 mlir::Location loc = getLoc(dce->getSourceRange());
1051
1052 cgm.emitExplicitCastExprType(dce, this);
1053 QualType destTy = dce->getTypeAsWritten();
1054 QualType srcTy = dce->getSubExpr()->getType();
1055
1056 // C++ [expr.dynamic.cast]p7:
1057 // If T is "pointer to cv void," then the result is a pointer to the most
1058 // derived object pointed to by v.
1059 bool isDynCastToVoid = destTy->isVoidPointerType();
1060 bool isRefCast = destTy->isReferenceType();
1061
1062 QualType srcRecordTy;
1063 QualType destRecordTy;
1064 if (isDynCastToVoid) {
1065 srcRecordTy = srcTy->getPointeeType();
1066 // No destRecordTy.
1067 } else if (const PointerType *destPTy = destTy->getAs<PointerType>()) {
1068 srcRecordTy = srcTy->castAs<PointerType>()->getPointeeType();
1069 destRecordTy = destPTy->getPointeeType();
1070 } else {
1071 srcRecordTy = srcTy;
1072 destRecordTy = destTy->castAs<ReferenceType>()->getPointeeType();
1073 }
1074
1075 assert(srcRecordTy->isRecordType() && "source type must be a record type!");
1077
1078 if (dce->isAlwaysNull())
1079 return emitDynamicCastToNull(*this, loc, destTy);
1080
1081 auto destCirTy = mlir::cast<cir::PointerType>(convertType(destTy));
1082 return cgm.getCXXABI().emitDynamicCast(*this, loc, srcRecordTy, destRecordTy,
1083 destCirTy, isRefCast, thisAddr);
1084}
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address newPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
static void emitObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de, Address ptr, QualType elementType)
Emit the code for deleting a single object.
static void emitNullBaseClassInitialization(CIRGenFunction &cgf, Address destPtr, const CXXRecordDecl *base)
static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e, unsigned minElements, mlir::Value &numElements, mlir::Value &sizeWithoutCookie)
static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init, QualType allocType, Address newPtr, AggValueSlot::Overlap_t mayOverlap)
static CharUnits calculateCookiePadding(CIRGenFunction &cgf, const CXXNewExpr *e)
static mlir::Value emitDynamicCastToNull(CIRGenFunction &cgf, mlir::Location loc, QualType destTy)
static MemberCallInfo commonBuildCXXMemberOrOperatorCall(CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr, mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce, CallArgList &args, CallArgList *rtlArgs)
static RValue emitNewDeleteCall(CIRGenFunction &cgf, const FunctionDecl *calleeDecl, const FunctionProtoType *calleeType, const CallArgList &args)
Emit a call to an operator new or operator delete function, as implicitly created by new-expressions ...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines an enumeration for C++ overloaded operators.
static QualType getPointeeType(const MemRegion *R)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
DeclarationNameTable DeclarationNames
Definition ASTContext.h:794
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3723
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4038
Expr * getLHS() const
Definition Expr.h:4088
Expr * getRHS() const
Definition Expr.h:4090
Opcode getOpcode() const
Definition Expr.h:4083
mlir::Value getPointer() const
Definition Address.h:95
static Address invalid()
Definition Address.h:73
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
Address withAlignment(clang::CharUnits newAlignment) const
Return address with different alignment, but same pointer and element type.
Definition Address.h:86
An aggregate value slot.
IsZeroed_t isZeroed() const
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
bool isNullValue(mlir::Attribute attr) const
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
virtual void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de, Address ptr, QualType elementType, const CXXDestructorDecl *dtor)=0
virtual const clang::CXXRecordDecl * getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md)
Get the type of the implicit "this" parameter used by a method.
virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc)=0
virtual CharUnits getArrayCookieSize(const CXXNewExpr *e)
Returns the extra size required in order to store the array cookie for the given new-expression.
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:92
static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)
Definition CIRGenCall.h:154
An abstract representation of regular/ObjC call/message targets.
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
CIRGenTypes & getTypes() const
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
const clang::LangOptions & getLangOpts() const
RValue emitCXXMemberPointerCallExpr(const CXXMemberCallExpr *ce, ReturnValueSlot returnValue)
void emitDeleteCall(const FunctionDecl *deleteFD, mlir::Value ptr, QualType deleteTy)
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
RValue emitCXXMemberOrOperatorCall(const clang::CXXMethodDecl *md, const CIRGenCallee &callee, ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam, clang::QualType implicitParamTy, const clang::CallExpr *ce, CallArgList *rtlArgs)
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Type convertTypeForMem(QualType t)
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
Address returnValue
The temporary alloca to hold the return value.
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d, clang::CXXCtorType type, bool forVirtualBase, bool delegating, AggValueSlot thisAVS, const clang::CXXConstructExpr *e)
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
CIRGenBuilderTy & getBuilder()
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, const CallExpr *callExpr, OverloadedOperatorKind op)
void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType, Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize=false)
Emit a loop to call a particular constructor for each of several members of an array.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
RValue emitCXXMemberOrOperatorMemberCallExpr(const clang::CallExpr *ce, const clang::CXXMethodDecl *md, ReturnValueSlot returnValue, bool hasQualifier, clang::NestedNameSpecifier qualifier, bool isArrow, const clang::Expr *base)
void emitCXXDeleteExpr(const CXXDeleteExpr *e)
RValue emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e, const CXXMethodDecl *md, ReturnValueSlot returnValue)
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void popCleanupBlock()
Pops a cleanup block.
RValue emitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *expr)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)
Return a null constant appropriate for zero-initializing a base class with the given type.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
const cir::CIRDataLayout getDataLayout() const
CIRGenCXXABI & getCXXABI() const
const CIRGenFunctionInfo & arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType)
clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, const clang::CXXMethodDecl *md)
Derives the 'this' type for CIRGen purposes, i.e.
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
Definition CIRGenCall.h:244
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:235
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
Information for lazily generating a cleanup.
AlignmentSource getAlignmentSource() const
Address getAddress() const
mlir::Value getPointer() const
void setAddress(Address address)
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:57
A class for recording the number of arguments that a function signature requires.
static RequiredArgs getFromProtoWithExtraSlots(const clang::FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:256
Represents a call to a C++ constructor.
Definition ExprCXX.h:1548
bool isElidable() const
Whether this construction is elidable.
Definition ExprCXX.h:1617
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1691
bool requiresZeroInitialization() const
Whether this construction first requires zero-initialization before the initializer is called.
Definition ExprCXX.h:1650
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1611
CXXConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Definition ExprCXX.h:1659
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:2999
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2626
FunctionDecl * getOperatorDelete() const
Definition ExprCXX.h:2665
bool isArrayForm() const
Definition ExprCXX.h:2652
QualType getDestroyedType() const
Retrieve the type being destroyed.
Definition ExprCXX.cpp:338
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
Definition ExprCXX.h:481
bool isAlwaysNull() const
isAlwaysNull - Return whether the result of the dynamic_cast is proven to always be null.
Definition ExprCXX.cpp:838
Represents a call to a member function that may be written either with member call syntax (e....
Definition ExprCXX.h:179
SourceLocation getExprLoc() const LLVM_READONLY
Definition ExprCXX.h:220
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
bool isVirtual() const
Definition DeclCXX.h:2184
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
bool isInstance() const
Definition DeclCXX.h:2156
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2355
bool isArray() const
Definition ExprCXX.h:2464
llvm::iterator_range< arg_iterator > placement_arguments()
Definition ExprCXX.h:2572
QualType getAllocatedType() const
Definition ExprCXX.h:2434
std::optional< Expr * > getArraySize()
This might return std::nullopt even if isArray() returns true, since there might not be an array size...
Definition ExprCXX.h:2469
bool hasInitializer() const
Whether this new-expression has any initializer at all.
Definition ExprCXX.h:2524
bool shouldNullCheckAllocation() const
True if the allocation result needs to be null-checked.
Definition ExprCXX.cpp:326
bool passAlignment() const
Indicates whether the required alignment should be implicitly passed to the allocation function.
Definition ExprCXX.h:2551
FunctionDecl * getOperatorDelete() const
Definition ExprCXX.h:2461
unsigned getNumPlacementArgs() const
Definition ExprCXX.h:2494
SourceRange getSourceRange() const
Definition ExprCXX.h:2610
FunctionDecl * getOperatorNew() const
Definition ExprCXX.h:2459
Expr * getInitializer()
The initializer of this new-expression.
Definition ExprCXX.h:2533
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:84
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Definition ExprCXX.h:2745
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1186
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2943
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3147
arg_iterator arg_begin()
Definition Expr.h:3200
arg_iterator arg_end()
Definition Expr.h:3203
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3126
Expr * getCallee()
Definition Expr.h:3090
arg_range arguments()
Definition Expr.h:3195
Expr * getSubExpr()
Definition Expr.h:3726
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3761
The results of name lookup within a DeclContext.
Definition DeclBase.h:1382
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
The name of a declaration.
QualType getTypeAsWritten() const
getTypeAsWritten - Returns the type that this expression is casting to, as written in the source code...
Definition Expr.h:3955
This represents one expression.
Definition Expr.h:112
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3085
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const
Determine whether the result of this expression is a temporary object of the given class type.
Definition Expr.cpp:3252
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2000
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
Definition Decl.cpp:3551
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
UsualDeleteParams getUsualDeleteParams() const
Definition Decl.cpp:3567
bool isReservedGlobalPlacementOperator() const
Determines whether this operator new or delete is one of the reserved global placement operators: voi...
Definition Decl.cpp:3403
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2385
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4549
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5269
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
Describes an C or C++ initializer list.
Definition Expr.h:5299
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3654
QualType getPointeeType() const
Definition TypeBase.h:3672
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3329
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8332
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1438
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
Definition Type.cpp:2695
bool hasStrongOrWeakObjCLifetime() const
Definition TypeBase.h:1446
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3574
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4893
bool isUnion() const
Definition Decl.h:3925
Exposes information about the current target.
Definition TargetInfo.h:226
unsigned getNewAlign() const
Return the largest alignment for which a suitably-sized allocation with 'operator new(size_t)' is gua...
Definition TargetInfo.h:766
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3547
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isVoidPointerType() const
Definition Type.cpp:713
bool isPointerType() const
Definition TypeBase.h:8529
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9178
bool isReferenceType() const
Definition TypeBase.h:8553
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9111
bool isRecordType() const
Definition TypeBase.h:8656
QualType getType() const
Definition Decl.h:723
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isAlignedAllocation(AlignedAllocationMode Mode)
Definition ExprCXX.h:2265
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
bool isTypeAwareAllocation(TypeAwareAllocationMode Mode)
Definition ExprCXX.h:2253
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool objCLifetime()
static bool addressSpace()
static bool devirtualizeDestructor()
static bool aggValueSlotGC()
static bool devirtualizeMemberFunction()
static bool deleteArray()
static bool emitTypeCheck()
static bool opCallMustTail()
static bool exprNewNullCheck()
static bool attributeBuiltin()
static bool emitNullCheckForDeleteCalls()
static bool generateDebugInfo()
clang::CharUnits getSizeAlign() const
The parameters to pass to a usual operator delete.
Definition ExprCXX.h:2344
TypeAwareAllocationMode TypeAwareDelete
Definition ExprCXX.h:2345
AlignedAllocationMode Alignment
Definition ExprCXX.h:2348