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"
19
20using namespace clang;
21using namespace clang::CIRGen;
22
26 RequiredArgs required) {
27 // The first slot allocated for arg type slot is for the return value.
28 void *buffer = operator new(
29 totalSizeToAlloc<CanQualType>(argTypes.size() + 1));
30
32
33 CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
34
35 fi->noReturn = info.getNoReturn();
36
37 fi->required = required;
38 fi->numArgs = argTypes.size();
39
40 fi->getArgTypes()[0] = resultType;
41 std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());
43
44 return fi;
45}
46
51
53 mlir::Type resultType = convertType(info.getReturnType());
55 argTypes.reserve(info.getNumRequiredArgs());
56
57 for (const CanQualType &argType : info.requiredArguments())
58 argTypes.push_back(convertType(argType));
59
60 return cir::FuncType::get(argTypes,
61 (resultType ? resultType : builder.getVoidTy()),
62 info.isVariadic());
63}
64
67 const FunctionProtoType *fpt = md->getType()->getAs<FunctionProtoType>();
68
69 if (!isFuncTypeConvertible(fpt))
70 cgm.errorNYI("getFunctionTypeForVTable: non-convertible function type");
71
72 return getFunctionType(gd);
73}
74
76 if (isVirtual()) {
77 const CallExpr *ce = getVirtualCallExpr();
80 ce ? ce->getBeginLoc() : SourceLocation());
81 }
82 return *this;
83}
84
85void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
86 // In classic codegen:
87 // Function to store a first-class aggregate into memory. We prefer to
88 // store the elements rather than the aggregate to be more friendly to
89 // fast-isel.
90 // In CIR codegen:
91 // Emit the most simple cir.store possible (e.g. a store for a whole
92 // record), which can later be broken down in other CIR levels (or prior
93 // to dialect codegen).
94
95 // Stored result for the callers of this function expected to be in the same
96 // scope as the value, don't make assumptions about current insertion point.
97 mlir::OpBuilder::InsertionGuard guard(builder);
98 builder.setInsertionPointAfter(value.getDefiningOp());
99 builder.createStore(*currSrcLoc, value, dest);
100}
101
103 mlir::NamedAttrList &attrs,
104 const FunctionProtoType *fpt) {
105 if (!fpt)
106 return;
107
109 fpt->isNothrow())
110 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
111 mlir::UnitAttr::get(builder.getContext()));
112}
113
114/// Construct the CIR attribute list of a function or call.
115void CIRGenModule::constructAttributeList(llvm::StringRef name,
116 const CIRGenFunctionInfo &info,
117 CIRGenCalleeInfo calleeInfo,
118 mlir::NamedAttrList &attrs,
119 cir::CallingConv &callingConv,
120 cir::SideEffect &sideEffect,
121 bool attrOnCallSite, bool isThunk) {
123 sideEffect = cir::SideEffect::All;
124
125 auto addUnitAttr = [&](llvm::StringRef name) {
126 attrs.set(name, mlir::UnitAttr::get(&getMLIRContext()));
127 };
128
129 if (info.isNoReturn())
130 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
131
132 // TODO(cir): Implement/check the CSME Nonsecure call attribute here. This
133 // requires being in CSME mode.
134
136 calleeInfo.getCalleeFunctionProtoType());
137
138 const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
139
140 if (targetDecl) {
141 if (targetDecl->hasAttr<NoThrowAttr>())
142 addUnitAttr(cir::CIRDialect::getNoThrowAttrName());
143 // TODO(cir): This is actually only possible if targetDecl isn't a
144 // declarator, which ObjCMethodDecl seems to be the only way to get this to
145 // happen. We're including it here for completeness, but we should add a
146 // test for this when we start generating ObjectiveC.
147 if (targetDecl->hasAttr<NoReturnAttr>())
148 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
149 if (targetDecl->hasAttr<ReturnsTwiceAttr>())
150 addUnitAttr(cir::CIRDialect::getReturnsTwiceAttrName());
151 if (targetDecl->hasAttr<ColdAttr>())
152 addUnitAttr(cir::CIRDialect::getColdAttrName());
153 if (targetDecl->hasAttr<HotAttr>())
154 addUnitAttr(cir::CIRDialect::getHotAttrName());
155 if (targetDecl->hasAttr<NoDuplicateAttr>())
156 addUnitAttr(cir::CIRDialect::getNoDuplicatesAttrName());
157 if (targetDecl->hasAttr<ConvergentAttr>())
158 addUnitAttr(cir::CIRDialect::getConvergentAttrName());
159
160 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
162 getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
163
164 // TODO(cir): When doing 'return attrs' we need to cover the 'NoAlias' for
165 // global allocation functions here.
167
168 const CXXMethodDecl *md = dyn_cast<CXXMethodDecl>(func);
169 bool isVirtualCall = md && md->isVirtual();
170
171 // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
172 // virtual function. These attributes are not inherited by overloads.
173 if (!(attrOnCallSite && isVirtualCall)) {
174 if (func->isNoReturn())
175 addUnitAttr(cir::CIRDialect::getNoReturnAttrName());
176 // TODO(cir): Set NoBuiltinAttr here.
177 }
178 }
179
181
182 // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
183 if (targetDecl->hasAttr<ConstAttr>()) {
184 // gcc specifies that 'const' functions have greater restrictions than
185 // 'pure' functions, so they also cannot have infinite loops.
186 sideEffect = cir::SideEffect::Const;
187 } else if (targetDecl->hasAttr<PureAttr>()) {
188 // gcc specifies that 'pure' functions cannot have infinite loops.
189 sideEffect = cir::SideEffect::Pure;
190 }
191
192 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
193 cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
194
195 // TODO(cir): When doing 'return attrs' we need to cover the Restrict and
196 // ReturnsNonNull attributes here.
197 if (targetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
198 addUnitAttr(cir::CIRDialect::getNoCallerSavedRegsAttrName());
199 // TODO(cir): Implement 'NoCFCheck' attribute here. This requires
200 // fcf-protection mode.
201 if (targetDecl->hasAttr<LeafAttr>())
202 addUnitAttr(cir::CIRDialect::getNoCallbackAttrName());
203 // TODO(cir): Implement 'BPFFastCall' attribute here. This requires C, and
204 // the BPF target.
205
206 // TODO(cir): Detecting 'OptimizeNone' is done here in classic codegen, when
207 // we figure out when to do that, we should do it here.
208 // TODO(cir): AllocSize attr should be done here, but it has some additional
209 // work with forming the correct value for it. Typically this calls into
210 // LLVM to set it correctly, which flattens the elem size and num-elems into
211 // a single value. CIR should probably represent these as two values and
212 // handle the combination during lowering by calling into LLVM.
213
214 // TODO(cir): Quite a few CUDA and OpenCL attributes are added here, like
215 // uniform-work-group-size.
216
217 // TODO(cir): we should also do 'aarch64_pstate_sm_body' here.
218
219 if (auto *modularFormat = targetDecl->getAttr<ModularFormatAttr>()) {
220 FormatAttr *format = targetDecl->getAttr<FormatAttr>();
221 StringRef type = format->getType()->getName();
222 std::string formatIdx = std::to_string(format->getFormatIdx());
223 std::string firstArg = std::to_string(format->getFirstArg());
225 type, formatIdx, firstArg,
226 modularFormat->getModularImplFn()->getName(),
227 modularFormat->getImplName()};
228 llvm::append_range(args, modularFormat->aspects());
229 attrs.set(cir::CIRDialect::getModularFormatAttrName(),
230 builder.getStringAttr(llvm::join(args, ",")));
231 }
232
233 // TODO(cir): We should set nobuiltin and default function attrs here.
234
235 // TODO(cir): There is another region of `if (targetDecl)` that handles
236 // removing some attributes that are necessary modifications of the
237 // default-function attrs. We should do that here.
238 }
240}
241
242/// Returns the canonical formal type of the given C++ method.
248
249/// Adds the formal parameters in FPT to the given prefix. If any parameter in
250/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
251/// TODO(cir): this should be shared with LLVM codegen
252static void appendParameterTypes(const CIRGenTypes &cgt,
256 // Fast path: don't touch param info if we don't need to.
257 if (!fpt->hasExtParameterInfos()) {
258 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
259 return;
260 }
261
262 cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
263}
264
265const CIRGenFunctionInfo &
267 auto *md = cast<CXXMethodDecl>(gd.getDecl());
268
270 argTypes.push_back(deriveThisType(md->getParent(), md));
271
272 bool passParams = true;
273
274 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
275 // A base class inheriting constructor doesn't get forwarded arguments
276 // needed to construct a virtual base (or base class thereof)
277 if (cd->getInheritedConstructor())
278 cgm.errorNYI(cd->getSourceRange(),
279 "arrangeCXXStructorDeclaration: inheriting constructor");
280 }
281
283
284 if (passParams)
285 appendParameterTypes(*this, argTypes, fpt);
286
287 // The structor signature may include implicit parameters.
288 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
289 theCXXABI.buildStructorSignature(gd, argTypes);
291
292 RequiredArgs required =
293 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
295
296 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
297 : theCXXABI.hasMostDerivedReturn(gd)
298 ? astContext.VoidPtrTy
299 : astContext.VoidTy;
300
301 assert(!theCXXABI.hasThisReturn(gd) &&
302 "Please send PR with a test and remove this");
303
306
307 return arrangeCIRFunctionInfo(resultType, argTypes, fpt->getExtInfo(),
308 required);
309}
310
311/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
312/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
313/// indicates that there is no meaningful 'this' type, and a null `md` can occur
314/// when calling a method pointer.
316 const CXXMethodDecl *md) {
317 CanQualType recTy;
318 if (rd) {
320 } else {
321 // This can happen with the MS ABI. It shouldn't need anything more than
322 // setting recTy to VoidTy here, but we're flagging it for now because we
323 // don't have the full handling implemented.
324 cgm.errorNYI("deriveThisType: no record decl");
325 recTy = getASTContext().VoidTy;
326 }
327
328 if (md)
329 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
330 recTy, md->getMethodQualifiers().getAddressSpace()));
331 return getASTContext().getPointerType(recTy);
332}
333
334/// Arrange the CIR function layout for a value of the given function type, on
335/// top of any implicit parameters already stored.
336static const CIRGenFunctionInfo &
340 RequiredArgs required =
343 appendParameterTypes(cgt, prefix, fpt);
344 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
345 return cgt.arrangeCIRFunctionInfo(resultType, prefix, fpt->getExtInfo(),
346 required);
347}
348
350 const VarDecl *param,
351 SourceLocation loc) {
352 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
353 // We need to turn that into an r-value suitable for emitCall
354 Address local = getAddrOfLocalVar(param);
355
356 QualType type = param->getType();
357
358 if (type->getAsCXXRecordDecl()) {
359 cgm.errorNYI(param->getSourceRange(),
360 "emitDelegateCallArg: record argument");
361 return;
362 }
363
364 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
365 // argument needs to be the original pointer.
366 if (type->isReferenceType()) {
367 args.add(
368 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
369 type);
370 } else if (getLangOpts().ObjCAutoRefCount) {
371 cgm.errorNYI(param->getSourceRange(),
372 "emitDelegateCallArg: ObjCAutoRefCount");
373 // For the most part, we just need to load the alloca, except that aggregate
374 // r-values are actually pointers to temporaries.
375 } else {
376 args.add(convertTempToRValue(local, type, loc), type);
377 }
378
379 // Deactivate the cleanup for the callee-destructed param that was pushed.
381 if (type->isRecordType() &&
382 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
383 param->needsDestruction(getContext())) {
384 cgm.errorNYI(param->getSourceRange(),
385 "emitDelegateCallArg: callee-destructed param");
386 }
387}
388
389static const CIRGenFunctionInfo &
391 const CallArgList &args,
392 const FunctionType *fnType) {
393
395
396 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
397 if (proto->isVariadic())
398 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
399 if (proto->hasExtParameterInfos())
400 cgm.errorNYI("call to functions with extra parameter info");
403 cgm.errorNYI("call to function without a prototype");
404
406 for (const CallArg &arg : args)
407 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
408
410
412 return cgt.arrangeCIRFunctionInfo(retType, argTypes, fnType->getExtInfo(),
413 required);
414}
415
416/// Arrange a call to a C++ method, passing the given arguments.
417///
418/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
419/// parameter.
420/// passProtoArgs indicates whether `args` has args for the parameters in the
421/// given CXXConstructorDecl.
423 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
424 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
425
426 // FIXME: Kill copy.
428 for (const auto &arg : args)
429 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
430
431 // +1 for implicit this, which should always be args[0]
432 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
433
435 RequiredArgs required = passProtoArgs
437 fpt, totalPrefixArgs + extraSuffixArgs)
439
440 GlobalDecl gd(d, ctorKind);
441 if (theCXXABI.hasThisReturn(gd))
442 cgm.errorNYI(d->getSourceRange(),
443 "arrangeCXXConstructorCall: hasThisReturn");
444 if (theCXXABI.hasMostDerivedReturn(gd))
445 cgm.errorNYI(d->getSourceRange(),
446 "arrangeCXXConstructorCall: hasMostDerivedReturn");
447 CanQualType resultType = astContext.VoidTy;
448
451
452 return arrangeCIRFunctionInfo(resultType, argTypes, fpt->getExtInfo(),
453 required);
454}
455
456/// Arrange a call to a C++ method, passing the given arguments.
457///
458/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
459/// does not count `this`.
461 const CallArgList &args, const FunctionProtoType *proto,
462 RequiredArgs required, unsigned numPrefixArgs) {
464 assert(numPrefixArgs + 1 <= args.size() &&
465 "Emitting a call with less args than the required prefix?");
466
467 // FIXME: Kill copy.
469 for (const CallArg &arg : args)
470 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
471
474 proto->getReturnType()->getCanonicalTypeUnqualified(), argTypes,
475 proto->getExtInfo(), required);
476}
477
478const CIRGenFunctionInfo &
480 const FunctionType *fnType) {
481 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
482}
483
484/// Arrange the argument and result information for a declaration or definition
485/// of the given C++ non-static member function. The member function must be an
486/// ordinary function, i.e. not a constructor or destructor.
487const CIRGenFunctionInfo &
489 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
490 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
491
492 auto prototype =
495
496 if (md->isInstance()) {
497 // The abstract case is perfectly fine.
498 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
499 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
500 }
501
502 return arrangeFreeFunctionType(prototype);
503}
504
505/// Arrange the argument and result information for a call to an unknown C++
506/// non-static member function of the given abstract type. (A null RD means we
507/// don't have any meaningful "this" argument type, so fall back to a generic
508/// pointer type). The member fucntion must be an ordinary function, i.e. not a
509/// constructor or destructor.
510const CIRGenFunctionInfo &
512 const FunctionProtoType *fpt,
513 const CXXMethodDecl *md) {
515
516 // Add the 'this' pointer.
517 argTypes.push_back(deriveThisType(rd, md));
518
520 return ::arrangeCIRFunctionInfo(
521 *this, argTypes,
523}
524
525/// Arrange the argument and result information for the declaration or
526/// definition of the given function.
527const CIRGenFunctionInfo &
529 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
530 if (md->isInstance())
532
534
535 assert(isa<FunctionType>(funcTy));
536 // TODO: setCUDAKernelCallingConvention
538
539 // When declaring a function without a prototype, always use a non-variadic
540 // type.
541 if (CanQual<FunctionNoProtoType> noProto =
542 funcTy.getAs<FunctionNoProtoType>()) {
545 return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
546 noProto->getExtInfo(), RequiredArgs::All);
547 }
548
550}
551
552static cir::CIRCallOpInterface
553emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
554 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
555 cir::FuncOp directFuncOp,
556 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
557 const mlir::NamedAttrList &attrs) {
558 CIRGenBuilderTy &builder = cgf.getBuilder();
559
561
562 if (isInvoke) {
563 // This call may throw and requires catch and/or cleanup handling.
564 // If this call does not appear within the `try` region of an existing
565 // TryOp, we must create a synthetic TryOp to contain the call. This
566 // happens when a call that may throw appears within a cleanup
567 // scope.
568
569 // In OG, we build the landing pad for this scope. In CIR, we emit a
570 // synthetic cir.try because this didn't come from code generating from a
571 // try/catch in C++.
572 assert(cgf.curLexScope && "expected scope");
573 cir::TryOp tryOp = cgf.curLexScope->getClosestTryParent();
574 if (!tryOp) {
575 cgf.cgm.errorNYI(
576 "emitCallLikeOp: call does not have an associated cir.try");
577 return {};
578 }
579
580 if (tryOp.getSynthetic()) {
581 cgf.cgm.errorNYI("emitCallLikeOp: tryOp synthetic");
582 return {};
583 }
584
585 cir::CallOp callOpWithExceptions;
586 if (indirectFuncTy) {
587 cgf.cgm.errorNYI("emitCallLikeOp: indirect function type");
588 return {};
589 }
590
591 callOpWithExceptions =
592 builder.createCallOp(callLoc, directFuncOp, cirCallArgs);
593
595 return callOpWithExceptions;
596 }
597
598 assert(builder.getInsertionBlock() && "expected valid basic block");
599
600 cir::CallOp op;
601 if (indirectFuncTy) {
602 // TODO(cir): Set calling convention for indirect calls.
604 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
605 cirCallArgs, attrs);
606 } else {
607 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);
608 }
609
610 return op;
611}
612
613const CIRGenFunctionInfo &
617 return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
618}
619
620const CIRGenFunctionInfo &
622 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
624 return arrangeCIRFunctionInfo(resultType, {}, fnpt->getExtInfo(),
625 RequiredArgs(0));
626}
627
629 const CIRGenCallee &callee,
631 const CallArgList &args,
632 cir::CIRCallOpInterface *callOp,
633 mlir::Location loc) {
634 QualType retTy = funcInfo.getReturnType();
635 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
636
637 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
638
640
641 // Translate all of the arguments as necessary to match the CIR lowering.
642 for (auto [argNo, arg, canQualArgType] :
643 llvm::enumerate(args, funcInfo.argTypes())) {
644
645 // Insert a padding argument to ensure proper alignment.
647
648 mlir::Type argType = convertType(canQualArgType);
649 if (!mlir::isa<cir::RecordType>(argType) &&
650 !mlir::isa<cir::ComplexType>(argType)) {
651 mlir::Value v;
652 if (arg.isAggregate())
653 cgm.errorNYI(loc, "emitCall: aggregate call argument");
654 v = arg.getKnownRValue().getValue();
655
656 // We might have to widen integers, but we should never truncate.
657 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
658 cgm.errorNYI(loc, "emitCall: widening integer call argument");
659
660 // If the argument doesn't match, perform a bitcast to coerce it. This
661 // can happen due to trivial type mismatches.
662 // TODO(cir): When getFunctionType is added, assert that this isn't
663 // needed.
665 cirCallArgs[argNo] = v;
666 } else {
668 if (!arg.isAggregate()) {
669 src = createMemTemp(arg.ty, loc, "coerce");
670 arg.copyInto(*this, src, loc);
671 } else {
672 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
673 : arg.getKnownRValue().getAggregateAddress();
674 }
675
676 // Fast-isel and the optimizer generally like scalar values better than
677 // FCAs, so we flatten them if this is safe to do for this argument.
678 mlir::Type srcTy = src.getElementType();
679 // FIXME(cir): get proper location for each argument.
680 mlir::Location argLoc = loc;
681
682 // If the source type is smaller than the destination type of the
683 // coerce-to logic, copy the source value into a temp alloca the size
684 // of the destination type to allow loading all of it. The bits past
685 // the source value are left undef.
686 // FIXME(cir): add data layout info and compare sizes instead of
687 // matching the types.
688 //
689 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
690 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
691 // if (SrcSize < DstSize) {
693 if (srcTy != argType) {
694 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
695 } else {
696 // FIXME(cir): this currently only runs when the types are exactly the
697 // same, but should be when alloc sizes are the same, fix this as soon
698 // as datalayout gets introduced.
700 }
701
702 // assert(NumCIRArgs == STy.getMembers().size());
703 // In LLVMGen: Still only pass the struct without any gaps but mark it
704 // as such somehow.
705 //
706 // In CIRGen: Emit a load from the "whole" struct,
707 // which shall be broken later by some lowering step into multiple
708 // loads.
710 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
711 }
712 }
713
714 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
715 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
716
718
719 mlir::NamedAttrList attrs;
720 StringRef funcName;
721 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
722 funcName = calleeFuncOp.getName();
723
726 cir::CallingConv callingConv;
727 cir::SideEffect sideEffect;
728 cgm.constructAttributeList(funcName, funcInfo, callee.getAbstractInfo(),
729 attrs, callingConv, sideEffect,
730 /*attrOnCallSite=*/true, /*isThunk=*/false);
731
732 cir::FuncType indirectFuncTy;
733 mlir::Value indirectFuncVal;
734 cir::FuncOp directFuncOp;
735 if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
736 directFuncOp = fnOp;
737 } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
738 // FIXME(cir): This peephole optimization avoids indirect calls for
739 // builtins. This should be fixed in the builtin declaration instead by
740 // not emitting an unecessary get_global in the first place.
741 // However, this is also used for no-prototype functions.
742 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
743 assert(globalOp && "undefined global function");
744 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
745 } else {
746 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
747 calleePtr->getResultTypes();
748 [[maybe_unused]] auto funcPtrTy =
749 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
750 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
751 "expected pointer to function");
752
753 indirectFuncTy = cirFuncTy;
754 indirectFuncVal = calleePtr->getResult(0);
755 }
756
760
761 bool cannotThrow = attrs.getNamed("nothrow").has_value();
762 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
763
764 mlir::Location callLoc = loc;
765 cir::CIRCallOpInterface theCall =
766 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
767 cirCallArgs, isInvoke, attrs);
768
769 if (callOp)
770 *callOp = theCall;
771
774
775 mlir::Type retCIRTy = convertType(retTy);
776 if (isa<cir::VoidType>(retCIRTy))
777 return getUndefRValue(retTy);
778 switch (getEvaluationKind(retTy)) {
779 case cir::TEK_Aggregate: {
780 Address destPtr = returnValue.getValue();
781
782 if (!destPtr.isValid())
783 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
784
785 mlir::ResultRange results = theCall->getOpResults();
786 assert(results.size() <= 1 && "multiple returns from a call");
787
788 SourceLocRAIIObject loc{*this, callLoc};
789 emitAggregateStore(results[0], destPtr);
790 return RValue::getAggregate(destPtr);
791 }
792 case cir::TEK_Scalar: {
793 mlir::ResultRange results = theCall->getOpResults();
794 assert(results.size() == 1 && "unexpected number of returns");
795
796 // If the argument doesn't match, perform a bitcast to coerce it. This
797 // can happen due to trivial type mismatches.
798 if (results[0].getType() != retCIRTy)
799 cgm.errorNYI(loc, "bitcast on function return value");
800
801 mlir::Region *region = builder.getBlock()->getParent();
802 if (region != theCall->getParentRegion())
803 cgm.errorNYI(loc, "function calls with cleanup");
804
805 return RValue::get(results[0]);
806 }
807 case cir::TEK_Complex: {
808 mlir::ResultRange results = theCall->getOpResults();
809 assert(!results.empty() &&
810 "Expected at least one result for complex rvalue");
811 return RValue::getComplex(results[0]);
812 }
813 }
814 llvm_unreachable("Invalid evaluation kind");
815}
816
818 mlir::Location loc) const {
819 LValue dst = cgf.makeAddrLValue(addr, ty);
820 if (!hasLV && rv.isScalar())
821 cgf.cgm.errorNYI(loc, "copyInto scalar value");
822 else if (!hasLV && rv.isComplex())
823 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
824 else
825 cgf.cgm.errorNYI(loc, "copyInto hasLV");
826 isUsed = true;
827}
828
829mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
830 cir::FuncOp callee,
832 // TODO(cir): set the calling convention to this runtime call.
834
835 cir::CallOp call = builder.createCallOp(loc, callee, args);
836 assert(call->getNumResults() <= 1 &&
837 "runtime functions have at most 1 result");
838
839 if (call->getNumResults() == 0)
840 return nullptr;
841
842 return call->getResult(0);
843}
844
846 clang::QualType argType) {
847 assert(argType->isReferenceType() == e->isGLValue() &&
848 "reference binding to unmaterialized r-value!");
849
850 if (e->isGLValue()) {
851 assert(e->getObjectKind() == OK_Ordinary);
852 return args.add(emitReferenceBindingToExpr(e), argType);
853 }
854
855 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
856
857 // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
858 // However, we still have to push an EH-only cleanup in case we unwind before
859 // we make it to the call.
860 if (argType->isRecordType() &&
863 cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
864 }
865
866 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
867 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
868 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
869 assert(lv.isSimple());
870 args.addUncopiedAggregate(lv, argType);
871 return;
872 }
873
874 args.add(emitAnyExprToTemp(e), argType);
875}
876
877QualType CIRGenFunction::getVarArgType(const Expr *arg) {
878 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
879 // implicitly widens null pointer constants that are arguments to varargs
880 // functions to pointer-sized ints.
881 if (!getTarget().getTriple().isOSWindows())
882 return arg->getType();
883
885 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
886 return arg->getType();
887}
888
889/// Similar to emitAnyExpr(), however, the result will always be accessible
890/// even if no aggregate location is provided.
893
895 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
897
898 return emitAnyExpr(e, aggSlot);
899}
900
902 CallArgList &args, PrototypeWrapper prototype,
903 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
904 AbstractCallee callee, unsigned paramsToSkip) {
906
908
909 // First, if a prototype was provided, use those argument types.
910 bool isVariadic = false;
911 if (prototype.p) {
913
914 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
915 isVariadic = fpt->isVariadic();
917 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
918 fpt->param_type_end());
919 }
920
921 // If we still have any arguments, emit them using the type of the argument.
922 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
923 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
924 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
925
926 // We must evaluate arguments from right to left in the MS C++ ABI, because
927 // arguments are destroyed left to right in the callee. As a special case,
928 // there are certain language constructs taht require left-to-right
929 // evaluation, and in those cases we consider the evaluation order requirement
930 // to trump the "destruction order is reverse construction order" guarantee.
931 auto leftToRight = true;
933
934 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
935 RValue emittedArg) {
936 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
937 return;
938 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
939 if (!ps)
940 return;
941
943 cgm.errorNYI("emit implicit object size for call arg");
944 };
945
946 // Evaluate each argument in the appropriate order.
947 size_t callArgsStart = args.size();
948 for (size_t i = 0; i != argTypes.size(); ++i) {
949 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
950 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
951 size_t initialArgSize = args.size();
952
953 emitCallArg(args, *currentArg, argTypes[idx]);
954
955 // In particular, we depend on it being the last arg in Args, and the
956 // objectsize bits depend on there only being one arg if !LeftToRight.
957 assert(initialArgSize + 1 == args.size() &&
958 "The code below depends on only adding one arg per emitCallArg");
959 (void)initialArgSize;
960
961 // Since pointer argument are never emitted as LValue, it is safe to emit
962 // non-null argument check for r-value only.
963 if (!args.back().hasLValue()) {
964 RValue rvArg = args.back().getKnownRValue();
966 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
967 }
968
969 if (!leftToRight)
970 std::reverse(args.begin() + callArgsStart, args.end());
971 }
972}
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)
static const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CIRGenTypes &cgt, 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...
static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Adds the formal parameters in FPT to the given prefix.
static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder, mlir::NamedAttrList &attrs, const FunctionProtoType *fpt)
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)
TokenType getType() const
Returns the token's type, e.g.
static bool isVirtualCall(const CallExpr *CE)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
cir::CallOp createIndirectCallOp(mlir::Location loc, mlir::Value indirectTarget, cir::FuncType funcType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
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
mlir::Type getElementType() const
Definition Address.h:122
static Address invalid()
Definition Address.h:73
bool isValid() const
Definition Address.h:74
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
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
llvm::MutableArrayRef< CanQualType > argTypes()
llvm::ArrayRef< CanQualType > requiredArguments() 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.
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.
void populateCatchHandlersIfRequired(cir::TryOp tryOp)
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={})
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.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
CIRGenBuilderTy & getBuilder()
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
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 & 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 & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, RequiredArgs required)
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.
void addUncopiedAggregate(LValue lvalue, clang::QualType type)
Definition CIRGenCall.h:237
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:235
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:256
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:2604
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
bool isVirtual() const
Definition DeclCXX.h:2184
bool isInstance() const
Definition DeclCXX.h:2156
Qualifiers getMethodQualifiers() const
Definition DeclCXX.h:2290
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:2943
SourceLocation getBeginLoc() const
Definition Expr.h:3277
ConstExprIterator const_arg_iterator
Definition Expr.h:3191
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.
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:451
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:4549
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4847
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5269
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5576
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5668
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4576
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4465
ExtInfo getExtInfo() const
Definition TypeBase.h:4821
QualType getReturnType() const
Definition TypeBase.h:4805
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
A (possibly-)qualified type.
Definition TypeBase.h:937
LangAS getAddressSpace() const
Definition TypeBase.h:571
bool isParamDestroyedInCallee() const
Definition Decl.h:4474
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:338
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition TypeBase.h:8563
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9121
bool isRecordType() const
Definition TypeBase.h:8666
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:2201
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2862
@ 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
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
U cast(CodeGen::Address addr)
Definition Address.h:327
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
void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const