1//===-- WebAssemblyCallLowering.cpp - Call lowering for GlobalISel -*- C++ -*-//
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/// \file
10/// This file implements the lowering of LLVM calls to machine code calls for
11/// GlobalISel.
12///
13//===----------------------------------------------------------------------===//
14
15#include "WebAssemblyCallLowering.h"
16#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17#include "Utils/WebAssemblyTypeUtilities.h"
18#include "WebAssemblyISelLowering.h"
19#include "WebAssemblyMachineFunctionInfo.h"
20#include "WebAssemblyRegisterInfo.h"
21#include "WebAssemblySubtarget.h"
22#include "WebAssemblyUtilities.h"
23#include "llvm/CodeGen/Analysis.h"
24#include "llvm/CodeGen/FunctionLoweringInfo.h"
25#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
26#include "llvm/CodeGen/LowLevelTypeUtils.h"
27#include "llvm/CodeGen/MachineInstrBuilder.h"
28#include "llvm/CodeGen/RegisterBankInfo.h"
29#include "llvm/IR/DataLayout.h"
30#include "llvm/IR/DebugLoc.h"
31#include "llvm/IR/Value.h"
32#include "llvm/Support/ErrorHandling.h"
33
34#define DEBUG_TYPE "wasm-call-lowering"
35
36using namespace llvm;
37
38// Test whether the given calling convention is supported.
39static bool callingConvSupported(CallingConv::ID CallConv) {
40 // We currently support the language-independent target-independent
41 // conventions. We don't yet have a way to annotate calls with properties like
42 // "cold", and we don't have any call-clobbered registers, so these are mostly
43 // all handled the same.
44 return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
45 CallConv == CallingConv::Cold ||
46 CallConv == CallingConv::PreserveMost ||
47 CallConv == CallingConv::PreserveAll ||
48 CallConv == CallingConv::CXX_FAST_TLS ||
49 CallConv == CallingConv::WASM_EmscriptenInvoke ||
50 CallConv == CallingConv::Swift;
51}
52
53static unsigned extendOpFromFlags(ISD::ArgFlagsTy Flags) {
54 if (Flags.isSExt())
55 return TargetOpcode::G_SEXT;
56 if (Flags.isZExt())
57 return TargetOpcode::G_ZEXT;
58 return TargetOpcode::G_ANYEXT;
59}
60
61// GlobalISel doesn't handle reference types. We bail out of GlobalISel for
62// functions passing/returning references and fall back to SDAG.
63static bool typeContainsReference(const Type *Ty) {
64 if (WebAssembly::isWebAssemblyReferenceType(Ty))
65 return true;
66 if (const auto *ArrTy = dyn_cast<ArrayType>(Val: Ty))
67 return typeContainsReference(Ty: ArrTy->getElementType());
68 if (const auto *StructTy = dyn_cast<StructType>(Val: Ty))
69 return any_of(Range: StructTy->elements(), P: [](const Type *ElemTy) {
70 return typeContainsReference(Ty: ElemTy);
71 });
72 return false;
73}
74
75WebAssemblyCallLowering::WebAssemblyCallLowering(
76 const WebAssemblyTargetLowering &TLI)
77 : CallLowering(&TLI) {}
78
79bool WebAssemblyCallLowering::canLowerReturn(MachineFunction &MF,
80 CallingConv::ID CallConv,
81 SmallVectorImpl<BaseArgInfo> &Outs,
82 bool IsVarArg) const {
83 return WebAssembly::canLowerReturn(ResultSize: Outs.size(),
84 Subtarget: &MF.getSubtarget<WebAssemblySubtarget>());
85}
86
87bool WebAssemblyCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
88 const Value *Val,
89 ArrayRef<Register> VRegs,
90 FunctionLoweringInfo &FLI,
91 Register SwiftErrorVReg) const {
92 MachineFunction &MF = MIRBuilder.getMF();
93 const Function &F = MF.getFunction();
94 MachineRegisterInfo &MRI = MF.getRegInfo();
95 const WebAssemblyTargetLowering &TLI = *getTLI<WebAssemblyTargetLowering>();
96 const DataLayout &DL = F.getDataLayout();
97
98 if (Val && typeContainsReference(Ty: Val->getType()))
99 return false;
100
101 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Opcode: WebAssembly::RETURN);
102
103 assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
104 "Return value without a vreg or vice versa");
105
106 if (Val) {
107 LLVMContext &Ctx = Val->getType()->getContext();
108
109 if (!FLI.CanLowerReturn) {
110 insertSRetStores(MIRBuilder, RetTy: Val->getType(), VRegs, DemoteReg: FLI.DemoteRegister);
111 } else {
112 SmallVector<EVT, 4> SplitEVTs;
113 ComputeValueVTs(TLI, DL, Ty: Val->getType(), ValueVTs&: SplitEVTs);
114 assert(VRegs.size() == SplitEVTs.size() &&
115 "For each split Type there should be exactly one VReg.");
116
117 SmallVector<ArgInfo, 8> SplitRets;
118 CallingConv::ID CallConv = F.getCallingConv();
119
120 unsigned RetIdx = 0;
121 for (EVT SplitEVT : SplitEVTs) {
122 Register CurVReg = VRegs[RetIdx];
123 ArgInfo CurRetInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Context&: Ctx), 0};
124 setArgFlags(Arg&: CurRetInfo, OpIdx: AttributeList::ReturnIndex, DL, FuncInfo: F);
125
126 splitToValueTypes(OrigArgInfo: CurRetInfo, SplitArgs&: SplitRets, DL, CallConv);
127 ++RetIdx;
128 }
129
130 for (ArgInfo &Ret : SplitRets) {
131 const EVT OrigVT = TLI.getValueType(DL, Ty: Ret.Ty);
132 const MVT NewVT =
133 TLI.getRegisterTypeForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
134 const LLT OrigLLT =
135 getLLTForType(Ty&: *OrigVT.getTypeForEVT(Context&: F.getContext()), DL);
136 const LLT NewLLT = getLLTForMVT(Ty: NewVT);
137
138 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(VT: NewVT);
139
140 // If we need to split the type over multiple regs, check it's a
141 // scenario we currently support.
142 const unsigned NumParts =
143 TLI.getNumRegistersForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
144
145 const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
146 Ret.Flags.clear();
147
148 for (unsigned Part = 0; Part < NumParts; ++Part) {
149 ISD::ArgFlagsTy Flags = OrigFlags;
150
151 if (Part == 0) {
152 Flags.setSplit();
153 } else {
154 Flags.setOrigAlign(Align(1));
155 if (Part == NumParts - 1)
156 Flags.setSplitEnd();
157 }
158
159 Ret.Flags.push_back(Elt: Flags);
160 }
161
162 Ret.OrigRegs.assign(in_start: Ret.Regs.begin(), in_end: Ret.Regs.end());
163 if (NumParts != 1 || OrigLLT != NewLLT) {
164 // If we can't directly assign the register, we need one or more
165 // intermediate values.
166 Ret.Regs.resize(N: NumParts);
167
168 // For each split register, create and assign a vreg that will store
169 // the incoming component of the larger value. These will later be
170 // merged to form the final vreg.
171 for (unsigned Part = 0; Part < NumParts; ++Part) {
172 Register NewReg = MRI.createVirtualRegister(RegClass: &NewRegClass);
173 MRI.setType(VReg: NewReg, Ty: NewLLT);
174 MIB.addUse(RegNo: NewReg);
175 Ret.Regs[Part] = NewReg;
176 }
177
178 buildCopyToRegs(B&: MIRBuilder, DstRegs: Ret.Regs, SrcReg: Ret.OrigRegs[0], SrcTy: OrigLLT,
179 PartTy: NewLLT, ExtendOp: extendOpFromFlags(Flags: Ret.Flags[0]));
180 } else {
181 MIB.addUse(RegNo: Ret.Regs[0]);
182 }
183 }
184 }
185 }
186
187 if (SwiftErrorVReg) {
188 reportFatalInternalError(
189 reason: "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
190 "improperly valid.");
191 }
192
193 MIRBuilder.insertInstr(MIB);
194 return true;
195}
196
197static unsigned getWasmArgumentOpcode(MVT ArgType) {
198 switch (ArgType.SimpleTy) {
199 case MVT::i32:
200 return WebAssembly::ARGUMENT_i32;
201 case MVT::i64:
202 return WebAssembly::ARGUMENT_i64;
203 case MVT::f32:
204 return WebAssembly::ARGUMENT_f32;
205 case MVT::f64:
206 return WebAssembly::ARGUMENT_f64;
207
208 case MVT::funcref:
209 return WebAssembly::ARGUMENT_funcref;
210 case MVT::externref:
211 return WebAssembly::ARGUMENT_externref;
212 case MVT::exnref:
213 return WebAssembly::ARGUMENT_exnref;
214
215 case MVT::v16i8:
216 return WebAssembly::ARGUMENT_v16i8;
217 case MVT::v8i16:
218 return WebAssembly::ARGUMENT_v8i16;
219 case MVT::v4i32:
220 return WebAssembly::ARGUMENT_v4i32;
221 case MVT::v2i64:
222 return WebAssembly::ARGUMENT_v2i64;
223 case MVT::v8f16:
224 return WebAssembly::ARGUMENT_v8f16;
225 case MVT::v4f32:
226 return WebAssembly::ARGUMENT_v4f32;
227 case MVT::v2f64:
228 return WebAssembly::ARGUMENT_v2f64;
229 default:
230 break;
231 }
232 llvm_unreachable("Found unexpected type for Wasm argument");
233}
234
235static Register buildWasmArgument(unsigned Idx, MVT ArgVT, LLT ArgLLT,
236 MachineIRBuilder &MIRBuilder,
237 Register Def = Register()) {
238 unsigned Op = getWasmArgumentOpcode(ArgType: ArgVT);
239
240 const TargetInstrInfo &TII = MIRBuilder.getTII();
241 MachineFunction &MF = MIRBuilder.getMF();
242 MachineRegisterInfo &MRI = MF.getRegInfo();
243 const TargetRegisterClass &RegClass = *TII.getRegClass(MCID: TII.get(Opcode: Op), OpNum: 0);
244
245 Register NewReg;
246
247 if (Def.isValid()) {
248 assert(MRI.getRegClassOrRegBank(Def).isNull() &&
249 "Def already has reg bank or reg class?");
250 MRI.setRegClass(Reg: Def, RC: &RegClass);
251
252 NewReg = Def;
253 } else {
254 NewReg = MRI.createVirtualRegister(RegClass: &RegClass);
255 MRI.setType(VReg: NewReg, Ty: ArgLLT);
256 }
257
258 MIRBuilder.buildInstr(Opcode: Op).addDef(RegNo: NewReg).addImm(Val: Idx);
259
260 return NewReg;
261}
262
263bool WebAssemblyCallLowering::lowerFormalArguments(
264 MachineIRBuilder &MIRBuilder, const Function &F,
265 ArrayRef<ArrayRef<Register>> VRegs, FunctionLoweringInfo &FLI) const {
266 MachineFunction &MF = MIRBuilder.getMF();
267 MachineRegisterInfo &MRI = MF.getRegInfo();
268 WebAssemblyFunctionInfo *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
269 const DataLayout &DL = F.getDataLayout();
270 const WebAssemblyTargetLowering &TLI = *getTLI<WebAssemblyTargetLowering>();
271
272 LLVMContext &Ctx = MIRBuilder.getContext();
273 const CallingConv::ID CallConv = F.getCallingConv();
274
275 if (!callingConvSupported(CallConv))
276 return false;
277
278 if (typeContainsReference(Ty: F.getReturnType()))
279 return false;
280 for (const Argument &Arg : F.args())
281 if (typeContainsReference(Ty: Arg.getType()))
282 return false;
283
284 MF.getRegInfo().addLiveIn(Reg: WebAssembly::ARGUMENTS);
285 MF.front().addLiveIn(PhysReg: WebAssembly::ARGUMENTS);
286
287 SmallVector<ArgInfo, 8> SplitArgs;
288
289 if (!FLI.CanLowerReturn)
290 insertSRetIncomingArgument(F, SplitArgs, DemoteReg&: FLI.DemoteRegister, MRI, DL);
291
292 unsigned ArgIdx = 0;
293 bool HasSwiftErrorArg = false;
294 bool HasSwiftSelfArg = false;
295 for (const Argument &Arg : F.args()) {
296 ArgInfo OrigArg{VRegs[ArgIdx], Arg.getType(), ArgIdx};
297 setArgFlags(Arg&: OrigArg, OpIdx: ArgIdx + AttributeList::FirstArgIndex, DL, FuncInfo: F);
298
299 HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
300 HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
301 if (Arg.hasInAllocaAttr())
302 return false;
303 if (Arg.hasNestAttr())
304 return false;
305
306 splitToValueTypes(OrigArgInfo: OrigArg, SplitArgs, DL, CallConv: F.getCallingConv());
307 ++ArgIdx;
308 }
309
310 unsigned FinalArgIdx = 0;
311 for (ArgInfo &Arg : SplitArgs) {
312 const EVT OrigVT = TLI.getValueType(DL, Ty: Arg.Ty);
313 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
314 const LLT OrigLLT =
315 getLLTForType(Ty&: *OrigVT.getTypeForEVT(Context&: F.getContext()), DL);
316 const LLT NewLLT = getLLTForMVT(Ty: NewVT);
317
318 // If we need to split the type over multiple regs, check it's a scenario
319 // we currently support.
320 const unsigned NumParts =
321 TLI.getNumRegistersForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
322
323 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
324 Arg.Flags.clear();
325
326 for (unsigned Part = 0; Part < NumParts; ++Part) {
327 ISD::ArgFlagsTy Flags = OrigFlags;
328 if (Part == 0) {
329 Flags.setSplit();
330 } else {
331 Flags.setOrigAlign(Align(1));
332 if (Part == NumParts - 1)
333 Flags.setSplitEnd();
334 }
335
336 Arg.Flags.push_back(Elt: Flags);
337 }
338
339 Arg.OrigRegs.assign(in_start: Arg.Regs.begin(), in_end: Arg.Regs.end());
340 if (NumParts != 1 || OrigLLT != NewLLT) {
341 // If we can't directly assign the register, we need one or more
342 // intermediate values.
343 Arg.Regs.resize(N: NumParts);
344
345 // For each split register, create and assign a vreg that will store
346 // the incoming component of the larger value. These will later be
347 // merged to form the final vreg.
348 for (unsigned Part = 0; Part < NumParts; ++Part) {
349 Arg.Regs[Part] =
350 buildWasmArgument(Idx: FinalArgIdx++, ArgVT: NewVT, ArgLLT: NewLLT, MIRBuilder);
351 MFI->addParam(VT: NewVT);
352 }
353
354 buildCopyFromRegs(B&: MIRBuilder, OrigRegs: Arg.OrigRegs, Regs: Arg.Regs, LLTy: OrigLLT, PartLLT: NewLLT,
355 Flags: Arg.Flags[0]);
356 } else {
357 buildWasmArgument(Idx: FinalArgIdx++, ArgVT: NewVT, ArgLLT: NewLLT, MIRBuilder, Def: Arg.Regs[0]);
358 MFI->addParam(VT: NewVT);
359 }
360 }
361
362 // For swiftcc, emit additional swiftself and swifterror arguments
363 // if there aren't. These additional arguments are also added for callee
364 // signature They are necessary to match callee and caller signature for
365 // indirect call.
366 if (CallConv == CallingConv::Swift) {
367 const MVT PtrVT = TLI.getPointerTy(DL);
368
369 if (!HasSwiftSelfArg)
370 MFI->addParam(VT: PtrVT);
371 if (!HasSwiftErrorArg)
372 MFI->addParam(VT: PtrVT);
373 }
374
375 // Varargs are copied into a buffer allocated by the caller, and a pointer to
376 // the buffer is passed as an argument.
377 if (F.isVarArg()) {
378 const MVT PtrVT = TLI.getPointerTy(DL, AS: 0);
379 const LLT PtrLLT = LLT::pointer(AddressSpace: 0, SizeInBits: DL.getPointerSizeInBits(AS: 0));
380
381 Register VarargVreg =
382 buildWasmArgument(Idx: FinalArgIdx++, ArgVT: PtrVT, ArgLLT: PtrLLT, MIRBuilder);
383 MFI->setVarargBufferVreg(VarargVreg);
384
385 MFI->addParam(VT: PtrVT);
386 ++FinalArgIdx;
387 }
388
389 // Record the number and types of arguments and results.
390 SmallVector<MVT, 4> Params;
391 SmallVector<MVT, 4> Results;
392 computeSignatureVTs(Ty: MF.getFunction().getFunctionType(), TargetFunc: &MF.getFunction(),
393 ContextFunc: MF.getFunction(), TM: MF.getTarget(), Params, Results);
394 for (MVT VT : Results)
395 MFI->addResult(VT);
396
397 // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
398 // the param logic here with ComputeSignatureVTs
399 assert(MFI->getParams().size() == Params.size() &&
400 std::equal(MFI->getParams().begin(), MFI->getParams().end(),
401 Params.begin()));
402 return true;
403}
404
405bool WebAssemblyCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
406 CallLoweringInfo &Info) const {
407 MachineFunction &MF = MIRBuilder.getMF();
408 const DataLayout &DL = MIRBuilder.getDataLayout();
409 LLVMContext &Ctx = MIRBuilder.getContext();
410 const WebAssemblyTargetLowering &TLI = *getTLI<WebAssemblyTargetLowering>();
411 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
412 const Function &F = MF.getFunction();
413
414 CallingConv::ID CallConv = Info.CallConv;
415 if (!callingConvSupported(CallConv))
416 return false;
417
418 if (typeContainsReference(Ty: Info.OrigRet.Ty))
419 return false;
420 for (const ArgInfo &Arg : Info.OrigArgs)
421 if (typeContainsReference(Ty: Arg.Ty))
422 return false;
423
424 // TODO: tail calls
425 if (Info.IsMustTailCall)
426 return false;
427
428 // TODO: varargs
429 if (Info.IsVarArg)
430 return false;
431
432 // TODO: swiftcc
433 if (CallConv == CallingConv::Swift)
434 return false;
435
436 MachineInstrBuilder CallInst;
437
438 // TODO: indirect calls
439 if (Info.Callee.isReg())
440 return false;
441
442 CallInst = MIRBuilder.buildInstrNoInsert(Opcode: WebAssembly::CALL);
443
444 SmallVector<ArgInfo, 8> SplitArgs;
445
446 for (const ArgInfo &Arg : Info.OrigArgs) {
447 if (Arg.Flags[0].isNest())
448 return false;
449 if (Arg.Flags[0].isInAlloca())
450 return false;
451 if (Arg.Flags[0].isInConsecutiveRegs())
452 return false;
453 if (Arg.Flags[0].isInConsecutiveRegsLast())
454 return false;
455
456 // TODO: bulk memory, then byval
457 if (Arg.Flags[0].isByVal() && Arg.Flags[0].getByValSize() != 0)
458 return false;
459
460 splitToValueTypes(OrigArgInfo: Arg, SplitArgs, DL, CallConv);
461 }
462
463 SmallVector<Register> CallUseRegs;
464
465 for (ArgInfo &Arg : SplitArgs) {
466 const EVT OrigVT = TLI.getValueType(DL, Ty: Arg.Ty);
467 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
468 const LLT OrigLLT =
469 getLLTForType(Ty&: *OrigVT.getTypeForEVT(Context&: F.getContext()), DL);
470 const LLT NewLLT = getLLTForMVT(Ty: NewVT);
471
472 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(VT: NewVT);
473
474 // If we need to split the type over multiple regs, check it's a scenario
475 // we currently support.
476 const unsigned NumParts =
477 TLI.getNumRegistersForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
478
479 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
480 Arg.Flags.clear();
481
482 for (unsigned Part = 0; Part < NumParts; ++Part) {
483 ISD::ArgFlagsTy Flags = OrigFlags;
484 if (Part == 0) {
485 Flags.setSplit();
486 } else {
487 Flags.setOrigAlign(Align(1));
488 if (Part == NumParts - 1)
489 Flags.setSplitEnd();
490 }
491
492 Arg.Flags.push_back(Elt: Flags);
493 }
494
495 Arg.OrigRegs.assign(in_start: Arg.Regs.begin(), in_end: Arg.Regs.end());
496 if (NumParts != 1 || OrigLLT != NewLLT) {
497 // If we can't directly assign the register, we need one or more
498 // intermediate values.
499 Arg.Regs.resize(N: NumParts);
500
501 // For each split register, create and assign a vreg that will store
502 // the incoming component of the larger value. These will later be
503 // merged to form the final vreg.
504 for (unsigned Part = 0; Part < NumParts; ++Part) {
505 Register NewReg = MRI.createVirtualRegister(RegClass: &NewRegClass);
506 MRI.setType(VReg: NewReg, Ty: NewLLT);
507 CallUseRegs.push_back(Elt: NewReg);
508 Arg.Regs[Part] = NewReg;
509 }
510
511 buildCopyToRegs(B&: MIRBuilder, DstRegs: Arg.Regs, SrcReg: Arg.OrigRegs[0], SrcTy: OrigLLT, PartTy: NewLLT,
512 ExtendOp: extendOpFromFlags(Flags: Arg.Flags[0]));
513 } else {
514 CallUseRegs.push_back(Elt: Arg.Regs[0]);
515 }
516 }
517
518 // Analyze operands of the call, assigning locations to each operand.
519 SmallVector<CCValAssign, 16> ArgLocs;
520 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
521
522 MIRBuilder.insertInstr(MIB: CallInst);
523
524 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
525 SmallVector<EVT, 4> SplitEVTs;
526 ComputeValueVTs(TLI, DL, Ty: Info.OrigRet.Ty, ValueVTs&: SplitEVTs);
527 assert(Info.OrigRet.Regs.size() == SplitEVTs.size() &&
528 "For each split Type there should be exactly one VReg.");
529
530 SmallVector<ArgInfo, 8> SplitRets;
531
532 unsigned RetIdx = 0;
533 for (EVT SplitEVT : SplitEVTs) {
534 Register CurVReg = Info.OrigRet.Regs[RetIdx];
535 ArgInfo CurArgInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Context&: Ctx), 0};
536
537 if (Info.CB) {
538 setArgFlags(Arg&: CurArgInfo, OpIdx: AttributeList::ReturnIndex, DL, FuncInfo: *Info.CB);
539 } else {
540 // We don't have a call base, so chances are we're looking at a
541 // libcall (external symbol).
542
543 // TODO: figure out how to get ALL the correct attributes
544 ISD::ArgFlagsTy &Flags = CurArgInfo.Flags[0];
545 PointerType *PtrTy =
546 dyn_cast<PointerType>(Val: CurArgInfo.Ty->getScalarType());
547 if (PtrTy) {
548 Flags.setPointer();
549 Flags.setPointerAddrSpace(PtrTy->getPointerAddressSpace());
550 }
551 Align MemAlign = DL.getABITypeAlign(Ty: CurArgInfo.Ty);
552 Flags.setMemAlign(MemAlign);
553 Flags.setOrigAlign(MemAlign);
554 }
555
556 splitToValueTypes(OrigArgInfo: CurArgInfo, SplitArgs&: SplitRets, DL, CallConv);
557 ++RetIdx;
558 }
559
560 for (ArgInfo &Ret : SplitRets) {
561 const EVT OrigVT = TLI.getValueType(DL, Ty: Ret.Ty);
562 const MVT NewVT =
563 TLI.getRegisterTypeForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
564 const LLT OrigLLT =
565 getLLTForType(Ty&: *OrigVT.getTypeForEVT(Context&: F.getContext()), DL);
566 const LLT NewLLT = getLLTForMVT(Ty: NewVT);
567
568 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(VT: NewVT);
569
570 // If we need to split the type over multiple regs, check it's a scenario
571 // we currently support.
572 const unsigned NumParts =
573 TLI.getNumRegistersForCallingConv(Context&: Ctx, CC: CallConv, VT: OrigVT);
574
575 const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
576 Ret.Flags.clear();
577
578 for (unsigned Part = 0; Part < NumParts; ++Part) {
579 ISD::ArgFlagsTy Flags = OrigFlags;
580 if (Part == 0) {
581 Flags.setSplit();
582 } else {
583 Flags.setOrigAlign(Align(1));
584 if (Part == NumParts - 1)
585 Flags.setSplitEnd();
586 }
587
588 Ret.Flags.push_back(Elt: Flags);
589 }
590
591 Ret.OrigRegs.assign(in_start: Ret.Regs.begin(), in_end: Ret.Regs.end());
592
593 if (NumParts != 1 || OrigLLT != NewLLT) {
594 // If we can't directly assign the register, we need one or more
595 // intermediate values.
596 Ret.Regs.resize(N: NumParts);
597
598 // For each split register, create and assign a vreg that will store
599 // the incoming component of the larger value. These will later be
600 // merged to form the final vreg.
601 for (unsigned Part = 0; Part < NumParts; ++Part) {
602 Register NewReg = MRI.createVirtualRegister(RegClass: &NewRegClass);
603 MRI.setType(VReg: NewReg, Ty: NewLLT);
604 CallInst.addDef(RegNo: NewReg);
605 Ret.Regs[Part] = NewReg;
606 }
607
608 buildCopyFromRegs(B&: MIRBuilder, OrigRegs: Ret.OrigRegs, Regs: Ret.Regs, LLTy: OrigLLT, PartLLT: NewLLT,
609 Flags: Ret.Flags[0]);
610 } else {
611 MRI.setRegClass(Reg: Ret.Regs[0], RC: &NewRegClass);
612 CallInst.addDef(RegNo: Ret.Regs[0]);
613 }
614 }
615 }
616
617 if (Info.Callee.isGlobal()) {
618 CallInst.addGlobalAddress(GV: Info.Callee.getGlobal());
619 } else if (Info.Callee.isSymbol()) {
620 CallInst.addExternalSymbol(FnName: Info.Callee.getSymbolName());
621 } else {
622 return false;
623 }
624
625 for (Register Reg : CallUseRegs) {
626 CallInst.addUse(RegNo: Reg);
627 }
628
629 if (!Info.CanLowerReturn)
630 insertSRetLoads(MIRBuilder, RetTy: Info.OrigRet.Ty, VRegs: Info.OrigRet.Regs,
631 DemoteReg: Info.DemoteRegister, FI: Info.DemoteStackIndex);
632
633 return true;
634}
635