LLVM 24.0.0git
WebAssemblyCallLowering.cpp
Go to the documentation of this file.
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
29#include "llvm/IR/DataLayout.h"
30#include "llvm/IR/DebugLoc.h"
31#include "llvm/IR/Value.h"
33
34#define DEBUG_TYPE "wasm-call-lowering"
35
36using namespace llvm;
37
38// Test whether the given calling convention is supported.
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 ||
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) {
65 return true;
66 if (const auto *ArrTy = dyn_cast<ArrayType>(Ty))
67 return typeContainsReference(ArrTy->getElementType());
68 if (const auto *StructTy = dyn_cast<StructType>(Ty))
69 return any_of(StructTy->elements(), [](const Type *ElemTy) {
70 return typeContainsReference(ElemTy);
71 });
72 return false;
73}
74
78
86
88 const Value *Val,
91 Register SwiftErrorVReg) const {
92 MachineFunction &MF = MIRBuilder.getMF();
93 const Function &F = MF.getFunction();
96 const DataLayout &DL = F.getDataLayout();
97
98 if (Val && typeContainsReference(Val->getType()))
99 return false;
100
101 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(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, Val->getType(), VRegs, FLI.DemoteRegister);
111 } else {
112 SmallVector<EVT, 4> SplitEVTs;
113 ComputeValueVTs(TLI, DL, Val->getType(), 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(Ctx), 0};
124 setArgFlags(CurRetInfo, AttributeList::ReturnIndex, DL, F);
125
126 splitToValueTypes(CurRetInfo, SplitRets, DL, CallConv);
127 ++RetIdx;
128 }
129
130 for (ArgInfo &Ret : SplitRets) {
131 const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
132 const MVT NewVT =
133 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
134 const LLT OrigLLT =
135 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
136 const LLT NewLLT = getLLTForMVT(NewVT);
137
138 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(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(Ctx, CallConv, 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(Flags);
160 }
161
162 Ret.OrigRegs.assign(Ret.Regs.begin(), 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(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(&NewRegClass);
173 MRI.setType(NewReg, NewLLT);
174 MIB.addUse(NewReg);
175 Ret.Regs[Part] = NewReg;
176 }
177
178 buildCopyToRegs(MIRBuilder, Ret.Regs, Ret.OrigRegs[0], OrigLLT,
179 NewLLT, extendOpFromFlags(Ret.Flags[0]));
180 } else {
181 MIB.addUse(Ret.Regs[0]);
182 }
183 }
184 }
185 }
186
187 if (SwiftErrorVReg) {
189 "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(ArgVT);
239
240 const TargetInstrInfo &TII = MIRBuilder.getTII();
241 MachineFunction &MF = MIRBuilder.getMF();
243 const TargetRegisterClass &RegClass = *TII.getRegClass(TII.get(Op), 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(Def, &RegClass);
251
252 NewReg = Def;
253 } else {
254 NewReg = MRI.createVirtualRegister(&RegClass);
255 MRI.setType(NewReg, ArgLLT);
256 }
257
258 MIRBuilder.buildInstr(Op).addDef(NewReg).addImm(Idx);
259
260 return NewReg;
261}
262
264 MachineIRBuilder &MIRBuilder, const Function &F,
266 MachineFunction &MF = MIRBuilder.getMF();
269 const DataLayout &DL = F.getDataLayout();
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(F.getReturnType()))
279 return false;
280 for (const Argument &Arg : F.args())
281 if (typeContainsReference(Arg.getType()))
282 return false;
283
284 MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
285 MF.front().addLiveIn(WebAssembly::ARGUMENTS);
286
287 SmallVector<ArgInfo, 8> SplitArgs;
288
289 if (!FLI.CanLowerReturn)
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(OrigArg, ArgIdx + AttributeList::FirstArgIndex, DL, F);
298
299 HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
300 HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
301 // TODO: Support SwiftAsync attributes instead of falling back to
302 // SelectionDAG.
303 if (Arg.hasAttribute(Attribute::SwiftAsync))
304 return false;
305 if (Arg.hasInAllocaAttr())
306 return false;
307 if (Arg.hasNestAttr())
308 return false;
309
310 splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
311 ++ArgIdx;
312 }
313
314 unsigned FinalArgIdx = 0;
315 for (ArgInfo &Arg : SplitArgs) {
316 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
317 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
318 const LLT OrigLLT =
319 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
320 const LLT NewLLT = getLLTForMVT(NewVT);
321
322 // If we need to split the type over multiple regs, check it's a scenario
323 // we currently support.
324 const unsigned NumParts =
325 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
326
327 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
328 Arg.Flags.clear();
329
330 for (unsigned Part = 0; Part < NumParts; ++Part) {
331 ISD::ArgFlagsTy Flags = OrigFlags;
332 if (Part == 0) {
333 Flags.setSplit();
334 } else {
335 Flags.setOrigAlign(Align(1));
336 if (Part == NumParts - 1)
337 Flags.setSplitEnd();
338 }
339
340 Arg.Flags.push_back(Flags);
341 }
342
343 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
344 if (NumParts != 1 || OrigLLT != NewLLT) {
345 // If we can't directly assign the register, we need one or more
346 // intermediate values.
347 Arg.Regs.resize(NumParts);
348
349 // For each split register, create and assign a vreg that will store
350 // the incoming component of the larger value. These will later be
351 // merged to form the final vreg.
352 for (unsigned Part = 0; Part < NumParts; ++Part) {
353 Arg.Regs[Part] =
354 buildWasmArgument(FinalArgIdx++, NewVT, NewLLT, MIRBuilder);
355 MFI->addParam(NewVT);
356 }
357
358 buildCopyFromRegs(MIRBuilder, Arg.OrigRegs, Arg.Regs, OrigLLT, NewLLT,
359 Arg.Flags[0]);
360 } else {
361 buildWasmArgument(FinalArgIdx++, NewVT, NewLLT, MIRBuilder, Arg.Regs[0]);
362 MFI->addParam(NewVT);
363 }
364 }
365
366 // For swiftcc, emit additional swiftself and swifterror arguments
367 // if there aren't. These additional arguments are also added for callee
368 // signature They are necessary to match callee and caller signature for
369 // indirect call.
370 if (CallConv == CallingConv::Swift) {
371 const MVT PtrVT = TLI.getPointerTy(DL);
372
373 if (!HasSwiftSelfArg)
374 MFI->addParam(PtrVT);
375 if (!HasSwiftErrorArg)
376 MFI->addParam(PtrVT);
377 }
378
379 // Varargs are copied into a buffer allocated by the caller, and a pointer to
380 // the buffer is passed as an argument.
381 if (F.isVarArg()) {
382 const MVT PtrVT = TLI.getPointerTy(DL, 0);
383 const LLT PtrLLT = LLT::pointer(0, DL.getPointerSizeInBits(0));
384
385 Register VarargVreg =
386 buildWasmArgument(FinalArgIdx++, PtrVT, PtrLLT, MIRBuilder);
387 MFI->setVarargBufferVreg(VarargVreg);
388
389 MFI->addParam(PtrVT);
390 ++FinalArgIdx;
391 }
392
393 // Record the number and types of arguments and results.
394 SmallVector<MVT, 4> Params;
397 MF.getFunction(), MF.getTarget(), Params, Results);
398 for (MVT VT : Results)
399 MFI->addResult(VT);
400
401 // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
402 // the param logic here with ComputeSignatureVTs
403 assert(MFI->getParams().size() == Params.size() &&
404 std::equal(MFI->getParams().begin(), MFI->getParams().end(),
405 Params.begin()));
406 return true;
407}
408
410 CallLoweringInfo &Info) const {
411 MachineFunction &MF = MIRBuilder.getMF();
412 const DataLayout &DL = MIRBuilder.getDataLayout();
413 LLVMContext &Ctx = MIRBuilder.getContext();
415 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
416 const Function &F = MF.getFunction();
417
418 CallingConv::ID CallConv = Info.CallConv;
419 if (!callingConvSupported(CallConv))
420 return false;
421
422 if (typeContainsReference(Info.OrigRet.Ty))
423 return false;
424 for (const ArgInfo &Arg : Info.OrigArgs)
425 if (typeContainsReference(Arg.Ty))
426 return false;
427
428 // TODO: tail calls
429 if (Info.IsMustTailCall)
430 return false;
431
432 // TODO: varargs
433 if (Info.IsVarArg)
434 return false;
435
436 // TODO: swiftcc
437 if (CallConv == CallingConv::Swift)
438 return false;
439
440 // TODO: Support SwiftAsync attributes instead of falling back to
441 // SelectionDAG.
442 if (Info.CB)
443 for (unsigned I = 0, E = Info.CB->arg_size(); I != E; ++I)
444 if (Info.CB->paramHasAttr(I, Attribute::SwiftAsync))
445 return false;
446
448
449 // TODO: indirect calls
450 if (Info.Callee.isReg())
451 return false;
452
453 CallInst = MIRBuilder.buildInstrNoInsert(WebAssembly::CALL);
454 if (Info.NoMerge)
456
457 SmallVector<ArgInfo, 8> SplitArgs;
458
459 for (const ArgInfo &Arg : Info.OrigArgs) {
460 if (Arg.Flags[0].isNest())
461 return false;
462 if (Arg.Flags[0].isInAlloca())
463 return false;
464 if (Arg.Flags[0].isInConsecutiveRegs())
465 return false;
466 if (Arg.Flags[0].isInConsecutiveRegsLast())
467 return false;
468
469 // TODO: bulk memory, then byval
470 if (Arg.Flags[0].isByVal() && Arg.Flags[0].getByValSize() != 0)
471 return false;
472
473 splitToValueTypes(Arg, SplitArgs, DL, CallConv);
474 }
475
476 SmallVector<Register> CallUseRegs;
477
478 for (ArgInfo &Arg : SplitArgs) {
479 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
480 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
481 const LLT OrigLLT =
482 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
483 const LLT NewLLT = getLLTForMVT(NewVT);
484
485 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
486
487 // If we need to split the type over multiple regs, check it's a scenario
488 // we currently support.
489 const unsigned NumParts =
490 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
491
492 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
493 Arg.Flags.clear();
494
495 for (unsigned Part = 0; Part < NumParts; ++Part) {
496 ISD::ArgFlagsTy Flags = OrigFlags;
497 if (Part == 0) {
498 Flags.setSplit();
499 } else {
500 Flags.setOrigAlign(Align(1));
501 if (Part == NumParts - 1)
502 Flags.setSplitEnd();
503 }
504
505 Arg.Flags.push_back(Flags);
506 }
507
508 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
509 if (NumParts != 1 || OrigLLT != NewLLT) {
510 // If we can't directly assign the register, we need one or more
511 // intermediate values.
512 Arg.Regs.resize(NumParts);
513
514 // For each split register, create and assign a vreg that will store
515 // the incoming component of the larger value. These will later be
516 // merged to form the final vreg.
517 for (unsigned Part = 0; Part < NumParts; ++Part) {
518 Register NewReg = MRI.createVirtualRegister(&NewRegClass);
519 MRI.setType(NewReg, NewLLT);
520 CallUseRegs.push_back(NewReg);
521 Arg.Regs[Part] = NewReg;
522 }
523
524 buildCopyToRegs(MIRBuilder, Arg.Regs, Arg.OrigRegs[0], OrigLLT, NewLLT,
525 extendOpFromFlags(Arg.Flags[0]));
526 } else {
527 CallUseRegs.push_back(Arg.Regs[0]);
528 }
529 }
530
531 // Analyze operands of the call, assigning locations to each operand.
533 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
534
535 MIRBuilder.insertInstr(CallInst);
536
537 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
538 SmallVector<EVT, 4> SplitEVTs;
539 ComputeValueVTs(TLI, DL, Info.OrigRet.Ty, SplitEVTs);
540 assert(Info.OrigRet.Regs.size() == SplitEVTs.size() &&
541 "For each split Type there should be exactly one VReg.");
542
543 SmallVector<ArgInfo, 8> SplitRets;
544
545 unsigned RetIdx = 0;
546 for (EVT SplitEVT : SplitEVTs) {
547 Register CurVReg = Info.OrigRet.Regs[RetIdx];
548 ArgInfo CurArgInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
549
550 if (Info.CB) {
551 setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, *Info.CB);
552 } else {
553 // We don't have a call base, so chances are we're looking at a
554 // libcall (external symbol).
555
556 // TODO: figure out how to get ALL the correct attributes
557 ISD::ArgFlagsTy &Flags = CurArgInfo.Flags[0];
558 PointerType *PtrTy =
560 if (PtrTy) {
561 Flags.setPointer();
562 Flags.setPointerAddrSpace(PtrTy->getPointerAddressSpace());
563 }
564 Align MemAlign = DL.getABITypeAlign(CurArgInfo.Ty);
565 Flags.setMemAlign(MemAlign);
566 Flags.setOrigAlign(MemAlign);
567 }
568
569 splitToValueTypes(CurArgInfo, SplitRets, DL, CallConv);
570 ++RetIdx;
571 }
572
573 for (ArgInfo &Ret : SplitRets) {
574 const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
575 const MVT NewVT =
576 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
577 const LLT OrigLLT =
578 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
579 const LLT NewLLT = getLLTForMVT(NewVT);
580
581 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
582
583 // If we need to split the type over multiple regs, check it's a scenario
584 // we currently support.
585 const unsigned NumParts =
586 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
587
588 const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
589 Ret.Flags.clear();
590
591 for (unsigned Part = 0; Part < NumParts; ++Part) {
592 ISD::ArgFlagsTy Flags = OrigFlags;
593 if (Part == 0) {
594 Flags.setSplit();
595 } else {
596 Flags.setOrigAlign(Align(1));
597 if (Part == NumParts - 1)
598 Flags.setSplitEnd();
599 }
600
601 Ret.Flags.push_back(Flags);
602 }
603
604 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
605
606 if (NumParts != 1 || OrigLLT != NewLLT) {
607 // If we can't directly assign the register, we need one or more
608 // intermediate values.
609 Ret.Regs.resize(NumParts);
610
611 // For each split register, create and assign a vreg that will store
612 // the incoming component of the larger value. These will later be
613 // merged to form the final vreg.
614 for (unsigned Part = 0; Part < NumParts; ++Part) {
615 Register NewReg = MRI.createVirtualRegister(&NewRegClass);
616 MRI.setType(NewReg, NewLLT);
617 CallInst.addDef(NewReg);
618 Ret.Regs[Part] = NewReg;
619 }
620
621 buildCopyFromRegs(MIRBuilder, Ret.OrigRegs, Ret.Regs, OrigLLT, NewLLT,
622 Ret.Flags[0]);
623 } else {
624 MRI.setRegClass(Ret.Regs[0], &NewRegClass);
625 CallInst.addDef(Ret.Regs[0]);
626 }
627 }
628 }
629
630 if (Info.Callee.isGlobal()) {
631 CallInst.addGlobalAddress(Info.Callee.getGlobal());
632 } else if (Info.Callee.isSymbol()) {
633 CallInst.addExternalSymbol(Info.Callee.getSymbolName());
634 } else {
635 return false;
636 }
637
638 for (Register Reg : CallUseRegs) {
639 CallInst.addUse(Reg);
640 }
641
642 if (!Info.CanLowerReturn)
643 insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,
644 Info.DemoteRegister, Info.DemoteStackIndex);
645
646 return true;
647}
unsigned NumParts
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static unsigned extendOpFromFlags(llvm::ISD::ArgFlagsTy Flags)
const HexagonInstrInfo * TII
Implement a low-level type suitable for MachineInstr level instruction selection.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
Promote Memory to Register
Definition Mem2Reg.cpp:110
MachineRegisterInfo & MRI
static bool callingConvSupported(CallingConv::ID CallConv)
static bool typeContainsReference(const Type *Ty)
static unsigned getWasmArgumentOpcode(MVT ArgType)
static Register buildWasmArgument(unsigned Idx, MVT ArgVT, LLT ArgLLT, MachineIRBuilder &MIRBuilder, Register Def=Register())
static unsigned extendOpFromFlags(ISD::ArgFlagsTy Flags)
This file describes how to lower LLVM calls to machine code calls.
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG.
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file contains the WebAssembly implementation of the WebAssemblyRegisterInfo class.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
CCState - This class holds information needed while lowering arguments and return values.
This class represents a function call, abstracting a target machine's calling convention.
void insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg, int FI) const
Load the returned value from the stack into virtual registers in VRegs.
void insertSRetIncomingArgument(const Function &F, SmallVectorImpl< ArgInfo > &SplitArgs, Register &DemoteReg, MachineRegisterInfo &MRI, const DataLayout &DL) const
Insert the hidden sret ArgInfo to the beginning of SplitArgs.
void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl< ArgInfo > &SplitArgs, const DataLayout &DL, CallingConv::ID CallConv, SmallVectorImpl< TypeSize > *Offsets=nullptr) const
Break OrigArgInfo into one or more pieces the calling convention can process, returned in SplitArgs.
static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef< Register > DstRegs, Register SrcReg, LLT SrcTy, LLT PartTy, unsigned ExtendOp=TargetOpcode::G_ANYEXT)
Create a sequence of instructions to expand the value in SrcReg (of type SrcTy) to the types in DstRe...
void insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy, ArrayRef< Register > VRegs, Register DemoteReg) const
Store the return value given by VRegs into stack starting at the offset specified in DemoteReg.
static void buildCopyFromRegs(MachineIRBuilder &B, ArrayRef< Register > OrigRegs, ArrayRef< Register > Regs, LLT LLTy, LLT PartLLT, const ISD::ArgFlagsTy Flags)
Create a sequence of instructions to combine pieces split into register typed values to the original ...
CallLowering(const TargetLowering *TLI)
const TargetLowering * getTLI() const
Getter for generic TargetLowering class.
void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Register DemoteRegister
DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg allocated to hold a pointer to ...
bool CanLowerReturn
CanLowerReturn - true iff the function's return value can be lowered to registers.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
Machine Value Type.
SimpleValueType SimpleTy
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
LLVMContext & getContext() const
const TargetInstrInfo & getTII()
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
const DataLayout & getDataLayout() const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
Class to represent pointers.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
void addUse(Use &U)
This method should only be used by the Use class.
Definition Value.h:515
bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef< Register > VRegs, FunctionLoweringInfo &FLI, Register SwiftErrorVReg) const override
This hook must be implemented to lower outgoing return values, described by Val, into the specified v...
WebAssemblyCallLowering(const WebAssemblyTargetLowering &TLI)
bool lowerCall(MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const override
This hook must be implemented to lower the given call instruction, including argument and return valu...
bool canLowerReturn(MachineFunction &MF, CallingConv::ID CallConv, SmallVectorImpl< BaseArgInfo > &Outs, bool IsVarArg) const override
This hook must be implemented to check whether the return values described by Outs can fit into the r...
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef< ArrayRef< Register > > VRegs, FunctionLoweringInfo &FLI) const override
This hook must be implemented to lower the incoming (formal) arguments, described by VRegs,...
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const std::vector< MVT > & getParams() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ Swift
Calling convention for Swift.
Definition CallingConv.h:69
@ PreserveMost
Used for runtime calls that preserves most registers.
Definition CallingConv.h:63
@ CXX_FAST_TLS
Used for access functions.
Definition CallingConv.h:72
@ WASM_EmscriptenInvoke
For emscripten __invoke_* functions.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
Definition CallingConv.h:47
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
Definition CallingConv.h:66
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
bool isWebAssemblyReferenceType(const Type *Ty)
Return true if this is a WebAssembly Reference Type.
bool canLowerReturn(size_t ResultSize, const WebAssemblySubtarget *Subtarget)
Returns true if the function's return value(s) can be lowered directly, i.e., not indirectly via a po...
This is an optimization pass for GlobalISel generic memory operations.
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, const Function &ContextFunc, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
LLVM_ABI void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl< EVT > &ValueVTs, SmallVectorImpl< EVT > *MemVTs=nullptr, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
ComputeValueVTs - Given an LLVM IR type, compute a sequence of EVTs that represent all the individual...
Definition Analysis.cpp:121
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI LLT getLLTForMVT(MVT Ty)
Get a rough equivalent of an LLT for a given MVT.
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
DWARFExpression::Operation Op
LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL)
Construct a low-level type based on an LLVM type.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
SmallVector< Register, 4 > Regs
SmallVector< Register, 2 > OrigRegs
SmallVector< ISD::ArgFlagsTy, 4 > Flags
Extended Value Type.
Definition ValueTypes.h:35
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Flags
Flag bits describing an argument.