12
12
// ===----------------------------------------------------------------------===//
13
13
14
14
#include " LowerFunction.h"
15
+ #include " CIRToCIRArgMapping.h"
15
16
#include " LowerCall.h"
17
+ #include " LowerFunctionInfo.h"
16
18
#include " LowerModule.h"
19
+ #include " mlir/IR/MLIRContext.h"
17
20
#include " mlir/IR/PatternMatch.h"
18
21
#include " mlir/Support/LogicalResult.h"
22
+ #include " clang/CIR/ABIArgInfo.h"
23
+ #include " clang/CIR/Dialect/IR/CIRAttrs.h"
19
24
#include " clang/CIR/Dialect/IR/CIRDialect.h"
25
+ #include " clang/CIR/MissingFeatures.h"
26
+ #include " llvm/Support/ErrorHandling.h"
27
+
28
+ using ABIArgInfo = ::cir::ABIArgInfo;
20
29
21
30
namespace mlir {
22
31
namespace cir {
@@ -32,5 +41,329 @@ LowerFunction::LowerFunction(LowerModule &LM, PatternRewriter &rewriter,
32
41
: Target(LM.getTarget()), rewriter(rewriter), SrcFn(srcFn), callOp(callOp),
33
42
LM(LM) {}
34
43
44
+ // / This method has partial parity with CodeGenFunction::EmitFunctionProlog from
45
+ // / the original codegen. However, it focuses on the ABI-specific details. On
46
+ // / top of that, it is also responsible for rewriting the original function.
47
+ LogicalResult
48
+ LowerFunction::buildFunctionProlog (const LowerFunctionInfo &FI, FuncOp Fn,
49
+ MutableArrayRef<BlockArgument> Args) {
50
+ // NOTE(cir): Skipping naked and implicit-return-zero functions here. These
51
+ // are dealt with in CIRGen.
52
+
53
+ CIRToCIRArgMapping IRFunctionArgs (LM.getContext (), FI);
54
+ assert (Fn.getNumArguments () == IRFunctionArgs.totalIRArgs ());
55
+
56
+ // If we're using inalloca, all the memory arguments are GEPs off of the last
57
+ // parameter, which is a pointer to the complete memory area.
58
+ assert (!::cir::MissingFeatures::inallocaArgs ());
59
+
60
+ // Name the struct return parameter.
61
+ assert (!::cir::MissingFeatures::sretArgs ());
62
+
63
+ // Track if we received the parameter as a pointer (indirect, byval, or
64
+ // inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it
65
+ // into a local alloca for us.
66
+ SmallVector<Value, 8 > ArgVals;
67
+ ArgVals.reserve (Args.size ());
68
+
69
+ // Create a pointer value for every parameter declaration. This usually
70
+ // entails copying one or more LLVM IR arguments into an alloca. Don't push
71
+ // any cleanups or do anything that might unwind. We do that separately, so
72
+ // we can push the cleanups in the correct order for the ABI.
73
+ assert (FI.arg_size () == Args.size ());
74
+ unsigned ArgNo = 0 ;
75
+ LowerFunctionInfo::const_arg_iterator info_it = FI.arg_begin ();
76
+ for (MutableArrayRef<BlockArgument>::const_iterator i = Args.begin (),
77
+ e = Args.end ();
78
+ i != e; ++i, ++info_it, ++ArgNo) {
79
+ llvm_unreachable (" NYI" );
80
+ }
81
+
82
+ if (getTarget ().getCXXABI ().areArgsDestroyedLeftToRightInCallee ()) {
83
+ llvm_unreachable (" NYI" );
84
+ } else {
85
+ // FIXME(cir): In the original codegen, EmitParamDecl is called here. It is
86
+ // likely that said function considers ABI details during emission, so we
87
+ // migth have to add a counter part here. Currently, it is not needed.
88
+ }
89
+
90
+ return success ();
91
+ }
92
+
93
+ LogicalResult LowerFunction::buildFunctionEpilog (const LowerFunctionInfo &FI) {
94
+ const ABIArgInfo &RetAI = FI.getReturnInfo ();
95
+
96
+ switch (RetAI.getKind ()) {
97
+
98
+ case ABIArgInfo::Ignore:
99
+ break ;
100
+
101
+ default :
102
+ llvm_unreachable (" Unhandled ABIArgInfo::Kind" );
103
+ }
104
+
105
+ return success ();
106
+ }
107
+
108
+ // / Generate code for a function based on the ABI-specific information.
109
+ // /
110
+ // / This method has partial parity with CodeGenFunction::GenerateCode, but it
111
+ // / focuses on the ABI-specific details. So a lot of codegen stuff is removed.
112
+ LogicalResult LowerFunction::generateCode (FuncOp oldFn, FuncOp newFn,
113
+ const LowerFunctionInfo &FnInfo) {
114
+ assert (newFn && " generating code for null Function" );
115
+ auto Args = oldFn.getArguments ();
116
+
117
+ // Emit the ABI-specific function prologue.
118
+ assert (newFn.empty () && " Function already has a body" );
119
+ rewriter.setInsertionPointToEnd (newFn.addEntryBlock ());
120
+ if (buildFunctionProlog (FnInfo, newFn, oldFn.getArguments ()).failed ())
121
+ return failure ();
122
+
123
+ // Ensure that old ABI-agnostic arguments uses were replaced.
124
+ const auto hasNoUses = [](Value val) { return val.getUses ().empty (); };
125
+ assert (std::all_of (Args.begin (), Args.end (), hasNoUses) && " Missing RAUW?" );
126
+
127
+ // Migrate function body to new ABI-aware function.
128
+ assert (oldFn.getBody ().hasOneBlock () &&
129
+ " Multiple blocks in original function not supported" );
130
+
131
+ // Move old function body to new function.
132
+ // FIXME(cir): The merge below is not very good: will not work if SrcFn has
133
+ // multiple blocks and it mixes the new and old prologues.
134
+ rewriter.mergeBlocks (&oldFn.getBody ().front (), &newFn.getBody ().front (),
135
+ newFn.getArguments ());
136
+
137
+ // FIXME(cir): What about saving parameters for corotines? Should we do
138
+ // something about it in this pass? If the change with the calling
139
+ // convention, we might have to handle this here.
140
+
141
+ // Emit the standard function epilogue.
142
+ if (buildFunctionEpilog (FnInfo).failed ())
143
+ return failure ();
144
+
145
+ return success ();
146
+ }
147
+
148
+ // / Rewrite a call operation to abide to the ABI calling convention.
149
+ // /
150
+ // / FIXME(cir): This method has partial parity to CodeGenFunction's
151
+ // / EmitCallEpxr method defined in CGExpr.cpp. This could likely be
152
+ // / removed in favor of a more direct approach.
153
+ LogicalResult LowerFunction::rewriteCallOp (CallOp op,
154
+ ReturnValueSlot retValSlot) {
155
+
156
+ // TODO(cir): Check if BlockCall, CXXMemberCall, CUDAKernelCall, or
157
+ // CXXOperatorMember require special handling here. These should be handled in
158
+ // CIRGen, unless there is call conv or ABI-specific stuff to be handled, them
159
+ // we should do it here.
160
+
161
+ // TODO(cir): Also check if Builtin and CXXPeseudoDtor need special handling
162
+ // here. These should be handled in CIRGen, unless there is call conv or
163
+ // ABI-specific stuff to be handled, them we should do it here.
164
+
165
+ // NOTE(cir): There is no direct way to fetch the function type from the
166
+ // CallOp, so we fetch it from the source function. This assumes the function
167
+ // definition has not yet been lowered.
168
+ assert (SrcFn && " No source function" );
169
+ auto fnType = SrcFn.getFunctionType ();
170
+
171
+ // Rewrite the call operation to abide to the ABI calling convention.
172
+ auto Ret = rewriteCallOp (fnType, SrcFn, op, retValSlot);
173
+
174
+ // Replace the original call result with the new one.
175
+ if (Ret)
176
+ rewriter.replaceAllUsesWith (op.getResult (), Ret);
177
+
178
+ return success ();
179
+ }
180
+
181
+ // / Rewrite a call operation to abide to the ABI calling convention.
182
+ // /
183
+ // / FIXME(cir): This method has partial parity to CodeGenFunction's EmitCall
184
+ // / method defined in CGExpr.cpp. This could likely be removed in favor of a
185
+ // / more direct approach since most of the code here is exclusively CodeGen.
186
+ Value LowerFunction::rewriteCallOp (FuncType calleeTy, FuncOp origCallee,
187
+ CallOp callOp, ReturnValueSlot retValSlot,
188
+ Value Chain) {
189
+ // NOTE(cir): Skip a bunch of function pointer stuff and AST declaration
190
+ // asserts. Also skip sanitizers, as these should likely be handled at
191
+ // CIRGen.
192
+ CallArgList Args;
193
+ if (Chain)
194
+ llvm_unreachable (" NYI" );
195
+
196
+ // NOTE(cir): Call args were already emitted in CIRGen. Skip the evaluation
197
+ // order done in CIRGen and just fetch the exiting arguments here.
198
+ Args = callOp.getArgOperands ();
199
+
200
+ const LowerFunctionInfo &FnInfo = LM.getTypes ().arrangeFreeFunctionCall (
201
+ callOp.getArgOperands (), calleeTy, /* chainCall=*/ false );
202
+
203
+ // C99 6.5.2.2p6:
204
+ // If the expression that denotes the called function has a type
205
+ // that does not include a prototype, [the default argument
206
+ // promotions are performed]. If the number of arguments does not
207
+ // equal the number of parameters, the behavior is undefined. If
208
+ // the function is defined with a type that includes a prototype,
209
+ // and either the prototype ends with an ellipsis (, ...) or the
210
+ // types of the arguments after promotion are not compatible with
211
+ // the types of the parameters, the behavior is undefined. If the
212
+ // function is defined with a type that does not include a
213
+ // prototype, and the types of the arguments after promotion are
214
+ // not compatible with those of the parameters after promotion,
215
+ // the behavior is undefined [except in some trivial cases].
216
+ // That is, in the general case, we should assume that a call
217
+ // through an unprototyped function type works like a *non-variadic*
218
+ // call. The way we make this work is to cast to the exact type
219
+ // of the promoted arguments.
220
+ //
221
+ // Chain calls use this same code path to add the invisible chain parameter
222
+ // to the function type.
223
+ if (origCallee.getNoProto () || Chain) {
224
+ llvm_unreachable (" NYI" );
225
+ }
226
+
227
+ assert (!::cir::MissingFeatures::CUDA ());
228
+
229
+ // TODO(cir): LLVM IR has the concept of "CallBase", which is a base class for
230
+ // all types of calls. Perhaps we should have a CIR interface to mimic this
231
+ // class.
232
+ CallOp CallOrInvoke = {};
233
+ Value CallResult = {};
234
+ rewriteCallOp (FnInfo, origCallee, callOp, retValSlot, Args, CallOrInvoke,
235
+ /* isMustTail=*/ false , callOp.getLoc ());
236
+
237
+ // NOTE(cir): Skipping debug stuff here.
238
+
239
+ return CallResult;
240
+ }
241
+
242
+ // NOTE(cir): This method has partial parity to CodeGenFunction's EmitCall
243
+ // method in CGCall.cpp. When incrementing it, use the original codegen as a
244
+ // reference: add ABI-specific stuff and skip codegen stuff.
245
+ Value LowerFunction::rewriteCallOp (const LowerFunctionInfo &CallInfo,
246
+ FuncOp Callee, CallOp Caller,
247
+ ReturnValueSlot ReturnValue,
248
+ CallArgList &CallArgs, CallOp CallOrInvoke,
249
+ bool isMustTail, Location loc) {
250
+ // FIXME: We no longer need the types from CallArgs; lift up and simplify.
251
+
252
+ // Handle struct-return functions by passing a pointer to the
253
+ // location that we would like to return into.
254
+ Type RetTy = CallInfo.getReturnType (); // ABI-agnostic type.
255
+ const ::cir::ABIArgInfo &RetAI = CallInfo.getReturnInfo ();
256
+
257
+ FuncType IRFuncTy = LM.getTypes ().getFunctionType (CallInfo);
258
+
259
+ // NOTE(cir): Some target/ABI related checks happen here. I'm skipping them
260
+ // under the assumption that they are handled in CIRGen.
261
+
262
+ // 1. Set up the arguments.
263
+
264
+ // If we're using inalloca, insert the allocation after the stack save.
265
+ // FIXME: Do this earlier rather than hacking it in here!
266
+ if (StructType ArgStruct = CallInfo.getArgStruct ()) {
267
+ llvm_unreachable (" NYI" );
268
+ }
269
+
270
+ CIRToCIRArgMapping IRFunctionArgs (LM.getContext (), CallInfo);
271
+ SmallVector<Value, 16 > IRCallArgs (IRFunctionArgs.totalIRArgs ());
272
+
273
+ // If the call returns a temporary with struct return, create a temporary
274
+ // alloca to hold the result, unless one is given to us.
275
+ if (RetAI.isIndirect () || RetAI.isCoerceAndExpand () || RetAI.isInAlloca ()) {
276
+ llvm_unreachable (" NYI" );
277
+ }
278
+
279
+ assert (!::cir::MissingFeatures::swift ());
280
+
281
+ // NOTE(cir): Skipping lifetime markers here.
282
+
283
+ // Translate all of the arguments as necessary to match the IR lowering.
284
+ assert (CallInfo.arg_size () == CallArgs.size () &&
285
+ " Mismatch between function signature & arguments." );
286
+ unsigned ArgNo = 0 ;
287
+ LowerFunctionInfo::const_arg_iterator info_it = CallInfo.arg_begin ();
288
+ for (auto I = CallArgs.begin (), E = CallArgs.end (); I != E;
289
+ ++I, ++info_it, ++ArgNo) {
290
+ llvm_unreachable (" NYI" );
291
+ }
292
+
293
+ // 2. Prepare the function pointer.
294
+ // NOTE(cir): This is not needed for CIR.
295
+
296
+ // 3. Perform the actual call.
297
+
298
+ // NOTE(cir): CIRGen handle when to "deactive" cleanups. We also skip some
299
+ // debugging stuff here.
300
+
301
+ // Update the largest vector width if any arguments have vector types.
302
+ assert (!::cir::MissingFeatures::vectorType ());
303
+
304
+ // Compute the calling convention and attributes.
305
+
306
+ // FIXME(cir): Skipping call attributes for now. Not sure if we have to do
307
+ // this at all since we already do it for the function definition.
308
+
309
+ // FIXME(cir): Implement the required procedures for strictfp function and
310
+ // fast-math.
311
+
312
+ // FIXME(cir): Add missing call-site attributes here if they are
313
+ // ABI/target-specific, otherwise, do it in CIRGen.
314
+
315
+ // NOTE(cir): Deciding whether to use Call or Invoke is done in CIRGen.
316
+
317
+ // Rewrite the actual call operation.
318
+ // TODO(cir): Handle other types of CIR calls (e.g. cir.try_call).
319
+ // NOTE(cir): We don't know if the callee was already lowered, so we only
320
+ // fetch the name from the callee, while the return type is fetch from the
321
+ // lowering types manager.
322
+ CallOp newCallOp = rewriter.create <CallOp>(
323
+ loc, Caller.getCalleeAttr (), IRFuncTy.getReturnType (), IRCallArgs);
324
+ auto extraAttrs =
325
+ rewriter.getAttr <ExtraFuncAttributesAttr>(rewriter.getDictionaryAttr ({}));
326
+ newCallOp->setAttr (" extra_attrs" , extraAttrs);
327
+
328
+ assert (!::cir::MissingFeatures::vectorType ());
329
+
330
+ // NOTE(cir): Skipping some ObjC, tail-call, debug, and attribute stuff here.
331
+
332
+ // 4. Finish the call.
333
+
334
+ // NOTE(cir): Skipping no-return, isMustTail, swift error handling, and
335
+ // writebacks here. These should be handled in CIRGen, I think.
336
+
337
+ // Convert return value from ABI-agnostic to ABI-aware.
338
+ Value Ret = [&] {
339
+ // NOTE(cir): CIRGen already handled the emission of the return value. We
340
+ // need only to handle the ABI-specific to ABI-agnostic cast here.
341
+ switch (RetAI.getKind ()) {
342
+ case ::cir::ABIArgInfo::Ignore:
343
+ // If we are ignoring an argument that had a result, make sure to
344
+ // construct the appropriate return value for our caller.
345
+ return getUndefRValue (RetTy);
346
+ default :
347
+ llvm::errs () << " Unhandled ABIArgInfo kind: " << RetAI.getKind () << " \n " ;
348
+ llvm_unreachable (" NYI" );
349
+ }
350
+ }();
351
+
352
+ // NOTE(cir): Skipping Emissions, lifetime markers, and dtors here that should
353
+ // be handled in CIRGen.
354
+
355
+ return Ret;
356
+ }
357
+
358
+ // NOTE(cir): This method has partial parity to CodeGenFunction's GetUndefRValue
359
+ // defined in CGExpr.cpp.
360
+ Value LowerFunction::getUndefRValue (Type Ty) {
361
+ if (Ty.isa <VoidType>())
362
+ return nullptr ;
363
+
364
+ llvm::outs () << " Missing undef handler for value type: " << Ty << " \n " ;
365
+ llvm_unreachable (" NYI" );
366
+ }
367
+
35
368
} // namespace cir
36
369
} // namespace mlir
0 commit comments