34#define DEBUG_TYPE "wasm-call-lowering"
55 return TargetOpcode::G_SEXT;
57 return TargetOpcode::G_ZEXT;
58 return TargetOpcode::G_ANYEXT;
62 if (Ty == MVT::externref) {
65 DL.getPointerSizeInBits(
69 if (Ty == MVT::funcref) {
72 DL.getPointerSizeInBits(
86 bool IsVarArg)
const {
105 "Return value without a vreg or vice versa");
116 "For each split Type there should be exactly one VReg.");
122 for (
EVT SplitEVT : SplitEVTs) {
124 ArgInfo CurRetInfo =
ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
131 for (
ArgInfo &Ret : SplitRets) {
132 const EVT OrigVT = TLI.getValueType(
DL, Ret.Ty);
134 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
143 const unsigned NumParts =
144 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
149 for (
unsigned Part = 0; Part < NumParts; ++Part) {
155 Flags.setOrigAlign(
Align(1));
156 if (Part == NumParts - 1)
160 Ret.Flags.push_back(Flags);
163 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
164 if (NumParts != 1 || OrigLLT != NewLLT) {
167 Ret.Regs.resize(NumParts);
172 for (
unsigned Part = 0; Part < NumParts; ++Part) {
176 Ret.Regs[Part] = NewReg;
188 if (SwiftErrorVReg) {
190 "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
191 "improperly valid.");
201 return WebAssembly::ARGUMENT_i32;
203 return WebAssembly::ARGUMENT_i64;
205 return WebAssembly::ARGUMENT_f32;
207 return WebAssembly::ARGUMENT_f64;
210 return WebAssembly::ARGUMENT_funcref;
212 return WebAssembly::ARGUMENT_externref;
214 return WebAssembly::ARGUMENT_exnref;
217 return WebAssembly::ARGUMENT_v16i8;
219 return WebAssembly::ARGUMENT_v8i16;
221 return WebAssembly::ARGUMENT_v4i32;
223 return WebAssembly::ARGUMENT_v2i64;
225 return WebAssembly::ARGUMENT_v8f16;
227 return WebAssembly::ARGUMENT_v4f32;
229 return WebAssembly::ARGUMENT_v2f64;
250 "Def already has reg bank or reg class?");
288 bool HasSwiftErrorArg =
false;
289 bool HasSwiftSelfArg =
false;
291 ArgInfo OrigArg{VRegs[ArgIdx], Arg.getType(), ArgIdx};
292 setArgFlags(OrigArg, ArgIdx + AttributeList::FirstArgIndex,
DL,
F);
294 HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
295 HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
296 if (Arg.hasInAllocaAttr())
298 if (Arg.hasNestAttr())
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);
315 const unsigned NumParts =
316 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
321 for (
unsigned Part = 0; Part < NumParts; ++Part) {
326 Flags.setOrigAlign(
Align(1));
327 if (Part == NumParts - 1)
331 Arg.Flags.push_back(Flags);
334 Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
335 if (NumParts != 1 || OrigLLT != NewLLT) {
338 Arg.Regs.resize(NumParts);
343 for (
unsigned Part = 0; Part < NumParts; ++Part) {
362 const MVT PtrVT = TLI.getPointerTy(
DL);
364 if (!HasSwiftSelfArg)
366 if (!HasSwiftErrorArg)
373 const MVT PtrVT = TLI.getPointerTy(
DL, 0);
414 if (Info.CB->isMustTailCall())
428 if (Info.Callee.isReg())
433 if (Info.Callee.isGlobal()) {
434 CallInst.addGlobalAddress(Info.Callee.getGlobal());
435 }
else if (Info.Callee.isSymbol()) {
436 CallInst.addExternalSymbol(Info.Callee.getSymbolName());
443 for (
const ArgInfo &Arg : Info.OrigArgs) {
444 if (Arg.
Flags[0].isNest())
446 if (Arg.
Flags[0].isInAlloca())
448 if (Arg.
Flags[0].isInConsecutiveRegs())
450 if (Arg.
Flags[0].isInConsecutiveRegsLast())
454 if (Arg.
Flags[0].isByVal() && Arg.
Flags[0].getByValSize() != 0)
460 for (
ArgInfo &Arg : SplitArgs) {
461 const EVT OrigVT = TLI.getValueType(
DL, Arg.
Ty);
462 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
471 const unsigned NumParts =
472 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
477 for (
unsigned Part = 0; Part < NumParts; ++Part) {
482 Flags.setOrigAlign(
Align(1));
483 if (Part == NumParts - 1)
487 Arg.
Flags.push_back(Flags);
491 if (NumParts != 1 || OrigLLT != NewLLT) {
494 Arg.
Regs.resize(NumParts);
499 for (
unsigned Part = 0; Part < NumParts; ++Part) {
503 Arg.
Regs[Part] = NewReg;
515 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
519 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
522 assert(Info.OrigRet.Regs.size() == SplitEVTs.
size() &&
523 "For each split Type there should be exactly one VReg.");
528 for (
EVT SplitEVT : SplitEVTs) {
529 Register CurVReg = Info.OrigRet.Regs[RetIdx];
530 ArgInfo CurArgInfo =
ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
533 setArgFlags(CurArgInfo, AttributeList::ReturnIndex,
DL, *Info.CB);
546 Align MemAlign =
DL.getABITypeAlign(CurArgInfo.
Ty);
547 Flags.setMemAlign(MemAlign);
548 Flags.setOrigAlign(MemAlign);
555 for (
ArgInfo &Ret : SplitRets) {
556 const EVT OrigVT = TLI.getValueType(
DL, Ret.Ty);
558 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
567 const unsigned NumParts =
568 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
573 for (
unsigned Part = 0; Part < NumParts; ++Part) {
578 Flags.setOrigAlign(
Align(1));
579 if (Part == NumParts - 1)
583 Ret.Flags.push_back(Flags);
586 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
588 if (NumParts != 1 || OrigLLT != NewLLT) {
591 Ret.Regs.resize(NumParts);
596 for (
unsigned Part = 0; Part < NumParts; ++Part) {
600 Ret.Regs[Part] = NewReg;
611 if (!Info.CanLowerReturn)
613 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
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - 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,...
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.
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'.
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.
@ WASM_ADDRESS_SPACE_EXTERNREF
@ WASM_ADDRESS_SPACE_FUNCREF
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...
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.
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.
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.