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
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()) {
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)
290 insertSRetIncomingArgument(F, SplitArgs, 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(OrigArg, ArgIdx + AttributeList::FirstArgIndex, DL, 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(OrigArg, SplitArgs, DL, F.getCallingConv());
307 ++ArgIdx;
308 }
309
310 unsigned FinalArgIdx = 0;
311 for (ArgInfo &Arg : SplitArgs) {
312 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
313 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
314 const LLT OrigLLT =
315 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
316 const LLT NewLLT = getLLTForMVT(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(Ctx, CallConv, 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(Flags);
337 }
338
339 Arg.OrigRegs.assign(Arg.Regs.begin(), 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(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(FinalArgIdx++, NewVT, NewLLT, MIRBuilder);
351 MFI->addParam(NewVT);
352 }
353
354 buildCopyFromRegs(MIRBuilder, Arg.OrigRegs, Arg.Regs, OrigLLT, NewLLT,
355 Arg.Flags[0]);
356 } else {
357 buildWasmArgument(FinalArgIdx++, NewVT, NewLLT, MIRBuilder, Arg.Regs[0]);
358 MFI->addParam(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(PtrVT);
371 if (!HasSwiftErrorArg)
372 MFI->addParam(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, 0);
379 const LLT PtrLLT = LLT::pointer(0, DL.getPointerSizeInBits(0));
380
381 Register VarargVreg =
382 buildWasmArgument(FinalArgIdx++, PtrVT, PtrLLT, MIRBuilder);
383 MFI->setVarargBufferVreg(VarargVreg);
384
385 MFI->addParam(PtrVT);
386 ++FinalArgIdx;
387 }
388
389 // Record the number and types of arguments and results.
390 SmallVector<MVT, 4> Params;
393 MF.getFunction(), 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
406 CallLoweringInfo &Info) const {
407 MachineFunction &MF = MIRBuilder.getMF();
408 const DataLayout &DL = MIRBuilder.getDataLayout();
409 LLVMContext &Ctx = MIRBuilder.getContext();
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(Info.OrigRet.Ty))
419 return false;
420 for (const ArgInfo &Arg : Info.OrigArgs)
421 if (typeContainsReference(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
437
438 // TODO: indirect calls
439 if (Info.Callee.isReg())
440 return false;
441
442 CallInst = MIRBuilder.buildInstrNoInsert(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(Arg, SplitArgs, DL, CallConv);
461 }
462
463 SmallVector<Register> CallUseRegs;
464
465 for (ArgInfo &Arg : SplitArgs) {
466 const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
467 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
468 const LLT OrigLLT =
469 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
470 const LLT NewLLT = getLLTForMVT(NewVT);
471
472 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(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(Ctx, CallConv, 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(Flags);
493 }
494
495 Arg.OrigRegs.assign(Arg.Regs.begin(), 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(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(&NewRegClass);
506 MRI.setType(NewReg, NewLLT);
507 CallUseRegs.push_back(NewReg);
508 Arg.Regs[Part] = NewReg;
509 }
510
511 buildCopyToRegs(MIRBuilder, Arg.Regs, Arg.OrigRegs[0], OrigLLT, NewLLT,
512 extendOpFromFlags(Arg.Flags[0]));
513 } else {
514 CallUseRegs.push_back(Arg.Regs[0]);
515 }
516 }
517
518 // Analyze operands of the call, assigning locations to each operand.
520 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
521
522 MIRBuilder.insertInstr(CallInst);
523
524 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
525 SmallVector<EVT, 4> SplitEVTs;
526 ComputeValueVTs(TLI, DL, Info.OrigRet.Ty, 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(Ctx), 0};
536
537 if (Info.CB) {
538 setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, *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 =
547 if (PtrTy) {
548 Flags.setPointer();
549 Flags.setPointerAddrSpace(PtrTy->getPointerAddressSpace());
550 }
551 Align MemAlign = DL.getABITypeAlign(CurArgInfo.Ty);
552 Flags.setMemAlign(MemAlign);
553 Flags.setOrigAlign(MemAlign);
554 }
555
556 splitToValueTypes(CurArgInfo, SplitRets, DL, CallConv);
557 ++RetIdx;
558 }
559
560 for (ArgInfo &Ret : SplitRets) {
561 const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
562 const MVT NewVT =
563 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
564 const LLT OrigLLT =
565 getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
566 const LLT NewLLT = getLLTForMVT(NewVT);
567
568 const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(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(Ctx, CallConv, 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(Flags);
589 }
590
591 Ret.OrigRegs.assign(Ret.Regs.begin(), 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(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(&NewRegClass);
603 MRI.setType(NewReg, NewLLT);
604 CallInst.addDef(NewReg);
605 Ret.Regs[Part] = NewReg;
606 }
607
608 buildCopyFromRegs(MIRBuilder, Ret.OrigRegs, Ret.Regs, OrigLLT, NewLLT,
609 Ret.Flags[0]);
610 } else {
611 MRI.setRegClass(Ret.Regs[0], &NewRegClass);
612 CallInst.addDef(Ret.Regs[0]);
613 }
614 }
615 }
616
617 if (Info.Callee.isGlobal()) {
618 CallInst.addGlobalAddress(Info.Callee.getGlobal());
619 } else if (Info.Callee.isSymbol()) {
620 CallInst.addExternalSymbol(Info.Callee.getSymbolName());
621 } else {
622 return false;
623 }
624
625 for (Register Reg : CallUseRegs) {
626 CallInst.addUse(Reg);
627 }
628
629 if (!Info.CanLowerReturn)
630 insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,
631 Info.DemoteRegister, Info.DemoteStackIndex);
632
633 return true;
634}
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 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: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...
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:368
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 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: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
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:1746
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.