clang 22.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->required = required;
36 fi->numArgs = argTypes.size();
37
38 fi->getArgTypes()[0] = resultType;
39 std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());
41
42 return fi;
43}
44
47 return getFunctionType(fi);
48}
49
51 mlir::Type resultType = convertType(info.getReturnType());
53 argTypes.reserve(info.getNumRequiredArgs());
54
55 for (const CanQualType &argType : info.requiredArguments())
56 argTypes.push_back(convertType(argType));
57
58 return cir::FuncType::get(argTypes,
59 (resultType ? resultType : builder.getVoidTy()),
60 info.isVariadic());
61}
62
64 const CXXMethodDecl *md = cast<CXXMethodDecl>(gd.getDecl());
65 const FunctionProtoType *fpt = md->getType()->getAs<FunctionProtoType>();
66
67 if (!isFuncTypeConvertible(fpt))
68 cgm.errorNYI("getFunctionTypeForVTable: non-convertible function type");
69
70 return getFunctionType(gd);
71}
72
74 if (isVirtual()) {
75 const CallExpr *ce = getVirtualCallExpr();
78 ce ? ce->getBeginLoc() : SourceLocation());
79 }
80 return *this;
81}
82
83void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
84 // In classic codegen:
85 // Function to store a first-class aggregate into memory. We prefer to
86 // store the elements rather than the aggregate to be more friendly to
87 // fast-isel.
88 // In CIR codegen:
89 // Emit the most simple cir.store possible (e.g. a store for a whole
90 // record), which can later be broken down in other CIR levels (or prior
91 // to dialect codegen).
92
93 // Stored result for the callers of this function expected to be in the same
94 // scope as the value, don't make assumptions about current insertion point.
95 mlir::OpBuilder::InsertionGuard guard(builder);
96 builder.setInsertionPointAfter(value.getDefiningOp());
97 builder.createStore(*currSrcLoc, value, dest);
98}
99
101 mlir::NamedAttrList &attrs,
102 const FunctionProtoType *fpt) {
103 if (!fpt)
104 return;
105
107 fpt->isNothrow())
108 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
109 mlir::UnitAttr::get(builder.getContext()));
110}
111
112/// Construct the CIR attribute list of a function or call.
114 mlir::NamedAttrList &attrs) {
116 auto sideEffect = cir::SideEffect::All;
117
119 calleeInfo.getCalleeFunctionProtoType());
120
121 const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
122
123 if (targetDecl) {
124 if (targetDecl->hasAttr<NoThrowAttr>())
125 attrs.set(cir::CIRDialect::getNoThrowAttrName(),
126 mlir::UnitAttr::get(&getMLIRContext()));
127
128 if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
130 getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
132 }
133
135
136 // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
137 if (targetDecl->hasAttr<ConstAttr>()) {
138 // gcc specifies that 'const' functions have greater restrictions than
139 // 'pure' functions, so they also cannot have infinite loops.
140 sideEffect = cir::SideEffect::Const;
141 } else if (targetDecl->hasAttr<PureAttr>()) {
142 // gcc specifies that 'pure' functions cannot have infinite loops.
143 sideEffect = cir::SideEffect::Pure;
144 }
145
147 }
148
150
151 attrs.set(cir::CIRDialect::getSideEffectAttrName(),
152 cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
153}
154
155/// Returns the canonical formal type of the given C++ method.
157 return md->getType()
160}
161
162/// Adds the formal parameters in FPT to the given prefix. If any parameter in
163/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
164/// TODO(cir): this should be shared with LLVM codegen
165static void appendParameterTypes(const CIRGenTypes &cgt,
169 // Fast path: don't touch param info if we don't need to.
170 if (!fpt->hasExtParameterInfos()) {
171 prefix.append(fpt->param_type_begin(), fpt->param_type_end());
172 return;
173 }
174
175 cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
176}
177
178const CIRGenFunctionInfo &
180 auto *md = cast<CXXMethodDecl>(gd.getDecl());
181
183 argTypes.push_back(deriveThisType(md->getParent(), md));
184
185 bool passParams = true;
186
187 if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
188 // A base class inheriting constructor doesn't get forwarded arguments
189 // needed to construct a virtual base (or base class thereof)
190 if (cd->getInheritedConstructor())
191 cgm.errorNYI(cd->getSourceRange(),
192 "arrangeCXXStructorDeclaration: inheriting constructor");
193 }
194
196
197 if (passParams)
198 appendParameterTypes(*this, argTypes, fpt);
199
201
202 RequiredArgs required =
203 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
205
206 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
207 : theCXXABI.hasMostDerivedReturn(gd)
208 ? astContext.VoidPtrTy
209 : astContext.VoidTy;
210
211 assert(!theCXXABI.hasThisReturn(gd) &&
212 "Please send PR with a test and remove this");
213
216
217 return arrangeCIRFunctionInfo(resultType, argTypes, required);
218}
219
220/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
221/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
222/// indicates that there is no meaningful 'this' type, and a null `md` can occur
223/// when calling a method pointer.
225 const CXXMethodDecl *md) {
226 CanQualType recTy;
227 if (rd) {
229 } else {
230 // This can happen with the MS ABI. It shouldn't need anything more than
231 // setting recTy to VoidTy here, but we're flagging it for now because we
232 // don't have the full handling implemented.
233 cgm.errorNYI("deriveThisType: no record decl");
234 recTy = getASTContext().VoidTy;
235 }
236
237 if (md)
238 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
239 recTy, md->getMethodQualifiers().getAddressSpace()));
240 return getASTContext().getPointerType(recTy);
241}
242
243/// Arrange the CIR function layout for a value of the given function type, on
244/// top of any implicit parameters already stored.
245static const CIRGenFunctionInfo &
249 RequiredArgs required =
252 appendParameterTypes(cgt, prefix, fpt);
253 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
254 return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
255}
256
258 const VarDecl *param,
259 SourceLocation loc) {
260 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
261 // We need to turn that into an r-value suitable for emitCall
262 Address local = getAddrOfLocalVar(param);
263
264 QualType type = param->getType();
265
266 if (type->getAsCXXRecordDecl()) {
267 cgm.errorNYI(param->getSourceRange(),
268 "emitDelegateCallArg: record argument");
269 return;
270 }
271
272 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
273 // argument needs to be the original pointer.
274 if (type->isReferenceType()) {
275 args.add(
276 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
277 type);
278 } else if (getLangOpts().ObjCAutoRefCount) {
279 cgm.errorNYI(param->getSourceRange(),
280 "emitDelegateCallArg: ObjCAutoRefCount");
281 // For the most part, we just need to load the alloca, except that aggregate
282 // r-values are actually pointers to temporaries.
283 } else {
284 args.add(convertTempToRValue(local, type, loc), type);
285 }
286
287 // Deactivate the cleanup for the callee-destructed param that was pushed.
289 if (type->isRecordType() &&
290 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
291 param->needsDestruction(getContext())) {
292 cgm.errorNYI(param->getSourceRange(),
293 "emitDelegateCallArg: callee-destructed param");
294 }
295}
296
297static const CIRGenFunctionInfo &
299 const CallArgList &args,
300 const FunctionType *fnType) {
301
303
304 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
305 if (proto->isVariadic())
306 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
307 if (proto->hasExtParameterInfos())
308 cgm.errorNYI("call to functions with extra parameter info");
310 cast<FunctionNoProtoType>(fnType)))
311 cgm.errorNYI("call to function without a prototype");
312
314 for (const CallArg &arg : args)
315 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
316
317 CanQualType retType = fnType->getReturnType()
320
322 return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
323}
324
325/// Arrange a call to a C++ method, passing the given arguments.
326///
327/// passProtoArgs indicates whether `args` has args for the parameters in the
328/// given CXXConstructorDecl.
330 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
331 bool passProtoArgs) {
332
333 // FIXME: Kill copy.
335 for (const auto &arg : args)
336 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
337
339 // +1 for implicit this, which should always be args[0]
340 unsigned totalPrefixArgs = 1;
341
343 RequiredArgs required =
344 passProtoArgs
345 ? RequiredArgs::getFromProtoWithExtraSlots(fpt, totalPrefixArgs)
347
348 GlobalDecl gd(d, ctorKind);
349 if (theCXXABI.hasThisReturn(gd))
350 cgm.errorNYI(d->getSourceRange(),
351 "arrangeCXXConstructorCall: hasThisReturn");
352 if (theCXXABI.hasMostDerivedReturn(gd))
353 cgm.errorNYI(d->getSourceRange(),
354 "arrangeCXXConstructorCall: hasMostDerivedReturn");
355 CanQualType resultType = astContext.VoidTy;
356
359
360 return arrangeCIRFunctionInfo(resultType, argTypes, required);
361}
362
363/// Arrange a call to a C++ method, passing the given arguments.
364///
365/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
366/// does not count `this`.
368 const CallArgList &args, const FunctionProtoType *proto,
369 RequiredArgs required, unsigned numPrefixArgs) {
371 assert(numPrefixArgs + 1 <= args.size() &&
372 "Emitting a call with less args than the required prefix?");
373
374 // FIXME: Kill copy.
376 for (const CallArg &arg : args)
377 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
378
383 argTypes, required);
384}
385
386const CIRGenFunctionInfo &
388 const FunctionType *fnType) {
389 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
390}
391
392/// Arrange the argument and result information for a declaration or definition
393/// of the given C++ non-static member function. The member function must be an
394/// ordinary function, i.e. not a constructor or destructor.
395const CIRGenFunctionInfo &
397 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
398 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
399
400 auto prototype =
403
404 if (md->isInstance()) {
405 // The abstract case is perfectly fine.
406 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
407 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
408 }
409
410 return arrangeFreeFunctionType(prototype);
411}
412
413/// Arrange the argument and result information for a call to an unknown C++
414/// non-static member function of the given abstract type. (A null RD means we
415/// don't have any meaningful "this" argument type, so fall back to a generic
416/// pointer type). The member fucntion must be an ordinary function, i.e. not a
417/// constructor or destructor.
418const CIRGenFunctionInfo &
420 const FunctionProtoType *fpt,
421 const CXXMethodDecl *md) {
423
424 // Add the 'this' pointer.
425 argTypes.push_back(deriveThisType(rd, md));
426
428 return ::arrangeCIRFunctionInfo(
429 *this, argTypes,
431}
432
433/// Arrange the argument and result information for the declaration or
434/// definition of the given function.
435const CIRGenFunctionInfo &
437 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
438 if (md->isInstance())
440
442
443 assert(isa<FunctionType>(funcTy));
444 // TODO: setCUDAKernelCallingConvention
446
447 // When declaring a function without a prototype, always use a non-variadic
448 // type.
449 if (CanQual<FunctionNoProtoType> noProto =
450 funcTy.getAs<FunctionNoProtoType>()) {
453 return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
455 }
456
458}
459
460static cir::CIRCallOpInterface
461emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
462 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
463 cir::FuncOp directFuncOp,
464 const SmallVectorImpl<mlir::Value> &cirCallArgs,
465 const mlir::NamedAttrList &attrs) {
466 CIRGenBuilderTy &builder = cgf.getBuilder();
467
470
471 assert(builder.getInsertionBlock() && "expected valid basic block");
472
473 cir::CallOp op;
474 if (indirectFuncTy) {
475 // TODO(cir): Set calling convention for indirect calls.
477 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
478 cirCallArgs, attrs);
479 } else {
480 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);
481 }
482
483 return op;
484}
485
486const CIRGenFunctionInfo &
490 return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
491}
492
493const CIRGenFunctionInfo &
495 CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
497 return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
498}
499
501 const CIRGenCallee &callee,
502 ReturnValueSlot returnValue,
503 const CallArgList &args,
504 cir::CIRCallOpInterface *callOp,
505 mlir::Location loc) {
506 QualType retTy = funcInfo.getReturnType();
507 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
508
509 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
510
512
513 // Translate all of the arguments as necessary to match the CIR lowering.
514 for (auto [argNo, arg, canQualArgType] :
515 llvm::enumerate(args, funcInfo.argTypes())) {
516
517 // Insert a padding argument to ensure proper alignment.
519
520 mlir::Type argType = convertType(canQualArgType);
521 if (!mlir::isa<cir::RecordType>(argType)) {
522 mlir::Value v;
523 if (arg.isAggregate())
524 cgm.errorNYI(loc, "emitCall: aggregate call argument");
525 v = arg.getKnownRValue().getValue();
526
527 // We might have to widen integers, but we should never truncate.
528 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
529 cgm.errorNYI(loc, "emitCall: widening integer call argument");
530
531 // If the argument doesn't match, perform a bitcast to coerce it. This
532 // can happen due to trivial type mismatches.
533 // TODO(cir): When getFunctionType is added, assert that this isn't
534 // needed.
536 cirCallArgs[argNo] = v;
537 } else {
539 if (!arg.isAggregate())
540 cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
541 else
542 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
543 : arg.getKnownRValue().getAggregateAddress();
544
545 // Fast-isel and the optimizer generally like scalar values better than
546 // FCAs, so we flatten them if this is safe to do for this argument.
547 auto argRecordTy = cast<cir::RecordType>(argType);
548 mlir::Type srcTy = src.getElementType();
549 // FIXME(cir): get proper location for each argument.
550 mlir::Location argLoc = loc;
551
552 // If the source type is smaller than the destination type of the
553 // coerce-to logic, copy the source value into a temp alloca the size
554 // of the destination type to allow loading all of it. The bits past
555 // the source value are left undef.
556 // FIXME(cir): add data layout info and compare sizes instead of
557 // matching the types.
558 //
559 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
560 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
561 // if (SrcSize < DstSize) {
563 if (srcTy != argRecordTy) {
564 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
565 } else {
566 // FIXME(cir): this currently only runs when the types are exactly the
567 // same, but should be when alloc sizes are the same, fix this as soon
568 // as datalayout gets introduced.
570 }
571
572 // assert(NumCIRArgs == STy.getMembers().size());
573 // In LLVMGen: Still only pass the struct without any gaps but mark it
574 // as such somehow.
575 //
576 // In CIRGen: Emit a load from the "whole" struct,
577 // which shall be broken later by some lowering step into multiple
578 // loads.
580 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
581 }
582 }
583
584 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
585 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
586
588
589 mlir::NamedAttrList attrs;
590 StringRef funcName;
591 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
592 funcName = calleeFuncOp.getName();
593
597
599
600 cir::FuncType indirectFuncTy;
601 mlir::Value indirectFuncVal;
602 cir::FuncOp directFuncOp;
603 if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
604 directFuncOp = fnOp;
605 } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
606 // FIXME(cir): This peephole optimization avoids indirect calls for
607 // builtins. This should be fixed in the builtin declaration instead by
608 // not emitting an unecessary get_global in the first place.
609 // However, this is also used for no-prototype functions.
610 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
611 assert(globalOp && "undefined global function");
612 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
613 } else {
614 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
615 calleePtr->getResultTypes();
616 [[maybe_unused]] auto funcPtrTy =
617 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
618 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
619 "expected pointer to function");
620
621 indirectFuncTy = cirFuncTy;
622 indirectFuncVal = calleePtr->getResult(0);
623 }
624
625 mlir::Location callLoc = loc;
626 cir::CIRCallOpInterface theCall =
627 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
628 cirCallArgs, attrs);
629
630 if (callOp)
631 *callOp = theCall;
632
635
636 mlir::Type retCIRTy = convertType(retTy);
637 if (isa<cir::VoidType>(retCIRTy))
638 return getUndefRValue(retTy);
639 switch (getEvaluationKind(retTy)) {
640 case cir::TEK_Aggregate: {
641 Address destPtr = returnValue.getValue();
642
643 if (!destPtr.isValid())
644 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
645
646 mlir::ResultRange results = theCall->getOpResults();
647 assert(results.size() <= 1 && "multiple returns from a call");
648
649 SourceLocRAIIObject loc{*this, callLoc};
650 emitAggregateStore(results[0], destPtr);
651 return RValue::getAggregate(destPtr);
652 }
653 case cir::TEK_Scalar: {
654 mlir::ResultRange results = theCall->getOpResults();
655 assert(results.size() == 1 && "unexpected number of returns");
656
657 // If the argument doesn't match, perform a bitcast to coerce it. This
658 // can happen due to trivial type mismatches.
659 if (results[0].getType() != retCIRTy)
660 cgm.errorNYI(loc, "bitcast on function return value");
661
662 mlir::Region *region = builder.getBlock()->getParent();
663 if (region != theCall->getParentRegion())
664 cgm.errorNYI(loc, "function calls with cleanup");
665
666 return RValue::get(results[0]);
667 }
668 case cir::TEK_Complex:
669 cgm.errorNYI(loc, "unsupported evaluation kind of function call result");
670 return getUndefRValue(retTy);
671 }
672 llvm_unreachable("Invalid evaluation kind");
673}
674
676 clang::QualType argType) {
677 assert(argType->isReferenceType() == e->isGLValue() &&
678 "reference binding to unmaterialized r-value!");
679
680 if (e->isGLValue()) {
681 assert(e->getObjectKind() == OK_Ordinary);
682 return args.add(emitReferenceBindingToExpr(e), argType);
683 }
684
685 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
686
687 // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
688 // However, we still have to push an EH-only cleanup in case we unwind before
689 // we make it to the call.
690 if (argType->isRecordType() &&
693 cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
694 }
695
696 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
697 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
698 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
699 assert(lv.isSimple());
700 args.addUncopiedAggregate(lv, argType);
701 return;
702 }
703
704 args.add(emitAnyExprToTemp(e), argType);
705}
706
707QualType CIRGenFunction::getVarArgType(const Expr *arg) {
708 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
709 // implicitly widens null pointer constants that are arguments to varargs
710 // functions to pointer-sized ints.
711 if (!getTarget().getTriple().isOSWindows())
712 return arg->getType();
713
715 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
716 return arg->getType();
717}
718
719/// Similar to emitAnyExpr(), however, the result will always be accessible
720/// even if no aggregate location is provided.
723
725 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
727
728 return emitAnyExpr(e, aggSlot);
729}
730
732 CallArgList &args, PrototypeWrapper prototype,
733 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
734 AbstractCallee callee, unsigned paramsToSkip) {
736
738
739 // First, if a prototype was provided, use those argument types.
740 bool isVariadic = false;
741 if (prototype.p) {
743
744 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
745 isVariadic = fpt->isVariadic();
747 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
748 fpt->param_type_end());
749 }
750
751 // If we still have any arguments, emit them using the type of the argument.
752 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
753 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
754 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
755
756 // We must evaluate arguments from right to left in the MS C++ ABI, because
757 // arguments are destroyed left to right in the callee. As a special case,
758 // there are certain language constructs taht require left-to-right
759 // evaluation, and in those cases we consider the evaluation order requirement
760 // to trump the "destruction order is reverse construction order" guarantee.
761 auto leftToRight = true;
763
764 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
765 RValue emittedArg) {
766 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
767 return;
768 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
769 if (!ps)
770 return;
771
773 cgm.errorNYI("emit implicit object size for call arg");
774 };
775
776 // Evaluate each argument in the appropriate order.
777 size_t callArgsStart = args.size();
778 for (size_t i = 0; i != argTypes.size(); ++i) {
779 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
780 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
781 size_t initialArgSize = args.size();
782
783 emitCallArg(args, *currentArg, argTypes[idx]);
784
785 // In particular, we depend on it being the last arg in Args, and the
786 // objectsize bits depend on there only being one arg if !LeftToRight.
787 assert(initialArgSize + 1 == args.size() &&
788 "The code below depends on only adding one arg per emitCallArg");
789 (void)initialArgSize;
790
791 // Since pointer argument are never emitted as LValue, it is safe to emit
792 // non-null argument check for r-value only.
793 if (!args.back().hasLValue()) {
794 RValue rvArg = args.back().getKnownRValue();
796 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
797 }
798
799 if (!leftToRight)
800 std::reverse(args.begin() + callArgsStart, args.end());
801 }
802}
static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc, cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal, cir::FuncOp directFuncOp, const SmallVectorImpl< mlir::Value > &cirCallArgs, const mlir::NamedAttrList &attrs)
Definition: CIRGenCall.cpp:461
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...
Definition: CIRGenCall.cpp:246
static void appendParameterTypes(const CIRGenTypes &cgt, SmallVectorImpl< CanQualType > &prefix, CanQual< FunctionProtoType > fpt)
Adds the formal parameters in FPT to the given prefix.
Definition: CIRGenCall.cpp:165
static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder, mlir::NamedAttrList &attrs, const FunctionProtoType *fpt)
Definition: CIRGenCall.cpp:100
static CanQual< FunctionProtoType > getFormalType(const CXXMethodDecl *md)
Returns the canonical formal type of the given C++ method.
Definition: CIRGenCall.cpp:156
static const CIRGenFunctionInfo & arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm, const CallArgList &args, const FunctionType *fnType)
Definition: CIRGenCall.cpp:298
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 VoidPtrTy
Definition: ASTContext.h:1249
CanQualType VoidTy
Definition: ASTContext.h:1222
CanQualType getCanonicalTagType(const TagDecl *TD) const
mlir::Type getElementType() const
Definition: Address.h:101
static Address invalid()
Definition: Address.h:66
bool isValid() const
Definition: Address.h:67
An aggregate value slot.
Definition: CIRGenValue.h:302
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
Definition: CIRGenValue.h:348
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
virtual const clang::CXXRecordDecl * getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md)
Get the type of the implicit "this" parameter used by a method.
Definition: CIRGenCXXABI.h:66
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.
virtual bool hasThisReturn(clang::GlobalDecl gd) const
Returns true if the given constructor or destructor is one of the kinds that the ABI says returns 'th...
Definition: CIRGenCXXABI.h:153
virtual bool hasMostDerivedReturn(clang::GlobalDecl gd) const
Definition: CIRGenCXXABI.h:155
Abstract information about a function or function prototype.
Definition: CIRGenCall.h:27
clang::GlobalDecl getCalleeDecl() const
Definition: CIRGenCall.h:42
const clang::FunctionProtoType * getCalleeFunctionProtoType() const
Definition: CIRGenCall.h:39
CIRGenCalleeInfo getAbstractInfo() const
Definition: CIRGenCall.h:138
clang::GlobalDecl getVirtualMethodDecl() const
Definition: CIRGenCall.h:168
CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const
If this is a delayed callee computation of some sort, prepare a concrete callee.
Definition: CIRGenCall.cpp:73
Address getThisAddress() const
Definition: CIRGenCall.h:173
cir::FuncType getVirtualFunctionType() const
Definition: CIRGenCall.h:178
const clang::CallExpr * getVirtualCallExpr() const
Definition: CIRGenCall.h:163
mlir::Operation * getFunctionPointer() const
Definition: CIRGenCall.h:145
llvm::MutableArrayRef< CanQualType > argTypes()
llvm::ArrayRef< CanQualType > requiredArguments() const
const_arg_iterator argTypesBegin() const
static CIRGenFunctionInfo * create(CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
Definition: CIRGenCall.cpp:24
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)
Definition: CIRGenCall.cpp:731
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)
Definition: CIRGenCall.cpp:83
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored())
Emit code to compute the specified expression which can have any type.
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
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...
Definition: CIRGenCall.cpp:721
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
Definition: CIRGenCall.cpp:500
void emitCallArg(CallArgList &args, const clang::Expr *e, clang::QualType argType)
Definition: CIRGenCall.cpp:675
CIRGenBuilderTy & getBuilder()
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.
Definition: CIRGenCall.cpp:257
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.
Definition: CIRGenModule.h:56
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
void constructAttributeList(CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs)
Get the CIR attributes and calling convention to use for a particular function type.
Definition: CIRGenCall.cpp:113
CIRGenBuilderTy & getBuilder()
Definition: CIRGenModule.h:101
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Operation * getGlobalValue(llvm::StringRef ref)
mlir::MLIRContext & getMLIRContext()
Definition: CIRGenModule.h:110
CIRGenCXXABI & getCXXABI() const
Definition: CIRGenModule.h:109
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.
Definition: CIRGenCall.cpp:396
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
Definition: CIRGenCall.cpp:179
const CIRGenFunctionInfo & arrangeFreeFunctionCall(const CallArgList &args, const FunctionType *fnType)
Definition: CIRGenCall.cpp:387
const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)
Definition: CIRGenCall.cpp:487
bool isFuncTypeConvertible(const clang::FunctionType *ft)
Utility to check whether a function type can be converted to a CIR type (i.e.
Definition: CIRGenTypes.cpp:53
cir::FuncType getFunctionTypeForVTable(clang::GlobalDecl gd)
Get the CIR function type for use in a vtable, given a CXXMethodDecl.
Definition: CIRGenCall.cpp:63
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...
Definition: CIRGenCall.cpp:419
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
Definition: CIRGenCall.cpp:50
clang::CanQualType deriveThisType(const clang::CXXRecordDecl *rd, const clang::CXXMethodDecl *md)
Derives the 'this' type for CIRGen purposes, i.e.
Definition: CIRGenCall.cpp:224
const CIRGenFunctionInfo & arrangeCXXConstructorCall(const CallArgList &args, const clang::CXXConstructorDecl *d, clang::CXXCtorType ctorKind, bool passProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
Definition: CIRGenCall.cpp:329
const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)
Free functions are functions that are compatible with an ordinary C function pointer type.
Definition: CIRGenCall.cpp:436
clang::ASTContext & getASTContext() const
Definition: CIRGenTypes.h:100
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.
Definition: CIRGenCall.cpp:367
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
void addUncopiedAggregate(LValue lvalue, clang::QualType type)
Definition: CIRGenCall.h:233
void add(RValue rvalue, clang::QualType type)
Definition: CIRGenCall.h:231
bool isSimple() const
Definition: CIRGenValue.h:190
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:82
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
Definition: CIRGenValue.h:104
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:252
virtual bool isNoProtoCallVariadic(const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
Definition: TargetInfo.cpp:63
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 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:2879
SourceLocation getBeginLoc() const
Definition: Expr.h:3213
static CanQual< Type > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
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.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
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:1999
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4486
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition: TypeBase.h:4860
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition: TypeBase.h:5589
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition: TypeBase.h:5681
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: TypeBase.h:4478
QualType getReturnType() const
Definition: TypeBase.h:4818
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:4455
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:334
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
Definition: TypeBase.h:8604
RecordDecl * castAsRecordDecl() const
Definition: Type.h:48
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isRecordType() const
Definition: TypeBase.h:8707
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2190
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition: Decl.cpp:2851
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
Definition: ABI.h:24
bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType)
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
static bool opCallBitcastArg()
static bool opCallCIRGenFuncInfoExtParamInfo()
static bool implicitConstructorArgs()
static bool emitLifetimeMarkers()
static bool lowerAggregateLoadStore()
static bool opCallSurroundingTry()
static bool sanitizers()
static bool opCallReturn()
static bool opCallPaddingArgs()
static bool opCallExtParameterInfo()
static bool dataLayoutTypeAllocSize()
static bool invokeOp()
static bool opCallObjCMethod()
static bool opCallInAlloca()
static bool opCallCallConv()
static bool opCallAttrs()
static bool opCallImplicitObjectSizeArgs()
static bool opCallMustTail()
static bool cudaSupport()
static bool opCallFnInfoOpts()
static bool opCallCIRGenFuncInfoParamInfo()
llvm::PointerUnion< const clang::FunctionProtoType *, const clang::ObjCMethodDecl * > p
Iterator for iterating over Stmt * arrays that contain only T *.
Definition: Stmt.h:1441