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
207std::optional<cir::FramePointerKind>
209 switch (kind) {
211 return std::nullopt;
213 return cir::FramePointerKind::Reserved;
215 return cir::FramePointerKind::NonLeafNoReserve;
217 return cir::FramePointerKind::NonLeaf;
219 return cir::FramePointerKind::All;
220 }
221 llvm_unreachable("Unknown frame pointer kind");
222}
223
224/// Add default attributes to a function, which have merge semantics under
225/// -mlink-builtin-bitcode and should not simply overwrite any existing
226/// attributes in the linked library.
228 mlir::MLIRContext *mlirCtx, StringRef name, bool hasOptNoneAttr,
229 const CodeGenOptions &codeGenOpts, const LangOptions &langOpts,
230 bool attrOnCallSite, mlir::NamedAttrList &attrs) {
231 // TODO(cir): Handle optimize attribute flag here.
232 // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
233 if (!hasOptNoneAttr) {
234 if (codeGenOpts.OptimizeSize)
235 attrs.set(cir::CIRDialect::getOptimizeForSizeAttrName(),
236 mlir::UnitAttr::get(mlirCtx));
237 if (codeGenOpts.OptimizeSize == 2)
238 attrs.set(cir::CIRDialect::getMinSizeAttrName(),
239 mlir::UnitAttr::get(mlirCtx));
240 }
241
242 // TODO(cir): Classic codegen adds 'DisableRedZone', 'indirect-tls-seg-refs'
243 // and 'NoImplicitFloat' here.
244
245 if (attrOnCallSite) {
246 // Add the 'nobuiltin' tag, which is different from 'no-builtins'.
247 if (!codeGenOpts.SimplifyLibCalls || langOpts.isNoBuiltinFunc(name))
248 attrs.set(cir::CIRDialect::getNoBuiltinAttrName(),
249 mlir::UnitAttr::get(mlirCtx));
250
251 if (!codeGenOpts.TrapFuncName.empty())
252 attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
253 mlir::StringAttr::get(mlirCtx, codeGenOpts.TrapFuncName));
254 } else {
255 if (std::optional<cir::FramePointerKind> kind =
256 CIRGenModule::getFramePointerKind(codeGenOpts.getFramePointer()))
257 attrs.set(cir::CIRDialect::getFramePointerAttrName(),
258 cir::FramePointerKindAttr::get(mlirCtx, *kind));
259
260 // TODO(cir): a number of other attribute 1-offs based on codegen/lang opts
261 // should be done here: less-recise-fpmad null-pointer-is-valid
262 // no-trapping-math
263 // various inf/nan/nsz/etc work here.
264 //
265 // TODO(cir): set stack-protector buffer size attribute (sorted oddly in
266 // classic compiler inside of the above region, but should be done on its
267 // own).
268 // TODO(cir): other attributes here:
269 // reciprocal estimates, prefer-vector-width, stackrealign, backchain,
270 // split-stack, speculative-load-hardening.
271
272 if (codeGenOpts.getZeroCallUsedRegs() ==
273 llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
274 attrs.erase(cir::CIRDialect::getZeroCallUsedRegsAttrName());
275 else
276 attrs.set(cir::CIRDialect::getZeroCallUsedRegsAttrName(),
277 mlir::StringAttr::get(mlirCtx,
279 codeGenOpts.getZeroCallUsedRegs())));
280 }
281
282 if (langOpts.assumeFunctionsAreConvergent()) {
283 // Conservatively, mark all functions and calls in CUDA and OpenCL as
284 // convergent (meaning, they may call an intrinsically convergent op, such
285 // as __syncthreads() / barrier(), and so can't have certain optimizations
286 // applied around them). LLVM will remove this attribute where it safely
287 // can.
288 attrs.set(cir::CIRDialect::getConvergentAttrName(),
289 mlir::UnitAttr::get(mlirCtx));
290 }
291
292 // Device code cannot unwind. 'nothrow' keeps calls from getting an unwind
293 // edge, so 'nounwind' becomes LLVM's nounwind.
294 // TODO: OpenMP offload is not covered.
295 if ((langOpts.CUDA && langOpts.CUDAIsDevice) || langOpts.OpenCL ||
296 langOpts.SYCLIsDevice) {
297 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
298 mlir::UnitAttr::get(mlirCtx));
299 attrs.set(cir::CIRDialect::getNoUnwindAttrName(),
300 mlir::UnitAttr::get(mlirCtx));
301 }
302
303 if (codeGenOpts.SaveRegParams && !attrOnCallSite)
304 attrs.set(cir::CIRDialect::getSaveRegParamsAttrName(),
305 mlir::UnitAttr::get(mlirCtx));
306
307 // These come in the form of an optional equality sign, so make sure we pass
308 // these on correctly. These will eventually just be passed through to
309 // LLVM-IR, but we want to put them all in 1 array to simplify the
310 // LLVM-MLIR dialect.
311 SmallVector<mlir::NamedAttribute> defaultFuncAttrs;
312 llvm::transform(
313 codeGenOpts.DefaultFunctionAttrs, std::back_inserter(defaultFuncAttrs),
314 [mlirCtx](llvm::StringRef arg) {
315 auto [var, value] = arg.split('=');
316 auto valueAttr =
317 value.empty()
318 ? cast<mlir::Attribute>(mlir::UnitAttr::get(mlirCtx))
319 : cast<mlir::Attribute>(mlir::StringAttr::get(mlirCtx, value));
320 return mlir::NamedAttribute(var, valueAttr);
321 });
322
323 if (!defaultFuncAttrs.empty())
324 attrs.set(cir::CIRDialect::getDefaultFuncAttrsAttrName(),
325 mlir::DictionaryAttr::get(mlirCtx, defaultFuncAttrs));
326
327 // TODO(cir): Do branch protection attributes here.
328}
329
330/// This function matches the behavior of 'getDefaultFunctionAttributes' from
331/// classic codegen, despite the similarity of its name to
332/// 'addDefaultFunctionDefinitionAttributes', which is a caller of this
333/// function.
335 bool hasOptNoneAttr,
336 bool attrOnCallSite,
337 mlir::NamedAttrList &attrs) {
338
340 codeGenOpts, langOpts, attrOnCallSite,
341 attrs);
342
343 if (!attrOnCallSite) {
344 // TODO(cir): Classic codegen adds pointer-auth attributes here, by calling
345 // into TargetCodeGenInfo. At the moment, we've not looked into this as it
346 // is somewhat less used.
347 addMergeableDefaultFunctionAttributes(codeGenOpts, attrs);
348 }
349}
350
351/// Construct the CIR attribute list of a function or call.
353 llvm::StringRef name, const CIRGenFunctionInfo &info,
354 CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs,
356 mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv,
357 bool attrOnCallSite, bool isThunk) {
358 callingConv = info.getCallingConvention();
359
360 auto addUnitAttr = [&](llvm::StringRef name) {
361 attrs.set(name, mlir::UnitAttr::get(&getMLIRContext()));
362 };
363
364 if (info.isNoReturn())
365 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
366
367 // TODO(cir): Implement/check the CSME Nonsecure call attribute here. This
368 // requires being in CSME mode.
369
371 calleeInfo.getCalleeFunctionProtoType());
372
373 const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
374
375 // TODO(cir): OMP Assume Attributes should be here.
376
377 const NoBuiltinAttr *nba = nullptr;
378
379 // TODO(cir): Some work for arg memory effects can be done here, as it is in
380 // classic codegen.
381
382 if (targetDecl) {
383 if (targetDecl->hasAttr<NoThrowAttr>())
384 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
385 // TODO(cir): This is actually only possible if targetDecl isn't a
386 // declarator, which ObjCMethodDecl seems to be the only way to get this to
387 // happen. We're including it here for completeness, but we should add a
388 // test for this when we start generating ObjectiveC.
389 if (targetDecl->hasAttr<NoReturnAttr>())
390 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
391 if (targetDecl->hasAttr<ReturnsTwiceAttr>())
392 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
393 if (targetDecl->hasAttr<ColdAttr>())
394 addUnitAttr(cir::CIRDialect::getColdAttrName());
395 if (targetDecl->hasAttr<HotAttr>())
396 addUnitAttr(cir::CIRDialect::getHotAttrName());
397 if (targetDecl->hasAttr<NoDuplicateAttr>())
398 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
399 if (targetDecl->hasAttr<ConvergentAttr>())
400 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
401
402 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
404 getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
405
406 // TODO(cir): When doing 'return attrs' we need to cover the 'NoAlias' for
407 // global allocation functions here.
409
410 const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
411 bool isVirtualCall = md && md->isVirtual();
412
413 // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
414 // virtual function. These attributes are not inherited by overloads.
415 if (!(attrOnCallSite && isVirtualCall)) {
416 if (func->isNoReturn())
417 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
418 nba = func->getAttr<NoBuiltinAttr>();
419 }
420 }
421
423
424 auto setMemoryEffects = [&](cir::MemoryEffectsAttr effects) {
425 attrs.set(cir::CIRDialect::getMemoryEffectsAttrName(), effects);
426 };
427
428 // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
429 if (targetDecl->hasAttr<ConstAttr>()) {
430 setMemoryEffects(cir::MemoryEffectsAttr::none(&getMLIRContext()));
431 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
432 // gcc specifies that 'const' functions have greater restrictions than
433 // 'pure' functions, so they also cannot have infinite loops.
434 addUnitAttr(cir::CIRDialect::getWillReturnAttrName());
435 } else if (targetDecl->hasAttr<PureAttr>()) {
436 setMemoryEffects(cir::MemoryEffectsAttr::readOnly(&getMLIRContext()));
437 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
438 // gcc specifies that 'pure' functions cannot have infinite loops.
439 addUnitAttr(cir::CIRDialect::getWillReturnAttrName());
440 } else if (targetDecl->hasAttr<NoAliasAttr>()) {
441 setMemoryEffects(
442 cir::MemoryEffectsAttr::inaccessibleOrArgMemOnly(&getMLIRContext()));
443 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
444 }
445
446 // Both __attribute__((malloc)) and __declspec(restrict) are represented by
447 // RestrictAttr. Only forms without a deallocator imply a noalias return.
448 if (const auto *restrictAttr = targetDecl->getAttr<RestrictAttr>();
449 restrictAttr && restrictAttr->getDeallocator() == nullptr)
450 retAttrs.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
451 mlir::UnitAttr::get(&getMLIRContext()));
452
453 if (targetDecl->hasAttr<ReturnsNonNullAttr>() &&
454 !codeGenOpts.NullPointerIsValid)
455 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
456 mlir::UnitAttr::get(&getMLIRContext()));
457 if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
458 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
459 // TODO(cir): Implement 'NoCFCheck' attribute here. This requires
460 // fcf-protection mode.
461 if (targetDecl->hasAttr<LeafAttr>())
462 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
463 // TODO(cir): Implement 'BPFFastCall' attribute here. This requires C, and
464 // the BPF target.
465
466 if (auto *allocSizeAttr = targetDecl->getAttr<AllocSizeAttr>()) {
467 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
468
469 if (allocSizeAttr->getNumElemsParam().isValid()) {
470 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
471 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
472 builder.getDenseI32ArrayAttr(
473 {static_cast<int>(size), static_cast<int>(numElts)}));
474 } else {
475 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
476 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
477 }
478 }
479
480 // TODO(cir): Quite a few CUDA and OpenCL attributes are added here.
481
482 // -cl-uniform-work-group-size / -foffload-uniform-block: work groups are
483 // uniform (global work-size is a multiple of work-group size).
484 if (langOpts.OffloadUniformBlock)
485 addUnitAttr(cir::CIRDialect::getUniformWorkGroupSizeAttrName());
486
487 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
488 targetDecl->hasAttr<CUDAGlobalAttr>()) {
489 GlobalDecl kernel(calleeInfo.getCalleeDecl());
490 llvm::StringRef kernelName = getMangledName(
492 auto attr = cir::CUDAKernelNameAttr::get(
494 mlir::StringAttr::get(&getMLIRContext(), kernelName));
495 attrs.set(attr.getMnemonic(), attr);
496 }
497
498 // TODO(cir): we should also do 'aarch64_pstate_sm_body' here.
499
500 if (auto *modularFormat = targetDecl->getAttr<ModularFormatAttr>()) {
501 FormatAttr *format = targetDecl->getAttr<FormatAttr>();
502 StringRef type = format->getType()->getName();
503 std::string formatIdx = std::to_string(format->getFormatIdx());
504 std::string firstArg = std::to_string(format->getFirstArg());
506 type, formatIdx, firstArg,
507 modularFormat->getModularImplFn()->getName(),
508 modularFormat->getImplName()};
509 llvm::append_range(args, modularFormat->aspects());
510 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
511 builder.getStringAttr(llvm::join(args, ",")));
512 }
513 }
514
516
517 bool hasOptNoneAttr = targetDecl && targetDecl->hasAttr<OptimizeNoneAttr>();
518 addDefaultFunctionAttributes(name, hasOptNoneAttr, attrOnCallSite, attrs);
519 if (targetDecl) {
520 // TODO(cir): There is another region of `if (targetDecl)` that handles
521 // removing some attributes that are necessary modifications of the
522 // default-function attrs. Including:
523 // NoSpeculativeLoadHardening
524 // SpeculativeLoadHardening
525 // NoSplitStack
526 // Non-lazy-bind
527 // 'sample-profile-suffix-elision-policy'.
528
529 if (targetDecl->hasAttr<ZeroCallUsedRegsAttr>()) {
530 // A function "__attribute__((...))" overrides the command-line flag.
531 auto kind =
532 targetDecl->getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
533 attrs.set(
534 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
535 mlir::StringAttr::get(
537 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(kind)));
538 }
539
540 if (targetDecl->hasAttr<NoConvergentAttr>())
541 attrs.erase(cir::CIRDialect::getConvergentAttrName());
542 }
543
544 // Collect non-call-site function IR attributes from declaration-specific
545 // information.
546 if (!attrOnCallSite) {
547 // These functions require the returns_twice attribute for correct
548 // codegen, but the attribute may not be added if -fno-builtin is
549 // specified. We explicitly add that attribute here.
550 static const llvm::StringSet<> returnsTwiceFn{
551 "_setjmpex", "setjmp", "_setjmp", "vfork",
552 "sigsetjmp", "__sigsetjmp", "savectx", "getcontext"};
553 if (returnsTwiceFn.contains(name))
554 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
555
556 llvm::StringMap<std::string> cpuAndFeatures;
557 if (getCPUAndFeaturesAttributes(calleeInfo.getCalleeDecl(),
558 cpuAndFeatures)) {
559 for (const auto &[key, val] : cpuAndFeatures)
560 attrs.set(key, builder.getStringAttr(val));
561 }
562 }
563
564 // TODO(cir): A bunch of non-call-site function IR attributes from
565 // declaration-specific information, including tail calls,
566 // cmse_nonsecure_entry, and hotpatch support.
567
568 // TODO(cir): Add loader-replaceable attribute here.
569
570 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
571 constructFunctionArgumentAttributes(info, targetDecl, isThunk, attrOnCallSite,
572 argAttrs);
573}
574
575bool CIRGenModule::hasStrictReturn(QualType retTy, const Decl *targetDecl) {
576 // As-is msan can not tolerate noundef mismatch between caller and
577 // implementation. Mismatch is possible for e.g. indirect calls from C-caller
578 // into C++. Such mismatches lead to confusing false reports. To avoid
579 // expensive workaround on msan we enforce initialization event in uncommon
580 // cases where it's allowed.
581 if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
582 return true;
583 // C++ explicitly makes returning undefined values UB. C's rule only applies
584 // to used values, so we never mark them noundef for now.
585 if (!getLangOpts().CPlusPlus)
586 return false;
587 if (targetDecl) {
588 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
589 if (func->isExternC())
590 return false;
591 } else if (const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
592 // Function pointer.
593 if (var->isExternC())
594 return false;
595 }
596 }
597
598 // We don't want to be too aggressive with the return checking, unless
599 // it's explicit in the code opts or we're using an appropriate sanitizer.
600 // Try to respect what the programmer intended.
601 return getCodeGenOpts().StrictReturn ||
602 !mayDropFunctionReturn(getASTContext(), retTy) ||
603 getLangOpts().Sanitize.has(SanitizerKind::Return);
604}
605
606bool CIRGenModule::mayDropFunctionReturn(const ASTContext &context,
607 QualType retTy) {
608 // We can't just discard the return value for a record type with a
609 // complex destructor or a non-trivially copyable type.
610 if (const RecordType *recTy =
611 retTy.getCanonicalType()->getAsCanonical<RecordType>()) {
612 if (const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
613 return record->hasTrivialDestructor();
614 }
615 return retTy.isTriviallyCopyableType(context);
616}
617
618static bool determineNoUndef(QualType clangTy, CIRGenTypes &types,
619 const cir::CIRDataLayout &layout,
620 const cir::ABIArgInfo &argInfo) {
621 mlir::Type ty = types.convertTypeForMem(clangTy);
623 if (argInfo.isIndirect() || argInfo.isIndirectAliased())
624 return true;
625 if (argInfo.isExtend() && !argInfo.isNoExt())
626 return true;
627
628 if (cir::isSized(ty) && !layout.typeSizeEqualsStoreSize(ty))
629 // TODO: This will result in a modest amount of values not marked noundef
630 // when they could be. We care about values that *invisibly* contain undef
631 // bits from the perspective of LLVM IR.
632 return false;
633
634 // Classic CodeGen stores a packed bool vector as an integer with one bit per
635 // element, at least a byte wide, so the check above drops noundef when that
636 // integer is not a whole number of bytes. The CIR vector type is sized to a
637 // power of two of at least a byte, which always passes that check, so test
638 // the storage integer's width directly.
639 if (clangTy->isPackedVectorBoolType(types.getASTContext()) &&
640 mlir::cast<cir::VectorType>(ty).getBoolStorageWidth() % 8)
641 return false;
642
644 // The coerced type is not known until CallConvLowering, which drops noundef
645 // when it is wider than the value's memory type, the check classic
646 // DetermineNoUndef makes at this point.
647 if (clangTy->isBitIntType())
648 return true;
649 if (clangTy->isReferenceType())
650 return true;
651 if (clangTy->isNullPtrType())
652 return false;
653 if (clangTy->isMemberPointerType())
654 // TODO: Some member pointers are `noundef`, but it depends on the ABI. For
655 // now, never mark them.
656 return false;
657 if (clangTy->isScalarType()) {
658 if (const ComplexType *Complex = dyn_cast<ComplexType>(clangTy))
659 return determineNoUndef(Complex->getElementType(), types, layout,
660 argInfo);
661 return true;
662 }
663 if (const VectorType *Vector = dyn_cast<VectorType>(clangTy))
664 return determineNoUndef(Vector->getElementType(), types, layout, argInfo);
665 if (const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
666 return determineNoUndef(Matrix->getElementType(), types, layout, argInfo);
667 if (const ArrayType *Array = dyn_cast<ArrayType>(clangTy))
668 return determineNoUndef(Array->getElementType(), types, layout, argInfo);
669
670 // TODO: Some structs may be `noundef`, in specific situations.
671 return false;
672}
673
674void CIRGenModule::constructFunctionReturnAttributes(
675 const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
676 mlir::NamedAttrList &retAttrs) {
677 // Collect attributes from arguments and return values.
678 QualType retTy = info.getReturnType();
679 const cir::ABIArgInfo retInfo = info.getReturnInfo();
680 const cir::CIRDataLayout &layout = getDataLayout();
681
682 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
683 !retTy->isVoidType() &&
684 determineNoUndef(retTy, getTypes(), layout, retInfo))
685 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
686 mlir::UnitAttr::get(&getMLIRContext()));
687
688 if (retTy->hasFloatingRepresentation())
689 if (llvm::FPClassTest mask =
691 retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
692 builder.getI64IntegerAttr(mask));
693
694 if (!isThunk) {
695 // TODO(cir): following comment taken from classic codegen, so if anything
696 // happens there, we should reflect it here.
697 // FIXME: fix this properly, https://reviews.llvm.org/D100388
698 if (const auto *refTy = retTy->getAs<ReferenceType>()) {
699 QualType pointeeTy = refTy->getPointeeType();
700 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
701 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
702 builder.getI64IntegerAttr(
703 getMinimumObjectSize(pointeeTy).getQuantity()));
704
705 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
706 !codeGenOpts.NullPointerIsValid)
707 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
708 mlir::UnitAttr::get(&getMLIRContext()));
709
710 if (pointeeTy->isObjectType())
711 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
712 builder.getI64IntegerAttr(
713 getNaturalPointeeTypeAlignment(retTy).getQuantity()));
714 }
715 }
716}
717
718void CIRGenModule::constructFunctionArgumentAttributes(
719 const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
720 bool attrOnCallSite, llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
722 // TODO(cir): classic codegen does a lot of work here based on the ABIArgInfo
723 // to set things based on calling convention.
724
725 if (info.isInstanceMethod() && !isThunk) {
726 QualType thisPtrTy = info.arguments()[0];
727 // Member allocation functions are instance methods, but setting attributes
728 // on them is nonsensical and not correct. Make sure we skip that here.
729 if (!thisPtrTy->isVoidPointerType()) {
730 QualType thisTy = thisPtrTy->getPointeeType();
731
732 if (!codeGenOpts.NullPointerIsValid &&
733 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
734 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
735 builder.getI64IntegerAttr(
736 getMinimumObjectSize(thisTy).getQuantity()));
737 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
738 mlir::UnitAttr::get(&getMLIRContext()));
739 } else {
741
742 if (bytes != 0)
743 argAttrs[0].set(
744 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
745 builder.getI64IntegerAttr(bytes));
746 }
747
748 argAttrs[0].set(
749 mlir::LLVM::LLVMDialect::getAlignAttrName(),
750 builder.getI64IntegerAttr(
751 getNaturalPointeeTypeAlignment(thisPtrTy).getQuantity()));
752
753 // TODO(cir): the classic codegen has a recently-added bunch of logic for
754 // 'dead_on_return' as an attribute. This both doesn't exist in the LLVM
755 // dialect, and is 'too new' at the time of writing this to be considered
756 // stable enough here. For now, we'll leave this as a TODO so that when
757 // we come back, it is hopefully a more stabilized implementation.
758 }
759 }
760
761 // TODO(cir): the logic between 'this', return, and normal arguments hsould
762 // probably be merged at one point, however the logic is unfortunately mildly
763 // different between each in classic codegen, so trying to do anything like
764 // that seems risky at the moment. At one point we should evaluate if at least
765 // dereferenceable, nonnull, and align can be combined.
766 const cir::CIRDataLayout &layout = getDataLayout();
767 const auto *fd = dyn_cast_or_null<FunctionDecl>(targetDecl);
768
769 // Build a parallel array of ParmVarDecls aligned with argAttrs so we can
770 // access parameter-level attributes (e.g. restrict, nonnull) without manual
771 // index arithmetic in the loop.
772 SmallVector<const ParmVarDecl *> parmDecls;
773 parmDecls.reserve(argAttrs.size());
774 if (fd) {
775 if (info.isInstanceMethod())
776 parmDecls.push_back(nullptr);
777 parmDecls.insert(parmDecls.end(), fd->param_begin(), fd->param_end());
778 }
779 parmDecls.resize(argAttrs.size(), nullptr);
780
781 for (const auto &[argAttrList, argCanType, pvd] :
782 llvm::zip_equal(argAttrs, info.arguments(), parmDecls)) {
784 QualType argType = argCanType;
785 const cir::ABIArgInfo argInfo = cir::ABIArgInfo::getDirect();
786
787 if (codeGenOpts.EnableNoundefAttrs &&
788 determineNoUndef(argType, getTypes(), layout, argInfo))
789 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
790 mlir::UnitAttr::get(&getMLIRContext()));
791
793 // TODO(cir): there is plenty of other attributes here added due to ABI
794 // decisions. While these probably won't end up here, we note that the
795 // classic codegen does it here and perhaps we should pay attention to that.
796
797 if (const auto *refTy = argType->getAs<ReferenceType>()) {
798 QualType pointeeTy = refTy->getPointeeType();
799 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
800 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
801 builder.getI64IntegerAttr(
802 getMinimumObjectSize(pointeeTy).getQuantity()));
803 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
804 !codeGenOpts.NullPointerIsValid)
805 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
806 mlir::UnitAttr::get(&getMLIRContext()));
807 if (pointeeTy->isObjectType())
808 argAttrList.set(
809 mlir::LLVM::LLVMDialect::getAlignAttrName(),
810 builder.getI64IntegerAttr(
811 getNaturalPointeeTypeAlignment(argType).getQuantity()));
812 }
813
814 if (argType->hasFloatingRepresentation())
815 if (llvm::FPClassTest mask =
817 argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
818 builder.getI64IntegerAttr(mask));
819
820 // restrict -> noalias on definitions only (not call sites). Skip
821 // builtins: OGCG applies restrict->noalias in EmitFunctionProlog.
822 if (!attrOnCallSite && pvd && pvd->getType()->isPointerType() &&
823 pvd->getType().isRestrictQualified() && !fd->getBuiltinID())
824 argAttrList.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
825 mlir::UnitAttr::get(&getMLIRContext()));
826
827 // __attribute__((nonnull)) on pointer parameters. Checks both
828 // per-parameter and function-level nonnull attributes.
829 if (pvd && argType->isAnyPointerType() && !codeGenOpts.NullPointerIsValid) {
830 unsigned srcIdx = pvd->getFunctionScopeIndex();
831 if (pvd->hasAttr<NonNullAttr>() ||
832 (fd->getAttr<NonNullAttr>() &&
833 fd->getAttr<NonNullAttr>()->isNonNull(srcIdx)))
834 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
835 mlir::UnitAttr::get(&getMLIRContext()));
836 }
837 }
838}
839
840/// Adds the formal parameters in FPT to the given prefix. If any parameter in
841/// FPT has pass_object_size attrs, then we'll add parameters for those, too.
842/// TODO(cir): this should be shared with LLVM codegen
843static void appendParameterTypes(const CIRGenTypes &cgt,
846 // Fast path: don't touch param info if we don't need to.
847 if (!fpt->hasExtParameterInfos()) {
848 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
849 return;
850 }
851
852 // In the vast majority of cases, we'll have precisely fpt->getNumParams()
853 // parameters; the only thing that can change this is the presence of
854 // pass_object_size. So, we preallocate for the common case.
855 prefix.reserve(prefix.size() + fpt->getNumParams());
857 fpt->getExtParameterInfos();
858 assert(extInfos.size() == fpt->getNumParams());
859 for (auto [paramType, extInfo] : llvm::zip_equal(
860 llvm::make_range(fpt->param_type_begin(), fpt->param_type_end()),
861 extInfos)) {
862 prefix.push_back(paramType);
863 if (extInfo.hasPassObjectSize())
864 prefix.push_back(cgt.getASTContext().getCanonicalSizeType());
865 }
866}
867
868const CIRGenFunctionInfo &
870 auto *md = cast<CXXMethodDecl>(gd.getDecl());
871
873 argTypes.push_back(deriveThisType(md->getParent(), md));
874
875 bool passParams = true;
876
877 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
878 // A base class inheriting constructor doesn't get forwarded arguments
879 // needed to construct a virtual base (or base class thereof)
880 if (auto inherited = cd->getInheritedConstructor())
881 passParams = inheritingCtorHasParams(inherited, gd.getCtorType());
882 }
883
885
886 if (passParams)
887 appendParameterTypes(*this, argTypes, fpt);
888
889 // The structor signature may include implicit parameters.
890 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
891 theCXXABI.buildStructorSignature(gd, argTypes);
893
894 RequiredArgs required =
895 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
897
898 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
899 : theCXXABI.hasMostDerivedReturn(gd)
900 ? astContext.VoidPtrTy
901 : astContext.VoidTy;
902
903 assert(!theCXXABI.hasThisReturn(gd) &&
904 "Please send PR with a test and remove this");
905
908
909 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
910 fpt->getExtInfo(), required);
911}
912
913/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
914/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
915/// indicates that there is no meaningful 'this' type, and a null `md` can occur
916/// when calling a method pointer.
918 const CXXMethodDecl *md) {
919 CanQualType recTy;
920 if (rd) {
922 } else {
923 // This can happen with the MS ABI. It shouldn't need anything more than
924 // setting recTy to VoidTy here, but we're flagging it for now because we
925 // don't have the full handling implemented.
926 cgm.errorNYI("deriveThisType: no record decl");
927 recTy = getASTContext().VoidTy;
928 }
929
930 if (md)
931 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
932 recTy, md->getMethodQualifiers().getAddressSpace()));
933 return getASTContext().getPointerType(recTy);
934}
935
936/// Arrange the CIR function layout for a value of the given function type, on
937/// top of any implicit parameters already stored.
938static const CIRGenFunctionInfo &
939arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod,
943 RequiredArgs required =
946 appendParameterTypes(cgt, prefix, fpt);
947 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
948 return cgt.arrangeCIRFunctionInfo(resultType, instanceMethod, prefix,
949 fpt->getExtInfo(), required);
950}
951
953 const VarDecl *param,
954 SourceLocation loc) {
955 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
956 // We need to turn that into an r-value suitable for emitCall
957 Address local = getAddrOfLocalVar(param);
958
959 QualType type = param->getType();
960
961 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
962 // argument needs to be the original pointer.
963 if (type->isReferenceType()) {
964 args.add(
965 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
966 type);
967 } else if (getLangOpts().ObjCAutoRefCount) {
968 cgm.errorNYI(param->getSourceRange(),
969 "emitDelegateCallArg: ObjCAutoRefCount");
970 // For the most part, we just need to load the alloca, except that aggregate
971 // r-values are actually pointers to temporaries.
972 } else {
973 args.add(convertTempToRValue(local, type, loc), type);
974 }
975
976 // Deactivate the cleanup for the callee-destructed param that was pushed.
978 if (type->isRecordType() &&
979 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
980 param->needsDestruction(getContext())) {
981 cgm.errorNYI(param->getSourceRange(),
982 "emitDelegateCallArg: callee-destructed param");
983 }
984}
985
986static const CIRGenFunctionInfo &
988 const CallArgList &args,
989 const FunctionType *fnType) {
990
992
993 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
994 // A free function call has no extra prefix arguments. Note that
995 // getFromProtoWithExtraSlots already accounts for the prototype's
996 // pass_object_size parameters; adding them here too would double-count
997 // them and make the signature claim more required arguments than `args`
998 // actually holds.
999 if (proto->isVariadic())
1000 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
1003 cgm.errorNYI("call to function without a prototype");
1004
1006 for (const CallArg &arg : args)
1007 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
1008
1010
1012 return cgt.arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false,
1013 argTypes, fnType->getExtInfo(), required);
1014}
1015
1016/// Arrange a call to a C++ method, passing the given arguments.
1017///
1018/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
1019/// parameter.
1020/// passProtoArgs indicates whether `args` has args for the parameters in the
1021/// given CXXConstructorDecl.
1023 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
1024 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
1025
1026 // FIXME: Kill copy.
1028 for (const auto &arg : args)
1029 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1030
1031 // +1 for implicit this, which should always be args[0]
1032 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
1033
1035 RequiredArgs required = passProtoArgs
1037 fpt, totalPrefixArgs + extraSuffixArgs)
1039
1040 GlobalDecl gd(d, ctorKind);
1041 if (theCXXABI.hasThisReturn(gd))
1042 cgm.errorNYI(d->getSourceRange(),
1043 "arrangeCXXConstructorCall: hasThisReturn");
1044 if (theCXXABI.hasMostDerivedReturn(gd))
1045 cgm.errorNYI(d->getSourceRange(),
1046 "arrangeCXXConstructorCall: hasMostDerivedReturn");
1047 CanQualType resultType = astContext.VoidTy;
1048
1051
1052 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
1053 fpt->getExtInfo(), required);
1054}
1055
1056/// Arrange a call to a C++ method, passing the given arguments.
1057///
1058/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
1059/// does not count `this`.
1061 const CallArgList &args, const FunctionProtoType *proto,
1062 RequiredArgs required, unsigned numPrefixArgs) {
1064 assert(numPrefixArgs + 1 <= args.size() &&
1065 "Emitting a call with less args than the required prefix?");
1066
1067 // FIXME: Kill copy.
1069 for (const CallArg &arg : args)
1070 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1071
1075 /*isInstanceMethod=*/true, argTypes, proto->getExtInfo(), required);
1076}
1077
1078const CIRGenFunctionInfo &
1080 const FunctionType *fnType) {
1081 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
1082}
1083
1084const CIRGenFunctionInfo &
1086 const CallArgList &args) {
1088 for (const CallArg &arg : args)
1089 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1090
1091 CanQualType retType = resultType->getCanonicalTypeUnqualified();
1092 return arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false, argTypes,
1094}
1095
1096/// Set calling convention for CUDA/HIP kernel.
1098 CIRGenModule &cgm,
1099 const FunctionDecl *fd) {
1100 if (fd->hasAttr<CUDAGlobalAttr>()) {
1101 const FunctionType *ft = funcTy->getAs<FunctionType>();
1103 funcTy = ft->getCanonicalTypeUnqualified();
1104 }
1105}
1106
1107/// Arrange the argument and result information for a declaration or definition
1108/// of the given C++ non-static member function. The member function must be an
1109/// ordinary function, i.e. not a constructor or destructor.
1110const CIRGenFunctionInfo &
1112 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
1113 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
1114
1116 setCUDAKernelCallingConvention(funcTy, cgm, md);
1117 auto prototype = funcTy.getAs<FunctionProtoType>();
1118
1119 // Mirrors classic CodeGen's check at CGCall.cpp. C++23 explicit-object
1120 // member functions (P0847R7, `void f(this Self&&)`) do not receive an
1121 // implicit `this`; the explicit object parameter takes its place at the
1122 // AST level and appears as the first parameter of the FunctionProtoType.
1123 // Arrange them as free functions so we don't prepend a stale implicit
1124 // `this` to the parameter list, which would produce a CIRGenFunctionInfo
1125 // with one more argument than the matching cir.func type and trip the
1126 // assertion in setArgAttrs.
1128 // The abstract case is perfectly fine.
1129 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1130 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
1131 }
1132
1133 return arrangeFreeFunctionType(prototype);
1134}
1135
1136/// Arrange the argument and result information for a call to an unknown C++
1137/// non-static member function of the given abstract type. (A null RD means we
1138/// don't have any meaningful "this" argument type, so fall back to a generic
1139/// pointer type). The member fucntion must be an ordinary function, i.e. not a
1140/// constructor or destructor.
1141const CIRGenFunctionInfo &
1143 const FunctionProtoType *fpt,
1144 const CXXMethodDecl *md) {
1146
1147 // Add the 'this' pointer.
1148 argTypes.push_back(deriveThisType(rd, md));
1149
1151 return ::arrangeCIRFunctionInfo(
1152 *this, /*isInstanceMethod=*/true, argTypes,
1154}
1155
1156/// Arrange the argument and result information for the declaration or
1157/// definition of the given function.
1158const CIRGenFunctionInfo &
1160 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1161 if (md->isInstance())
1162 return arrangeCXXMethodDeclaration(md);
1163
1165
1166 assert(isa<FunctionType>(funcTy));
1167 setCUDAKernelCallingConvention(funcTy, cgm, fd);
1168
1169 // When declaring a function without a prototype, always use a non-variadic
1170 // type.
1171 if (CanQual<FunctionNoProtoType> noProto =
1172 funcTy.getAs<FunctionNoProtoType>()) {
1175 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1176 /*isInstanceMethod=*/false, {},
1177 noProto->getExtInfo(), RequiredArgs::All);
1178 }
1179
1181}
1182
1183RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1184 if (!hasLV)
1185 return rv;
1186 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1188 lv.isVolatile());
1189 isUsed = true;
1190 return RValue::getAggregate(copy.getAddress());
1191}
1192
1194 SourceLocation argLoc,
1195 AbstractCallee ac, unsigned paramNum) {
1196 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1197 sanOpts.has(SanitizerKind::NullabilityArg)))
1198 return;
1199 cgm.errorNYI("non-null arg check is NYI");
1200}
1201
1202static cir::CIRCallOpInterface emitCallLikeOp(
1203 CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy,
1204 mlir::Value indirectFuncVal, cir::FuncOp directFuncOp,
1205 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1206 const mlir::NamedAttrList &attrs,
1208 const mlir::NamedAttrList &retAttrs, cir::CallingConv callingConv) {
1209 CIRGenBuilderTy &builder = cgf.getBuilder();
1210
1212
1213 assert(builder.getInsertionBlock() && "expected valid basic block");
1214
1215 cir::CallOp op;
1216 if (indirectFuncTy) {
1217 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1218 cirCallArgs, attrs, argAttrs, retAttrs,
1219 callingConv);
1220 } else {
1221 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1222 argAttrs, retAttrs, callingConv);
1223 }
1224
1225 return op;
1226}
1227
1228const CIRGenFunctionInfo &
1232 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1233 fpt);
1234}
1235
1236const CIRGenFunctionInfo &
1238 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1240 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1241 fnpt->getExtInfo(), RequiredArgs(0));
1242}
1243
1245 const CIRGenCallee &callee,
1247 const CallArgList &args,
1248 cir::CIRCallOpInterface *callOp,
1249 bool isMustTail, SourceRange clangLoc) {
1250 QualType retTy = funcInfo.getReturnType();
1251 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1252 mlir::Location loc = getLoc(clangLoc);
1253
1254 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1255
1256 const Decl *targetDecl = callee.getAbstractInfo().getCalleeDecl().getDecl();
1257
1258 if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(targetDecl)) {
1259 // We can only guarantee that a function is called from the correct
1260 // context/function based on the appropriate target attributes,
1261 // so only check in the case where we have both always_inline and target
1262 // since otherwise we could be making a conditional call after a check for
1263 // the proper cpu features (and it won't cause code generation issues due to
1264 // function based code generation).
1265 if ((targetDecl->hasAttr<AlwaysInlineAttr>() &&
1266 (targetDecl->hasAttr<TargetAttr>() ||
1267 (curFuncDecl && curFuncDecl->hasAttr<TargetAttr>()))) ||
1268 (curFuncDecl && curFuncDecl->hasAttr<FlattenAttr>() &&
1269 (curFuncDecl->hasAttr<TargetAttr>() ||
1270 targetDecl->hasAttr<TargetAttr>())))
1271 checkTargetFeatures(clangLoc.getBegin(), fd);
1272 }
1273
1274 const FunctionDecl *callerDecl = dyn_cast_or_null<FunctionDecl>(curCodeDecl);
1275 const FunctionDecl *calleeDecl = dyn_cast_or_null<FunctionDecl>(targetDecl);
1276
1278
1279 // Translate all of the arguments as necessary to match the CIR lowering.
1280 for (auto [argNo, arg, canQualArgType] :
1281 llvm::enumerate(args, funcInfo.argTypes())) {
1282
1283 // Insert a padding argument to ensure proper alignment.
1285
1286 mlir::Type argType = convertType(canQualArgType);
1287 if (!mlir::isa<cir::RecordType>(argType) &&
1288 !mlir::isa<cir::ComplexType>(argType)) {
1289 mlir::Value v;
1290 if (arg.isAggregate())
1291 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1292 v = arg.getKnownRValue().getValue();
1293
1294 // We might have to widen integers, but we should never truncate.
1295 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1296 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1297
1298 // If we have a pointer argument and there's an address space mismatch,
1299 // insert an address_space cast to match the expected function signature.
1300 if (argType != v.getType()) {
1301 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1302 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1303 if (argPtrTy && vPtrTy &&
1304 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1305 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1306 v = performAddrSpaceCast(v, argPtrTy);
1307 }
1308 }
1309
1310 // If the argument doesn't match, perform a bitcast to coerce it. This
1311 // can happen due to trivial type mismatches.
1312 // TODO(cir): When getFunctionType is added, assert that this isn't
1313 // needed.
1315 cirCallArgs[argNo] = v;
1316 } else {
1317 Address src = Address::invalid();
1318 if (!arg.isAggregate()) {
1319 src = createMemTemp(arg.ty, loc, "coerce");
1320 arg.copyInto(*this, src, loc);
1321 } else {
1322 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1323 : arg.getKnownRValue().getAggregateAddress();
1324 }
1325
1326 // Fast-isel and the optimizer generally like scalar values better than
1327 // FCAs, so we flatten them if this is safe to do for this argument.
1328 mlir::Type srcTy = src.getElementType();
1329 // FIXME(cir): get proper location for each argument.
1330 mlir::Location argLoc = loc;
1331
1332 // If the source type is smaller than the destination type of the
1333 // coerce-to logic, copy the source value into a temp alloca the size
1334 // of the destination type to allow loading all of it. The bits past
1335 // the source value are left undef.
1336 // FIXME(cir): add data layout info and compare sizes instead of
1337 // matching the types.
1338 //
1339 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1340 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1341 // if (SrcSize < DstSize) {
1343 if (srcTy != argType) {
1344 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1345 } else {
1346 // FIXME(cir): this currently only runs when the types are exactly the
1347 // same, but should be when alloc sizes are the same, fix this as soon
1348 // as datalayout gets introduced.
1350 }
1351
1352 // assert(NumCIRArgs == STy.getMembers().size());
1353 // In LLVMGen: Still only pass the struct without any gaps but mark it
1354 // as such somehow.
1355 //
1356 // In CIRGen: Emit a load from the "whole" struct,
1357 // which shall be broken later by some lowering step into multiple
1358 // loads.
1360 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1361 }
1362 }
1363
1364 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1365 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1366
1368
1369 mlir::NamedAttrList attrs;
1370 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1371 mlir::NamedAttrList retAttrs;
1372 StringRef funcName;
1373 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1374 funcName = calleeFuncOp.getName();
1375
1377 cir::CallingConv callingConv;
1378 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1379 attrs, argAttrs, retAttrs, callingConv,
1380 /*attrOnCallSite=*/true, /*isThunk=*/false);
1381
1382 // TODO(cir): Classic CodeGen redirects calls to OpenCL kernels to a
1383 // non-kernel stub (__clang_ocl_kern_imp_*), since kernel calling conventions
1384 // do not permit calls.
1385 if (callingConv == cir::CallingConv::SpirKernel ||
1386 callingConv == cir::CallingConv::AMDGPUKernel ||
1387 callingConv == cir::CallingConv::PTXKernel)
1388 cgm.errorNYI(loc, "emitCall: call to kernel function");
1389
1390 auto resolvedFuncOpFromGlobal = [&](mlir::Operation *op) -> cir::FuncOp {
1391 if (auto fnOp = dyn_cast<cir::FuncOp>(op))
1392 return fnOp;
1393 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(op)) {
1394 // FIXME(cir): This peephole optimization avoids indirect calls for
1395 // builtins. This should be fixed in the builtin declaration instead by
1396 // not emitting an unecessary get_global in the first place. However,
1397 // this is also used for no-prototype functions.
1398 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1399 assert(globalOp && "undefined global function");
1400 return cast<cir::FuncOp>(globalOp);
1401 }
1402 return nullptr;
1403 };
1404
1405 cir::FuncType indirectFuncTy;
1406 mlir::Value indirectFuncVal;
1407 cir::FuncOp directFuncOp;
1408
1409 // If the callee resolves to a FuncOp whose stored signature differs from
1410 // this call site's expected signature, the CIR verifier would reject the
1411 // mismatched types. This happens, for example, when two declarations share a
1412 // mangled name via __asm__ renaming (glibc's __REDIRECT_NTH pattern) but
1413 // disagree about a struct argument type. If that happens, we demote the
1414 // direct call to an indirect call through a function-pointer bitcast typed
1415 // at the call site.
1416 if (cir::FuncOp candidate = resolvedFuncOpFromGlobal(calleePtr)) {
1417 if (candidate.getFunctionType() == cirFuncTy) {
1418 directFuncOp = candidate;
1419 } else {
1420 mlir::Value addr = cir::GetGlobalOp::create(
1421 builder, loc, cir::PointerType::get(candidate.getFunctionType()),
1422 candidate.getSymName());
1423 indirectFuncTy = cirFuncTy;
1424 indirectFuncVal =
1425 builder.createBitcast(addr, cir::PointerType::get(cirFuncTy));
1426 }
1427 } else {
1428 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1429 calleePtr->getResultTypes();
1430 [[maybe_unused]] auto funcPtrTy =
1431 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1432 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1433 "expected pointer to function");
1434
1435 indirectFuncTy = cirFuncTy;
1436 indirectFuncVal = calleePtr->getResult(0);
1437 }
1438
1442
1443 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1444 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1445
1446 mlir::Location callLoc = loc;
1447 cir::CIRCallOpInterface theCall = emitCallLikeOp(
1448 *this, loc, indirectFuncTy, indirectFuncVal, directFuncOp, cirCallArgs,
1449 isInvoke, attrs, argAttrs, retAttrs, callingConv);
1450
1451 if (callOp)
1452 *callOp = theCall;
1453
1454 // Add srcloc if we have [[gnu::error/warning]] or ShowInliningChain.
1455 if (calleeDecl) {
1456 bool needSrcLoc = calleeDecl->hasAttr<ErrorAttr>();
1457 if (!needSrcLoc && cgm.getCodeGenOpts().ShowInliningChain)
1458 needSrcLoc = calleeDecl->isInlined() ||
1459 calleeDecl->hasAttr<AlwaysInlineAttr>() ||
1460 calleeDecl->getStorageClass() == SC_Static ||
1461 calleeDecl->isInAnonymousNamespace();
1462 if (needSrcLoc)
1463 theCall->setAttr(
1464 cir::CIRDialect::getSrcLocAttrName(),
1465 builder.getI64IntegerAttr(clangLoc.getBegin().getRawEncoding()));
1466 }
1467
1468 // Sema/emitAttributedStmt (see
1469 // https://github.com/llvm/llvm-project/issues/214764) should one-day enforce
1470 // that only one of these is valid at a time. For now, we have the same 'bug'
1471 // as classic codegen where we can end up having BOTH of these.
1473 theCall.setInlineKind(cir::InlineKind::NoInline);
1475 !cgm.getTargetCIRGenInfo().wouldInliningViolateFunctionCallABI(
1476 callerDecl, calleeDecl))
1477 theCall.setInlineKind(cir::InlineKind::AlwaysInline);
1478
1479 if (isMustTail) {
1480 // PPC/MIPS have some diagnostics for classic-codegen, but we don't support
1481 // them yet.
1482 const llvm::Triple &triple = getTarget().getTriple();
1483 if (triple.isPPC() || triple.isMIPS()) {
1484 cgm.errorNYI(mustTailCall->getBeginLoc(),
1485 "musttail call target legality checks");
1486 return getUndefRValue(retTy);
1487 }
1488
1489 // This call replaces the frame that the handler enforcing the exception
1490 // specification belongs to, taking that handler with it.
1491 if (ehSpecTryOp) {
1492 if (!inEHSpecTerminateScope()) {
1493 // The filter of a dynamic specification has to run while an exception
1494 // is leaving the function, and the tail call skips over it.
1495 cgm.errorUnsupported(mustTailCall, "tail call skipping over cleanups");
1496 return getUndefRValue(retTy);
1497 }
1498
1499 // Losing a terminate handler is safe when the callee cannot throw,
1500 // because then the callee's own handler stands in for it.
1501 if (!cannotThrow) {
1502 cgm.getDiags().Report(mustTailCall->getBeginLoc(),
1503 diag::err_musttail_noexcept_mismatch);
1504 return getUndefRValue(retTy);
1505 }
1506 }
1507
1508 // Musttail is required to return immediately, so no cleanup can run
1509 // between the call and the return. Cleanups that the return makes
1510 // unnecessary are simply skipped. Anything else cannot be expressed.
1512 for (EHScopeStack::iterator it = ehStack.begin(),
1513 end = ehStack.find(prologueCleanupDepth);
1514 it != end; ++it) {
1515 auto *cleanupScope = dyn_cast<EHCleanupScope>(&*it);
1516 if (!cleanupScope ||
1517 !cleanupScope->getCleanup()->isRedundantBeforeReturn()) {
1518 cgm.errorUnsupported(mustTailCall, "tail call skipping over cleanups");
1519 return getUndefRValue(retTy);
1520 }
1521 }
1522
1523 theCall->setAttr(cir::CIRDialect::getMustTailAttrName(),
1524 builder.getUnitAttr());
1525
1526 if (isa<cir::VoidType>(convertType(retTy)))
1527 cir::ReturnOp::create(builder, loc);
1528 else
1529 cir::ReturnOp::create(builder, loc, theCall->getResult(0));
1530
1531 // Musttail must return immediately, so we just do that. All of the below
1532 // stuff is effectively UB if this is a musttail, so just do a return
1533 // immediately.
1534 builder.createBlock(builder.getBlock()->getParent());
1535 return getUndefRValue(retTy);
1536 }
1537
1539
1540 mlir::Type retCIRTy = convertType(retTy);
1541 if (isa<cir::VoidType>(retCIRTy))
1542 return getUndefRValue(retTy);
1543 switch (getEvaluationKind(retTy)) {
1544 case cir::TEK_Aggregate: {
1545 Address destPtr = returnValue.getValue();
1546
1547 if (!destPtr.isValid())
1548 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1549
1550 mlir::ResultRange results = theCall->getOpResults();
1551 assert(results.size() <= 1 && "multiple returns from a call");
1552
1553 SourceLocRAIIObject loc{*this, clangLoc};
1554 emitAggregateStore(results[0], destPtr);
1555 return RValue::getAggregate(destPtr);
1556 }
1557 case cir::TEK_Scalar: {
1558 mlir::ResultRange results = theCall->getOpResults();
1559 assert(results.size() == 1 && "unexpected number of returns");
1560
1561 // If the argument doesn't match, perform a bitcast to coerce it. This
1562 // can happen due to trivial type mismatches.
1563 if (results[0].getType() != retCIRTy)
1564 cgm.errorNYI(loc, "bitcast on function return value");
1565
1566 mlir::Region *region = builder.getBlock()->getParent();
1567 if (region != theCall->getParentRegion())
1568 cgm.errorNYI(loc, "function calls with cleanup");
1569
1570 return RValue::get(results[0]);
1571 }
1572 case cir::TEK_Complex: {
1573 mlir::ResultRange results = theCall->getOpResults();
1574 assert(!results.empty() &&
1575 "Expected at least one result for complex rvalue");
1576 return RValue::getComplex(results[0]);
1577 }
1578 }
1579 llvm_unreachable("Invalid evaluation kind");
1580}
1581
1583 mlir::Location loc) const {
1584 LValue dst = cgf.makeAddrLValue(addr, ty);
1585 if (!hasLV && rv.isScalar())
1586 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1587 else if (!hasLV && rv.isComplex())
1588 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1589 else
1590 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1591 isUsed = true;
1592}
1593
1594mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1595 cir::FuncOp callee,
1597 mlir::NamedAttrList attrs) {
1598
1599 // TODO(cir): set the calling convention to this runtime call.
1601
1602 cir::CallOp call = builder.createCallOp(loc, callee, args);
1603 assert(call->getNumResults() <= 1 &&
1604 "runtime functions have at most 1 result");
1605
1606 if (!attrs.empty())
1607 call->setAttrs(attrs);
1608
1609 if (call->getNumResults() == 0)
1610 return nullptr;
1611
1612 return call->getResult(0);
1613}
1614
1616 clang::QualType argType) {
1617 assert(argType->isReferenceType() == e->isGLValue() &&
1618 "reference binding to unmaterialized r-value!");
1619
1620 if (e->isGLValue()) {
1621 assert(e->getObjectKind() == OK_Ordinary);
1622 return args.add(emitReferenceBindingToExpr(e), argType);
1623 }
1624
1625 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1626
1627 // For callee-destructed parameters (trivial_abi, MS ABI), create an
1628 // aggregate temp and let the callee destroy it.
1629 if (argType->isRecordType() &&
1631 AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
1633
1634 bool destroyedInCallee = true;
1635 if (const auto *rd = argType->getAsCXXRecordDecl())
1636 destroyedInCallee = rd->hasNonTrivialDestructor();
1637
1638 if (destroyedInCallee)
1640
1641 emitAggExpr(e, slot);
1642 RValue rv = slot.asRValue();
1643 args.add(rv, argType);
1644
1645 if (destroyedInCallee && getLangOpts().Exceptions)
1646 cgm.errorNYI(e->getSourceRange(),
1647 "callee-destructed param with exceptions");
1648 return;
1649 }
1650
1651 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1652 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1653 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1654 assert(lv.isSimple());
1655 args.addUncopiedAggregate(lv, argType);
1656 return;
1657 }
1658
1659 args.add(emitAnyExprToTemp(e), argType);
1660}
1661
1662QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1663 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1664 // implicitly widens null pointer constants that are arguments to varargs
1665 // functions to pointer-sized ints.
1666 if (!getTarget().getTriple().isOSWindows())
1667 return arg->getType();
1668
1669 assert(!cir::MissingFeatures::msabi());
1670 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1671 return arg->getType();
1672}
1673
1674/// Similar to emitAnyExpr(), however, the result will always be accessible
1675/// even if no aggregate location is provided.
1678
1680 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1682
1683 return emitAnyExpr(e, aggSlot);
1684}
1685
1687 CallArgList &args, PrototypeWrapper prototype,
1688 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1689 AbstractCallee callee, unsigned paramsToSkip) {
1691
1693
1694 // First, if a prototype was provided, use those argument types.
1695 bool isVariadic = false;
1696 if (prototype.p) {
1698
1699 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1700 isVariadic = fpt->isVariadic();
1702 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1703 fpt->param_type_end());
1704 }
1705
1706 // If we still have any arguments, emit them using the type of the argument.
1707 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1708 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1709 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1710
1711 // We must evaluate arguments from right to left in the MS C++ ABI, because
1712 // arguments are destroyed left to right in the callee. As a special case,
1713 // there are certain language constructs taht require left-to-right
1714 // evaluation, and in those cases we consider the evaluation order requirement
1715 // to trump the "destruction order is reverse construction order" guarantee.
1716 auto leftToRight = true;
1717 assert(!cir::MissingFeatures::msabi());
1718
1719 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1720 RValue emittedArg) {
1721 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1722 return;
1723 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1724 if (!ps)
1725 return;
1726
1728 assert(emittedArg.getValue() && "We emitted nothing for the arg?");
1729 mlir::Value v = evaluateOrEmitBuiltinObjectSize(
1730 arg, ps->getType(), cast<cir::IntType>(cgm.sizeTy),
1731 emittedArg.getValue(), ps->isDynamic());
1732 args.add(RValue::get(v), sizeTy);
1733 // When emitting right-to-left, the size arg was appended after the
1734 // pointer arg; swap them so the size follows the pointer in the final
1735 // argument list after the outer reverse.
1736 if (!leftToRight)
1737 std::iter_swap(args.rbegin(), std::next(args.rbegin()));
1738 };
1739
1740 // Evaluate each argument in the appropriate order.
1741 size_t callArgsStart = args.size();
1742 for (size_t i = 0; i != argTypes.size(); ++i) {
1743 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1744 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1745 size_t initialArgSize = args.size();
1746
1747 emitCallArg(args, *currentArg, argTypes[idx]);
1748
1749 // In particular, we depend on it being the last arg in Args, and the
1750 // objectsize bits depend on there only being one arg if !LeftToRight.
1751 assert(initialArgSize + 1 == args.size() &&
1752 "The code below depends on only adding one arg per emitCallArg");
1753 (void)initialArgSize;
1754
1755 // Since pointer argument are never emitted as LValue, it is safe to emit
1756 // non-null argument check for r-value only.
1757 if (!args.back().hasLValue()) {
1758 RValue rvArg = args.back().getKnownRValue();
1760 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1761 }
1762
1763 if (!leftToRight)
1764 std::reverse(args.begin() + callArgsStart, args.end());
1765 }
1766}
1767
1768// FIXME(cir): This is identical to the version from classic-codegen, we should
1769// figure out how to move this to a common location.
1771 CXXCtorType type) {
1772 // Parameters are unnecessary if we're constructing a base class subobject
1773 // and the inherited constructor lives in a virtual base.
1774 return type == Ctor_Complete ||
1775 !inherited.getShadowDecl()->constructsVirtualBase() ||
1777}
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 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 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, cir::CallingConv callingConv)
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 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={}, cir::CallingConv callingConv=cir::CallingConv::C)
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::CallingConv callingConv=cir::CallingConv::C)
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:975
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
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.
static std::optional< cir::FramePointerKind > getFramePointerKind(CodeGenOptions::FramePointerKind kind)
Returns the frame pointer kind to record on functions and on the module, or std::nullopt when kind is...
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:173
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:2991
SourceLocation getBeginLoc() const
Definition Expr.h:3325
ConstExprIterator const_arg_iterator
Definition Expr.h:3239
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
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
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:3362
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 isInAnonymousNamespace() const
Definition DeclBase.cpp:443
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
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
Definition Decl.h:3056
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:3023
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4618
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4994
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5723
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5815
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4723
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4612
ExtInfo getExtInfo() const
Definition TypeBase.h:4968
QualType getReturnType() const
Definition TypeBase.h:4952
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:4435
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:3094
QualType getCanonicalType() const
Definition TypeBase.h:8498
LangAS getAddressSpace() const
Definition TypeBase.h:572
bool isParamDestroyedInCallee() const
Definition Decl.h:4614
Encodes a location in the source.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
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:9068
bool isPackedVectorBoolType(const ASTContext &ctx) const
Definition Type.cpp:542
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:845
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition Type.cpp:2645
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8707
bool isScalarType() const
Definition TypeBase.h:9178
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isBitIntType() const
Definition TypeBase.h:8958
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isMemberPointerType() const
Definition TypeBase.h:8764
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:2655
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition Type.cpp:2525
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:3002
bool isAnyPointerType() const
Definition TypeBase.h:8691
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
bool isNullPtrType() const
Definition TypeBase.h:9109
bool isRecordType() const
Definition TypeBase.h:8810
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:2826
Represents a GCC generic vector type.
Definition TypeBase.h:4273
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:155
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ SC_Static
Definition Specifiers.h:256
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