25struct MemberCallInfo {
39 "Trying to emit a member or operator call expr on a static method!");
54 unsigned prefixSize = args.size() - 1;
69 fpt->getNumParams() == 0 &&
70 "No CallExpr specified for function with non-zero number of arguments");
74 return {required, prefixSize};
84 bool canUseVirtualCall = md->
isVirtual() && !hasQualifier;
100 if (
auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
101 if (oce->isAssignmentOp()) {
102 rtlArgs = &rtlArgStorage;
121 "emitCXXMemberOrOperatorMemberCallExpr: constructor call");
131 devirtualizedMethod ? devirtualizedMethod : md;
133 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl))
134 fInfo = &
cgm.getTypes().arrangeCXXStructorDeclaration(
137 fInfo = &
cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);
139 cir::FuncType ty =
cgm.getTypes().getFunctionType(*fInfo);
150 bool useVirtualCall = canUseVirtualCall && !devirtualizedMethod;
152 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl)) {
154 "Destructor shouldn't have explicit parameters");
155 assert(
returnValue.isNull() &&
"Destructor shouldn't have return value");
156 if (useVirtualCall) {
164 if (!devirtualizedMethod) {
166 cgm.getAddrOfCXXStructor(globalDecl, fInfo, ty), globalDecl);
184 if (useVirtualCall) {
190 "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");
200 cgm.getCXXABI().adjustThisArgumentForVirtualFunctionCall(
201 *
this, calleeDecl, thisPtr.
getAddress(), useVirtualCall);
215 "Trying to emit a member call expr on a static method!");
228 *
this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);
229 auto &fnInfo =
cgm.getTypes().arrangeCXXMethodCall(
230 args, fpt, callInfo.reqArgs, callInfo.prefixSize);
231 assert((ce ||
currSrcLoc) &&
"expected source location");
251 unsigned minElements,
252 mlir::Value &numElements,
253 mlir::Value &sizeWithoutCookie) {
261 return sizeWithoutCookie;
278 llvm::APInt arraySizeMultiplier(sizeWidth, 1);
281 type = cat->getElementType();
282 arraySizeMultiplier *= cat->getSize();
286 llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.
getQuantity());
287 typeSizeMultiplier *= arraySizeMultiplier;
290 llvm::APInt cookieSize(sizeWidth,
300 mlir::Attribute constNumElements =
303 if (constNumElements) {
305 const llvm::APInt &count =
306 mlir::cast<cir::IntAttr>(constNumElements).getValue();
308 unsigned numElementsWidth = count.getBitWidth();
309 bool hasAnyOverflow =
false;
315 assert(!count.isNegative() &&
"Expected non-negative array size");
316 assert(numElementsWidth == sizeWidth &&
317 "Expected a size_t array size constant");
320 llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);
332 llvm::APInt allocationSize =
333 adjustedCount.umul_ov(typeSizeMultiplier, overflow);
336 assert(!overflow &&
"Overflow in array allocation size");
339 if (cookieSize != 0) {
343 loc, allocationSize.zextOrTrunc(sizeWidth));
345 allocationSize = allocationSize.uadd_ov(cookieSize, overflow);
346 hasAnyOverflow |= overflow;
350 if (hasAnyOverflow) {
359 "emitCXXNewAllocSize: variable array size");
363 sizeWithoutCookie = size;
365 assert(sizeWithoutCookie &&
"didn't set sizeWithoutCookie?");
393 llvm_unreachable(
"bad evaluation kind");
398 Address beginPtr, mlir::Value numElements,
399 mlir::Value allocSizeWithoutCookie) {
405 unsigned initListElements = 0;
416 auto constOp = mlir::dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
418 auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constOp.getValue());
420 if (constIntAttr && constIntAttr.getUInt() <= initListElements)
424 assert(init &&
"have trailing elements to initialize but no initializer");
433 if (!cce->requiresZeroInitialization())
436 cgm.errorNYI(cce->getSourceRange(),
437 "emitNewArrayInitializer: trivial ctor zero-init");
441 cgm.errorNYI(cce->getSourceRange(),
442 "emitNewArrayInitializer: ctor initializer");
447 "emitNewArrayInitializer: unsupported initializer");
452 QualType elementType, mlir::Type elementTy,
453 Address newPtr, mlir::Value numElements,
454 mlir::Value allocSizeWithoutCookie) {
458 allocSizeWithoutCookie);
473 "Pointer/Object mixup");
479 implicitParamTy, ce, args,
nullptr);
480 assert((ce || dtor.
getDecl()) &&
"expected source location provider");
482 return emitCall(
cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee,
493 cgm.errorNYI(
expr->getExprLoc(),
494 "emitCXXPseudoDestructorExpr: Objective-C lifetime is NYI");
513 cir::CIRCallOpInterface callOrTryCall;
534 const FunctionDecl *operatorDelete;
535 QualType elementType;
537 CallObjectDelete(mlir::Value ptr,
const FunctionDecl *operatorDelete,
538 QualType elementType)
539 : ptr(ptr), operatorDelete(operatorDelete), elementType(elementType) {}
541 void emit(CIRGenFunction &cgf)
override {
564 if (rd->hasDefinition() && !rd->hasTrivialDestructor()) {
565 dtor = rd->getDestructor();
579 cgf.
ehStack.pushCleanup<CallObjectDelete>(
585 false, ptr, elementType);
620 "emitCXXDeleteExpr: destroying operator delete");
645 unsigned minElements = 0;
647 mlir::Value numElements =
nullptr;
648 mlir::Value allocSizeWithoutCookie =
nullptr;
650 *
this, e, minElements, numElements, allocSizeWithoutCookie);
656 if (allocator->isReservedGlobalPlacementOperator()) {
658 "emitCXXNewExpr: reserved global placement operator");
662 unsigned paramsToSkip = 0;
669 if (allocSize != allocSizeWithoutCookie) {
671 allocAlign = std::max(allocAlign, cookieAlign);
694 allocator->isReplaceableGlobalAllocationFunction()) {
695 const TargetInfo &target =
cgm.getASTContext().getTargetInfo();
696 unsigned allocatorAlign = llvm::bit_floor(std::min<uint64_t>(
698 allocationAlign = std::max(
699 allocationAlign,
getContext().toCharUnitsFromBits(allocatorAlign));
702 mlir::Value allocPtr = rv.
getValue();
704 allocPtr, mlir::cast<cir::PointerType>(allocPtr.getType()).getPointee(),
724 if (allocSize != allocSizeWithoutCookie) {
726 allocation =
cgm.getCXXABI().initializeArrayCookie(
727 *
this, allocation, numElements, e, allocType);
730 mlir::Type elementTy;
739 allocation, elementTy);
745 if (
cgm.getCodeGenOpts().StrictVTablePointers &&
746 allocator->isReservedGlobalPlacementOperator())
752 allocSizeWithoutCookie);
757 mlir::Value ptr,
QualType deleteTy) {
764 auto paramTypeIt = deleteFTy->param_type_begin();
769 "emitDeleteCall: type aware delete");
773 mlir::Value deletePtr =
774 builder.createBitcast(ptr.getLoc(), ptr,
convertType(argTy));
780 "emitDeleteCall: destroying delete");
786 assert(mlir::isa<cir::IntType>(
convertType(sizeType)) &&
787 "expected cir::IntType");
788 cir::ConstantOp size = builder.getConstInt(
797 "emitDeleteCall: aligned allocation");
799 assert(paramTypeIt == deleteFTy->param_type_end() &&
800 "unknown parameter to usual delete function");
807 mlir::Location loc,
QualType destTy) {
809 assert(mlir::isa<cir::PointerType>(destCIRTy) &&
810 "result of dynamic_cast should be a ptr");
813 mlir::Region *currentRegion = cgf.
getBuilder().getBlock()->getParent();
820 cgf.
getBuilder().createBlock(currentRegion, currentRegion->end());
830 cgm.emitExplicitCastExprType(dce,
this);
842 if (isDynCastToVoid) {
853 assert(srcRecordTy->
isRecordType() &&
"source type must be a record type!");
859 auto destCirTy = mlir::cast<cir::PointerType>(
convertType(destTy));
860 return cgm.getCXXABI().emitDynamicCast(*
this, loc, srcRecordTy, destRecordTy,
861 destCirTy, isRefCast, thisAddr);
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 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.
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
const ConstantArrayType * getAsConstantArrayType(QualType T) const
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
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
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())
static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)
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.
void emitNewArrayInitializer(const CXXNewExpr *e, QualType elementType, mlir::Type elementTy, Address beginPtr, mlir::Value numElements, mlir::Value allocSizeWithoutCookie)
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.
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.
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.
void add(RValue rvalue, clang::QualType type)
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.
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.
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
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...
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
Represents a delete expression for memory deallocation and destructor calls, e.g.
FunctionDecl * getOperatorDelete() const
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents a C++ destructor within a class.
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
bool isAlwaysNull() const
isAlwaysNull - Return whether the result of the dynamic_cast is proven to always be null.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
llvm::iterator_range< arg_iterator > placement_arguments()
QualType getAllocatedType() const
std::optional< Expr * > getArraySize()
This might return std::nullopt even if isArray() returns true, since there might not be an array size...
bool hasInitializer() const
Whether this new-expression has any initializer at all.
bool shouldNullCheckAllocation() const
True if the allocation result needs to be null-checked.
bool passAlignment() const
Indicates whether the required alignment should be implicitly passed to the allocation function.
FunctionDecl * getOperatorDelete() const
SourceRange getSourceRange() const
FunctionDecl * getOperatorNew() const
Expr * getInitializer()
The initializer of this new-expression.
A call to an overloaded operator written using operator syntax.
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Represents the canonical version of C arrays with a specified constant size.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
QualType getTypeAsWritten() const
getTypeAsWritten - Returns the type that this expression is casting to, as written in the source code...
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
UsualDeleteParams getUsualDeleteParams() const
bool isReservedGlobalPlacementOperator() const
Determines whether this operator new or delete is one of the reserved global placement operators: voi...
bool isDefaulted() const
Whether this function is defaulted.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Represents a prototype with parameter type info, e.g.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
Describes an C or C++ initializer list.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
bool hasStrongOrWeakObjCLifetime() const
Base for LValueReferenceType and RValueReferenceType.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Exposes information about the current target.
unsigned getNewAlign() const
Return the largest alignment for which a suitably-sized allocation with 'operator new(size_t)' is gua...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isVoidPointerType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
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)
bool isAlignedAllocation(AlignedAllocationMode Mode)
@ Dtor_Complete
Complete object dtor.
bool isTypeAwareAllocation(TypeAwareAllocationMode Mode)
U cast(CodeGen::Address addr)
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.
TypeAwareAllocationMode TypeAwareDelete
AlignedAllocationMode Alignment