18#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
19#include "mlir/IR/Attributes.h"
22#include "llvm/ADT/FloatingPointMode.h"
23#include "llvm/ADT/StringSet.h"
24#include "llvm/Support/TypeSize.h"
33 void *buffer =
operator new(
34 totalSizeToAlloc<CanQualType>(
argTypes.size() + 1));
38 CIRGenFunctionInfo *fi =
new (buffer) CIRGenFunctionInfo();
43 fi->required = required;
46 fi->getArgTypes()[0] = resultType;
66 return cir::FuncType::get(argTypes,
67 (resultType ? resultType : builder.getVoidTy()),
93 mlir::OpBuilder::InsertionGuard guard(builder);
94 builder.setInsertionPointAfter(value.getDefiningOp());
99 mlir::NamedAttrList &attrs,
106 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
107 mlir::UnitAttr::get(builder.getContext()));
111 mlir::NamedAttrList &attrs,
113 const NoBuiltinAttr *nba =
nullptr) {
117 if (langOpts.NoBuiltin ||
118 (nba && llvm::is_contained(nba->builtinNames(),
"*"))) {
121 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
122 mlir::ArrayAttr::get(&ctx, {}));
126 llvm::SetVector<mlir::Attribute> nbFuncs;
127 auto addNoBuiltinAttr = [&ctx, &nbFuncs](StringRef builtinName) {
128 nbFuncs.insert(mlir::StringAttr::get(&ctx, builtinName));
137 llvm::for_each(nba->builtinNames(), addNoBuiltinAttr);
139 if (!nbFuncs.empty())
140 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
141 mlir::ArrayAttr::get(&ctx, nbFuncs.getArrayRef()));
148 llvm::DenormalMode fp32DenormalMode,
149 mlir::NamedAttrList &attrs) {
161 mlir::NamedAttrList &attrs) {
166static llvm::StringLiteral
169 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip:
170 llvm_unreachable(
"No string value, shouldn't be able to get here");
171 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg:
172 return "used-gpr-arg";
173 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR:
175 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg:
177 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used:
179 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg:
180 return "all-gpr-arg";
181 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR:
183 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg:
185 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All:
189 llvm_unreachable(
"Unknown kind?");
196 mlir::MLIRContext *mlirCtx, StringRef name,
bool hasOptNoneAttr,
198 bool attrOnCallSite, mlir::NamedAttrList &attrs) {
201 if (!hasOptNoneAttr) {
202 if (codeGenOpts.OptimizeSize)
203 attrs.set(cir::CIRDialect::getOptimizeForSizeAttrName(),
204 mlir::UnitAttr::get(mlirCtx));
205 if (codeGenOpts.OptimizeSize == 2)
206 attrs.set(cir::CIRDialect::getMinSizeAttrName(),
207 mlir::UnitAttr::get(mlirCtx));
213 if (attrOnCallSite) {
216 attrs.set(cir::CIRDialect::getNoBuiltinAttrName(),
217 mlir::UnitAttr::get(mlirCtx));
220 attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
221 mlir::StringAttr::get(mlirCtx, codeGenOpts.
TrapFuncName));
236 if (codeGenOpts.getZeroCallUsedRegs() ==
237 llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
238 attrs.erase(cir::CIRDialect::getZeroCallUsedRegsAttrName());
240 attrs.set(cir::CIRDialect::getZeroCallUsedRegsAttrName(),
241 mlir::StringAttr::get(mlirCtx,
243 codeGenOpts.getZeroCallUsedRegs())));
252 attrs.set(cir::CIRDialect::getConvergentAttrName(),
253 mlir::UnitAttr::get(mlirCtx));
259 if (codeGenOpts.SaveRegParams && !attrOnCallSite)
260 attrs.set(cir::CIRDialect::getSaveRegParamsAttrName(),
261 mlir::UnitAttr::get(mlirCtx));
270 [mlirCtx](llvm::StringRef arg) {
271 auto [var, value] = arg.split(
'=');
274 ? cast<mlir::Attribute>(mlir::UnitAttr::get(mlirCtx))
275 : cast<mlir::Attribute>(mlir::StringAttr::get(mlirCtx, value));
276 return mlir::NamedAttribute(var, valueAttr);
279 if (!defaultFuncAttrs.empty())
280 attrs.set(cir::CIRDialect::getDefaultFuncAttrsAttrName(),
281 mlir::DictionaryAttr::get(mlirCtx, defaultFuncAttrs));
293 mlir::NamedAttrList &attrs) {
296 codeGenOpts, langOpts, attrOnCallSite,
299 if (!attrOnCallSite) {
312 mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv,
313 cir::SideEffect &sideEffect,
bool attrOnCallSite,
bool isThunk) {
315 sideEffect = cir::SideEffect::All;
317 auto addUnitAttr = [&](llvm::StringRef name) {
322 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
334 const NoBuiltinAttr *nba =
nullptr;
340 if (targetDecl->
hasAttr<NoThrowAttr>())
341 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
346 if (targetDecl->
hasAttr<NoReturnAttr>())
347 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
348 if (targetDecl->
hasAttr<ReturnsTwiceAttr>())
349 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
350 if (targetDecl->
hasAttr<ColdAttr>())
351 addUnitAttr(cir::CIRDialect::getColdAttrName());
352 if (targetDecl->
hasAttr<HotAttr>())
353 addUnitAttr(cir::CIRDialect::getHotAttrName());
354 if (targetDecl->
hasAttr<NoDuplicateAttr>())
355 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
356 if (targetDecl->
hasAttr<ConvergentAttr>())
357 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
359 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
373 if (func->isNoReturn())
374 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
375 nba = func->getAttr<NoBuiltinAttr>();
382 if (targetDecl->
hasAttr<ConstAttr>()) {
385 sideEffect = cir::SideEffect::Const;
386 }
else if (targetDecl->
hasAttr<PureAttr>()) {
388 sideEffect = cir::SideEffect::Pure;
391 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
397 if (targetDecl->
hasAttr<ReturnsNonNullAttr>() &&
398 !codeGenOpts.NullPointerIsValid)
399 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
401 if (targetDecl->
hasAttr<AnyX86NoCallerSavedRegistersAttr>())
402 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
405 if (targetDecl->
hasAttr<LeafAttr>())
406 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
410 if (
auto *allocSizeAttr = targetDecl->
getAttr<AllocSizeAttr>()) {
411 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
413 if (allocSizeAttr->getNumElemsParam().isValid()) {
414 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
415 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
416 builder.getDenseI32ArrayAttr(
417 {static_cast<int>(size), static_cast<int>(numElts)}));
419 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
420 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
427 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
428 targetDecl->
hasAttr<CUDAGlobalAttr>()) {
432 auto attr = cir::CUDAKernelNameAttr::get(
435 attrs.set(
attr.getMnemonic(),
attr);
440 if (
auto *modularFormat = targetDecl->
getAttr<ModularFormatAttr>()) {
442 StringRef
type =
format->getType()->getName();
443 std::string formatIdx = std::to_string(
format->getFormatIdx());
444 std::string firstArg = std::to_string(
format->getFirstArg());
446 type, formatIdx, firstArg,
447 modularFormat->getModularImplFn()->getName(),
448 modularFormat->getImplName()};
449 llvm::append_range(args, modularFormat->aspects());
450 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
451 builder.getStringAttr(llvm::join(args,
",")));
457 bool hasOptNoneAttr = targetDecl && targetDecl->
hasAttr<OptimizeNoneAttr>();
469 if (targetDecl->
hasAttr<ZeroCallUsedRegsAttr>()) {
472 targetDecl->
getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
474 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
475 mlir::StringAttr::get(
477 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(
kind)));
480 if (targetDecl->
hasAttr<NoConvergentAttr>())
481 attrs.erase(cir::CIRDialect::getConvergentAttrName());
486 if (!attrOnCallSite) {
490 static const llvm::StringSet<> returnsTwiceFn{
491 "_setjmpex",
"setjmp",
"_setjmp",
"vfork",
492 "sigsetjmp",
"__sigsetjmp",
"savectx",
"getcontext"};
493 if (returnsTwiceFn.contains(name))
494 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
503 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
504 constructFunctionArgumentAttributes(info, targetDecl, isThunk, attrOnCallSite,
508bool CIRGenModule::hasStrictReturn(
QualType retTy,
const Decl *targetDecl) {
514 if (
getLangOpts().Sanitize.has(SanitizerKind::Memory))
521 if (
const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
522 if (func->isExternC())
524 }
else if (
const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
526 if (var->isExternC())
539bool CIRGenModule::mayDropFunctionReturn(
const ASTContext &context,
543 if (
const RecordType *recTy =
545 if (
const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
546 return record->hasTrivialDestructor();
589 if (
const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
601 if (langOpts.NoHonorInfs)
603 if (langOpts.NoHonorNaNs)
608void CIRGenModule::constructFunctionReturnAttributes(
610 mlir::NamedAttrList &retAttrs) {
616 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
619 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
624 retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
625 builder.getI64IntegerAttr(mask));
631 if (
const auto *refTy = retTy->
getAs<ReferenceType>()) {
632 QualType pointeeTy = refTy->getPointeeType();
634 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
635 builder.getI64IntegerAttr(
638 if (
getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
639 !codeGenOpts.NullPointerIsValid)
640 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
644 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
645 builder.getI64IntegerAttr(
651void CIRGenModule::constructFunctionArgumentAttributes(
653 bool attrOnCallSite, llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
659 QualType thisPtrTy = info.
arguments()[0];
665 if (!codeGenOpts.NullPointerIsValid &&
666 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
667 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
668 builder.getI64IntegerAttr(
670 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
677 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
678 builder.getI64IntegerAttr(
bytes));
682 mlir::LLVM::LLVMDialect::getAlignAttrName(),
683 builder.getI64IntegerAttr(
700 const auto *fd = dyn_cast_or_null<FunctionDecl>(targetDecl);
705 SmallVector<const ParmVarDecl *> parmDecls;
706 parmDecls.reserve(argAttrs.size());
709 parmDecls.push_back(
nullptr);
710 parmDecls.insert(parmDecls.end(), fd->param_begin(), fd->param_end());
712 parmDecls.resize(argAttrs.size(),
nullptr);
714 for (
const auto &[argAttrList, argCanType, pvd] :
715 llvm::zip_equal(argAttrs, info.
arguments(), parmDecls)) {
717 QualType argType = argCanType;
720 if (codeGenOpts.EnableNoundefAttrs &&
722 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
730 if (
const auto *refTy = argType->
getAs<ReferenceType>()) {
733 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
734 builder.getI64IntegerAttr(
736 if (
getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
737 !codeGenOpts.NullPointerIsValid)
738 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
742 mlir::LLVM::LLVMDialect::getAlignAttrName(),
743 builder.getI64IntegerAttr(
749 argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
750 builder.getI64IntegerAttr(mask));
754 if (!attrOnCallSite && pvd && pvd->getType()->isPointerType() &&
755 pvd->getType().isRestrictQualified() && !fd->getBuiltinID())
756 argAttrList.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
761 if (pvd && argType->
isAnyPointerType() && !codeGenOpts.NullPointerIsValid) {
762 unsigned srcIdx = pvd->getFunctionScopeIndex();
763 if (pvd->hasAttr<NonNullAttr>() ||
764 (fd->getAttr<NonNullAttr>() &&
765 fd->getAttr<NonNullAttr>()->isNonNull(srcIdx)))
766 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
786 if (!fpt->hasExtParameterInfos()) {
787 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
794 prefix.reserve(prefix.size() + fpt->getNumParams());
796 fpt->getExtParameterInfos();
797 assert(extInfos.size() == fpt->getNumParams());
798 for (
auto [paramType, extInfo] : llvm::zip_equal(
799 llvm::make_range(fpt->param_type_begin(), fpt->param_type_end()),
801 prefix.push_back(paramType);
802 if (extInfo.hasPassObjectSize())
814 bool passParams =
true;
816 if (
auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
819 if (
auto inherited = cd->getInheritedConstructor())
830 theCXXABI.buildStructorSignature(gd, argTypes);
834 (passParams && md->isVariadic() ?
RequiredArgs(argTypes.size())
837 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
838 : theCXXABI.hasMostDerivedReturn(gd)
839 ? astContext.VoidPtrTy
842 assert(!theCXXABI.hasThisReturn(gd) &&
843 "Please send PR with a test and remove this");
849 fpt->getExtInfo(), required);
865 cgm.errorNYI(
"deriveThisType: no record decl");
888 fpt->getExtInfo(), required);
902 if (
type->isReferenceType()) {
908 "emitDelegateCallArg: ObjCAutoRefCount");
917 if (
type->isRecordType() &&
918 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
921 "emitDelegateCallArg: callee-destructed param");
932 if (
const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
934 if (proto->isVariadic())
938 cgm.
errorNYI(
"call to function without a prototype");
941 for (
const CallArg &arg : args)
959 unsigned extraPrefixArgs,
unsigned extraSuffixArgs,
bool passProtoArgs) {
963 for (
const auto &arg : args)
964 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
967 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
972 fpt, totalPrefixArgs + extraSuffixArgs)
976 if (theCXXABI.hasThisReturn(gd))
978 "arrangeCXXConstructorCall: hasThisReturn");
979 if (theCXXABI.hasMostDerivedReturn(gd))
981 "arrangeCXXConstructorCall: hasMostDerivedReturn");
988 fpt->getExtInfo(), required);
999 assert(numPrefixArgs + 1 <= args.size() &&
1000 "Emitting a call with less args than the required prefix?");
1004 for (
const CallArg &arg : args)
1005 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1010 true, argTypes, proto->
getExtInfo(), required);
1033 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1055 return ::arrangeCIRFunctionInfo(
1056 *
this,
true, argTypes,
1064 if (
const auto *md = dyn_cast<CXXMethodDecl>(fd))
1065 if (md->isInstance())
1101 if (!ac.
getDecl() || !(
sanOpts.has(SanitizerKind::NonnullAttribute) ||
1102 sanOpts.has(SanitizerKind::NullabilityArg)))
1104 cgm.errorNYI(
"non-null arg check is NYI");
1107static cir::CIRCallOpInterface
1109 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1110 cir::FuncOp directFuncOp,
1112 const mlir::NamedAttrList &attrs,
1114 const mlir::NamedAttrList &retAttrs) {
1119 assert(builder.getInsertionBlock() &&
"expected valid basic block");
1122 if (indirectFuncTy) {
1126 cirCallArgs, attrs, argAttrs, retAttrs);
1128 op = builder.
createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1129 argAttrs, retAttrs);
1139 return ::arrangeCIRFunctionInfo(*
this,
false, argTypes,
1155 cir::CIRCallOpInterface *callOp,
1156 mlir::Location loc) {
1165 for (
auto [argNo, arg, canQualArgType] :
1166 llvm::enumerate(args, funcInfo.
argTypes())) {
1172 if (!mlir::isa<cir::RecordType>(argType) &&
1173 !mlir::isa<cir::ComplexType>(argType)) {
1175 if (arg.isAggregate())
1176 cgm.errorNYI(loc,
"emitCall: aggregate call argument");
1177 v = arg.getKnownRValue().getValue();
1180 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1181 cgm.errorNYI(loc,
"emitCall: widening integer call argument");
1185 if (argType != v.getType()) {
1186 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1187 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1188 if (argPtrTy && vPtrTy &&
1189 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1190 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1200 cirCallArgs[argNo] = v;
1203 if (!arg.isAggregate()) {
1205 arg.copyInto(*
this, src, loc);
1207 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1208 : arg.getKnownRValue().getAggregateAddress();
1215 mlir::Location argLoc = loc;
1228 if (srcTy != argType) {
1229 cgm.errorNYI(loc,
"emitCall: source type does not match argument type");
1245 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1254 mlir::NamedAttrList attrs;
1255 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.
arguments().size());
1256 mlir::NamedAttrList retAttrs;
1258 if (
auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1259 funcName = calleeFuncOp.getName();
1263 cir::CallingConv callingConv;
1264 cir::SideEffect sideEffect;
1266 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1269 cir::FuncType indirectFuncTy;
1270 mlir::Value indirectFuncVal;
1271 cir::FuncOp directFuncOp;
1272 if (
auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
1273 directFuncOp = fnOp;
1274 }
else if (
auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
1279 mlir::Operation *globalOp =
cgm.getGlobalValue(getGlobalOp.getName());
1280 assert(globalOp &&
"undefined global function");
1281 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
1283 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1284 calleePtr->getResultTypes();
1285 [[maybe_unused]]
auto funcPtrTy =
1286 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1287 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1288 "expected pointer to function");
1290 indirectFuncTy = cirFuncTy;
1291 indirectFuncVal = calleePtr->getResult(0);
1298 bool cannotThrow = attrs.getNamed(
"nothrow").has_value();
1301 mlir::Location callLoc = loc;
1302 cir::CIRCallOpInterface theCall =
1303 emitCallLikeOp(*
this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1304 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1322 mlir::ResultRange results = theCall->getOpResults();
1323 assert(results.size() <= 1 &&
"multiple returns from a call");
1330 mlir::ResultRange results = theCall->getOpResults();
1331 assert(results.size() == 1 &&
"unexpected number of returns");
1335 if (results[0].
getType() != retCIRTy)
1336 cgm.errorNYI(loc,
"bitcast on function return value");
1338 mlir::Region *region = builder.getBlock()->getParent();
1339 if (region != theCall->getParentRegion())
1340 cgm.errorNYI(loc,
"function calls with cleanup");
1345 mlir::ResultRange results = theCall->getOpResults();
1346 assert(!results.empty() &&
1347 "Expected at least one result for complex rvalue");
1351 llvm_unreachable(
"Invalid evaluation kind");
1355 mlir::Location loc)
const {
1357 if (!hasLV &&
rv.isScalar())
1359 else if (!hasLV &&
rv.isComplex())
1369 mlir::NamedAttrList attrs) {
1374 cir::CallOp call = builder.createCallOp(loc, callee, args);
1375 assert(call->getNumResults() <= 1 &&
1376 "runtime functions have at most 1 result");
1379 call->setAttrs(attrs);
1381 if (call->getNumResults() == 0)
1384 return call->getResult(0);
1390 "reference binding to unmaterialized r-value!");
1406 bool destroyedInCallee =
true;
1408 destroyedInCallee = rd->hasNonTrivialDestructor();
1410 if (destroyedInCallee)
1415 args.
add(rv, argType);
1417 if (destroyedInCallee &&
getLangOpts().Exceptions)
1419 "callee-destructed param with exceptions");
1434QualType CIRGenFunction::getVarArgType(
const Expr *arg) {
1439 return arg->getType();
1442 cgm.
errorNYI(arg->getSourceRange(),
"getVarArgType: NYI for Windows target");
1443 return arg->getType();
1460 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1467 bool isVariadic =
false;
1472 isVariadic = fpt->isVariadic();
1474 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1475 fpt->param_type_end());
1479 for (
const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1480 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1481 assert(argTypes.size() == (
size_t)(argRange.end() - argRange.begin()));
1488 auto leftToRight =
true;
1491 auto maybeEmitImplicitObjectSize = [&](
size_t i,
const Expr *arg,
1500 assert(emittedArg.getValue() &&
"We emitted nothing for the arg?");
1503 emittedArg.getValue(), ps->isDynamic());
1509 std::iter_swap(args.rbegin(), std::next(args.rbegin()));
1513 size_t callArgsStart = args.size();
1514 for (
size_t i = 0; i != argTypes.size(); ++i) {
1515 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1517 size_t initialArgSize = args.size();
1523 assert(initialArgSize + 1 == args.size() &&
1524 "The code below depends on only adding one arg per emitCallArg");
1525 (void)initialArgSize;
1529 if (!args.back().hasLValue()) {
1530 RValue rvArg = args.back().getKnownRValue();
1532 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1536 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.
CanQualType getCanonicalSizeType() const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
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.
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
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.
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...
bool isAnyPointerType() const
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 ...
unsigned getNumPassObjectSizeParams(const clang::FunctionProtoType *proto)
Return the number of parameters with the pass_object_size attribute.
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 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.