Add the llvm.frameallocate and llvm.recoverframeallocation intrinsics

These intrinsics allow multiple functions to share a single stack
allocation from one function's call frame. The function with the
allocation may only perform one allocation, and it must be in the entry
block.

Functions accessing the allocation call llvm.recoverframeallocation with
the function whose frame they are accessing and a frame pointer from an
active call frame of that function.

These intrinsics are very difficult to inline correctly, so the
intention is that they be introduced rarely, or at least very late
during EH preparation.

Reviewers: echristo, andrew.w.kaylor

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225746 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner
2015-01-13 00:48:10 +00:00
parent 698be08c84
commit 221a7075cf
21 changed files with 303 additions and 4 deletions

View File

@@ -48,6 +48,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -5581,6 +5582,58 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
}
case Intrinsic::instrprof_increment:
llvm_unreachable("instrprof failed to lower an increment");
case Intrinsic::frameallocate: {
MachineFunction &MF = DAG.getMachineFunction();
const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo();
// Do the allocation and map it as a normal value.
// FIXME: Maybe we should add this to the alloca map so that we don't have
// to register allocate it?
uint64_t Size = cast<ConstantInt>(I.getArgOperand(0))->getZExtValue();
int Alloc = MF.getFrameInfo()->CreateFrameAllocation(Size);
MVT PtrVT = TLI.getPointerTy(0);
SDValue FIVal = DAG.getFrameIndex(Alloc, PtrVT);
setValue(&I, FIVal);
// Directly emit a FRAME_ALLOC machine instr. Label assignment emission is
// the same on all targets.
MCSymbol *FrameAllocSym =
MF.getMMI().getContext().getOrCreateFrameAllocSymbol(MF.getName());
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, dl,
TII->get(TargetOpcode::FRAME_ALLOC))
.addSym(FrameAllocSym)
.addFrameIndex(Alloc);
return nullptr;
}
case Intrinsic::recoverframeallocation: {
// i8* @llvm.recoverframeallocation(i8* %fn, i8* %fp)
MachineFunction &MF = DAG.getMachineFunction();
MVT PtrVT = TLI.getPointerTy(0);
// Get the symbol that defines the frame offset.
Function *Fn = cast<Function>(I.getArgOperand(0)->stripPointerCasts());
MCSymbol *FrameAllocSym =
MF.getMMI().getContext().getOrCreateFrameAllocSymbol(Fn->getName());
// Create a TargetExternalSymbol for the label to avoid any target lowering
// that would make this PC relative.
StringRef Name = FrameAllocSym->getName();
assert(Name.size() == strlen(Name.data()) && "not null terminated");
SDValue OffsetSym = DAG.getTargetExternalSymbol(Name.data(), PtrVT);
SDValue OffsetVal =
DAG.getNode(ISD::RECOVER_FRAME_ALLOC, sdl, PtrVT, OffsetSym);
// Add the offset to the FP.
Value *FP = I.getArgOperand(1);
SDValue FPVal = getValue(FP);
SDValue Add = DAG.getNode(ISD::ADD, sdl, PtrVT, FPVal, OffsetVal);
setValue(&I, Add);
return nullptr;
}
}
}