summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@google.com>2016-01-29 18:37:49 +0000
committerDerek Schuff <dschuff@google.com>2016-01-29 18:37:49 +0000
commit6ea637af35c992cb3bece3e3e9e8de9cc42b8cd1 (patch)
tree611323b1eb845f348b851842c19d6ed0f16f709c /llvm/lib/Target
parent0df98ff9132a250aaf4b96accd1173ebe2f30ee5 (diff)
downloadbcm5719-llvm-6ea637af35c992cb3bece3e3e9e8de9cc42b8cd1.tar.gz
bcm5719-llvm-6ea637af35c992cb3bece3e3e9e8de9cc42b8cd1.zip
[WebAssembly] Support frame pointer
Add support for frame pointer use in prolog/epilog. Supports dynamic allocas but not yet over-aligned locals. Target-independend CG generates SP updates, but we still need to write back the SP value to memory when necessary. llvm-svn: 259220
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp90
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp2
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyRegNumbering.cpp7
3 files changed, 82 insertions, 17 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index 32d390de40a..2edcc3f8818 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -70,6 +70,7 @@ static void adjustStackPointer(unsigned StackSize,
const TargetInstrInfo* TII,
MachineBasicBlock::iterator InsertPt,
const DebugLoc& DL) {
+ assert((StackSize || !AdjustUp) && "Adjusting up by 0");
auto &MRI = MF.getRegInfo();
unsigned SPReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
@@ -82,8 +83,8 @@ static void adjustStackPointer(unsigned StackSize,
auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(),
MachineMemOperand::MOLoad, 4, 4);
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg)
- .addImm(0)
- .addReg(SPReg)
+ .addImm(0) // offset
+ .addReg(SPReg) // addr
.addImm(2) // p2align
.addMemOperand(LoadMMO);
// Add/Subtract the frame size
@@ -116,6 +117,9 @@ void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr(
unsigned Opc = I->getOpcode();
bool IsDestroy = Opc == TII->getCallFrameDestroyOpcode();
unsigned Amount = I->getOperand(0).getImm();
+ // TODO(dschuff): After we switch varargs to passing an explicit pointer
+ // rather than using an implicit call frame, assert here that Amount is 0
+ // and remove adjustStackPointer altogether.
if (Amount)
adjustStackPointer(Amount, IsDestroy, MF, MBB,
TII, I, DL);
@@ -128,23 +132,76 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
auto *MFI = MF.getFrameInfo();
assert(MFI->getCalleeSavedInfo().empty() &&
"WebAssembly should not have callee-saved registers");
- assert(!hasFP(MF) && "Functions needing frame pointers not yet supported");
+
uint64_t StackSize = MFI->getStackSize();
- if (!StackSize && (!MFI->adjustsStack() || MFI->getMaxCallFrameSize() == 0))
+ if (!StackSize && !MFI->adjustsStack())
return;
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
+ auto &MRI = MF.getRegInfo();
auto InsertPt = MBB.begin();
DebugLoc DL;
- adjustStackPointer(StackSize, false, MF, MBB, TII, InsertPt, DL);
+ unsigned SPReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
+ auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPReg)
+ .addExternalSymbol(SPSymbol);
+ // This MachinePointerInfo should reference __stack_pointer as well but
+ // doesn't because MachinePointerInfo() takes a GV which we don't have for
+ // __stack_pointer. TODO: check if PseudoSourceValue::ExternalSymbolCallEntry
+ // is appropriate instead. (likewise for EmitEpologue below)
+ auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(),
+ MachineMemOperand::MOLoad, 4, 4);
+ // Load the SP value.
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32),
+ StackSize ? SPReg : WebAssembly::SP32)
+ .addImm(0) // offset
+ .addReg(SPReg) // addr
+ .addImm(2) // p2align
+ .addMemOperand(LoadMMO);
+
+ unsigned OffsetReg = 0;
+ if (StackSize) {
+ // Subtract the frame size
+ OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
+ .addImm(StackSize);
+ BuildMI(MBB, InsertPt, DL,
+ TII->get(WebAssembly::SUB_I32),
+ WebAssembly::SP32)
+ .addReg(SPReg)
+ .addReg(OffsetReg);
+ }
+ if (hasFP(MF)) {
+ // Unlike most conventional targets (where FP points to the saved FP),
+ // FP points to the bottom of the fixed-size locals, so we can use positive
+ // offsets in load/store instructions.
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY_LOCAL_I32),
+ WebAssembly::FP32)
+ .addReg(WebAssembly::SP32);
+ }
+ if (StackSize) {
+ assert(OffsetReg);
+ // The SP32 register now has the new stacktop. Also write it back to memory.
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
+ .addExternalSymbol(SPSymbol);
+ auto *MMO = new MachineMemOperand(MachinePointerInfo(),
+ MachineMemOperand::MOStore, 4, 4);
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), WebAssembly::SP32)
+ .addImm(0)
+ .addReg(OffsetReg)
+ .addImm(2) // p2align
+ .addReg(WebAssembly::SP32)
+ .addMemOperand(MMO);
+ }
}
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
- uint64_t StackSize = MF.getFrameInfo()->getStackSize();
- if (!StackSize)
+ auto *MFI = MF.getFrameInfo();
+ uint64_t StackSize = MFI->getStackSize();
+ if (!StackSize && !MFI->adjustsStack())
return;
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
auto &MRI = MF.getRegInfo();
@@ -156,14 +213,17 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
DL = InsertPt->getDebugLoc();
}
- // Restore the stack pointer. Without FP its value is just SP32 - stacksize
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
- .addImm(StackSize);
+ // Restore the stack pointer. If we had fixed-size locals, add the offset
+ // subtracted in the prolog.
+ if (StackSize) {
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
+ .addImm(StackSize);
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), WebAssembly::SP32)
+ .addReg(hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32)
+ .addReg(OffsetReg);
+ }
+
auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
- // TODO: Fold this add into the const offset field of the store.
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), WebAssembly::SP32)
- .addReg(WebAssembly::SP32)
- .addReg(OffsetReg);
// Re-use OffsetReg to hold the address of the stacktop
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
.addExternalSymbol(SPSymbol);
@@ -173,6 +233,6 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
.addImm(0)
.addReg(OffsetReg)
.addImm(2) // p2align
- .addReg(WebAssembly::SP32)
+ .addReg((!StackSize && hasFP(MF)) ? WebAssembly::FP32 : WebAssembly::SP32)
.addMemOperand(MMO);
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
index 00aca688af4..a1181c8a4a3 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
@@ -58,7 +58,7 @@ void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
const TargetRegisterClass *RC =
TargetRegisterInfo::isVirtualRegister(DestReg)
? MRI.getRegClass(DestReg)
- : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(SrcReg);
+ : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
unsigned CopyLocalOpcode;
if (RC == &WebAssembly::I32RegClass)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegNumbering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegNumbering.cpp
index a76cb81b34f..f38f635d822 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegNumbering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegNumbering.cpp
@@ -108,10 +108,15 @@ bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
}
}
// Allocate locals for used physical registers
- if (FrameInfo.getStackSize() > 0) {
+ if (FrameInfo.getStackSize() > 0 || FrameInfo.adjustsStack()) {
DEBUG(dbgs() << "PReg SP " << CurReg << "\n");
MFI.addPReg(WebAssembly::SP32, CurReg++);
}
+ bool HasFP = MF.getSubtarget().getFrameLowering()->hasFP(MF);
+ if (HasFP) {
+ DEBUG(dbgs() << "PReg FP " << CurReg << "\n");
+ MFI.addPReg(WebAssembly::FP32, CurReg++);
+ }
return true;
}
OpenPOWER on IntegriCloud