18
18
using namespace clang ;
19
19
using namespace clang ::CIRGen;
20
20
21
- CIRGenFunctionInfo *CIRGenFunctionInfo::create () {
22
- // For now we just create an empty CIRGenFunctionInfo.
23
- CIRGenFunctionInfo *fi = new CIRGenFunctionInfo ();
21
+ CIRGenFunctionInfo *CIRGenFunctionInfo::create (CanQualType resultType) {
22
+ void *buffer = operator new (totalSizeToAlloc<ArgInfo>(1 ));
23
+
24
+ CIRGenFunctionInfo *fi = new (buffer) CIRGenFunctionInfo ();
25
+ fi->getArgsBuffer ()[0 ].type = resultType;
26
+
24
27
return fi;
25
28
}
26
29
@@ -29,13 +32,29 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
29
32
return *this ;
30
33
}
31
34
32
- static const CIRGenFunctionInfo &arrangeFreeFunctionLikeCall (CIRGenTypes &cgt) {
35
+ static const CIRGenFunctionInfo &
36
+ arrangeFreeFunctionLikeCall (CIRGenTypes &cgt, CIRGenModule &cgm,
37
+ const FunctionType *fnType) {
38
+ if (const auto *proto = dyn_cast<FunctionProtoType>(fnType)) {
39
+ if (proto->isVariadic ())
40
+ cgm.errorNYI (" call to variadic function" );
41
+ if (proto->hasExtParameterInfos ())
42
+ cgm.errorNYI (" call to functions with extra parameter info" );
43
+ } else if (cgm.getTargetCIRGenInfo ().isNoProtoCallVariadic (
44
+ cast<FunctionNoProtoType>(fnType)))
45
+ cgm.errorNYI (" call to function without a prototype" );
46
+
33
47
assert (!cir::MissingFeatures::opCallArgs ());
34
- return cgt.arrangeCIRFunctionInfo ();
48
+
49
+ CanQualType retType = fnType->getReturnType ()
50
+ ->getCanonicalTypeUnqualified ()
51
+ .getUnqualifiedType ();
52
+ return cgt.arrangeCIRFunctionInfo (retType);
35
53
}
36
54
37
- const CIRGenFunctionInfo &CIRGenTypes::arrangeFreeFunctionCall () {
38
- return arrangeFreeFunctionLikeCall (*this );
55
+ const CIRGenFunctionInfo &
56
+ CIRGenTypes::arrangeFreeFunctionCall (const FunctionType *fnType) {
57
+ return arrangeFreeFunctionLikeCall (*this , cgm, fnType);
39
58
}
40
59
41
60
static cir::CIRCallOpInterface emitCallLikeOp (CIRGenFunction &cgf,
@@ -54,8 +73,12 @@ static cir::CIRCallOpInterface emitCallLikeOp(CIRGenFunction &cgf,
54
73
55
74
RValue CIRGenFunction::emitCall (const CIRGenFunctionInfo &funcInfo,
56
75
const CIRGenCallee &callee,
76
+ ReturnValueSlot returnValue,
57
77
cir::CIRCallOpInterface *callOp,
58
78
mlir::Location loc) {
79
+ QualType retTy = funcInfo.getReturnType ();
80
+ const cir::ABIArgInfo &retInfo = funcInfo.getReturnInfo ();
81
+
59
82
assert (!cir::MissingFeatures::opCallArgs ());
60
83
assert (!cir::MissingFeatures::emitLifetimeMarkers ());
61
84
@@ -87,9 +110,45 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
87
110
assert (!cir::MissingFeatures::opCallMustTail ());
88
111
assert (!cir::MissingFeatures::opCallReturn ());
89
112
90
- // For now we just return nothing because we don't have support for return
91
- // values yet.
92
- RValue ret = RValue::get (nullptr );
113
+ RValue ret;
114
+ switch (retInfo.getKind ()) {
115
+ case cir::ABIArgInfo::Direct: {
116
+ mlir::Type retCIRTy = convertType (retTy);
117
+ if (retInfo.getCoerceToType () == retCIRTy &&
118
+ retInfo.getDirectOffset () == 0 ) {
119
+ switch (getEvaluationKind (retTy)) {
120
+ case cir::TEK_Scalar: {
121
+ mlir::ResultRange results = theCall->getOpResults ();
122
+ assert (results.size () == 1 && " unexpected number of returns" );
123
+
124
+ // If the argument doesn't match, perform a bitcast to coerce it. This
125
+ // can happen due to trivial type mismatches.
126
+ if (results[0 ].getType () != retCIRTy)
127
+ cgm.errorNYI (loc, " bitcast on function return value" );
128
+
129
+ mlir::Region *region = builder.getBlock ()->getParent ();
130
+ if (region != theCall->getParentRegion ())
131
+ cgm.errorNYI (loc, " function calls with cleanup" );
132
+
133
+ return RValue::get (results[0 ]);
134
+ }
135
+ default :
136
+ cgm.errorNYI (loc,
137
+ " unsupported evaluation kind of function call result" );
138
+ }
139
+ } else
140
+ cgm.errorNYI (loc, " unsupported function call form" );
141
+
142
+ break ;
143
+ }
144
+ case cir::ABIArgInfo::Ignore:
145
+ // If we are ignoring an argument that had a result, make sure to construct
146
+ // the appropriate return value for our caller.
147
+ ret = getUndefRValue (retTy);
148
+ break ;
149
+ default :
150
+ cgm.errorNYI (loc, " unsupported return value information" );
151
+ }
93
152
94
153
return ret;
95
154
}
0 commit comments