clang 23.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/Support/TypeSize.h"
24
25using namespace clang;
26using namespace clang::CIRGen;
27
28CIRGenFunctionInfo *CIRGenFunctionInfo::create(
31 // The first slot allocated for arg type slot is for the return value.
32 void *buffer = operator new(
33 totalSizeToAlloc<CanQualType>(argTypes.size() + 1));
34
36
37 CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
38
39 fi->noReturn = info.getNoReturn();
40 fi->instanceMethod = isInstanceMethod;
41
42 fi->required = required;
43 fi->numArgs = argTypes.size();
44
45 fi->getArgTypes()[0] = resultType;
46 std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());
48
49 return fi;
50}
51
56
58 mlir::Type resultType = convertType(info.getReturnType());
60 argTypes.reserve(info.getNumRequiredArgs());
61
62 for (const CanQualType &argType : info.requiredArguments())
63 argTypes.push_back(convertType(argType));
64
65 return cir::FuncType::get(argTypes,
66 (resultType ? resultType : builder.getVoidTy()),
67 info.isVariadic());
68}
69
71 if (isVirtual()) {
72 const CallExpr *ce = getVirtualCallExpr();
75 ce ? ce->getBeginLoc() : SourceLocation());
76 }
77 return *this;
78}
79
80void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
81 // In classic codegen:
82 // Function to store a first-class aggregate into memory. We prefer to
83 // store the elements rather than the aggregate to be more friendly to
84 // fast-isel.
85 // In CIR codegen:
86 // Emit the most simple cir.store possible (e.g. a store for a whole
87 // record), which can later be broken down in other CIR levels (or prior
88 // to dialect codegen).
89
90 // Stored result for the callers of this function expected to be in the same
91 // scope as the value, don't make assumptions about current insertion point.
92 mlir::OpBuilder::InsertionGuard guard(builder);
93 builder.setInsertionPointAfter(value.getDefiningOp());
94 builder.createStore(*currSrcLoc, value, dest);
95}
96
98 mlir::NamedAttrList &attrs,
99 const FunctionProtoType *fpt) {
100 if (!fpt)
101 return;
102
104 fpt->isNothrow())
105 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
106 mlir::UnitAttr::get(builder.getContext()));
107}
108
109static void addNoBuiltinAttributes(mlir::MLIRContext &ctx,
110 mlir::NamedAttrList &attrs,
111 const LangOptions &langOpts,
112 const NoBuiltinAttr *nba = nullptr) {
113 // First, handle the language options passed through -fno-builtin.
114 // or, if there is a wildcard in the builtin names specified through the
115 // attribute, disable them all.
116 if (langOpts.NoBuiltin ||
117 (nba && llvm::is_contained(nba->builtinNames(), "*"))) {
118 // -fno-builtin disables them all.
119 // Empty attribute means 'all'.
120 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
121 mlir::ArrayAttr::get(&ctx, {}));
122 return;
123 }
124
125 llvm::SetVector<mlir::Attribute> nbFuncs;
126 auto addNoBuiltinAttr = [&ctx, &nbFuncs](StringRef builtinName) {
127 nbFuncs.insert(mlir::StringAttr::get(&ctx, builtinName));
128 };
129
130 // Then, add attributes for builtins specified through -fno-builtin-<name>.
131 llvm::for_each(langOpts.NoBuiltinFuncs, addNoBuiltinAttr);
132
133 // Now, let's check the __attribute__((no_builtin("...")) attribute added to
134 // the source.
135 if (nba)
136 llvm::for_each(nba->builtinNames(), addNoBuiltinAttr);
137
138 if (!nbFuncs.empty())
139 attrs.set(cir::CIRDialect::getNoBuiltinsAttrName(),
140 mlir::ArrayAttr::get(&ctx, nbFuncs.getArrayRef()));
141}
142
143/// Add denormal-fp-math and denormal-fp-math-f32 as appropriate for the
144/// requested denormal behavior, accounting for the overriding behavior of the
145/// -f32 case.
146static void addDenormalModeAttrs(llvm::DenormalMode fpDenormalMode,
147 llvm::DenormalMode fp32DenormalMode,
148 mlir::NamedAttrList &attrs) {
149 // TODO(cir): Classic-codegen sets the denormal modes here. There are two
150 // values, both with a string, but it seems that perhaps we could combine
151 // these into a single attribute? It seems a little silly to have two so
152 // similar named attributes that do the same thing.
153}
154
155/// Add default attributes to a function, which have merge semantics under
156/// -mlink-builtin-bitcode and should not simply overwrite any existing
157/// attributes in the linked library.
158static void
160 mlir::NamedAttrList &attrs) {
162 attrs);
163}
164
165static llvm::StringLiteral
166getZeroCallUsedRegsKindStr(llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind k) {
167 switch (k) {
168 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip:
169 llvm_unreachable("No string value, shouldn't be able to get here");
170 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg:
171 return "used-gpr-arg";
172 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR:
173 return "used-gpr";
174 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg:
175 return "used-arg";
176 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used:
177 return "used";
178 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg:
179 return "all-gpr-arg";
180 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR:
181 return "all-gpr";
182 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg:
183 return "all-arg";
184 case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All:
185 return "all";
186 }
187
188 llvm_unreachable("Unknown kind?");
189}
190
191/// Add default attributes to a function, which have merge semantics under
192/// -mlink-builtin-bitcode and should not simply overwrite any existing
193/// attributes in the linked library.
195 mlir::MLIRContext *mlirCtx, StringRef name, bool hasOptNoneAttr,
196 const CodeGenOptions &codeGenOpts, const LangOptions &langOpts,
197 bool attrOnCallSite, mlir::NamedAttrList &attrs) {
198 // TODO(cir): Handle optimize attribute flag here.
199 // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
200 if (!hasOptNoneAttr) {
201 if (codeGenOpts.OptimizeSize)
202 attrs.set(cir::CIRDialect::getOptimizeForSizeAttrName(),
203 mlir::UnitAttr::get(mlirCtx));
204 if (codeGenOpts.OptimizeSize == 2)
205 attrs.set(cir::CIRDialect::getMinSizeAttrName(),
206 mlir::UnitAttr::get(mlirCtx));
207 }
208
209 // TODO(cir): Classic codegen adds 'DisableRedZone', 'indirect-tls-seg-refs'
210 // and 'NoImplicitFloat' here.
211
212 if (attrOnCallSite) {
213 // Add the 'nobuiltin' tag, which is different from 'no-builtins'.
214 if (!codeGenOpts.SimplifyLibCalls || langOpts.isNoBuiltinFunc(name))
215 attrs.set(cir::CIRDialect::getNoBuiltinAttrName(),
216 mlir::UnitAttr::get(mlirCtx));
217
218 if (!codeGenOpts.TrapFuncName.empty())
219 attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
220 mlir::StringAttr::get(mlirCtx, codeGenOpts.TrapFuncName));
221 } else {
222 // TODO(cir): Set frame pointer attribute here.
223 // TODO(cir): a number of other attribute 1-offs based on codegen/lang opts
224 // should be done here: less-recise-fpmad null-pointer-is-valid
225 // no-trapping-math
226 // various inf/nan/nsz/etc work here.
227 //
228 // TODO(cir): set stack-protector buffer size attribute (sorted oddly in
229 // classic compiler inside of the above region, but should be done on its
230 // own).
231 // TODO(cir): other attributes here:
232 // reciprocal estimates, prefer-vector-width, stackrealign, backchain,
233 // split-stack, speculative-load-hardening.
234
235 if (codeGenOpts.getZeroCallUsedRegs() ==
236 llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip)
237 attrs.erase(cir::CIRDialect::getZeroCallUsedRegsAttrName());
238 else
239 attrs.set(cir::CIRDialect::getZeroCallUsedRegsAttrName(),
240 mlir::StringAttr::get(mlirCtx,
242 codeGenOpts.getZeroCallUsedRegs())));
243 }
244
245 if (langOpts.assumeFunctionsAreConvergent()) {
246 // Conservatively, mark all functions and calls in CUDA and OpenCL as
247 // convergent (meaning, they may call an intrinsically convergent op, such
248 // as __syncthreads() / barrier(), and so can't have certain optimizations
249 // applied around them). LLVM will remove this attribute where it safely
250 // can.
251 attrs.set(cir::CIRDialect::getConvergentAttrName(),
252 mlir::UnitAttr::get(mlirCtx));
253 }
254
255 // TODO(cir): Classic codegen adds 'nounwind' here in a bunch of offload
256 // targets.
257
258 if (codeGenOpts.SaveRegParams && !attrOnCallSite)
259 attrs.set(cir::CIRDialect::getSaveRegParamsAttrName(),
260 mlir::UnitAttr::get(mlirCtx));
261
262 // These come in the form of an optional equality sign, so make sure we pass
263 // these on correctly. These will eventually just be passed through to
264 // LLVM-IR, but we want to put them all in 1 array to simplify the
265 // LLVM-MLIR dialect.
266 SmallVector<mlir::NamedAttribute> defaultFuncAttrs;
267 llvm::transform(
268 codeGenOpts.DefaultFunctionAttrs, std::back_inserter(defaultFuncAttrs),
269 [mlirCtx](llvm::StringRef arg) {
270 auto [var, value] = arg.split('=');
271 auto valueAttr =
272 value.empty()
273 ? cast<mlir::Attribute>(mlir::UnitAttr::get(mlirCtx))
274 : cast<mlir::Attribute>(mlir::StringAttr::get(mlirCtx, value));
275 return mlir::NamedAttribute(var, valueAttr);
276 });
277
278 if (!defaultFuncAttrs.empty())
279 attrs.set(cir::CIRDialect::getDefaultFuncAttrsAttrName(),
280 mlir::DictionaryAttr::get(mlirCtx, defaultFuncAttrs));
281
282 // TODO(cir): Do branch protection attributes here.
283}
284
285/// This function matches the behavior of 'getDefaultFunctionAttributes' from
286/// classic codegen, despite the similarity of its name to
287/// 'addDefaultFunctionDefinitionAttributes', which is a caller of this
288/// function.
290 bool hasOptNoneAttr,
291 bool attrOnCallSite,
292 mlir::NamedAttrList &attrs) {
293
295 codeGenOpts, langOpts, attrOnCallSite,
296 attrs);
297
298 if (!attrOnCallSite) {
299 // TODO(cir): Classic codegen adds pointer-auth attributes here, by calling
300 // into TargetCodeGenInfo. At the moment, we've not looked into this as it
301 // is somewhat less used.
302 addMergeableDefaultFunctionAttributes(codeGenOpts, attrs);
303 }
304}
305
306/// Construct the CIR attribute list of a function or call.
308 llvm::StringRef name, const CIRGenFunctionInfo &info,
309 CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs,
311 mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv,
312 cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk) {
314 sideEffect = cir::SideEffect::All;
315
316 auto addUnitAttr = [&](llvm::StringRef name) {
317 attrs.set(name, mlir::UnitAttr::get(&getMLIRContext()));
318 };
319
320 if (info.isNoReturn())
321 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
322
323 // TODO(cir): Implement/check the CSME Nonsecure call attribute here. This
324 // requires being in CSME mode.
325
327 calleeInfo.getCalleeFunctionProtoType());
328
329 const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
330
331 // TODO(cir): OMP Assume Attributes should be here.
332
333 const NoBuiltinAttr *nba = nullptr;
334
335 // TODO(cir): Some work for arg memory effects can be done here, as it is in
336 // classic codegen.
337
338 if (targetDecl) {
339 if (targetDecl->hasAttr<NoThrowAttr>())
340 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
341 // TODO(cir): This is actually only possible if targetDecl isn't a
342 // declarator, which ObjCMethodDecl seems to be the only way to get this to
343 // happen. We're including it here for completeness, but we should add a
344 // test for this when we start generating ObjectiveC.
345 if (targetDecl->hasAttr<NoReturnAttr>())
346 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
347 if (targetDecl->hasAttr<ReturnsTwiceAttr>())
348 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
349 if (targetDecl->hasAttr<ColdAttr>())
350 addUnitAttr(cir::CIRDialect::getColdAttrName());
351 if (targetDecl->hasAttr<HotAttr>())
352 addUnitAttr(cir::CIRDialect::getHotAttrName());
353 if (targetDecl->hasAttr<NoDuplicateAttr>())
354 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
355 if (targetDecl->hasAttr<ConvergentAttr>())
356 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
357
358 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
360 getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
361
362 // TODO(cir): When doing 'return attrs' we need to cover the 'NoAlias' for
363 // global allocation functions here.
365
366 const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
367 bool isVirtualCall = md && md->isVirtual();
368
369 // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
370 // virtual function. These attributes are not inherited by overloads.
371 if (!(attrOnCallSite && isVirtualCall)) {
372 if (func->isNoReturn())
373 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
374 nba = func->getAttr<NoBuiltinAttr>();
375 }
376 }
377
379
380 // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
381 if (targetDecl->hasAttr<ConstAttr>()) {
382 // gcc specifies that 'const' functions have greater restrictions than
383 // 'pure' functions, so they also cannot have infinite loops.
384 sideEffect = cir::SideEffect::Const;
385 } else if (targetDecl->hasAttr<PureAttr>()) {
386 // gcc specifies that 'pure' functions cannot have infinite loops.
387 sideEffect = cir::SideEffect::Pure;
388 }
389
390 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
391 cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
392
393 // TODO(cir): When doing 'return attrs' we need to cover the Restrict and
394 // ReturnsNonNull attributes here.
395 if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
396 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
397 // TODO(cir): Implement 'NoCFCheck' attribute here. This requires
398 // fcf-protection mode.
399 if (targetDecl->hasAttr<LeafAttr>())
400 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
401 // TODO(cir): Implement 'BPFFastCall' attribute here. This requires C, and
402 // the BPF target.
403
404 if (auto *allocSizeAttr = targetDecl->getAttr<AllocSizeAttr>()) {
405 unsigned size = allocSizeAttr->getElemSizeParam().getLLVMIndex();
406
407 if (allocSizeAttr->getNumElemsParam().isValid()) {
408 unsigned numElts = allocSizeAttr->getNumElemsParam().getLLVMIndex();
409 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
410 builder.getDenseI32ArrayAttr(
411 {static_cast<int>(size), static_cast<int>(numElts)}));
412 } else {
413 attrs.set(cir::CIRDialect::getAllocSizeAttrName(),
414 builder.getDenseI32ArrayAttr({static_cast<int>(size)}));
415 }
416 }
417
418 // TODO(cir): Quite a few CUDA and OpenCL attributes are added here, like
419 // uniform-work-group-size.
420
421 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
422 targetDecl->hasAttr<CUDAGlobalAttr>()) {
423 GlobalDecl kernel(calleeInfo.getCalleeDecl());
424 llvm::StringRef kernelName = getMangledName(
426 auto attr = cir::CUDAKernelNameAttr::get(
428 mlir::StringAttr::get(&getMLIRContext(), kernelName));
429 attrs.set(attr.getMnemonic(), attr);
430 }
431
432 // TODO(cir): we should also do 'aarch64_pstate_sm_body' here.
433
434 if (auto *modularFormat = targetDecl->getAttr<ModularFormatAttr>()) {
435 FormatAttr *format = targetDecl->getAttr<FormatAttr>();
436 StringRef type = format->getType()->getName();
437 std::string formatIdx = std::to_string(format->getFormatIdx());
438 std::string firstArg = std::to_string(format->getFirstArg());
440 type, formatIdx, firstArg,
441 modularFormat->getModularImplFn()->getName(),
442 modularFormat->getImplName()};
443 llvm::append_range(args, modularFormat->aspects());
444 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
445 builder.getStringAttr(llvm::join(args, ",")));
446 }
447 }
448
450
451 bool hasOptNoneAttr = targetDecl && targetDecl->hasAttr<OptimizeNoneAttr>();
452 addDefaultFunctionAttributes(name, hasOptNoneAttr, attrOnCallSite, attrs);
453 if (targetDecl) {
454 // TODO(cir): There is another region of `if (targetDecl)` that handles
455 // removing some attributes that are necessary modifications of the
456 // default-function attrs. Including:
457 // NoSpeculativeLoadHardening
458 // SpeculativeLoadHardening
459 // NoSplitStack
460 // Non-lazy-bind
461 // 'sample-profile-suffix-elision-policy'.
462
463 if (targetDecl->hasAttr<ZeroCallUsedRegsAttr>()) {
464 // A function "__attribute__((...))" overrides the command-line flag.
465 auto kind =
466 targetDecl->getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
467 attrs.set(
468 cir::CIRDialect::getZeroCallUsedRegsAttrName(),
469 mlir::StringAttr::get(
471 ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(kind)));
472 }
473
474 if (targetDecl->hasAttr<NoConvergentAttr>())
475 attrs.erase(cir::CIRDialect::getConvergentAttrName());
476 }
477
478 // TODO(cir): A bunch of non-call-site function IR attributes from
479 // declaration-specific information, including tail calls,
480 // cmse_nonsecure_entry, additional/automatic 'returns-twice' functions,
481 // CPU-features/overrides, and hotpatch support.
482
483 // TODO(cir): Add loader-replaceable attribute here.
484
485 constructFunctionReturnAttributes(info, targetDecl, isThunk, retAttrs);
486 constructFunctionArgumentAttributes(info, isThunk, argAttrs);
487}
488
489bool CIRGenModule::hasStrictReturn(QualType retTy, const Decl *targetDecl) {
490 // As-is msan can not tolerate noundef mismatch between caller and
491 // implementation. Mismatch is possible for e.g. indirect calls from C-caller
492 // into C++. Such mismatches lead to confusing false reports. To avoid
493 // expensive workaround on msan we enforce initialization event in uncommon
494 // cases where it's allowed.
495 if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
496 return true;
497 // C++ explicitly makes returning undefined values UB. C's rule only applies
498 // to used values, so we never mark them noundef for now.
499 if (!getLangOpts().CPlusPlus)
500 return false;
501 if (targetDecl) {
502 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
503 if (func->isExternC())
504 return false;
505 } else if (const VarDecl *var = dyn_cast<VarDecl>(targetDecl)) {
506 // Function pointer.
507 if (var->isExternC())
508 return false;
509 }
510 }
511
512 // We don't want to be too aggressive with the return checking, unless
513 // it's explicit in the code opts or we're using an appropriate sanitizer.
514 // Try to respect what the programmer intended.
515 return getCodeGenOpts().StrictReturn ||
516 !mayDropFunctionReturn(getASTContext(), retTy) ||
517 getLangOpts().Sanitize.has(SanitizerKind::Return);
518}
519
520bool CIRGenModule::mayDropFunctionReturn(const ASTContext &context,
521 QualType retTy) {
522 // We can't just discard the return value for a record type with a
523 // complex destructor or a non-trivially copyable type.
524 if (const RecordType *recTy =
525 retTy.getCanonicalType()->getAsCanonical<RecordType>()) {
526 if (const auto *record = dyn_cast<CXXRecordDecl>(recTy->getDecl()))
527 return record->hasTrivialDestructor();
528 }
529 return retTy.isTriviallyCopyableType(context);
530}
531
532static bool determineNoUndef(QualType clangTy, CIRGenTypes &types,
533 const cir::CIRDataLayout &layout,
534 const cir::ABIArgInfo &argInfo) {
535 mlir::Type ty = types.convertTypeForMem(clangTy);
537 if (argInfo.isIndirect() || argInfo.isIndirectAliased())
538 return true;
539 if (argInfo.isExtend() && !argInfo.isNoExt())
540 return true;
541
542 if (cir::isSized(ty) && !layout.typeSizeEqualsStoreSize(ty))
543 // TODO: This will result in a modest amount of values not marked noundef
544 // when they could be. We care about values that *invisibly* contain undef
545 // bits from the perspective of LLVM IR.
546 return false;
547
549 // TODO(cir): The calling convention code needs to figure if the
550 // coerced-to-type is larger than the actual type, and remove the noundef
551 // attribute. Classic compiler did it here.
552 if (clangTy->isBitIntType())
553 return true;
554 if (clangTy->isReferenceType())
555 return true;
556 if (clangTy->isNullPtrType())
557 return false;
558 if (clangTy->isMemberPointerType())
559 // TODO: Some member pointers are `noundef`, but it depends on the ABI. For
560 // now, never mark them.
561 return false;
562 if (clangTy->isScalarType()) {
563 if (const ComplexType *Complex = dyn_cast<ComplexType>(clangTy))
564 return determineNoUndef(Complex->getElementType(), types, layout,
565 argInfo);
566 return true;
567 }
568 if (const VectorType *Vector = dyn_cast<VectorType>(clangTy))
569 return determineNoUndef(Vector->getElementType(), types, layout, argInfo);
570 if (const MatrixType *Matrix = dyn_cast<MatrixType>(clangTy))
571 return determineNoUndef(Matrix->getElementType(), types, layout, argInfo);
572 if (const ArrayType *Array = dyn_cast<ArrayType>(clangTy))
573 return determineNoUndef(Array->getElementType(), types, layout, argInfo);
574
575 // TODO: Some structs may be `noundef`, in specific situations.
576 return false;
577}
578
579/// Compute the nofpclass mask for FP types based on language options.
580static unsigned getNoFPClassTestMask(const LangOptions &langOpts) {
581 unsigned mask = 0;
582 if (langOpts.NoHonorInfs)
583 mask |= llvm::fcInf;
584 if (langOpts.NoHonorNaNs)
585 mask |= llvm::fcNan;
586 return mask;
587}
588
589void CIRGenModule::constructFunctionReturnAttributes(
590 const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
591 mlir::NamedAttrList &retAttrs) {
592 // Collect attributes from arguments and return values.
593 QualType retTy = info.getReturnType();
594 const cir::ABIArgInfo retInfo = info.getReturnInfo();
595 const cir::CIRDataLayout &layout = getDataLayout();
596
597 if (codeGenOpts.EnableNoundefAttrs && hasStrictReturn(retTy, targetDecl) &&
598 !retTy->isVoidType() &&
599 determineNoUndef(retTy, getTypes(), layout, retInfo))
600 retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
601 mlir::UnitAttr::get(&getMLIRContext()));
602
603 if (retTy->hasFloatingRepresentation())
604 if (unsigned mask = getNoFPClassTestMask(getLangOpts()))
605 retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
606 builder.getI64IntegerAttr(mask));
607
608 if (!isThunk) {
609 // TODO(cir): following comment taken from classic codegen, so if anything
610 // happens there, we should reflect it here.
611 // FIXME: fix this properly, https://reviews.llvm.org/D100388
612 if (const auto *refTy = retTy->getAs<ReferenceType>()) {
613 QualType pointeeTy = refTy->getPointeeType();
614 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
615 retAttrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
616 builder.getI64IntegerAttr(
617 getMinimumObjectSize(pointeeTy).getQuantity()));
618
619 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
620 !codeGenOpts.NullPointerIsValid)
621 retAttrs.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
622 mlir::UnitAttr::get(&getMLIRContext()));
623
624 if (pointeeTy->isObjectType())
625 retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
626 builder.getI64IntegerAttr(
627 getNaturalPointeeTypeAlignment(retTy).getQuantity()));
628 }
629 }
630}
631
632void CIRGenModule::constructFunctionArgumentAttributes(
633 const CIRGenFunctionInfo &info, bool isThunk,
634 llvm::MutableArrayRef<mlir::NamedAttrList> argAttrs) {
636 // TODO(cir): classic codegen does a lot of work here based on the ABIArgInfo
637 // to set things based on calling convention.
638 // At the moment, only nonnull, dereferenceable, align, and noundef are being
639 // implemented here, using similar logic to how we do so for return types.
640
641 if (info.isInstanceMethod() && !isThunk) {
642 QualType thisPtrTy = info.arguments()[0];
643 // Member allocation functions are instance methods, but setting attributes
644 // on them is nonsensical and not correct. Make sure we skip that here.
645 if (!thisPtrTy->isVoidPointerType()) {
646 QualType thisTy = thisPtrTy->getPointeeType();
647
648 if (!codeGenOpts.NullPointerIsValid &&
649 getTypes().getTargetAddressSpace(thisPtrTy) == 0) {
650 argAttrs[0].set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
651 builder.getI64IntegerAttr(
652 getMinimumObjectSize(thisTy).getQuantity()));
653 argAttrs[0].set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
654 mlir::UnitAttr::get(&getMLIRContext()));
655 } else {
657
658 if (bytes != 0)
659 argAttrs[0].set(
660 mlir::LLVM::LLVMDialect::getDereferenceableOrNullAttrName(),
661 builder.getI64IntegerAttr(bytes));
662 }
663
664 argAttrs[0].set(
665 mlir::LLVM::LLVMDialect::getAlignAttrName(),
666 builder.getI64IntegerAttr(
667 getNaturalPointeeTypeAlignment(thisPtrTy).getQuantity()));
668
669 // TODO(cir): the classic codegen has a recently-added bunch of logic for
670 // 'dead_on_return' as an attribute. This both doesn't exist in the LLVM
671 // dialect, and is 'too new' at the time of writing this to be considered
672 // stable enough here. For now, we'll leave this as a TODO so that when
673 // we come back, it is hopefully a more stabilized implementation.
674 }
675 }
676
677 // TODO(cir): the logic between 'this', return, and normal arguments hsould
678 // probably be merged at one point, however the logic is unfortunately mildly
679 // different between each in classic codegen, so trying to do anything like
680 // that seems risky at the moment. At one point we should evaluate if at least
681 // dereferenceable, nonnull, and align can be combined.
682 const cir::CIRDataLayout &layout = getDataLayout();
683 for (const auto &[argAttrList, argCanType] :
684 llvm::zip_equal(argAttrs, info.arguments())) {
686 QualType argType = argCanType;
687 const cir::ABIArgInfo argInfo = cir::ABIArgInfo::getDirect();
688
689 if (codeGenOpts.EnableNoundefAttrs &&
690 determineNoUndef(argType, getTypes(), layout, argInfo))
691 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
692 mlir::UnitAttr::get(&getMLIRContext()));
693
695 // TODO(cir): there is plenty of other attributes here added due to ABI
696 // decisions. While these probably won't end up here, we note that the
697 // classic codegen does it here and perhaps we should pay attention to that.
698
699 if (const auto *refTy = argType->getAs<ReferenceType>()) {
700 QualType pointeeTy = refTy->getPointeeType();
701 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
702 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
703 builder.getI64IntegerAttr(
704 getMinimumObjectSize(pointeeTy).getQuantity()));
705 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
706 !codeGenOpts.NullPointerIsValid)
707 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
708 mlir::UnitAttr::get(&getMLIRContext()));
709 if (pointeeTy->isObjectType())
710 argAttrList.set(
711 mlir::LLVM::LLVMDialect::getAlignAttrName(),
712 builder.getI64IntegerAttr(
713 getNaturalPointeeTypeAlignment(argType).getQuantity()));
714 }
715
716 if (argType->hasFloatingRepresentation())
717 if (unsigned mask = getNoFPClassTestMask(getLangOpts()))
718 argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
719 builder.getI64IntegerAttr(mask));
720 }
721}
722
723/// Returns the canonical formal type of the given C++ method.
729
730/// Adds the formal parameters in FPT to the given prefix. If any parameter in
731/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
732/// TODO(cir): this should be shared with LLVM codegen
733static void appendParameterTypes(const CIRGenTypes &cgt,
737 // Fast path: don't touch param info if we don't need to.
738 if (!fpt->hasExtParameterInfos()) {
739 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
740 return;
741 }
742
743 cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
744}
745
746const CIRGenFunctionInfo &
748 auto *md = cast<CXXMethodDecl>(gd.getDecl());
749
751 argTypes.push_back(deriveThisType(md->getParent(), md));
752
753 bool passParams = true;
754
755 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
756 // A base class inheriting constructor doesn't get forwarded arguments
757 // needed to construct a virtual base (or base class thereof)
758 if (auto inherited = cd->getInheritedConstructor())
759 passParams = inheritingCtorHasParams(inherited, gd.getCtorType());
760 }
761
763
764 if (passParams)
765 appendParameterTypes(*this, argTypes, fpt);
766
767 // The structor signature may include implicit parameters.
768 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
769 theCXXABI.buildStructorSignature(gd, argTypes);
771
772 RequiredArgs required =
773 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
775
776 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
777 : theCXXABI.hasMostDerivedReturn(gd)
778 ? astContext.VoidPtrTy
779 : astContext.VoidTy;
780
781 assert(!theCXXABI.hasThisReturn(gd) &&
782 "Please send PR with a test and remove this");
783
786
787 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
788 fpt->getExtInfo(), required);
789}
790
791/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
792/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
793/// indicates that there is no meaningful 'this' type, and a null `md` can occur
794/// when calling a method pointer.
796 const CXXMethodDecl *md) {
797 CanQualType recTy;
798 if (rd) {
800 } else {
801 // This can happen with the MS ABI. It shouldn't need anything more than
802 // setting recTy to VoidTy here, but we're flagging it for now because we
803 // don't have the full handling implemented.
804 cgm.errorNYI("deriveThisType: no record decl");
805 recTy = getASTContext().VoidTy;
806 }
807
808 if (md)
809 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
810 recTy, md->getMethodQualifiers().getAddressSpace()));
811 return getASTContext().getPointerType(recTy);
812}
813
814/// Arrange the CIR function layout for a value of the given function type, on
815/// top of any implicit parameters already stored.
816static const CIRGenFunctionInfo &
817arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod,
821 RequiredArgs required =
824 appendParameterTypes(cgt, prefix, fpt);
825 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
826 return cgt.arrangeCIRFunctionInfo(resultType, instanceMethod, prefix,
827 fpt->getExtInfo(), required);
828}
829
831 const VarDecl *param,
832 SourceLocation loc) {
833 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
834 // We need to turn that into an r-value suitable for emitCall
835 Address local = getAddrOfLocalVar(param);
836
837 QualType type = param->getType();
838
839 if (type->getAsCXXRecordDecl()) {
840 cgm.errorNYI(param->getSourceRange(),
841 "emitDelegateCallArg: record argument");
842 return;
843 }
844
845 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
846 // argument needs to be the original pointer.
847 if (type->isReferenceType()) {
848 args.add(
849 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
850 type);
851 } else if (getLangOpts().ObjCAutoRefCount) {
852 cgm.errorNYI(param->getSourceRange(),
853 "emitDelegateCallArg: ObjCAutoRefCount");
854 // For the most part, we just need to load the alloca, except that aggregate
855 // r-values are actually pointers to temporaries.
856 } else {
857 args.add(convertTempToRValue(local, type, loc), type);
858 }
859
860 // Deactivate the cleanup for the callee-destructed param that was pushed.
862 if (type->isRecordType() &&
863 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
864 param->needsDestruction(getContext())) {
865 cgm.errorNYI(param->getSourceRange(),
866 "emitDelegateCallArg: callee-destructed param");
867 }
868}
869
870static const CIRGenFunctionInfo &
872 const CallArgList &args,
873 const FunctionType *fnType) {
874
876
877 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
878 if (proto->isVariadic())
879 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
880 if (proto->hasExtParameterInfos())
881 cgm.errorNYI("call to functions with extra parameter info");
884 cgm.errorNYI("call to function without a prototype");
885
887 for (const CallArg &arg : args)
888 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
889
891
893 return cgt.arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false,
894 argTypes, fnType->getExtInfo(), required);
895}
896
897/// Arrange a call to a C++ method, passing the given arguments.
898///
899/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
900/// parameter.
901/// passProtoArgs indicates whether `args` has args for the parameters in the
902/// given CXXConstructorDecl.
904 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
905 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
906
907 // FIXME: Kill copy.
909 for (const auto &arg : args)
910 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
911
912 // +1 for implicit this, which should always be args[0]
913 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
914
916 RequiredArgs required = passProtoArgs
918 fpt, totalPrefixArgs + extraSuffixArgs)
920
921 GlobalDecl gd(d, ctorKind);
922 if (theCXXABI.hasThisReturn(gd))
923 cgm.errorNYI(d->getSourceRange(),
924 "arrangeCXXConstructorCall: hasThisReturn");
925 if (theCXXABI.hasMostDerivedReturn(gd))
926 cgm.errorNYI(d->getSourceRange(),
927 "arrangeCXXConstructorCall: hasMostDerivedReturn");
928 CanQualType resultType = astContext.VoidTy;
929
932
933 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
934 fpt->getExtInfo(), required);
935}
936
937/// Arrange a call to a C++ method, passing the given arguments.
938///
939/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
940/// does not count `this`.
942 const CallArgList &args, const FunctionProtoType *proto,
943 RequiredArgs required, unsigned numPrefixArgs) {
945 assert(numPrefixArgs + 1 <= args.size() &&
946 "Emitting a call with less args than the required prefix?");
947
948 // FIXME: Kill copy.
950 for (const CallArg &arg : args)
951 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
952
956 /*isInstanceMethod=*/true, argTypes, proto->getExtInfo(), required);
957}
958
959const CIRGenFunctionInfo &
961 const FunctionType *fnType) {
962 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
963}
964
965/// Arrange the argument and result information for a declaration or definition
966/// of the given C++ non-static member function. The member function must be an
967/// ordinary function, i.e. not a constructor or destructor.
968const CIRGenFunctionInfo &
970 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
971 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
972
973 auto prototype =
976
977 if (md->isInstance()) {
978 // The abstract case is perfectly fine.
979 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
980 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
981 }
982
983 return arrangeFreeFunctionType(prototype);
984}
985
986/// Arrange the argument and result information for a call to an unknown C++
987/// non-static member function of the given abstract type. (A null RD means we
988/// don't have any meaningful "this" argument type, so fall back to a generic
989/// pointer type). The member fucntion must be an ordinary function, i.e. not a
990/// constructor or destructor.
991const CIRGenFunctionInfo &
993 const FunctionProtoType *fpt,
994 const CXXMethodDecl *md) {
996
997 // Add the 'this' pointer.
998 argTypes.push_back(deriveThisType(rd, md));
999
1001 return ::arrangeCIRFunctionInfo(
1002 *this, /*isInstanceMethod=*/true, argTypes,
1004}
1005
1006/// Arrange the argument and result information for the declaration or
1007/// definition of the given function.
1008const CIRGenFunctionInfo &
1010 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1011 if (md->isInstance())
1012 return arrangeCXXMethodDeclaration(md);
1013
1015
1016 assert(isa<FunctionType>(funcTy));
1017 // TODO: setCUDAKernelCallingConvention
1019
1020 // When declaring a function without a prototype, always use a non-variadic
1021 // type.
1022 if (CanQual<FunctionNoProtoType> noProto =
1023 funcTy.getAs<FunctionNoProtoType>()) {
1026 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1027 /*isInstanceMethod=*/false, {},
1028 noProto->getExtInfo(), RequiredArgs::All);
1029 }
1030
1032}
1033
1034RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1035 if (!hasLV)
1036 return rv;
1037 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1039 lv.isVolatile());
1040 isUsed = true;
1041 return RValue::getAggregate(copy.getAddress());
1042}
1043
1045 SourceLocation argLoc,
1046 AbstractCallee ac, unsigned paramNum) {
1047 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1048 sanOpts.has(SanitizerKind::NullabilityArg)))
1049 return;
1050 cgm.errorNYI("non-null arg check is NYI");
1051}
1052
1053static cir::CIRCallOpInterface
1054emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
1055 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1056 cir::FuncOp directFuncOp,
1057 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1058 const mlir::NamedAttrList &attrs,
1060 const mlir::NamedAttrList &retAttrs) {
1061 CIRGenBuilderTy &builder = cgf.getBuilder();
1062
1064
1065 assert(builder.getInsertionBlock() && "expected valid basic block");
1066
1067 cir::CallOp op;
1068 if (indirectFuncTy) {
1069 // TODO(cir): Set calling convention for indirect calls.
1071 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1072 cirCallArgs, attrs, argAttrs, retAttrs);
1073 } else {
1074 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1075 argAttrs, retAttrs);
1076 }
1077
1078 return op;
1079}
1080
1081const CIRGenFunctionInfo &
1085 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1086 fpt);
1087}
1088
1089const CIRGenFunctionInfo &
1091 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1093 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1094 fnpt->getExtInfo(), RequiredArgs(0));
1095}
1096
1098 const CIRGenCallee &callee,
1100 const CallArgList &args,
1101 cir::CIRCallOpInterface *callOp,
1102 mlir::Location loc) {
1103 QualType retTy = funcInfo.getReturnType();
1104 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1105
1106 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1107
1109
1110 // Translate all of the arguments as necessary to match the CIR lowering.
1111 for (auto [argNo, arg, canQualArgType] :
1112 llvm::enumerate(args, funcInfo.argTypes())) {
1113
1114 // Insert a padding argument to ensure proper alignment.
1116
1117 mlir::Type argType = convertType(canQualArgType);
1118 if (!mlir::isa<cir::RecordType>(argType) &&
1119 !mlir::isa<cir::ComplexType>(argType)) {
1120 mlir::Value v;
1121 if (arg.isAggregate())
1122 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1123 v = arg.getKnownRValue().getValue();
1124
1125 // We might have to widen integers, but we should never truncate.
1126 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1127 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1128
1129 // If we have a pointer argument and there's an address space mismatch,
1130 // insert an address_space cast to match the expected function signature.
1131 if (argType != v.getType()) {
1132 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1133 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1134 if (argPtrTy && vPtrTy &&
1135 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1136 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1137 v = performAddrSpaceCast(v, argPtrTy);
1138 }
1139 }
1140
1141 // If the argument doesn't match, perform a bitcast to coerce it. This
1142 // can happen due to trivial type mismatches.
1143 // TODO(cir): When getFunctionType is added, assert that this isn't
1144 // needed.
1146 cirCallArgs[argNo] = v;
1147 } else {
1148 Address src = Address::invalid();
1149 if (!arg.isAggregate()) {
1150 src = createMemTemp(arg.ty, loc, "coerce");
1151 arg.copyInto(*this, src, loc);
1152 } else {
1153 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1154 : arg.getKnownRValue().getAggregateAddress();
1155 }
1156
1157 // Fast-isel and the optimizer generally like scalar values better than
1158 // FCAs, so we flatten them if this is safe to do for this argument.
1159 mlir::Type srcTy = src.getElementType();
1160 // FIXME(cir): get proper location for each argument.
1161 mlir::Location argLoc = loc;
1162
1163 // If the source type is smaller than the destination type of the
1164 // coerce-to logic, copy the source value into a temp alloca the size
1165 // of the destination type to allow loading all of it. The bits past
1166 // the source value are left undef.
1167 // FIXME(cir): add data layout info and compare sizes instead of
1168 // matching the types.
1169 //
1170 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1171 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1172 // if (SrcSize < DstSize) {
1174 if (srcTy != argType) {
1175 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1176 } else {
1177 // FIXME(cir): this currently only runs when the types are exactly the
1178 // same, but should be when alloc sizes are the same, fix this as soon
1179 // as datalayout gets introduced.
1181 }
1182
1183 // assert(NumCIRArgs == STy.getMembers().size());
1184 // In LLVMGen: Still only pass the struct without any gaps but mark it
1185 // as such somehow.
1186 //
1187 // In CIRGen: Emit a load from the "whole" struct,
1188 // which shall be broken later by some lowering step into multiple
1189 // loads.
1191 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1192 }
1193 }
1194
1195 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1196 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1197
1199
1200 mlir::NamedAttrList attrs;
1201 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1202 mlir::NamedAttrList retAttrs;
1203 StringRef funcName;
1204 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1205 funcName = calleeFuncOp.getName();
1206
1209 cir::CallingConv callingConv;
1210 cir::SideEffect sideEffect;
1211 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1212 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1213 /*attrOnCallSite=*/true, /*isThunk=*/false);
1214
1215 cir::FuncType indirectFuncTy;
1216 mlir::Value indirectFuncVal;
1217 cir::FuncOp directFuncOp;
1218 if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
1219 directFuncOp = fnOp;
1220 } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
1221 // FIXME(cir): This peephole optimization avoids indirect calls for
1222 // builtins. This should be fixed in the builtin declaration instead by
1223 // not emitting an unecessary get_global in the first place.
1224 // However, this is also used for no-prototype functions.
1225 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1226 assert(globalOp && "undefined global function");
1227 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
1228 } else {
1229 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1230 calleePtr->getResultTypes();
1231 [[maybe_unused]] auto funcPtrTy =
1232 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1233 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1234 "expected pointer to function");
1235
1236 indirectFuncTy = cirFuncTy;
1237 indirectFuncVal = calleePtr->getResult(0);
1238 }
1239
1243
1244 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1245 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1246
1247 mlir::Location callLoc = loc;
1248 cir::CIRCallOpInterface theCall =
1249 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1250 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1251
1252 if (callOp)
1253 *callOp = theCall;
1254
1257
1258 mlir::Type retCIRTy = convertType(retTy);
1259 if (isa<cir::VoidType>(retCIRTy))
1260 return getUndefRValue(retTy);
1261 switch (getEvaluationKind(retTy)) {
1262 case cir::TEK_Aggregate: {
1263 Address destPtr = returnValue.getValue();
1264
1265 if (!destPtr.isValid())
1266 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1267
1268 mlir::ResultRange results = theCall->getOpResults();
1269 assert(results.size() <= 1 && "multiple returns from a call");
1270
1271 SourceLocRAIIObject loc{*this, callLoc};
1272 emitAggregateStore(results[0], destPtr);
1273 return RValue::getAggregate(destPtr);
1274 }
1275 case cir::TEK_Scalar: {
1276 mlir::ResultRange results = theCall->getOpResults();
1277 assert(results.size() == 1 && "unexpected number of returns");
1278
1279 // If the argument doesn't match, perform a bitcast to coerce it. This
1280 // can happen due to trivial type mismatches.
1281 if (results[0].getType() != retCIRTy)
1282 cgm.errorNYI(loc, "bitcast on function return value");
1283
1284 mlir::Region *region = builder.getBlock()->getParent();
1285 if (region != theCall->getParentRegion())
1286 cgm.errorNYI(loc, "function calls with cleanup");
1287
1288 return RValue::get(results[0]);
1289 }
1290 case cir::TEK_Complex: {
1291 mlir::ResultRange results = theCall->getOpResults();
1292 assert(!results.empty() &&
1293 "Expected at least one result for complex rvalue");
1294 return RValue::getComplex(results[0]);
1295 }
1296 }
1297 llvm_unreachable("Invalid evaluation kind");
1298}
1299
1301 mlir::Location loc) const {
1302 LValue dst = cgf.makeAddrLValue(addr, ty);
1303 if (!hasLV && rv.isScalar())
1304 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1305 else if (!hasLV && rv.isComplex())
1306 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1307 else
1308 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1309 isUsed = true;
1310}
1311
1312mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1313 cir::FuncOp callee,
1315 mlir::NamedAttrList attrs) {
1316 // TODO(cir): set the calling convention to this runtime call.
1318
1319 cir::CallOp call = builder.createCallOp(loc, callee, args);
1320 assert(call->getNumResults() <= 1 &&
1321 "runtime functions have at most 1 result");
1322
1323 if (!attrs.empty())
1324 call->setAttrs(attrs);
1325
1326 if (call->getNumResults() == 0)
1327 return nullptr;
1328
1329 return call->getResult(0);
1330}
1331
1333 clang::QualType argType) {
1334 assert(argType->isReferenceType() == e->isGLValue() &&
1335 "reference binding to unmaterialized r-value!");
1336
1337 if (e->isGLValue()) {
1338 assert(e->getObjectKind() == OK_Ordinary);
1339 return args.add(emitReferenceBindingToExpr(e), argType);
1340 }
1341
1342 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1343
1344 // For callee-destructed parameters (trivial_abi, MS ABI), create an
1345 // aggregate temp and let the callee destroy it.
1346 if (argType->isRecordType() &&
1348 AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
1350
1351 bool destroyedInCallee = true;
1352 if (const auto *rd = argType->getAsCXXRecordDecl())
1353 destroyedInCallee = rd->hasNonTrivialDestructor();
1354
1355 if (destroyedInCallee)
1357
1358 emitAggExpr(e, slot);
1359 RValue rv = slot.asRValue();
1360 args.add(rv, argType);
1361
1362 if (destroyedInCallee && getLangOpts().Exceptions)
1363 cgm.errorNYI(e->getSourceRange(),
1364 "callee-destructed param with exceptions");
1365 return;
1366 }
1367
1368 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1369 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1370 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1371 assert(lv.isSimple());
1372 args.addUncopiedAggregate(lv, argType);
1373 return;
1374 }
1375
1376 args.add(emitAnyExprToTemp(e), argType);
1377}
1378
1379QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1380 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1381 // implicitly widens null pointer constants that are arguments to varargs
1382 // functions to pointer-sized ints.
1383 if (!getTarget().getTriple().isOSWindows())
1384 return arg->getType();
1385
1386 assert(!cir::MissingFeatures::msabi());
1387 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1388 return arg->getType();
1389}
1390
1391/// Similar to emitAnyExpr(), however, the result will always be accessible
1392/// even if no aggregate location is provided.
1395
1397 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1399
1400 return emitAnyExpr(e, aggSlot);
1401}
1402
1404 CallArgList &args, PrototypeWrapper prototype,
1405 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1406 AbstractCallee callee, unsigned paramsToSkip) {
1408
1410
1411 // First, if a prototype was provided, use those argument types.
1412 bool isVariadic = false;
1413 if (prototype.p) {
1415
1416 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1417 isVariadic = fpt->isVariadic();
1419 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1420 fpt->param_type_end());
1421 }
1422
1423 // If we still have any arguments, emit them using the type of the argument.
1424 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1425 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1426 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1427
1428 // We must evaluate arguments from right to left in the MS C++ ABI, because
1429 // arguments are destroyed left to right in the callee. As a special case,
1430 // there are certain language constructs taht require left-to-right
1431 // evaluation, and in those cases we consider the evaluation order requirement
1432 // to trump the "destruction order is reverse construction order" guarantee.
1433 auto leftToRight = true;
1434 assert(!cir::MissingFeatures::msabi());
1435
1436 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1437 RValue emittedArg) {
1438 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1439 return;
1440 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1441 if (!ps)
1442 return;
1443
1445 cgm.errorNYI("emit implicit object size for call arg");
1446 };
1447
1448 // Evaluate each argument in the appropriate order.
1449 size_t callArgsStart = args.size();
1450 for (size_t i = 0; i != argTypes.size(); ++i) {
1451 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1452 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1453 size_t initialArgSize = args.size();
1454
1455 emitCallArg(args, *currentArg, argTypes[idx]);
1456
1457 // In particular, we depend on it being the last arg in Args, and the
1458 // objectsize bits depend on there only being one arg if !LeftToRight.
1459 assert(initialArgSize + 1 == args.size() &&
1460 "The code below depends on only adding one arg per emitCallArg");
1461 (void)initialArgSize;
1462
1463 // Since pointer argument are never emitted as LValue, it is safe to emit
1464 // non-null argument check for r-value only.
1465 if (!args.back().hasLValue()) {
1466 RValue rvArg = args.back().getKnownRValue();
1468 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1469 }
1470
1471 if (!leftToRight)
1472 std::reverse(args.begin() + callArgsStart, args.end());
1473 }
1474}
1475
1476// FIXME(cir): This is identical to the version from classic-codegen, we should
1477// figure out how to move this to a common location.
1479 CXXCtorType type) {
1480 // Parameters are unnecessary if we're constructing a base class subobject
1481 // and the inherited constructor lives in a virtual base.
1482 return type == Ctor_Complete ||
1483 !inherited.getShadowDecl()->constructsVirtualBase() ||
1485}
static StringRef bytes(const std::vector< T, Allocator > &v)
static void addTrivialDefaultFunctionAttributes(mlir::MLIRContext *mlirCtx, StringRef name, bool hasOptNoneAttr, const CodeGenOptions &codeGenOpts, const LangOptions &langOpts, bool attrOnCallSite, mlir::NamedAttrList &attrs)
Add default attributes to a function, which have merge semantics under -mlink-builtin-bitcode and sho...
static void addNoBuiltinAttributes(mlir::MLIRContext &ctx, mlir::NamedAttrList &attrs, const LangOptions &langOpts, const NoBuiltinAttr *nba=nullptr)
static bool determineNoUndef(QualType clangTy, CIRGenTypes &types, const cir::CIRDataLayout &layout, const cir::ABIArgInfo &argInfo)
static void addDenormalModeAttrs(llvm::DenormalMode fpDenormalMode, llvm::DenormalMode fp32DenormalMode, mlir::NamedAttrList &attrs)
Add denormal-fp-math and denormal-fp-math-f32 as appropriate for the requested denormal behavior,...
static unsigned getNoFPClassTestMask(const LangOptions &langOpts)
Compute the nofpclass mask for FP types based on language options.
static void addMergeableDefaultFunctionAttributes(const CodeGenOptions &codeGenOpts, mlir::NamedAttrList &attrs)
Add default attributes to a function, which have merge semantics under -mlink-builtin-bitcode and sho...
static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Adds the formal parameters in FPT to the given prefix.
static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal, cir::FuncOp directFuncOp, const SmallVectorImpl< mlir::Value > &cirCallArgs, bool isInvoke, const mlir::NamedAttrList &attrs, llvm::ArrayRef< mlir::NamedAttrList > argAttrs, const mlir::NamedAttrList &retAttrs)
static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder, mlir::NamedAttrList &attrs, const FunctionProtoType *fpt)
static llvm::StringLiteral getZeroCallUsedRegsKindStr(llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind k)
static CanQual< FunctionProtoType > getFormalType(const CXXMethodDecl *md)
Returns the canonical formal type of the given C++ method.
static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const CallArgList &args, const FunctionType *fnType)
static const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Arrange the CIR function layout for a value of the given function type, on top of any implicit parame...
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 VoidTy
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:917
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3772
mlir::Type getElementType() const
Definition Address.h:123
static Address invalid()
Definition Address.h:74
bool isValid() const
Definition Address.h:75
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
cir::ABIArgInfo getReturnInfo() const
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, bool instanceMethod, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
llvm::MutableArrayRef< CanQualType > argTypes()
llvm::ArrayRef< CanQualType > requiredArguments() const
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.
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.
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.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
CIRGenBuilderTy & getBuilder()
void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc, AbstractCallee ac, unsigned paramNum)
Create a check for a function parameter that may potentially be declared as non-null.
mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={}, mlir::NamedAttrList attrs={})
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
void emitDelegateCallArg(CallArgList &args, const clang::VarDecl *param, clang::SourceLocation loc)
We are performing a delegate call; that is, the current function is delegating to another one.
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
void addDefaultFunctionAttributes(StringRef name, bool hasOptNoneAttr, bool attrOnCallSite, mlir::NamedAttrList &attrs)
Helper function for constructAttributeList/others.
CIRGenBuilderTy & getBuilder()
CharUnits getMinimumObjectSize(QualType ty)
Returns the minimum object size for an object of the given type.
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
clang::CharUnits getNaturalPointeeTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
This class organizes the cross-module state that is used while lowering AST types to CIR types.
Definition CIRGenTypes.h:49
CIRGenModule & getCGModule() const
Definition CIRGenTypes.h:83
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md)
C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, bool isInstanceMethod, llvm::ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, RequiredArgs required)
const CIRGenFunctionInfo & arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType)
const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)
const CIRGenFunctionInfo & arrangeCXXConstructorCall(const CallArgList &args, const clang::CXXConstructorDecl *d, clang::CXXCtorType ctorKind, unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
const CIRGenFunctionInfo & arrangeCXXMethodType(const clang::CXXRecordDecl *rd, const clang::FunctionProtoType *ftp, const clang::CXXMethodDecl *md)
Arrange the argument and result information for a call to an unknown C++ non-static member function o...
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
bool inheritingCtorHasParams(const InheritedConstructor &inherited, CXXCtorType type)
Determine if a C++ inheriting constructor should have parameters matching those of its inherited cons...
clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, const clang::CXXMethodDecl *md)
Derives the 'this' type for CIRGen purposes, i.e.
const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)
Free functions are functions that are compatible with an ordinary C function pointer type.
clang::ASTContext & getASTContext() const
const CIRGenFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const clang::FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)
Arrange a call to a C++ method, passing the given arguments.
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void addUncopiedAggregate(LValue lvalue, clang::QualType type)
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...
Represents a C++ constructor within a class.
Definition DeclCXX.h:2624
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
bool isVirtual() const
Definition DeclCXX.h:2191
bool isInstance() const
Definition DeclCXX.h:2163
Qualifiers getMethodQualifiers() const
Definition DeclCXX.h:2310
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:2946
SourceLocation getBeginLoc() const
Definition Expr.h:3280
ConstExprIterator const_arg_iterator
Definition Expr.h:3194
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:3325
bool constructsVirtualBase() const
Returns true if the constructed base class is a virtual base class subobject of this declaration's cl...
Definition DeclCXX.h:3793
T * getAttr() const
Definition DeclBase.h:581
bool hasAttr() const
Definition DeclBase.h:585
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:454
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2015
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4551
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4935
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5357
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5664
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5756
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4664
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4553
ExtInfo getExtInfo() const
Definition TypeBase.h:4909
QualType getReturnType() const
Definition TypeBase.h:4893
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
CXXCtorType getCtorType() const
Definition GlobalDecl.h:108
GlobalDecl getWithKernelReferenceKind(KernelReferenceKind Kind)
Definition GlobalDecl.h:203
const Decl * getDecl() const
Definition GlobalDecl.h:106
Description of a constructor that was inherited from a base class.
Definition DeclCXX.h:2595
ConstructorUsingShadowDecl * getShadowDecl() const
Definition DeclCXX.h:2607
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:4387
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2914
QualType getCanonicalType() const
Definition TypeBase.h:8483
LangAS getAddressSpace() const
Definition TypeBase.h:571
bool isParamDestroyedInCallee() const
Definition Decl.h:4492
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?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
bool isVoidType() const
Definition TypeBase.h:9034
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:714
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition Type.cpp:2470
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8692
bool isScalarType() const
Definition TypeBase.h:9140
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
bool isBitIntType() const
Definition TypeBase.h:8943
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isMemberPointerType() const
Definition TypeBase.h:8749
bool isObjectType() const
Determine whether this type is an object type.
Definition TypeBase.h:2558
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2480
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition Type.cpp:2350
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2971
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
bool isNullPtrType() const
Definition TypeBase.h:9071
bool isRecordType() const
Definition TypeBase.h:8795
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2203
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2864
Represents a GCC generic vector type.
Definition TypeBase.h:4225
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:34
@ 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.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
CXXCtorType
C++ constructor types.
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 opCallImplicitObjectSizeArgs()
static bool opCallMustTail()
static bool cudaSupport()
static bool opCallFnInfoOpts()
static bool msvcCXXPersonality()
static bool opCallCIRGenFuncInfoParamInfo()
Similar to AddedStructorArgs, but only notes the number of additional arguments.
llvm::PointerUnion< const clang::FunctionProtoType *, const clang::ObjCMethodDecl * > p
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