clang 24.0.0git
CIRGenCall.cpp
Go to the documentation of this file.
1//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// These classes wrap the information about a call or function definition used
10// to handle ABI compliancy.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIRGenCall.h"
15#include "CIRGenCXXABI.h"
16#include "CIRGenCleanup.h"
17#include "CIRGenFunction.h"
18#include "CIRGenFunctionInfo.h"
19#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
20#include "mlir/IR/Attributes.h"
25#include "llvm/ADT/FloatingPointMode.h"
26#include "llvm/ADT/StringSet.h"
27#include "llvm/Support/TypeSize.h"
28
29using namespace clang;
30using namespace clang::CIRGen;
31
34 bool isInstanceMethod, CanQualType resultType,
36 RequiredArgs required) {
37 // The first slot allocated for arg type slot is for the return value.
38 void *buffer = operator new(
39 totalSizeToAlloc<CanQualType>(argTypes.size() + 1));
40
42
43 CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
44
45 fi->callingConvention = llvm::to_underlying(cirCC);
46 fi->astCallingConvention = info.getCC();
47 fi->noReturn = info.getNoReturn();
48 fi->instanceMethod = isInstanceMethod;
49
50 fi->required = required;
51 fi->numArgs = argTypes.size();
52
53 // requiredArguments() reads getNumRequiredArgs() entries out of the
54 // trailing-object array, so a signature that claims more required arguments
55 // than we have types for reads past the end and hands a null QualType to
56 // convertType.
57 assert((!required.allowsOptionalArgs() ||
58 required.getNumRequiredArgs() <= fi->numArgs) &&
59 "more required arguments than argument types");
60
61 fi->getArgTypes()[0] = resultType;
62 std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());
64
65 return fi;
66}
67
72
74 mlir::Type resultType = convertType(info.getReturnType());
76 argTypes.reserve(info.getNumRequiredArgs());
77
78 for (const CanQualType &argType : info.requiredArguments())
79 argTypes.push_back(convertType(argType));
80
81 return cir::FuncType::get(argTypes,
82 (resultType ? resultType : builder.getVoidTy()),
83 info.isVariadic());
84}
85
87 if (isVirtual()) {
88 const CallExpr *ce = getVirtualCallExpr();
91 ce ? ce->getBeginLoc() : SourceLocation());
92 }
93 return *this;
94}
95
96void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
97 // In classic codegen:
98 // Function to store a first-class aggregate into memory. We prefer to
99 // store the elements rather than the aggregate to be more friendly to
100 // fast-isel.
101 // In CIR codegen:
102 // Emit the most simple cir.store possible (e.g. a store for a whole
103 // record), which can later be broken down in other CIR levels (or prior
104 // to dialect codegen).
105
106 // Stored result for the callers of this function expected to be in the same
107 // scope as the value, don't make assumptions about current insertion point.
108 mlir::OpBuilder::InsertionGuard guard(builder);
109 builder.setInsertionPointAfter(value.getDefiningOp());
110 builder.createStore(getLoc(*currSrcLoc), value, dest);
111}
112
114 mlir::NamedAttrList &attrs,
115 const FunctionProtoType *fpt) {
116 if (!fpt)
117 return;
118
120 fpt->isNothrow())
121 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
122 mlir::UnitAttr::get(builder.getContext()));
123}
124
125static void addNoBuiltinAttributes(mlir::MLIRContext &ctx,
126 mlir::NamedAttrList &attrs,
127 const LangOptions &langOpts,
128 const NoBuiltinAttr *nba = nullptr) {
129 // First, handle the language options passed through -fno-builtin.
130 // or, if there is a wildcard in the builtin names specified through the
131 // attribute, disable them all.
132 if (langOpts.NoBuiltin ||
133 (nba && llvm::is_contained(nba->builtinNames(), "*"))) {
134 // -fno-builtin disables them all.
135 // Empty attribute means 'all'.
136 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
137 mlir::ArrayAttr::get(&ctx, {}));
138 return;
139 }
140
141 llvm::SetVector<mlir::Attribute> nbFuncs;
142 auto addNoBuiltinAttr = [&ctx, &nbFuncs](StringRef builtinName) {
143 nbFuncs.insert(mlir::StringAttr::get(&ctx, builtinName));
144 };
145
146 // Then, add attributes for builtins specified through -fno-builtin-<name>.
147 llvm::for_each(langOpts.NoBuiltinFuncs, addNoBuiltinAttr);
148
149 // Now, let's check the __attribute__((no_builtin("...")) attribute added to
150 // the source.
151 if (nba)
152 llvm::for_each(nba->builtinNames(), addNoBuiltinAttr);
153
154 if (!nbFuncs.empty())
155 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
156 mlir::ArrayAttr::get(&ctx, nbFuncs.getArrayRef()));
157}
158
159/// Add denormal-fp-math and denormal-fp-math-f32 as appropriate for the
160/// requested denormal behavior, accounting for the overriding behavior of the
161/// -f32 case.
162static void addDenormalModeAttrs(llvm::DenormalMode fpDenormalMode,
163 llvm::DenormalMode fp32DenormalMode,
164 mlir::NamedAttrList &attrs) {
165 // TODO(cir): Classic-codegen sets the denormal modes here. There are two
166 // values, both with a string, but it seems that perhaps we could combine
167 // these into a single attribute? It seems a little silly to have two so
168 // similar named attributes that do the same thing.
169}
170
171/// Add default attributes to a function, which have merge semantics under
172/// -mlink-builtin-bitcode and should not simply overwrite any existing
173/// attributes in the linked library.
174static void
176 mlir::NamedAttrList &attrs) {
178 attrs);
179}
180
181static llvm::StringLiteral
182getZeroCallUsedRegsKindStr(llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind k) {
183 switch (k) {
184 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip:
185 llvm_unreachable("No string value, shouldn't be able to get here");
186 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg:
187 return "used-gpr-arg";
188 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR:
189 return "used-gpr";
190 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg:
191 return "used-arg";
192 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used:
193 return "used";
194 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg:
195 return "all-gpr-arg";
196 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR:
197 return "all-gpr";
198 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg:
199 return "all-arg";
200 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All:
201 return "all";
202 }
203
204 llvm_unreachable("Unknown kind?");
205}
206
207/// Add default attributes to a function, which have merge semantics under
208/// -mlink-builtin-bitcode and should not simply overwrite any existing
209/// attributes in the linked library.
211 mlir::MLIRContext *mlirCtx, StringRef name, bool hasOptNoneAttr,
212 const CodeGenOptions &codeGenOpts, const LangOptions &langOpts,
213 bool attrOnCallSite, mlir::NamedAttrList &attrs) {
214 // TODO(cir): Handle optimize attribute flag here.
215 // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
216 if (!hasOptNoneAttr) {
217 if (codeGenOpts.OptimizeSize)
218 attrs.set(cir::CIRDialect::getOptimizeForSizeAttrName(),
219 mlir::UnitAttr::get(mlirCtx));
220 if (codeGenOpts.OptimizeSize == 2)
221 attrs.set(cir::CIRDialect::getMinSizeAttrName(),
222 mlir::UnitAttr::get(mlirCtx));
223 }
224
225 // TODO(cir): Classic codegen adds 'DisableRedZone', 'indirect-tls-seg-refs'
226 // and 'NoImplicitFloat' here.
227
228 if (attrOnCallSite) {
229 // Add the 'nobuiltin' tag, which is different from 'no-builtins'.
230 if (!codeGenOpts.SimplifyLibCalls || langOpts.isNoBuiltinFunc(name))
231 attrs.set(cir::CIRDialect::getNoBuiltinAttrName(),
232 mlir::UnitAttr::get(mlirCtx));
233
234 if (!codeGenOpts.TrapFuncName.empty())
235 attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
236 mlir::StringAttr::get(mlirCtx, codeGenOpts.TrapFuncName));
237 } else {
238 // TODO(cir): Set frame pointer attribute here.
239 // TODO(cir): a number of other attribute 1-offs based on codegen/lang opts
240 // should be done here: less-recise-fpmad null-pointer-is-valid
241 // no-trapping-math
242 // various inf/nan/nsz/etc work here.
243 //
244 // TODO(cir): set stack-protector buffer size attribute (sorted oddly in
245 // classic compiler inside of the above region, but should be done on its
246 // own).
247 // TODO(cir): other attributes here:
248 // reciprocal estimates, prefer-vector-width, stackrealign, backchain,
249 // split-stack, speculative-load-hardening.
250
251 if (codeGenOpts.getZeroCallUsedRegs() ==
252 llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
253 attrs.erase(cir::CIRDialect::getZeroCallUsedRegsAttrName());
254 else
255 attrs.set(cir::CIRDialect::getZeroCallUsedRegsAttrName(),
256 mlir::StringAttr::get(mlirCtx,
258 codeGenOpts.getZeroCallUsedRegs())));
259 }
260
261 if (langOpts.assumeFunctionsAreConvergent()) {
262 // Conservatively, mark all functions and calls in CUDA and OpenCL as
263 // convergent (meaning, they may call an intrinsically convergent op, such
264 // as __syncthreads() / barrier(), and so can't have certain optimizations
265 // applied around them). LLVM will remove this attribute where it safely
266 // can.
267 attrs.set(cir::CIRDialect::getConvergentAttrName(),
268 mlir::UnitAttr::get(mlirCtx));
269 }
270
271 // TODO(cir): Classic codegen adds 'nounwind' here in a bunch of offload
272 // targets.
273
274 if (codeGenOpts.SaveRegParams && !attrOnCallSite)
275 attrs.set(cir::CIRDialect::getSaveRegParamsAttrName(),
276 mlir::UnitAttr::get(mlirCtx));
277
278 // These come in the form of an optional equality sign, so make sure we pass
279 // these on correctly. These will eventually just be passed through to
280 // LLVM-IR, but we want to put them all in 1 array to simplify the
281 // LLVM-MLIR dialect.
282 SmallVector<mlir::NamedAttribute> defaultFuncAttrs;
283 llvm::transform(
284 codeGenOpts.DefaultFunctionAttrs, std::back_inserter(defaultFuncAttrs),
285 [mlirCtx](llvm::StringRef arg) {
286 auto [var, value] = arg.split('=');
287 auto valueAttr =
288 value.empty()
289 ? cast<mlir::Attribute>(mlir::UnitAttr::get(mlirCtx))
290 : cast<mlir::Attribute>(mlir::StringAttr::get(mlirCtx, value));
291 return mlir::NamedAttribute(var, valueAttr);
292 });
293
294 if (!defaultFuncAttrs.empty())
295 attrs.set(cir::CIRDialect::getDefaultFuncAttrsAttrName(),
296 mlir::DictionaryAttr::get(mlirCtx, defaultFuncAttrs));
297
298 // TODO(cir): Do branch protection attributes here.
299}
300
301/// This function matches the behavior of 'getDefaultFunctionAttributes' from
302/// classic codegen, despite the similarity of its name to
303/// 'addDefaultFunctionDefinitionAttributes', which is a caller of this
304/// function.
306 bool hasOptNoneAttr,
307 bool attrOnCallSite,
308 mlir::NamedAttrList &attrs) {
309
311 codeGenOpts, langOpts, attrOnCallSite,
312 attrs);
313
314 if (!attrOnCallSite) {
315 // TODO(cir): Classic codegen adds pointer-auth attributes here, by calling
316 // into TargetCodeGenInfo. At the moment, we've not looked into this as it
317 // is somewhat less used.
318 addMergeableDefaultFunctionAttributes(codeGenOpts, attrs);
319 }
320}
321
322/// Construct the CIR attribute list of a function or call.
324 llvm::StringRef name, const CIRGenFunctionInfo &info,
325 CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs,
327 mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv,
328 bool attrOnCallSite, bool isThunk) {
329 callingConv = info.getCallingConvention();
330
331 auto addUnitAttr = [&](llvm::StringRef name) {
332 attrs.set(name, mlir::UnitAttr::get(&getMLIRContext()));
333 };
334
335 if (info.isNoReturn())
336 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
337
338 // TODO(cir): Implement/check the CSME Nonsecure call attribute here. This
339 // requires being in CSME mode.
340
342 calleeInfo.getCalleeFunctionProtoType());
343
344 const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
345
346 // TODO(cir): OMP Assume Attributes should be here.
347
348 const NoBuiltinAttr *nba = nullptr;
349
350 // TODO(cir): Some work for arg memory effects can be done here, as it is in
351 // classic codegen.
352
353 if (targetDecl) {
354 if (targetDecl->hasAttr<NoThrowAttr>())
355 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
356 // TODO(cir): This is actually only possible if targetDecl isn't a
357 // declarator, which ObjCMethodDecl seems to be the only way to get this to
358 // happen. We're including it here for completeness, but we should add a
359 // test for this when we start generating ObjectiveC.
360 if (targetDecl->hasAttr<NoReturnAttr>())
361 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
362 if (targetDecl->hasAttr<ReturnsTwiceAttr>())
363 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
364 if (targetDecl->hasAttr<ColdAttr>())
365 addUnitAttr(cir::CIRDialect::getColdAttrName());
366 if (targetDecl->hasAttr<HotAttr>())
367 addUnitAttr(cir::CIRDialect::getHotAttrName());
368 if (targetDecl->hasAttr<NoDuplicateAttr>())
369 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
370 if (targetDecl->hasAttr<ConvergentAttr>())
371 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
372
373 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
375 getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
376
377 // TODO(cir): When doing 'return attrs' we need to cover the 'NoAlias' for
378 // global allocation functions here.
380
381 const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
382 bool isVirtualCall = md && md->isVirtual();
383
384 // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
385 // virtual function. These attributes are not inherited by overloads.
386 if (!(attrOnCallSite && isVirtualCall)) {
387 if (func->isNoReturn())
388 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
389 nba = func->getAttr<NoBuiltinAttr>();
390 }
391 }
392
394
395 auto setMemoryEffects = [&](cir::MemoryEffectsAttr effects) {
396 attrs.set(cir::CIRDialect::getMemoryEffectsAttrName(), effects);
397 };
398
399 // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
400 if (targetDecl->hasAttr<ConstAttr>()) {
401 setMemoryEffects(cir::MemoryEffectsAttr::none(&getMLIRContext()));
402 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
403 // gcc specifies that 'const' functions have greater restrictions than
404 // 'pure' functions, so they also cannot have infinite loops.
405 addUnitAttr(cir::CIRDialect::getWillReturnAttrName());
406 } else if (targetDecl->hasAttr<PureAttr>()) {
407 setMemoryEffects(cir::MemoryEffectsAttr::readOnly(&getMLIRContext()));
408 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
409 // gcc specifies that 'pure' functions cannot have infinite loops.
410 addUnitAttr(cir::CIRDialect::getWillReturnAttrName());
411 } else if (targetDecl->hasAttr<NoAliasAttr>()) {
412 setMemoryEffects(
413 cir::MemoryEffectsAttr::inaccessibleOrArgMemOnly(&getMLIRContext()));
414 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
415 }
416
417 // TODO(cir): Add noalias to returns for malloc-like functions
418 // (__attribute__((malloc)) / __declspec(restrict)).
419
420 if (targetDecl->hasAttr<ReturnsNonNullAttr>() &&
421 !codeGenOpts.NullPointerIsValid)
422 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
423 mlir::UnitAttr::get(&getMLIRContext()));
424 if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
425 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
426 // TODO(cir): Implement 'NoCFCheck' attribute here. This requires
427 // fcf-protection mode.
428 if (targetDecl->hasAttr<LeafAttr>())
429 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
430 // TODO(cir): Implement 'BPFFastCall' attribute here. This requires C, and
431 // the BPF target.
432
433 if (auto *allocSizeAttr = targetDecl->getAttr<AllocSizeAttr>()) {
434 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
435
436 if (allocSizeAttr->getNumElemsParam().isValid()) {
437 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
438 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
439 builder.getDenseI32ArrayAttr(
440 {static_cast<int>(size), static_cast<int>(numElts)}));
441 } else {
442 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
443 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
444 }
445 }
446
447 // TODO(cir): Quite a few CUDA and OpenCL attributes are added here.
448
449 // -cl-uniform-work-group-size / -foffload-uniform-block: work groups are
450 // uniform (global work-size is a multiple of work-group size).
451 if (langOpts.OffloadUniformBlock)
452 addUnitAttr(cir::CIRDialect::getUniformWorkGroupSizeAttrName());
453
454 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
455 targetDecl->hasAttr<CUDAGlobalAttr>()) {
456 GlobalDecl kernel(calleeInfo.getCalleeDecl());
457 llvm::StringRef kernelName = getMangledName(
459 auto attr = cir::CUDAKernelNameAttr::get(
461 mlir::StringAttr::get(&getMLIRContext(), kernelName));
462 attrs.set(attr.getMnemonic(), attr);
463 }
464
465 // TODO(cir): we should also do 'aarch64_pstate_sm_body' here.
466
467 if (auto *modularFormat = targetDecl->getAttr<ModularFormatAttr>()) {
468 FormatAttr *format = targetDecl->getAttr<FormatAttr>();
469 StringRef type = format->getType()->getName();
470 std::string formatIdx = std::to_string(format->getFormatIdx());
471 std::string firstArg = std::to_string(format->getFirstArg());
473 type, formatIdx, firstArg,
474 modularFormat->getModularImplFn()->getName(),
475 modularFormat->getImplName()};
476 llvm::append_range(args, modularFormat->aspects());
477 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
478 builder.getStringAttr(llvm::join(args, ",")));
479 }
480 }
481
483
484 bool hasOptNoneAttr = targetDecl && targetDecl->hasAttr<OptimizeNoneAttr>();
485 addDefaultFunctionAttributes(name, hasOptNoneAttr, attrOnCallSite, attrs);
486 if (targetDecl) {
487 // TODO(cir): There is another region of `if (targetDecl)` that handles
488 // removing some attributes that are necessary modifications of the
489 // default-function attrs. Including:
490 // NoSpeculativeLoadHardening
491 // SpeculativeLoadHardening
492 // NoSplitStack
493 // Non-lazy-bind
494 // 'sample-profile-suffix-elision-policy'.
495
496 if (targetDecl->hasAttr<ZeroCallUsedRegsAttr>()) {
497 // A function "__attribute__((...))" overrides the command-line flag.
498 auto kind =
499 targetDecl->getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
500 attrs.set(
501 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
502 mlir::StringAttr::get(
504 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(kind)));
505 }
506
507 if (targetDecl->hasAttr<NoConvergentAttr>())
508 attrs.erase(cir::CIRDialect::getConvergentAttrName());
509 }
510
511 // Collect non-call-site function IR attributes from declaration-specific
512 // information.
513 if (!attrOnCallSite) {
514 // These functions require the returns_twice attribute for correct
515 // codegen, but the attribute may not be added if -fno-builtin is
516 // specified. We explicitly add that attribute here.
517 static const llvm::StringSet<> returnsTwiceFn{
518 "_setjmpex", "setjmp", "_setjmp", "vfork",
519 "sigsetjmp", "__sigsetjmp", "savectx", "getcontext"};
520 if (returnsTwiceFn.contains(name))
521 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
522
523 llvm::StringMap<std::string> cpuAndFeatures;
524 if (getCPUAndFeaturesAttributes(calleeInfo.getCalleeDecl(),
525 cpuAndFeatures)) {
526 for (const auto &[key, val] : cpuAndFeatures)
527 attrs.set(key, builder.getStringAttr(val));
528 }
529 }
530
531 // TODO(cir): A bunch of non-call-site function IR attributes from
532 // declaration-specific information, including tail calls,
533 // cmse_nonsecure_entry, and hotpatch support.
534
535 // TODO(cir): Add loader-replaceable attribute here.
536
537 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
538 constructFunctionArgumentAttributes(info, targetDecl, isThunk, attrOnCallSite,
539 argAttrs);
540}
541
542bool CIRGenModule::hasStrictReturn(QualType retTy, const Decl *targetDecl) {
543 // As-is msan can not tolerate noundef mismatch between caller and
544 // implementation. Mismatch is possible for e.g. indirect calls from C-caller
545 // into C++. Such mismatches lead to confusing false reports. To avoid
546 // expensive workaround on msan we enforce initialization event in uncommon
547 // cases where it's allowed.
548 if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
549 return true;
550 // C++ explicitly makes returning undefined values UB. C's rule only applies
551 // to used values, so we never mark them noundef for now.
552 if (!getLangOpts().CPlusPlus)
553 return false;
554 if (targetDecl) {
555 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
556 if (func->isExternC())
557 return false;
558 } else if (const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
559 // Function pointer.
560 if (var->isExternC())
561 return false;
562 }
563 }
564
565 // We don't want to be too aggressive with the return checking, unless
566 // it's explicit in the code opts or we're using an appropriate sanitizer.
567 // Try to respect what the programmer intended.
568 return getCodeGenOpts().StrictReturn ||
569 !mayDropFunctionReturn(getASTContext(), retTy) ||
570 getLangOpts().Sanitize.has(SanitizerKind::Return);
571}
572
573bool CIRGenModule::mayDropFunctionReturn(const ASTContext &context,
574 QualType retTy) {
575 // We can't just discard the return value for a record type with a
576 // complex destructor or a non-trivially copyable type.
577 if (const RecordType *recTy =
578 retTy.getCanonicalType()->getAsCanonical<RecordType>()) {
579 if (const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
580 return record->hasTrivialDestructor();
581 }
582 return retTy.isTriviallyCopyableType(context);
583}
584
585static bool determineNoUndef(QualType clangTy, CIRGenTypes &types,
586 const cir::CIRDataLayout &layout,
587 const cir::ABIArgInfo &argInfo) {
588 mlir::Type ty = types.convertTypeForMem(clangTy);
590 if (argInfo.isIndirect() || argInfo.isIndirectAliased())
591 return true;
592 if (argInfo.isExtend() && !argInfo.isNoExt())
593 return true;
594
595 if (cir::isSized(ty) && !layout.typeSizeEqualsStoreSize(ty))
596 // TODO: This will result in a modest amount of values not marked noundef
597 // when they could be. We care about values that *invisibly* contain undef
598 // bits from the perspective of LLVM IR.
599 return false;
600
602 // TODO(cir): The calling convention code needs to figure if the
603 // coerced-to-type is larger than the actual type, and remove the noundef
604 // attribute. Classic compiler did it here.
605 if (clangTy->isBitIntType())
606 return true;
607 if (clangTy->isReferenceType())
608 return true;
609 if (clangTy->isNullPtrType())
610 return false;
611 if (clangTy->isMemberPointerType())
612 // TODO: Some member pointers are `noundef`, but it depends on the ABI. For
613 // now, never mark them.
614 return false;
615 if (clangTy->isScalarType()) {
616 if (const ComplexType *Complex = dyn_cast<ComplexType>(clangTy))
617 return determineNoUndef(Complex->getElementType(), types, layout,
618 argInfo);
619 return true;
620 }
621 if (const VectorType *Vector = dyn_cast<VectorType>(clangTy))
622 return determineNoUndef(Vector->getElementType(), types, layout, argInfo);
623 if (const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
624 return determineNoUndef(Matrix->getElementType(), types, layout, argInfo);
625 if (const ArrayType *Array = dyn_cast<ArrayType>(clangTy))
626 return determineNoUndef(Array->getElementType(), types, layout, argInfo);
627
628 // TODO: Some structs may be `noundef`, in specific situations.
629 return false;
630}
631
632void CIRGenModule::constructFunctionReturnAttributes(
633 const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
634 mlir::NamedAttrList &retAttrs) {
635 // Collect attributes from arguments and return values.
636 QualType retTy = info.getReturnType();
637 const cir::ABIArgInfo retInfo = info.getReturnInfo();
638 const cir::CIRDataLayout &layout = getDataLayout();
639
640 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
641 !retTy->isVoidType() &&
642 determineNoUndef(retTy, getTypes(), layout, retInfo))
643 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
644 mlir::UnitAttr::get(&getMLIRContext()));
645
646 if (retTy->hasFloatingRepresentation())
647 if (llvm::FPClassTest mask =
649 retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
650 builder.getI64IntegerAttr(mask));
651
652 if (!isThunk) {
653 // TODO(cir): following comment taken from classic codegen, so if anything
654 // happens there, we should reflect it here.
655 // FIXME: fix this properly, https://reviews.llvm.org/D100388
656 if (const auto *refTy = retTy->getAs<ReferenceType>()) {
657 QualType pointeeTy = refTy->getPointeeType();
658 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
659 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
660 builder.getI64IntegerAttr(
661 getMinimumObjectSize(pointeeTy).getQuantity()));
662
663 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
664 !codeGenOpts.NullPointerIsValid)
665 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
666 mlir::UnitAttr::get(&getMLIRContext()));
667
668 if (pointeeTy->isObjectType())
669 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
670 builder.getI64IntegerAttr(
671 getNaturalPointeeTypeAlignment(retTy).getQuantity()));
672 }
673 }
674}
675
676void CIRGenModule::constructFunctionArgumentAttributes(
677 const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
678 bool attrOnCallSite, llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
680 // TODO(cir): classic codegen does a lot of work here based on the ABIArgInfo
681 // to set things based on calling convention.
682
683 if (info.isInstanceMethod() && !isThunk) {
684 QualType thisPtrTy = info.arguments()[0];
685 // Member allocation functions are instance methods, but setting attributes
686 // on them is nonsensical and not correct. Make sure we skip that here.
687 if (!thisPtrTy->isVoidPointerType()) {
688 QualType thisTy = thisPtrTy->getPointeeType();
689
690 if (!codeGenOpts.NullPointerIsValid &&
691 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
692 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
693 builder.getI64IntegerAttr(
694 getMinimumObjectSize(thisTy).getQuantity()));
695 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
696 mlir::UnitAttr::get(&getMLIRContext()));
697 } else {
699
700 if (bytes != 0)
701 argAttrs[0].set(
702 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
703 builder.getI64IntegerAttr(bytes));
704 }
705
706 argAttrs[0].set(
707 mlir::LLVM::LLVMDialect::getAlignAttrName(),
708 builder.getI64IntegerAttr(
709 getNaturalPointeeTypeAlignment(thisPtrTy).getQuantity()));
710
711 // TODO(cir): the classic codegen has a recently-added bunch of logic for
712 // 'dead_on_return' as an attribute. This both doesn't exist in the LLVM
713 // dialect, and is 'too new' at the time of writing this to be considered
714 // stable enough here. For now, we'll leave this as a TODO so that when
715 // we come back, it is hopefully a more stabilized implementation.
716 }
717 }
718
719 // TODO(cir): the logic between 'this', return, and normal arguments hsould
720 // probably be merged at one point, however the logic is unfortunately mildly
721 // different between each in classic codegen, so trying to do anything like
722 // that seems risky at the moment. At one point we should evaluate if at least
723 // dereferenceable, nonnull, and align can be combined.
724 const cir::CIRDataLayout &layout = getDataLayout();
725 const auto *fd = dyn_cast_or_null<FunctionDecl>(targetDecl);
726
727 // Build a parallel array of ParmVarDecls aligned with argAttrs so we can
728 // access parameter-level attributes (e.g. restrict, nonnull) without manual
729 // index arithmetic in the loop.
730 SmallVector<const ParmVarDecl *> parmDecls;
731 parmDecls.reserve(argAttrs.size());
732 if (fd) {
733 if (info.isInstanceMethod())
734 parmDecls.push_back(nullptr);
735 parmDecls.insert(parmDecls.end(), fd->param_begin(), fd->param_end());
736 }
737 parmDecls.resize(argAttrs.size(), nullptr);
738
739 for (const auto &[argAttrList, argCanType, pvd] :
740 llvm::zip_equal(argAttrs, info.arguments(), parmDecls)) {
742 QualType argType = argCanType;
743 const cir::ABIArgInfo argInfo = cir::ABIArgInfo::getDirect();
744
745 if (codeGenOpts.EnableNoundefAttrs &&
746 determineNoUndef(argType, getTypes(), layout, argInfo))
747 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
748 mlir::UnitAttr::get(&getMLIRContext()));
749
751 // TODO(cir): there is plenty of other attributes here added due to ABI
752 // decisions. While these probably won't end up here, we note that the
753 // classic codegen does it here and perhaps we should pay attention to that.
754
755 if (const auto *refTy = argType->getAs<ReferenceType>()) {
756 QualType pointeeTy = refTy->getPointeeType();
757 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
758 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
759 builder.getI64IntegerAttr(
760 getMinimumObjectSize(pointeeTy).getQuantity()));
761 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
762 !codeGenOpts.NullPointerIsValid)
763 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
764 mlir::UnitAttr::get(&getMLIRContext()));
765 if (pointeeTy->isObjectType())
766 argAttrList.set(
767 mlir::LLVM::LLVMDialect::getAlignAttrName(),
768 builder.getI64IntegerAttr(
769 getNaturalPointeeTypeAlignment(argType).getQuantity()));
770 }
771
772 if (argType->hasFloatingRepresentation())
773 if (llvm::FPClassTest mask =
775 argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
776 builder.getI64IntegerAttr(mask));
777
778 // restrict -> noalias on definitions only (not call sites). Skip
779 // builtins: OGCG applies restrict->noalias in EmitFunctionProlog.
780 if (!attrOnCallSite && pvd && pvd->getType()->isPointerType() &&
781 pvd->getType().isRestrictQualified() && !fd->getBuiltinID())
782 argAttrList.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
783 mlir::UnitAttr::get(&getMLIRContext()));
784
785 // __attribute__((nonnull)) on pointer parameters. Checks both
786 // per-parameter and function-level nonnull attributes.
787 if (pvd && argType->isAnyPointerType() && !codeGenOpts.NullPointerIsValid) {
788 unsigned srcIdx = pvd->getFunctionScopeIndex();
789 if (pvd->hasAttr<NonNullAttr>() ||
790 (fd->getAttr<NonNullAttr>() &&
791 fd->getAttr<NonNullAttr>()->isNonNull(srcIdx)))
792 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
793 mlir::UnitAttr::get(&getMLIRContext()));
794 }
795 }
796}
797
798/// Adds the formal parameters in FPT to the given prefix. If any parameter in
799/// FPT has pass_object_size attrs, then we'll add parameters for those, too.
800/// TODO(cir): this should be shared with LLVM codegen
801static void appendParameterTypes(const CIRGenTypes &cgt,
804 // Fast path: don't touch param info if we don't need to.
805 if (!fpt->hasExtParameterInfos()) {
806 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
807 return;
808 }
809
810 // In the vast majority of cases, we'll have precisely fpt->getNumParams()
811 // parameters; the only thing that can change this is the presence of
812 // pass_object_size. So, we preallocate for the common case.
813 prefix.reserve(prefix.size() + fpt->getNumParams());
815 fpt->getExtParameterInfos();
816 assert(extInfos.size() == fpt->getNumParams());
817 for (auto [paramType, extInfo] : llvm::zip_equal(
818 llvm::make_range(fpt->param_type_begin(), fpt->param_type_end()),
819 extInfos)) {
820 prefix.push_back(paramType);
821 if (extInfo.hasPassObjectSize())
822 prefix.push_back(cgt.getASTContext().getCanonicalSizeType());
823 }
824}
825
826const CIRGenFunctionInfo &
828 auto *md = cast<CXXMethodDecl>(gd.getDecl());
829
831 argTypes.push_back(deriveThisType(md->getParent(), md));
832
833 bool passParams = true;
834
835 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
836 // A base class inheriting constructor doesn't get forwarded arguments
837 // needed to construct a virtual base (or base class thereof)
838 if (auto inherited = cd->getInheritedConstructor())
839 passParams = inheritingCtorHasParams(inherited, gd.getCtorType());
840 }
841
843
844 if (passParams)
845 appendParameterTypes(*this, argTypes, fpt);
846
847 // The structor signature may include implicit parameters.
848 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
849 theCXXABI.buildStructorSignature(gd, argTypes);
851
852 RequiredArgs required =
853 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
855
856 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
857 : theCXXABI.hasMostDerivedReturn(gd)
858 ? astContext.VoidPtrTy
859 : astContext.VoidTy;
860
861 assert(!theCXXABI.hasThisReturn(gd) &&
862 "Please send PR with a test and remove this");
863
866
867 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
868 fpt->getExtInfo(), required);
869}
870
871/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
872/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
873/// indicates that there is no meaningful 'this' type, and a null `md` can occur
874/// when calling a method pointer.
876 const CXXMethodDecl *md) {
877 CanQualType recTy;
878 if (rd) {
880 } else {
881 // This can happen with the MS ABI. It shouldn't need anything more than
882 // setting recTy to VoidTy here, but we're flagging it for now because we
883 // don't have the full handling implemented.
884 cgm.errorNYI("deriveThisType: no record decl");
885 recTy = getASTContext().VoidTy;
886 }
887
888 if (md)
889 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
890 recTy, md->getMethodQualifiers().getAddressSpace()));
891 return getASTContext().getPointerType(recTy);
892}
893
894/// Arrange the CIR function layout for a value of the given function type, on
895/// top of any implicit parameters already stored.
896static const CIRGenFunctionInfo &
897arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod,
901 RequiredArgs required =
904 appendParameterTypes(cgt, prefix, fpt);
905 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
906 return cgt.arrangeCIRFunctionInfo(resultType, instanceMethod, prefix,
907 fpt->getExtInfo(), required);
908}
909
911 const VarDecl *param,
912 SourceLocation loc) {
913 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
914 // We need to turn that into an r-value suitable for emitCall
915 Address local = getAddrOfLocalVar(param);
916
917 QualType type = param->getType();
918
919 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
920 // argument needs to be the original pointer.
921 if (type->isReferenceType()) {
922 args.add(
923 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
924 type);
925 } else if (getLangOpts().ObjCAutoRefCount) {
926 cgm.errorNYI(param->getSourceRange(),
927 "emitDelegateCallArg: ObjCAutoRefCount");
928 // For the most part, we just need to load the alloca, except that aggregate
929 // r-values are actually pointers to temporaries.
930 } else {
931 args.add(convertTempToRValue(local, type, loc), type);
932 }
933
934 // Deactivate the cleanup for the callee-destructed param that was pushed.
936 if (type->isRecordType() &&
937 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
938 param->needsDestruction(getContext())) {
939 cgm.errorNYI(param->getSourceRange(),
940 "emitDelegateCallArg: callee-destructed param");
941 }
942}
943
944static const CIRGenFunctionInfo &
946 const CallArgList &args,
947 const FunctionType *fnType) {
948
950
951 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
952 // A free function call has no extra prefix arguments. Note that
953 // getFromProtoWithExtraSlots already accounts for the prototype's
954 // pass_object_size parameters; adding them here too would double-count
955 // them and make the signature claim more required arguments than `args`
956 // actually holds.
957 if (proto->isVariadic())
958 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
961 cgm.errorNYI("call to function without a prototype");
962
964 for (const CallArg &arg : args)
965 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
966
968
970 return cgt.arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false,
971 argTypes, fnType->getExtInfo(), required);
972}
973
974/// Arrange a call to a C++ method, passing the given arguments.
975///
976/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
977/// parameter.
978/// passProtoArgs indicates whether `args` has args for the parameters in the
979/// given CXXConstructorDecl.
981 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
982 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
983
984 // FIXME: Kill copy.
986 for (const auto &arg : args)
987 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
988
989 // +1 for implicit this, which should always be args[0]
990 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
991
993 RequiredArgs required = passProtoArgs
995 fpt, totalPrefixArgs + extraSuffixArgs)
997
998 GlobalDecl gd(d, ctorKind);
999 if (theCXXABI.hasThisReturn(gd))
1000 cgm.errorNYI(d->getSourceRange(),
1001 "arrangeCXXConstructorCall: hasThisReturn");
1002 if (theCXXABI.hasMostDerivedReturn(gd))
1003 cgm.errorNYI(d->getSourceRange(),
1004 "arrangeCXXConstructorCall: hasMostDerivedReturn");
1005 CanQualType resultType = astContext.VoidTy;
1006
1009
1010 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
1011 fpt->getExtInfo(), required);
1012}
1013
1014/// Arrange a call to a C++ method, passing the given arguments.
1015///
1016/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
1017/// does not count `this`.
1019 const CallArgList &args, const FunctionProtoType *proto,
1020 RequiredArgs required, unsigned numPrefixArgs) {
1022 assert(numPrefixArgs + 1 <= args.size() &&
1023 "Emitting a call with less args than the required prefix?");
1024
1025 // FIXME: Kill copy.
1027 for (const CallArg &arg : args)
1028 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1029
1033 /*isInstanceMethod=*/true, argTypes, proto->getExtInfo(), required);
1034}
1035
1036const CIRGenFunctionInfo &
1038 const FunctionType *fnType) {
1039 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
1040}
1041
1042const CIRGenFunctionInfo &
1044 const CallArgList &args) {
1046 for (const CallArg &arg : args)
1047 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1048
1049 CanQualType retType = resultType->getCanonicalTypeUnqualified();
1050 return arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false, argTypes,
1052}
1053
1054/// Set calling convention for CUDA/HIP kernel.
1056 CIRGenModule &cgm,
1057 const FunctionDecl *fd) {
1058 if (fd->hasAttr<CUDAGlobalAttr>()) {
1059 const FunctionType *ft = funcTy->getAs<FunctionType>();
1061 funcTy = ft->getCanonicalTypeUnqualified();
1062 }
1063}
1064
1065/// Arrange the argument and result information for a declaration or definition
1066/// of the given C++ non-static member function. The member function must be an
1067/// ordinary function, i.e. not a constructor or destructor.
1068const CIRGenFunctionInfo &
1070 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
1071 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
1072
1074 setCUDAKernelCallingConvention(funcTy, cgm, md);
1075 auto prototype = funcTy.getAs<FunctionProtoType>();
1076
1077 // Mirrors classic CodeGen's check at CGCall.cpp. C++23 explicit-object
1078 // member functions (P0847R7, `void f(this Self&&)`) do not receive an
1079 // implicit `this`; the explicit object parameter takes its place at the
1080 // AST level and appears as the first parameter of the FunctionProtoType.
1081 // Arrange them as free functions so we don't prepend a stale implicit
1082 // `this` to the parameter list, which would produce a CIRGenFunctionInfo
1083 // with one more argument than the matching cir.func type and trip the
1084 // assertion in setArgAttrs.
1086 // The abstract case is perfectly fine.
1087 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1088 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
1089 }
1090
1091 return arrangeFreeFunctionType(prototype);
1092}
1093
1094/// Arrange the argument and result information for a call to an unknown C++
1095/// non-static member function of the given abstract type. (A null RD means we
1096/// don't have any meaningful "this" argument type, so fall back to a generic
1097/// pointer type). The member fucntion must be an ordinary function, i.e. not a
1098/// constructor or destructor.
1099const CIRGenFunctionInfo &
1101 const FunctionProtoType *fpt,
1102 const CXXMethodDecl *md) {
1104
1105 // Add the 'this' pointer.
1106 argTypes.push_back(deriveThisType(rd, md));
1107
1109 return ::arrangeCIRFunctionInfo(
1110 *this, /*isInstanceMethod=*/true, argTypes,
1112}
1113
1114/// Arrange the argument and result information for the declaration or
1115/// definition of the given function.
1116const CIRGenFunctionInfo &
1118 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1119 if (md->isInstance())
1120 return arrangeCXXMethodDeclaration(md);
1121
1123
1124 assert(isa<FunctionType>(funcTy));
1125 setCUDAKernelCallingConvention(funcTy, cgm, fd);
1126
1127 // When declaring a function without a prototype, always use a non-variadic
1128 // type.
1129 if (CanQual<FunctionNoProtoType> noProto =
1130 funcTy.getAs<FunctionNoProtoType>()) {
1133 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1134 /*isInstanceMethod=*/false, {},
1135 noProto->getExtInfo(), RequiredArgs::All);
1136 }
1137
1139}
1140
1141RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1142 if (!hasLV)
1143 return rv;
1144 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1146 lv.isVolatile());
1147 isUsed = true;
1148 return RValue::getAggregate(copy.getAddress());
1149}
1150
1152 SourceLocation argLoc,
1153 AbstractCallee ac, unsigned paramNum) {
1154 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1155 sanOpts.has(SanitizerKind::NullabilityArg)))
1156 return;
1157 cgm.errorNYI("non-null arg check is NYI");
1158}
1159
1160static cir::CIRCallOpInterface
1161emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
1162 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1163 cir::FuncOp directFuncOp,
1164 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1165 const mlir::NamedAttrList &attrs,
1167 const mlir::NamedAttrList &retAttrs) {
1168 CIRGenBuilderTy &builder = cgf.getBuilder();
1169
1171
1172 assert(builder.getInsertionBlock() && "expected valid basic block");
1173
1174 cir::CallOp op;
1175 if (indirectFuncTy) {
1176 // TODO(cir): Set calling convention for indirect calls.
1178 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1179 cirCallArgs, attrs, argAttrs, retAttrs);
1180 } else {
1181 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1182 argAttrs, retAttrs);
1183 }
1184
1185 return op;
1186}
1187
1188const CIRGenFunctionInfo &
1192 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1193 fpt);
1194}
1195
1196const CIRGenFunctionInfo &
1198 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1200 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1201 fnpt->getExtInfo(), RequiredArgs(0));
1202}
1203
1205 const CIRGenCallee &callee,
1207 const CallArgList &args,
1208 cir::CIRCallOpInterface *callOp,
1209 bool isMustTail, SourceRange clangLoc) {
1210 QualType retTy = funcInfo.getReturnType();
1211 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1212 mlir::Location loc = getLoc(clangLoc);
1213
1214 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1215
1216 const Decl *targetDecl = callee.getAbstractInfo().getCalleeDecl().getDecl();
1217
1218 if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(targetDecl)) {
1219 // We can only guarantee that a function is called from the correct
1220 // context/function based on the appropriate target attributes,
1221 // so only check in the case where we have both always_inline and target
1222 // since otherwise we could be making a conditional call after a check for
1223 // the proper cpu features (and it won't cause code generation issues due to
1224 // function based code generation).
1225 if ((targetDecl->hasAttr<AlwaysInlineAttr>() &&
1226 (targetDecl->hasAttr<TargetAttr>() ||
1227 (curFuncDecl && curFuncDecl->hasAttr<TargetAttr>()))) ||
1228 (curFuncDecl && curFuncDecl->hasAttr<FlattenAttr>() &&
1229 (curFuncDecl->hasAttr<TargetAttr>() ||
1230 targetDecl->hasAttr<TargetAttr>())))
1231 checkTargetFeatures(clangLoc.getBegin(), fd);
1232 }
1233
1234 const FunctionDecl *callerDecl = dyn_cast_or_null<FunctionDecl>(curCodeDecl);
1235 const FunctionDecl *calleeDecl = dyn_cast_or_null<FunctionDecl>(targetDecl);
1236
1238
1239 // Translate all of the arguments as necessary to match the CIR lowering.
1240 for (auto [argNo, arg, canQualArgType] :
1241 llvm::enumerate(args, funcInfo.argTypes())) {
1242
1243 // Insert a padding argument to ensure proper alignment.
1245
1246 mlir::Type argType = convertType(canQualArgType);
1247 if (!mlir::isa<cir::RecordType>(argType) &&
1248 !mlir::isa<cir::ComplexType>(argType)) {
1249 mlir::Value v;
1250 if (arg.isAggregate())
1251 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1252 v = arg.getKnownRValue().getValue();
1253
1254 // We might have to widen integers, but we should never truncate.
1255 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1256 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1257
1258 // If we have a pointer argument and there's an address space mismatch,
1259 // insert an address_space cast to match the expected function signature.
1260 if (argType != v.getType()) {
1261 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1262 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1263 if (argPtrTy && vPtrTy &&
1264 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1265 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1266 v = performAddrSpaceCast(v, argPtrTy);
1267 }
1268 }
1269
1270 // If the argument doesn't match, perform a bitcast to coerce it. This
1271 // can happen due to trivial type mismatches.
1272 // TODO(cir): When getFunctionType is added, assert that this isn't
1273 // needed.
1275 cirCallArgs[argNo] = v;
1276 } else {
1277 Address src = Address::invalid();
1278 if (!arg.isAggregate()) {
1279 src = createMemTemp(arg.ty, loc, "coerce");
1280 arg.copyInto(*this, src, loc);
1281 } else {
1282 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1283 : arg.getKnownRValue().getAggregateAddress();
1284 }
1285
1286 // Fast-isel and the optimizer generally like scalar values better than
1287 // FCAs, so we flatten them if this is safe to do for this argument.
1288 mlir::Type srcTy = src.getElementType();
1289 // FIXME(cir): get proper location for each argument.
1290 mlir::Location argLoc = loc;
1291
1292 // If the source type is smaller than the destination type of the
1293 // coerce-to logic, copy the source value into a temp alloca the size
1294 // of the destination type to allow loading all of it. The bits past
1295 // the source value are left undef.
1296 // FIXME(cir): add data layout info and compare sizes instead of
1297 // matching the types.
1298 //
1299 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1300 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1301 // if (SrcSize < DstSize) {
1303 if (srcTy != argType) {
1304 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1305 } else {
1306 // FIXME(cir): this currently only runs when the types are exactly the
1307 // same, but should be when alloc sizes are the same, fix this as soon
1308 // as datalayout gets introduced.
1310 }
1311
1312 // assert(NumCIRArgs == STy.getMembers().size());
1313 // In LLVMGen: Still only pass the struct without any gaps but mark it
1314 // as such somehow.
1315 //
1316 // In CIRGen: Emit a load from the "whole" struct,
1317 // which shall be broken later by some lowering step into multiple
1318 // loads.
1320 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1321 }
1322 }
1323
1324 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1325 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1326
1328
1329 mlir::NamedAttrList attrs;
1330 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1331 mlir::NamedAttrList retAttrs;
1332 StringRef funcName;
1333 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1334 funcName = calleeFuncOp.getName();
1335
1338 cir::CallingConv callingConv;
1339 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1340 attrs, argAttrs, retAttrs, callingConv,
1341 /*attrOnCallSite=*/true, /*isThunk=*/false);
1342
1343 auto resolvedFuncOpFromGlobal = [&](mlir::Operation *op) -> cir::FuncOp {
1344 if (auto fnOp = dyn_cast<cir::FuncOp>(op))
1345 return fnOp;
1346 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(op)) {
1347 // FIXME(cir): This peephole optimization avoids indirect calls for
1348 // builtins. This should be fixed in the builtin declaration instead by
1349 // not emitting an unecessary get_global in the first place. However,
1350 // this is also used for no-prototype functions.
1351 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1352 assert(globalOp && "undefined global function");
1353 return cast<cir::FuncOp>(globalOp);
1354 }
1355 return nullptr;
1356 };
1357
1358 cir::FuncType indirectFuncTy;
1359 mlir::Value indirectFuncVal;
1360 cir::FuncOp directFuncOp;
1361
1362 // If the callee resolves to a FuncOp whose stored signature differs from
1363 // this call site's expected signature, the CIR verifier would reject the
1364 // mismatched types. This happens, for example, when two declarations share a
1365 // mangled name via __asm__ renaming (glibc's __REDIRECT_NTH pattern) but
1366 // disagree about a struct argument type. If that happens, we demote the
1367 // direct call to an indirect call through a function-pointer bitcast typed
1368 // at the call site.
1369 if (cir::FuncOp candidate = resolvedFuncOpFromGlobal(calleePtr)) {
1370 if (candidate.getFunctionType() == cirFuncTy) {
1371 directFuncOp = candidate;
1372 } else {
1373 mlir::Value addr = cir::GetGlobalOp::create(
1374 builder, loc, cir::PointerType::get(candidate.getFunctionType()),
1375 candidate.getSymName());
1376 indirectFuncTy = cirFuncTy;
1377 indirectFuncVal =
1378 builder.createBitcast(addr, cir::PointerType::get(cirFuncTy));
1379 }
1380 } else {
1381 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1382 calleePtr->getResultTypes();
1383 [[maybe_unused]] auto funcPtrTy =
1384 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1385 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1386 "expected pointer to function");
1387
1388 indirectFuncTy = cirFuncTy;
1389 indirectFuncVal = calleePtr->getResult(0);
1390 }
1391
1395
1396 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1397 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1398
1399 mlir::Location callLoc = loc;
1400 cir::CIRCallOpInterface theCall =
1401 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1402 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1403
1404 if (callOp)
1405 *callOp = theCall;
1406
1407 // Sema/emitAttributedStmt (see
1408 // https://github.com/llvm/llvm-project/issues/214764) should one-day enforce
1409 // that only one of these is valid at a time. For now, we have the same 'bug'
1410 // as classic codegen where we can end up having BOTH of these.
1412 theCall.setInlineKind(cir::InlineKind::NoInline);
1414 !cgm.getTargetCIRGenInfo().wouldInliningViolateFunctionCallABI(
1415 callerDecl, calleeDecl))
1416 theCall.setInlineKind(cir::InlineKind::AlwaysInline);
1417
1418 if (isMustTail) {
1419 // PPC/MIPS have some diagnostics for classic-codegen, but we don't support
1420 // them yet.
1421 const llvm::Triple &triple = getTarget().getTriple();
1422 if (triple.isPPC() || triple.isMIPS()) {
1423 cgm.errorNYI(mustTailCall->getBeginLoc(),
1424 "musttail call target legality checks");
1425 return getUndefRValue(retTy);
1426 }
1427
1428 // This call replaces the frame that the handler enforcing the exception
1429 // specification belongs to, taking that handler with it.
1430 if (ehSpecTryOp) {
1431 if (!inEHSpecTerminateScope()) {
1432 // The filter of a dynamic specification has to run while an exception
1433 // is leaving the function, and the tail call skips over it.
1434 cgm.errorUnsupported(mustTailCall, "tail call skipping over cleanups");
1435 return getUndefRValue(retTy);
1436 }
1437
1438 // Losing a terminate handler is safe when the callee cannot throw,
1439 // because then the callee's own handler stands in for it.
1440 if (!cannotThrow) {
1441 cgm.getDiags().Report(mustTailCall->getBeginLoc(),
1442 diag::err_musttail_noexcept_mismatch);
1443 return getUndefRValue(retTy);
1444 }
1445 }
1446
1447 // Musttail is required to return immediately, so no cleanup can run
1448 // between the call and the return. Cleanups that the return makes
1449 // unnecessary are simply skipped. Anything else cannot be expressed.
1451 for (EHScopeStack::iterator it = ehStack.begin(),
1452 end = ehStack.find(prologueCleanupDepth);
1453 it != end; ++it) {
1454 auto *cleanupScope = dyn_cast<EHCleanupScope>(&*it);
1455 if (!cleanupScope ||
1456 !cleanupScope->getCleanup()->isRedundantBeforeReturn()) {
1457 cgm.errorUnsupported(mustTailCall, "tail call skipping over cleanups");
1458 return getUndefRValue(retTy);
1459 }
1460 }
1461
1462 theCall->setAttr(cir::CIRDialect::getMustTailAttrName(),
1463 builder.getUnitAttr());
1464
1465 if (isa<cir::VoidType>(convertType(retTy)))
1466 cir::ReturnOp::create(builder, loc);
1467 else
1468 cir::ReturnOp::create(builder, loc, theCall->getResult(0));
1469
1470 // Musttail must return immediately, so we just do that. All of the below
1471 // stuff is effectively UB if this is a musttail, so just do a return
1472 // immediately.
1473 builder.createBlock(builder.getBlock()->getParent());
1474 return getUndefRValue(retTy);
1475 }
1476
1478
1479 mlir::Type retCIRTy = convertType(retTy);
1480 if (isa<cir::VoidType>(retCIRTy))
1481 return getUndefRValue(retTy);
1482 switch (getEvaluationKind(retTy)) {
1483 case cir::TEK_Aggregate: {
1484 Address destPtr = returnValue.getValue();
1485
1486 if (!destPtr.isValid())
1487 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1488
1489 mlir::ResultRange results = theCall->getOpResults();
1490 assert(results.size() <= 1 && "multiple returns from a call");
1491
1492 SourceLocRAIIObject loc{*this, clangLoc};
1493 emitAggregateStore(results[0], destPtr);
1494 return RValue::getAggregate(destPtr);
1495 }
1496 case cir::TEK_Scalar: {
1497 mlir::ResultRange results = theCall->getOpResults();
1498 assert(results.size() == 1 && "unexpected number of returns");
1499
1500 // If the argument doesn't match, perform a bitcast to coerce it. This
1501 // can happen due to trivial type mismatches.
1502 if (results[0].getType() != retCIRTy)
1503 cgm.errorNYI(loc, "bitcast on function return value");
1504
1505 mlir::Region *region = builder.getBlock()->getParent();
1506 if (region != theCall->getParentRegion())
1507 cgm.errorNYI(loc, "function calls with cleanup");
1508
1509 return RValue::get(results[0]);
1510 }
1511 case cir::TEK_Complex: {
1512 mlir::ResultRange results = theCall->getOpResults();
1513 assert(!results.empty() &&
1514 "Expected at least one result for complex rvalue");
1515 return RValue::getComplex(results[0]);
1516 }
1517 }
1518 llvm_unreachable("Invalid evaluation kind");
1519}
1520
1522 mlir::Location loc) const {
1523 LValue dst = cgf.makeAddrLValue(addr, ty);
1524 if (!hasLV && rv.isScalar())
1525 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1526 else if (!hasLV && rv.isComplex())
1527 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1528 else
1529 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1530 isUsed = true;
1531}
1532
1533mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1534 cir::FuncOp callee,
1536 mlir::NamedAttrList attrs) {
1537
1538 // TODO(cir): set the calling convention to this runtime call.
1540
1541 cir::CallOp call = builder.createCallOp(loc, callee, args);
1542 assert(call->getNumResults() <= 1 &&
1543 "runtime functions have at most 1 result");
1544
1545 if (!attrs.empty())
1546 call->setAttrs(attrs);
1547
1548 if (call->getNumResults() == 0)
1549 return nullptr;
1550
1551 return call->getResult(0);
1552}
1553
1555 clang::QualType argType) {
1556 assert(argType->isReferenceType() == e->isGLValue() &&
1557 "reference binding to unmaterialized r-value!");
1558
1559 if (e->isGLValue()) {
1560 assert(e->getObjectKind() == OK_Ordinary);
1561 return args.add(emitReferenceBindingToExpr(e), argType);
1562 }
1563
1564 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1565
1566 // For callee-destructed parameters (trivial_abi, MS ABI), create an
1567 // aggregate temp and let the callee destroy it.
1568 if (argType->isRecordType() &&
1570 AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
1572
1573 bool destroyedInCallee = true;
1574 if (const auto *rd = argType->getAsCXXRecordDecl())
1575 destroyedInCallee = rd->hasNonTrivialDestructor();
1576
1577 if (destroyedInCallee)
1579
1580 emitAggExpr(e, slot);
1581 RValue rv = slot.asRValue();
1582 args.add(rv, argType);
1583
1584 if (destroyedInCallee && getLangOpts().Exceptions)
1585 cgm.errorNYI(e->getSourceRange(),
1586 "callee-destructed param with exceptions");
1587 return;
1588 }
1589
1590 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1591 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1592 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1593 assert(lv.isSimple());
1594 args.addUncopiedAggregate(lv, argType);
1595 return;
1596 }
1597
1598 args.add(emitAnyExprToTemp(e), argType);
1599}
1600
1601QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1602 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1603 // implicitly widens null pointer constants that are arguments to varargs
1604 // functions to pointer-sized ints.
1605 if (!getTarget().getTriple().isOSWindows())
1606 return arg->getType();
1607
1608 assert(!cir::MissingFeatures::msabi());
1609 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1610 return arg->getType();
1611}
1612
1613/// Similar to emitAnyExpr(), however, the result will always be accessible
1614/// even if no aggregate location is provided.
1617
1619 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1621
1622 return emitAnyExpr(e, aggSlot);
1623}
1624
1626 CallArgList &args, PrototypeWrapper prototype,
1627 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1628 AbstractCallee callee, unsigned paramsToSkip) {
1630
1632
1633 // First, if a prototype was provided, use those argument types.
1634 bool isVariadic = false;
1635 if (prototype.p) {
1637
1638 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1639 isVariadic = fpt->isVariadic();
1641 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1642 fpt->param_type_end());
1643 }
1644
1645 // If we still have any arguments, emit them using the type of the argument.
1646 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1647 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1648 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1649
1650 // We must evaluate arguments from right to left in the MS C++ ABI, because
1651 // arguments are destroyed left to right in the callee. As a special case,
1652 // there are certain language constructs taht require left-to-right
1653 // evaluation, and in those cases we consider the evaluation order requirement
1654 // to trump the "destruction order is reverse construction order" guarantee.
1655 auto leftToRight = true;
1656 assert(!cir::MissingFeatures::msabi());
1657
1658 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1659 RValue emittedArg) {
1660 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1661 return;
1662 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1663 if (!ps)
1664 return;
1665
1667 assert(emittedArg.getValue() && "We emitted nothing for the arg?");
1668 mlir::Value v = evaluateOrEmitBuiltinObjectSize(
1669 arg, ps->getType(), cast<cir::IntType>(cgm.sizeTy),
1670 emittedArg.getValue(), ps->isDynamic());
1671 args.add(RValue::get(v), sizeTy);
1672 // When emitting right-to-left, the size arg was appended after the
1673 // pointer arg; swap them so the size follows the pointer in the final
1674 // argument list after the outer reverse.
1675 if (!leftToRight)
1676 std::iter_swap(args.rbegin(), std::next(args.rbegin()));
1677 };
1678
1679 // Evaluate each argument in the appropriate order.
1680 size_t callArgsStart = args.size();
1681 for (size_t i = 0; i != argTypes.size(); ++i) {
1682 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1683 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1684 size_t initialArgSize = args.size();
1685
1686 emitCallArg(args, *currentArg, argTypes[idx]);
1687
1688 // In particular, we depend on it being the last arg in Args, and the
1689 // objectsize bits depend on there only being one arg if !LeftToRight.
1690 assert(initialArgSize + 1 == args.size() &&
1691 "The code below depends on only adding one arg per emitCallArg");
1692 (void)initialArgSize;
1693
1694 // Since pointer argument are never emitted as LValue, it is safe to emit
1695 // non-null argument check for r-value only.
1696 if (!args.back().hasLValue()) {
1697 RValue rvArg = args.back().getKnownRValue();
1699 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1700 }
1701
1702 if (!leftToRight)
1703 std::reverse(args.begin() + callArgsStart, args.end());
1704 }
1705}
1706
1707// FIXME(cir): This is identical to the version from classic-codegen, we should
1708// figure out how to move this to a common location.
1710 CXXCtorType type) {
1711 // Parameters are unnecessary if we're constructing a base class subobject
1712 // and the inherited constructor lives in a virtual base.
1713 return type == Ctor_Complete ||
1714 !inherited.getShadowDecl()->constructsVirtualBase() ||
1716}
static StringRef bytes(const std::vector< T, Allocator > &v)
static void setCUDAKernelCallingConvention(CanQualType &funcTy, CIRGenModule &cgm, const FunctionDecl *fd)
Set calling convention for CUDA/HIP kernel.
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 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...
TokenType getType() const
Returns the token's type, e.g.
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
llvm::json::Array Array
static bool isVirtualCall(const CallExpr *CE)
bool isIndirectAliased() const
Definition ABIArgInfo.h:80
bool isExtend() const
Definition ABIArgInfo.h:72
bool isNoExt() const
Definition ABIArgInfo.h:76
static ABIArgInfo getDirect(mlir::Type ty=nullptr)
Definition ABIArgInfo.h:56
bool isIndirect() const
Definition ABIArgInfo.h:68
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
CanQualType VoidTy
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:965
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3813
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
bool isValid() const
Definition Address.h:77
An aggregate value slot.
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.
Definition CIRGenCall.h:27
clang::GlobalDecl getCalleeDecl() const
Definition CIRGenCall.h:44
const clang::FunctionProtoType * getCalleeFunctionProtoType() const
Definition CIRGenCall.h:41
CIRGenCalleeInfo getAbstractInfo() const
Definition CIRGenCall.h:140
clang::GlobalDecl getVirtualMethodDecl() const
Definition CIRGenCall.h:170
CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const
If this is a delayed callee computation of some sort, prepare a concrete callee.
Address getThisAddress() const
Definition CIRGenCall.h:175
cir::FuncType getVirtualFunctionType() const
Definition CIRGenCall.h:180
const clang::CallExpr * getVirtualCallExpr() const
Definition CIRGenCall.h:165
mlir::Operation * getFunctionPointer() const
Definition CIRGenCall.h:147
llvm::MutableArrayRef< CanQualType > argTypes()
static CIRGenFunctionInfo * create(cir::CallingConv cirCC, FunctionType::ExtInfo info, bool instanceMethod, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
llvm::ArrayRef< CanQualType > arguments() const
const_arg_iterator argTypesBegin() const
An abstract representation of regular/ObjC call/message targets.
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.
EHScopeStack::stable_iterator prologueCleanupDepth
The cleanup depth enclosing all the cleanups associated with the parameters.
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.
const clang::Decl * curFuncDecl
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.
cir::TryOp ehSpecTryOp
The cir.try wrapping a function whose exception specification has to be enforced.
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)
void checkTargetFeatures(const clang::CallExpr *e, const clang::FunctionDecl *targetDecl)
Emit a diagnostic if the target features required by targetDecl are not available in the calling func...
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
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.
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
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={})
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, bool isMustTail, SourceRange clangLoc)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
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.
bool inEHSpecTerminateScope()
Whether the wrapper opened by emitStartEHSpec is a terminate scope, whose handler calls std::terminat...
clang::ASTContext & getContext() const
bool inAlwaysInlineAttributedStmt
True if the current statement has always_inline attribute.
bool inNoInlineAttributedStmt
True if the current statement has noinline attribute.
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
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
clang::CharUnits getNaturalPointeeTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition CIRGenTypes.h:51
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 & arrangeBuiltinFunctionCall(QualType resultType, const CallArgList &args)
A builtin function is a freestanding function using the default C conventions.
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)
Definition CIRGenCall.h:241
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:239
A non-stable pointer into the scope stack.
Address getAddress() const
bool isSimple() const
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
static RValue getComplex(mlir::Value v)
Definition CIRGenValue.h:91
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...
Definition CIRGenCall.h:260
virtual bool isNoProtoCallVariadic(const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
virtual void setCUDAKernelCallingConvention(const clang::FunctionType *&ft) const
Definition TargetInfo.h:171
Represents a C++ constructor within a class.
Definition DeclCXX.h:2642
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2150
bool isImplicitObjectMemberFunction() const
[C++2b][dcl.fct]/p7 An implicit object member function is a non-static member function without an exp...
Definition DeclCXX.cpp:2726
bool isVirtual() const
Definition DeclCXX.h:2205
Qualifiers getMethodQualifiers() const
Definition DeclCXX.h:2328
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
SourceLocation getBeginLoc() const
Definition Expr.h:3321
ConstExprIterator const_arg_iterator
Definition Expr.h:3235
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.
Definition CharUnits.h:185
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.
Definition TypeBase.h:3355
bool constructsVirtualBase() const
Returns true if the constructed base class is a virtual base class subobject of this declaration's cl...
Definition DeclCXX.h:3807
T * getAttr() const
Definition DeclBase.h:581
bool hasAttr() const
Definition DeclBase.h:585
This represents one expression.
Definition Expr.h:113
bool isGLValue() const
Definition Expr.h:288
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:455
QualType getType() const
Definition Expr.h:145
Represents a function declaration or definition.
Definition Decl.h:2059
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4608
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4976
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5398
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5705
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5797
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4705
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4594
ExtInfo getExtInfo() const
Definition TypeBase.h:4950
QualType getReturnType() const
Definition TypeBase.h:4934
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
CXXCtorType getCtorType() const
Definition GlobalDecl.h:117
GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind)
Definition GlobalDecl.h:200
const Decl * getDecl() const
Definition GlobalDecl.h:115
Description of a constructor that was inherited from a base class.
Definition DeclCXX.h:2613
ConstructorUsingShadowDecl * getShadowDecl() const
Definition DeclCXX.h:2625
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.
Definition TypeBase.h:4428
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:3090
QualType getCanonicalType() const
Definition TypeBase.h:8480
LangAS getAddressSpace() const
Definition TypeBase.h:572
bool isParamDestroyedInCallee() const
Definition Decl.h:4610
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
bool hasConstructorVariants() const
Does this ABI have different entrypoints for complete-object and base-subobject constructors?
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
bool isVoidType() const
Definition TypeBase.h:9037
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isVoidPointerType() const
Definition Type.cpp:841
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition Type.cpp:2641
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8689
bool isScalarType() const
Definition TypeBase.h:9143
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:881
bool isBitIntType() const
Definition TypeBase.h:8940
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isMemberPointerType() const
Definition TypeBase.h:8746
bool isObjectType() const
Determine whether this type is an object type.
Definition TypeBase.h:2574
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2651
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition Type.cpp:2521
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2998
bool isAnyPointerType() const
Definition TypeBase.h:8673
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9264
bool isNullPtrType() const
Definition TypeBase.h:9074
bool isRecordType() const
Definition TypeBase.h:8792
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2170
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2821
Represents a GCC generic vector type.
Definition TypeBase.h:4266
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:35
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CanQual< FunctionProtoType > getFormalType(const CXXMethodDecl *MD)
Returns the canonical formal type of the given C++ method.
Definition CallUtils.cpp:13
llvm::FPClassTest getNoFPClassTestMask(const LangOptions &LangOpts)
Returns the set of floating-point value kinds that the language options promise never reach a functio...
Definition CallUtils.cpp:19
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Definition Utils.h:57
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
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 fakeUseCleanup()
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
clang::QualType ty
Definition CIRGenCall.h:208
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.
Definition Sanitizers.h:174