28 void *buffer =
operator new(
29 totalSizeToAlloc<CanQualType>(
argTypes.size() + 1));
35 fi->required = required;
38 fi->getArgTypes()[0] = resultType;
58 return cir::FuncType::get(argTypes,
59 (resultType ? resultType : builder.
getVoidTy()),
68 cgm.
errorNYI(
"getFunctionTypeForVTable: non-convertible function type");
95 mlir::OpBuilder::InsertionGuard guard(builder);
96 builder.setInsertionPointAfter(value.getDefiningOp());
101 mlir::NamedAttrList &attrs,
108 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
109 mlir::UnitAttr::get(builder.getContext()));
114 mlir::NamedAttrList &attrs) {
116 auto sideEffect = cir::SideEffect::All;
124 if (targetDecl->
hasAttr<NoThrowAttr>())
125 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
128 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
137 if (targetDecl->
hasAttr<ConstAttr>()) {
140 sideEffect = cir::SideEffect::Const;
141 }
else if (targetDecl->
hasAttr<PureAttr>()) {
143 sideEffect = cir::SideEffect::Pure;
151 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
170 if (!fpt->hasExtParameterInfos()) {
171 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
180 auto *md = cast<CXXMethodDecl>(gd.
getDecl());
185 bool passParams =
true;
187 if (
auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
190 if (cd->getInheritedConstructor())
192 "arrangeCXXStructorDeclaration: inheriting constructor");
203 (passParams && md->isVariadic() ?
RequiredArgs(argTypes.size())
212 "Please send PR with a test and remove this");
233 cgm.
errorNYI(
"deriveThisType: no record decl");
266 if (
type->getAsCXXRecordDecl()) {
268 "emitDelegateCallArg: record argument");
274 if (
type->isReferenceType()) {
280 "emitDelegateCallArg: ObjCAutoRefCount");
289 if (
type->isRecordType() &&
290 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
293 "emitDelegateCallArg: callee-destructed param");
304 if (
const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
305 if (proto->isVariadic())
307 if (proto->hasExtParameterInfos())
308 cgm.
errorNYI(
"call to functions with extra parameter info");
310 cast<FunctionNoProtoType>(fnType)))
311 cgm.
errorNYI(
"call to function without a prototype");
314 for (
const CallArg &arg : args)
331 bool passProtoArgs) {
335 for (
const auto &arg : args)
340 unsigned totalPrefixArgs = 1;
351 "arrangeCXXConstructorCall: hasThisReturn");
354 "arrangeCXXConstructorCall: hasMostDerivedReturn");
371 assert(numPrefixArgs + 1 <= args.size() &&
372 "Emitting a call with less args than the required prefix?");
376 for (
const CallArg &arg : args)
397 assert(!isa<CXXConstructorDecl>(md) &&
"wrong method for constructors!");
398 assert(!isa<CXXDestructorDecl>(md) &&
"wrong method for destructors!");
428 return ::arrangeCIRFunctionInfo(
437 if (
const auto *md = dyn_cast<CXXMethodDecl>(fd))
438 if (md->isInstance())
443 assert(isa<FunctionType>(funcTy));
460static cir::CIRCallOpInterface
462 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
463 cir::FuncOp directFuncOp,
465 const mlir::NamedAttrList &attrs) {
471 assert(builder.getInsertionBlock() &&
"expected valid basic block");
474 if (indirectFuncTy) {
480 op = builder.
createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);
490 return ::arrangeCIRFunctionInfo(*
this, argTypes, fpt);
504 cir::CIRCallOpInterface *callOp,
505 mlir::Location loc) {
514 for (
auto [argNo, arg, canQualArgType] :
515 llvm::enumerate(args, funcInfo.
argTypes())) {
521 if (!mlir::isa<cir::RecordType>(argType)) {
523 if (arg.isAggregate())
524 cgm.
errorNYI(loc,
"emitCall: aggregate call argument");
525 v = arg.getKnownRValue().getValue();
528 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
529 cgm.
errorNYI(loc,
"emitCall: widening integer call argument");
536 cirCallArgs[argNo] = v;
539 if (!arg.isAggregate())
540 cgm.
errorNYI(loc,
"emitCall: non-aggregate call argument");
542 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
543 : arg.getKnownRValue().getAggregateAddress();
547 auto argRecordTy = cast<cir::RecordType>(argType);
550 mlir::Location argLoc = loc;
563 if (srcTy != argRecordTy) {
564 cgm.
errorNYI(loc,
"emitCall: source type does not match argument type");
580 cirCallArgs[argNo] = builder.
createLoad(argLoc, src);
589 mlir::NamedAttrList attrs;
591 if (
auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
592 funcName = calleeFuncOp.getName();
600 cir::FuncType indirectFuncTy;
601 mlir::Value indirectFuncVal;
602 cir::FuncOp directFuncOp;
603 if (
auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
605 }
else if (
auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
611 assert(globalOp &&
"undefined global function");
612 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
614 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
615 calleePtr->getResultTypes();
616 [[maybe_unused]]
auto funcPtrTy =
617 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
618 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
619 "expected pointer to function");
621 indirectFuncTy = cirFuncTy;
622 indirectFuncVal = calleePtr->getResult(0);
625 mlir::Location callLoc = loc;
626 cir::CIRCallOpInterface theCall =
627 emitCallLikeOp(*
this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
637 if (isa<cir::VoidType>(retCIRTy))
646 mlir::ResultRange results = theCall->getOpResults();
647 assert(results.size() <= 1 &&
"multiple returns from a call");
654 mlir::ResultRange results = theCall->getOpResults();
655 assert(results.size() == 1 &&
"unexpected number of returns");
659 if (results[0].getType() != retCIRTy)
660 cgm.
errorNYI(loc,
"bitcast on function return value");
662 mlir::Region *region = builder.getBlock()->getParent();
663 if (region != theCall->getParentRegion())
669 cgm.
errorNYI(loc,
"unsupported evaluation kind of function call result");
672 llvm_unreachable(
"Invalid evaluation kind");
678 "reference binding to unmaterialized r-value!");
696 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
697 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
707QualType CIRGenFunction::getVarArgType(
const Expr *arg) {
711 if (!
getTarget().getTriple().isOSWindows())
712 return arg->getType();
715 cgm.
errorNYI(arg->getSourceRange(),
"getVarArgType: NYI for Windows target");
716 return arg->getType();
733 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
740 bool isVariadic =
false;
744 const auto *fpt = cast<const FunctionProtoType *>(prototype.
p);
745 isVariadic = fpt->isVariadic();
747 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
748 fpt->param_type_end());
752 for (
const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
753 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
754 assert(argTypes.size() == (
size_t)(argRange.end() - argRange.begin()));
761 auto leftToRight =
true;
764 auto maybeEmitImplicitObjectSize = [&](
size_t i,
const Expr *arg,
773 cgm.
errorNYI(
"emit implicit object size for call arg");
777 size_t callArgsStart = args.size();
778 for (
size_t i = 0; i != argTypes.size(); ++i) {
779 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
781 size_t initialArgSize = args.size();
787 assert(initialArgSize + 1 == args.size() &&
788 "The code below depends on only adding one arg per emitCallArg");
789 (void)initialArgSize;
793 if (!args.back().hasLValue()) {
794 RValue rvArg = args.back().getKnownRValue();
796 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
800 std::reverse(args.begin() + callArgsStart, args.end());
static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal, cir::FuncOp directFuncOp, const SmallVectorImpl< mlir::Value > &cirCallArgs, const mlir::NamedAttrList &attrs)
static const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Arrange the CIR function layout for a value of the given function type, on top of any implicit parame...
static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Adds the formal parameters in FPT to the given prefix.
static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder, mlir::NamedAttrList &attrs, const FunctionProtoType *fpt)
static CanQual< FunctionProtoType > getFormalType(const CXXMethodDecl *md)
Returns the canonical formal type of the given C++ method.
static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const CallArgList &args, const FunctionType *fnType)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
CanQualType getCanonicalParamType(QualType T) const
Return the canonical parameter type corresponding to the specific potentially non-canonical one.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType getCanonicalTagType(const TagDecl *TD) const
mlir::Type getElementType() const
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
cir::VoidType getVoidTy()
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
virtual const clang::CXXRecordDecl * getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md)
Get the type of the implicit "this" parameter used by a method.
virtual CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty, SourceLocation loc)=0
Build a virtual function pointer in the ABI-specific way.
virtual bool hasThisReturn(clang::GlobalDecl gd) const
Returns true if the given constructor or destructor is one of the kinds that the ABI says returns 'th...
virtual bool hasMostDerivedReturn(clang::GlobalDecl gd) const
Abstract information about a function or function prototype.
clang::GlobalDecl getCalleeDecl() const
const clang::FunctionProtoType * getCalleeFunctionProtoType() const
CIRGenCalleeInfo getAbstractInfo() const
clang::GlobalDecl getVirtualMethodDecl() const
CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const
If this is a delayed callee computation of some sort, prepare a concrete callee.
Address getThisAddress() const
cir::FuncType getVirtualFunctionType() const
const clang::CallExpr * getVirtualCallExpr() const
mlir::Operation * getFunctionPointer() const
CanQualType getReturnType() const
unsigned getNumRequiredArgs() const
llvm::MutableArrayRef< CanQualType > argTypes()
llvm::ArrayRef< CanQualType > requiredArguments() const
const_arg_iterator argTypesBegin() const
static CIRGenFunctionInfo * create(CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
An abstract representation of regular/ObjC call/message targets.
bool hasFunctionDecl() const
unsigned getNumParams() const
const clang::ParmVarDecl * getParamDecl(unsigned I) const
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.
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
CIRGenTypes & getTypes() const
const clang::LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitAggregateStore(mlir::Value value, Address dest)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored())
Emit code to compute the specified expression which can have any type.
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
static bool hasAggregateEvaluationKind(clang::QualType type)
RValue emitAnyExprToTemp(const clang::Expr *e)
Similarly to emitAnyExpr(), however, the result will always be accessible even if no aggregate locati...
std::string getCounterAggTmpAsString()
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
CIRGenBuilderTy & getBuilder()
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
void constructAttributeList(CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs)
Get the CIR attributes and calling convention to use for a particular function type.
CIRGenBuilderTy & getBuilder()
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Operation * getGlobalValue(llvm::StringRef ref)
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
This class organizes the cross-module state that is used while lowering AST types to CIR types.
CIRGenModule & getCGModule() const
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md)
C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
const CIRGenFunctionInfo & arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType)
const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)
bool isFuncTypeConvertible(const clang::FunctionType *ft)
Utility to check whether a function type can be converted to a CIR type (i.e.
cir::FuncType getFunctionTypeForVTable(clang::GlobalDecl gd)
Get the CIR function type for use in a vtable, given a CXXMethodDecl.
const CIRGenFunctionInfo & arrangeCXXMethodType(const clang::CXXRecordDecl *rd, const clang::FunctionProtoType *ftp, const clang::CXXMethodDecl *md)
Arrange the argument and result information for a call to an unknown C++ non-static member function o...
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, const clang::CXXMethodDecl *md)
Derives the 'this' type for CIRGen purposes, i.e.
const CIRGenFunctionInfo & arrangeCXXConstructorCall(const CallArgList &args, const clang::CXXConstructorDecl *d, clang::CXXCtorType ctorKind, bool passProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)
Free functions are functions that are compatible with an ordinary C function pointer type.
clang::ASTContext & getASTContext() const
const CIRGenFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const clang::FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)
Arrange a call to a C++ method, passing the given arguments.
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
void addUncopiedAggregate(LValue lvalue, clang::QualType type)
void add(RValue rvalue, clang::QualType type)
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
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...
virtual bool isNoProtoCallVariadic(const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
Represents a C++ constructor within a class.
Represents a static or instance method of a struct/union/class.
Qualifiers getMethodQualifiers() const
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getBeginLoc() const
static CanQual< Type > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
CanProxy< U > castAs() const
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
CanProxy< U > getAs() const
Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Represents a function declaration or definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Represents a prototype with parameter type info, e.g.
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
A (possibly-)qualified type.
LangAS getAddressSpace() const
bool isParamDestroyedInCallee() const
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
RecordDecl * castAsRecordDecl() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represents a variable declaration or definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ OK_Ordinary
An ordinary object is located at an address in memory.
static bool opCallBitcastArg()
static bool opCallCIRGenFuncInfoExtParamInfo()
static bool implicitConstructorArgs()
static bool emitLifetimeMarkers()
static bool lowerAggregateLoadStore()
static bool opCallSurroundingTry()
static bool opCallReturn()
static bool opCallPaddingArgs()
static bool opCallExtParameterInfo()
static bool dataLayoutTypeAllocSize()
static bool opCallObjCMethod()
static bool opCallInAlloca()
static bool opCallCallConv()
static bool opCallAttrs()
static bool opCallImplicitObjectSizeArgs()
static bool opCallMustTail()
static bool cudaSupport()
static bool opCallFnInfoOpts()
static bool opCallCIRGenFuncInfoParamInfo()
llvm::PointerUnion< const clang::FunctionProtoType *, const clang::ObjCMethodDecl * > p
Iterator for iterating over Stmt * arrays that contain only T *.