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