34#define DEBUG_TYPE "wasm-call-lowering"
55 return TargetOpcode::G_SEXT;
57 return TargetOpcode::G_ZEXT;
58 return TargetOpcode::G_ANYEXT;
70 return typeContainsReference(ElemTy);
82 bool IsVarArg)
const {
104 "Return value without a vreg or vice versa");
115 "For each split Type there should be exactly one VReg.");
121 for (
EVT SplitEVT : SplitEVTs) {
123 ArgInfo CurRetInfo =
ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
130 for (
ArgInfo &Ret : SplitRets) {
131 const EVT OrigVT = TLI.getValueType(
DL, Ret.Ty);
133 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
142 const unsigned NumParts =
143 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
148 for (
unsigned Part = 0; Part < NumParts; ++Part) {
154 Flags.setOrigAlign(
Align(1));
155 if (Part == NumParts - 1)
159 Ret.
Flags.push_back(Flags);
162 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
163 if (NumParts != 1 || OrigLLT != NewLLT) {
166 Ret.Regs.resize(NumParts);
171 for (
unsigned Part = 0; Part < NumParts; ++Part) {
172 Register NewReg =
MRI.createVirtualRegister(&NewRegClass);
173 MRI.setType(NewReg, NewLLT);
175 Ret.Regs[Part] = NewReg;
187 if (SwiftErrorVReg) {
189 "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
190 "improperly valid.");
200 return WebAssembly::ARGUMENT_i32;
202 return WebAssembly::ARGUMENT_i64;
204 return WebAssembly::ARGUMENT_f32;
206 return WebAssembly::ARGUMENT_f64;
209 return WebAssembly::ARGUMENT_funcref;
211 return WebAssembly::ARGUMENT_externref;
213 return WebAssembly::ARGUMENT_exnref;
216 return WebAssembly::ARGUMENT_v16i8;
218 return WebAssembly::ARGUMENT_v8i16;
220 return WebAssembly::ARGUMENT_v4i32;
222 return WebAssembly::ARGUMENT_v2i64;
224 return WebAssembly::ARGUMENT_v8f16;
226 return WebAssembly::ARGUMENT_v4f32;
228 return WebAssembly::ARGUMENT_v2f64;
248 assert(
MRI.getRegClassOrRegBank(Def).isNull() &&
249 "Def already has reg bank or reg class?");
250 MRI.setRegClass(Def, &RegClass);
254 NewReg =
MRI.createVirtualRegister(&RegClass);
255 MRI.setType(NewReg, ArgLLT);
293 bool HasSwiftErrorArg =
false;
294 bool HasSwiftSelfArg =
false;
296 ArgInfo OrigArg{VRegs[ArgIdx], Arg.getType(), ArgIdx};
297 setArgFlags(OrigArg, ArgIdx + AttributeList::FirstArgIndex,
DL,
F);
299 HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
300 HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
301 if (Arg.hasInAllocaAttr())
303 if (Arg.hasNestAttr())
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);
320 const unsigned NumParts =
321 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
326 for (
unsigned Part = 0; Part < NumParts; ++Part) {
331 Flags.setOrigAlign(
Align(1));
332 if (Part == NumParts - 1)
336 Arg.
Flags.push_back(Flags);
339 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
340 if (NumParts != 1 || OrigLLT != NewLLT) {
343 Arg.Regs.resize(NumParts);
348 for (
unsigned Part = 0; Part < NumParts; ++Part) {
367 const MVT PtrVT = TLI.getPointerTy(
DL);
369 if (!HasSwiftSelfArg)
371 if (!HasSwiftErrorArg)
378 const MVT PtrVT = TLI.getPointerTy(
DL, 0);
420 for (
const ArgInfo &Arg : Info.OrigArgs)
425 if (Info.IsMustTailCall)
439 if (Info.Callee.isReg())
448 for (
const ArgInfo &Arg : Info.OrigArgs) {
449 if (Arg.
Flags[0].isNest())
451 if (Arg.
Flags[0].isInAlloca())
453 if (Arg.
Flags[0].isInConsecutiveRegs())
455 if (Arg.
Flags[0].isInConsecutiveRegsLast())
459 if (Arg.
Flags[0].isByVal() && Arg.
Flags[0].getByValSize() != 0)
467 for (
ArgInfo &Arg : SplitArgs) {
468 const EVT OrigVT = TLI.getValueType(
DL, Arg.
Ty);
469 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
478 const unsigned NumParts =
479 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
484 for (
unsigned Part = 0; Part < NumParts; ++Part) {
489 Flags.setOrigAlign(
Align(1));
490 if (Part == NumParts - 1)
494 Arg.
Flags.push_back(Flags);
498 if (NumParts != 1 || OrigLLT != NewLLT) {
501 Arg.
Regs.resize(NumParts);
506 for (
unsigned Part = 0; Part < NumParts; ++Part) {
507 Register NewReg =
MRI.createVirtualRegister(&NewRegClass);
508 MRI.setType(NewReg, NewLLT);
510 Arg.
Regs[Part] = NewReg;
522 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
526 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
529 assert(Info.OrigRet.Regs.size() == SplitEVTs.
size() &&
530 "For each split Type there should be exactly one VReg.");
535 for (
EVT SplitEVT : SplitEVTs) {
536 Register CurVReg = Info.OrigRet.Regs[RetIdx];
537 ArgInfo CurArgInfo =
ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
540 setArgFlags(CurArgInfo, AttributeList::ReturnIndex,
DL, *Info.CB);
553 Align MemAlign =
DL.getABITypeAlign(CurArgInfo.
Ty);
554 Flags.setMemAlign(MemAlign);
555 Flags.setOrigAlign(MemAlign);
562 for (
ArgInfo &Ret : SplitRets) {
563 const EVT OrigVT = TLI.getValueType(
DL, Ret.Ty);
565 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
574 const unsigned NumParts =
575 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
580 for (
unsigned Part = 0; Part < NumParts; ++Part) {
585 Flags.setOrigAlign(
Align(1));
586 if (Part == NumParts - 1)
590 Ret.
Flags.push_back(Flags);
593 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
595 if (NumParts != 1 || OrigLLT != NewLLT) {
598 Ret.Regs.resize(NumParts);
603 for (
unsigned Part = 0; Part < NumParts; ++Part) {
604 Register NewReg =
MRI.createVirtualRegister(&NewRegClass);
605 MRI.setType(NewReg, NewLLT);
607 Ret.Regs[Part] = NewReg;
613 MRI.setRegClass(Ret.Regs[0], &NewRegClass);
619 if (Info.Callee.isGlobal()) {
620 CallInst.addGlobalAddress(Info.Callee.getGlobal());
621 }
else if (Info.Callee.isSymbol()) {
622 CallInst.addExternalSymbol(Info.Callee.getSymbolName());
631 if (!Info.CanLowerReturn)
633 Info.DemoteRegister, Info.DemoteStackIndex);
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.
This file declares the MachineIRBuilder class.
Promote Memory to Register
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
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.
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.
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.
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.
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.
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'.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void addUse(Use &U)
This method should only be used by the Use class.
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 ...
void setVarargBufferVreg(unsigned Reg)
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.
@ Swift
Calling convention for Swift.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ CXX_FAST_TLS
Used for access functions.
@ 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...
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
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...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
DWARFExpression::Operation Op
LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL)
Construct a low-level type based on an LLVM type.
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
SmallVector< Register, 4 > Regs
SmallVector< Register, 2 > OrigRegs
SmallVector< ISD::ArgFlagsTy, 4 > Flags
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Flags
Flag bits describing an argument.