18#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
21#include "llvm/Support/TypeSize.h"
30 void *buffer =
operator new(
31 totalSizeToAlloc<CanQualType>(
argTypes.size() + 1));
35 CIRGenFunctionInfo *fi =
new (buffer) CIRGenFunctionInfo();
40 fi->required = required;
43 fi->getArgTypes()[0] = resultType;
63 return cir::FuncType::get(argTypes,
64 (resultType ? resultType : builder.getVoidTy()),
73 cgm.errorNYI(
"getFunctionTypeForVTable: non-convertible function type");
100 mlir::OpBuilder::InsertionGuard guard(builder);
101 builder.setInsertionPointAfter(value.getDefiningOp());
102 builder.createStore(*
currSrcLoc, value, dest);
106 mlir::NamedAttrList &attrs,
113 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
114 mlir::UnitAttr::get(builder.getContext()));
118 mlir::NamedAttrList &attrs,
120 const NoBuiltinAttr *nba =
nullptr) {
124 if (langOpts.NoBuiltin ||
125 (nba && llvm::is_contained(nba->builtinNames(),
"*"))) {
128 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
129 mlir::ArrayAttr::get(&ctx, {}));
133 llvm::SetVector<mlir::Attribute> nbFuncs;
134 auto addNoBuiltinAttr = [&ctx, &nbFuncs](StringRef builtinName) {
135 nbFuncs.insert(mlir::StringAttr::get(&ctx, builtinName));
144 llvm::for_each(nba->builtinNames(), addNoBuiltinAttr);
146 if (!nbFuncs.empty())
147 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
148 mlir::ArrayAttr::get(&ctx, nbFuncs.getArrayRef()));
155 llvm::DenormalMode fp32DenormalMode,
156 mlir::NamedAttrList &attrs) {
168 mlir::NamedAttrList &attrs) {
173static llvm::StringLiteral
176 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip:
177 llvm_unreachable(
"No string value, shouldn't be able to get here");
178 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg:
179 return "used-gpr-arg";
180 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR:
182 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg:
184 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used:
186 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg:
187 return "all-gpr-arg";
188 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR:
190 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg:
192 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All:
196 llvm_unreachable(
"Unknown kind?");
203 mlir::MLIRContext *mlirCtx, StringRef name,
bool hasOptNoneAttr,
205 bool attrOnCallSite, mlir::NamedAttrList &attrs) {
208 if (!hasOptNoneAttr) {
209 if (codeGenOpts.OptimizeSize)
210 attrs.set(cir::CIRDialect::getOptimizeForSizeAttrName(),
211 mlir::UnitAttr::get(mlirCtx));
212 if (codeGenOpts.OptimizeSize == 2)
213 attrs.set(cir::CIRDialect::getMinSizeAttrName(),
214 mlir::UnitAttr::get(mlirCtx));
220 if (attrOnCallSite) {
223 attrs.set(cir::CIRDialect::getNoBuiltinAttrName(),
224 mlir::UnitAttr::get(mlirCtx));
227 attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
228 mlir::StringAttr::get(mlirCtx, codeGenOpts.
TrapFuncName));
243 if (codeGenOpts.getZeroCallUsedRegs() ==
244 llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
245 attrs.erase(cir::CIRDialect::getZeroCallUsedRegsAttrName());
247 attrs.set(cir::CIRDialect::getZeroCallUsedRegsAttrName(),
248 mlir::StringAttr::get(mlirCtx,
250 codeGenOpts.getZeroCallUsedRegs())));
259 attrs.set(cir::CIRDialect::getConvergentAttrName(),
260 mlir::UnitAttr::get(mlirCtx));
266 if (codeGenOpts.SaveRegParams && !attrOnCallSite)
267 attrs.set(cir::CIRDialect::getSaveRegParamsAttrName(),
268 mlir::UnitAttr::get(mlirCtx));
277 [mlirCtx](llvm::StringRef arg) {
278 auto [var, value] = arg.split(
'=');
281 ? cast<mlir::Attribute>(mlir::UnitAttr::get(mlirCtx))
282 : cast<mlir::Attribute>(mlir::StringAttr::get(mlirCtx, value));
283 return mlir::NamedAttribute(var, valueAttr);
286 if (!defaultFuncAttrs.empty())
287 attrs.set(cir::CIRDialect::getDefaultFuncAttrsAttrName(),
288 mlir::DictionaryAttr::get(mlirCtx, defaultFuncAttrs));
300 mlir::NamedAttrList &attrs) {
303 codeGenOpts, langOpts, attrOnCallSite,
306 if (!attrOnCallSite) {
319 mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv,
320 cir::SideEffect &sideEffect,
bool attrOnCallSite,
bool isThunk) {
322 sideEffect = cir::SideEffect::All;
324 auto addUnitAttr = [&](llvm::StringRef name) {
329 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
341 const NoBuiltinAttr *nba =
nullptr;
347 if (targetDecl->
hasAttr<NoThrowAttr>())
348 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
353 if (targetDecl->
hasAttr<NoReturnAttr>())
354 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
355 if (targetDecl->
hasAttr<ReturnsTwiceAttr>())
356 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
357 if (targetDecl->
hasAttr<ColdAttr>())
358 addUnitAttr(cir::CIRDialect::getColdAttrName());
359 if (targetDecl->
hasAttr<HotAttr>())
360 addUnitAttr(cir::CIRDialect::getHotAttrName());
361 if (targetDecl->
hasAttr<NoDuplicateAttr>())
362 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
363 if (targetDecl->
hasAttr<ConvergentAttr>())
364 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
366 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
380 if (func->isNoReturn())
381 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
382 nba = func->getAttr<NoBuiltinAttr>();
389 if (targetDecl->
hasAttr<ConstAttr>()) {
392 sideEffect = cir::SideEffect::Const;
393 }
else if (targetDecl->
hasAttr<PureAttr>()) {
395 sideEffect = cir::SideEffect::Pure;
398 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
403 if (targetDecl->
hasAttr<AnyX86NoCallerSavedRegistersAttr>())
404 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
407 if (targetDecl->
hasAttr<LeafAttr>())
408 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
412 if (
auto *allocSizeAttr = targetDecl->
getAttr<AllocSizeAttr>()) {
413 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
415 if (allocSizeAttr->getNumElemsParam().isValid()) {
416 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
417 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
418 builder.getDenseI32ArrayAttr(
419 {static_cast<int>(size), static_cast<int>(numElts)}));
421 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
422 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
429 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
430 targetDecl->
hasAttr<CUDAGlobalAttr>()) {
435 cir::CUDAKernelNameAttr::get(&
getMLIRContext(), kernelName.str());
436 attrs.set(
attr.getMnemonic(),
attr);
441 if (
auto *modularFormat = targetDecl->
getAttr<ModularFormatAttr>()) {
443 StringRef
type =
format->getType()->getName();
444 std::string formatIdx = std::to_string(
format->getFormatIdx());
445 std::string firstArg = std::to_string(
format->getFirstArg());
447 type, formatIdx, firstArg,
448 modularFormat->getModularImplFn()->getName(),
449 modularFormat->getImplName()};
450 llvm::append_range(args, modularFormat->aspects());
451 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
452 builder.getStringAttr(llvm::join(args,
",")));
458 bool hasOptNoneAttr = targetDecl && targetDecl->
hasAttr<OptimizeNoneAttr>();
470 if (targetDecl->
hasAttr<ZeroCallUsedRegsAttr>()) {
473 targetDecl->
getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
475 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
476 mlir::StringAttr::get(
478 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(
kind)));
481 if (targetDecl->
hasAttr<NoConvergentAttr>())
482 attrs.erase(cir::CIRDialect::getConvergentAttrName());
492 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
493 constructFunctionArgumentAttributes(info, isThunk, argAttrs);
496bool CIRGenModule::hasStrictReturn(
QualType retTy,
const Decl *targetDecl) {
502 if (
getLangOpts().Sanitize.has(SanitizerKind::Memory))
509 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
510 if (func->isExternC())
512 }
else if (
const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
514 if (var->isExternC())
527bool CIRGenModule::mayDropFunctionReturn(
const ASTContext &context,
531 if (
const RecordType *recTy =
533 if (
const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
534 return record->hasTrivialDestructor();
577 if (
const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
579 if (
const ArrayType *Array = dyn_cast<ArrayType>(clangTy))
586void CIRGenModule::constructFunctionReturnAttributes(
588 mlir::NamedAttrList &retAttrs) {
594 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
597 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
608 if (
const auto *refTy = retTy->
getAs<ReferenceType>()) {
609 QualType pointeeTy = refTy->getPointeeType();
611 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
612 builder.getI64IntegerAttr(
615 if (
getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
616 !codeGenOpts.NullPointerIsValid)
617 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
621 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
622 builder.getI64IntegerAttr(
628void CIRGenModule::constructFunctionArgumentAttributes(
630 llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
638 QualType thisPtrTy = info.
arguments()[0];
644 if (!codeGenOpts.NullPointerIsValid &&
645 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
646 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
647 builder.getI64IntegerAttr(
649 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
656 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
657 builder.getI64IntegerAttr(
bytes));
660 argAttrs[0].set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
661 builder.getI64IntegerAttr(
678 for (
const auto &[argAttrList, argCanType] :
679 llvm::zip_equal(argAttrs, info.
arguments())) {
681 QualType argType = argCanType;
684 if (codeGenOpts.EnableNoundefAttrs &&
686 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
694 if (
const auto *refTy = argType->
getAs<ReferenceType>()) {
697 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
698 builder.getI64IntegerAttr(
700 if (
getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
701 !codeGenOpts.NullPointerIsValid)
702 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
705 argAttrList.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
706 builder.getI64IntegerAttr(
727 if (!fpt->hasExtParameterInfos()) {
728 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
742 bool passParams =
true;
744 if (
auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
747 if (cd->getInheritedConstructor())
748 cgm.errorNYI(cd->getSourceRange(),
749 "arrangeCXXStructorDeclaration: inheriting constructor");
759 theCXXABI.buildStructorSignature(gd, argTypes);
763 (passParams && md->isVariadic() ?
RequiredArgs(argTypes.size())
766 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
767 : theCXXABI.hasMostDerivedReturn(gd)
768 ? astContext.VoidPtrTy
771 assert(!theCXXABI.hasThisReturn(gd) &&
772 "Please send PR with a test and remove this");
778 fpt->getExtInfo(), required);
794 cgm.errorNYI(
"deriveThisType: no record decl");
817 fpt->getExtInfo(), required);
829 if (
type->getAsCXXRecordDecl()) {
831 "emitDelegateCallArg: record argument");
837 if (
type->isReferenceType()) {
843 "emitDelegateCallArg: ObjCAutoRefCount");
852 if (
type->isRecordType() &&
853 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
856 "emitDelegateCallArg: callee-destructed param");
867 if (
const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
868 if (proto->isVariadic())
870 if (proto->hasExtParameterInfos())
871 cgm.
errorNYI(
"call to functions with extra parameter info");
874 cgm.
errorNYI(
"call to function without a prototype");
877 for (
const CallArg &arg : args)
895 unsigned extraPrefixArgs,
unsigned extraSuffixArgs,
bool passProtoArgs) {
899 for (
const auto &arg : args)
900 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
903 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
908 fpt, totalPrefixArgs + extraSuffixArgs)
912 if (theCXXABI.hasThisReturn(gd))
914 "arrangeCXXConstructorCall: hasThisReturn");
915 if (theCXXABI.hasMostDerivedReturn(gd))
917 "arrangeCXXConstructorCall: hasMostDerivedReturn");
924 fpt->getExtInfo(), required);
935 assert(numPrefixArgs + 1 <= args.size() &&
936 "Emitting a call with less args than the required prefix?");
940 for (
const CallArg &arg : args)
941 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
946 true, argTypes, proto->
getExtInfo(), required);
969 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
991 return ::arrangeCIRFunctionInfo(
992 *
this,
true, argTypes,
1000 if (
const auto *md = dyn_cast<CXXMethodDecl>(fd))
1001 if (md->isInstance())
1034static cir::CIRCallOpInterface
1036 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1037 cir::FuncOp directFuncOp,
1039 const mlir::NamedAttrList &attrs,
1041 const mlir::NamedAttrList &retAttrs) {
1046 assert(builder.getInsertionBlock() &&
"expected valid basic block");
1049 if (indirectFuncTy) {
1053 cirCallArgs, attrs, argAttrs, retAttrs);
1055 op = builder.
createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1056 argAttrs, retAttrs);
1066 return ::arrangeCIRFunctionInfo(*
this,
false, argTypes,
1082 cir::CIRCallOpInterface *callOp,
1083 mlir::Location loc) {
1092 for (
auto [argNo, arg, canQualArgType] :
1093 llvm::enumerate(args, funcInfo.
argTypes())) {
1099 if (!mlir::isa<cir::RecordType>(argType) &&
1100 !mlir::isa<cir::ComplexType>(argType)) {
1102 if (arg.isAggregate())
1103 cgm.errorNYI(loc,
"emitCall: aggregate call argument");
1104 v = arg.getKnownRValue().getValue();
1107 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1108 cgm.errorNYI(loc,
"emitCall: widening integer call argument");
1115 cirCallArgs[argNo] = v;
1118 if (!arg.isAggregate()) {
1120 arg.copyInto(*
this, src, loc);
1122 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1123 : arg.getKnownRValue().getAggregateAddress();
1130 mlir::Location argLoc = loc;
1143 if (srcTy != argType) {
1144 cgm.errorNYI(loc,
"emitCall: source type does not match argument type");
1160 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1169 mlir::NamedAttrList attrs;
1170 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.
arguments().size());
1171 mlir::NamedAttrList retAttrs;
1173 if (
auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1174 funcName = calleeFuncOp.getName();
1178 cir::CallingConv callingConv;
1179 cir::SideEffect sideEffect;
1181 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1184 cir::FuncType indirectFuncTy;
1185 mlir::Value indirectFuncVal;
1186 cir::FuncOp directFuncOp;
1187 if (
auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
1188 directFuncOp = fnOp;
1189 }
else if (
auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
1194 mlir::Operation *globalOp =
cgm.getGlobalValue(getGlobalOp.getName());
1195 assert(globalOp &&
"undefined global function");
1196 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
1198 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1199 calleePtr->getResultTypes();
1200 [[maybe_unused]]
auto funcPtrTy =
1201 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1202 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1203 "expected pointer to function");
1205 indirectFuncTy = cirFuncTy;
1206 indirectFuncVal = calleePtr->getResult(0);
1213 bool cannotThrow = attrs.getNamed(
"nothrow").has_value();
1216 mlir::Location callLoc = loc;
1217 cir::CIRCallOpInterface theCall =
1218 emitCallLikeOp(*
this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1219 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1237 mlir::ResultRange results = theCall->getOpResults();
1238 assert(results.size() <= 1 &&
"multiple returns from a call");
1245 mlir::ResultRange results = theCall->getOpResults();
1246 assert(results.size() == 1 &&
"unexpected number of returns");
1250 if (results[0].
getType() != retCIRTy)
1251 cgm.errorNYI(loc,
"bitcast on function return value");
1253 mlir::Region *region = builder.getBlock()->getParent();
1254 if (region != theCall->getParentRegion())
1255 cgm.errorNYI(loc,
"function calls with cleanup");
1260 mlir::ResultRange results = theCall->getOpResults();
1261 assert(!results.empty() &&
1262 "Expected at least one result for complex rvalue");
1266 llvm_unreachable(
"Invalid evaluation kind");
1270 mlir::Location loc)
const {
1272 if (!hasLV &&
rv.isScalar())
1274 else if (!hasLV &&
rv.isComplex())
1284 mlir::NamedAttrList attrs) {
1288 cir::CallOp call = builder.createCallOp(loc, callee, args);
1289 assert(call->getNumResults() <= 1 &&
1290 "runtime functions have at most 1 result");
1293 call->setAttrs(attrs);
1295 if (call->getNumResults() == 0)
1298 return call->getResult(0);
1304 "reference binding to unmaterialized r-value!");
1333QualType CIRGenFunction::getVarArgType(
const Expr *arg) {
1337 if (!
getTarget().getTriple().isOSWindows())
1338 return arg->getType();
1341 cgm.
errorNYI(arg->getSourceRange(),
"getVarArgType: NYI for Windows target");
1342 return arg->getType();
1359 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1366 bool isVariadic =
false;
1371 isVariadic = fpt->isVariadic();
1373 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1374 fpt->param_type_end());
1378 for (
const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1379 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1380 assert(argTypes.size() == (
size_t)(argRange.end() - argRange.begin()));
1387 auto leftToRight =
true;
1390 auto maybeEmitImplicitObjectSize = [&](
size_t i,
const Expr *arg,
1399 cgm.errorNYI(
"emit implicit object size for call arg");
1403 size_t callArgsStart = args.size();
1404 for (
size_t i = 0; i != argTypes.size(); ++i) {
1405 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1407 size_t initialArgSize = args.size();
1413 assert(initialArgSize + 1 == args.size() &&
1414 "The code below depends on only adding one arg per emitCallArg");
1415 (void)initialArgSize;
1419 if (!args.back().hasLValue()) {
1420 RValue rvArg = args.back().getKnownRValue();
1422 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1426 std::reverse(args.begin() + callArgsStart, args.end());
static StringRef bytes(const std::vector< T, Allocator > &v)
static void addTrivialDefaultFunctionAttributes(mlir::MLIRContext *mlirCtx, StringRef name, bool hasOptNoneAttr, const CodeGenOptions &codeGenOpts, const LangOptions &langOpts, bool attrOnCallSite, mlir::NamedAttrList &attrs)
Add default attributes to a function, which have merge semantics under -mlink-builtin-bitcode and sho...
static void addNoBuiltinAttributes(mlir::MLIRContext &ctx, mlir::NamedAttrList &attrs, const LangOptions &langOpts, const NoBuiltinAttr *nba=nullptr)
static bool determineNoUndef(QualType clangTy, CIRGenTypes &types, const cir::CIRDataLayout &layout, const cir::ABIArgInfo &argInfo)
static void addDenormalModeAttrs(llvm::DenormalMode fpDenormalMode, llvm::DenormalMode fp32DenormalMode, mlir::NamedAttrList &attrs)
Add denormal-fp-math and denormal-fp-math-f32 as appropriate for the requested denormal behavior,...
static void addMergeableDefaultFunctionAttributes(const CodeGenOptions &codeGenOpts, mlir::NamedAttrList &attrs)
Add default attributes to a function, which have merge semantics under -mlink-builtin-bitcode and sho...
static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Adds the formal parameters in FPT to the given prefix.
static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal, cir::FuncOp directFuncOp, const SmallVectorImpl< mlir::Value > &cirCallArgs, bool isInvoke, const mlir::NamedAttrList &attrs, llvm::ArrayRef< mlir::NamedAttrList > argAttrs, const mlir::NamedAttrList &retAttrs)
static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder, mlir::NamedAttrList &attrs, const FunctionProtoType *fpt)
static llvm::StringLiteral getZeroCallUsedRegsKindStr(llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind k)
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)
static const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod, 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...
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
static bool isVirtualCall(const CallExpr *CE)
bool isIndirectAliased() const
static ABIArgInfo getDirect(mlir::Type ty=nullptr)
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, llvm::ArrayRef< mlir::NamedAttrList > argAttrs={}, llvm::ArrayRef< mlir::NamedAttribute > resAttrs={})
bool typeSizeEqualsStoreSize(mlir::Type ty) const
Returns true if no extra padding bits are needed when storing the specified type.
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
Represents an array type, per C99 6.7.5.2 - Array Declarators.
mlir::Type getElementType() const
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
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.
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
cir::ABIArgInfo getReturnInfo() const
unsigned getNumRequiredArgs() const
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, bool instanceMethod, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
llvm::MutableArrayRef< CanQualType > argTypes()
llvm::ArrayRef< CanQualType > requiredArguments() const
bool isInstanceMethod() const
llvm::ArrayRef< CanQualType > arguments() const
const_arg_iterator argTypesBegin() const
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.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
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.
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.
Address returnValue
The temporary alloca to hold the return value.
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...
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
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()
mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={}, mlir::NamedAttrList attrs={})
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
bool isCatchOrCleanupRequired()
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
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.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
void addDefaultFunctionAttributes(StringRef name, bool hasOptNoneAttr, bool attrOnCallSite, mlir::NamedAttrList &attrs)
Helper function for constructAttributeList/others.
CIRGenBuilderTy & getBuilder()
CharUnits getMinimumObjectSize(QualType ty)
Returns the minimum object size for an object of the given type.
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
FIXME: this could likely be a common helper and not necessarily related with codegen.
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 & arrangeCIRFunctionInfo(CanQualType returnType, bool isInstanceMethod, llvm::ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, RequiredArgs required)
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 & arrangeCXXConstructorCall(const CallArgList &args, const clang::CXXConstructorDecl *d, clang::CXXCtorType ctorKind, unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
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...
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 & 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.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void addUncopiedAggregate(LValue lvalue, clang::QualType type)
void add(RValue rvalue, clang::QualType type)
Address getAddress() const
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.
static RValue getComplex(mlir::Value v)
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
ConstExprIterator const_arg_iterator
Represents a canonical, potentially-qualified type.
static CanQual< Type > CreateUnsafe(QualType Other)
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
llvm::DenormalMode FPDenormalMode
The floating-point denormal mode to use.
llvm::DenormalMode FP32DenormalMode
The floating-point denormal mode to use, for float.
std::string TrapFuncName
If not an empty string, trap intrinsics are lowered to calls to this function instead of to trap inst...
std::vector< std::string > DefaultFunctionAttrs
Complex values, per C99 6.2.5p11.
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.
A class which abstracts out some details necessary for making a call.
FunctionType - C99 6.7.5.3 - Function Declarators.
ExtInfo getExtInfo() const
QualType getReturnType() const
GlobalDecl - represents a global declaration.
GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind)
const Decl * getDecl() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::vector< std::string > NoBuiltinFuncs
A list of all -fno-builtin-* function names (e.g., memset).
bool isNoBuiltinFunc(StringRef Name) const
Is this a libc/libm function that is no longer recognized as a builtin because a -fno-builtin-* optio...
SanitizerSet Sanitize
Set of enabled sanitizers.
bool assumeFunctionsAreConvergent() const
Represents a matrix type, as defined in the Matrix Types clang extensions.
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
QualType getCanonicalType() const
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...
bool isVoidPointerType() const
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
bool isScalarType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isBitIntType() const
RecordDecl * castAsRecordDecl() const
bool isMemberPointerType() const
bool isObjectType() const
Determine whether this type is an object type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
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?
Represents a GCC generic vector type.
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
bool isa(CodeGen::Address addr)
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ OK_Ordinary
An ordinary object is located at an address in memory.
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
U cast(CodeGen::Address addr)
static bool opCallBitcastArg()
static bool opCallCIRGenFuncInfoExtParamInfo()
static bool functionUsesSEHTry()
static bool emitLifetimeMarkers()
static bool lowerAggregateLoadStore()
static bool opCallSurroundingTry()
static bool nothrowAttr()
static bool opCallReturn()
static bool opCallPaddingArgs()
static bool opCallExtParameterInfo()
static bool dataLayoutTypeAllocSize()
static bool opCallObjCMethod()
static bool opCallInAlloca()
static bool opCallCallConv()
static bool opFuncCallingConv()
static bool opCallAttrs()
static bool opCallImplicitObjectSizeArgs()
static bool opCallMustTail()
static bool cudaSupport()
static bool opCallFnInfoOpts()
static bool msvcCXXPersonality()
static bool opCallCIRGenFuncInfoParamInfo()
Similar to AddedStructorArgs, but only notes the number of additional arguments.
llvm::PointerUnion< const clang::FunctionProtoType *, const clang::ObjCMethodDecl * > p
RValue getRValue(CIRGenFunction &cgf, mlir::Location loc) const
void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.