LLVM: lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
35using namespace llvm;
36
37#define DEBUG_TYPE "wasm-frame-info"
38
39
40
41
42
43
44
45
46
47
48
49
50
51std::optional
53 int FrameIndex) {
55
56
58 return static_cast<unsigned>(MFI.getObjectOffset(FrameIndex));
59
60
61
64 return std::nullopt;
65
66
67
74
77
78
79 for (EVT ValueVT : ValueVTs)
80 FuncInfo->addLocal(ValueVT.getSimpleVT());
81
82
84 return static_cast<unsigned>(Local);
85}
86
87
88
89
90
91bool WebAssemblyFrameLowering::hasBP(const MachineFunction &MF) const {
92 const auto *RegInfo =
94 return RegInfo->hasStackRealignment(MF);
95}
96
97
98
101
102
103
104
105
106
107
108 bool HasFixedSizedObjects = MFI.getStackSize() > 0;
109 bool NeedsFixedReference = !hasBP(MF) || HasFixedSizedObjects;
110
114}
115
116
117
118
119
120
124}
125
126
127
128bool WebAssemblyFrameLowering::needsSPForLocalFrame(
132
133
134 bool HasExplicitSPUse =
137
138 return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF) ||
139 HasExplicitSPUse;
140}
141
142
143
144
150}
151
152
153
154
155bool WebAssemblyFrameLowering::needsSP(const MachineFunction &MF) const {
157}
158
159
160
161
162
163bool WebAssemblyFrameLowering::needsSPWriteback(
167
168
169
170
171
172
173
174 bool CanUseRedZone = MFI.getStackSize() <= RedZoneSize && !MFI.hasCalls() &&
176 return needsSPForLocalFrame(MF) && !CanUseRedZone;
177}
178
181 ? WebAssembly::SP64
182 : WebAssembly::SP32;
183}
184
187 ? WebAssembly::FP64
188 : WebAssembly::FP32;
189}
190
191unsigned
194 ? WebAssembly::CONST_I64
195 : WebAssembly::CONST_I32;
196}
197
200 ? WebAssembly::ADD_I64
201 : WebAssembly::ADD_I32;
202}
203
206 ? WebAssembly::SUB_I64
207 : WebAssembly::SUB_I32;
208}
209
212 ? WebAssembly::AND_I64
213 : WebAssembly::AND_I32;
214}
215
216unsigned
219 ? WebAssembly::GLOBAL_GET_I64
220 : WebAssembly::GLOBAL_GET_I32;
221}
222
223unsigned
226 ? WebAssembly::GLOBAL_SET_I64
227 : WebAssembly::GLOBAL_SET_I32;
228}
229
234
235 const char *ES = "__stack_pointer";
237
241}
242
247 assert(->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) &&
248 "Call frame pseudos should only be used for dynamic stack adjustment");
250 const auto *TII = ST.getInstrInfo();
251 if (I->getOpcode() == TII->getCallFrameDestroyOpcode() &&
252 needsSPWriteback(MF)) {
255 }
257}
258
261
263 assert(MFI.getCalleeSavedInfo().empty() &&
264 "WebAssembly should not have callee-saved registers");
265
266 if (!needsSP(MF))
267 return;
268 uint64_t StackSize = MFI.getStackSize();
269
271 const auto *TII = ST.getInstrInfo();
273
275 while (InsertPt != MBB.end() &&
277 ++InsertPt;
279
281 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
283 if (StackSize)
284 SPReg = MRI.createVirtualRegister(PtrRC);
285
286 const char *ES = "__stack_pointer";
290
291 bool HasBP = hasBP(MF);
292 if (HasBP) {
294 Register BasePtr = MRI.createVirtualRegister(PtrRC);
295 FI->setBasePointerVreg(BasePtr);
296 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), BasePtr)
298 }
299 if (StackSize) {
300
301 Register OffsetReg = MRI.createVirtualRegister(PtrRC);
307 }
308 if (HasBP) {
309 Register BitmaskReg = MRI.createVirtualRegister(PtrRC);
310 Align Alignment = MFI.getMaxAlign();
312 .addImm((int64_t) ~(Alignment.value() - 1));
316 }
318
319
320
323 }
324 if (StackSize && needsSPWriteback(MF)) {
326 }
327}
328
332 if (!needsSP(MF) || !needsSPWriteback(MF))
333 return;
335 const auto *TII = ST.getInstrInfo();
339
340 if (InsertPt != MBB.end())
341 DL = InsertPt->getDebugLoc();
342
343
344
345 unsigned SPReg = 0;
347 if (hasBP(MF)) {
349 SPReg = FI->getBasePointerVreg();
350 } else if (StackSize) {
352 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
353 Register OffsetReg = MRI.createVirtualRegister(PtrRC);
356
357
358
359 SPReg = MRI.createVirtualRegister(PtrRC);
363 } else {
365 }
366
368}
369
372
373
375 return true;
376
378}
379
383 Loc.Kind = DwarfFrameBase::WasmFrameBase;
388 } else {
389
390
392 }
393 return Loc;
394}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
static constexpr Register SPReg
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements WebAssembly-specific bits of TargetFrameLowering class.
This file contains the WebAssembly implementation of the TargetInstrInfo class.
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
an instruction to allocate memory on the stack
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
bool hasPersonalityFn() const
Check whether this function has a personality function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
ExceptionHandling getExceptionHandlingType() const
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
const AllocaInst * getObjectAllocation(int ObjectIdx) const
Return the underlying Alloca of the specified stack object if it exists.
bool hasCalls() const
Return true if the current function has any function calls.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
bool hasPatchPoint() const
This method may be called any time after instruction selection is complete to determine if there is a...
void setObjectSize(int ObjectIdx, int64_t Size)
Change the size of the specified stack object.
void setStackID(int ObjectIdx, uint8_t ID)
bool hasStackMap() const
This method may be called any time after instruction selection is complete to determine if there is a...
uint8_t getStackID(int ObjectIdx) const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const char * createExternalSymbolName(StringRef Name)
Allocate a string and populate it with the given external symbol name.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
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 TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MachineOperand class - Representation of each machine instruction operand.
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual bool isSupportedStackID(TargetStackID::Value ID) const
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
static unsigned getOpcAdd(const MachineFunction &MF)
static unsigned getFPReg(const MachineFunction &MF)
bool needsPrologForEH(const MachineFunction &MF) const
static unsigned getOpcGlobSet(const MachineFunction &MF)
bool hasReservedCallFrame(const MachineFunction &MF) const override
Under normal circumstances, when a frame pointer is not required, we reserve argument space for call ...
static unsigned getOpcAnd(const MachineFunction &MF)
static unsigned getSPReg(const MachineFunction &MF)
static unsigned getOpcGlobGet(const MachineFunction &MF)
DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override
Return the frame base information to be encoded in the DWARF subprogram debug info.
bool isSupportedStackID(TargetStackID::Value ID) const override
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
static unsigned getOpcConst(const MachineFunction &MF)
bool hasFPImpl(const MachineFunction &MF) const override
Return true if the specified function should have a dedicated frame pointer register.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
These methods insert prolog and epilog code into the function.
void writeSPToGlobal(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) const
Write SP back to __stack_pointer global.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
static const size_t RedZoneSize
Size of the red zone for the user stack (leaf functions can use this much space below the stack point...
static std::optional< unsigned > getLocalForStackObject(MachineFunction &MF, int FrameIndex)
static unsigned getOpcSub(const MachineFunction &MF)
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
unsigned getFrameBaseLocal() const
const std::vector< MVT > & getLocals() const
bool isFrameBaseVirtual() const
const std::vector< MVT > & getParams() const
bool isArgument(unsigned Opc)
bool isWasmVarAddressSpace(unsigned AS)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Wasm
WebAssembly Exception Handling.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl< EVT > &ValueVTs, SmallVectorImpl< EVT > *MemVTs, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
ComputeValueVTs - Given an LLVM IR type, compute a sequence of EVTs that represent all the individual...
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
union llvm::TargetFrameLowering::DwarfFrameBase::@248 Location
enum llvm::TargetFrameLowering::DwarfFrameBase::FrameBaseKind Kind
struct WasmFrameBase WasmLoc