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