34#define DEBUG_TYPE "wasm-call-lowering"
55 return TargetOpcode::G_SEXT;
57 return TargetOpcode::G_ZEXT;
58 return TargetOpcode::G_ANYEXT;
69 return any_of(StructTy->elements(), [](
const Type *ElemTy) {
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) {
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;
249 "Def already has reg bank or reg class?");
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())
446 for (
const ArgInfo &Arg : Info.OrigArgs) {
447 if (Arg.
Flags[0].isNest())
449 if (Arg.
Flags[0].isInAlloca())
451 if (Arg.
Flags[0].isInConsecutiveRegs())
453 if (Arg.
Flags[0].isInConsecutiveRegsLast())
457 if (Arg.
Flags[0].isByVal() && Arg.
Flags[0].getByValSize() != 0)
465 for (
ArgInfo &Arg : SplitArgs) {
466 const EVT OrigVT = TLI.getValueType(
DL, Arg.
Ty);
467 const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
476 const unsigned NumParts =
477 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
482 for (
unsigned Part = 0; Part < NumParts; ++Part) {
487 Flags.setOrigAlign(
Align(1));
488 if (Part == NumParts - 1)
492 Arg.
Flags.push_back(Flags);
496 if (NumParts != 1 || OrigLLT != NewLLT) {
499 Arg.
Regs.resize(NumParts);
504 for (
unsigned Part = 0; Part < NumParts; ++Part) {
508 Arg.
Regs[Part] = NewReg;
520 CCState CCInfo(CallConv, Info.IsVarArg, MF, ArgLocs, Ctx);
524 if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {
527 assert(Info.OrigRet.Regs.size() == SplitEVTs.
size() &&
528 "For each split Type there should be exactly one VReg.");
533 for (
EVT SplitEVT : SplitEVTs) {
534 Register CurVReg = Info.OrigRet.Regs[RetIdx];
535 ArgInfo CurArgInfo =
ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
538 setArgFlags(CurArgInfo, AttributeList::ReturnIndex,
DL, *Info.CB);
551 Align MemAlign =
DL.getABITypeAlign(CurArgInfo.
Ty);
552 Flags.setMemAlign(MemAlign);
553 Flags.setOrigAlign(MemAlign);
560 for (
ArgInfo &Ret : SplitRets) {
561 const EVT OrigVT = TLI.getValueType(
DL, Ret.Ty);
563 TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
572 const unsigned NumParts =
573 TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
578 for (
unsigned Part = 0; Part < NumParts; ++Part) {
583 Flags.setOrigAlign(
Align(1));
584 if (Part == NumParts - 1)
588 Ret.Flags.push_back(Flags);
591 Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
593 if (NumParts != 1 || OrigLLT != NewLLT) {
596 Ret.Regs.resize(NumParts);
601 for (
unsigned Part = 0; Part < NumParts; ++Part) {
605 Ret.Regs[Part] = NewReg;
617 if (Info.Callee.isGlobal()) {
618 CallInst.addGlobalAddress(Info.Callee.getGlobal());
619 }
else if (Info.Callee.isSymbol()) {
620 CallInst.addExternalSymbol(Info.Callee.getSymbolName());
629 if (!Info.CanLowerReturn)
631 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 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,...
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...
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.
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.