#define DEBUG_TYPE "stackmaps"
#include "llvm/CodeGen/StackMaps.h"
-
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetOpcodes.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOpcodes.h"
#include "llvm/Target/TargetRegisterInfo.h"
-
#include <iterator>
using namespace llvm;
++CheckStartIdx;
assert(getMetaIdx() == CheckStartIdx &&
- "Unexpected additonal definition in Patchpoint intrinsic.");
+ "Unexpected additional definition in Patchpoint intrinsic.");
#endif
}
}
/// Go up the super-register chain until we hit a valid dwarf register number.
-static unsigned short getDwarfRegNum(unsigned Reg, const MCRegisterInfo &MCRI,
- const TargetRegisterInfo *TRI) {
- int RegNo = MCRI.getDwarfRegNum(Reg, false);
- for (MCSuperRegIterator SR(Reg, TRI);
- SR.isValid() && RegNo < 0; ++SR)
+static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI) {
+ int RegNo = TRI->getDwarfRegNum(Reg, false);
+ for (MCSuperRegIterator SR(Reg, TRI); SR.isValid() && RegNo < 0; ++SR)
RegNo = TRI->getDwarfRegNum(*SR, false);
assert(RegNo >= 0 && "Invalid Dwarf register number.");
- return (unsigned short) RegNo;
+ return (unsigned) RegNo;
}
/// Create a live-out register record for the given register Reg.
StackMaps::LiveOutReg
-StackMaps::createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI,
- const TargetRegisterInfo *TRI) const {
- unsigned RegNo = getDwarfRegNum(Reg, MCRI, TRI);
+StackMaps::createLiveOutReg(unsigned Reg, const TargetRegisterInfo *TRI) const {
+ unsigned RegNo = getDwarfRegNum(Reg, TRI);
unsigned Size = TRI->getMinimalPhysRegClass(Reg)->getSize();
return LiveOutReg(Reg, RegNo, Size);
}
StackMaps::parseRegisterLiveOutMask(const uint32_t *Mask) const {
assert(Mask && "No register mask specified");
const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
- MCContext &OutContext = AP.OutStreamer.getContext();
- const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();
LiveOutVec LiveOuts;
// Create a LiveOutReg for each bit that is set in the register mask.
for (unsigned Reg = 0, NumRegs = TRI->getNumRegs(); Reg != NumRegs; ++Reg)
if ((Mask[Reg / 32] >> Reg % 32) & 1)
- LiveOuts.push_back(createLiveOutReg(Reg, MCRI, TRI));
+ LiveOuts.push_back(createLiveOutReg(Reg, TRI));
// We don't need to keep track of a register if its super-register is already
// in the list. Merge entries that refer to the same dwarf register and use
std::sort(LiveOuts.begin(), LiveOuts.end());
for (LiveOutVec::iterator I = LiveOuts.begin(), E = LiveOuts.end();
I != E; ++I) {
- for (LiveOutVec::iterator II = next(I); II != E; ++II) {
+ for (LiveOutVec::iterator II = std::next(I); II != E; ++II) {
if (I->RegNo != II->RegNo) {
// Skip all the now invalid entries.
I = --II;
if (recordResult) {
assert(PatchPointOpers(&MI).hasDef() && "Stackmap has no return value.");
- parseOperand(MI.operands_begin(), llvm::next(MI.operands_begin()),
+ parseOperand(MI.operands_begin(), std::next(MI.operands_begin()),
Locations, LiveOuts);
}
// Move large constants into the constant pool.
for (LocationVec::iterator I = Locations.begin(), E = Locations.end();
I != E; ++I) {
- if (I->LocType == Location::Constant && (I->Offset & ~0xFFFFFFFFULL)) {
+ // Constants are encoded as sign-extended integers.
+ // -1 is directly encoded as .long 0xFFFFFFFF with no constant pool.
+ if (I->LocType == Location::Constant &&
+ ((I->Offset + (int64_t(1)<<31)) >> 32) != 0) {
I->LocType = Location::ConstantIndex;
I->Offset = ConstPool.getConstantIndex(I->Offset);
}
}
+ // Create an expression to calculate the offset of the callsite from function
+ // entry.
const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
MCSymbolRefExpr::Create(MILabel, OutContext),
MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
OutContext);
CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, Locations, LiveOuts));
+
+ // Record the stack size of the current function.
+ const MachineFrameInfo *MFI = AP.MF->getFrameInfo();
+ FnStackSize[AP.CurrentFnSym] =
+ MFI->hasVarSizedObjects() ? ~0U : MFI->getStackSize();
}
void StackMaps::recordStackMap(const MachineInstr &MI) {
assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
int64_t ID = MI.getOperand(0).getImm();
- recordStackMapOpers(MI, ID, llvm::next(MI.operands_begin(), 2),
+ recordStackMapOpers(MI, ID, std::next(MI.operands_begin(), 2),
MI.operands_end());
}
int64_t ID = opers.getMetaOper(PatchPointOpers::IDPos).getImm();
MachineInstr::const_mop_iterator MOI =
- llvm::next(MI.operands_begin(), opers.getStackMapStartIdx());
+ std::next(MI.operands_begin(), opers.getStackMapStartIdx());
recordStackMapOpers(MI, ID, MOI, MI.operands_end(),
opers.isAnyReg() && opers.hasDef());
/// serializeToStackMapSection conceptually populates the following fields:
///
/// uint32 : Reserved (header)
+/// uint32 : NumFunctions
+/// StkSizeRecord[NumFunctions] {
+/// uint32 : Function Offset
+/// uint32 : Stack Size
+/// }
/// uint32 : NumConstants
/// int64 : Constants[NumConstants]
/// uint32 : NumRecords
// Serialize data.
const char *WSMP = "Stack Maps: ";
(void)WSMP;
- const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();
DEBUG(dbgs() << "********** Stack Map Output **********\n");
// Header.
AP.OutStreamer.EmitIntValue(0, 4);
+ // Num functions.
+ AP.OutStreamer.EmitIntValue(FnStackSize.size(), 4);
+
+ // Stack size entries.
+ for (FnStackSizeMap::iterator I = FnStackSize.begin(), E = FnStackSize.end();
+ I != E; ++I) {
+ AP.OutStreamer.EmitSymbolValue(I->first, 4);
+ AP.OutStreamer.EmitIntValue(I->second, 4);
+ }
+
// Num constants.
AP.OutStreamer.EmitIntValue(ConstPool.getNumConstants(), 4);
unsigned RegNo = 0;
int Offset = Loc.Offset;
if(Loc.Reg) {
- RegNo = MCRI.getDwarfRegNum(Loc.Reg, false);
- for (MCSuperRegIterator SR(Loc.Reg, TRI);
- SR.isValid() && (int)RegNo < 0; ++SR) {
- RegNo = TRI->getDwarfRegNum(*SR, false);
- }
+ RegNo = getDwarfRegNum(Loc.Reg, TRI);
+
// If this is a register location, put the subregister byte offset in
// the location offset.
if (Loc.LocType == Location::Register) {
assert(!Loc.Offset && "Register location should have zero offset");
- unsigned LLVMRegNo = MCRI.getLLVMRegNum(RegNo, false);
- unsigned SubRegIdx = MCRI.getSubRegIndex(LLVMRegNo, Loc.Reg);
+ unsigned LLVMRegNo = TRI->getLLVMRegNum(RegNo, false);
+ unsigned SubRegIdx = TRI->getSubRegIndex(LLVMRegNo, Loc.Reg);
if (SubRegIdx)
- Offset = MCRI.getSubRegIdxOffset(SubRegIdx);
+ Offset = TRI->getSubRegIdxOffset(SubRegIdx);
}
}
else {
dbgs() << "<Unprocessed operand>";
break;
case Location::Register:
- dbgs() << "Register " << MCRI.getName(Loc.Reg);
+ dbgs() << "Register " << TRI->getName(Loc.Reg);
break;
case Location::Direct:
- dbgs() << "Direct " << MCRI.getName(Loc.Reg);
+ dbgs() << "Direct " << TRI->getName(Loc.Reg);
if (Loc.Offset)
dbgs() << " + " << Loc.Offset;
break;
case Location::Indirect:
- dbgs() << "Indirect " << MCRI.getName(Loc.Reg)
+ dbgs() << "Indirect " << TRI->getName(Loc.Reg)
<< " + " << Loc.Offset;
break;
case Location::Constant:
for (LiveOutVec::const_iterator LI = LiveOuts.begin(), LE = LiveOuts.end();
LI != LE; ++LI, ++operIdx) {
DEBUG(dbgs() << WSMP << " LO " << operIdx << ": "
- << MCRI.getName(LI->Reg)
+ << TRI->getName(LI->Reg)
<< " [encoding: .short " << LI->RegNo
<< ", .byte 0, .byte " << LI->Size << "]\n");