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
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
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.
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
200 // The structor signature may include implicit parameters.
201 [[maybe_unused]] CIRGenCXXABI::AddedStructorArgCounts addedArgs =
202 theCXXABI.buildStructorSignature(gd, argTypes);
204
205 RequiredArgs required =
206 (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
208
209 CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
210 : theCXXABI.hasMostDerivedReturn(gd)
211 ? astContext.VoidPtrTy
212 : astContext.VoidTy;
213
214 assert(!theCXXABI.hasThisReturn(gd) &&
215 "Please send PR with a test and remove this");
216
219
220 return arrangeCIRFunctionInfo(resultType, argTypes, required);
221}
222
223/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
224/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
225/// indicates that there is no meaningful 'this' type, and a null `md` can occur
226/// when calling a method pointer.
228 const CXXMethodDecl *md) {
229 CanQualType recTy;
230 if (rd) {
232 } else {
233 // This can happen with the MS ABI. It shouldn't need anything more than
234 // setting recTy to VoidTy here, but we're flagging it for now because we
235 // don't have the full handling implemented.
236 cgm.errorNYI("deriveThisType: no record decl");
237 recTy = getASTContext().VoidTy;
238 }
239
240 if (md)
241 recTy = CanQualType::CreateUnsafe(getASTContext().getAddrSpaceQualType(
242 recTy, md->getMethodQualifiers().getAddressSpace()));
243 return getASTContext().getPointerType(recTy);
244}
245
246/// Arrange the CIR function layout for a value of the given function type, on
247/// top of any implicit parameters already stored.
248static const CIRGenFunctionInfo &
252 RequiredArgs required =
255 appendParameterTypes(cgt, prefix, fpt);
256 CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
257 return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
258}
259
261 const VarDecl *param,
262 SourceLocation loc) {
263 // StartFunction converted the ABI-lowered parameter(s) into a local alloca.
264 // We need to turn that into an r-value suitable for emitCall
265 Address local = getAddrOfLocalVar(param);
266
267 QualType type = param->getType();
268
269 if (type->getAsCXXRecordDecl()) {
270 cgm.errorNYI(param->getSourceRange(),
271 "emitDelegateCallArg: record argument");
272 return;
273 }
274
275 // GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
276 // argument needs to be the original pointer.
277 if (type->isReferenceType()) {
278 args.add(
279 RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
280 type);
281 } else if (getLangOpts().ObjCAutoRefCount) {
282 cgm.errorNYI(param->getSourceRange(),
283 "emitDelegateCallArg: ObjCAutoRefCount");
284 // For the most part, we just need to load the alloca, except that aggregate
285 // r-values are actually pointers to temporaries.
286 } else {
287 args.add(convertTempToRValue(local, type, loc), type);
288 }
289
290 // Deactivate the cleanup for the callee-destructed param that was pushed.
292 if (type->isRecordType() &&
293 type->castAsRecordDecl()->isParamDestroyedInCallee() &&
294 param->needsDestruction(getContext())) {
295 cgm.errorNYI(param->getSourceRange(),
296 "emitDelegateCallArg: callee-destructed param");
297 }
298}
299
300static const CIRGenFunctionInfo &
302 const CallArgList &args,
303 const FunctionType *fnType) {
304
306
307 if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
308 if (proto->isVariadic())
309 required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
310 if (proto->hasExtParameterInfos())
311 cgm.errorNYI("call to functions with extra parameter info");
314 cgm.errorNYI("call to function without a prototype");
315
317 for (const CallArg &arg : args)
318 argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
319
320 CanQualType retType = fnType->getReturnType()
323
325 return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
326}
327
328/// Arrange a call to a C++ method, passing the given arguments.
329///
330/// extraPrefixArgs is the number of ABI-specific args passed after the `this`
331/// parameter.
332/// passProtoArgs indicates whether `args` has args for the parameters in the
333/// given CXXConstructorDecl.
335 const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
336 unsigned extraPrefixArgs, unsigned extraSuffixArgs, bool passProtoArgs) {
337
338 // FIXME: Kill copy.
340 for (const auto &arg : args)
341 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
342
343 // +1 for implicit this, which should always be args[0]
344 unsigned totalPrefixArgs = 1 + extraPrefixArgs;
345
347 RequiredArgs required = passProtoArgs
349 fpt, totalPrefixArgs + extraSuffixArgs)
351
352 GlobalDecl gd(d, ctorKind);
353 if (theCXXABI.hasThisReturn(gd))
354 cgm.errorNYI(d->getSourceRange(),
355 "arrangeCXXConstructorCall: hasThisReturn");
356 if (theCXXABI.hasMostDerivedReturn(gd))
357 cgm.errorNYI(d->getSourceRange(),
358 "arrangeCXXConstructorCall: hasMostDerivedReturn");
359 CanQualType resultType = astContext.VoidTy;
360
363
364 return arrangeCIRFunctionInfo(resultType, argTypes, required);
365}
366
367/// Arrange a call to a C++ method, passing the given arguments.
368///
369/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
370/// does not count `this`.
372 const CallArgList &args, const FunctionProtoType *proto,
373 RequiredArgs required, unsigned numPrefixArgs) {
375 assert(numPrefixArgs + 1 <= args.size() &&
376 "Emitting a call with less args than the required prefix?");
377
378 // FIXME: Kill copy.
380 for (const CallArg &arg : args)
381 argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
382
387 argTypes, required);
388}
389
390const CIRGenFunctionInfo &
392 const FunctionType *fnType) {
393 return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
394}
395
396/// Arrange the argument and result information for a declaration or definition
397/// of the given C++ non-static member function. The member function must be an
398/// ordinary function, i.e. not a constructor or destructor.
399const CIRGenFunctionInfo &
401 assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
402 assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
403
404 auto prototype =
407
408 if (md->isInstance()) {
409 // The abstract case is perfectly fine.
410 auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
411 return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
412 }
413
414 return arrangeFreeFunctionType(prototype);
415}
416
417/// Arrange the argument and result information for a call to an unknown C++
418/// non-static member function of the given abstract type. (A null RD means we
419/// don't have any meaningful "this" argument type, so fall back to a generic
420/// pointer type). The member fucntion must be an ordinary function, i.e. not a
421/// constructor or destructor.
422const CIRGenFunctionInfo &
424 const FunctionProtoType *fpt,
425 const CXXMethodDecl *md) {
427
428 // Add the 'this' pointer.
429 argTypes.push_back(deriveThisType(rd, md));
430
432 return ::arrangeCIRFunctionInfo(
433 *this, argTypes,
435}
436
437/// Arrange the argument and result information for the declaration or
438/// definition of the given function.
439const CIRGenFunctionInfo &
441 if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
442 if (md->isInstance())
444
446
447 assert(isa<FunctionType>(funcTy));
448 // TODO: setCUDAKernelCallingConvention
450
451 // When declaring a function without a prototype, always use a non-variadic
452 // type.
453 if (CanQual<FunctionNoProtoType> noProto =
454 funcTy.getAs<FunctionNoProtoType>()) {
457 return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
459 }
460
462}
463
464static cir::CIRCallOpInterface
465emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
466 cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
467 cir::FuncOp directFuncOp,
468 const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
469 const mlir::NamedAttrList &attrs) {
470 CIRGenBuilderTy &builder = cgf.getBuilder();
471
473
474 if (isInvoke) {
475 // This call may throw and requires catch and/or cleanup handling.
476 // If this call does not appear within the `try` region of an existing
477 // TryOp, we must create a synthetic TryOp to contain the call. This
478 // happens when a call that may throw appears within a cleanup
479 // scope.
480
481 // In OG, we build the landing pad for this scope. In CIR, we emit a
482 // synthetic cir.try because this didn't come from code generating from a
483 // try/catch in C++.
484 assert(cgf.curLexScope && "expected scope");
485 cir::TryOp tryOp = cgf.curLexScope->getClosestTryParent();
486 if (!tryOp) {
487 cgf.cgm.errorNYI(
488 "emitCallLikeOp: call does not have an associated cir.try");
489 return {};
490 }
491
492 if (tryOp.getSynthetic()) {
493 cgf.cgm.errorNYI("emitCallLikeOp: tryOp synthetic");
494 return {};
495 }
496
497 cir::CallOp callOpWithExceptions;
498 if (indirectFuncTy) {
499 cgf.cgm.errorNYI("emitCallLikeOp: indirect function type");
500 return {};
501 }
502
503 callOpWithExceptions =
504 builder.createCallOp(callLoc, directFuncOp, cirCallArgs);
505
507 return callOpWithExceptions;
508 }
509
510 assert(builder.getInsertionBlock() && "expected valid basic block");
511
512 cir::CallOp op;
513 if (indirectFuncTy) {
514 // TODO(cir): Set calling convention for indirect calls.
516 op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
517 cirCallArgs, attrs);
518 } else {
519 op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);
520 }
521
522 return op;
523}
524
525const CIRGenFunctionInfo &
529 return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
530}
531
532const CIRGenFunctionInfo &
538
540 const CIRGenCallee &callee,
542 const CallArgList &args,
543 cir::CIRCallOpInterface *callOp,
544 mlir::Location loc) {
545 QualType retTy = funcInfo.getReturnType();
546 cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
547
548 SmallVector<mlir::Value, 16> cirCallArgs(args.size());
549
551
552 // Translate all of the arguments as necessary to match the CIR lowering.
553 for (auto [argNo, arg, canQualArgType] :
554 llvm::enumerate(args, funcInfo.argTypes())) {
555
556 // Insert a padding argument to ensure proper alignment.
558
559 mlir::Type argType = convertType(canQualArgType);
560 if (!mlir::isa<cir::RecordType>(argType) &&
561 !mlir::isa<cir::ComplexType>(argType)) {
562 mlir::Value v;
563 if (arg.isAggregate())
564 cgm.errorNYI(loc, "emitCall: aggregate call argument");
565 v = arg.getKnownRValue().getValue();
566
567 // We might have to widen integers, but we should never truncate.
568 if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
569 cgm.errorNYI(loc, "emitCall: widening integer call argument");
570
571 // If the argument doesn't match, perform a bitcast to coerce it. This
572 // can happen due to trivial type mismatches.
573 // TODO(cir): When getFunctionType is added, assert that this isn't
574 // needed.
576 cirCallArgs[argNo] = v;
577 } else {
579 if (!arg.isAggregate()) {
580 src = createMemTemp(arg.ty, loc, "coerce");
581 arg.copyInto(*this, src, loc);
582 } else {
583 src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
584 : arg.getKnownRValue().getAggregateAddress();
585 }
586
587 // Fast-isel and the optimizer generally like scalar values better than
588 // FCAs, so we flatten them if this is safe to do for this argument.
589 mlir::Type srcTy = src.getElementType();
590 // FIXME(cir): get proper location for each argument.
591 mlir::Location argLoc = loc;
592
593 // If the source type is smaller than the destination type of the
594 // coerce-to logic, copy the source value into a temp alloca the size
595 // of the destination type to allow loading all of it. The bits past
596 // the source value are left undef.
597 // FIXME(cir): add data layout info and compare sizes instead of
598 // matching the types.
599 //
600 // uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
601 // uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
602 // if (SrcSize < DstSize) {
604 if (srcTy != argType) {
605 cgm.errorNYI(loc, "emitCall: source type does not match argument type");
606 } else {
607 // FIXME(cir): this currently only runs when the types are exactly the
608 // same, but should be when alloc sizes are the same, fix this as soon
609 // as datalayout gets introduced.
611 }
612
613 // assert(NumCIRArgs == STy.getMembers().size());
614 // In LLVMGen: Still only pass the struct without any gaps but mark it
615 // as such somehow.
616 //
617 // In CIRGen: Emit a load from the "whole" struct,
618 // which shall be broken later by some lowering step into multiple
619 // loads.
621 cirCallArgs[argNo] = builder.createLoad(argLoc, src);
622 }
623 }
624
625 const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
626 mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
627
629
630 mlir::NamedAttrList attrs;
631 StringRef funcName;
632 if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
633 funcName = calleeFuncOp.getName();
634
637 cgm.constructAttributeList(callee.getAbstractInfo(), attrs);
638
639 cir::FuncType indirectFuncTy;
640 mlir::Value indirectFuncVal;
641 cir::FuncOp directFuncOp;
642 if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
643 directFuncOp = fnOp;
644 } else if (auto getGlobalOp = mlir::dyn_cast<cir::GetGlobalOp>(calleePtr)) {
645 // FIXME(cir): This peephole optimization avoids indirect calls for
646 // builtins. This should be fixed in the builtin declaration instead by
647 // not emitting an unecessary get_global in the first place.
648 // However, this is also used for no-prototype functions.
649 mlir::Operation *globalOp = cgm.getGlobalValue(getGlobalOp.getName());
650 assert(globalOp && "undefined global function");
651 directFuncOp = mlir::cast<cir::FuncOp>(globalOp);
652 } else {
653 [[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
654 calleePtr->getResultTypes();
655 [[maybe_unused]] auto funcPtrTy =
656 mlir::dyn_cast<cir::PointerType>(resultTypes.front());
657 assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
658 "expected pointer to function");
659
660 indirectFuncTy = cirFuncTy;
661 indirectFuncVal = calleePtr->getResult(0);
662 }
663
667
668 bool cannotThrow = attrs.getNamed("nothrow").has_value();
669 bool isInvoke = !cannotThrow && isCatchOrCleanupRequired();
670
671 mlir::Location callLoc = loc;
672 cir::CIRCallOpInterface theCall =
673 emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
674 cirCallArgs, isInvoke, attrs);
675
676 if (callOp)
677 *callOp = theCall;
678
681
682 mlir::Type retCIRTy = convertType(retTy);
683 if (isa<cir::VoidType>(retCIRTy))
684 return getUndefRValue(retTy);
685 switch (getEvaluationKind(retTy)) {
686 case cir::TEK_Aggregate: {
687 Address destPtr = returnValue.getValue();
688
689 if (!destPtr.isValid())
690 destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
691
692 mlir::ResultRange results = theCall->getOpResults();
693 assert(results.size() <= 1 && "multiple returns from a call");
694
695 SourceLocRAIIObject loc{*this, callLoc};
696 emitAggregateStore(results[0], destPtr);
697 return RValue::getAggregate(destPtr);
698 }
699 case cir::TEK_Scalar: {
700 mlir::ResultRange results = theCall->getOpResults();
701 assert(results.size() == 1 && "unexpected number of returns");
702
703 // If the argument doesn't match, perform a bitcast to coerce it. This
704 // can happen due to trivial type mismatches.
705 if (results[0].getType() != retCIRTy)
706 cgm.errorNYI(loc, "bitcast on function return value");
707
708 mlir::Region *region = builder.getBlock()->getParent();
709 if (region != theCall->getParentRegion())
710 cgm.errorNYI(loc, "function calls with cleanup");
711
712 return RValue::get(results[0]);
713 }
714 case cir::TEK_Complex: {
715 mlir::ResultRange results = theCall->getOpResults();
716 assert(!results.empty() &&
717 "Expected at least one result for complex rvalue");
718 return RValue::getComplex(results[0]);
719 }
720 }
721 llvm_unreachable("Invalid evaluation kind");
722}
723
725 mlir::Location loc) const {
726 LValue dst = cgf.makeAddrLValue(addr, ty);
727 if (!hasLV && rv.isScalar())
728 cgf.cgm.errorNYI(loc, "copyInto scalar value");
729 else if (!hasLV && rv.isComplex())
730 cgf.emitStoreOfComplex(loc, rv.getComplexValue(), dst, /*isInit=*/true);
731 else
732 cgf.cgm.errorNYI(loc, "copyInto hasLV");
733 isUsed = true;
734}
735
736mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
737 cir::FuncOp callee,
739 // TODO(cir): set the calling convention to this runtime call.
741
742 cir::CallOp call = builder.createCallOp(loc, callee, args);
743 assert(call->getNumResults() <= 1 &&
744 "runtime functions have at most 1 result");
745
746 if (call->getNumResults() == 0)
747 return nullptr;
748
749 return call->getResult(0);
750}
751
753 clang::QualType argType) {
754 assert(argType->isReferenceType() == e->isGLValue() &&
755 "reference binding to unmaterialized r-value!");
756
757 if (e->isGLValue()) {
758 assert(e->getObjectKind() == OK_Ordinary);
759 return args.add(emitReferenceBindingToExpr(e), argType);
760 }
761
762 bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
763
764 // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
765 // However, we still have to push an EH-only cleanup in case we unwind before
766 // we make it to the call.
767 if (argType->isRecordType() &&
770 cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
771 }
772
773 if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
774 cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
775 LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
776 assert(lv.isSimple());
777 args.addUncopiedAggregate(lv, argType);
778 return;
779 }
780
781 args.add(emitAnyExprToTemp(e), argType);
782}
783
784QualType CIRGenFunction::getVarArgType(const Expr *arg) {
785 // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
786 // implicitly widens null pointer constants that are arguments to varargs
787 // functions to pointer-sized ints.
788 if (!getTarget().getTriple().isOSWindows())
789 return arg->getType();
790
792 cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
793 return arg->getType();
794}
795
796/// Similar to emitAnyExpr(), however, the result will always be accessible
797/// even if no aggregate location is provided.
800
802 aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
804
805 return emitAnyExpr(e, aggSlot);
806}
807
809 CallArgList &args, PrototypeWrapper prototype,
810 llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
811 AbstractCallee callee, unsigned paramsToSkip) {
813
815
816 // First, if a prototype was provided, use those argument types.
817 bool isVariadic = false;
818 if (prototype.p) {
820
821 const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
822 isVariadic = fpt->isVariadic();
824 argTypes.assign(fpt->param_type_begin() + paramsToSkip,
825 fpt->param_type_end());
826 }
827
828 // If we still have any arguments, emit them using the type of the argument.
829 for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
830 argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
831 assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
832
833 // We must evaluate arguments from right to left in the MS C++ ABI, because
834 // arguments are destroyed left to right in the callee. As a special case,
835 // there are certain language constructs taht require left-to-right
836 // evaluation, and in those cases we consider the evaluation order requirement
837 // to trump the "destruction order is reverse construction order" guarantee.
838 auto leftToRight = true;
840
841 auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
842 RValue emittedArg) {
843 if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
844 return;
845 auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
846 if (!ps)
847 return;
848
850 cgm.errorNYI("emit implicit object size for call arg");
851 };
852
853 // Evaluate each argument in the appropriate order.
854 size_t callArgsStart = args.size();
855 for (size_t i = 0; i != argTypes.size(); ++i) {
856 size_t idx = leftToRight ? i : argTypes.size() - i - 1;
857 CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
858 size_t initialArgSize = args.size();
859
860 emitCallArg(args, *currentArg, argTypes[idx]);
861
862 // In particular, we depend on it being the last arg in Args, and the
863 // objectsize bits depend on there only being one arg if !LeftToRight.
864 assert(initialArgSize + 1 == args.size() &&
865 "The code below depends on only adding one arg per emitCallArg");
866 (void)initialArgSize;
867
868 // Since pointer argument are never emitted as LValue, it is safe to emit
869 // non-null argument check for r-value only.
870 if (!args.back().hasLValue()) {
871 RValue rvArg = args.back().getKnownRValue();
873 maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
874 }
875
876 if (!leftToRight)
877 std::reverse(args.begin() + callArgsStart, args.end());
878 }
879}
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.
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:111
static Address invalid()
Definition Address.h:69
bool isValid() const
Definition Address.h:70
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: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.
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)
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.
void constructAttributeList(CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs)
Get the CIR attributes and calling convention to use for a particular function type.
CIRGenBuilderTy & getBuilder()
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
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...
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
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.
void addUncopiedAggregate(LValue lvalue, clang::QualType type)
Definition CIRGenCall.h:235
void add(RValue rvalue, clang::QualType type)
Definition CIRGenCall.h:233
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:254
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 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:2877
SourceLocation getBeginLoc() const
Definition Expr.h:3211
ConstExprIterator const_arg_iterator
Definition Expr.h:3125
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:4541
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4832
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5254
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
Definition TypeBase.h:5561
bool isNothrow(bool ResultIfDependent=false) const
Determine whether this function type has a non-throwing exception specification.
Definition TypeBase.h:5653
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4450
QualType getReturnType() const
Definition TypeBase.h:4790
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:4462
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:8539
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
bool isRecordType() const
Definition TypeBase.h:8642
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:2193
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2854
@ 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:206
void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const