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 GlobalDecl targetGlobalDecl = calleeInfo.getCalleeDecl();
374 const Decl *targetDecl = targetGlobalDecl.getDecl();
375
376 // TODO(cir): OMP Assume Attributes should be here.
377
378 const NoBuiltinAttr *nba = nullptr;
379
380 // TODO(cir): Some work for arg memory effects can be done here, as it is in
381 // classic codegen.
382
383 if (targetDecl) {
384 if (targetDecl->hasAttr<NoThrowAttr>())
385 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
386 // TODO(cir): This is actually only possible if targetDecl isn't a
387 // declarator, which ObjCMethodDecl seems to be the only way to get this to
388 // happen. We're including it here for completeness, but we should add a
389 // test for this when we start generating ObjectiveC.
390 if (targetDecl->hasAttr<NoReturnAttr>())
391 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
392 if (targetDecl->hasAttr<ReturnsTwiceAttr>())
393 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
394 if (targetDecl->hasAttr<ColdAttr>())
395 addUnitAttr(cir::CIRDialect::getColdAttrName());
396 if (targetDecl->hasAttr<HotAttr>())
397 addUnitAttr(cir::CIRDialect::getHotAttrName());
398 if (targetDecl->hasAttr<NoDuplicateAttr>())
399 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
400 if (targetDecl->hasAttr<ConvergentAttr>())
401 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
402
403 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
405 getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
406
407 // A sane operator new returns a non-aliasing pointer.
408 if (attrOnCallSite && func->isReplaceableGlobalAllocationFunction() &&
409 codeGenOpts.AssumeSaneOperatorNew &&
410 func->getDeclName().isAnyOperatorNew()) {
411 retAttrs.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
412 mlir::UnitAttr::get(&getMLIRContext()));
413 }
414
416
417 const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
418 bool isVirtualCall = md && md->isVirtual();
419
420 // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
421 // virtual function. These attributes are not inherited by overloads.
422 if (!(attrOnCallSite && isVirtualCall)) {
423 if (func->isNoReturn())
424 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
425 nba = func->getAttr<NoBuiltinAttr>();
426 }
427 }
428
430
431 auto setMemoryEffects = [&](cir::MemoryEffectsAttr effects) {
432 attrs.set(cir::CIRDialect::getMemoryEffectsAttrName(), effects);
433 };
434
435 // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
436 if (targetDecl->hasAttr<ConstAttr>()) {
437 setMemoryEffects(cir::MemoryEffectsAttr::none(&getMLIRContext()));
438 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
439 // gcc specifies that 'const' functions have greater restrictions than
440 // 'pure' functions, so they also cannot have infinite loops.
441 addUnitAttr(cir::CIRDialect::getWillReturnAttrName());
442 } else if (targetDecl->hasAttr<PureAttr>()) {
443 setMemoryEffects(cir::MemoryEffectsAttr::readOnly(&getMLIRContext()));
444 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
445 // gcc specifies that 'pure' functions cannot have infinite loops.
446 addUnitAttr(cir::CIRDialect::getWillReturnAttrName());
447 } else if (targetDecl->hasAttr<NoAliasAttr>()) {
448 setMemoryEffects(
449 cir::MemoryEffectsAttr::inaccessibleOrArgMemOnly(&getMLIRContext()));
450 addUnitAttr(cir::CIRDialect::getNoUnwindAttrName());
451 }
452
453 // Both __attribute__((malloc)) and __declspec(restrict) are represented by
454 // RestrictAttr. Only forms without a deallocator imply a noalias return.
455 if (const auto *restrictAttr = targetDecl->getAttr<RestrictAttr>();
456 restrictAttr && restrictAttr->getDeallocator() == nullptr)
457 retAttrs.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
458 mlir::UnitAttr::get(&getMLIRContext()));
459
460 if (targetDecl->hasAttr<ReturnsNonNullAttr>() &&
461 !codeGenOpts.NullPointerIsValid)
462 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
463 mlir::UnitAttr::get(&getMLIRContext()));
464 if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
465 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
466 // TODO(cir): Implement 'NoCFCheck' attribute here. This requires
467 // fcf-protection mode.
468 if (targetDecl->hasAttr<LeafAttr>())
469 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
470 // TODO(cir): Implement 'BPFFastCall' attribute here. This requires C, and
471 // the BPF target.
472
473 if (auto *allocSizeAttr = targetDecl->getAttr<AllocSizeAttr>()) {
474 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
475
476 if (allocSizeAttr->getNumElemsParam().isValid()) {
477 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
478 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
479 builder.getDenseI32ArrayAttr(
480 {static_cast<int>(size), static_cast<int>(numElts)}));
481 } else {
482 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
483 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
484 }
485 }
486
487 // TODO(cir): Quite a few CUDA and OpenCL attributes are added here.
488
489 // -cl-uniform-work-group-size / -foffload-uniform-block: work groups are
490 // uniform (global work-size is a multiple of work-group size).
491 if (langOpts.OffloadUniformBlock)
492 addUnitAttr(cir::CIRDialect::getUniformWorkGroupSizeAttrName());
493
494 // TODO(cir): we should also do 'aarch64_pstate_sm_body' here.
495
496 if (auto *modularFormat = targetDecl->getAttr<ModularFormatAttr>()) {
497 FormatAttr *format = targetDecl->getAttr<FormatAttr>();
498 StringRef type = format->getType()->getName();
499 std::string formatIdx = std::to_string(format->getFormatIdx());
500 std::string firstArg = std::to_string(format->getFirstArg());
502 type, formatIdx, firstArg,
503 modularFormat->getModularImplFn()->getName(),
504 modularFormat->getImplName()};
505 llvm::append_range(args, modularFormat->aspects());
506 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
507 builder.getStringAttr(llvm::join(args, ",")));
508 }
509 }
510
512
513 bool hasOptNoneAttr = targetDecl && targetDecl->hasAttr<OptimizeNoneAttr>();
514 addDefaultFunctionAttributes(name, hasOptNoneAttr, attrOnCallSite, attrs);
515 if (targetDecl) {
516 // TODO(cir): There is another region of `if (targetDecl)` that handles
517 // removing some attributes that are necessary modifications of the
518 // default-function attrs. Including:
519 // NoSpeculativeLoadHardening
520 // SpeculativeLoadHardening
521 // NoSplitStack
522 // Non-lazy-bind
523 // 'sample-profile-suffix-elision-policy'.
524
525 if (targetDecl->hasAttr<ZeroCallUsedRegsAttr>()) {
526 // A function "__attribute__((...))" overrides the command-line flag.
527 auto kind =
528 targetDecl->getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
529 attrs.set(
530 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
531 mlir::StringAttr::get(
533 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(kind)));
534 }
535
536 if (targetDecl->hasAttr<NoConvergentAttr>())
537 attrs.erase(cir::CIRDialect::getConvergentAttrName());
538 }
539
540 // Collect non-call-site function IR attributes from declaration-specific
541 // information.
542 if (!attrOnCallSite) {
543 // These functions require the returns_twice attribute for correct
544 // codegen, but the attribute may not be added if -fno-builtin is
545 // specified. We explicitly add that attribute here.
546 static const llvm::StringSet<> returnsTwiceFn{
547 "_setjmpex", "setjmp", "_setjmp", "vfork",
548 "sigsetjmp", "__sigsetjmp", "savectx", "getcontext"};
549 if (returnsTwiceFn.contains(name))
550 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
551
552 llvm::StringMap<std::string> cpuAndFeatures;
553 if (getCPUAndFeaturesAttributes(targetGlobalDecl, cpuAndFeatures)) {
554 for (const auto &[key, val] : cpuAndFeatures)
555 attrs.set(key, builder.getStringAttr(val));
556 }
557 }
558
559 // TODO(cir): A bunch of non-call-site function IR attributes from
560 // declaration-specific information, including tail calls,
561 // cmse_nonsecure_entry, and hotpatch support.
562
563 // TODO(cir): Add loader-replaceable attribute here.
564
565 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
566 constructFunctionArgumentAttributes(info, targetGlobalDecl, isThunk,
567 attrOnCallSite, argAttrs);
568}
569
570bool CIRGenModule::hasStrictReturn(QualType retTy, const Decl *targetDecl) {
571 // As-is msan can not tolerate noundef mismatch between caller and
572 // implementation. Mismatch is possible for e.g. indirect calls from C-caller
573 // into C++. Such mismatches lead to confusing false reports. To avoid
574 // expensive workaround on msan we enforce initialization event in uncommon
575 // cases where it's allowed.
576 if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
577 return true;
578 // C++ explicitly makes returning undefined values UB. C's rule only applies
579 // to used values, so we never mark them noundef for now.
580 if (!getLangOpts().CPlusPlus)
581 return false;
582 if (targetDecl) {
583 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
584 if (func->isExternC())
585 return false;
586 } else if (const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
587 // Function pointer.
588 if (var->isExternC())
589 return false;
590 }
591 }
592
593 // We don't want to be too aggressive with the return checking, unless
594 // it's explicit in the code opts or we're using an appropriate sanitizer.
595 // Try to respect what the programmer intended.
596 return getCodeGenOpts().StrictReturn ||
597 !mayDropFunctionReturn(getASTContext(), retTy) ||
598 getLangOpts().Sanitize.has(SanitizerKind::Return);
599}
600
601bool CIRGenModule::mayDropFunctionReturn(const ASTContext &context,
602 QualType retTy) {
603 // We can't just discard the return value for a record type with a
604 // complex destructor or a non-trivially copyable type.
605 if (const RecordType *recTy =
606 retTy.getCanonicalType()->getAsCanonical<RecordType>()) {
607 if (const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
608 return record->hasTrivialDestructor();
609 }
610 return retTy.isTriviallyCopyableType(context);
611}
612
613static bool determineNoUndef(QualType clangTy, CIRGenTypes &types,
614 const cir::CIRDataLayout &layout,
615 const cir::ABIArgInfo &argInfo) {
616 mlir::Type ty = types.convertTypeForMem(clangTy);
618 if (argInfo.isIndirect() || argInfo.isIndirectAliased())
619 return true;
620 if (argInfo.isExtend() && !argInfo.isNoExt())
621 return true;
622
623 if (cir::isSized(ty) && !layout.typeSizeEqualsStoreSize(ty))
624 // TODO: This will result in a modest amount of values not marked noundef
625 // when they could be. We care about values that *invisibly* contain undef
626 // bits from the perspective of LLVM IR.
627 return false;
628
629 // Classic CodeGen stores a packed bool vector as an integer with one bit per
630 // element, at least a byte wide, so the check above drops noundef when that
631 // integer is not a whole number of bytes. The CIR vector type is sized to a
632 // power of two of at least a byte, which always passes that check, so test
633 // the storage integer's width directly.
634 if (clangTy->isPackedVectorBoolType(types.getASTContext()) &&
635 mlir::cast<cir::VectorType>(ty).getBoolStorageWidth() % 8)
636 return false;
637
639 // The coerced type is not known until CallConvLowering, which drops noundef
640 // when it is wider than the value's memory type, the check classic
641 // DetermineNoUndef makes at this point.
642 if (clangTy->isBitIntType())
643 return true;
644 if (clangTy->isReferenceType())
645 return true;
646 if (clangTy->isNullPtrType())
647 return false;
648 if (clangTy->isMemberPointerType())
649 // TODO: Some member pointers are `noundef`, but it depends on the ABI. For
650 // now, never mark them.
651 return false;
652 if (clangTy->isScalarType()) {
653 if (const ComplexType *Complex = dyn_cast<ComplexType>(clangTy))
654 return determineNoUndef(Complex->getElementType(), types, layout,
655 argInfo);
656 return true;
657 }
658 if (const VectorType *Vector = dyn_cast<VectorType>(clangTy))
659 return determineNoUndef(Vector->getElementType(), types, layout, argInfo);
660 if (const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
661 return determineNoUndef(Matrix->getElementType(), types, layout, argInfo);
662 if (const ArrayType *Array = dyn_cast<ArrayType>(clangTy))
663 return determineNoUndef(Array->getElementType(), types, layout, argInfo);
664
665 // TODO: Some structs may be `noundef`, in specific situations.
666 return false;
667}
668
669void CIRGenModule::constructFunctionReturnAttributes(
670 const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
671 mlir::NamedAttrList &retAttrs) {
672 // Collect attributes from arguments and return values.
673 QualType retTy = info.getReturnType();
674 const cir::ABIArgInfo retInfo = info.getReturnInfo();
675 const cir::CIRDataLayout &layout = getDataLayout();
676
677 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
678 !retTy->isVoidType() &&
679 determineNoUndef(retTy, getTypes(), layout, retInfo))
680 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
681 mlir::UnitAttr::get(&getMLIRContext()));
682
683 if (retTy->hasFloatingRepresentation())
684 if (llvm::FPClassTest mask =
686 retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
687 builder.getI64IntegerAttr(mask));
688
689 if (!isThunk) {
690 // TODO(cir): following comment taken from classic codegen, so if anything
691 // happens there, we should reflect it here.
692 // FIXME: fix this properly, https://reviews.llvm.org/D100388
693 if (const auto *refTy = retTy->getAs<ReferenceType>()) {
694 QualType pointeeTy = refTy->getPointeeType();
695 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
696 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
697 builder.getI64IntegerAttr(
698 getMinimumObjectSize(pointeeTy).getQuantity()));
699
700 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
701 !codeGenOpts.NullPointerIsValid)
702 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
703 mlir::UnitAttr::get(&getMLIRContext()));
704
705 if (pointeeTy->isObjectType())
706 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
707 builder.getI64IntegerAttr(
708 getNaturalPointeeTypeAlignment(retTy).getQuantity()));
709 }
710 }
711}
712
713void CIRGenModule::constructFunctionArgumentAttributes(
714 const CIRGenFunctionInfo &info, GlobalDecl calleeDecl, bool isThunk,
715 bool attrOnCallSite, llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
717 const Decl *targetDecl = calleeDecl.getDecl();
718 // TODO(cir): classic codegen does a lot of work here based on the ABIArgInfo
719 // to set things based on calling convention.
720
721 if (info.isInstanceMethod() && !isThunk) {
722 QualType thisPtrTy = info.arguments()[0];
723 // Member allocation functions are instance methods, but setting attributes
724 // on them is nonsensical and not correct. Make sure we skip that here.
725 if (!thisPtrTy->isVoidPointerType()) {
726 QualType thisTy = thisPtrTy->getPointeeType();
727
728 if (!codeGenOpts.NullPointerIsValid &&
729 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
730 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
731 builder.getI64IntegerAttr(
732 getMinimumObjectSize(thisTy).getQuantity()));
733 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
734 mlir::UnitAttr::get(&getMLIRContext()));
735 } else {
737
738 if (bytes != 0)
739 argAttrs[0].set(
740 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
741 builder.getI64IntegerAttr(bytes));
742 }
743
744 argAttrs[0].set(
745 mlir::LLVM::LLVMDialect::getAlignAttrName(),
746 builder.getI64IntegerAttr(
747 getNaturalPointeeTypeAlignment(thisPtrTy).getQuantity()));
748
749 // Do not annotate vector deleting destructors with dead_on_return as the
750 // this pointer in that case points to an array which we cannot
751 // statically know the size of. Also do not mark deleting destructors
752 // dead_on_return as then we might delete stores inside of a user-defined
753 // operator delete implementation if it gets inlined, which would be
754 // incorrect as the object's lifetime has already ended and the operator
755 // delete implementation is allowed to manipulate the underlying storage.
756 const auto *dd = dyn_cast_if_present<CXXDestructorDecl>(targetDecl);
757 if (dd && codeGenOpts.StrictLifetimes &&
759 calleeDecl.getDtorType() != CXXDtorType::Dtor_Deleting) {
760 const CXXRecordDecl *classDecl = dd->getParent();
761 uint64_t dataSize = astContext.getASTRecordLayout(classDecl)
762 .getDataSize()
763 .getQuantity();
764 // We cannot add dead_on_return if we have virtual base classes because
765 // they will generally still be live after the base object destructor.
766
767 if (classDecl->getNumVBases() == 0 && dataSize != 0)
768 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDeadOnReturnAttrName(),
769 builder.getI64IntegerAttr(dataSize));
770 }
771 }
772 }
773
774 // TODO(cir): the logic between 'this', return, and normal arguments hsould
775 // probably be merged at one point, however the logic is unfortunately mildly
776 // different between each in classic codegen, so trying to do anything like
777 // that seems risky at the moment. At one point we should evaluate if at least
778 // dereferenceable, nonnull, and align can be combined.
779 const cir::CIRDataLayout &layout = getDataLayout();
780 const auto *fd = dyn_cast_or_null<FunctionDecl>(targetDecl);
781
782 // Build a parallel array of ParmVarDecls aligned with argAttrs so we can
783 // access parameter-level attributes (e.g. restrict, nonnull) without manual
784 // index arithmetic in the loop.
785 SmallVector<const ParmVarDecl *> parmDecls;
786 parmDecls.reserve(argAttrs.size());
787 if (fd) {
788 if (info.isInstanceMethod())
789 parmDecls.push_back(nullptr);
790 parmDecls.insert(parmDecls.end(), fd->param_begin(), fd->param_end());
791 }
792 parmDecls.resize(argAttrs.size(), nullptr);
793
794 for (const auto &[argAttrList, argCanType, pvd] :
795 llvm::zip_equal(argAttrs, info.arguments(), parmDecls)) {
797 QualType argType = argCanType;
798 const cir::ABIArgInfo argInfo = cir::ABIArgInfo::getDirect();
799
800 if (codeGenOpts.EnableNoundefAttrs &&
801 determineNoUndef(argType, getTypes(), layout, argInfo))
802 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
803 mlir::UnitAttr::get(&getMLIRContext()));
804
806 // TODO(cir): there is plenty of other attributes here added due to ABI
807 // decisions. While these probably won't end up here, we note that the
808 // classic codegen does it here and perhaps we should pay attention to that.
809
810 if (const auto *refTy = argType->getAs<ReferenceType>()) {
811 QualType pointeeTy = refTy->getPointeeType();
812 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
813 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
814 builder.getI64IntegerAttr(
815 getMinimumObjectSize(pointeeTy).getQuantity()));
816 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
817 !codeGenOpts.NullPointerIsValid)
818 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
819 mlir::UnitAttr::get(&getMLIRContext()));
820 if (pointeeTy->isObjectType())
821 argAttrList.set(
822 mlir::LLVM::LLVMDialect::getAlignAttrName(),
823 builder.getI64IntegerAttr(
824 getNaturalPointeeTypeAlignment(argType).getQuantity()));
825 }
826
827 if (argType->hasFloatingRepresentation())
828 if (llvm::FPClassTest mask =
830 argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
831 builder.getI64IntegerAttr(mask));
832
833 // restrict -> noalias on definitions only (not call sites). Skip
834 // builtins: OGCG applies restrict->noalias in EmitFunctionProlog.
835 if (!attrOnCallSite && pvd && pvd->getType()->isPointerType() &&
836 pvd->getType().isRestrictQualified() && !fd->getBuiltinID())
837 argAttrList.set(mlir::LLVM::LLVMDialect::getNoAliasAttrName(),
838 mlir::UnitAttr::get(&getMLIRContext()));
839
840 // __attribute__((nonnull)) on pointer parameters. Checks both
841 // per-parameter and function-level nonnull attributes.
842 if (pvd && argType->isAnyPointerType() && !codeGenOpts.NullPointerIsValid) {
843 unsigned srcIdx = pvd->getFunctionScopeIndex();
844 if (pvd->hasAttr<NonNullAttr>() ||
845 (fd->getAttr<NonNullAttr>() &&
846 fd->getAttr<NonNullAttr>()->isNonNull(srcIdx)))
847 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
848 mlir::UnitAttr::get(&getMLIRContext()));
849 }
850 }
851}
852
853/// Adds the formal parameters in FPT to the given prefix. If any parameter in
854/// FPT has pass_object_size attrs, then we'll add parameters for those, too.
855/// TODO(cir): this should be shared with LLVM codegen
856static void appendParameterTypes(const CIRGenTypes &cgt,
859 // Fast path: don't touch param info if we don't need to.
860 if (!fpt->hasExtParameterInfos()) {
861 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
862 return;
863 }
864
865 // In the vast majority of cases, we'll have precisely fpt->getNumParams()
866 // parameters; the only thing that can change this is the presence of
867 // pass_object_size. So, we preallocate for the common case.
868 prefix.reserve(prefix.size() + fpt->getNumParams());
870 fpt->getExtParameterInfos();
871 assert(extInfos.size() == fpt->getNumParams());
872 for (auto [paramType, extInfo] : llvm::zip_equal(
873 llvm::make_range(fpt->param_type_begin(), fpt->param_type_end()),
874 extInfos)) {
875 prefix.push_back(paramType);
876 if (extInfo.hasPassObjectSize())
877 prefix.push_back(cgt.getASTContext().getCanonicalSizeType());
878 }
879}
880
881const CIRGenFunctionInfo &
883 auto *md = cast<CXXMethodDecl>(gd.getDecl());
884
886 argTypes.push_back(deriveThisType(md->getParent(), md));
887
888 bool passParams = true;
889
890 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
891 // A base class inheriting constructor doesn't get forwarded arguments
892 // needed to construct a virtual base (or base class thereof)
893 if (auto inherited = cd->getInheritedConstructor())
894 passParams = inheritingCtorHasParams(inherited, gd.getCtorType());
895 }
896
898
899 if (passParams)
900 appendParameterTypes(*this, argTypes, fpt);
901
902 // The structor signature may include implicit parameters.
903 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
904 theCXXABI.buildStructorSignature(gd, argTypes);
906
907 RequiredArgs required =
908 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
910
911 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
912 : theCXXABI.hasMostDerivedReturn(gd)
913 ? astContext.VoidPtrTy
914 : astContext.VoidTy;
915
916 assert(!theCXXABI.hasThisReturn(gd) &&
917 "Please send PR with a test and remove this");
918
921
922 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
923 fpt->getExtInfo(), required);
924}
925
926/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
927/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
928/// indicates that there is no meaningful 'this' type, and a null `md` can occur
929/// when calling a method pointer.
931 const CXXMethodDecl *md) {
932 CanQualType recTy;
933 if (rd) {
935 } else {
936 // This can happen with the MS ABI. It shouldn't need anything more than
937 // setting recTy to VoidTy here, but we're flagging it for now because we
938 // don't have the full handling implemented.
939 cgm.errorNYI("deriveThisType: no record decl");
940 recTy = getASTContext().VoidTy;
941 }
942
943 if (md)
944 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
945 recTy, md->getMethodQualifiers().getAddressSpace()));
946 return getASTContext().getPointerType(recTy);
947}
948
949/// Arrange the CIR function layout for a value of the given function type, on
950/// top of any implicit parameters already stored.
951static const CIRGenFunctionInfo &
952arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod,
956 RequiredArgs required =
959 appendParameterTypes(cgt, prefix, fpt);
960 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
961 return cgt.arrangeCIRFunctionInfo(resultType, instanceMethod, prefix,
962 fpt->getExtInfo(), required);
963}
964
966 const VarDecl *param,
967 SourceLocation loc) {
968 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
969 // We need to turn that into an r-value suitable for emitCall
970 Address local = getAddrOfLocalVar(param);
971
972 QualType type = param->getType();
973
974 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
975 // argument needs to be the original pointer.
976 if (type->isReferenceType()) {
977 args.add(
978 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
979 type);
980 } else if (getLangOpts().ObjCAutoRefCount) {
981 cgm.errorNYI(param->getSourceRange(),
982 "emitDelegateCallArg: ObjCAutoRefCount");
983 // For the most part, we just need to load the alloca, except that aggregate
984 // r-values are actually pointers to temporaries.
985 } else {
986 args.add(convertTempToRValue(local, type, loc), type);
987 }
988
989 // Deactivate the cleanup for the callee-destructed param that was pushed.
991 if (type->isRecordType() &&
992 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
993 param->needsDestruction(getContext())) {
994 cgm.errorNYI(param->getSourceRange(),
995 "emitDelegateCallArg: callee-destructed param");
996 }
997}
998
999static const CIRGenFunctionInfo &
1001 const CallArgList &args,
1002 const FunctionType *fnType) {
1003
1005
1006 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
1007 // A free function call has no extra prefix arguments. Note that
1008 // getFromProtoWithExtraSlots already accounts for the prototype's
1009 // pass_object_size parameters; adding them here too would double-count
1010 // them and make the signature claim more required arguments than `args`
1011 // actually holds.
1012 if (proto->isVariadic())
1013 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
1016 cgm.errorNYI("call to function without a prototype");
1017
1019 for (const CallArg &arg : args)
1020 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
1021
1023
1025 return cgt.arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false,
1026 argTypes, fnType->getExtInfo(), required);
1027}
1028
1029/// Arrange a call to a C++ method, passing the given arguments.
1030///
1031/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
1032/// parameter.
1033/// passProtoArgs indicates whether `args` has args for the parameters in the
1034/// given CXXConstructorDecl.
1036 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
1037 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
1038
1039 // FIXME: Kill copy.
1041 for (const auto &arg : args)
1042 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1043
1044 // +1 for implicit this, which should always be args[0]
1045 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
1046
1048 RequiredArgs required = passProtoArgs
1050 fpt, totalPrefixArgs + extraSuffixArgs)
1052
1053 GlobalDecl gd(d, ctorKind);
1054 if (theCXXABI.hasThisReturn(gd))
1055 cgm.errorNYI(d->getSourceRange(),
1056 "arrangeCXXConstructorCall: hasThisReturn");
1057 if (theCXXABI.hasMostDerivedReturn(gd))
1058 cgm.errorNYI(d->getSourceRange(),
1059 "arrangeCXXConstructorCall: hasMostDerivedReturn");
1060 CanQualType resultType = astContext.VoidTy;
1061
1064
1065 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
1066 fpt->getExtInfo(), required);
1067}
1068
1069/// Arrange a call to a C++ method, passing the given arguments.
1070///
1071/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
1072/// does not count `this`.
1074 const CallArgList &args, const FunctionProtoType *proto,
1075 RequiredArgs required, unsigned numPrefixArgs) {
1077 assert(numPrefixArgs + 1 <= args.size() &&
1078 "Emitting a call with less args than the required prefix?");
1079
1080 // FIXME: Kill copy.
1082 for (const CallArg &arg : args)
1083 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1084
1088 /*isInstanceMethod=*/true, argTypes, proto->getExtInfo(), required);
1089}
1090
1091const CIRGenFunctionInfo &
1093 const FunctionType *fnType) {
1094 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
1095}
1096
1097const CIRGenFunctionInfo &
1099 const CallArgList &args) {
1101 for (const CallArg &arg : args)
1102 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
1103
1104 CanQualType retType = resultType->getCanonicalTypeUnqualified();
1105 return arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false, argTypes,
1107}
1108
1109/// Set calling convention for CUDA/HIP kernel.
1111 CIRGenModule &cgm,
1112 const FunctionDecl *fd) {
1113 if (fd->hasAttr<CUDAGlobalAttr>()) {
1114 const FunctionType *ft = funcTy->getAs<FunctionType>();
1116 funcTy = ft->getCanonicalTypeUnqualified();
1117 }
1118}
1119
1120/// Arrange the argument and result information for a declaration or definition
1121/// of the given C++ non-static member function. The member function must be an
1122/// ordinary function, i.e. not a constructor or destructor.
1123const CIRGenFunctionInfo &
1125 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
1126 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
1127
1129 setCUDAKernelCallingConvention(funcTy, cgm, md);
1130 auto prototype = funcTy.getAs<FunctionProtoType>();
1131
1132 // Mirrors classic CodeGen's check at CGCall.cpp. C++23 explicit-object
1133 // member functions (P0847R7, `void f(this Self&&)`) do not receive an
1134 // implicit `this`; the explicit object parameter takes its place at the
1135 // AST level and appears as the first parameter of the FunctionProtoType.
1136 // Arrange them as free functions so we don't prepend a stale implicit
1137 // `this` to the parameter list, which would produce a CIRGenFunctionInfo
1138 // with one more argument than the matching cir.func type and trip the
1139 // assertion in setArgAttrs.
1141 // The abstract case is perfectly fine.
1142 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1143 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
1144 }
1145
1146 return arrangeFreeFunctionType(prototype);
1147}
1148
1149/// Arrange the argument and result information for a call to an unknown C++
1150/// non-static member function of the given abstract type. (A null RD means we
1151/// don't have any meaningful "this" argument type, so fall back to a generic
1152/// pointer type). The member fucntion must be an ordinary function, i.e. not a
1153/// constructor or destructor.
1154const CIRGenFunctionInfo &
1156 const FunctionProtoType *fpt,
1157 const CXXMethodDecl *md) {
1159
1160 // Add the 'this' pointer.
1161 argTypes.push_back(deriveThisType(rd, md));
1162
1164 return ::arrangeCIRFunctionInfo(
1165 *this, /*isInstanceMethod=*/true, argTypes,
1167}
1168
1169/// Arrange the argument and result information for the declaration or
1170/// definition of the given function.
1171const CIRGenFunctionInfo &
1173 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1174 if (md->isInstance())
1175 return arrangeCXXMethodDeclaration(md);
1176
1178
1179 assert(isa<FunctionType>(funcTy));
1180 setCUDAKernelCallingConvention(funcTy, cgm, fd);
1181
1182 // When declaring a function without a prototype, always use a non-variadic
1183 // type.
1184 if (CanQual<FunctionNoProtoType> noProto =
1185 funcTy.getAs<FunctionNoProtoType>()) {
1188 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1189 /*isInstanceMethod=*/false, {},
1190 noProto->getExtInfo(), RequiredArgs::All);
1191 }
1192
1194}
1195
1196RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1197 if (!hasLV)
1198 return rv;
1199 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1201 lv.isVolatile());
1202 isUsed = true;
1203 return RValue::getAggregate(copy.getAddress());
1204}
1205
1207 SourceLocation argLoc,
1208 AbstractCallee ac, unsigned paramNum) {
1209 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1210 sanOpts.has(SanitizerKind::NullabilityArg)))
1211 return;
1212 cgm.errorNYI("non-null arg check is NYI");
1213}
1214
1215static cir::CIRCallOpInterface emitCallLikeOp(
1216 CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy,
1217 mlir::Value indirectFuncVal, cir::FuncOp directFuncOp,
1218 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1219 const mlir::NamedAttrList &attrs,
1221 const mlir::NamedAttrList &retAttrs, cir::CallingConv callingConv) {
1222 CIRGenBuilderTy &builder = cgf.getBuilder();
1223
1225
1226 assert(builder.getInsertionBlock() && "expected valid basic block");
1227
1228 cir::CallOp op;
1229 if (indirectFuncTy) {
1230 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1231 cirCallArgs, attrs, argAttrs, retAttrs,
1232 callingConv);
1233 } else {
1234 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1235 argAttrs, retAttrs, callingConv);
1236 }
1237
1238 return op;
1239}
1240
1241const CIRGenFunctionInfo &
1245 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1246 fpt);
1247}
1248
1249const CIRGenFunctionInfo &
1251 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1253 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1254 fnpt->getExtInfo(), RequiredArgs(0));
1255}
1256
1258 const CIRGenCallee &callee,
1260 const CallArgList &args,
1261 cir::CIRCallOpInterface *callOp,
1262 bool isMustTail, SourceRange clangLoc) {
1263 QualType retTy = funcInfo.getReturnType();
1264 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1265 mlir::Location loc = getLoc(clangLoc);
1266
1267 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1268
1269 const Decl *targetDecl = callee.getAbstractInfo().getCalleeDecl().getDecl();
1270
1271 if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(targetDecl)) {
1272 // We can only guarantee that a function is called from the correct
1273 // context/function based on the appropriate target attributes,
1274 // so only check in the case where we have both always_inline and target
1275 // since otherwise we could be making a conditional call after a check for
1276 // the proper cpu features (and it won't cause code generation issues due to
1277 // function based code generation).
1278 if ((targetDecl->hasAttr<AlwaysInlineAttr>() &&
1279 (targetDecl->hasAttr<TargetAttr>() ||
1280 (curFuncDecl && curFuncDecl->hasAttr<TargetAttr>()))) ||
1281 (curFuncDecl && curFuncDecl->hasAttr<FlattenAttr>() &&
1282 (curFuncDecl->hasAttr<TargetAttr>() ||
1283 targetDecl->hasAttr<TargetAttr>())))
1284 checkTargetFeatures(clangLoc.getBegin(), fd);
1285 }
1286
1287 const FunctionDecl *callerDecl = dyn_cast_or_null<FunctionDecl>(curCodeDecl);
1288 const FunctionDecl *calleeDecl = dyn_cast_or_null<FunctionDecl>(targetDecl);
1289
1291
1292 // Translate all of the arguments as necessary to match the CIR lowering.
1293 for (auto [argNo, arg, canQualArgType] :
1294 llvm::enumerate(args, funcInfo.argTypes())) {
1295
1296 // Insert a padding argument to ensure proper alignment.
1298
1299 mlir::Type argType = convertType(canQualArgType);
1300 if (!mlir::isa<cir::RecordType>(argType) &&
1301 !mlir::isa<cir::ComplexType>(argType)) {
1302 mlir::Value v;
1303 if (arg.isAggregate())
1304 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1305 v = arg.getKnownRValue().getValue();
1306
1307 // We might have to widen integers, but we should never truncate.
1308 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1309 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1310
1311 // If we have a pointer argument and there's an address space mismatch,
1312 // insert an address_space cast to match the expected function signature.
1313 if (argType != v.getType()) {
1314 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1315 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1316 if (argPtrTy && vPtrTy &&
1317 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1318 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1319 v = performAddrSpaceCast(v, argPtrTy);
1320 }
1321 }
1322
1323 // If the argument doesn't match, perform a bitcast to coerce it. This
1324 // can happen due to trivial type mismatches.
1325 // TODO(cir): When getFunctionType is added, assert that this isn't
1326 // needed.
1328 cirCallArgs[argNo] = v;
1329 } else {
1330 Address src = Address::invalid();
1331 if (!arg.isAggregate()) {
1332 src = createMemTemp(arg.ty, loc, "coerce");
1333 arg.copyInto(*this, src, loc);
1334 } else {
1335 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1336 : arg.getKnownRValue().getAggregateAddress();
1337 }
1338
1339 // Fast-isel and the optimizer generally like scalar values better than
1340 // FCAs, so we flatten them if this is safe to do for this argument.
1341 mlir::Type srcTy = src.getElementType();
1342 // FIXME(cir): get proper location for each argument.
1343 mlir::Location argLoc = loc;
1344
1345 // If the source type is smaller than the destination type of the
1346 // coerce-to logic, copy the source value into a temp alloca the size
1347 // of the destination type to allow loading all of it. The bits past
1348 // the source value are left undef.
1349 // FIXME(cir): add data layout info and compare sizes instead of
1350 // matching the types.
1351 //
1352 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1353 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1354 // if (SrcSize < DstSize) {
1356 if (srcTy != argType) {
1357 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1358 } else {
1359 // FIXME(cir): this currently only runs when the types are exactly the
1360 // same, but should be when alloc sizes are the same, fix this as soon
1361 // as datalayout gets introduced.
1363 }
1364
1365 // assert(NumCIRArgs == STy.getMembers().size());
1366 // In LLVMGen: Still only pass the struct without any gaps but mark it
1367 // as such somehow.
1368 //
1369 // In CIRGen: Emit a load from the "whole" struct,
1370 // which shall be broken later by some lowering step into multiple
1371 // loads.
1373 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1374 }
1375 }
1376
1377 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1378 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1379
1381
1382 mlir::NamedAttrList attrs;
1383 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1384 mlir::NamedAttrList retAttrs;
1385 StringRef funcName;
1386 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1387 funcName = calleeFuncOp.getName();
1388
1390 cir::CallingConv callingConv;
1391 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1392 attrs, argAttrs, retAttrs, callingConv,
1393 /*attrOnCallSite=*/true, /*isThunk=*/false);
1394
1395 // TODO(cir): Classic CodeGen redirects calls to OpenCL kernels to a
1396 // non-kernel stub (__clang_ocl_kern_imp_*), since kernel calling conventions
1397 // do not permit calls.
1398 if (callingConv == cir::CallingConv::SpirKernel ||
1399 callingConv == cir::CallingConv::AMDGPUKernel ||
1400 callingConv == cir::CallingConv::PTXKernel)
1401 cgm.errorNYI(loc, "emitCall: call to kernel function");
1402
1403 auto resolvedFuncOpFromGlobal = [&](mlir::Operation *op) -> cir::FuncOp {
1404 if (auto fnOp = dyn_cast<cir::FuncOp>(op))
1405 return fnOp;
1406 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(op)) {
1407 // FIXME(cir): This peephole optimization avoids indirect calls for
1408 // builtins. This should be fixed in the builtin declaration instead by
1409 // not emitting an unecessary get_global in the first place. However,
1410 // this is also used for no-prototype functions.
1411 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1412 assert(globalOp && "undefined global function");
1413 return cast<cir::FuncOp>(globalOp);
1414 }
1415 return nullptr;
1416 };
1417
1418 cir::FuncType indirectFuncTy;
1419 mlir::Value indirectFuncVal;
1420 cir::FuncOp directFuncOp;
1421
1422 // If the callee resolves to a FuncOp whose stored signature differs from
1423 // this call site's expected signature, the CIR verifier would reject the
1424 // mismatched types. This happens, for example, when two declarations share a
1425 // mangled name via __asm__ renaming (glibc's __REDIRECT_NTH pattern) but
1426 // disagree about a struct argument type. If that happens, we demote the
1427 // direct call to an indirect call through a function-pointer bitcast typed
1428 // at the call site.
1429 if (cir::FuncOp candidate = resolvedFuncOpFromGlobal(calleePtr)) {
1430 if (candidate.getFunctionType() == cirFuncTy) {
1431 directFuncOp = candidate;
1432 } else {
1433 mlir::Value addr = cir::GetGlobalOp::create(
1434 builder, loc, cir::PointerType::get(candidate.getFunctionType()),
1435 candidate.getSymName());
1436 indirectFuncTy = cirFuncTy;
1437 indirectFuncVal =
1438 builder.createBitcast(addr, cir::PointerType::get(cirFuncTy));
1439 }
1440 } else {
1441 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1442 calleePtr->getResultTypes();
1443 [[maybe_unused]] auto funcPtrTy =
1444 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1445 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1446 "expected pointer to function");
1447
1448 indirectFuncTy = cirFuncTy;
1449 indirectFuncVal = calleePtr->getResult(0);
1450 }
1451
1455
1456 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1457 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1458
1459 mlir::Location callLoc = loc;
1460 cir::CIRCallOpInterface theCall = emitCallLikeOp(
1461 *this, loc, indirectFuncTy, indirectFuncVal, directFuncOp, cirCallArgs,
1462 isInvoke, attrs, argAttrs, retAttrs, callingConv);
1463
1464 if (callOp)
1465 *callOp = theCall;
1466
1467 // Add srcloc if we have [[gnu::error/warning]] or ShowInliningChain.
1468 if (calleeDecl) {
1469 bool needSrcLoc = calleeDecl->hasAttr<ErrorAttr>();
1470 if (!needSrcLoc && cgm.getCodeGenOpts().ShowInliningChain)
1471 needSrcLoc = calleeDecl->isInlined() ||
1472 calleeDecl->hasAttr<AlwaysInlineAttr>() ||
1473 calleeDecl->getStorageClass() == SC_Static ||
1474 calleeDecl->isInAnonymousNamespace();
1475 if (needSrcLoc)
1476 theCall->setAttr(
1477 cir::CIRDialect::getSrcLocAttrName(),
1478 builder.getI64IntegerAttr(clangLoc.getBegin().getRawEncoding()));
1479 }
1480
1481 // Sema/emitAttributedStmt (see
1482 // https://github.com/llvm/llvm-project/issues/214764) should one-day enforce
1483 // that only one of these is valid at a time. For now, we have the same 'bug'
1484 // as classic codegen where we can end up having BOTH of these.
1486 theCall.setInlineKind(cir::InlineKind::NoInline);
1488 !cgm.getTargetCIRGenInfo().wouldInliningViolateFunctionCallABI(
1489 callerDecl, calleeDecl))
1490 theCall.setInlineKind(cir::InlineKind::AlwaysInline);
1491
1492 if (isMustTail) {
1493 // PPC/MIPS have some diagnostics for classic-codegen, but we don't support
1494 // them yet.
1495 const llvm::Triple &triple = getTarget().getTriple();
1496 if (triple.isPPC() || triple.isMIPS()) {
1497 cgm.errorNYI(mustTailCall->getBeginLoc(),
1498 "musttail call target legality checks");
1499 return getUndefRValue(retTy);
1500 }
1501
1502 // This call replaces the frame that the handler enforcing the exception
1503 // specification belongs to, taking that handler with it.
1504 if (ehSpecTryOp) {
1505 if (!inEHSpecTerminateScope()) {
1506 // The filter of a dynamic specification has to run while an exception
1507 // is leaving the function, and the tail call skips over it.
1508 cgm.errorUnsupported(mustTailCall, "tail call skipping over cleanups");
1509 return getUndefRValue(retTy);
1510 }
1511
1512 // Losing a terminate handler is safe when the callee cannot throw,
1513 // because then the callee's own handler stands in for it.
1514 if (!cannotThrow) {
1515 cgm.getDiags().Report(mustTailCall->getBeginLoc(),
1516 diag::err_musttail_noexcept_mismatch);
1517 return getUndefRValue(retTy);
1518 }
1519 }
1520
1521 // Musttail is required to return immediately, so no cleanup can run
1522 // between the call and the return. Cleanups that the return makes
1523 // unnecessary are simply skipped. Anything else cannot be expressed.
1525 for (EHScopeStack::iterator it = ehStack.begin(),
1526 end = ehStack.find(prologueCleanupDepth);
1527 it != end; ++it) {
1528 auto *cleanupScope = dyn_cast<EHCleanupScope>(&*it);
1529 if (!cleanupScope ||
1530 !cleanupScope->getCleanup()->isRedundantBeforeReturn()) {
1531 cgm.errorUnsupported(mustTailCall, "tail call skipping over cleanups");
1532 return getUndefRValue(retTy);
1533 }
1534 }
1535
1536 theCall->setAttr(cir::CIRDialect::getMustTailAttrName(),
1537 builder.getUnitAttr());
1538
1539 if (isa<cir::VoidType>(convertType(retTy)))
1540 cir::ReturnOp::create(builder, loc);
1541 else
1542 cir::ReturnOp::create(builder, loc, theCall->getResult(0));
1543
1544 // Musttail must return immediately, so we just do that. All of the below
1545 // stuff is effectively UB if this is a musttail, so just do a return
1546 // immediately.
1547 builder.createBlock(builder.getBlock()->getParent());
1548 return getUndefRValue(retTy);
1549 }
1550
1552
1553 mlir::Type retCIRTy = convertType(retTy);
1554 if (isa<cir::VoidType>(retCIRTy))
1555 return getUndefRValue(retTy);
1556 switch (getEvaluationKind(retTy)) {
1557 case cir::TEK_Aggregate: {
1558 Address destPtr = returnValue.getValue();
1559
1560 if (!destPtr.isValid())
1561 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1562
1563 mlir::ResultRange results = theCall->getOpResults();
1564 assert(results.size() <= 1 && "multiple returns from a call");
1565
1566 SourceLocRAIIObject loc{*this, clangLoc};
1567 emitAggregateStore(results[0], destPtr);
1568 return RValue::getAggregate(destPtr);
1569 }
1570 case cir::TEK_Scalar: {
1571 mlir::ResultRange results = theCall->getOpResults();
1572 assert(results.size() == 1 && "unexpected number of returns");
1573
1574 // If the argument doesn't match, perform a bitcast to coerce it. This
1575 // can happen due to trivial type mismatches.
1576 if (results[0].getType() != retCIRTy)
1577 cgm.errorNYI(loc, "bitcast on function return value");
1578
1579 mlir::Region *region = builder.getBlock()->getParent();
1580 if (region != theCall->getParentRegion())
1581 cgm.errorNYI(loc, "function calls with cleanup");
1582
1583 return RValue::get(results[0]);
1584 }
1585 case cir::TEK_Complex: {
1586 mlir::ResultRange results = theCall->getOpResults();
1587 assert(!results.empty() &&
1588 "Expected at least one result for complex rvalue");
1589 return RValue::getComplex(results[0]);
1590 }
1591 }
1592 llvm_unreachable("Invalid evaluation kind");
1593}
1594
1596 mlir::Location loc) const {
1597 LValue dst = cgf.makeAddrLValue(addr, ty);
1598 if (!hasLV && rv.isScalar())
1599 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1600 else if (!hasLV && rv.isComplex())
1601 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1602 else
1603 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1604 isUsed = true;
1605}
1606
1607mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1608 cir::FuncOp callee,
1610 mlir::NamedAttrList attrs) {
1611
1612 // TODO(cir): set the calling convention to this runtime call.
1614
1615 cir::CallOp call = builder.createCallOp(loc, callee, args);
1616 assert(call->getNumResults() <= 1 &&
1617 "runtime functions have at most 1 result");
1618
1619 if (!attrs.empty())
1620 call->setAttrs(attrs);
1621
1622 if (call->getNumResults() == 0)
1623 return nullptr;
1624
1625 return call->getResult(0);
1626}
1627
1629 clang::QualType argType) {
1630 assert(argType->isReferenceType() == e->isGLValue() &&
1631 "reference binding to unmaterialized r-value!");
1632
1633 if (e->isGLValue()) {
1634 assert(e->getObjectKind() == OK_Ordinary);
1635 return args.add(emitReferenceBindingToExpr(e), argType);
1636 }
1637
1638 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1639
1640 // For callee-destructed parameters (trivial_abi, MS ABI), create an
1641 // aggregate temp and let the callee destroy it.
1642 if (argType->isRecordType() &&
1644 AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
1646
1647 bool destroyedInCallee = true;
1648 if (const auto *rd = argType->getAsCXXRecordDecl())
1649 destroyedInCallee = rd->hasNonTrivialDestructor();
1650
1651 if (destroyedInCallee)
1653
1654 emitAggExpr(e, slot);
1655 RValue rv = slot.asRValue();
1656 args.add(rv, argType);
1657
1658 if (destroyedInCallee && getLangOpts().Exceptions)
1659 cgm.errorNYI(e->getSourceRange(),
1660 "callee-destructed param with exceptions");
1661 return;
1662 }
1663
1664 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1665 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1666 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1667 assert(lv.isSimple());
1668 args.addUncopiedAggregate(lv, argType);
1669 return;
1670 }
1671
1672 args.add(emitAnyExprToTemp(e), argType);
1673}
1674
1675QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1676 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1677 // implicitly widens null pointer constants that are arguments to varargs
1678 // functions to pointer-sized ints.
1679 if (!getTarget().getTriple().isOSWindows())
1680 return arg->getType();
1681
1682 assert(!cir::MissingFeatures::msabi());
1683 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1684 return arg->getType();
1685}
1686
1687/// Similar to emitAnyExpr(), however, the result will always be accessible
1688/// even if no aggregate location is provided.
1691
1693 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1695
1696 return emitAnyExpr(e, aggSlot);
1697}
1698
1700 CallArgList &args, PrototypeWrapper prototype,
1701 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1702 AbstractCallee callee, unsigned paramsToSkip, EvaluationOrder order) {
1704
1706
1707 // First, if a prototype was provided, use those argument types.
1708 bool isVariadic = false;
1709 if (prototype.p) {
1711
1712 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1713 isVariadic = fpt->isVariadic();
1715 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1716 fpt->param_type_end());
1717 }
1718
1719 // If we still have any arguments, emit them using the type of the argument.
1720 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1721 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1722 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1723
1724 // We must evaluate arguments from right to left in the MS C++ ABI, because
1725 // arguments are destroyed left to right in the callee. As a special case,
1726 // there are certain language constructs that require left-to-right
1727 // evaluation, and in those cases we consider the evaluation order requirement
1728 // to trump the "destruction order is reverse construction order" guarantee.
1730 order, getTarget().getCXXABI());
1731
1732 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1733 RValue emittedArg) {
1734 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1735 return;
1736 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1737 if (!ps)
1738 return;
1739
1741 assert(emittedArg.getValue() && "We emitted nothing for the arg?");
1742 mlir::Value v = evaluateOrEmitBuiltinObjectSize(
1743 arg, ps->getType(), cast<cir::IntType>(cgm.sizeTy),
1744 emittedArg.getValue(), ps->isDynamic());
1745 args.add(RValue::get(v), sizeTy);
1746 // When emitting right-to-left, the size arg was appended after the
1747 // pointer arg; swap them so the size follows the pointer in the final
1748 // argument list after the outer reverse.
1749 if (!leftToRight)
1750 std::iter_swap(args.rbegin(), std::next(args.rbegin()));
1751 };
1752
1753 // Evaluate each argument in the appropriate order.
1754 size_t callArgsStart = args.size();
1755 for (size_t i = 0; i != argTypes.size(); ++i) {
1756 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1757 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1758 size_t initialArgSize = args.size();
1759
1760 emitCallArg(args, *currentArg, argTypes[idx]);
1761
1762 // In particular, we depend on it being the last arg in Args, and the
1763 // objectsize bits depend on there only being one arg if !LeftToRight.
1764 assert(initialArgSize + 1 == args.size() &&
1765 "The code below depends on only adding one arg per emitCallArg");
1766 (void)initialArgSize;
1767
1768 // Since pointer argument are never emitted as LValue, it is safe to emit
1769 // non-null argument check for r-value only.
1770 if (!args.back().hasLValue()) {
1771 RValue rvArg = args.back().getKnownRValue();
1773 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1774 }
1775 }
1776
1777 if (!leftToRight) {
1778 // Un-reverse the arguments we just evaluated so they match up with the
1779 // callee's parameter order.
1780 std::reverse(args.begin() + callArgsStart, args.end());
1782 }
1783}
1784
1785// FIXME(cir): This is identical to the version from classic-codegen, we should
1786// figure out how to move this to a common location.
1788 CXXCtorType type) {
1789 // Parameters are unnecessary if we're constructing a base class subobject
1790 // and the inherited constructor lives in a virtual base.
1791 return type == Ctor_Complete ||
1792 !inherited.getShadowDecl()->constructsVirtualBase() ||
1794}
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:971
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
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.
CodeGenUtils::EvaluationOrder EvaluationOrder
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0, EvaluationOrder order=EvaluationOrder::Default)
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.
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()
const cir::CIRDataLayout & getDataLayout() const
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 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
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:624
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:3012
SourceLocation getBeginLoc() const
Definition Expr.h:3346
ConstExprIterator const_arg_iterator
Definition Expr.h:3260
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:582
bool isInAnonymousNamespace() const
Definition DeclBase.cpp:443
bool hasAttr() const
Definition DeclBase.h:586
This represents one expression.
Definition Expr.h:114
bool isGLValue() const
Definition Expr.h:289
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:456
QualType getType() const
Definition Expr.h:146
Represents a function declaration or definition.
Definition Decl.h:2071
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
Definition Decl.h:3068
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:3035
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4634
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
CXXDtorType getDtorType() const
Definition GlobalDecl.h:122
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:3092
QualType getCanonicalType() const
Definition TypeBase.h:8498
LangAS getAddressSpace() const
Definition TypeBase.h:572
bool isParamDestroyedInCallee() const
Definition Decl.h:4626
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:725
Represents a variable declaration or definition.
Definition Decl.h:934
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2171
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2843
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:37
@ 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:15
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:21
bool shouldEvaluateArgsLeftToRight(EvaluationOrder Order, const TargetCXXABI &ABI)
Returns true if call arguments should be emitted left-to-right, given the order the language requires...
Definition CallUtils.cpp:55
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
@ Dtor_VectorDeleting
Vector deleting dtor.
Definition ABI.h:40
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
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