LLVM 23.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
61static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL) {
62 if (Ty == MVT::externref) {
63 return LLT::pointer(
65 DL.getPointerSizeInBits(
67 }
68
69 if (Ty == MVT::funcref) {
70 return LLT::pointer(
72 DL.getPointerSizeInBits(
74 }
75
76 return llvm::getLLTForMVT(Ty);
77}
78
82
90
92 const Value *Val,
95 Register SwiftErrorVReg) const {
96 MachineFunction &MF = MIRBuilder.getMF();
97 const Function &F = MF.getFunction();
100 const DataLayout &DL = F.getDataLayout();
101
102 MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(WebAssembly::RETURN);
103
104 assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
105 "Return value without a vreg or vice versa");
106
107 if (Val) {
108 LLVMContext &Ctx = Val->getType()->getContext();
109
110 if (!FLI.CanLowerReturn) {
111 insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);
112 } else {
113 SmallVector<EVT, 4> SplitEVTs;
114 ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
115 assert(VRegs.size() == SplitEVTs.size() &&
116 "For each split Type there should be exactly one VReg.");
117
118 SmallVector<ArgInfo, 8> SplitRets;
119 CallingConv::ID CallConv = F.getCallingConv();
120
121 unsigned RetIdx = 0;
122 for (EVT SplitEVT : SplitEVTs) {
123 Register CurVReg = VRegs[RetIdx];
124 ArgInfo CurRetInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
125 setArgFlags(CurRetInfo, AttributeList::ReturnIndex, DL, F);
126
127 splitToValueTypes(CurRetInfo, SplitRets, DL, CallConv);
128 ++RetIdx;
129 }
130
131 for (ArgInfo &Ret : SplitRets) {
132 const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
133 const MVT NewVT =
134 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
135 const LLT OrigLLT =
136 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
137 const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
138
139 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
140
141 // If we need to split the type over multiple regs, check it's a
142 // scenario we currently support.
143 const unsigned NumParts =
144 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
145
146 const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
147 Ret.Flags.clear();
148
149 for (unsigned Part = 0; Part < NumParts; ++Part) {
150 ISD::ArgFlagsTy Flags = OrigFlags;
151
152 if (Part == 0) {
153 Flags.setSplit();
154 } else {
155 Flags.setOrigAlign(Align(1));
156 if (Part == NumParts - 1)
157 Flags.setSplitEnd();
158 }
159
160 Ret.Flags.push_back(Flags);
161 }
162
163 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
164 if (NumParts != 1 || OrigLLT != NewLLT) {
165 // If we can't directly assign the register, we need one or more
166 // intermediate values.
167 Ret.Regs.resize(NumParts);
168
169 // For each split register, create and assign a vreg that will store
170 // the incoming component of the larger value. These will later be
171 // merged to form the final vreg.
172 for (unsigned Part = 0; Part < NumParts; ++Part) {
173 Register NewReg = MRI.createVirtualRegister(&NewRegClass);
174 MRI.setType(NewReg, NewLLT);
175 MIB.addUse(NewReg);
176 Ret.Regs[Part] = NewReg;
177 }
178
179 buildCopyToRegs(MIRBuilder, Ret.Regs, Ret.OrigRegs[0], OrigLLT,
180 NewLLT, extendOpFromFlags(Ret.Flags[0]));
181 } else {
182 MIB.addUse(Ret.Regs[0]);
183 }
184 }
185 }
186 }
187
188 if (SwiftErrorVReg) {
190 "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
191 "improperly valid.");
192 }
193
194 MIRBuilder.insertInstr(MIB);
195 return true;
196}
197
198static unsigned getWasmArgumentOpcode(MVT ArgType) {
199 switch (ArgType.SimpleTy) {
200 case MVT::i32:
201 return WebAssembly::ARGUMENT_i32;
202 case MVT::i64:
203 return WebAssembly::ARGUMENT_i64;
204 case MVT::f32:
205 return WebAssembly::ARGUMENT_f32;
206 case MVT::f64:
207 return WebAssembly::ARGUMENT_f64;
208
209 case MVT::funcref:
210 return WebAssembly::ARGUMENT_funcref;
211 case MVT::externref:
212 return WebAssembly::ARGUMENT_externref;
213 case MVT::exnref:
214 return WebAssembly::ARGUMENT_exnref;
215
216 case MVT::v16i8:
217 return WebAssembly::ARGUMENT_v16i8;
218 case MVT::v8i16:
219 return WebAssembly::ARGUMENT_v8i16;
220 case MVT::v4i32:
221 return WebAssembly::ARGUMENT_v4i32;
222 case MVT::v2i64:
223 return WebAssembly::ARGUMENT_v2i64;
224 case MVT::v8f16:
225 return WebAssembly::ARGUMENT_v8f16;
226 case MVT::v4f32:
227 return WebAssembly::ARGUMENT_v4f32;
228 case MVT::v2f64:
229 return WebAssembly::ARGUMENT_v2f64;
230 default:
231 break;
232 }
233 llvm_unreachable("Found unexpected type for Wasm argument");
234}
235
236static Register buildWasmArgument(unsigned Idx, MVT ArgVT, LLT ArgLLT,
237 MachineIRBuilder &MIRBuilder,
238 Register Def = Register()) {
239 unsigned Op = getWasmArgumentOpcode(ArgVT);
240
241 const TargetInstrInfo &TII = MIRBuilder.getTII();
242 MachineFunction &MF = MIRBuilder.getMF();
244 const TargetRegisterClass &RegClass = *TII.getRegClass(TII.get(Op), 0);
245
246 Register NewReg;
247
248 if (Def.isValid()) {
250 "Def already has reg bank or reg class?");
251 MRI.setRegClass(Def, &RegClass);
252
253 NewReg = Def;
254 } else {
255 NewReg = MRI.createVirtualRegister(&RegClass);
256 MRI.setType(NewReg, ArgLLT);
257 }
258
259 MIRBuilder.buildInstr(Op).addDef(NewReg).addImm(Idx);
260
261 return NewReg;
262}
263
265 MachineIRBuilder &MIRBuilder, const Function &F,
267 MachineFunction &MF = MIRBuilder.getMF();
270 const DataLayout &DL = F.getDataLayout();
272
273 LLVMContext &Ctx = MIRBuilder.getContext();
274 const CallingConv::ID CallConv = F.getCallingConv();
275
276 if (!callingConvSupported(CallConv))
277 return false;
278
279 MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
280 MF.front().addLiveIn(WebAssembly::ARGUMENTS);
281
282 SmallVector<ArgInfo, 8> SplitArgs;
283
284 if (!FLI.CanLowerReturn)
285 insertSRetIncomingArgument(F, SplitArgs, FLI.DemoteRegister, MRI, DL);
286
287 unsigned ArgIdx = 0;
288 bool HasSwiftErrorArg = false;
289 bool HasSwiftSelfArg = false;
290 for (const Argument &Arg : F.args()) {
291 ArgInfo OrigArg{VRegs[ArgIdx], Arg.getType(), ArgIdx};
292 setArgFlags(OrigArg, ArgIdx + AttributeList::FirstArgIndex, DL, F);
293
294 HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
295 HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
296 if (Arg.hasInAllocaAttr())
297 return false;
298 if (Arg.hasNestAttr())
299 return false;
300
301 splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
302 ++ArgIdx;
303 }
304
305 unsigned FinalArgIdx = 0;
306 for (ArgInfo &Arg : SplitArgs) {
307 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
308 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
309 const LLT OrigLLT =
310 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
311 const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
312
313 // If we need to split the type over multiple regs, check it's a scenario
314 // we currently support.
315 const unsigned NumParts =
316 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
317
318 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
319 Arg.Flags.clear();
320
321 for (unsigned Part = 0; Part < NumParts; ++Part) {
322 ISD::ArgFlagsTy Flags = OrigFlags;
323 if (Part == 0) {
324 Flags.setSplit();
325 } else {
326 Flags.setOrigAlign(Align(1));
327 if (Part == NumParts - 1)
328 Flags.setSplitEnd();
329 }
330
331 Arg.Flags.push_back(Flags);
332 }
333
334 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
335 if (NumParts != 1 || OrigLLT != NewLLT) {
336 // If we can't directly assign the register, we need one or more
337 // intermediate values.
338 Arg.Regs.resize(NumParts);
339
340 // For each split register, create and assign a vreg that will store
341 // the incoming component of the larger value. These will later be
342 // merged to form the final vreg.
343 for (unsigned Part = 0; Part < NumParts; ++Part) {
344 Arg.Regs[Part] =
345 buildWasmArgument(FinalArgIdx++, NewVT, NewLLT, MIRBuilder);
346 MFI->addParam(NewVT);
347 }
348
349 buildCopyFromRegs(MIRBuilder, Arg.OrigRegs, Arg.Regs, OrigLLT, NewLLT,
350 Arg.Flags[0]);
351 } else {
352 buildWasmArgument(FinalArgIdx++, NewVT, NewLLT, MIRBuilder, Arg.Regs[0]);
353 MFI->addParam(NewVT);
354 }
355 }
356
357 // For swiftcc, emit additional swiftself and swifterror arguments
358 // if there aren't. These additional arguments are also added for callee
359 // signature They are necessary to match callee and caller signature for
360 // indirect call.
361 if (CallConv == CallingConv::Swift) {
362 const MVT PtrVT = TLI.getPointerTy(DL);
363
364 if (!HasSwiftSelfArg)
365 MFI->addParam(PtrVT);
366 if (!HasSwiftErrorArg)
367 MFI->addParam(PtrVT);
368 }
369
370 // Varargs are copied into a buffer allocated by the caller, and a pointer to
371 // the buffer is passed as an argument.
372 if (F.isVarArg()) {
373 const MVT PtrVT = TLI.getPointerTy(DL, 0);
374 const LLT PtrLLT = LLT::pointer(0, DL.getPointerSizeInBits(0));
375
376 Register VarargVreg =
377 buildWasmArgument(FinalArgIdx++, PtrVT, PtrLLT, MIRBuilder);
378 MFI->setVarargBufferVreg(VarargVreg);
379
380 MFI->addParam(PtrVT);
381 ++FinalArgIdx;
382 }
383
384 // Record the number and types of arguments and results.
385 SmallVector<MVT, 4> Params;
388 MF.getFunction(), MF.getTarget(), Params, Results);
389 for (MVT VT : Results)
390 MFI->addResult(VT);
391
392 // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
393 // the param logic here with ComputeSignatureVTs
394 assert(MFI->getParams().size() == Params.size() &&
395 std::equal(MFI->getParams().begin(), MFI->getParams().end(),
396 Params.begin()));
397 return true;
398}
399
401 CallLoweringInfo &Info) const {
402 MachineFunction &MF = MIRBuilder.getMF();
403 const DataLayout &DL = MIRBuilder.getDataLayout();
404 LLVMContext &Ctx = MIRBuilder.getContext();
406 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
407 const Function &F = MF.getFunction();
408
409 CallingConv::ID CallConv = Info.CallConv;
410 if (!callingConvSupported(CallConv))
411 return false;
412
413 // TODO: tail calls
414 if (Info.CB->isMustTailCall())
415 return false;
416
417 // TODO: varargs
418 if (Info.IsVarArg)
419 return false;
420
421 // TODO: swiftcc
422 if (CallConv == CallingConv::Swift)
423 return false;
424
426
427 // TODO: indirect calls
428 if (Info.Callee.isReg())
429 return false;
430
431 CallInst = MIRBuilder.buildInstrNoInsert(WebAssembly::CALL);
432
433 if (Info.Callee.isGlobal()) {
434 CallInst.addGlobalAddress(Info.Callee.getGlobal());
435 } else if (Info.Callee.isSymbol()) {
436 CallInst.addExternalSymbol(Info.Callee.getSymbolName());
437 } else {
438 return false;
439 }
440
441 SmallVector<ArgInfo, 8> SplitArgs;
442
443 for (const ArgInfo &Arg : Info.OrigArgs) {
444 if (Arg.Flags[0].isNest())
445 return false;
446 if (Arg.Flags[0].isInAlloca())
447 return false;
448 if (Arg.Flags[0].isInConsecutiveRegs())
449 return false;
450 if (Arg.Flags[0].isInConsecutiveRegsLast())
451 return false;
452
453 // TODO: bulk memory, then byval
454 if (Arg.Flags[0].isByVal() && Arg.Flags[0].getByValSize() != 0)
455 return false;
456
457 splitToValueTypes(Arg, SplitArgs, DL, CallConv);
458 }
459
460 for (ArgInfo &Arg : SplitArgs) {
461 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
462 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
463 const LLT OrigLLT =
464 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
465 const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
466
467 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
468
469 // If we need to split the type over multiple regs, check it's a scenario
470 // we currently support.
471 const unsigned NumParts =
472 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
473
474 const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
475 Arg.Flags.clear();
476
477 for (unsigned Part = 0; Part < NumParts; ++Part) {
478 ISD::ArgFlagsTy Flags = OrigFlags;
479 if (Part == 0) {
480 Flags.setSplit();
481 } else {
482 Flags.setOrigAlign(Align(1));
483 if (Part == NumParts - 1)
484 Flags.setSplitEnd();
485 }
486
487 Arg.Flags.push_back(Flags);
488 }
489
490 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
491 if (NumParts != 1 || OrigLLT != NewLLT) {
492 // If we can't directly assign the register, we need one or more
493 // intermediate values.
494 Arg.Regs.resize(NumParts);
495
496 // For each split register, create and assign a vreg that will store
497 // the incoming component of the larger value. These will later be
498 // merged to form the final vreg.
499 for (unsigned Part = 0; Part < NumParts; ++Part) {
500 Register NewReg = MRI.createVirtualRegister(&NewRegClass);
501 MRI.setType(NewReg, NewLLT);
502 CallInst.addUse(NewReg);
503 Arg.Regs[Part] = NewReg;
504 }
505
506 buildCopyToRegs(MIRBuilder, Arg.Regs, Arg.OrigRegs[0], OrigLLT, NewLLT,
507 extendOpFromFlags(Arg.Flags[0]));
508 } else {
509 CallInst.addUse(Arg.Regs[0]);
510 }
511 }
512
513 // Analyze operands of the call, assigning locations to each operand.
515 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
516
517 MIRBuilder.insertInstr(CallInst);
518
519 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
520 SmallVector<EVT, 4> SplitEVTs;
521 ComputeValueVTs(TLI, DL, Info.OrigRet.Ty, SplitEVTs);
522 assert(Info.OrigRet.Regs.size() == SplitEVTs.size() &&
523 "For each split Type there should be exactly one VReg.");
524
525 SmallVector<ArgInfo, 8> SplitRets;
526
527 unsigned RetIdx = 0;
528 for (EVT SplitEVT : SplitEVTs) {
529 Register CurVReg = Info.OrigRet.Regs[RetIdx];
530 ArgInfo CurArgInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
531
532 if (Info.CB) {
533 setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, *Info.CB);
534 } else {
535 // We don't have a call base, so chances are we're looking at a
536 // libcall (external symbol).
537
538 // TODO: figure out how to get ALL the correct attributes
539 ISD::ArgFlagsTy &Flags = CurArgInfo.Flags[0];
540 PointerType *PtrTy =
542 if (PtrTy) {
543 Flags.setPointer();
544 Flags.setPointerAddrSpace(PtrTy->getPointerAddressSpace());
545 }
546 Align MemAlign = DL.getABITypeAlign(CurArgInfo.Ty);
547 Flags.setMemAlign(MemAlign);
548 Flags.setOrigAlign(MemAlign);
549 }
550
551 splitToValueTypes(CurArgInfo, SplitRets, DL, CallConv);
552 ++RetIdx;
553 }
554
555 for (ArgInfo &Ret : SplitRets) {
556 const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
557 const MVT NewVT =
558 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
559 const LLT OrigLLT =
560 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
561 const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
562
563 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
564
565 // If we need to split the type over multiple regs, check it's a scenario
566 // we currently support.
567 const unsigned NumParts =
568 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
569
570 const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
571 Ret.Flags.clear();
572
573 for (unsigned Part = 0; Part < NumParts; ++Part) {
574 ISD::ArgFlagsTy Flags = OrigFlags;
575 if (Part == 0) {
576 Flags.setSplit();
577 } else {
578 Flags.setOrigAlign(Align(1));
579 if (Part == NumParts - 1)
580 Flags.setSplitEnd();
581 }
582
583 Ret.Flags.push_back(Flags);
584 }
585
586 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
587
588 if (NumParts != 1 || OrigLLT != NewLLT) {
589 // If we can't directly assign the register, we need one or more
590 // intermediate values.
591 Ret.Regs.resize(NumParts);
592
593 // For each split register, create and assign a vreg that will store
594 // the incoming component of the larger value. These will later be
595 // merged to form the final vreg.
596 for (unsigned Part = 0; Part < NumParts; ++Part) {
597 Register NewReg = MRI.createVirtualRegister(&NewRegClass);
598 MRI.setType(NewReg, NewLLT);
599 CallInst.addDef(NewReg);
600 Ret.Regs[Part] = NewReg;
601 }
602
603 buildCopyFromRegs(MIRBuilder, Ret.OrigRegs, Ret.Regs, OrigLLT, NewLLT,
604 Ret.Flags[0]);
605 } else {
606 CallInst.addDef(Ret.Regs[0]);
607 }
608 }
609 }
610
611 if (!Info.CanLowerReturn)
612 insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,
613 Info.DemoteRegister, Info.DemoteStackIndex);
614
615 return true;
616}
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
This file declares the MachineIRBuilder class.
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool callingConvSupported(CallingConv::ID CallConv)
static unsigned getWasmArgumentOpcode(MVT ArgType)
static Register buildWasmArgument(unsigned Idx, MVT ArgVT, LLT ArgLLT, MachineIRBuilder &MIRBuilder, Register Def=Register())
static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL)
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 utility functions.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
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:211
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:68
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,...
const RegClassOrRegBank & getRegClassOrRegBank(Register Reg) const
Return the register bank or register class of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
Class to represent pointers.
bool isNull() const
Test if the pointer held in the union is null, regardless of which type it is.
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...
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.
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:370
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:255
void addUse(Use &U)
This method should only be used by the Use class.
Definition Value.h:513
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 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)
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:119
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
DWARFExpression::Operation Op
LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL)
Construct a low-level type based on an LLVM type.
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.