[llvm] r193811 - Add support for stack map generation in the X86 backend.

Andrew Trick atrick at apple.com
Tue Nov 19 10:34:10 PST 2013


On Nov 18, 2013, at 1:56 PM, Aaron Ballman <aaron at aaronballman.com> wrote:

> On Thu, Oct 31, 2013 at 6:11 PM, Andrew Trick <atrick at apple.com> wrote:
>> Author: atrick
>> Date: Thu Oct 31 17:11:56 2013
>> New Revision: 193811
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=193811&view=rev
>> Log:
>> Add support for stack map generation in the X86 backend.
>> 
>> Originally implemented by Lang Hames.
>> 
>> Added:
>>    llvm/trunk/include/llvm/CodeGen/StackMaps.h
>>    llvm/trunk/lib/CodeGen/StackMaps.cpp
>>    llvm/trunk/test/CodeGen/X86/patchpoint.ll
>>    llvm/trunk/test/CodeGen/X86/stackmap.ll
>> Modified:
>>    llvm/trunk/lib/CodeGen/CMakeLists.txt
>>    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>>    llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp
>>    llvm/trunk/lib/Target/X86/X86AsmPrinter.h
>>    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
>>    llvm/trunk/lib/Target/X86/X86MCInstLower.cpp
>> 
>> Added: llvm/trunk/include/llvm/CodeGen/StackMaps.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMaps.h?rev=193811&view=auto
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/StackMaps.h (added)
>> +++ llvm/trunk/include/llvm/CodeGen/StackMaps.h Thu Oct 31 17:11:56 2013
>> @@ -0,0 +1,107 @@
>> +//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_STACKMAPS
>> +#define LLVM_STACKMAPS
>> +
>> +#include "llvm/ADT/SmallVector.h"
>> +#include "llvm/CodeGen/MachineInstr.h"
>> +#include <map>
>> +#include <vector>
>> +
>> +namespace llvm {
>> +
>> +class AsmPrinter;
>> +class MCExpr;
>> +
>> +class StackMaps {
>> +public:
>> +  struct Location {
>> +    enum LocationType { Unprocessed, Register, Direct, Indirect, Constant,
>> +                        ConstantIndex };
>> +    LocationType LocType;
>> +    unsigned Reg;
>> +    int64_t Offset;
>> +    Location() : LocType(Unprocessed), Reg(0), Offset(0) {}
>> +    Location(LocationType LocType, unsigned Reg, int64_t Offset)
>> +      : LocType(LocType), Reg(Reg), Offset(Offset) {}
>> +  };
>> +
>> +  // Typedef a function pointer for functions that parse sequences of operands
>> +  // and return a Location, plus a new "next" operand iterator.
>> +  typedef std::pair<Location, MachineInstr::const_mop_iterator>
>> +    (*OperandParser)(MachineInstr::const_mop_iterator,
>> +                     MachineInstr::const_mop_iterator);
>> +
>> +  // OpTypes are used to encode information about the following logical
>> +  // operand (which may consist of several MachineOperands) for the
>> +  // OpParser.
>> +  typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType;
>> +
>> +  StackMaps(AsmPrinter &AP, OperandParser OpParser)
>> +    : AP(AP), OpParser(OpParser) {}
>> +
>> +  /// This should be called by the MC lowering code _immediately_ before
>> +  /// lowering the MI to an MCInst. It records where the operands for the
>> +  /// instruction are stored, and outputs a label to record the offset of
>> +  /// the call from the start of the text section.
>> +  void recordStackMap(const MachineInstr &MI, uint32_t ID,
>> +                      MachineInstr::const_mop_iterator MOI,
>> +                      MachineInstr::const_mop_iterator MOE);
>> +
>> +  /// If there is any stack map data, create a stack map section and serialize
>> +  /// the map info into it. This clears the stack map data structures
>> +  /// afterwards.
>> +  void serializeToStackMapSection();
>> +
>> +private:
>> +
>> +  typedef SmallVector<Location, 8> LocationVec;
>> +
>> +  struct CallsiteInfo {
>> +    const MCExpr *CSOffsetExpr;
>> +    unsigned ID;
>> +    LocationVec Locations;
>> +    CallsiteInfo() : CSOffsetExpr(0), ID(0) {}
>> +    CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID,
>> +                 LocationVec Locations)
>> +      : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {}
>> +  };
>> +
>> +  typedef std::vector<CallsiteInfo> CallsiteInfoList;
>> +
>> +  struct ConstantPool {
>> +  private:
>> +    typedef std::map<int64_t, size_t> ConstantsMap;
>> +    std::vector<int64_t> ConstantsList;
>> +    ConstantsMap ConstantIndexes;
>> +
>> +  public:
>> +    size_t getNumConstants() const { return ConstantsList.size(); }
>> +    int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; }
>> +    size_t getConstantIndex(int64_t ConstVal) {
>> +      size_t NextIdx = ConstantsList.size();
>> +      ConstantsMap::const_iterator I =
>> +        ConstantIndexes.insert(ConstantIndexes.end(),
>> +                               std::make_pair(ConstVal, NextIdx));
>> +      if (I->second == NextIdx)
>> +        ConstantsList.push_back(ConstVal);
>> +      return I->second;
>> +    }
>> +  };
>> +
>> +  AsmPrinter &AP;
>> +  OperandParser OpParser;
>> +  CallsiteInfoList CSInfos;
>> +  ConstantPool ConstPool;
>> +};
>> +
>> +}
>> +
>> +#endif // LLVM_STACKMAPS
>> 
>> Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=193811&r1=193810&r2=193811&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
>> +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Thu Oct 31 17:11:56 2013
>> @@ -97,6 +97,7 @@ add_llvm_library(LLVMCodeGen
>>   StackColoring.cpp
>>   StackProtector.cpp
>>   StackSlotColoring.cpp
>> +  StackMaps.cpp
>>   TailDuplication.cpp
>>   TargetFrameLoweringImpl.cpp
>>   TargetInstrInfo.cpp
>> 
>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=193811&r1=193810&r2=193811&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Thu Oct 31 17:11:56 2013
>> @@ -33,6 +33,7 @@
>> #include "llvm/CodeGen/MachineModuleInfo.h"
>> #include "llvm/CodeGen/MachineRegisterInfo.h"
>> #include "llvm/CodeGen/SelectionDAG.h"
>> +#include "llvm/CodeGen/StackMaps.h"
>> #include "llvm/DebugInfo.h"
>> #include "llvm/IR/CallingConv.h"
>> #include "llvm/IR/Constants.h"
>> @@ -6879,6 +6880,8 @@ void SelectionDAGBuilder::visitPatchpoin
>>     SDValue OpVal = getValue(CI.getArgOperand(i));
>>     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(OpVal)) {
>>       Ops.push_back(
>> +        DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64));
>> +      Ops.push_back(
>>         DAG.getTargetConstant(C->getSExtValue(), MVT::i64));
>>     } else
>>       Ops.push_back(OpVal);
>> 
>> Added: llvm/trunk/lib/CodeGen/StackMaps.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMaps.cpp?rev=193811&view=auto
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/StackMaps.cpp (added)
>> +++ llvm/trunk/lib/CodeGen/StackMaps.cpp Thu Oct 31 17:11:56 2013
>> @@ -0,0 +1,213 @@
>> +//===---------------------------- StackMaps.cpp ---------------------------===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#define DEBUG_TYPE "stackmaps"
>> +
>> +#include "llvm/CodeGen/StackMaps.h"
>> +
>> +#include "llvm/CodeGen/AsmPrinter.h"
>> +#include "llvm/CodeGen/MachineInstr.h"
>> +#include "llvm/MC/MCContext.h"
>> +#include "llvm/MC/MCExpr.h"
>> +#include "llvm/MC/MCSectionMachO.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/TargetRegisterInfo.h"
>> +
>> +#include <iterator>
>> +
>> +using namespace llvm;
>> +
>> +void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID,
>> +                               MachineInstr::const_mop_iterator MOI,
>> +                               MachineInstr::const_mop_iterator MOE) {
>> +
>> +  MCContext &OutContext = AP.OutStreamer.getContext();
>> +  MCSymbol *MILabel = OutContext.CreateTempSymbol();
>> +  AP.OutStreamer.EmitLabel(MILabel);
>> +
>> +  LocationVec CallsiteLocs;
>> +
>> +  while (MOI != MOE) {
>> +    std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
>> +      OpParser(MOI, MOE);
>> +
>> +    Location &Loc = ParseResult.first;
>> +
>> +    // Move large constants into the constant pool.
>> +    if (Loc.LocType == Location::Constant && (Loc.Offset & ~0xFFFFFFFFULL)) {
>> +      Loc.LocType = Location::ConstantIndex;
>> +      Loc.Offset = ConstPool.getConstantIndex(Loc.Offset);
>> +    }
>> +
>> +    CallsiteLocs.push_back(Loc);
>> +    MOI = ParseResult.second;
>> +  }
>> +
>> +  const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
>> +    MCSymbolRefExpr::Create(MILabel, OutContext),
>> +    MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
>> +    OutContext);
>> +
>> +  CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, CallsiteLocs));
>> +}
>> +
>> +/// serializeToStackMapSection conceptually populates the following fields:
>> +///
>> +/// uint32 : Reserved (header)
>> +/// uint32 : NumConstants
>> +/// int64  : Constants[NumConstants]
>> +/// uint32 : NumRecords
>> +/// StkMapRecord[NumRecords] {
>> +///   uint32 : PatchPoint ID
>> +///   uint32 : Instruction Offset
>> +///   uint16 : Reserved (record flags)
>> +///   uint16 : NumLocations
>> +///   Location[NumLocations] {
>> +///     uint8  : Register | Direct | Indirect | Constant | ConstantIndex
>> +///     uint8  : Reserved (location flags)
>> +///     uint16 : Dwarf RegNum
>> +///     int32  : Offset
>> +///   }
>> +/// }
>> +///
>> +/// Location Encoding, Type, Value:
>> +///   0x1, Register, Reg                 (value in register)
>> +///   0x2, Direct, Reg + Offset          (frame index)
>> +///   0x3, Indirect, [Reg + Offset]      (spilled value)
>> +///   0x4, Constant, Offset              (small constant)
>> +///   0x5, ConstIndex, Constants[Offset] (large constant)
>> +///
>> +void StackMaps::serializeToStackMapSection() {
>> +  // Bail out if there's no stack map data.
>> +  if (CSInfos.empty())
>> +    return;
>> +
>> +  MCContext &OutContext = AP.OutStreamer.getContext();
>> +  const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
>> +
>> +  // Create the section.
>> +  const MCSection *StackMapSection =
>> +    OutContext.getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps", 0,
>> +                               SectionKind::getMetadata());
>> +  AP.OutStreamer.SwitchSection(StackMapSection);
>> +
>> +  // Emit a dummy symbol to force section inclusion.
>> +  AP.OutStreamer.EmitLabel(
>> +    OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));
>> +
>> +  // Serialize data.
>> +  const char *WSMP = "Stack Maps: ";
>> +  const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();
>> +
>> +  DEBUG(dbgs() << "********** Stack Map Output **********\n");
>> +
>> +  // Header.
>> +  AP.OutStreamer.EmitIntValue(0, 4);
>> +
>> +  // Num constants.
>> +  AP.OutStreamer.EmitIntValue(ConstPool.getNumConstants(), 4);
>> +
>> +  // Constant pool entries.
>> +  for (unsigned i = 0; i < ConstPool.getNumConstants(); ++i)
>> +    AP.OutStreamer.EmitIntValue(ConstPool.getConstant(i), 8);
>> +
>> +  DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << "\n");
>> +  AP.OutStreamer.EmitIntValue(CSInfos.size(), 4);
>> +
>> +  for (CallsiteInfoList::const_iterator CSII = CSInfos.begin(),
>> +                                        CSIE = CSInfos.end();
>> +       CSII != CSIE; ++CSII) {
>> +
>> +    unsigned CallsiteID = CSII->ID;
>> +    const LocationVec &CSLocs = CSII->Locations;
>> +
>> +    DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n");
>> +
>> +    // Verify stack map entry. It's better to communicate a problem to the
>> +    // runtime than crash in case of in-process compilation. Currently, we do
>> +    // simple overflow checks, but we may eventually communicate other
>> +    // compilation errors this way.
>> +    if (CSLocs.size() > UINT16_MAX) {
>> +      AP.OutStreamer.EmitIntValue(UINT32_MAX, 4); // Invalid ID.
>> +      AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
>> +      AP.OutStreamer.EmitIntValue(0, 2); // Reserved.
>> +      AP.OutStreamer.EmitIntValue(0, 2); // 0 locations.
>> +      continue;
>> +    }
>> +
>> +    AP.OutStreamer.EmitIntValue(CallsiteID, 4);
>> +    AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);
>> +
>> +    // Reserved for flags.
>> +    AP.OutStreamer.EmitIntValue(0, 2);
>> +
>> +    DEBUG(dbgs() << WSMP << "  has " << CSLocs.size() << " locations\n");
>> +
>> +    AP.OutStreamer.EmitIntValue(CSLocs.size(), 2);
>> +
>> +    unsigned operIdx = 0;
>> +    for (LocationVec::const_iterator LocI = CSLocs.begin(), LocE = CSLocs.end();
>> +         LocI != LocE; ++LocI, ++operIdx) {
>> +      const Location &Loc = *LocI;
>> +      DEBUG(
>> +        dbgs() << WSMP << "  Loc " << operIdx << ": ";
>> +        switch (Loc.LocType) {
>> +        case Location::Unprocessed:
>> +          dbgs() << "<Unprocessed operand>";
>> +          break;
>> +        case Location::Register:
>> +          dbgs() << "Register " << MCRI.getName(Loc.Reg);
>> +          break;
>> +        case Location::Direct:
>> +          dbgs() << "Direct " << MCRI.getName(Loc.Reg);
>> +          if (Loc.Offset)
>> +            dbgs() << " + " << Loc.Offset;
>> +          break;
>> +        case Location::Indirect:
>> +          dbgs() << "Indirect " << MCRI.getName(Loc.Reg)
>> +                 << " + " << Loc.Offset;
>> +          break;
>> +        case Location::Constant:
>> +          dbgs() << "Constant " << Loc.Offset;
>> +          break;
>> +        case Location::ConstantIndex:
>> +          dbgs() << "Constant Index " << Loc.Offset;
>> +          break;
>> +        }
>> +        dbgs() << "\n";
>> +      );
>> +
>> +      unsigned RegNo = 0;
>> +      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);
>> +        }
>> +      }
>> +      else {
>> +        assert((Loc.LocType != Location::Register
>> +                && Loc.LocType != Location::Register) &&
>> +               "Missing location register");
> 
> This appears to be a typo -- LocType != Location::Register appears
> twice in the assert.
> 

Thanks for taking time to review. r195138.

-Andy

> ~Aaron




More information about the llvm-commits mailing list