Thanks to visit codestin.com
Credit goes to clang.llvm.org

clang 22.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"
14#include "CIRGenFunction.h"
15
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/ExprCXX.h"
19
20using namespace clang;
21using namespace clang::CIRGen;
22
23namespace {
24struct MemberCallInfo {
25 RequiredArgs reqArgs;
26 // Number of prefix arguments for the call. Ignores the `this` pointer.
27 unsigned prefixSize;
28};
29} // namespace
30
32 CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr,
33 mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce,
34 CallArgList &args, CallArgList *rtlArgs) {
35 assert(ce == nullptr || isa<CXXMemberCallExpr>(ce) ||
37 assert(md->isInstance() &&
38 "Trying to emit a member or operator call expr on a static method!");
39
40 // Push the this ptr.
41 const CXXRecordDecl *rd =
43 args.add(RValue::get(thisPtr), cgf.getTypes().deriveThisType(rd, md));
44
45 // If there is an implicit parameter (e.g. VTT), emit it.
46 if (implicitParam) {
47 args.add(RValue::get(implicitParam), implicitParamTy);
48 }
49
50 const auto *fpt = md->getType()->castAs<FunctionProtoType>();
51 RequiredArgs required =
53 unsigned prefixSize = args.size() - 1;
54
55 // Add the rest of the call args
56 if (rtlArgs) {
57 // Special case: if the caller emitted the arguments right-to-left already
58 // (prior to emitting the *this argument), we're done. This happens for
59 // assignment operators.
60 args.addFrom(*rtlArgs);
61 } else if (ce) {
62 // Special case: skip first argument of CXXOperatorCall (it is "this").
63 unsigned argsToSkip = isa<CXXOperatorCallExpr>(ce) ? 1 : 0;
64 cgf.emitCallArgs(args, fpt, drop_begin(ce->arguments(), argsToSkip),
65 ce->getDirectCallee());
66 } else {
67 assert(
68 fpt->getNumParams() == 0 &&
69 "No CallExpr specified for function with non-zero number of arguments");
70 }
71
72 // return {required, prefixSize};
73 return {required, prefixSize};
74}
75
78 bool hasQualifier, NestedNameSpecifier qualifier, bool isArrow,
79 const Expr *base) {
81
82 // Compute the object pointer.
83 bool canUseVirtualCall = md->isVirtual() && !hasQualifier;
84 const CXXMethodDecl *devirtualizedMethod = nullptr;
86
87 // Note on trivial assignment
88 // --------------------------
89 // Classic codegen avoids generating the trivial copy/move assignment operator
90 // when it isn't necessary, choosing instead to just produce IR with an
91 // equivalent effect. We have chosen not to do that in CIR, instead emitting
92 // trivial copy/move assignment operators and allowing later transformations
93 // to optimize them away if appropriate.
94
95 // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
96 // operator before the LHS.
97 CallArgList rtlArgStorage;
98 CallArgList *rtlArgs = nullptr;
99 if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
100 if (oce->isAssignmentOp()) {
101 rtlArgs = &rtlArgStorage;
102 emitCallArgs(*rtlArgs, md->getType()->castAs<FunctionProtoType>(),
103 drop_begin(ce->arguments(), 1), ce->getDirectCallee(),
104 /*ParamsToSkip*/ 0);
105 }
106 }
107
108 LValue thisPtr;
109 if (isArrow) {
110 LValueBaseInfo baseInfo;
112 Address thisValue = emitPointerWithAlignment(base, &baseInfo);
113 thisPtr = makeAddrLValue(thisValue, base->getType(), baseInfo);
114 } else {
115 thisPtr = emitLValue(base);
116 }
117
118 if (isa<CXXConstructorDecl>(md)) {
119 cgm.errorNYI(ce->getSourceRange(),
120 "emitCXXMemberOrOperatorMemberCallExpr: constructor call");
121 return RValue::get(nullptr);
122 }
123
124 if ((md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion())) &&
126 return RValue::get(nullptr);
127
128 // Compute the function type we're calling
129 const CXXMethodDecl *calleeDecl =
130 devirtualizedMethod ? devirtualizedMethod : md;
131 const CIRGenFunctionInfo *fInfo = nullptr;
132 if (isa<CXXDestructorDecl>(calleeDecl)) {
133 cgm.errorNYI(ce->getSourceRange(),
134 "emitCXXMemberOrOperatorMemberCallExpr: destructor call");
135 return RValue::get(nullptr);
136 }
137
138 fInfo = &cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);
139
140 cir::FuncType ty = cgm.getTypes().getFunctionType(*fInfo);
141
144
145 // C++ [class.virtual]p12:
146 // Explicit qualification with the scope operator (5.1) suppresses the
147 // virtual call mechanism.
148 //
149 // We also don't emit a virtual call if the base expression has a record type
150 // because then we know what the type is.
151 bool useVirtualCall = canUseVirtualCall && !devirtualizedMethod;
152
153 if (isa<CXXDestructorDecl>(calleeDecl)) {
154 cgm.errorNYI(ce->getSourceRange(),
155 "emitCXXMemberOrOperatorMemberCallExpr: destructor call");
156 return RValue::get(nullptr);
157 }
158
159 CIRGenCallee callee;
160 if (useVirtualCall) {
161 callee = CIRGenCallee::forVirtual(ce, md, thisPtr.getAddress(), ty);
162 } else {
164 if (getLangOpts().AppleKext) {
165 cgm.errorNYI(ce->getSourceRange(),
166 "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");
167 return RValue::get(nullptr);
168 }
169
170 callee = CIRGenCallee::forDirect(cgm.getAddrOfFunction(calleeDecl, ty),
171 GlobalDecl(calleeDecl));
172 }
173
174 if (md->isVirtual()) {
175 Address newThisAddr =
176 cgm.getCXXABI().adjustThisArgumentForVirtualFunctionCall(
177 *this, calleeDecl, thisPtr.getAddress(), useVirtualCall);
178 thisPtr.setAddress(newThisAddr);
179 }
180
182 calleeDecl, callee, returnValue, thisPtr.getPointer(),
183 /*ImplicitParam=*/nullptr, QualType(), ce, rtlArgs);
184}
185
186RValue
188 const CXXMethodDecl *md,
190 assert(md->isInstance() &&
191 "Trying to emit a member call expr on a static method!");
193 e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt,
194 /*IsArrow=*/false, e->getArg(0));
195}
196
198 const CXXMethodDecl *md, const CIRGenCallee &callee,
199 ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam,
200 QualType implicitParamTy, const CallExpr *ce, CallArgList *rtlArgs) {
201 const auto *fpt = md->getType()->castAs<FunctionProtoType>();
202 CallArgList args;
203 MemberCallInfo callInfo = commonBuildCXXMemberOrOperatorCall(
204 *this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);
205 auto &fnInfo = cgm.getTypes().arrangeCXXMethodCall(
206 args, fpt, callInfo.reqArgs, callInfo.prefixSize);
207 assert((ce || currSrcLoc) && "expected source location");
208 mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
210 return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
211}
212
213static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,
214 unsigned minElements,
215 mlir::Value &numElements,
216 mlir::Value &sizeWithoutCookie) {
218 mlir::Location loc = cgf.getLoc(e->getSourceRange());
219
220 if (!e->isArray()) {
222 sizeWithoutCookie = cgf.getBuilder().getConstant(
223 loc, cir::IntAttr::get(cgf.SizeTy, typeSize.getQuantity()));
224 return sizeWithoutCookie;
225 }
226
227 cgf.cgm.errorNYI(e->getSourceRange(), "emitCXXNewAllocSize: array");
228 return {};
229}
230
231static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,
232 QualType allocType, Address newPtr,
233 AggValueSlot::Overlap_t mayOverlap) {
234 // FIXME: Refactor with emitExprAsInit.
235 switch (cgf.getEvaluationKind(allocType)) {
236 case cir::TEK_Scalar:
237 cgf.emitScalarInit(init, cgf.getLoc(init->getSourceRange()),
238 cgf.makeAddrLValue(newPtr, allocType), false);
239 return;
240 case cir::TEK_Complex:
241 cgf.emitComplexExprIntoLValue(init, cgf.makeAddrLValue(newPtr, allocType),
242 /*isInit*/ true);
243 return;
244 case cir::TEK_Aggregate: {
248 newPtr, allocType.getQualifiers(), AggValueSlot::IsDestructed,
250 cgf.emitAggExpr(init, slot);
251 return;
252 }
253 }
254 llvm_unreachable("bad evaluation kind");
255}
256
258 QualType elementType, mlir::Type elementTy,
259 Address newPtr, mlir::Value numElements,
260 mlir::Value allocSizeWithoutCookie) {
262 if (e->isArray()) {
263 cgf.cgm.errorNYI(e->getSourceRange(), "emitNewInitializer: array");
264 } else if (const Expr *init = e->getInitializer()) {
265 storeAnyExprIntoOneUnit(cgf, init, e->getAllocatedType(), newPtr,
267 }
268}
269
271 GlobalDecl dtor, const CIRGenCallee &callee, mlir::Value thisVal,
272 QualType thisTy, mlir::Value implicitParam, QualType implicitParamTy,
273 const CallExpr *ce) {
274 const CXXMethodDecl *dtorDecl = cast<CXXMethodDecl>(dtor.getDecl());
275
276 assert(!thisTy.isNull());
277 assert(thisTy->getAsCXXRecordDecl() == dtorDecl->getParent() &&
278 "Pointer/Object mixup");
279
281
282 CallArgList args;
283 commonBuildCXXMemberOrOperatorCall(*this, dtorDecl, thisVal, implicitParam,
284 implicitParamTy, ce, args, nullptr);
285 assert((ce || dtor.getDecl()) && "expected source location provider");
287 return emitCall(cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee,
288 ReturnValueSlot(), args, nullptr,
289 ce ? getLoc(ce->getExprLoc())
290 : getLoc(dtor.getDecl()->getSourceRange()));
291}
292
295 QualType destroyedType = expr->getDestroyedType();
296 if (destroyedType.hasStrongOrWeakObjCLifetime()) {
298 cgm.errorNYI(expr->getExprLoc(),
299 "emitCXXPseudoDestructorExpr: Objective-C lifetime is NYI");
300 } else {
301 // C++ [expr.pseudo]p1:
302 // The result shall only be used as the operand for the function call
303 // operator (), and the result of such a call has type void. The only
304 // effect is the evaluation of the postfix-expression before the dot or
305 // arrow.
306 emitIgnoredExpr(expr->getBase());
307 }
308
309 return RValue::get(nullptr);
310}
311
312/// Emit a call to an operator new or operator delete function, as implicitly
313/// created by new-expressions and delete-expressions.
315 const FunctionDecl *calleeDecl,
316 const FunctionProtoType *calleeType,
317 const CallArgList &args) {
318 cir::CIRCallOpInterface callOrTryCall;
319 cir::FuncOp calleePtr = cgf.cgm.getAddrOfFunction(calleeDecl);
320 CIRGenCallee callee =
321 CIRGenCallee::forDirect(calleePtr, GlobalDecl(calleeDecl));
322 RValue rv =
323 cgf.emitCall(cgf.cgm.getTypes().arrangeFreeFunctionCall(args, calleeType),
324 callee, ReturnValueSlot(), args, &callOrTryCall);
325
326 /// C++1y [expr.new]p10:
327 /// [In a new-expression,] an implementation is allowed to omit a call
328 /// to a replaceable global allocation function.
329 ///
330 /// We model such elidable calls with the 'builtin' attribute.
332 return rv;
333}
334
335namespace {
336/// Calls the given 'operator delete' on a single object.
337struct CallObjectDelete final : EHScopeStack::Cleanup {
338 mlir::Value ptr;
339 const FunctionDecl *operatorDelete;
340 QualType elementType;
341
342 CallObjectDelete(mlir::Value ptr, const FunctionDecl *operatorDelete,
343 QualType elementType)
344 : ptr(ptr), operatorDelete(operatorDelete), elementType(elementType) {}
345
346 void emit(CIRGenFunction &cgf) override {
347 cgf.emitDeleteCall(operatorDelete, ptr, elementType);
348 }
349
350 // This is a placeholder until EHCleanupScope is implemented.
351 size_t getSize() const override {
353 return sizeof(CallObjectDelete);
354 }
355};
356} // namespace
357
358/// Emit the code for deleting a single object.
360 Address ptr, QualType elementType) {
361 // C++11 [expr.delete]p3:
362 // If the static type of the object to be deleted is different from its
363 // dynamic type, the static type shall be a base class of the dynamic type
364 // of the object to be deleted and the static type shall have a virtual
365 // destructor or the behavior is undefined.
367
368 const FunctionDecl *operatorDelete = de->getOperatorDelete();
369 assert(!operatorDelete->isDestroyingOperatorDelete());
370
371 // Find the destructor for the type, if applicable. If the
372 // destructor is virtual, we'll just emit the vcall and return.
373 const CXXDestructorDecl *dtor = nullptr;
374 if (const auto *rd = elementType->getAsCXXRecordDecl()) {
375 if (rd->hasDefinition() && !rd->hasTrivialDestructor()) {
376 dtor = rd->getDestructor();
377
378 if (dtor->isVirtual()) {
379 cgf.cgm.errorNYI(de->getSourceRange(),
380 "emitObjectDelete: virtual destructor");
381 }
382 }
383 }
384
385 // Make sure that we call delete even if the dtor throws.
386 // This doesn't have to a conditional cleanup because we're going
387 // to pop it off in a second.
388 cgf.ehStack.pushCleanup<CallObjectDelete>(
389 NormalAndEHCleanup, ptr.getPointer(), operatorDelete, elementType);
390
391 if (dtor) {
393 /*ForVirtualBase=*/false,
394 /*Delegating=*/false, ptr, elementType);
395 } else if (elementType.getObjCLifetime()) {
397 cgf.cgm.errorNYI(de->getSourceRange(), "emitObjectDelete: ObjCLifetime");
398 }
399
400 // In traditional LLVM codegen null checks are emitted to save a delete call.
401 // In CIR we optimize for size by default, the null check should be added into
402 // this function callers.
404
405 cgf.popCleanupBlock();
406}
407
409 const Expr *arg = e->getArgument();
411
412 // Null check the pointer.
413 //
414 // We could avoid this null check if we can determine that the object
415 // destruction is trivial and doesn't require an array cookie; we can
416 // unconditionally perform the operator delete call in that case. For now, we
417 // assume that deleted pointers are null rarely enough that it's better to
418 // keep the branch. This might be worth revisiting for a -O0 code size win.
419 //
420 // CIR note: emit the code size friendly by default for now, such as mentioned
421 // in `emitObjectDelete`.
423 QualType deleteTy = e->getDestroyedType();
424
425 // A destroying operator delete overrides the entire operation of the
426 // delete expression.
428 cgm.errorNYI(e->getSourceRange(),
429 "emitCXXDeleteExpr: destroying operator delete");
430 return;
431 }
432
433 // We might be deleting a pointer to array.
434 deleteTy = getContext().getBaseElementType(deleteTy);
435 ptr = ptr.withElementType(builder, convertTypeForMem(deleteTy));
436
437 if (e->isArrayForm()) {
439 cgm.errorNYI(e->getSourceRange(), "emitCXXDeleteExpr: array delete");
440 return;
441 } else {
442 emitObjectDelete(*this, e, ptr, deleteTy);
443 }
444}
445
447 // The element type being allocated.
449
450 // 1. Build a call to the allocation function.
451 FunctionDecl *allocator = e->getOperatorNew();
452
453 // If there is a brace-initializer, cannot allocate fewer elements than inits.
454 unsigned minElements = 0;
455 if (e->isArray() && e->hasInitializer()) {
456 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array initializer");
457 }
458
459 mlir::Value numElements = nullptr;
460 mlir::Value allocSizeWithoutCookie = nullptr;
461 mlir::Value allocSize = emitCXXNewAllocSize(
462 *this, e, minElements, numElements, allocSizeWithoutCookie);
463 CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
464
465 // Emit the allocation call.
466 Address allocation = Address::invalid();
467 CallArgList allocatorArgs;
468 if (allocator->isReservedGlobalPlacementOperator()) {
469 cgm.errorNYI(e->getSourceRange(),
470 "emitCXXNewExpr: reserved global placement operator");
471 } else {
472 const FunctionProtoType *allocatorType =
473 allocator->getType()->castAs<FunctionProtoType>();
474 unsigned paramsToSkip = 0;
475
476 // The allocation size is the first argument.
477 QualType sizeType = getContext().getSizeType();
478 allocatorArgs.add(RValue::get(allocSize), sizeType);
479 ++paramsToSkip;
480
481 if (allocSize != allocSizeWithoutCookie) {
482 CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.
483 allocAlign = std::max(allocAlign, cookieAlign);
484 }
485
486 // The allocation alignment may be passed as the second argument.
487 if (e->passAlignment()) {
488 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: pass alignment");
489 }
490
491 // FIXME: Why do we not pass a CalleeDecl here?
492 emitCallArgs(allocatorArgs, allocatorType, e->placement_arguments(),
493 AbstractCallee(), paramsToSkip);
494 RValue rv =
495 emitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
496
497 // Set !heapallocsite metadata on the call to operator new.
499
500 // If this was a call to a global replaceable allocation function that does
501 // not take an alignment argument, the allocator is known to produce storage
502 // that's suitably aligned for any object that fits, up to a known
503 // threshold. Otherwise assume it's suitably aligned for the allocated type.
504 CharUnits allocationAlign = allocAlign;
505 if (!e->passAlignment() &&
506 allocator->isReplaceableGlobalAllocationFunction()) {
507 const TargetInfo &target = cgm.getASTContext().getTargetInfo();
508 unsigned allocatorAlign = llvm::bit_floor(std::min<uint64_t>(
509 target.getNewAlign(), getContext().getTypeSize(allocType)));
510 allocationAlign = std::max(
511 allocationAlign, getContext().toCharUnitsFromBits(allocatorAlign));
512 }
513
514 mlir::Value allocPtr = rv.getValue();
515 allocation = Address(
516 allocPtr, mlir::cast<cir::PointerType>(allocPtr.getType()).getPointee(),
517 allocationAlign);
518 }
519
520 // Emit a null check on the allocation result if the allocation
521 // function is allowed to return null (because it has a non-throwing
522 // exception spec or is the reserved placement new) and we have an
523 // interesting initializer will be running sanitizers on the initialization.
524 bool nullCheck = e->shouldNullCheckAllocation() &&
525 (!allocType.isPODType(getContext()) || e->hasInitializer());
527 if (nullCheck)
528 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: null check");
529
530 // If there's an operator delete, enter a cleanup to call it if an
531 // exception is thrown.
532 if (e->getOperatorDelete() &&
534 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");
535
536 if (allocSize != allocSizeWithoutCookie)
537 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: array with cookies");
538
539 mlir::Type elementTy = convertTypeForMem(allocType);
540 Address result = builder.createElementBitCast(getLoc(e->getSourceRange()),
541 allocation, elementTy);
542
543 // Passing pointer through launder.invariant.group to avoid propagation of
544 // vptrs information which may be included in previous type.
545 // To not break LTO with different optimizations levels, we do it regardless
546 // of optimization level.
547 if (cgm.getCodeGenOpts().StrictVTablePointers &&
548 allocator->isReservedGlobalPlacementOperator())
549 cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: strict vtable pointers");
550
552
553 emitNewInitializer(*this, e, allocType, elementTy, result, numElements,
554 allocSizeWithoutCookie);
555 return result.getPointer();
556}
557
559 mlir::Value ptr, QualType deleteTy) {
561
562 const auto *deleteFTy = deleteFD->getType()->castAs<FunctionProtoType>();
563 CallArgList deleteArgs;
564
565 UsualDeleteParams params = deleteFD->getUsualDeleteParams();
566 auto paramTypeIt = deleteFTy->param_type_begin();
567
568 // Pass std::type_identity tag if present
570 cgm.errorNYI(deleteFD->getSourceRange(),
571 "emitDeleteCall: type aware delete");
572
573 // Pass the pointer itself.
574 QualType argTy = *paramTypeIt++;
575 mlir::Value deletePtr =
576 builder.createBitcast(ptr.getLoc(), ptr, convertType(argTy));
577 deleteArgs.add(RValue::get(deletePtr), argTy);
578
579 // Pass the std::destroying_delete tag if present.
580 if (params.DestroyingDelete)
581 cgm.errorNYI(deleteFD->getSourceRange(),
582 "emitDeleteCall: destroying delete");
583
584 // Pass the size if the delete function has a size_t parameter.
585 if (params.Size) {
586 QualType sizeType = *paramTypeIt++;
587 CharUnits deleteTypeSize = getContext().getTypeSizeInChars(deleteTy);
588 assert(mlir::isa<cir::IntType>(convertType(sizeType)) &&
589 "expected cir::IntType");
590 cir::ConstantOp size = builder.getConstInt(
591 *currSrcLoc, convertType(sizeType), deleteTypeSize.getQuantity());
592
593 deleteArgs.add(RValue::get(size), sizeType);
594 }
595
596 // Pass the alignment if the delete function has an align_val_t parameter.
597 if (isAlignedAllocation(params.Alignment))
598 cgm.errorNYI(deleteFD->getSourceRange(),
599 "emitDeleteCall: aligned allocation");
600
601 assert(paramTypeIt == deleteFTy->param_type_end() &&
602 "unknown parameter to usual delete function");
603
604 // Emit the call to delete.
605 emitNewDeleteCall(*this, deleteFD, deleteFTy, deleteArgs);
606}
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 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 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.
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
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.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
mlir::Value getPointer() const
Definition Address.h:81
static Address invalid()
Definition Address.h:66
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
An aggregate value slot.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
virtual const clang::CXXRecordDecl * getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md)
Get the type of the implicit "this" parameter used by a method.
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:90
static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)
Definition CIRGenCall.h:152
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.
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
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)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::Type convertTypeForMem(QualType t)
mlir::Value emitCXXNewExpr(const CXXNewExpr *e)
Address returnValue
The temporary alloca to hold the return value.
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)
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)
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.
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.
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.
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:240
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:231
Information for lazily generating a cleanup.
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:82
mlir::Value getValue() const
Return the value of this scalar value.
Definition CIRGenValue.h:56
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:252
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2628
FunctionDecl * getOperatorDelete() const
Definition ExprCXX.h:2667
bool isArrayForm() const
Definition ExprCXX.h:2654
QualType getDestroyedType() const
Retrieve the type being destroyed.
Definition ExprCXX.cpp:338
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
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:2357
bool isArray() const
Definition ExprCXX.h:2466
llvm::iterator_range< arg_iterator > placement_arguments()
Definition ExprCXX.h:2574
QualType getAllocatedType() const
Definition ExprCXX.h:2436
bool hasInitializer() const
Whether this new-expression has any initializer at all.
Definition ExprCXX.h:2526
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:2553
FunctionDecl * getOperatorDelete() const
Definition ExprCXX.h:2463
SourceRange getSourceRange() const
Definition ExprCXX.h:2612
FunctionDecl * getOperatorNew() const
Definition ExprCXX.h:2461
Expr * getInitializer()
The initializer of this new-expression.
Definition ExprCXX.h:2535
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:2747
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3081
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
arg_range arguments()
Definition Expr.h:3129
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
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
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:3539
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
UsualDeleteParams getUsualDeleteParams() const
Definition Decl.cpp:3555
bool isReservedGlobalPlacementOperator() const
Determines whether this operator new or delete is one of the reserved global placement operators: voi...
Definition Decl.cpp:3391
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:4537
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5266
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
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:8327
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
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
bool isUnion() const
Definition Decl.h:3922
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:761
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9167
QualType getType() const
Definition Decl.h:723
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isAlignedAllocation(AlignedAllocationMode Mode)
Definition ExprCXX.h:2267
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
bool isTypeAwareAllocation(TypeAwareAllocationMode Mode)
Definition ExprCXX.h:2255
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool objCLifetime()
static bool addressSpace()
static bool ehCleanupScope()
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:2346
TypeAwareAllocationMode TypeAwareDelete
Definition ExprCXX.h:2347
AlignedAllocationMode Alignment
Definition ExprCXX.h:2350