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
1019/// Arrange the argument and result information for a declaration or definition
1020/// of the given C++ non-static member function. The member function must be an
1021/// ordinary function, i.e. not a constructor or destructor.
1022const CIRGenFunctionInfo &
1024 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
1025 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
1026
1027 auto prototype =
1030
1031 // Mirrors classic CodeGen's check at CGCall.cpp. C++23 explicit-object
1032 // member functions (P0847R7, `void f(this Self&&)`) do not receive an
1033 // implicit `this`; the explicit object parameter takes its place at the
1034 // AST level and appears as the first parameter of the FunctionProtoType.
1035 // Arrange them as free functions so we don't prepend a stale implicit
1036 // `this` to the parameter list, which would produce a CIRGenFunctionInfo
1037 // with one more argument than the matching cir.func type and trip the
1038 // assertion in setArgAttrs.
1040 // The abstract case is perfectly fine.
1041 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1042 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
1043 }
1044
1045 return arrangeFreeFunctionType(prototype);
1046}
1047
1048/// Arrange the argument and result information for a call to an unknown C++
1049/// non-static member function of the given abstract type. (A null RD means we
1050/// don't have any meaningful "this" argument type, so fall back to a generic
1051/// pointer type). The member fucntion must be an ordinary function, i.e. not a
1052/// constructor or destructor.
1053const CIRGenFunctionInfo &
1055 const FunctionProtoType *fpt,
1056 const CXXMethodDecl *md) {
1058
1059 // Add the 'this' pointer.
1060 argTypes.push_back(deriveThisType(rd, md));
1061
1063 return ::arrangeCIRFunctionInfo(
1064 *this, /*isInstanceMethod=*/true, argTypes,
1066}
1067
1068/// Arrange the argument and result information for the declaration or
1069/// definition of the given function.
1070const CIRGenFunctionInfo &
1072 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1073 if (md->isInstance())
1074 return arrangeCXXMethodDeclaration(md);
1075
1077
1078 assert(isa<FunctionType>(funcTy));
1079 // TODO: setCUDAKernelCallingConvention
1081
1082 // When declaring a function without a prototype, always use a non-variadic
1083 // type.
1084 if (CanQual<FunctionNoProtoType> noProto =
1085 funcTy.getAs<FunctionNoProtoType>()) {
1088 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1089 /*isInstanceMethod=*/false, {},
1090 noProto->getExtInfo(), RequiredArgs::All);
1091 }
1092
1094}
1095
1096RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1097 if (!hasLV)
1098 return rv;
1099 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1101 lv.isVolatile());
1102 isUsed = true;
1103 return RValue::getAggregate(copy.getAddress());
1104}
1105
1107 SourceLocation argLoc,
1108 AbstractCallee ac, unsigned paramNum) {
1109 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1110 sanOpts.has(SanitizerKind::NullabilityArg)))
1111 return;
1112 cgm.errorNYI("non-null arg check is NYI");
1113}
1114
1115static cir::CIRCallOpInterface
1116emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
1117 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1118 cir::FuncOp directFuncOp,
1119 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1120 const mlir::NamedAttrList &attrs,
1122 const mlir::NamedAttrList &retAttrs) {
1123 CIRGenBuilderTy &builder = cgf.getBuilder();
1124
1126
1127 assert(builder.getInsertionBlock() && "expected valid basic block");
1128
1129 cir::CallOp op;
1130 if (indirectFuncTy) {
1131 // TODO(cir): Set calling convention for indirect calls.
1133 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1134 cirCallArgs, attrs, argAttrs, retAttrs);
1135 } else {
1136 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1137 argAttrs, retAttrs);
1138 }
1139
1140 return op;
1141}
1142
1143const CIRGenFunctionInfo &
1147 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1148 fpt);
1149}
1150
1151const CIRGenFunctionInfo &
1153 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1155 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1156 fnpt->getExtInfo(), RequiredArgs(0));
1157}
1158
1160 const CIRGenCallee &callee,
1162 const CallArgList &args,
1163 cir::CIRCallOpInterface *callOp,
1164 mlir::Location loc) {
1165 QualType retTy = funcInfo.getReturnType();
1166 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1167
1168 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1169
1171
1172 // Translate all of the arguments as necessary to match the CIR lowering.
1173 for (auto [argNo, arg, canQualArgType] :
1174 llvm::enumerate(args, funcInfo.argTypes())) {
1175
1176 // Insert a padding argument to ensure proper alignment.
1178
1179 mlir::Type argType = convertType(canQualArgType);
1180 if (!mlir::isa<cir::RecordType>(argType) &&
1181 !mlir::isa<cir::ComplexType>(argType)) {
1182 mlir::Value v;
1183 if (arg.isAggregate())
1184 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1185 v = arg.getKnownRValue().getValue();
1186
1187 // We might have to widen integers, but we should never truncate.
1188 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1189 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1190
1191 // If we have a pointer argument and there's an address space mismatch,
1192 // insert an address_space cast to match the expected function signature.
1193 if (argType != v.getType()) {
1194 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1195 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1196 if (argPtrTy && vPtrTy &&
1197 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1198 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1199 v = performAddrSpaceCast(v, argPtrTy);
1200 }
1201 }
1202
1203 // If the argument doesn't match, perform a bitcast to coerce it. This
1204 // can happen due to trivial type mismatches.
1205 // TODO(cir): When getFunctionType is added, assert that this isn't
1206 // needed.
1208 cirCallArgs[argNo] = v;
1209 } else {
1210 Address src = Address::invalid();
1211 if (!arg.isAggregate()) {
1212 src = createMemTemp(arg.ty, loc, "coerce");
1213 arg.copyInto(*this, src, loc);
1214 } else {
1215 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1216 : arg.getKnownRValue().getAggregateAddress();
1217 }
1218
1219 // Fast-isel and the optimizer generally like scalar values better than
1220 // FCAs, so we flatten them if this is safe to do for this argument.
1221 mlir::Type srcTy = src.getElementType();
1222 // FIXME(cir): get proper location for each argument.
1223 mlir::Location argLoc = loc;
1224
1225 // If the source type is smaller than the destination type of the
1226 // coerce-to logic, copy the source value into a temp alloca the size
1227 // of the destination type to allow loading all of it. The bits past
1228 // the source value are left undef.
1229 // FIXME(cir): add data layout info and compare sizes instead of
1230 // matching the types.
1231 //
1232 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1233 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1234 // if (SrcSize < DstSize) {
1236 if (srcTy != argType) {
1237 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1238 } else {
1239 // FIXME(cir): this currently only runs when the types are exactly the
1240 // same, but should be when alloc sizes are the same, fix this as soon
1241 // as datalayout gets introduced.
1243 }
1244
1245 // assert(NumCIRArgs == STy.getMembers().size());
1246 // In LLVMGen: Still only pass the struct without any gaps but mark it
1247 // as such somehow.
1248 //
1249 // In CIRGen: Emit a load from the "whole" struct,
1250 // which shall be broken later by some lowering step into multiple
1251 // loads.
1253 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1254 }
1255 }
1256
1257 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1258 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1259
1261
1262 mlir::NamedAttrList attrs;
1263 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1264 mlir::NamedAttrList retAttrs;
1265 StringRef funcName;
1266 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1267 funcName = calleeFuncOp.getName();
1268
1271 cir::CallingConv callingConv;
1272 cir::SideEffect sideEffect;
1273 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1274 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1275 /*attrOnCallSite=*/true, /*isThunk=*/false);
1276
1277 auto resolvedFuncOpFromGlobal = [&](mlir::Operation *op) -> cir::FuncOp {
1278 if (auto fnOp = dyn_cast<cir::FuncOp>(op))
1279 return fnOp;
1280 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(op)) {
1281 // FIXME(cir): This peephole optimization avoids indirect calls for
1282 // builtins. This should be fixed in the builtin declaration instead by
1283 // not emitting an unecessary get_global in the first place. However,
1284 // this is also used for no-prototype functions.
1285 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1286 assert(globalOp && "undefined global function");
1287 return cast<cir::FuncOp>(globalOp);
1288 }
1289 return nullptr;
1290 };
1291
1292 cir::FuncType indirectFuncTy;
1293 mlir::Value indirectFuncVal;
1294 cir::FuncOp directFuncOp;
1295
1296 // If the callee resolves to a FuncOp whose stored signature differs from
1297 // this call site's expected signature, the CIR verifier would reject the
1298 // mismatched types. This happens, for example, when two declarations share a
1299 // mangled name via __asm__ renaming (glibc's __REDIRECT_NTH pattern) but
1300 // disagree about a struct argument type. If that happens, we demote the
1301 // direct call to an indirect call through a function-pointer bitcast typed
1302 // at the call site.
1303 if (cir::FuncOp candidate = resolvedFuncOpFromGlobal(calleePtr)) {
1304 if (candidate.getFunctionType() == cirFuncTy) {
1305 directFuncOp = candidate;
1306 } else {
1307 mlir::Value addr = cir::GetGlobalOp::create(
1308 builder, loc, cir::PointerType::get(candidate.getFunctionType()),
1309 candidate.getSymName());
1310 indirectFuncTy = cirFuncTy;
1311 indirectFuncVal =
1312 builder.createBitcast(addr, cir::PointerType::get(cirFuncTy));
1313 }
1314 } else {
1315 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1316 calleePtr->getResultTypes();
1317 [[maybe_unused]] auto funcPtrTy =
1318 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1319 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1320 "expected pointer to function");
1321
1322 indirectFuncTy = cirFuncTy;
1323 indirectFuncVal = calleePtr->getResult(0);
1324 }
1325
1329
1330 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1331 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1332
1333 mlir::Location callLoc = loc;
1334 cir::CIRCallOpInterface theCall =
1335 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1336 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1337
1338 if (callOp)
1339 *callOp = theCall;
1340
1343
1344 mlir::Type retCIRTy = convertType(retTy);
1345 if (isa<cir::VoidType>(retCIRTy))
1346 return getUndefRValue(retTy);
1347 switch (getEvaluationKind(retTy)) {
1348 case cir::TEK_Aggregate: {
1349 Address destPtr = returnValue.getValue();
1350
1351 if (!destPtr.isValid())
1352 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1353
1354 mlir::ResultRange results = theCall->getOpResults();
1355 assert(results.size() <= 1 && "multiple returns from a call");
1356
1357 SourceLocRAIIObject loc{*this, callLoc};
1358 emitAggregateStore(results[0], destPtr);
1359 return RValue::getAggregate(destPtr);
1360 }
1361 case cir::TEK_Scalar: {
1362 mlir::ResultRange results = theCall->getOpResults();
1363 assert(results.size() == 1 && "unexpected number of returns");
1364
1365 // If the argument doesn't match, perform a bitcast to coerce it. This
1366 // can happen due to trivial type mismatches.
1367 if (results[0].getType() != retCIRTy)
1368 cgm.errorNYI(loc, "bitcast on function return value");
1369
1370 mlir::Region *region = builder.getBlock()->getParent();
1371 if (region != theCall->getParentRegion())
1372 cgm.errorNYI(loc, "function calls with cleanup");
1373
1374 return RValue::get(results[0]);
1375 }
1376 case cir::TEK_Complex: {
1377 mlir::ResultRange results = theCall->getOpResults();
1378 assert(!results.empty() &&
1379 "Expected at least one result for complex rvalue");
1380 return RValue::getComplex(results[0]);
1381 }
1382 }
1383 llvm_unreachable("Invalid evaluation kind");
1384}
1385
1387 mlir::Location loc) const {
1388 LValue dst = cgf.makeAddrLValue(addr, ty);
1389 if (!hasLV && rv.isScalar())
1390 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1391 else if (!hasLV && rv.isComplex())
1392 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1393 else
1394 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1395 isUsed = true;
1396}
1397
1398mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1399 cir::FuncOp callee,
1401 mlir::NamedAttrList attrs) {
1402
1403 // TODO(cir): set the calling convention to this runtime call.
1405
1406 cir::CallOp call = builder.createCallOp(loc, callee, args);
1407 assert(call->getNumResults() <= 1 &&
1408 "runtime functions have at most 1 result");
1409
1410 if (!attrs.empty())
1411 call->setAttrs(attrs);
1412
1413 if (call->getNumResults() == 0)
1414 return nullptr;
1415
1416 return call->getResult(0);
1417}
1418
1420 clang::QualType argType) {
1421 assert(argType->isReferenceType() == e->isGLValue() &&
1422 "reference binding to unmaterialized r-value!");
1423
1424 if (e->isGLValue()) {
1425 assert(e->getObjectKind() == OK_Ordinary);
1426 return args.add(emitReferenceBindingToExpr(e), argType);
1427 }
1428
1429 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1430
1431 // For callee-destructed parameters (trivial_abi, MS ABI), create an
1432 // aggregate temp and let the callee destroy it.
1433 if (argType->isRecordType() &&
1435 AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
1437
1438 bool destroyedInCallee = true;
1439 if (const auto *rd = argType->getAsCXXRecordDecl())
1440 destroyedInCallee = rd->hasNonTrivialDestructor();
1441
1442 if (destroyedInCallee)
1444
1445 emitAggExpr(e, slot);
1446 RValue rv = slot.asRValue();
1447 args.add(rv, argType);
1448
1449 if (destroyedInCallee && getLangOpts().Exceptions)
1450 cgm.errorNYI(e->getSourceRange(),
1451 "callee-destructed param with exceptions");
1452 return;
1453 }
1454
1455 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1456 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1457 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1458 assert(lv.isSimple());
1459 args.addUncopiedAggregate(lv, argType);
1460 return;
1461 }
1462
1463 args.add(emitAnyExprToTemp(e), argType);
1464}
1465
1466QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1467 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1468 // implicitly widens null pointer constants that are arguments to varargs
1469 // functions to pointer-sized ints.
1470 if (!getTarget().getTriple().isOSWindows())
1471 return arg->getType();
1472
1473 assert(!cir::MissingFeatures::msabi());
1474 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1475 return arg->getType();
1476}
1477
1478/// Similar to emitAnyExpr(), however, the result will always be accessible
1479/// even if no aggregate location is provided.
1482
1484 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1486
1487 return emitAnyExpr(e, aggSlot);
1488}
1489
1491 CallArgList &args, PrototypeWrapper prototype,
1492 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1493 AbstractCallee callee, unsigned paramsToSkip) {
1495
1497
1498 // First, if a prototype was provided, use those argument types.
1499 bool isVariadic = false;
1500 if (prototype.p) {
1502
1503 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1504 isVariadic = fpt->isVariadic();
1506 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1507 fpt->param_type_end());
1508 }
1509
1510 // If we still have any arguments, emit them using the type of the argument.
1511 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1512 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1513 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1514
1515 // We must evaluate arguments from right to left in the MS C++ ABI, because
1516 // arguments are destroyed left to right in the callee. As a special case,
1517 // there are certain language constructs taht require left-to-right
1518 // evaluation, and in those cases we consider the evaluation order requirement
1519 // to trump the "destruction order is reverse construction order" guarantee.
1520 auto leftToRight = true;
1521 assert(!cir::MissingFeatures::msabi());
1522
1523 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1524 RValue emittedArg) {
1525 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1526 return;
1527 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1528 if (!ps)
1529 return;
1530
1532 assert(emittedArg.getValue() && "We emitted nothing for the arg?");
1533 mlir::Value v = evaluateOrEmitBuiltinObjectSize(
1534 arg, ps->getType(), cast<cir::IntType>(cgm.sizeTy),
1535 emittedArg.getValue(), ps->isDynamic());
1536 args.add(RValue::get(v), sizeTy);
1537 // When emitting right-to-left, the size arg was appended after the
1538 // pointer arg; swap them so the size follows the pointer in the final
1539 // argument list after the outer reverse.
1540 if (!leftToRight)
1541 std::iter_swap(args.rbegin(), std::next(args.rbegin()));
1542 };
1543
1544 // Evaluate each argument in the appropriate order.
1545 size_t callArgsStart = args.size();
1546 for (size_t i = 0; i != argTypes.size(); ++i) {
1547 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1548 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1549 size_t initialArgSize = args.size();
1550
1551 emitCallArg(args, *currentArg, argTypes[idx]);
1552
1553 // In particular, we depend on it being the last arg in Args, and the
1554 // objectsize bits depend on there only being one arg if !LeftToRight.
1555 assert(initialArgSize + 1 == args.size() &&
1556 "The code below depends on only adding one arg per emitCallArg");
1557 (void)initialArgSize;
1558
1559 // Since pointer argument are never emitted as LValue, it is safe to emit
1560 // non-null argument check for r-value only.
1561 if (!args.back().hasLValue()) {
1562 RValue rvArg = args.back().getKnownRValue();
1564 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1565 }
1566
1567 if (!leftToRight)
1568 std::reverse(args.begin() + callArgsStart, args.end());
1569 }
1570}
1571
1572// FIXME(cir): This is identical to the version from classic-codegen, we should
1573// figure out how to move this to a common location.
1575 CXXCtorType type) {
1576 // Parameters are unnecessary if we're constructing a base class subobject
1577 // and the inherited constructor lives in a virtual base.
1578 return type == Ctor_Complete ||
1579 !inherited.getShadowDecl()->constructsVirtualBase() ||
1581}
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:925
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3784
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 & 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:2620
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2132
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:2187
Qualifiers getMethodQualifiers() const
Definition DeclCXX.h:2306
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:3337
bool constructsVirtualBase() const
Returns true if the constructed base class is a virtual base class subobject of this declaration's cl...
Definition DeclCXX.h:3782
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:2018
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4523
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4947
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5369
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5676
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5768
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4676
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4565
ExtInfo getExtInfo() const
Definition TypeBase.h:4921
QualType getReturnType() const
Definition TypeBase.h:4905
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:2591
ConstructorUsingShadowDecl * getShadowDecl() const
Definition DeclCXX.h:2603
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:4399
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:2962
QualType getCanonicalType() const
Definition TypeBase.h:8497
LangAS getAddressSpace() const
Definition TypeBase.h:571
bool isParamDestroyedInCallee() const
Definition Decl.h:4493
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:9048
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:2517
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8706
bool isScalarType() const
Definition TypeBase.h:9154
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:8957
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isMemberPointerType() const
Definition TypeBase.h:8763
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:2527
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition Type.cpp:2397
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2983
bool isAnyPointerType() const
Definition TypeBase.h:8690
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9275
bool isNullPtrType() const
Definition TypeBase.h:9085
bool isRecordType() const
Definition TypeBase.h:8809
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:924
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:2809
Represents a GCC generic vector type.
Definition TypeBase.h:4237
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