forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCIRGenCall.cpp
154 lines (123 loc) · 5.37 KB
/
CIRGenCall.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===--- CIRGenCall.cpp - Encapsulate calling convention details ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// These classes wrap the information about a call or function definition used
// to handle ABI compliancy.
//
//===----------------------------------------------------------------------===//
#include "CIRGenCall.h"
#include "CIRGenFunction.h"
#include "clang/CIR/MissingFeatures.h"
using namespace clang;
using namespace clang::CIRGen;
CIRGenFunctionInfo *CIRGenFunctionInfo::create(CanQualType resultType) {
void *buffer = operator new(totalSizeToAlloc<ArgInfo>(1));
CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo();
fi->getArgsBuffer()[0].type = resultType;
return fi;
}
CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
assert(!cir::MissingFeatures::opCallVirtual());
return *this;
}
static const CIRGenFunctionInfo &
arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
const FunctionType *fnType) {
if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
if (proto->isVariadic())
cgm.errorNYI("call to variadic function");
if (proto->hasExtParameterInfos())
cgm.errorNYI("call to functions with extra parameter info");
} else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(
cast<FunctionNoProtoType>(fnType)))
cgm.errorNYI("call to function without a prototype");
assert(!cir::MissingFeatures::opCallArgs());
CanQualType retType = fnType->getReturnType()
->getCanonicalTypeUnqualified()
.getUnqualifiedType();
return cgt.arrangeCIRFunctionInfo(retType);
}
const CIRGenFunctionInfo &
CIRGenTypes::arrangeFreeFunctionCall(const FunctionType *fnType) {
return arrangeFreeFunctionLikeCall(*this, cgm, fnType);
}
static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
mlir::Location callLoc,
cir::FuncOp directFuncOp) {
CIRGenBuilderTy &builder = cgf.getBuilder();
assert(!cir::MissingFeatures::opCallSurroundingTry());
assert(!cir::MissingFeatures::invokeOp());
assert(builder.getInsertionBlock() && "expected valid basic block");
assert(!cir::MissingFeatures::opCallIndirect());
return builder.createCallOp(callLoc, directFuncOp);
}
RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
const CIRGenCallee &callee,
ReturnValueSlot returnValue,
cir::CIRCallOpInterface *callOp,
mlir::Location loc) {
QualType retTy = funcInfo.getReturnType();
const cir::ABIArgInfo &retInfo = funcInfo.getReturnInfo();
assert(!cir::MissingFeatures::opCallArgs());
assert(!cir::MissingFeatures::emitLifetimeMarkers());
const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
mlir::Operation *calleePtr = concreteCallee.getFunctionPointer();
assert(!cir::MissingFeatures::opCallInAlloca());
mlir::NamedAttrList attrs;
StringRef funcName;
if (auto calleeFuncOp = dyn_cast<cir::FuncOp>(calleePtr))
funcName = calleeFuncOp.getName();
assert(!cir::MissingFeatures::opCallCallConv());
assert(!cir::MissingFeatures::opCallSideEffect());
assert(!cir::MissingFeatures::opCallAttrs());
assert(!cir::MissingFeatures::invokeOp());
auto directFuncOp = dyn_cast<cir::FuncOp>(calleePtr);
assert(!cir::MissingFeatures::opCallIndirect());
assert(!cir::MissingFeatures::opCallAttrs());
cir::CIRCallOpInterface theCall = emitCallLikeOp(*this, loc, directFuncOp);
if (callOp)
*callOp = theCall;
assert(!cir::MissingFeatures::opCallMustTail());
assert(!cir::MissingFeatures::opCallReturn());
RValue ret;
switch (retInfo.getKind()) {
case cir::ABIArgInfo::Direct: {
mlir::Type retCIRTy = convertType(retTy);
if (retInfo.getCoerceToType() == retCIRTy &&
retInfo.getDirectOffset() == 0) {
switch (getEvaluationKind(retTy)) {
case cir::TEK_Scalar: {
mlir::ResultRange results = theCall->getOpResults();
assert(results.size() == 1 && "unexpected number of returns");
// If the argument doesn't match, perform a bitcast to coerce it. This
// can happen due to trivial type mismatches.
if (results[0].getType() != retCIRTy)
cgm.errorNYI(loc, "bitcast on function return value");
mlir::Region *region = builder.getBlock()->getParent();
if (region != theCall->getParentRegion())
cgm.errorNYI(loc, "function calls with cleanup");
return RValue::get(results[0]);
}
default:
cgm.errorNYI(loc,
"unsupported evaluation kind of function call result");
}
} else
cgm.errorNYI(loc, "unsupported function call form");
break;
}
case cir::ABIArgInfo::Ignore:
// If we are ignoring an argument that had a result, make sure to construct
// the appropriate return value for our caller.
ret = getUndefRValue(retTy);
break;
default:
cgm.errorNYI(loc, "unsupported return value information");
}
return ret;
}