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 if (md->isInstance()) {
1032 // The abstract case is perfectly fine.
1033 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
1034 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
1035 }
1036
1037 return arrangeFreeFunctionType(prototype);
1038}
1039
1040/// Arrange the argument and result information for a call to an unknown C++
1041/// non-static member function of the given abstract type. (A null RD means we
1042/// don't have any meaningful "this" argument type, so fall back to a generic
1043/// pointer type). The member fucntion must be an ordinary function, i.e. not a
1044/// constructor or destructor.
1045const CIRGenFunctionInfo &
1047 const FunctionProtoType *fpt,
1048 const CXXMethodDecl *md) {
1050
1051 // Add the 'this' pointer.
1052 argTypes.push_back(deriveThisType(rd, md));
1053
1055 return ::arrangeCIRFunctionInfo(
1056 *this, /*isInstanceMethod=*/true, argTypes,
1058}
1059
1060/// Arrange the argument and result information for the declaration or
1061/// definition of the given function.
1062const CIRGenFunctionInfo &
1064 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1065 if (md->isInstance())
1066 return arrangeCXXMethodDeclaration(md);
1067
1069
1070 assert(isa<FunctionType>(funcTy));
1071 // TODO: setCUDAKernelCallingConvention
1073
1074 // When declaring a function without a prototype, always use a non-variadic
1075 // type.
1076 if (CanQual<FunctionNoProtoType> noProto =
1077 funcTy.getAs<FunctionNoProtoType>()) {
1080 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1081 /*isInstanceMethod=*/false, {},
1082 noProto->getExtInfo(), RequiredArgs::All);
1083 }
1084
1086}
1087
1088RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1089 if (!hasLV)
1090 return rv;
1091 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1093 lv.isVolatile());
1094 isUsed = true;
1095 return RValue::getAggregate(copy.getAddress());
1096}
1097
1099 SourceLocation argLoc,
1100 AbstractCallee ac, unsigned paramNum) {
1101 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1102 sanOpts.has(SanitizerKind::NullabilityArg)))
1103 return;
1104 cgm.errorNYI("non-null arg check is NYI");
1105}
1106
1107static cir::CIRCallOpInterface
1108emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
1109 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1110 cir::FuncOp directFuncOp,
1111 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1112 const mlir::NamedAttrList &attrs,
1114 const mlir::NamedAttrList &retAttrs) {
1115 CIRGenBuilderTy &builder = cgf.getBuilder();
1116
1118
1119 assert(builder.getInsertionBlock() && "expected valid basic block");
1120
1121 cir::CallOp op;
1122 if (indirectFuncTy) {
1123 // TODO(cir): Set calling convention for indirect calls.
1125 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1126 cirCallArgs, attrs, argAttrs, retAttrs);
1127 } else {
1128 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1129 argAttrs, retAttrs);
1130 }
1131
1132 return op;
1133}
1134
1135const CIRGenFunctionInfo &
1139 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1140 fpt);
1141}
1142
1143const CIRGenFunctionInfo &
1145 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1147 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1148 fnpt->getExtInfo(), RequiredArgs(0));
1149}
1150
1152 const CIRGenCallee &callee,
1154 const CallArgList &args,
1155 cir::CIRCallOpInterface *callOp,
1156 mlir::Location loc) {
1157 QualType retTy = funcInfo.getReturnType();
1158 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1159
1160 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1161
1163
1164 // Translate all of the arguments as necessary to match the CIR lowering.
1165 for (auto [argNo, arg, canQualArgType] :
1166 llvm::enumerate(args, funcInfo.argTypes())) {
1167
1168 // Insert a padding argument to ensure proper alignment.
1170
1171 mlir::Type argType = convertType(canQualArgType);
1172 if (!mlir::isa<cir::RecordType>(argType) &&
1173 !mlir::isa<cir::ComplexType>(argType)) {
1174 mlir::Value v;
1175 if (arg.isAggregate())
1176 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1177 v = arg.getKnownRValue().getValue();
1178
1179 // We might have to widen integers, but we should never truncate.
1180 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1181 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1182
1183 // If we have a pointer argument and there's an address space mismatch,
1184 // insert an address_space cast to match the expected function signature.
1185 if (argType != v.getType()) {
1186 auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
1187 auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
1188 if (argPtrTy && vPtrTy &&
1189 argPtrTy.getPointee() == vPtrTy.getPointee() &&
1190 argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
1191 v = performAddrSpaceCast(v, argPtrTy);
1192 }
1193 }
1194
1195 // If the argument doesn't match, perform a bitcast to coerce it. This
1196 // can happen due to trivial type mismatches.
1197 // TODO(cir): When getFunctionType is added, assert that this isn't
1198 // needed.
1200 cirCallArgs[argNo] = v;
1201 } else {
1202 Address src = Address::invalid();
1203 if (!arg.isAggregate()) {
1204 src = createMemTemp(arg.ty, loc, "coerce");
1205 arg.copyInto(*this, src, loc);
1206 } else {
1207 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1208 : arg.getKnownRValue().getAggregateAddress();
1209 }
1210
1211 // Fast-isel and the optimizer generally like scalar values better than
1212 // FCAs, so we flatten them if this is safe to do for this argument.
1213 mlir::Type srcTy = src.getElementType();
1214 // FIXME(cir): get proper location for each argument.
1215 mlir::Location argLoc = loc;
1216
1217 // If the source type is smaller than the destination type of the
1218 // coerce-to logic, copy the source value into a temp alloca the size
1219 // of the destination type to allow loading all of it. The bits past
1220 // the source value are left undef.
1221 // FIXME(cir): add data layout info and compare sizes instead of
1222 // matching the types.
1223 //
1224 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1225 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1226 // if (SrcSize < DstSize) {
1228 if (srcTy != argType) {
1229 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1230 } else {
1231 // FIXME(cir): this currently only runs when the types are exactly the
1232 // same, but should be when alloc sizes are the same, fix this as soon
1233 // as datalayout gets introduced.
1235 }
1236
1237 // assert(NumCIRArgs == STy.getMembers().size());
1238 // In LLVMGen: Still only pass the struct without any gaps but mark it
1239 // as such somehow.
1240 //
1241 // In CIRGen: Emit a load from the "whole" struct,
1242 // which shall be broken later by some lowering step into multiple
1243 // loads.
1245 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1246 }
1247 }
1248
1249 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1250 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1251
1253
1254 mlir::NamedAttrList attrs;
1255 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1256 mlir::NamedAttrList retAttrs;
1257 StringRef funcName;
1258 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1259 funcName = calleeFuncOp.getName();
1260
1263 cir::CallingConv callingConv;
1264 cir::SideEffect sideEffect;
1265 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1266 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1267 /*attrOnCallSite=*/true, /*isThunk=*/false);
1268
1269 cir::FuncType indirectFuncTy;
1270 mlir::Value indirectFuncVal;
1271 cir::FuncOp directFuncOp;
1272 if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
1273 directFuncOp = fnOp;
1274 } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
1275 // FIXME(cir): This peephole optimization avoids indirect calls for
1276 // builtins. This should be fixed in the builtin declaration instead by
1277 // not emitting an unecessary get_global in the first place.
1278 // However, this is also used for no-prototype functions.
1279 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1280 assert(globalOp && "undefined global function");
1281 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
1282 } else {
1283 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1284 calleePtr->getResultTypes();
1285 [[maybe_unused]] auto funcPtrTy =
1286 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1287 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1288 "expected pointer to function");
1289
1290 indirectFuncTy = cirFuncTy;
1291 indirectFuncVal = calleePtr->getResult(0);
1292 }
1293
1297
1298 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1299 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1300
1301 mlir::Location callLoc = loc;
1302 cir::CIRCallOpInterface theCall =
1303 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1304 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1305
1306 if (callOp)
1307 *callOp = theCall;
1308
1311
1312 mlir::Type retCIRTy = convertType(retTy);
1313 if (isa<cir::VoidType>(retCIRTy))
1314 return getUndefRValue(retTy);
1315 switch (getEvaluationKind(retTy)) {
1316 case cir::TEK_Aggregate: {
1317 Address destPtr = returnValue.getValue();
1318
1319 if (!destPtr.isValid())
1320 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1321
1322 mlir::ResultRange results = theCall->getOpResults();
1323 assert(results.size() <= 1 && "multiple returns from a call");
1324
1325 SourceLocRAIIObject loc{*this, callLoc};
1326 emitAggregateStore(results[0], destPtr);
1327 return RValue::getAggregate(destPtr);
1328 }
1329 case cir::TEK_Scalar: {
1330 mlir::ResultRange results = theCall->getOpResults();
1331 assert(results.size() == 1 && "unexpected number of returns");
1332
1333 // If the argument doesn't match, perform a bitcast to coerce it. This
1334 // can happen due to trivial type mismatches.
1335 if (results[0].getType() != retCIRTy)
1336 cgm.errorNYI(loc, "bitcast on function return value");
1337
1338 mlir::Region *region = builder.getBlock()->getParent();
1339 if (region != theCall->getParentRegion())
1340 cgm.errorNYI(loc, "function calls with cleanup");
1341
1342 return RValue::get(results[0]);
1343 }
1344 case cir::TEK_Complex: {
1345 mlir::ResultRange results = theCall->getOpResults();
1346 assert(!results.empty() &&
1347 "Expected at least one result for complex rvalue");
1348 return RValue::getComplex(results[0]);
1349 }
1350 }
1351 llvm_unreachable("Invalid evaluation kind");
1352}
1353
1355 mlir::Location loc) const {
1356 LValue dst = cgf.makeAddrLValue(addr, ty);
1357 if (!hasLV && rv.isScalar())
1358 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1359 else if (!hasLV && rv.isComplex())
1360 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1361 else
1362 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1363 isUsed = true;
1364}
1365
1366mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1367 cir::FuncOp callee,
1369 mlir::NamedAttrList attrs) {
1370
1371 // TODO(cir): set the calling convention to this runtime call.
1373
1374 cir::CallOp call = builder.createCallOp(loc, callee, args);
1375 assert(call->getNumResults() <= 1 &&
1376 "runtime functions have at most 1 result");
1377
1378 if (!attrs.empty())
1379 call->setAttrs(attrs);
1380
1381 if (call->getNumResults() == 0)
1382 return nullptr;
1383
1384 return call->getResult(0);
1385}
1386
1388 clang::QualType argType) {
1389 assert(argType->isReferenceType() == e->isGLValue() &&
1390 "reference binding to unmaterialized r-value!");
1391
1392 if (e->isGLValue()) {
1393 assert(e->getObjectKind() == OK_Ordinary);
1394 return args.add(emitReferenceBindingToExpr(e), argType);
1395 }
1396
1397 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1398
1399 // For callee-destructed parameters (trivial_abi, MS ABI), create an
1400 // aggregate temp and let the callee destroy it.
1401 if (argType->isRecordType() &&
1403 AggValueSlot slot = createAggTemp(argType, getLoc(e->getSourceRange()),
1405
1406 bool destroyedInCallee = true;
1407 if (const auto *rd = argType->getAsCXXRecordDecl())
1408 destroyedInCallee = rd->hasNonTrivialDestructor();
1409
1410 if (destroyedInCallee)
1412
1413 emitAggExpr(e, slot);
1414 RValue rv = slot.asRValue();
1415 args.add(rv, argType);
1416
1417 if (destroyedInCallee && getLangOpts().Exceptions)
1418 cgm.errorNYI(e->getSourceRange(),
1419 "callee-destructed param with exceptions");
1420 return;
1421 }
1422
1423 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1424 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1425 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1426 assert(lv.isSimple());
1427 args.addUncopiedAggregate(lv, argType);
1428 return;
1429 }
1430
1431 args.add(emitAnyExprToTemp(e), argType);
1432}
1433
1434QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1435 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1436 // implicitly widens null pointer constants that are arguments to varargs
1437 // functions to pointer-sized ints.
1438 if (!getTarget().getTriple().isOSWindows())
1439 return arg->getType();
1440
1441 assert(!cir::MissingFeatures::msabi());
1442 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1443 return arg->getType();
1444}
1445
1446/// Similar to emitAnyExpr(), however, the result will always be accessible
1447/// even if no aggregate location is provided.
1450
1452 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1454
1455 return emitAnyExpr(e, aggSlot);
1456}
1457
1459 CallArgList &args, PrototypeWrapper prototype,
1460 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1461 AbstractCallee callee, unsigned paramsToSkip) {
1463
1465
1466 // First, if a prototype was provided, use those argument types.
1467 bool isVariadic = false;
1468 if (prototype.p) {
1470
1471 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1472 isVariadic = fpt->isVariadic();
1474 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1475 fpt->param_type_end());
1476 }
1477
1478 // If we still have any arguments, emit them using the type of the argument.
1479 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1480 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1481 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1482
1483 // We must evaluate arguments from right to left in the MS C++ ABI, because
1484 // arguments are destroyed left to right in the callee. As a special case,
1485 // there are certain language constructs taht require left-to-right
1486 // evaluation, and in those cases we consider the evaluation order requirement
1487 // to trump the "destruction order is reverse construction order" guarantee.
1488 auto leftToRight = true;
1489 assert(!cir::MissingFeatures::msabi());
1490
1491 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1492 RValue emittedArg) {
1493 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1494 return;
1495 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1496 if (!ps)
1497 return;
1498
1500 assert(emittedArg.getValue() && "We emitted nothing for the arg?");
1501 mlir::Value v = evaluateOrEmitBuiltinObjectSize(
1502 arg, ps->getType(), cast<cir::IntType>(cgm.sizeTy),
1503 emittedArg.getValue(), ps->isDynamic());
1504 args.add(RValue::get(v), sizeTy);
1505 // When emitting right-to-left, the size arg was appended after the
1506 // pointer arg; swap them so the size follows the pointer in the final
1507 // argument list after the outer reverse.
1508 if (!leftToRight)
1509 std::iter_swap(args.rbegin(), std::next(args.rbegin()));
1510 };
1511
1512 // Evaluate each argument in the appropriate order.
1513 size_t callArgsStart = args.size();
1514 for (size_t i = 0; i != argTypes.size(); ++i) {
1515 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1516 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1517 size_t initialArgSize = args.size();
1518
1519 emitCallArg(args, *currentArg, argTypes[idx]);
1520
1521 // In particular, we depend on it being the last arg in Args, and the
1522 // objectsize bits depend on there only being one arg if !LeftToRight.
1523 assert(initialArgSize + 1 == args.size() &&
1524 "The code below depends on only adding one arg per emitCallArg");
1525 (void)initialArgSize;
1526
1527 // Since pointer argument are never emitted as LValue, it is safe to emit
1528 // non-null argument check for r-value only.
1529 if (!args.back().hasLValue()) {
1530 RValue rvArg = args.back().getKnownRValue();
1532 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1533 }
1534
1535 if (!leftToRight)
1536 std::reverse(args.begin() + callArgsStart, args.end());
1537 }
1538}
1539
1540// FIXME(cir): This is identical to the version from classic-codegen, we should
1541// figure out how to move this to a common location.
1543 CXXCtorType type) {
1544 // Parameters are unnecessary if we're constructing a base class subobject
1545 // and the inherited constructor lives in a virtual base.
1546 return type == Ctor_Complete ||
1547 !inherited.getShadowDecl()->constructsVirtualBase() ||
1549}
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:3777
mlir::Type getElementType() const
Definition Address.h:123
static Address invalid()
Definition Address.h:74
bool isValid() const
Definition Address.h:75
An aggregate value slot.
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
virtual CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty, SourceLocation loc)=0
Build a virtual function pointer in the ABI-specific way.
Abstract information about a function or function prototype.
Definition CIRGenCall.h:27
clang::GlobalDecl getCalleeDecl() const
Definition CIRGenCall.h:44
const clang::FunctionProtoType * getCalleeFunctionProtoType() const
Definition CIRGenCall.h:41
CIRGenCalleeInfo getAbstractInfo() const
Definition CIRGenCall.h:140
clang::GlobalDecl getVirtualMethodDecl() const
Definition CIRGenCall.h:170
CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const
If this is a delayed callee computation of some sort, prepare a concrete callee.
Address getThisAddress() const
Definition CIRGenCall.h:175
cir::FuncType getVirtualFunctionType() const
Definition CIRGenCall.h:180
const clang::CallExpr * getVirtualCallExpr() const
Definition CIRGenCall.h:165
mlir::Operation * getFunctionPointer() const
Definition CIRGenCall.h:147
cir::ABIArgInfo getReturnInfo() const
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, bool instanceMethod, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
llvm::MutableArrayRef< CanQualType > argTypes()
llvm::ArrayRef< CanQualType > requiredArguments() const
llvm::ArrayRef< CanQualType > arguments() const
const_arg_iterator argTypesBegin() const
An abstract representation of regular/ObjC call/message targets.
const clang::ParmVarDecl * getParamDecl(unsigned I) const
void emitCallArgs(CallArgList &args, PrototypeWrapper prototype, llvm::iterator_range< clang::CallExpr::const_arg_iterator > argRange, AbstractCallee callee=AbstractCallee(), unsigned paramsToSkip=0)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
RValue convertTempToRValue(Address addr, clang::QualType type, clang::SourceLocation loc)
Given the address of a temporary variable, produce an r-value of its type.
CIRGenTypes & getTypes() const
const clang::LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitAggregateStore(mlir::Value value, Address dest)
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
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 isVirtual() const
Definition DeclCXX.h:2187
bool isInstance() const
Definition DeclCXX.h:2159
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:3330
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:4544
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4940
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5362
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5669
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5761
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4669
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4558
ExtInfo getExtInfo() const
Definition TypeBase.h:4914
QualType getReturnType() const
Definition TypeBase.h:4898
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:4392
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:2961
QualType getCanonicalType() const
Definition TypeBase.h:8488
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:9039
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:8697
bool isScalarType() const
Definition TypeBase.h:9145
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:8948
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isMemberPointerType() const
Definition TypeBase.h:8754
bool isObjectType() const
Determine whether this type is an object type.
Definition TypeBase.h:2563
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:2976
bool isAnyPointerType() const
Definition TypeBase.h:8681
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9266
bool isNullPtrType() const
Definition TypeBase.h:9076
bool isRecordType() const
Definition TypeBase.h:8800
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:2830
Represents a GCC generic vector type.
Definition TypeBase.h:4230
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