18#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
19#include "mlir/IR/Attributes.h"
22#include "llvm/ADT/FloatingPointMode.h"
23#include "llvm/Support/TypeSize.h"
32 void *buffer =
operator new(
33 totalSizeToAlloc<CanQualType>(
argTypes.size() + 1));
37 CIRGenFunctionInfo *fi =
new (buffer) CIRGenFunctionInfo();
42 fi->required = required;
45 fi->getArgTypes()[0] = resultType;
65 return cir::FuncType::get(argTypes,
66 (resultType ? resultType : builder.getVoidTy()),
92 mlir::OpBuilder::InsertionGuard guard(builder);
93 builder.setInsertionPointAfter(value.getDefiningOp());
98 mlir::NamedAttrList &attrs,
105 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
106 mlir::UnitAttr::get(builder.getContext()));
110 mlir::NamedAttrList &attrs,
112 const NoBuiltinAttr *nba =
nullptr) {
116 if (langOpts.NoBuiltin ||
117 (nba && llvm::is_contained(nba->builtinNames(),
"*"))) {
120 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
121 mlir::ArrayAttr::get(&ctx, {}));
125 llvm::SetVector<mlir::Attribute> nbFuncs;
126 auto addNoBuiltinAttr = [&ctx, &nbFuncs](StringRef builtinName) {
127 nbFuncs.insert(mlir::StringAttr::get(&ctx, builtinName));
136 llvm::for_each(nba->builtinNames(), addNoBuiltinAttr);
138 if (!nbFuncs.empty())
139 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
140 mlir::ArrayAttr::get(&ctx, nbFuncs.getArrayRef()));
147 llvm::DenormalMode fp32DenormalMode,
148 mlir::NamedAttrList &attrs) {
160 mlir::NamedAttrList &attrs) {
165static llvm::StringLiteral
168 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip:
169 llvm_unreachable(
"No string value, shouldn't be able to get here");
170 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg:
171 return "used-gpr-arg";
172 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR:
174 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg:
176 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used:
178 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg:
179 return "all-gpr-arg";
180 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR:
182 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg:
184 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All:
188 llvm_unreachable(
"Unknown kind?");
195 mlir::MLIRContext *mlirCtx, StringRef name,
bool hasOptNoneAttr,
197 bool attrOnCallSite, mlir::NamedAttrList &attrs) {
200 if (!hasOptNoneAttr) {
201 if (codeGenOpts.OptimizeSize)
202 attrs.set(cir::CIRDialect::getOptimizeForSizeAttrName(),
203 mlir::UnitAttr::get(mlirCtx));
204 if (codeGenOpts.OptimizeSize == 2)
205 attrs.set(cir::CIRDialect::getMinSizeAttrName(),
206 mlir::UnitAttr::get(mlirCtx));
212 if (attrOnCallSite) {
215 attrs.set(cir::CIRDialect::getNoBuiltinAttrName(),
216 mlir::UnitAttr::get(mlirCtx));
219 attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
220 mlir::StringAttr::get(mlirCtx, codeGenOpts.
TrapFuncName));
235 if (codeGenOpts.getZeroCallUsedRegs() ==
236 llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
237 attrs.erase(cir::CIRDialect::getZeroCallUsedRegsAttrName());
239 attrs.set(cir::CIRDialect::getZeroCallUsedRegsAttrName(),
240 mlir::StringAttr::get(mlirCtx,
242 codeGenOpts.getZeroCallUsedRegs())));
251 attrs.set(cir::CIRDialect::getConvergentAttrName(),
252 mlir::UnitAttr::get(mlirCtx));
258 if (codeGenOpts.SaveRegParams && !attrOnCallSite)
259 attrs.set(cir::CIRDialect::getSaveRegParamsAttrName(),
260 mlir::UnitAttr::get(mlirCtx));
269 [mlirCtx](llvm::StringRef arg) {
270 auto [var, value] = arg.split(
'=');
273 ? cast<mlir::Attribute>(mlir::UnitAttr::get(mlirCtx))
274 : cast<mlir::Attribute>(mlir::StringAttr::get(mlirCtx, value));
275 return mlir::NamedAttribute(var, valueAttr);
278 if (!defaultFuncAttrs.empty())
279 attrs.set(cir::CIRDialect::getDefaultFuncAttrsAttrName(),
280 mlir::DictionaryAttr::get(mlirCtx, defaultFuncAttrs));
292 mlir::NamedAttrList &attrs) {
295 codeGenOpts, langOpts, attrOnCallSite,
298 if (!attrOnCallSite) {
311 mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv,
312 cir::SideEffect &sideEffect,
bool attrOnCallSite,
bool isThunk) {
314 sideEffect = cir::SideEffect::All;
316 auto addUnitAttr = [&](llvm::StringRef name) {
321 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
333 const NoBuiltinAttr *nba =
nullptr;
339 if (targetDecl->
hasAttr<NoThrowAttr>())
340 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
345 if (targetDecl->
hasAttr<NoReturnAttr>())
346 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
347 if (targetDecl->
hasAttr<ReturnsTwiceAttr>())
348 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
349 if (targetDecl->
hasAttr<ColdAttr>())
350 addUnitAttr(cir::CIRDialect::getColdAttrName());
351 if (targetDecl->
hasAttr<HotAttr>())
352 addUnitAttr(cir::CIRDialect::getHotAttrName());
353 if (targetDecl->
hasAttr<NoDuplicateAttr>())
354 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
355 if (targetDecl->
hasAttr<ConvergentAttr>())
356 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
358 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
372 if (func->isNoReturn())
373 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
374 nba = func->getAttr<NoBuiltinAttr>();
381 if (targetDecl->
hasAttr<ConstAttr>()) {
384 sideEffect = cir::SideEffect::Const;
385 }
else if (targetDecl->
hasAttr<PureAttr>()) {
387 sideEffect = cir::SideEffect::Pure;
390 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
395 if (targetDecl->
hasAttr<AnyX86NoCallerSavedRegistersAttr>())
396 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
399 if (targetDecl->
hasAttr<LeafAttr>())
400 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
404 if (
auto *allocSizeAttr = targetDecl->
getAttr<AllocSizeAttr>()) {
405 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
407 if (allocSizeAttr->getNumElemsParam().isValid()) {
408 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
409 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
410 builder.getDenseI32ArrayAttr(
411 {static_cast<int>(size), static_cast<int>(numElts)}));
413 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
414 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
421 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
422 targetDecl->
hasAttr<CUDAGlobalAttr>()) {
426 auto attr = cir::CUDAKernelNameAttr::get(
429 attrs.set(
attr.getMnemonic(),
attr);
434 if (
auto *modularFormat = targetDecl->
getAttr<ModularFormatAttr>()) {
436 StringRef
type =
format->getType()->getName();
437 std::string formatIdx = std::to_string(
format->getFormatIdx());
438 std::string firstArg = std::to_string(
format->getFirstArg());
440 type, formatIdx, firstArg,
441 modularFormat->getModularImplFn()->getName(),
442 modularFormat->getImplName()};
443 llvm::append_range(args, modularFormat->aspects());
444 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
445 builder.getStringAttr(llvm::join(args,
",")));
451 bool hasOptNoneAttr = targetDecl && targetDecl->
hasAttr<OptimizeNoneAttr>();
463 if (targetDecl->
hasAttr<ZeroCallUsedRegsAttr>()) {
466 targetDecl->
getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
468 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
469 mlir::StringAttr::get(
471 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(
kind)));
474 if (targetDecl->
hasAttr<NoConvergentAttr>())
475 attrs.erase(cir::CIRDialect::getConvergentAttrName());
485 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
486 constructFunctionArgumentAttributes(info, isThunk, argAttrs);
489bool CIRGenModule::hasStrictReturn(
QualType retTy,
const Decl *targetDecl) {
495 if (
getLangOpts().Sanitize.has(SanitizerKind::Memory))
502 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
503 if (func->isExternC())
505 }
else if (
const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
507 if (var->isExternC())
520bool CIRGenModule::mayDropFunctionReturn(
const ASTContext &context,
524 if (
const RecordType *recTy =
526 if (
const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
527 return record->hasTrivialDestructor();
570 if (
const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
582 if (langOpts.NoHonorInfs)
584 if (langOpts.NoHonorNaNs)
589void CIRGenModule::constructFunctionReturnAttributes(
591 mlir::NamedAttrList &retAttrs) {
597 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
600 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
605 retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
606 builder.getI64IntegerAttr(mask));
612 if (
const auto *refTy = retTy->
getAs<ReferenceType>()) {
613 QualType pointeeTy = refTy->getPointeeType();
615 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
616 builder.getI64IntegerAttr(
619 if (
getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
620 !codeGenOpts.NullPointerIsValid)
621 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
625 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
626 builder.getI64IntegerAttr(
632void CIRGenModule::constructFunctionArgumentAttributes(
634 llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
642 QualType thisPtrTy = info.
arguments()[0];
648 if (!codeGenOpts.NullPointerIsValid &&
649 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
650 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
651 builder.getI64IntegerAttr(
653 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
660 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
661 builder.getI64IntegerAttr(
bytes));
665 mlir::LLVM::LLVMDialect::getAlignAttrName(),
666 builder.getI64IntegerAttr(
683 for (
const auto &[argAttrList, argCanType] :
684 llvm::zip_equal(argAttrs, info.
arguments())) {
686 QualType argType = argCanType;
689 if (codeGenOpts.EnableNoundefAttrs &&
691 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
699 if (
const auto *refTy = argType->
getAs<ReferenceType>()) {
702 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
703 builder.getI64IntegerAttr(
705 if (
getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
706 !codeGenOpts.NullPointerIsValid)
707 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
711 mlir::LLVM::LLVMDialect::getAlignAttrName(),
712 builder.getI64IntegerAttr(
718 argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
719 builder.getI64IntegerAttr(mask));
738 if (!fpt->hasExtParameterInfos()) {
739 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
753 bool passParams =
true;
755 if (
auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
758 if (
auto inherited = cd->getInheritedConstructor())
769 theCXXABI.buildStructorSignature(gd, argTypes);
773 (passParams && md->isVariadic() ?
RequiredArgs(argTypes.size())
776 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
777 : theCXXABI.hasMostDerivedReturn(gd)
778 ? astContext.VoidPtrTy
781 assert(!theCXXABI.hasThisReturn(gd) &&
782 "Please send PR with a test and remove this");
788 fpt->getExtInfo(), required);
804 cgm.errorNYI(
"deriveThisType: no record decl");
827 fpt->getExtInfo(), required);
839 if (
type->getAsCXXRecordDecl()) {
841 "emitDelegateCallArg: record argument");
847 if (
type->isReferenceType()) {
853 "emitDelegateCallArg: ObjCAutoRefCount");
862 if (
type->isRecordType() &&
863 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
866 "emitDelegateCallArg: callee-destructed param");
877 if (
const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
878 if (proto->isVariadic())
880 if (proto->hasExtParameterInfos())
881 cgm.
errorNYI(
"call to functions with extra parameter info");
884 cgm.
errorNYI(
"call to function without a prototype");
887 for (
const CallArg &arg : args)
905 unsigned extraPrefixArgs,
unsigned extraSuffixArgs,
bool passProtoArgs) {
909 for (
const auto &arg : args)
910 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
913 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
918 fpt, totalPrefixArgs + extraSuffixArgs)
922 if (theCXXABI.hasThisReturn(gd))
924 "arrangeCXXConstructorCall: hasThisReturn");
925 if (theCXXABI.hasMostDerivedReturn(gd))
927 "arrangeCXXConstructorCall: hasMostDerivedReturn");
934 fpt->getExtInfo(), required);
945 assert(numPrefixArgs + 1 <= args.size() &&
946 "Emitting a call with less args than the required prefix?");
950 for (
const CallArg &arg : args)
951 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
956 true, argTypes, proto->
getExtInfo(), required);
979 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1001 return ::arrangeCIRFunctionInfo(
1002 *
this,
true, argTypes,
1010 if (
const auto *md = dyn_cast<CXXMethodDecl>(fd))
1011 if (md->isInstance())
1047 if (!ac.
getDecl() || !(
sanOpts.has(SanitizerKind::NonnullAttribute) ||
1048 sanOpts.has(SanitizerKind::NullabilityArg)))
1050 cgm.errorNYI(
"non-null arg check is NYI");
1053static cir::CIRCallOpInterface
1055 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1056 cir::FuncOp directFuncOp,
1058 const mlir::NamedAttrList &attrs,
1060 const mlir::NamedAttrList &retAttrs) {
1065 assert(builder.getInsertionBlock() &&
"expected valid basic block");
1068 if (indirectFuncTy) {
1072 cirCallArgs, attrs, argAttrs, retAttrs);
1074 op = builder.
createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1075 argAttrs, retAttrs);
1085 return ::arrangeCIRFunctionInfo(*
this,
false, argTypes,
1101 cir::CIRCallOpInterface *callOp,
1102 mlir::Location loc) {
1111 for (
auto [argNo, arg, canQualArgType] :
1112 llvm::enumerate(args, funcInfo.
argTypes())) {
1118 if (!mlir::isa<cir::RecordType>(argType) &&
1119 !mlir::isa<cir::ComplexType>(argType)) {
1121 if (arg.isAggregate())
1122 cgm.errorNYI(loc,
"emitCall: aggregate call argument");
1123 v = arg.getKnownRValue().getValue();
1126 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1127 cgm.errorNYI(loc,
"emitCall: widening integer call argument");
1131 if (argType != v.getType()) {
1132 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1133 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1134 if (argPtrTy && vPtrTy &&
1135 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1136 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1146 cirCallArgs[argNo] = v;
1149 if (!arg.isAggregate()) {
1151 arg.copyInto(*
this, src, loc);
1153 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1154 : arg.getKnownRValue().getAggregateAddress();
1161 mlir::Location argLoc = loc;
1174 if (srcTy != argType) {
1175 cgm.errorNYI(loc,
"emitCall: source type does not match argument type");
1191 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1200 mlir::NamedAttrList attrs;
1201 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.
arguments().size());
1202 mlir::NamedAttrList retAttrs;
1204 if (
auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1205 funcName = calleeFuncOp.getName();
1209 cir::CallingConv callingConv;
1210 cir::SideEffect sideEffect;
1212 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1215 cir::FuncType indirectFuncTy;
1216 mlir::Value indirectFuncVal;
1217 cir::FuncOp directFuncOp;
1218 if (
auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
1219 directFuncOp = fnOp;
1220 }
else if (
auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
1225 mlir::Operation *globalOp =
cgm.getGlobalValue(getGlobalOp.getName());
1226 assert(globalOp &&
"undefined global function");
1227 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
1229 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1230 calleePtr->getResultTypes();
1231 [[maybe_unused]]
auto funcPtrTy =
1232 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1233 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1234 "expected pointer to function");
1236 indirectFuncTy = cirFuncTy;
1237 indirectFuncVal = calleePtr->getResult(0);
1244 bool cannotThrow = attrs.getNamed(
"nothrow").has_value();
1247 mlir::Location callLoc = loc;
1248 cir::CIRCallOpInterface theCall =
1249 emitCallLikeOp(*
this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1250 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1268 mlir::ResultRange results = theCall->getOpResults();
1269 assert(results.size() <= 1 &&
"multiple returns from a call");
1276 mlir::ResultRange results = theCall->getOpResults();
1277 assert(results.size() == 1 &&
"unexpected number of returns");
1281 if (results[0].
getType() != retCIRTy)
1282 cgm.errorNYI(loc,
"bitcast on function return value");
1284 mlir::Region *region = builder.getBlock()->getParent();
1285 if (region != theCall->getParentRegion())
1286 cgm.errorNYI(loc,
"function calls with cleanup");
1291 mlir::ResultRange results = theCall->getOpResults();
1292 assert(!results.empty() &&
1293 "Expected at least one result for complex rvalue");
1297 llvm_unreachable(
"Invalid evaluation kind");
1301 mlir::Location loc)
const {
1303 if (!hasLV &&
rv.isScalar())
1305 else if (!hasLV &&
rv.isComplex())
1315 mlir::NamedAttrList attrs) {
1319 cir::CallOp call = builder.createCallOp(loc, callee, args);
1320 assert(call->getNumResults() <= 1 &&
1321 "runtime functions have at most 1 result");
1324 call->setAttrs(attrs);
1326 if (call->getNumResults() == 0)
1329 return call->getResult(0);
1335 "reference binding to unmaterialized r-value!");
1351 bool destroyedInCallee =
true;
1353 destroyedInCallee = rd->hasNonTrivialDestructor();
1355 if (destroyedInCallee)
1360 args.
add(rv, argType);
1362 if (destroyedInCallee &&
getLangOpts().Exceptions)
1364 "callee-destructed param with exceptions");
1379QualType CIRGenFunction::getVarArgType(
const Expr *arg) {
1384 return arg->getType();
1387 cgm.
errorNYI(arg->getSourceRange(),
"getVarArgType: NYI for Windows target");
1388 return arg->getType();
1405 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1412 bool isVariadic =
false;
1417 isVariadic = fpt->isVariadic();
1419 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1420 fpt->param_type_end());
1424 for (
const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1425 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1426 assert(argTypes.size() == (
size_t)(argRange.end() - argRange.begin()));
1433 auto leftToRight =
true;
1436 auto maybeEmitImplicitObjectSize = [&](
size_t i,
const Expr *arg,
1445 cgm.errorNYI(
"emit implicit object size for call arg");
1449 size_t callArgsStart = args.size();
1450 for (
size_t i = 0; i != argTypes.size(); ++i) {
1451 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1453 size_t initialArgSize = args.size();
1459 assert(initialArgSize + 1 == args.size() &&
1460 "The code below depends on only adding one arg per emitCallArg");
1461 (void)initialArgSize;
1465 if (!args.back().hasLValue()) {
1466 RValue rvArg = args.back().getKnownRValue();
1468 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1472 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 unsigned getNoFPClassTestMask(const LangOptions &langOpts)
Compute the nofpclass mask for FP types based on language options.
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...
static StringRef getTriple(const Command &Job)
*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.
const TargetInfo & getTargetInfo() const
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
mlir::Type getElementType() const
void setExternallyDestructed(bool destructed=true)
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::Decl * getDecl() 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)
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
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.
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
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()
void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc, AbstractCallee ac, unsigned paramNum)
Create a check for a function parameter that may potentially be declared as non-null.
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...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
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 getNaturalPointeeTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
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)
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.
bool inheritingCtorHasParams(const InheritedConstructor &inherited, CXXCtorType type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
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.
bool constructsVirtualBase() const
Returns true if the constructed base class is a virtual base class subobject of this declaration's cl...
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.
CXXCtorType getCtorType() const
GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind)
const Decl * getDecl() const
Description of a constructor that was inherited from a base class.
ConstructorUsingShadowDecl * getShadowDecl() 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 hasConstructorVariants() const
Does this ABI have different entrypoints for complete-object and base-subobject constructors?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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,...
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
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.
@ Ctor_Complete
Complete object ctor.
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.