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 getNaturalPointeeTypeAlignment(retTy).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(
661 mlir::LLVM::LLVMDialect::getAlignAttrName(),
662 builder.getI64IntegerAttr(
663 getNaturalPointeeTypeAlignment(thisPtrTy).getQuantity()));
664
665 // TODO(cir): the classic codegen has a recently-added bunch of logic for
666 // 'dead_on_return' as an attribute. This both doesn't exist in the LLVM
667 // dialect, and is 'too new' at the time of writing this to be considered
668 // stable enough here. For now, we'll leave this as a TODO so that when
669 // we come back, it is hopefully a more stabilized implementation.
670 }
671 }
672
673 // TODO(cir): the logic between 'this', return, and normal arguments hsould
674 // probably be merged at one point, however the logic is unfortunately mildly
675 // different between each in classic codegen, so trying to do anything like
676 // that seems risky at the moment. At one point we should evaluate if at least
677 // dereferenceable, nonnull, and align can be combined.
678 const cir::CIRDataLayout &layout = getDataLayout();
679 for (const auto &[argAttrList, argCanType] :
680 llvm::zip_equal(argAttrs, info.arguments())) {
682 QualType argType = argCanType;
683 const cir::ABIArgInfo argInfo = cir::ABIArgInfo::getDirect();
684
685 if (codeGenOpts.EnableNoundefAttrs &&
686 determineNoUndef(argType, getTypes(), layout, argInfo))
687 argAttrList.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(),
688 mlir::UnitAttr::get(&getMLIRContext()));
689
691 // TODO(cir): there is plenty of other attributes here added due to ABI
692 // decisions. While these probably won't end up here, we note that the
693 // classic codegen does it here and perhaps we should pay attention to that.
694
695 if (const auto *refTy = argType->getAs<ReferenceType>()) {
696 QualType pointeeTy = refTy->getPointeeType();
697 if (!pointeeTy->isIncompleteType() && pointeeTy->isConstantSizeType())
698 argAttrList.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
699 builder.getI64IntegerAttr(
700 getMinimumObjectSize(pointeeTy).getQuantity()));
701 if (getTypes().getTargetAddressSpace(pointeeTy) == 0 &&
702 !codeGenOpts.NullPointerIsValid)
703 argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
704 mlir::UnitAttr::get(&getMLIRContext()));
705 if (pointeeTy->isObjectType())
706 argAttrList.set(
707 mlir::LLVM::LLVMDialect::getAlignAttrName(),
708 builder.getI64IntegerAttr(
709 getNaturalPointeeTypeAlignment(argType).getQuantity()));
710 }
711 }
712}
713
714/// Returns the canonical formal type of the given C++ method.
720
721/// Adds the formal parameters in FPT to the given prefix. If any parameter in
722/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
723/// TODO(cir): this should be shared with LLVM codegen
724static void appendParameterTypes(const CIRGenTypes &cgt,
728 // Fast path: don't touch param info if we don't need to.
729 if (!fpt->hasExtParameterInfos()) {
730 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
731 return;
732 }
733
734 cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
735}
736
737const CIRGenFunctionInfo &
739 auto *md = cast<CXXMethodDecl>(gd.getDecl());
740
742 argTypes.push_back(deriveThisType(md->getParent(), md));
743
744 bool passParams = true;
745
746 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
747 // A base class inheriting constructor doesn't get forwarded arguments
748 // needed to construct a virtual base (or base class thereof)
749 if (cd->getInheritedConstructor())
750 cgm.errorNYI(cd->getSourceRange(),
751 "arrangeCXXStructorDeclaration: inheriting constructor");
752 }
753
755
756 if (passParams)
757 appendParameterTypes(*this, argTypes, fpt);
758
759 // The structor signature may include implicit parameters.
760 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
761 theCXXABI.buildStructorSignature(gd, argTypes);
763
764 RequiredArgs required =
765 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
767
768 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
769 : theCXXABI.hasMostDerivedReturn(gd)
770 ? astContext.VoidPtrTy
771 : astContext.VoidTy;
772
773 assert(!theCXXABI.hasThisReturn(gd) &&
774 "Please send PR with a test and remove this");
775
778
779 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
780 fpt->getExtInfo(), required);
781}
782
783/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
784/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
785/// indicates that there is no meaningful 'this' type, and a null `md` can occur
786/// when calling a method pointer.
788 const CXXMethodDecl *md) {
789 CanQualType recTy;
790 if (rd) {
792 } else {
793 // This can happen with the MS ABI. It shouldn't need anything more than
794 // setting recTy to VoidTy here, but we're flagging it for now because we
795 // don't have the full handling implemented.
796 cgm.errorNYI("deriveThisType: no record decl");
797 recTy = getASTContext().VoidTy;
798 }
799
800 if (md)
801 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
802 recTy, md->getMethodQualifiers().getAddressSpace()));
803 return getASTContext().getPointerType(recTy);
804}
805
806/// Arrange the CIR function layout for a value of the given function type, on
807/// top of any implicit parameters already stored.
808static const CIRGenFunctionInfo &
809arrangeCIRFunctionInfo(CIRGenTypes &cgt, bool instanceMethod,
813 RequiredArgs required =
816 appendParameterTypes(cgt, prefix, fpt);
817 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
818 return cgt.arrangeCIRFunctionInfo(resultType, instanceMethod, prefix,
819 fpt->getExtInfo(), required);
820}
821
823 const VarDecl *param,
824 SourceLocation loc) {
825 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
826 // We need to turn that into an r-value suitable for emitCall
827 Address local = getAddrOfLocalVar(param);
828
829 QualType type = param->getType();
830
831 if (type->getAsCXXRecordDecl()) {
832 cgm.errorNYI(param->getSourceRange(),
833 "emitDelegateCallArg: record argument");
834 return;
835 }
836
837 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
838 // argument needs to be the original pointer.
839 if (type->isReferenceType()) {
840 args.add(
841 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
842 type);
843 } else if (getLangOpts().ObjCAutoRefCount) {
844 cgm.errorNYI(param->getSourceRange(),
845 "emitDelegateCallArg: ObjCAutoRefCount");
846 // For the most part, we just need to load the alloca, except that aggregate
847 // r-values are actually pointers to temporaries.
848 } else {
849 args.add(convertTempToRValue(local, type, loc), type);
850 }
851
852 // Deactivate the cleanup for the callee-destructed param that was pushed.
854 if (type->isRecordType() &&
855 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
856 param->needsDestruction(getContext())) {
857 cgm.errorNYI(param->getSourceRange(),
858 "emitDelegateCallArg: callee-destructed param");
859 }
860}
861
862static const CIRGenFunctionInfo &
864 const CallArgList &args,
865 const FunctionType *fnType) {
866
868
869 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
870 if (proto->isVariadic())
871 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
872 if (proto->hasExtParameterInfos())
873 cgm.errorNYI("call to functions with extra parameter info");
876 cgm.errorNYI("call to function without a prototype");
877
879 for (const CallArg &arg : args)
880 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
881
883
885 return cgt.arrangeCIRFunctionInfo(retType, /*isInstanceMethod=*/false,
886 argTypes, fnType->getExtInfo(), required);
887}
888
889/// Arrange a call to a C++ method, passing the given arguments.
890///
891/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
892/// parameter.
893/// passProtoArgs indicates whether `args` has args for the parameters in the
894/// given CXXConstructorDecl.
896 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
897 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
898
899 // FIXME: Kill copy.
901 for (const auto &arg : args)
902 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
903
904 // +1 for implicit this, which should always be args[0]
905 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
906
908 RequiredArgs required = passProtoArgs
910 fpt, totalPrefixArgs + extraSuffixArgs)
912
913 GlobalDecl gd(d, ctorKind);
914 if (theCXXABI.hasThisReturn(gd))
915 cgm.errorNYI(d->getSourceRange(),
916 "arrangeCXXConstructorCall: hasThisReturn");
917 if (theCXXABI.hasMostDerivedReturn(gd))
918 cgm.errorNYI(d->getSourceRange(),
919 "arrangeCXXConstructorCall: hasMostDerivedReturn");
920 CanQualType resultType = astContext.VoidTy;
921
924
925 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/true, argTypes,
926 fpt->getExtInfo(), required);
927}
928
929/// Arrange a call to a C++ method, passing the given arguments.
930///
931/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
932/// does not count `this`.
934 const CallArgList &args, const FunctionProtoType *proto,
935 RequiredArgs required, unsigned numPrefixArgs) {
937 assert(numPrefixArgs + 1 <= args.size() &&
938 "Emitting a call with less args than the required prefix?");
939
940 // FIXME: Kill copy.
942 for (const CallArg &arg : args)
943 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
944
948 /*isInstanceMethod=*/true, argTypes, proto->getExtInfo(), required);
949}
950
951const CIRGenFunctionInfo &
953 const FunctionType *fnType) {
954 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
955}
956
957/// Arrange the argument and result information for a declaration or definition
958/// of the given C++ non-static member function. The member function must be an
959/// ordinary function, i.e. not a constructor or destructor.
960const CIRGenFunctionInfo &
962 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
963 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
964
965 auto prototype =
968
969 if (md->isInstance()) {
970 // The abstract case is perfectly fine.
971 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
972 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
973 }
974
975 return arrangeFreeFunctionType(prototype);
976}
977
978/// Arrange the argument and result information for a call to an unknown C++
979/// non-static member function of the given abstract type. (A null RD means we
980/// don't have any meaningful "this" argument type, so fall back to a generic
981/// pointer type). The member fucntion must be an ordinary function, i.e. not a
982/// constructor or destructor.
983const CIRGenFunctionInfo &
985 const FunctionProtoType *fpt,
986 const CXXMethodDecl *md) {
988
989 // Add the 'this' pointer.
990 argTypes.push_back(deriveThisType(rd, md));
991
993 return ::arrangeCIRFunctionInfo(
994 *this, /*isInstanceMethod=*/true, argTypes,
996}
997
998/// Arrange the argument and result information for the declaration or
999/// definition of the given function.
1000const CIRGenFunctionInfo &
1002 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
1003 if (md->isInstance())
1004 return arrangeCXXMethodDeclaration(md);
1005
1007
1008 assert(isa<FunctionType>(funcTy));
1009 // TODO: setCUDAKernelCallingConvention
1011
1012 // When declaring a function without a prototype, always use a non-variadic
1013 // type.
1014 if (CanQual<FunctionNoProtoType> noProto =
1015 funcTy.getAs<FunctionNoProtoType>()) {
1018 return arrangeCIRFunctionInfo(noProto->getReturnType(),
1019 /*isInstanceMethod=*/false, {},
1020 noProto->getExtInfo(), RequiredArgs::All);
1021 }
1022
1024}
1025
1026RValue CallArg::getRValue(CIRGenFunction &cgf, mlir::Location loc) const {
1027 if (!hasLV)
1028 return rv;
1029 LValue copy = cgf.makeAddrLValue(cgf.createMemTemp(ty, loc), ty);
1031 lv.isVolatile());
1032 isUsed = true;
1033 return RValue::getAggregate(copy.getAddress());
1034}
1035
1037 SourceLocation argLoc,
1038 AbstractCallee ac, unsigned paramNum) {
1039 if (!ac.getDecl() || !(sanOpts.has(SanitizerKind::NonnullAttribute) ||
1040 sanOpts.has(SanitizerKind::NullabilityArg)))
1041 return;
1042 cgm.errorNYI("non-null arg check is NYI");
1043}
1044
1045static cir::CIRCallOpInterface
1046emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
1047 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
1048 cir::FuncOp directFuncOp,
1049 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
1050 const mlir::NamedAttrList &attrs,
1052 const mlir::NamedAttrList &retAttrs) {
1053 CIRGenBuilderTy &builder = cgf.getBuilder();
1054
1056
1057 assert(builder.getInsertionBlock() && "expected valid basic block");
1058
1059 cir::CallOp op;
1060 if (indirectFuncTy) {
1061 // TODO(cir): Set calling convention for indirect calls.
1063 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
1064 cirCallArgs, attrs, argAttrs, retAttrs);
1065 } else {
1066 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs,
1067 argAttrs, retAttrs);
1068 }
1069
1070 return op;
1071}
1072
1073const CIRGenFunctionInfo &
1077 return ::arrangeCIRFunctionInfo(*this, /*isInstanceMethod=*/false, argTypes,
1078 fpt);
1079}
1080
1081const CIRGenFunctionInfo &
1083 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
1085 return arrangeCIRFunctionInfo(resultType, /*isInstanceMethod=*/false, {},
1086 fnpt->getExtInfo(), RequiredArgs(0));
1087}
1088
1090 const CIRGenCallee &callee,
1092 const CallArgList &args,
1093 cir::CIRCallOpInterface *callOp,
1094 mlir::Location loc) {
1095 QualType retTy = funcInfo.getReturnType();
1096 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
1097
1098 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
1099
1101
1102 // Translate all of the arguments as necessary to match the CIR lowering.
1103 for (auto [argNo, arg, canQualArgType] :
1104 llvm::enumerate(args, funcInfo.argTypes())) {
1105
1106 // Insert a padding argument to ensure proper alignment.
1108
1109 mlir::Type argType = convertType(canQualArgType);
1110 if (!mlir::isa<cir::RecordType>(argType) &&
1111 !mlir::isa<cir::ComplexType>(argType)) {
1112 mlir::Value v;
1113 if (arg.isAggregate())
1114 cgm.errorNYI(loc, "emitCall: aggregate call argument");
1115 v = arg.getKnownRValue().getValue();
1116
1117 // We might have to widen integers, but we should never truncate.
1118 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
1119 cgm.errorNYI(loc, "emitCall: widening integer call argument");
1120
1121 // If the argument doesn't match, perform a bitcast to coerce it. This
1122 // can happen due to trivial type mismatches.
1123 // TODO(cir): When getFunctionType is added, assert that this isn't
1124 // needed.
1126 cirCallArgs[argNo] = v;
1127 } else {
1128 Address src = Address::invalid();
1129 if (!arg.isAggregate()) {
1130 src = createMemTemp(arg.ty, loc, "coerce");
1131 arg.copyInto(*this, src, loc);
1132 } else {
1133 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
1134 : arg.getKnownRValue().getAggregateAddress();
1135 }
1136
1137 // Fast-isel and the optimizer generally like scalar values better than
1138 // FCAs, so we flatten them if this is safe to do for this argument.
1139 mlir::Type srcTy = src.getElementType();
1140 // FIXME(cir): get proper location for each argument.
1141 mlir::Location argLoc = loc;
1142
1143 // If the source type is smaller than the destination type of the
1144 // coerce-to logic, copy the source value into a temp alloca the size
1145 // of the destination type to allow loading all of it. The bits past
1146 // the source value are left undef.
1147 // FIXME(cir): add data layout info and compare sizes instead of
1148 // matching the types.
1149 //
1150 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
1151 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
1152 // if (SrcSize < DstSize) {
1154 if (srcTy != argType) {
1155 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
1156 } else {
1157 // FIXME(cir): this currently only runs when the types are exactly the
1158 // same, but should be when alloc sizes are the same, fix this as soon
1159 // as datalayout gets introduced.
1161 }
1162
1163 // assert(NumCIRArgs == STy.getMembers().size());
1164 // In LLVMGen: Still only pass the struct without any gaps but mark it
1165 // as such somehow.
1166 //
1167 // In CIRGen: Emit a load from the "whole" struct,
1168 // which shall be broken later by some lowering step into multiple
1169 // loads.
1171 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
1172 }
1173 }
1174
1175 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
1176 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
1177
1179
1180 mlir::NamedAttrList attrs;
1181 std::vector<mlir::NamedAttrList> argAttrs(funcInfo.arguments().size());
1182 mlir::NamedAttrList retAttrs;
1183 StringRef funcName;
1184 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
1185 funcName = calleeFuncOp.getName();
1186
1189 cir::CallingConv callingConv;
1190 cir::SideEffect sideEffect;
1191 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
1192 attrs, argAttrs, retAttrs, callingConv, sideEffect,
1193 /*attrOnCallSite=*/true, /*isThunk=*/false);
1194
1195 cir::FuncType indirectFuncTy;
1196 mlir::Value indirectFuncVal;
1197 cir::FuncOp directFuncOp;
1198 if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
1199 directFuncOp = fnOp;
1200 } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
1201 // FIXME(cir): This peephole optimization avoids indirect calls for
1202 // builtins. This should be fixed in the builtin declaration instead by
1203 // not emitting an unecessary get_global in the first place.
1204 // However, this is also used for no-prototype functions.
1205 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
1206 assert(globalOp && "undefined global function");
1207 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
1208 } else {
1209 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
1210 calleePtr->getResultTypes();
1211 [[maybe_unused]] auto funcPtrTy =
1212 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
1213 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
1214 "expected pointer to function");
1215
1216 indirectFuncTy = cirFuncTy;
1217 indirectFuncVal = calleePtr->getResult(0);
1218 }
1219
1223
1224 bool cannotThrow = attrs.getNamed("nothrow").has_value();
1225 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
1226
1227 mlir::Location callLoc = loc;
1228 cir::CIRCallOpInterface theCall =
1229 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
1230 cirCallArgs, isInvoke, attrs, argAttrs, retAttrs);
1231
1232 if (callOp)
1233 *callOp = theCall;
1234
1237
1238 mlir::Type retCIRTy = convertType(retTy);
1239 if (isa<cir::VoidType>(retCIRTy))
1240 return getUndefRValue(retTy);
1241 switch (getEvaluationKind(retTy)) {
1242 case cir::TEK_Aggregate: {
1243 Address destPtr = returnValue.getValue();
1244
1245 if (!destPtr.isValid())
1246 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
1247
1248 mlir::ResultRange results = theCall->getOpResults();
1249 assert(results.size() <= 1 && "multiple returns from a call");
1250
1251 SourceLocRAIIObject loc{*this, callLoc};
1252 emitAggregateStore(results[0], destPtr);
1253 return RValue::getAggregate(destPtr);
1254 }
1255 case cir::TEK_Scalar: {
1256 mlir::ResultRange results = theCall->getOpResults();
1257 assert(results.size() == 1 && "unexpected number of returns");
1258
1259 // If the argument doesn't match, perform a bitcast to coerce it. This
1260 // can happen due to trivial type mismatches.
1261 if (results[0].getType() != retCIRTy)
1262 cgm.errorNYI(loc, "bitcast on function return value");
1263
1264 mlir::Region *region = builder.getBlock()->getParent();
1265 if (region != theCall->getParentRegion())
1266 cgm.errorNYI(loc, "function calls with cleanup");
1267
1268 return RValue::get(results[0]);
1269 }
1270 case cir::TEK_Complex: {
1271 mlir::ResultRange results = theCall->getOpResults();
1272 assert(!results.empty() &&
1273 "Expected at least one result for complex rvalue");
1274 return RValue::getComplex(results[0]);
1275 }
1276 }
1277 llvm_unreachable("Invalid evaluation kind");
1278}
1279
1281 mlir::Location loc) const {
1282 LValue dst = cgf.makeAddrLValue(addr, ty);
1283 if (!hasLV && rv.isScalar())
1284 cgf.cgm.errorNYI(loc, "copyInto scalar value");
1285 else if (!hasLV && rv.isComplex())
1286 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
1287 else
1288 cgf.cgm.errorNYI(loc, "copyInto hasLV");
1289 isUsed = true;
1290}
1291
1292mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
1293 cir::FuncOp callee,
1295 mlir::NamedAttrList attrs) {
1296 // TODO(cir): set the calling convention to this runtime call.
1298
1299 cir::CallOp call = builder.createCallOp(loc, callee, args);
1300 assert(call->getNumResults() <= 1 &&
1301 "runtime functions have at most 1 result");
1302
1303 if (!attrs.empty())
1304 call->setAttrs(attrs);
1305
1306 if (call->getNumResults() == 0)
1307 return nullptr;
1308
1309 return call->getResult(0);
1310}
1311
1313 clang::QualType argType) {
1314 assert(argType->isReferenceType() == e->isGLValue() &&
1315 "reference binding to unmaterialized r-value!");
1316
1317 if (e->isGLValue()) {
1318 assert(e->getObjectKind() == OK_Ordinary);
1319 return args.add(emitReferenceBindingToExpr(e), argType);
1320 }
1321
1322 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
1323
1324 // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
1325 // However, we still have to push an EH-only cleanup in case we unwind before
1326 // we make it to the call.
1327 if (argType->isRecordType() &&
1329 assert(!cir::MissingFeatures::msabi());
1330 cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
1331 }
1332
1333 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
1334 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
1335 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
1336 assert(lv.isSimple());
1337 args.addUncopiedAggregate(lv, argType);
1338 return;
1339 }
1340
1341 args.add(emitAnyExprToTemp(e), argType);
1342}
1343
1344QualType CIRGenFunction::getVarArgType(const Expr *arg) {
1345 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
1346 // implicitly widens null pointer constants that are arguments to varargs
1347 // functions to pointer-sized ints.
1348 if (!getTarget().getTriple().isOSWindows())
1349 return arg->getType();
1350
1351 assert(!cir::MissingFeatures::msabi());
1352 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
1353 return arg->getType();
1354}
1355
1356/// Similar to emitAnyExpr(), however, the result will always be accessible
1357/// even if no aggregate location is provided.
1360
1362 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
1364
1365 return emitAnyExpr(e, aggSlot);
1366}
1367
1369 CallArgList &args, PrototypeWrapper prototype,
1370 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
1371 AbstractCallee callee, unsigned paramsToSkip) {
1373
1375
1376 // First, if a prototype was provided, use those argument types.
1377 bool isVariadic = false;
1378 if (prototype.p) {
1380
1381 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
1382 isVariadic = fpt->isVariadic();
1384 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
1385 fpt->param_type_end());
1386 }
1387
1388 // If we still have any arguments, emit them using the type of the argument.
1389 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
1390 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
1391 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
1392
1393 // We must evaluate arguments from right to left in the MS C++ ABI, because
1394 // arguments are destroyed left to right in the callee. As a special case,
1395 // there are certain language constructs taht require left-to-right
1396 // evaluation, and in those cases we consider the evaluation order requirement
1397 // to trump the "destruction order is reverse construction order" guarantee.
1398 auto leftToRight = true;
1399 assert(!cir::MissingFeatures::msabi());
1400
1401 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
1402 RValue emittedArg) {
1403 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
1404 return;
1405 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
1406 if (!ps)
1407 return;
1408
1410 cgm.errorNYI("emit implicit object size for call arg");
1411 };
1412
1413 // Evaluate each argument in the appropriate order.
1414 size_t callArgsStart = args.size();
1415 for (size_t i = 0; i != argTypes.size(); ++i) {
1416 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
1417 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
1418 size_t initialArgSize = args.size();
1419
1420 emitCallArg(args, *currentArg, argTypes[idx]);
1421
1422 // In particular, we depend on it being the last arg in Args, and the
1423 // objectsize bits depend on there only being one arg if !LeftToRight.
1424 assert(initialArgSize + 1 == args.size() &&
1425 "The code below depends on only adding one arg per emitCallArg");
1426 (void)initialArgSize;
1427
1428 // Since pointer argument are never emitted as LValue, it is safe to emit
1429 // non-null argument check for r-value only.
1430 if (!args.back().hasLValue()) {
1431 RValue rvArg = args.back().getKnownRValue();
1433 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
1434 }
1435
1436 if (!leftToRight)
1437 std::reverse(args.begin() + callArgsStart, args.end());
1438 }
1439}
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.
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
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:3772
mlir::Type getElementType() const
Definition Address.h:123
static Address invalid()
Definition Address.h:74
bool isValid() const
Definition Address.h:75
An aggregate value slot.
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.
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...
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: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:3325
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:2015
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:4935
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5357
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5664
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5756
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4664
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4553
ExtInfo getExtInfo() const
Definition TypeBase.h:4909
QualType getReturnType() const
Definition TypeBase.h:4893
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
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:4387
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2912
QualType getCanonicalType() const
Definition TypeBase.h:8483
LangAS getAddressSpace() const
Definition TypeBase.h:571
bool isParamDestroyedInCallee() const
Definition Decl.h:4492
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
bool isVoidType() const
Definition TypeBase.h:9034
bool isVoidPointerType() const
Definition Type.cpp:714
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition Type.cpp:2470
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8692
bool isScalarType() const
Definition TypeBase.h:9140
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
bool isBitIntType() const
Definition TypeBase.h:8943
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isMemberPointerType() const
Definition TypeBase.h:8749
bool isObjectType() const
Determine whether this type is an object type.
Definition TypeBase.h:2558
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2480
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2971
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
bool isNullPtrType() const
Definition TypeBase.h:9071
bool isRecordType() const
Definition TypeBase.h:8795
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp: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:4225
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