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