Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenCall.cpp
213799 views
1
//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// These classes wrap the information about a call or function definition used
10
// to handle ABI compliancy.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "CIRGenCall.h"
15
#include "CIRGenCXXABI.h"
16
#include "CIRGenFunction.h"
17
#include "CIRGenFunctionInfo.h"
18
#include "clang/CIR/MissingFeatures.h"
19
20
using namespace clang;
21
using namespace clang::CIRGen;
22
23
CIRGenFunctionInfo *
24
CIRGenFunctionInfo::create(CanQualType resultType,
25
llvm::ArrayRef<CanQualType> argTypes,
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
31
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoParamInfo());
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());
40
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
41
42
return fi;
43
}
44
45
cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
46
mlir::Type resultType = convertType(fi.getReturnType());
47
SmallVector<mlir::Type, 8> argTypes;
48
argTypes.reserve(fi.getNumRequiredArgs());
49
50
for (const CanQualType &argType : fi.requiredArguments())
51
argTypes.push_back(convertType(argType));
52
53
return cir::FuncType::get(argTypes,
54
(resultType ? resultType : builder.getVoidTy()),
55
fi.isVariadic());
56
}
57
58
CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
59
assert(!cir::MissingFeatures::opCallVirtual());
60
return *this;
61
}
62
63
void CIRGenFunction::emitAggregateStore(mlir::Value value, Address dest) {
64
// In classic codegen:
65
// Function to store a first-class aggregate into memory. We prefer to
66
// store the elements rather than the aggregate to be more friendly to
67
// fast-isel.
68
// In CIR codegen:
69
// Emit the most simple cir.store possible (e.g. a store for a whole
70
// record), which can later be broken down in other CIR levels (or prior
71
// to dialect codegen).
72
73
// Stored result for the callers of this function expected to be in the same
74
// scope as the value, don't make assumptions about current insertion point.
75
mlir::OpBuilder::InsertionGuard guard(builder);
76
builder.setInsertionPointAfter(value.getDefiningOp());
77
builder.createStore(*currSrcLoc, value, dest);
78
}
79
80
static void addAttributesFromFunctionProtoType(CIRGenBuilderTy &builder,
81
mlir::NamedAttrList &attrs,
82
const FunctionProtoType *fpt) {
83
if (!fpt)
84
return;
85
86
if (!isUnresolvedExceptionSpec(fpt->getExceptionSpecType()) &&
87
fpt->isNothrow())
88
attrs.set(cir::CIRDialect::getNoThrowAttrName(),
89
mlir::UnitAttr::get(builder.getContext()));
90
}
91
92
/// Construct the CIR attribute list of a function or call.
93
void CIRGenModule::constructAttributeList(CIRGenCalleeInfo calleeInfo,
94
mlir::NamedAttrList &attrs) {
95
assert(!cir::MissingFeatures::opCallCallConv());
96
auto sideEffect = cir::SideEffect::All;
97
98
addAttributesFromFunctionProtoType(getBuilder(), attrs,
99
calleeInfo.getCalleeFunctionProtoType());
100
101
const Decl *targetDecl = calleeInfo.getCalleeDecl().getDecl();
102
103
if (targetDecl) {
104
if (targetDecl->hasAttr<NoThrowAttr>())
105
attrs.set(cir::CIRDialect::getNoThrowAttrName(),
106
mlir::UnitAttr::get(&getMLIRContext()));
107
108
if (const FunctionDecl *func = dyn_cast<FunctionDecl>(targetDecl)) {
109
addAttributesFromFunctionProtoType(
110
getBuilder(), attrs, func->getType()->getAs<FunctionProtoType>());
111
assert(!cir::MissingFeatures::opCallAttrs());
112
}
113
114
assert(!cir::MissingFeatures::opCallAttrs());
115
116
// 'const', 'pure' and 'noalias' attributed functions are also nounwind.
117
if (targetDecl->hasAttr<ConstAttr>()) {
118
// gcc specifies that 'const' functions have greater restrictions than
119
// 'pure' functions, so they also cannot have infinite loops.
120
sideEffect = cir::SideEffect::Const;
121
} else if (targetDecl->hasAttr<PureAttr>()) {
122
// gcc specifies that 'pure' functions cannot have infinite loops.
123
sideEffect = cir::SideEffect::Pure;
124
}
125
126
assert(!cir::MissingFeatures::opCallAttrs());
127
}
128
129
assert(!cir::MissingFeatures::opCallAttrs());
130
131
attrs.set(cir::CIRDialect::getSideEffectAttrName(),
132
cir::SideEffectAttr::get(&getMLIRContext(), sideEffect));
133
}
134
135
/// Returns the canonical formal type of the given C++ method.
136
static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) {
137
return md->getType()
138
->getCanonicalTypeUnqualified()
139
.getAs<FunctionProtoType>();
140
}
141
142
/// Adds the formal parameters in FPT to the given prefix. If any parameter in
143
/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
144
/// TODO(cir): this should be shared with LLVM codegen
145
static void appendParameterTypes(const CIRGenTypes &cgt,
146
SmallVectorImpl<CanQualType> &prefix,
147
CanQual<FunctionProtoType> fpt) {
148
assert(!cir::MissingFeatures::opCallExtParameterInfo());
149
// Fast path: don't touch param info if we don't need to.
150
if (!fpt->hasExtParameterInfos()) {
151
prefix.append(fpt->param_type_begin(), fpt->param_type_end());
152
return;
153
}
154
155
cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
156
}
157
158
const CIRGenFunctionInfo &
159
CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
160
auto *md = cast<CXXMethodDecl>(gd.getDecl());
161
162
llvm::SmallVector<CanQualType, 16> argTypes;
163
argTypes.push_back(deriveThisType(md->getParent(), md));
164
165
bool passParams = true;
166
167
if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
168
// A base class inheriting constructor doesn't get forwarded arguments
169
// needed to construct a virtual base (or base class thereof)
170
if (cd->getInheritedConstructor())
171
cgm.errorNYI(cd->getSourceRange(),
172
"arrangeCXXStructorDeclaration: inheriting constructor");
173
}
174
175
CanQual<FunctionProtoType> fpt = getFormalType(md);
176
177
if (passParams)
178
appendParameterTypes(*this, argTypes, fpt);
179
180
assert(!cir::MissingFeatures::implicitConstructorArgs());
181
182
RequiredArgs required =
183
(passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
184
: RequiredArgs::All);
185
186
CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
187
: theCXXABI.hasMostDerivedReturn(gd)
188
? astContext.VoidPtrTy
189
: astContext.VoidTy;
190
191
assert(!theCXXABI.hasThisReturn(gd) &&
192
"Please send PR with a test and remove this");
193
194
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
195
assert(!cir::MissingFeatures::opCallFnInfoOpts());
196
197
return arrangeCIRFunctionInfo(resultType, argTypes, required);
198
}
199
200
/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
201
/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
202
/// indicates that there is no meaningful 'this' type, and a null `md` can occur
203
/// when calling a method pointer.
204
CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,
205
const CXXMethodDecl *md) {
206
QualType recTy;
207
if (rd) {
208
recTy = getASTContext().getTagDeclType(rd)->getCanonicalTypeInternal();
209
} else {
210
// This can happen with the MS ABI. It shouldn't need anything more than
211
// setting recTy to VoidTy here, but we're flagging it for now because we
212
// don't have the full handling implemented.
213
cgm.errorNYI("deriveThisType: no record decl");
214
recTy = getASTContext().VoidTy;
215
}
216
217
if (md)
218
recTy = getASTContext().getAddrSpaceQualType(
219
recTy, md->getMethodQualifiers().getAddressSpace());
220
return getASTContext().getPointerType(CanQualType::CreateUnsafe(recTy));
221
}
222
223
/// Arrange the CIR function layout for a value of the given function type, on
224
/// top of any implicit parameters already stored.
225
static const CIRGenFunctionInfo &
226
arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix,
227
CanQual<FunctionProtoType> fpt) {
228
assert(!cir::MissingFeatures::opCallFnInfoOpts());
229
RequiredArgs required =
230
RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size());
231
assert(!cir::MissingFeatures::opCallExtParameterInfo());
232
appendParameterTypes(cgt, prefix, fpt);
233
CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
234
return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
235
}
236
237
void CIRGenFunction::emitDelegateCallArg(CallArgList &args,
238
const VarDecl *param,
239
SourceLocation loc) {
240
// StartFunction converted the ABI-lowered parameter(s) into a local alloca.
241
// We need to turn that into an r-value suitable for emitCall
242
Address local = getAddrOfLocalVar(param);
243
244
QualType type = param->getType();
245
246
if (type->getAsCXXRecordDecl()) {
247
cgm.errorNYI(param->getSourceRange(),
248
"emitDelegateCallArg: record argument");
249
return;
250
}
251
252
// GetAddrOfLocalVar returns a pointer-to-pointer for references, but the
253
// argument needs to be the original pointer.
254
if (type->isReferenceType()) {
255
args.add(
256
RValue::get(builder.createLoad(getLoc(param->getSourceRange()), local)),
257
type);
258
} else if (getLangOpts().ObjCAutoRefCount) {
259
cgm.errorNYI(param->getSourceRange(),
260
"emitDelegateCallArg: ObjCAutoRefCount");
261
// For the most part, we just need to load the alloca, except that aggregate
262
// r-values are actually pointers to temporaries.
263
} else {
264
args.add(convertTempToRValue(local, type, loc), type);
265
}
266
267
// Deactivate the cleanup for the callee-destructed param that was pushed.
268
assert(!cir::MissingFeatures::thunks());
269
if (type->isRecordType() &&
270
type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
271
param->needsDestruction(getContext())) {
272
cgm.errorNYI(param->getSourceRange(),
273
"emitDelegateCallArg: callee-destructed param");
274
}
275
}
276
277
static const CIRGenFunctionInfo &
278
arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
279
const CallArgList &args,
280
const FunctionType *fnType) {
281
282
RequiredArgs required = RequiredArgs::All;
283
284
if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
285
if (proto->isVariadic())
286
required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
287
if (proto->hasExtParameterInfos())
288
cgm.errorNYI("call to functions with extra parameter info");
289
} else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(
290
cast<FunctionNoProtoType>(fnType)))
291
cgm.errorNYI("call to function without a prototype");
292
293
SmallVector<CanQualType, 16> argTypes;
294
for (const CallArg &arg : args)
295
argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
296
297
CanQualType retType = fnType->getReturnType()
298
->getCanonicalTypeUnqualified()
299
.getUnqualifiedType();
300
301
assert(!cir::MissingFeatures::opCallFnInfoOpts());
302
return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
303
}
304
305
/// Arrange a call to a C++ method, passing the given arguments.
306
///
307
/// passProtoArgs indicates whether `args` has args for the parameters in the
308
/// given CXXConstructorDecl.
309
const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
310
const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
311
bool passProtoArgs) {
312
313
// FIXME: Kill copy.
314
llvm::SmallVector<CanQualType, 16> argTypes;
315
for (const auto &arg : args)
316
argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
317
318
assert(!cir::MissingFeatures::implicitConstructorArgs());
319
// +1 for implicit this, which should always be args[0]
320
unsigned totalPrefixArgs = 1;
321
322
CanQual<FunctionProtoType> fpt = getFormalType(d);
323
RequiredArgs required =
324
passProtoArgs
325
? RequiredArgs::getFromProtoWithExtraSlots(fpt, totalPrefixArgs)
326
: RequiredArgs::All;
327
328
GlobalDecl gd(d, ctorKind);
329
if (theCXXABI.hasThisReturn(gd))
330
cgm.errorNYI(d->getSourceRange(),
331
"arrangeCXXConstructorCall: hasThisReturn");
332
if (theCXXABI.hasMostDerivedReturn(gd))
333
cgm.errorNYI(d->getSourceRange(),
334
"arrangeCXXConstructorCall: hasMostDerivedReturn");
335
CanQualType resultType = astContext.VoidTy;
336
337
assert(!cir::MissingFeatures::opCallFnInfoOpts());
338
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
339
340
return arrangeCIRFunctionInfo(resultType, argTypes, required);
341
}
342
343
/// Arrange a call to a C++ method, passing the given arguments.
344
///
345
/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
346
/// does not count `this`.
347
const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXMethodCall(
348
const CallArgList &args, const FunctionProtoType *proto,
349
RequiredArgs required, unsigned numPrefixArgs) {
350
assert(!cir::MissingFeatures::opCallExtParameterInfo());
351
assert(numPrefixArgs + 1 <= args.size() &&
352
"Emitting a call with less args than the required prefix?");
353
354
// FIXME: Kill copy.
355
llvm::SmallVector<CanQualType, 16> argTypes;
356
for (const CallArg &arg : args)
357
argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
358
359
assert(!cir::MissingFeatures::opCallFnInfoOpts());
360
return arrangeCIRFunctionInfo(proto->getReturnType()
361
->getCanonicalTypeUnqualified()
362
.getUnqualifiedType(),
363
argTypes, required);
364
}
365
366
const CIRGenFunctionInfo &
367
CIRGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
368
const FunctionType *fnType) {
369
return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
370
}
371
372
/// Arrange the argument and result information for a declaration or definition
373
/// of the given C++ non-static member function. The member function must be an
374
/// ordinary function, i.e. not a constructor or destructor.
375
const CIRGenFunctionInfo &
376
CIRGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *md) {
377
assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
378
assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
379
380
auto prototype =
381
md->getType()->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();
382
assert(!cir::MissingFeatures::cudaSupport());
383
384
if (md->isInstance()) {
385
// The abstract case is perfectly fine.
386
auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
387
return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
388
}
389
390
return arrangeFreeFunctionType(prototype);
391
}
392
393
/// Arrange the argument and result information for a call to an unknown C++
394
/// non-static member function of the given abstract type. (A null RD means we
395
/// don't have any meaningful "this" argument type, so fall back to a generic
396
/// pointer type). The member fucntion must be an ordinary function, i.e. not a
397
/// constructor or destructor.
398
const CIRGenFunctionInfo &
399
CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
400
const FunctionProtoType *fpt,
401
const CXXMethodDecl *md) {
402
llvm::SmallVector<CanQualType, 16> argTypes;
403
404
// Add the 'this' pointer.
405
argTypes.push_back(deriveThisType(rd, md));
406
407
assert(!cir::MissingFeatures::opCallFnInfoOpts());
408
return ::arrangeCIRFunctionInfo(
409
*this, argTypes,
410
fpt->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
411
}
412
413
/// Arrange the argument and result information for the declaration or
414
/// definition of the given function.
415
const CIRGenFunctionInfo &
416
CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl *fd) {
417
if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
418
if (md->isInstance())
419
return arrangeCXXMethodDeclaration(md);
420
421
CanQualType funcTy = fd->getType()->getCanonicalTypeUnqualified();
422
423
assert(isa<FunctionType>(funcTy));
424
// TODO: setCUDAKernelCallingConvention
425
assert(!cir::MissingFeatures::cudaSupport());
426
427
// When declaring a function without a prototype, always use a non-variadic
428
// type.
429
if (CanQual<FunctionNoProtoType> noProto =
430
funcTy.getAs<FunctionNoProtoType>()) {
431
assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
432
assert(!cir::MissingFeatures::opCallFnInfoOpts());
433
return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
434
RequiredArgs::All);
435
}
436
437
return arrangeFreeFunctionType(funcTy.castAs<FunctionProtoType>());
438
}
439
440
static cir::CIRCallOpInterface
441
emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
442
cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
443
cir::FuncOp directFuncOp,
444
const SmallVectorImpl<mlir::Value> &cirCallArgs,
445
const mlir::NamedAttrList &attrs) {
446
CIRGenBuilderTy &builder = cgf.getBuilder();
447
448
assert(!cir::MissingFeatures::opCallSurroundingTry());
449
assert(!cir::MissingFeatures::invokeOp());
450
451
assert(builder.getInsertionBlock() && "expected valid basic block");
452
453
cir::CallOp op;
454
if (indirectFuncTy) {
455
// TODO(cir): Set calling convention for indirect calls.
456
assert(!cir::MissingFeatures::opCallCallConv());
457
op = builder.createIndirectCallOp(callLoc, indirectFuncVal, indirectFuncTy,
458
cirCallArgs, attrs);
459
} else {
460
op = builder.createCallOp(callLoc, directFuncOp, cirCallArgs, attrs);
461
}
462
463
return op;
464
}
465
466
const CIRGenFunctionInfo &
467
CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt) {
468
SmallVector<CanQualType, 16> argTypes;
469
assert(!cir::MissingFeatures::opCallFnInfoOpts());
470
return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
471
}
472
473
const CIRGenFunctionInfo &
474
CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
475
CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
476
assert(!cir::MissingFeatures::opCallFnInfoOpts());
477
return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
478
}
479
480
RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
481
const CIRGenCallee &callee,
482
ReturnValueSlot returnValue,
483
const CallArgList &args,
484
cir::CIRCallOpInterface *callOp,
485
mlir::Location loc) {
486
QualType retTy = funcInfo.getReturnType();
487
cir::FuncType cirFuncTy = getTypes().getFunctionType(funcInfo);
488
489
SmallVector<mlir::Value, 16> cirCallArgs(args.size());
490
491
assert(!cir::MissingFeatures::emitLifetimeMarkers());
492
493
// Translate all of the arguments as necessary to match the CIR lowering.
494
for (auto [argNo, arg, canQualArgType] :
495
llvm::enumerate(args, funcInfo.argTypes())) {
496
497
// Insert a padding argument to ensure proper alignment.
498
assert(!cir::MissingFeatures::opCallPaddingArgs());
499
500
mlir::Type argType = convertType(canQualArgType);
501
if (!mlir::isa<cir::RecordType>(argType)) {
502
mlir::Value v;
503
if (arg.isAggregate())
504
cgm.errorNYI(loc, "emitCall: aggregate call argument");
505
v = arg.getKnownRValue().getValue();
506
507
// We might have to widen integers, but we should never truncate.
508
if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
509
cgm.errorNYI(loc, "emitCall: widening integer call argument");
510
511
// If the argument doesn't match, perform a bitcast to coerce it. This
512
// can happen due to trivial type mismatches.
513
// TODO(cir): When getFunctionType is added, assert that this isn't
514
// needed.
515
assert(!cir::MissingFeatures::opCallBitcastArg());
516
cirCallArgs[argNo] = v;
517
} else {
518
Address src = Address::invalid();
519
if (!arg.isAggregate())
520
cgm.errorNYI(loc, "emitCall: non-aggregate call argument");
521
else
522
src = arg.hasLValue() ? arg.getKnownLValue().getAddress()
523
: arg.getKnownRValue().getAggregateAddress();
524
525
// Fast-isel and the optimizer generally like scalar values better than
526
// FCAs, so we flatten them if this is safe to do for this argument.
527
auto argRecordTy = cast<cir::RecordType>(argType);
528
mlir::Type srcTy = src.getElementType();
529
// FIXME(cir): get proper location for each argument.
530
mlir::Location argLoc = loc;
531
532
// If the source type is smaller than the destination type of the
533
// coerce-to logic, copy the source value into a temp alloca the size
534
// of the destination type to allow loading all of it. The bits past
535
// the source value are left undef.
536
// FIXME(cir): add data layout info and compare sizes instead of
537
// matching the types.
538
//
539
// uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
540
// uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
541
// if (SrcSize < DstSize) {
542
assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
543
if (srcTy != argRecordTy) {
544
cgm.errorNYI(loc, "emitCall: source type does not match argument type");
545
} else {
546
// FIXME(cir): this currently only runs when the types are exactly the
547
// same, but should be when alloc sizes are the same, fix this as soon
548
// as datalayout gets introduced.
549
assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
550
}
551
552
// assert(NumCIRArgs == STy.getMembers().size());
553
// In LLVMGen: Still only pass the struct without any gaps but mark it
554
// as such somehow.
555
//
556
// In CIRGen: Emit a load from the "whole" struct,
557
// which shall be broken later by some lowering step into multiple
558
// loads.
559
assert(!cir::MissingFeatures::lowerAggregateLoadStore());
560
cirCallArgs[argNo] = builder.createLoad(argLoc, src);
561
}
562
}
563
564
const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
565
mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
566
567
assert(!cir::MissingFeatures::opCallInAlloca());
568
569
mlir::NamedAttrList attrs;
570
StringRef funcName;
571
if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
572
funcName = calleeFuncOp.getName();
573
574
assert(!cir::MissingFeatures::opCallCallConv());
575
assert(!cir::MissingFeatures::opCallAttrs());
576
cgm.constructAttributeList(callee.getAbstractInfo(), attrs);
577
578
assert(!cir::MissingFeatures::invokeOp());
579
580
cir::FuncType indirectFuncTy;
581
mlir::Value indirectFuncVal;
582
cir::FuncOp directFuncOp;
583
if (auto fnOp = dyn_cast<cir::FuncOp>(calleePtr)) {
584
directFuncOp = fnOp;
585
} else {
586
[[maybe_unused]] mlir::ValueTypeRange<mlir::ResultRange> resultTypes =
587
calleePtr->getResultTypes();
588
[[maybe_unused]] auto funcPtrTy =
589
mlir::dyn_cast<cir::PointerType>(resultTypes.front());
590
assert(funcPtrTy && mlir::isa<cir::FuncType>(funcPtrTy.getPointee()) &&
591
"expected pointer to function");
592
593
indirectFuncTy = cirFuncTy;
594
indirectFuncVal = calleePtr->getResult(0);
595
}
596
597
mlir::Location callLoc = loc;
598
cir::CIRCallOpInterface theCall =
599
emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
600
cirCallArgs, attrs);
601
602
if (callOp)
603
*callOp = theCall;
604
605
assert(!cir::MissingFeatures::opCallMustTail());
606
assert(!cir::MissingFeatures::opCallReturn());
607
608
mlir::Type retCIRTy = convertType(retTy);
609
if (isa<cir::VoidType>(retCIRTy))
610
return getUndefRValue(retTy);
611
switch (getEvaluationKind(retTy)) {
612
case cir::TEK_Aggregate: {
613
Address destPtr = returnValue.getValue();
614
615
if (!destPtr.isValid())
616
destPtr = createMemTemp(retTy, callLoc, getCounterAggTmpAsString());
617
618
mlir::ResultRange results = theCall->getOpResults();
619
assert(results.size() <= 1 && "multiple returns from a call");
620
621
SourceLocRAIIObject loc{*this, callLoc};
622
emitAggregateStore(results[0], destPtr);
623
return RValue::getAggregate(destPtr);
624
}
625
case cir::TEK_Scalar: {
626
mlir::ResultRange results = theCall->getOpResults();
627
assert(results.size() == 1 && "unexpected number of returns");
628
629
// If the argument doesn't match, perform a bitcast to coerce it. This
630
// can happen due to trivial type mismatches.
631
if (results[0].getType() != retCIRTy)
632
cgm.errorNYI(loc, "bitcast on function return value");
633
634
mlir::Region *region = builder.getBlock()->getParent();
635
if (region != theCall->getParentRegion())
636
cgm.errorNYI(loc, "function calls with cleanup");
637
638
return RValue::get(results[0]);
639
}
640
case cir::TEK_Complex:
641
cgm.errorNYI(loc, "unsupported evaluation kind of function call result");
642
return getUndefRValue(retTy);
643
}
644
llvm_unreachable("Invalid evaluation kind");
645
}
646
647
void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
648
clang::QualType argType) {
649
assert(argType->isReferenceType() == e->isGLValue() &&
650
"reference binding to unmaterialized r-value!");
651
652
if (e->isGLValue()) {
653
assert(e->getObjectKind() == OK_Ordinary);
654
return args.add(emitReferenceBindingToExpr(e), argType);
655
}
656
657
bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
658
659
// In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
660
// However, we still have to push an EH-only cleanup in case we unwind before
661
// we make it to the call.
662
if (argType->isRecordType() &&
663
argType->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
664
assert(!cir::MissingFeatures::msabi());
665
cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
666
}
667
668
if (hasAggregateEvalKind && isa<ImplicitCastExpr>(e) &&
669
cast<CastExpr>(e)->getCastKind() == CK_LValueToRValue) {
670
LValue lv = emitLValue(cast<CastExpr>(e)->getSubExpr());
671
assert(lv.isSimple());
672
args.addUncopiedAggregate(lv, argType);
673
return;
674
}
675
676
args.add(emitAnyExprToTemp(e), argType);
677
}
678
679
QualType CIRGenFunction::getVarArgType(const Expr *arg) {
680
// System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
681
// implicitly widens null pointer constants that are arguments to varargs
682
// functions to pointer-sized ints.
683
if (!getTarget().getTriple().isOSWindows())
684
return arg->getType();
685
686
assert(!cir::MissingFeatures::msabi());
687
cgm.errorNYI(arg->getSourceRange(), "getVarArgType: NYI for Windows target");
688
return arg->getType();
689
}
690
691
/// Similar to emitAnyExpr(), however, the result will always be accessible
692
/// even if no aggregate location is provided.
693
RValue CIRGenFunction::emitAnyExprToTemp(const Expr *e) {
694
AggValueSlot aggSlot = AggValueSlot::ignored();
695
696
if (hasAggregateEvaluationKind(e->getType()))
697
aggSlot = createAggTemp(e->getType(), getLoc(e->getSourceRange()),
698
getCounterAggTmpAsString());
699
700
return emitAnyExpr(e, aggSlot);
701
}
702
703
void CIRGenFunction::emitCallArgs(
704
CallArgList &args, PrototypeWrapper prototype,
705
llvm::iterator_range<clang::CallExpr::const_arg_iterator> argRange,
706
AbstractCallee callee, unsigned paramsToSkip) {
707
llvm::SmallVector<QualType, 16> argTypes;
708
709
assert(!cir::MissingFeatures::opCallCallConv());
710
711
// First, if a prototype was provided, use those argument types.
712
bool isVariadic = false;
713
if (prototype.p) {
714
assert(!cir::MissingFeatures::opCallObjCMethod());
715
716
const auto *fpt = cast<const FunctionProtoType *>(prototype.p);
717
isVariadic = fpt->isVariadic();
718
assert(!cir::MissingFeatures::opCallCallConv());
719
argTypes.assign(fpt->param_type_begin() + paramsToSkip,
720
fpt->param_type_end());
721
}
722
723
// If we still have any arguments, emit them using the type of the argument.
724
for (const clang::Expr *a : llvm::drop_begin(argRange, argTypes.size()))
725
argTypes.push_back(isVariadic ? getVarArgType(a) : a->getType());
726
assert(argTypes.size() == (size_t)(argRange.end() - argRange.begin()));
727
728
// We must evaluate arguments from right to left in the MS C++ ABI, because
729
// arguments are destroyed left to right in the callee. As a special case,
730
// there are certain language constructs taht require left-to-right
731
// evaluation, and in those cases we consider the evaluation order requirement
732
// to trump the "destruction order is reverse construction order" guarantee.
733
auto leftToRight = true;
734
assert(!cir::MissingFeatures::msabi());
735
736
auto maybeEmitImplicitObjectSize = [&](size_t i, const Expr *arg,
737
RValue emittedArg) {
738
if (!callee.hasFunctionDecl() || i >= callee.getNumParams())
739
return;
740
auto *ps = callee.getParamDecl(i)->getAttr<PassObjectSizeAttr>();
741
if (!ps)
742
return;
743
744
assert(!cir::MissingFeatures::opCallImplicitObjectSizeArgs());
745
cgm.errorNYI("emit implicit object size for call arg");
746
};
747
748
// Evaluate each argument in the appropriate order.
749
size_t callArgsStart = args.size();
750
for (size_t i = 0; i != argTypes.size(); ++i) {
751
size_t idx = leftToRight ? i : argTypes.size() - i - 1;
752
CallExpr::const_arg_iterator currentArg = argRange.begin() + idx;
753
size_t initialArgSize = args.size();
754
755
emitCallArg(args, *currentArg, argTypes[idx]);
756
757
// In particular, we depend on it being the last arg in Args, and the
758
// objectsize bits depend on there only being one arg if !LeftToRight.
759
assert(initialArgSize + 1 == args.size() &&
760
"The code below depends on only adding one arg per emitCallArg");
761
(void)initialArgSize;
762
763
// Since pointer argument are never emitted as LValue, it is safe to emit
764
// non-null argument check for r-value only.
765
if (!args.back().hasLValue()) {
766
RValue rvArg = args.back().getKnownRValue();
767
assert(!cir::MissingFeatures::sanitizers());
768
maybeEmitImplicitObjectSize(idx, *currentArg, rvArg);
769
}
770
771
if (!leftToRight)
772
std::reverse(args.begin() + callArgsStart, args.end());
773
}
774
}
775
776