[WebAssembly] Implement __builtin_frame_address.

Differential Revision: http://reviews.llvm.org/D17307


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261032 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2016-02-16 23:48:04 +00:00
parent 30d7b4334a
commit f3e241c3c2
5 changed files with 54 additions and 8 deletions

View File

@ -44,11 +44,11 @@ using namespace llvm;
/// register.
bool WebAssemblyFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
assert(!MFI->isFrameAddressTaken());
const auto *RegInfo =
MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
return MFI->hasVarSizedObjects() || MFI->hasStackMap() ||
MFI->hasPatchPoint() || RegInfo->needsStackRealignment(MF);
return MFI->isFrameAddressTaken() || MFI->hasVarSizedObjects() ||
MFI->hasStackMap() || MFI->hasPatchPoint() ||
RegInfo->needsStackRealignment(MF);
}
/// Under normal circumstances, when a frame pointer is not required, we reserve

View File

@ -542,9 +542,8 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
return SDValue();
case ISD::FRAMEADDR: // TODO: Make this return the userspace frame address
fail(DL, DAG, "WebAssembly hasn't implemented __builtin_frame_address");
return SDValue();
case ISD::FRAMEADDR:
return LowerFRAMEADDR(Op, DAG);
case ISD::CopyToReg:
return LowerCopyToReg(Op, DAG);
}
@ -579,6 +578,21 @@ SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
return DAG.getTargetFrameIndex(FI, Op.getValueType());
}
SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
SelectionDAG &DAG) const {
// Non-zero depths are not supported by WebAssembly currently. Use the
// legalizer's default expansion, which is to return 0 (what this function is
// documented to do).
if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
return SDValue();
DAG.getMachineFunction().getFrameInfo()->setFrameAddressIsTaken(true);
EVT VT = Op.getValueType();
unsigned FP =
Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction());
return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
}
SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);

View File

@ -78,6 +78,7 @@ class WebAssemblyTargetLowering final : public TargetLowering {
// Custom lowering hooks.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
SDValue LowerFrameIndex(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;

View File

@ -108,11 +108,11 @@ bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
}
}
// Allocate locals for used physical registers
if (FrameInfo.getStackSize() > 0 || FrameInfo.adjustsStack()) {
bool HasFP = MF.getSubtarget().getFrameLowering()->hasFP(MF);
if (FrameInfo.getStackSize() > 0 || FrameInfo.adjustsStack() || HasFP) {
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++);

View File

@ -181,4 +181,35 @@ exit:
ret void
}
declare void @use_i8_star(i8*)
declare i8* @llvm.frameaddress(i32)
; Test __builtin_frame_address(0).
; TODO: When the prolog/epilog sequences are optimized, refine these checks to
; be more specific.
; CHECK-LABEL: frameaddress_0:
; CHECK: __stack_pointer
; CHECK: load
; CHECK: call use_i8_star
; CHECK: __stack_pointer
; CHECK: store
define void @frameaddress_0() {
%t = call i8* @llvm.frameaddress(i32 0)
call void @use_i8_star(i8* %t)
ret void
}
; Test __builtin_frame_address(1).
; CHECK-LABEL: frameaddress_1:
; CHECK-NEXT: i32.const $push0=, 0{{$}}
; CHECK-NEXT: call use_i8_star@FUNCTION, $pop0{{$}}
; CHECK-NEXT: return{{$}}
define void @frameaddress_1() {
%t = call i8* @llvm.frameaddress(i32 1)
call void @use_i8_star(i8* %t)
ret void
}
; TODO: test over-aligned alloca