@@ -108,6 +108,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
108
108
default :
109
109
report_fatal_error (" Unsupported calling convention" );
110
110
case CallingConv::C:
111
+ case CallingConv::Fast:
111
112
break ;
112
113
}
113
114
@@ -144,6 +145,135 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
144
145
return Chain;
145
146
}
146
147
148
+ // Lower a call to a callseq_start + CALL + callseq_end chain, and add input
149
+ // and output parameter nodes.
150
+ SDValue RISCVTargetLowering::LowerCall (CallLoweringInfo &CLI,
151
+ SmallVectorImpl<SDValue> &InVals) const {
152
+ SelectionDAG &DAG = CLI.DAG ;
153
+ SDLoc &DL = CLI.DL ;
154
+ SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs ;
155
+ SmallVectorImpl<SDValue> &OutVals = CLI.OutVals ;
156
+ SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins ;
157
+ SDValue Chain = CLI.Chain ;
158
+ SDValue Callee = CLI.Callee ;
159
+ CLI.IsTailCall = false ;
160
+ CallingConv::ID CallConv = CLI.CallConv ;
161
+ bool IsVarArg = CLI.IsVarArg ;
162
+ EVT PtrVT = getPointerTy (DAG.getDataLayout ());
163
+
164
+ if (IsVarArg) {
165
+ report_fatal_error (" LowerCall with varargs not implemented" );
166
+ }
167
+
168
+ MachineFunction &MF = DAG.getMachineFunction ();
169
+
170
+ // Analyze the operands of the call, assigning locations to each operand.
171
+ SmallVector<CCValAssign, 16 > ArgLocs;
172
+ CCState ArgCCInfo (CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext ());
173
+ ArgCCInfo.AnalyzeCallOperands (Outs, CC_RISCV32);
174
+
175
+ // Get a count of how many bytes are to be pushed on the stack.
176
+ unsigned NumBytes = ArgCCInfo.getNextStackOffset ();
177
+
178
+ for (auto &Arg : Outs) {
179
+ if (!Arg.Flags .isByVal ())
180
+ continue ;
181
+ report_fatal_error (" Passing arguments byval not yet implemented" );
182
+ }
183
+
184
+ Chain = DAG.getCALLSEQ_START (Chain, NumBytes, 0 , CLI.DL );
185
+
186
+ // Copy argument values to their designated locations.
187
+ SmallVector<std::pair<unsigned , SDValue>, 8 > RegsToPass;
188
+ SDValue StackPtr;
189
+ for (unsigned I = 0 , E = ArgLocs.size (); I != E; ++I) {
190
+ CCValAssign &VA = ArgLocs[I];
191
+ SDValue ArgValue = OutVals[I];
192
+
193
+ // Promote the value if needed.
194
+ // For now, only handle fully promoted arguments.
195
+ switch (VA.getLocInfo ()) {
196
+ case CCValAssign::Full:
197
+ break ;
198
+ default :
199
+ llvm_unreachable (" Unknown loc info!" );
200
+ }
201
+
202
+ if (VA.isRegLoc ()) {
203
+ // Queue up the argument copies and emit them at the end.
204
+ RegsToPass.push_back (std::make_pair (VA.getLocReg (), ArgValue));
205
+ } else {
206
+ assert (VA.isMemLoc () && " Argument not register or memory" );
207
+ report_fatal_error (" Passing arguments via the stack not yet implemented" );
208
+ }
209
+ }
210
+
211
+ SDValue Glue;
212
+
213
+ // Build a sequence of copy-to-reg nodes, chained and glued together.
214
+ for (auto &Reg : RegsToPass) {
215
+ Chain = DAG.getCopyToReg (Chain, DL, Reg.first , Reg.second , Glue);
216
+ Glue = Chain.getValue (1 );
217
+ }
218
+
219
+ if (isa<GlobalAddressSDNode>(Callee)) {
220
+ Callee = lowerGlobalAddress (Callee, DAG);
221
+ } else if (isa<ExternalSymbolSDNode>(Callee)) {
222
+ report_fatal_error (
223
+ " lowerExternalSymbol, needed for lowerCall, not yet handled" );
224
+ }
225
+
226
+ // The first call operand is the chain and the second is the target address.
227
+ SmallVector<SDValue, 8 > Ops;
228
+ Ops.push_back (Chain);
229
+ Ops.push_back (Callee);
230
+
231
+ // Add argument registers to the end of the list so that they are
232
+ // known live into the call.
233
+ for (auto &Reg : RegsToPass)
234
+ Ops.push_back (DAG.getRegister (Reg.first , Reg.second .getValueType ()));
235
+
236
+ // Add a register mask operand representing the call-preserved registers.
237
+ const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo ();
238
+ const uint32_t *Mask = TRI->getCallPreservedMask (MF, CallConv);
239
+ assert (Mask && " Missing call preserved mask for calling convention" );
240
+ Ops.push_back (DAG.getRegisterMask (Mask));
241
+
242
+ // Glue the call to the argument copies, if any.
243
+ if (Glue.getNode ())
244
+ Ops.push_back (Glue);
245
+
246
+ // Emit the call.
247
+ SDVTList NodeTys = DAG.getVTList (MVT::Other, MVT::Glue);
248
+ Chain = DAG.getNode (RISCVISD::CALL, DL, NodeTys, Ops);
249
+ Glue = Chain.getValue (1 );
250
+
251
+ // Mark the end of the call, which is glued to the call itself.
252
+ Chain = DAG.getCALLSEQ_END (Chain,
253
+ DAG.getConstant (NumBytes, DL, PtrVT, true ),
254
+ DAG.getConstant (0 , DL, PtrVT, true ),
255
+ Glue, DL);
256
+ Glue = Chain.getValue (1 );
257
+
258
+ // Assign locations to each value returned by this call.
259
+ SmallVector<CCValAssign, 16 > RVLocs;
260
+ CCState RetCCInfo (CallConv, IsVarArg, MF, RVLocs, *DAG.getContext ());
261
+ RetCCInfo.AnalyzeCallResult (Ins, RetCC_RISCV32);
262
+
263
+ // Copy all of the result registers out of their specified physreg.
264
+ for (auto &VA : RVLocs) {
265
+ // Copy the value out, gluing the copy to the end of the call sequence.
266
+ SDValue RetValue = DAG.getCopyFromReg (Chain, DL, VA.getLocReg (),
267
+ VA.getLocVT (), Glue);
268
+ Chain = RetValue.getValue (1 );
269
+ Glue = RetValue.getValue (2 );
270
+
271
+ InVals.push_back (Chain.getValue (0 ));
272
+ }
273
+
274
+ return Chain;
275
+ }
276
+
147
277
SDValue
148
278
RISCVTargetLowering::LowerReturn (SDValue Chain, CallingConv::ID CallConv,
149
279
bool IsVarArg,
@@ -194,6 +324,8 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
194
324
break ;
195
325
case RISCVISD::RET_FLAG:
196
326
return " RISCVISD::RET_FLAG" ;
327
+ case RISCVISD::CALL:
328
+ return " RISCVISD::CALL" ;
197
329
}
198
330
return nullptr ;
199
331
}
0 commit comments