<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Oct 31, 2013, at 3:42 PM, Eric Christopher <<a href="mailto:echristo@gmail.com">echristo@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">You broke non-darwin bots. You need a triple on your testcases.</div></blockquote><div><br></div><div>I was wondering how these would fail no non-darwin. Forgot to check the label names. Anyway, for now I’ll use the triple since it’s experimental for darwin-only.</div><div><br></div><div>-Andy</div><br><blockquote type="cite"><div class="gmail_extra"><div class="gmail_quote">On Thu, Oct 31, 2013 at 3:11 PM, Andrew Trick <span dir="ltr"><<a href="mailto:atrick@apple.com" target="_blank">atrick@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: atrick<br>
Date: Thu Oct 31 17:11:56 2013<br>
New Revision: 193811<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=193811&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=193811&view=rev</a><br>
Log:<br>
Add support for stack map generation in the X86 backend.<br>
<br>
Originally implemented by Lang Hames.<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/CodeGen/StackMaps.h<br>
    llvm/trunk/lib/CodeGen/StackMaps.cpp<br>
    llvm/trunk/test/CodeGen/X86/patchpoint.ll<br>
    llvm/trunk/test/CodeGen/X86/stackmap.ll<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/CMakeLists.txt<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
    llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp<br>
    llvm/trunk/lib/Target/X86/X86AsmPrinter.h<br>
    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
    llvm/trunk/lib/Target/X86/X86MCInstLower.cpp<br>
<br>
Added: llvm/trunk/include/llvm/CodeGen/StackMaps.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMaps.h?rev=193811&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/StackMaps.h?rev=193811&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/StackMaps.h (added)<br>
+++ llvm/trunk/include/llvm/CodeGen/StackMaps.h Thu Oct 31 17:11:56 2013<br>
@@ -0,0 +1,107 @@<br>
+//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_STACKMAPS<br>
+#define LLVM_STACKMAPS<br>
+<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/CodeGen/MachineInstr.h"<br>
+#include <map><br>
+#include <vector><br>
+<br>
+namespace llvm {<br>
+<br>
+class AsmPrinter;<br>
+class MCExpr;<br>
+<br>
+class StackMaps {<br>
+public:<br>
+  struct Location {<br>
+    enum LocationType { Unprocessed, Register, Direct, Indirect, Constant,<br>
+                        ConstantIndex };<br>
+    LocationType LocType;<br>
+    unsigned Reg;<br>
+    int64_t Offset;<br>
+    Location() : LocType(Unprocessed), Reg(0), Offset(0) {}<br>
+    Location(LocationType LocType, unsigned Reg, int64_t Offset)<br>
+      : LocType(LocType), Reg(Reg), Offset(Offset) {}<br>
+  };<br>
+<br>
+  // Typedef a function pointer for functions that parse sequences of operands<br>
+  // and return a Location, plus a new "next" operand iterator.<br>
+  typedef std::pair<Location, MachineInstr::const_mop_iterator><br>
+    (*OperandParser)(MachineInstr::const_mop_iterator,<br>
+                     MachineInstr::const_mop_iterator);<br>
+<br>
+  // OpTypes are used to encode information about the following logical<br>
+  // operand (which may consist of several MachineOperands) for the<br>
+  // OpParser.<br>
+  typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType;<br>
+<br>
+  StackMaps(AsmPrinter &AP, OperandParser OpParser)<br>
+    : AP(AP), OpParser(OpParser) {}<br>
+<br>
+  /// This should be called by the MC lowering code _immediately_ before<br>
+  /// lowering the MI to an MCInst. It records where the operands for the<br>
+  /// instruction are stored, and outputs a label to record the offset of<br>
+  /// the call from the start of the text section.<br>
+  void recordStackMap(const MachineInstr &MI, uint32_t ID,<br>
+                      MachineInstr::const_mop_iterator MOI,<br>
+                      MachineInstr::const_mop_iterator MOE);<br>
+<br>
+  /// If there is any stack map data, create a stack map section and serialize<br>
+  /// the map info into it. This clears the stack map data structures<br>
+  /// afterwards.<br>
+  void serializeToStackMapSection();<br>
+<br>
+private:<br>
+<br>
+  typedef SmallVector<Location, 8> LocationVec;<br>
+<br>
+  struct CallsiteInfo {<br>
+    const MCExpr *CSOffsetExpr;<br>
+    unsigned ID;<br>
+    LocationVec Locations;<br>
+    CallsiteInfo() : CSOffsetExpr(0), ID(0) {}<br>
+    CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID,<br>
+                 LocationVec Locations)<br>
+      : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {}<br>
+  };<br>
+<br>
+  typedef std::vector<CallsiteInfo> CallsiteInfoList;<br>
+<br>
+  struct ConstantPool {<br>
+  private:<br>
+    typedef std::map<int64_t, size_t> ConstantsMap;<br>
+    std::vector<int64_t> ConstantsList;<br>
+    ConstantsMap ConstantIndexes;<br>
+<br>
+  public:<br>
+    size_t getNumConstants() const { return ConstantsList.size(); }<br>
+    int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; }<br>
+    size_t getConstantIndex(int64_t ConstVal) {<br>
+      size_t NextIdx = ConstantsList.size();<br>
+      ConstantsMap::const_iterator I =<br>
+        ConstantIndexes.insert(ConstantIndexes.end(),<br>
+                               std::make_pair(ConstVal, NextIdx));<br>
+      if (I->second == NextIdx)<br>
+        ConstantsList.push_back(ConstVal);<br>
+      return I->second;<br>
+    }<br>
+  };<br>
+<br>
+  AsmPrinter &AP;<br>
+  OperandParser OpParser;<br>
+  CallsiteInfoList CSInfos;<br>
+  ConstantPool ConstPool;<br>
+};<br>
+<br>
+}<br>
+<br>
+#endif // LLVM_STACKMAPS<br>
<br>
Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=193811&r1=193810&r2=193811&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=193811&r1=193810&r2=193811&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Thu Oct 31 17:11:56 2013<br>
@@ -97,6 +97,7 @@ add_llvm_library(LLVMCodeGen<br>
   StackColoring.cpp<br>
   StackProtector.cpp<br>
   StackSlotColoring.cpp<br>
+  StackMaps.cpp<br>
   TailDuplication.cpp<br>
   TargetFrameLoweringImpl.cpp<br>
   TargetInstrInfo.cpp<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=193811&r1=193810&r2=193811&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=193811&r1=193810&r2=193811&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Thu Oct 31 17:11:56 2013<br>
@@ -33,6 +33,7 @@<br>
 #include "llvm/CodeGen/MachineModuleInfo.h"<br>
 #include "llvm/CodeGen/MachineRegisterInfo.h"<br>
 #include "llvm/CodeGen/SelectionDAG.h"<br>
+#include "llvm/CodeGen/StackMaps.h"<br>
 #include "llvm/DebugInfo.h"<br>
 #include "llvm/IR/CallingConv.h"<br>
 #include "llvm/IR/Constants.h"<br>
@@ -6879,6 +6880,8 @@ void SelectionDAGBuilder::visitPatchpoin<br>
     SDValue OpVal = getValue(CI.getArgOperand(i));<br>
     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(OpVal)) {<br>
       Ops.push_back(<br>
+        DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64));<br>
+      Ops.push_back(<br>
         DAG.getTargetConstant(C->getSExtValue(), MVT::i64));<br>
     } else<br>
       Ops.push_back(OpVal);<br>
<br>
Added: llvm/trunk/lib/CodeGen/StackMaps.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMaps.cpp?rev=193811&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackMaps.cpp?rev=193811&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/StackMaps.cpp (added)<br>
+++ llvm/trunk/lib/CodeGen/StackMaps.cpp Thu Oct 31 17:11:56 2013<br>
@@ -0,0 +1,213 @@<br>
+//===---------------------------- StackMaps.cpp ---------------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#define DEBUG_TYPE "stackmaps"<br>
+<br>
+#include "llvm/CodeGen/StackMaps.h"<br>
+<br>
+#include "llvm/CodeGen/AsmPrinter.h"<br>
+#include "llvm/CodeGen/MachineInstr.h"<br>
+#include "llvm/MC/MCContext.h"<br>
+#include "llvm/MC/MCExpr.h"<br>
+#include "llvm/MC/MCSectionMachO.h"<br>
+#include "llvm/MC/MCStreamer.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include "llvm/Target/TargetOpcodes.h"<br>
+#include "llvm/Target/TargetMachine.h"<br>
+#include "llvm/Target/TargetRegisterInfo.h"<br>
+<br>
+#include <iterator><br>
+<br>
+using namespace llvm;<br>
+<br>
+void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID,<br>
+                               MachineInstr::const_mop_iterator MOI,<br>
+                               MachineInstr::const_mop_iterator MOE) {<br>
+<br>
+  MCContext &OutContext = AP.OutStreamer.getContext();<br>
+  MCSymbol *MILabel = OutContext.CreateTempSymbol();<br>
+  AP.OutStreamer.EmitLabel(MILabel);<br>
+<br>
+  LocationVec CallsiteLocs;<br>
+<br>
+  while (MOI != MOE) {<br>
+    std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =<br>
+      OpParser(MOI, MOE);<br>
+<br>
+    Location &Loc = ParseResult.first;<br>
+<br>
+    // Move large constants into the constant pool.<br>
+    if (Loc.LocType == Location::Constant && (Loc.Offset & ~0xFFFFFFFFULL)) {<br>
+      Loc.LocType = Location::ConstantIndex;<br>
+      Loc.Offset = ConstPool.getConstantIndex(Loc.Offset);<br>
+    }<br>
+<br>
+    CallsiteLocs.push_back(Loc);<br>
+    MOI = ParseResult.second;<br>
+  }<br>
+<br>
+  const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(<br>
+    MCSymbolRefExpr::Create(MILabel, OutContext),<br>
+    MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),<br>
+    OutContext);<br>
+<br>
+  CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, CallsiteLocs));<br>
+}<br>
+<br>
+/// serializeToStackMapSection conceptually populates the following fields:<br>
+///<br>
+/// uint32 : Reserved (header)<br>
+/// uint32 : NumConstants<br>
+/// int64  : Constants[NumConstants]<br>
+/// uint32 : NumRecords<br>
+/// StkMapRecord[NumRecords] {<br>
+///   uint32 : PatchPoint ID<br>
+///   uint32 : Instruction Offset<br>
+///   uint16 : Reserved (record flags)<br>
+///   uint16 : NumLocations<br>
+///   Location[NumLocations] {<br>
+///     uint8  : Register | Direct | Indirect | Constant | ConstantIndex<br>
+///     uint8  : Reserved (location flags)<br>
+///     uint16 : Dwarf RegNum<br>
+///     int32  : Offset<br>
+///   }<br>
+/// }<br>
+///<br>
+/// Location Encoding, Type, Value:<br>
+///   0x1, Register, Reg                 (value in register)<br>
+///   0x2, Direct, Reg + Offset          (frame index)<br>
+///   0x3, Indirect, [Reg + Offset]      (spilled value)<br>
+///   0x4, Constant, Offset              (small constant)<br>
+///   0x5, ConstIndex, Constants[Offset] (large constant)<br>
+///<br>
+void StackMaps::serializeToStackMapSection() {<br>
+  // Bail out if there's no stack map data.<br>
+  if (CSInfos.empty())<br>
+    return;<br>
+<br>
+  MCContext &OutContext = AP.OutStreamer.getContext();<br>
+  const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();<br>
+<br>
+  // Create the section.<br>
+  const MCSection *StackMapSection =<br>
+    OutContext.getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps", 0,<br>
+                               SectionKind::getMetadata());<br>
+  AP.OutStreamer.SwitchSection(StackMapSection);<br>
+<br>
+  // Emit a dummy symbol to force section inclusion.<br>
+  AP.OutStreamer.EmitLabel(<br>
+    OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));<br>
+<br>
+  // Serialize data.<br>
+  const char *WSMP = "Stack Maps: ";<br>
+  const MCRegisterInfo &MCRI = *OutContext.getRegisterInfo();<br>
+<br>
+  DEBUG(dbgs() << "********** Stack Map Output **********\n");<br>
+<br>
+  // Header.<br>
+  AP.OutStreamer.EmitIntValue(0, 4);<br>
+<br>
+  // Num constants.<br>
+  AP.OutStreamer.EmitIntValue(ConstPool.getNumConstants(), 4);<br>
+<br>
+  // Constant pool entries.<br>
+  for (unsigned i = 0; i < ConstPool.getNumConstants(); ++i)<br>
+    AP.OutStreamer.EmitIntValue(ConstPool.getConstant(i), 8);<br>
+<br>
+  DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << "\n");<br>
+  AP.OutStreamer.EmitIntValue(CSInfos.size(), 4);<br>
+<br>
+  for (CallsiteInfoList::const_iterator CSII = CSInfos.begin(),<br>
+                                        CSIE = CSInfos.end();<br>
+       CSII != CSIE; ++CSII) {<br>
+<br>
+    unsigned CallsiteID = CSII->ID;<br>
+    const LocationVec &CSLocs = CSII->Locations;<br>
+<br>
+    DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n");<br>
+<br>
+    // Verify stack map entry. It's better to communicate a problem to the<br>
+    // runtime than crash in case of in-process compilation. Currently, we do<br>
+    // simple overflow checks, but we may eventually communicate other<br>
+    // compilation errors this way.<br>
+    if (CSLocs.size() > UINT16_MAX) {<br>
+      AP.OutStreamer.EmitIntValue(UINT32_MAX, 4); // Invalid ID.<br>
+      AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);<br>
+      AP.OutStreamer.EmitIntValue(0, 2); // Reserved.<br>
+      AP.OutStreamer.EmitIntValue(0, 2); // 0 locations.<br>
+      continue;<br>
+    }<br>
+<br>
+    AP.OutStreamer.EmitIntValue(CallsiteID, 4);<br>
+    AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4);<br>
+<br>
+    // Reserved for flags.<br>
+    AP.OutStreamer.EmitIntValue(0, 2);<br>
+<br>
+    DEBUG(dbgs() << WSMP << "  has " << CSLocs.size() << " locations\n");<br>
+<br>
+    AP.OutStreamer.EmitIntValue(CSLocs.size(), 2);<br>
+<br>
+    unsigned operIdx = 0;<br>
+    for (LocationVec::const_iterator LocI = CSLocs.begin(), LocE = CSLocs.end();<br>
+         LocI != LocE; ++LocI, ++operIdx) {<br>
+      const Location &Loc = *LocI;<br>
+      DEBUG(<br>
+        dbgs() << WSMP << "  Loc " << operIdx << ": ";<br>
+        switch (Loc.LocType) {<br>
+        case Location::Unprocessed:<br>
+          dbgs() << "<Unprocessed operand>";<br>
+          break;<br>
+        case Location::Register:<br>
+          dbgs() << "Register " << MCRI.getName(Loc.Reg);<br>
+          break;<br>
+        case Location::Direct:<br>
+          dbgs() << "Direct " << MCRI.getName(Loc.Reg);<br>
+          if (Loc.Offset)<br>
+            dbgs() << " + " << Loc.Offset;<br>
+          break;<br>
+        case Location::Indirect:<br>
+          dbgs() << "Indirect " << MCRI.getName(Loc.Reg)<br>
+                 << " + " << Loc.Offset;<br>
+          break;<br>
+        case Location::Constant:<br>
+          dbgs() << "Constant " << Loc.Offset;<br>
+          break;<br>
+        case Location::ConstantIndex:<br>
+          dbgs() << "Constant Index " << Loc.Offset;<br>
+          break;<br>
+        }<br>
+        dbgs() << "\n";<br>
+      );<br>
+<br>
+      unsigned RegNo = 0;<br>
+      if(Loc.Reg) {<br>
+        RegNo = MCRI.getDwarfRegNum(Loc.Reg, false);<br>
+        for (MCSuperRegIterator SR(Loc.Reg, TRI);<br>
+             SR.isValid() && (int)RegNo < 0; ++SR) {<br>
+          RegNo = TRI->getDwarfRegNum(*SR, false);<br>
+        }<br>
+      }<br>
+      else {<br>
+        assert((Loc.LocType != Location::Register<br>
+                && Loc.LocType != Location::Register) &&<br>
+               "Missing location register");<br>
+      }<br>
+      AP.OutStreamer.EmitIntValue(Loc.LocType, 1);<br>
+      AP.OutStreamer.EmitIntValue(0, 1); // Reserved location flags.<br>
+      AP.OutStreamer.EmitIntValue(RegNo, 2);<br>
+      AP.OutStreamer.EmitIntValue(Loc.Offset, 4);<br>
+    }<br>
+  }<br>
+<br>
+  AP.OutStreamer.AddBlankLine();<br>
+<br>
+  CSInfos.clear();<br>
+}<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp?rev=193811&r1=193810&r2=193811&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp?rev=193811&r1=193810&r2=193811&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp Thu Oct 31 17:11:56 2013<br>
@@ -626,6 +626,8 @@ void X86AsmPrinter::EmitEndOfAsmFile(Mod<br>
       OutStreamer.AddBlankLine();<br>
     }<br>
<br>
+    SM.serializeToStackMapSection();<br>
+<br>
     // Funny Darwin hack: This flag tells the linker that no global symbols<br>
     // contain code that falls through to other global symbols (e.g. the obvious<br>
     // implementation of multiple entry points).  If this doesn't occur, the<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86AsmPrinter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.h?rev=193811&r1=193810&r2=193811&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86AsmPrinter.h?rev=193811&r1=193810&r2=193811&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86AsmPrinter.h (original)<br>
+++ llvm/trunk/lib/Target/X86/X86AsmPrinter.h Thu Oct 31 17:11:56 2013<br>
@@ -16,6 +16,7 @@<br>
 #include "llvm/CodeGen/AsmPrinter.h"<br>
 #include "llvm/CodeGen/MachineModuleInfo.h"<br>
 #include "llvm/CodeGen/ValueTypes.h"<br>
+#include "llvm/CodeGen/StackMaps.h"<br>
 #include "llvm/Support/Compiler.h"<br>
<br>
 namespace llvm {<br>
@@ -24,9 +25,20 @@ class MCStreamer;<br>
<br>
 class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {<br>
   const X86Subtarget *Subtarget;<br>
+  StackMaps SM;<br>
+<br>
+  // Parses operands of PATCHPOINT and STACKMAP to produce stack map Location<br>
+  // structures. Returns a result location and an iterator to the operand<br>
+  // immediately following the operands consumed.<br>
+  //<br>
+  // This method is implemented in X86MCInstLower.cpp.<br>
+  static std::pair<StackMaps::Location, MachineInstr::const_mop_iterator><br>
+    stackmapOperandParser(MachineInstr::const_mop_iterator MOI,<br>
+                          MachineInstr::const_mop_iterator MOE);<br>
+<br>
  public:<br>
   explicit X86AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)<br>
-    : AsmPrinter(TM, Streamer) {<br>
+    : AsmPrinter(TM, Streamer), SM(*this, stackmapOperandParser) {<br>
     Subtarget = &TM.getSubtarget<X86Subtarget>();<br>
   }<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=193811&r1=193810&r2=193811&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=193811&r1=193810&r2=193811&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Thu Oct 31 17:11:56 2013<br>
@@ -24,6 +24,7 @@<br>
 #include "llvm/CodeGen/MachineFrameInfo.h"<br>
 #include "llvm/CodeGen/MachineInstrBuilder.h"<br>
 #include "llvm/CodeGen/MachineRegisterInfo.h"<br>
+#include "llvm/CodeGen/StackMaps.h"<br>
 #include "llvm/IR/DerivedTypes.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
 #include "llvm/MC/MCAsmInfo.h"<br>
@@ -4192,10 +4193,44 @@ breakPartialRegDependency(MachineBasicBl<br>
   MI->addRegisterKilled(Reg, TRI, true);<br>
 }<br>
<br>
-MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,<br>
-                                                  MachineInstr *MI,<br>
-                                           const SmallVectorImpl<unsigned> &Ops,<br>
-                                                  int FrameIndex) const {<br>
+static MachineInstr* foldPatchpoint(MachineFunction &MF,<br>
+                                    MachineInstr *MI,<br>
+                                    const SmallVectorImpl<unsigned> &Ops,<br>
+                                    int FrameIndex,<br>
+                                    const TargetInstrInfo &TII) {<br>
+  MachineInstr *NewMI =<br>
+    MF.CreateMachineInstr(TII.get(MI->getOpcode()), MI->getDebugLoc(), true);<br>
+  MachineInstrBuilder MIB(MF, NewMI);<br>
+<br>
+  bool isPatchPoint = MI->getOpcode() == TargetOpcode::PATCHPOINT;<br>
+  unsigned StartIdx = isPatchPoint ? MI->getOperand(3).getImm() + 4 : 2;<br>
+<br>
+  // No need to fold the meta data and function arguments<br>
+  for (unsigned i = 0; i < StartIdx; ++i)<br>
+    MIB.addOperand(MI->getOperand(i));<br>
+<br>
+  for (unsigned i = StartIdx; i < MI->getNumOperands(); ++i) {<br>
+    MachineOperand &MO = MI->getOperand(i);<br>
+    if (std::find(Ops.begin(), Ops.end(), i) != Ops.end()) {<br>
+      MIB.addOperand(MachineOperand::CreateImm(StackMaps::IndirectMemRefOp));<br>
+      MIB.addOperand(MachineOperand::CreateFI(FrameIndex));<br>
+      addOffset(MIB, 0);<br>
+    }<br>
+    else<br>
+      MIB.addOperand(MO);<br>
+  }<br>
+  return NewMI;<br>
+}<br>
+<br>
+MachineInstr*<br>
+X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,<br>
+                                    const SmallVectorImpl<unsigned> &Ops,<br>
+                                    int FrameIndex) const {<br>
+  // Special case stack map and patch point intrinsics.<br>
+  if (MI->getOpcode() == TargetOpcode::STACKMAP<br>
+      || MI->getOpcode() == TargetOpcode::PATCHPOINT) {<br>
+    return foldPatchpoint(MF, MI, Ops, FrameIndex, *this);<br>
+  }<br>
   // Check switch flag<br>
   if (NoFusing) return NULL;<br>
<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86MCInstLower.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=193811&r1=193810&r2=193811&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCInstLower.cpp?rev=193811&r1=193810&r2=193811&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86MCInstLower.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86MCInstLower.cpp Thu Oct 31 17:11:56 2013<br>
@@ -17,6 +17,7 @@<br>
 #include "X86COFFMachineModuleInfo.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/CodeGen/MachineModuleInfoImpls.h"<br>
+#include "llvm/CodeGen/StackMaps.h"<br>
 #include "llvm/IR/Type.h"<br>
 #include "llvm/MC/MCAsmInfo.h"<br>
 #include "llvm/MC/MCContext.h"<br>
@@ -686,6 +687,123 @@ static void LowerTlsAddr(MCStreamer &Out<br>
     .addExpr(tlsRef));<br>
 }<br>
<br>
+static std::pair<StackMaps::Location, MachineInstr::const_mop_iterator><br>
+parseMemoryOperand(StackMaps::Location::LocationType LocTy,<br>
+                   MachineInstr::const_mop_iterator MOI,<br>
+                   MachineInstr::const_mop_iterator MOE) {<br>
+<br>
+  typedef StackMaps::Location Location;<br>
+<br>
+  assert(std::distance(MOI, MOE) >= 5 && "Too few operands to encode mem op.");<br>
+<br>
+  const MachineOperand &Base = *MOI;<br>
+  const MachineOperand &Scale = *(++MOI);<br>
+  const MachineOperand &Index = *(++MOI);<br>
+  const MachineOperand &Disp = *(++MOI);<br>
+  const MachineOperand &ZeroReg = *(++MOI);<br>
+<br>
+  // Sanity check for supported operand format.<br>
+  assert(Base.isReg() &&<br>
+         Scale.isImm() && Scale.getImm() == 1 &&<br>
+         Index.isReg() && Index.getReg() == 0 &&<br>
+         Disp.isImm() && ZeroReg.isReg() && (ZeroReg.getReg() == 0) &&<br>
+         "Unsupported x86 memory operand sequence.");<br>
+<br>
+  return std::make_pair(<br>
+           Location(LocTy, Base.getReg(), Disp.getImm()), ++MOI);<br>
+}<br>
+<br>
+std::pair<StackMaps::Location, MachineInstr::const_mop_iterator><br>
+X86AsmPrinter::stackmapOperandParser(MachineInstr::const_mop_iterator MOI,<br>
+                                     MachineInstr::const_mop_iterator MOE) {<br>
+<br>
+  typedef StackMaps::Location Location;<br>
+<br>
+  const MachineOperand &MOP = *MOI;<br>
+  assert(!MOP.isRegMask() && (!MOP.isReg() || !MOP.isImplicit()) &&<br>
+         "Register mask and implicit operands should not be processed.");<br>
+<br>
+  if (MOP.isImm()) {<br>
+    switch (MOP.getImm()) {<br>
+    default: llvm_unreachable("Unrecognized operand type.");<br>
+    case StackMaps::DirectMemRefOp:<br>
+      return parseMemoryOperand(StackMaps::Location::Direct,<br>
+                                llvm::next(MOI), MOE);<br>
+    case StackMaps::IndirectMemRefOp:<br>
+      return parseMemoryOperand(StackMaps::Location::Indirect,<br>
+                                llvm::next(MOI), MOE);<br>
+    case StackMaps::ConstantOp: {<br>
+      ++MOI;<br>
+      assert(MOI->isImm() && "Expected constant operand.");<br>
+      int64_t Imm = MOI->getImm();<br>
+      return std::make_pair(Location(Location::Constant, 0, Imm), ++MOI);<br>
+    }<br>
+    }<br>
+  }<br>
+<br>
+  // Otherwise this is a reg operand.<br>
+  assert(MOP.isReg() && "Expected register operand here.");<br>
+  assert(TargetRegisterInfo::isPhysicalRegister(MOP.getReg()) &&<br>
+         "Virtreg operands should have been rewritten before now.");<br>
+  return std::make_pair(Location(Location::Register, MOP.getReg(), 0), ++MOI);<br>
+}<br>
+<br>
+static MachineInstr::const_mop_iterator<br>
+getStackMapEndMOP(MachineInstr::const_mop_iterator MOI,<br>
+                  MachineInstr::const_mop_iterator MOE) {<br>
+  for (; MOI != MOE; ++MOI)<br>
+    if (MOI->isRegMask() || (MOI->isReg() && MOI->isImplicit()))<br>
+      break;<br>
+<br>
+  return MOI;<br>
+}<br>
+<br>
+static void LowerSTACKMAP(MCStreamer &OutStreamer,<br>
+                          X86MCInstLower &MCInstLowering,<br>
+                          StackMaps &SM,<br>
+                          const MachineInstr &MI)<br>
+{<br>
+  int64_t ID = MI.getOperand(0).getImm();<br>
+  unsigned NumNOPBytes = MI.getOperand(1).getImm();<br>
+<br>
+  assert((int32_t)ID == ID && "Stack maps hold 32-bit IDs");<br>
+  SM.recordStackMap(MI, ID, llvm::next(MI.operands_begin(), 2),<br>
+                    getStackMapEndMOP(MI.operands_begin(), MI.operands_end()));<br>
+  // Emit padding.<br>
+  for (unsigned i = 0; i < NumNOPBytes; ++i)<br>
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::NOOP));<br>
+}<br>
+<br>
+static void LowerPATCHPOINT(MCStreamer &OutStreamer,<br>
+                            X86MCInstLower &MCInstLowering,<br>
+                            StackMaps &SM,<br>
+                            const MachineInstr &MI)<br>
+{<br>
+  int64_t ID = MI.getOperand(0).getImm();<br>
+  assert((int32_t)ID == ID && "Stack maps hold 32-bit IDs");<br>
+<br>
+  // Get the number of arguments participating in the call. This number was<br>
+  // adjusted during call lowering by subtracting stack args.<br>
+  int64_t StackMapIdx = MI.getOperand(3).getImm() + 4;<br>
+  assert(StackMapIdx <= MI.getNumOperands() && "Patchpoint dropped args.");<br>
+<br>
+  SM.recordStackMap(MI, ID, llvm::next(MI.operands_begin(), StackMapIdx),<br>
+                     getStackMapEndMOP(MI.operands_begin(), MI.operands_end()));<br>
+<br>
+  // Emit call. We need to know how many bytes we encoded here.<br>
+  unsigned EncodedBytes = 2;<br>
+  OutStreamer.EmitInstruction(MCInstBuilder(X86::CALL64r)<br>
+                              .addReg(MI.getOperand(2).getReg()));<br>
+<br>
+  // Emit padding.<br>
+  unsigned NumNOPBytes = MI.getOperand(1).getImm();<br>
+  assert(NumNOPBytes >= EncodedBytes &&<br>
+         "Patchpoint can't request size less than the length of a call.");<br>
+<br>
+  for (unsigned i = EncodedBytes; i < NumNOPBytes; ++i)<br>
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::NOOP));<br>
+}<br>
+<br>
 void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {<br>
   X86MCInstLower MCInstLowering(*MF, *this);<br>
   switch (MI->getOpcode()) {<br>
@@ -775,6 +893,12 @@ void X86AsmPrinter::EmitInstruction(cons<br>
       .addExpr(DotExpr));<br>
     return;<br>
   }<br>
+<br>
+  case TargetOpcode::STACKMAP:<br>
+    return LowerSTACKMAP(OutStreamer, MCInstLowering, SM, *MI);<br>
+<br>
+  case TargetOpcode::PATCHPOINT:<br>
+    return LowerPATCHPOINT(OutStreamer, MCInstLowering, SM, *MI);<br>
   }<br>
<br>
   MCInst TmpInst;<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/patchpoint.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/patchpoint.ll?rev=193811&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/patchpoint.ll?rev=193811&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/patchpoint.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/patchpoint.ll Thu Oct 31 17:11:56 2013<br>
@@ -0,0 +1,48 @@<br>
+; RUN: llc < %s -march=x86-64 | FileCheck %s<br>
+<br>
+; Trivial patchpoint codegen<br>
+;<br>
+; FIXME: We should verify that the call target is materialize after<br>
+; the label immediately before the call.<br>
+; <<a href="rdar://15187295">rdar://15187295</a>> [JS] llvm.webkit.patchpoint call target should be<br>
+; materialized in nop slide.<br>
+define i64 @trivial_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {<br>
+entry:<br>
+; CHECK-LABEL: _trivial_patchpoint_codegen:<br>
+; CHECK:      Ltmp<br>
+; CHECK:      callq *%rax<br>
+; CHECK-NEXT: nop<br>
+; CHECK:      movq %rax, %[[REG:r.+]]<br>
+; CHECK:      callq *%rax<br>
+; CHECK-NEXT: nop<br>
+; CHECK:      movq %[[REG]], %rax<br>
+; CHECK:      ret<br>
+  %resolveCall2 = inttoptr i64 -559038736 to i8*<br>
+  %result = tail call i64 (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i32 2, i32 12, i8* %resolveCall2, i32 4, i64 %p1, i64 %p2, i64 %p3, i64 %p4)<br>
+  %resolveCall3 = inttoptr i64 -559038737 to i8*<br>
+  tail call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 3, i32 12, i8* %resolveCall3, i32 2, i64 %p1, i64 %result)<br>
+  ret i64 %result<br>
+}<br>
+<br>
+; Caller frame metadata with stackmaps. This should not be optimized<br>
+; as a leaf function.<br>
+;<br>
+; CHECK-LABEL: _caller_meta_leaf<br>
+; CHECK: subq $24, %rsp<br>
+; CHECK: Ltmp<br>
+; CHECK: addq $24, %rsp<br>
+; CHECK: ret<br>
+define void @caller_meta_leaf() {<br>
+entry:<br>
+  %metadata = alloca i64, i32 3, align 8<br>
+  store i64 11, i64* %metadata<br>
+  store i64 12, i64* %metadata<br>
+  store i64 13, i64* %metadata<br>
+  call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 4, i32 0, i64* %metadata)<br>
+  ret void<br>
+}<br>
+<br>
+<br>
+declare void @llvm.experimental.stackmap(i32, i32, ...)<br>
+declare void @llvm.experimental.patchpoint.void(i32, i32, i8*, i32, ...)<br>
+declare i64 @llvm.experimental.patchpoint.i64(i32, i32, i8*, i32, ...)<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/stackmap.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap.ll?rev=193811&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stackmap.ll?rev=193811&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/stackmap.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/stackmap.ll Thu Oct 31 17:11:56 2013<br>
@@ -0,0 +1,205 @@<br>
+; RUN: llc < %s -march=x86-64 | FileCheck %s<br>
+;<br>
+; Note: Print verbose stackmaps using -debug-only=stackmaps.<br>
+<br>
+; CHECK-LABEL:  .section  __LLVM_STACKMAPS,__llvm_stackmaps<br>
+; CHECK-NEXT:  __LLVM_StackMaps:<br>
+; CHECK-NEXT:   .long   0<br>
+; Num LargeConstants<br>
+; CHECK-NEXT:   .long   1<br>
+; CHECK-NEXT:   .quad   4294967296<br>
+; Num Callsites<br>
+; CHECK-NEXT:   .long   8<br>
+<br>
+; Constant arguments<br>
+;<br>
+; CHECK-NEXT:   .long   1<br>
+; CHECK-NEXT:   .long   L{{.*}}-_constantargs<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .short  4<br>
+; SmallConstant<br>
+; CHECK-NEXT:   .byte   4<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .long   65535<br>
+; SmallConstant<br>
+; CHECK-NEXT:   .byte   4<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .long   65536<br>
+; SmallConstant<br>
+; CHECK-NEXT:   .byte   4<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .long   4294967295<br>
+; LargeConstant at index 0<br>
+; CHECK-NEXT:   .byte   5<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .long   0<br>
+<br>
+define void @constantargs() {<br>
+entry:<br>
+  %0 = inttoptr i64 12345 to i8*<br>
+  tail call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 1, i32 2, i8* %0, i32 0, i64 65535, i64 65536, i64 4294967295, i64 4294967296)<br>
+  ret void<br>
+}<br>
+<br>
+; Inline OSR Exit<br>
+;<br>
+; CHECK-NEXT:   .long   3<br>
+; CHECK-NEXT:   .long   L{{.*}}-_osrinline<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .short  2<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long   0<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long  0<br>
+define void @osrinline(i64 %a, i64 %b) {<br>
+entry:<br>
+  ; Runtime void->void call.<br>
+  call void inttoptr (i64 -559038737 to void ()*)()<br>
+  ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars.<br>
+  call void (i32, i32, ...)* @llvm.experimental.stackmap(i32 3, i32 12, i64 %a, i64 %b)<br>
+  ret void<br>
+}<br>
+<br>
+; Cold OSR Exit<br>
+;<br>
+; 2 live variables in register.<br>
+;<br>
+; CHECK-NEXT:   .long  4<br>
+; CHECK-NEXT:   .long   L{{.*}}-_osrcold<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .short  2<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long   0<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long  0<br>
+define void @osrcold(i64 %a, i64 %b) {<br>
+entry:<br>
+  %test = icmp slt i64 %a, %b<br>
+  br i1 %test, label %ret, label %cold<br>
+cold:<br>
+  ; OSR patchpoint with 12-byte nop-slide and 2 live vars.<br>
+  %thunk = inttoptr i64 -559038737 to i8*<br>
+  call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 4, i32 12, i8* %thunk, i32 0, i64 %a, i64 %b)<br>
+  unreachable<br>
+ret:<br>
+  ret void<br>
+}<br>
+<br>
+; Property Read<br>
+; CHECK-NEXT:  .long  5<br>
+; CHECK-NEXT:   .long   L{{.*}}-_propertyRead<br>
+; CHECK-NEXT:  .short  0<br>
+; CHECK-NEXT:  .short  0<br>
+;<br>
+; FIXME: There are currently no stackmap entries. After moving to<br>
+; AnyRegCC, we will have entries for the object and return value.<br>
+define i64 @propertyRead(i64* %obj) {<br>
+entry:<br>
+  %resolveRead = inttoptr i64 -559038737 to i8*<br>
+  %result = call i64 (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i32 5, i32 12, i8* %resolveRead, i32 1, i64* %obj)<br>
+  %add = add i64 %result, 3<br>
+  ret i64 %add<br>
+}<br>
+<br>
+; Property Write<br>
+; CHECK-NEXT:  .long  6<br>
+; CHECK-NEXT:   .long   L{{.*}}-_propertyWrite<br>
+; CHECK-NEXT:  .short  0<br>
+; CHECK-NEXT:  .short  0<br>
+;<br>
+; FIXME: There are currently no stackmap entries. After moving to<br>
+; AnyRegCC, we will have entries for the object and return value.<br>
+define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) {<br>
+entry:<br>
+  %resolveWrite = inttoptr i64 -559038737 to i8*<br>
+  call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 6, i32 12, i8* %resolveWrite, i32 2, i64* %obj, i64 %a)<br>
+  ret void<br>
+}<br>
+<br>
+; Void JS Call<br>
+;<br>
+; 2 live variables in registers.<br>
+;<br>
+; CHECK-NEXT:   .long  7<br>
+; CHECK-NEXT:   .long   L{{.*}}-_jsVoidCall<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .short  2<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long   0<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long   0<br>
+define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {<br>
+entry:<br>
+  %resolveCall = inttoptr i64 -559038737 to i8*<br>
+  call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 7, i32 12, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)<br>
+  ret void<br>
+}<br>
+<br>
+; i64 JS Call<br>
+;<br>
+; 2 live variables in registers.<br>
+;<br>
+; CHECK:        .long  8<br>
+; CHECK-NEXT:   .long   L{{.*}}-_jsIntCall<br>
+; CHECK-NEXT:   .short  0<br>
+; CHECK-NEXT:   .short  2<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long   0<br>
+; CHECK-NEXT:   .byte   1<br>
+; CHECK-NEXT:   .byte   0<br>
+; CHECK-NEXT:   .short  {{[0-9]+}}<br>
+; CHECK-NEXT:   .long   0<br>
+define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {<br>
+entry:<br>
+  %resolveCall = inttoptr i64 -559038737 to i8*<br>
+  %result = call i64 (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i32 8, i32 12, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)<br>
+  %add = add i64 %result, 3<br>
+  ret i64 %add<br>
+}<br>
+<br>
+; Spilled stack map values.<br>
+;<br>
+; Verify 17 stack map entries.<br>
+;<br>
+; CHECK:      .long 11<br>
+; CHECK-NEXT: .long L{{.*}}-_spilledValue<br>
+; CHECK-NEXT: .short 0<br>
+; CHECK-NEXT: .short 10<br>
+;<br>
+; Check that at least one is a spilled entry (Indirect).<br>
+; CHECK: .byte 3<br>
+; CHECK: .byte 0<br>
+define void @spilledValue(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16) {<br>

+entry:<br>
+  %resolveCall = inttoptr i64 -559038737 to i8*<br>
+  call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 11, i32 12, i8* %resolveCall, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9)<br>

+<br>
+; FIXME: The Spiller needs to be able to fold all rematted loads! This<br>
+; can be seen by adding %l15 to the stackmap.<br>
+; <<a href="rdar:/15202984">rdar:/15202984</a>> [JS] Ran out of registers during register allocation<br>
+;  %resolveCall = inttoptr i64 -559038737 to i8*<br>
+;  call void (i32, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i32 12, i32 12, i8* %resolveCall, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16)<br>

+  ret void<br>
+}<br>
+<br>
+declare void @llvm.experimental.stackmap(i32, i32, ...)<br>
+declare void @llvm.experimental.patchpoint.void(i32, i32, i8*, i32, ...)<br>
+declare i64 @llvm.experimental.patchpoint.i64(i32, i32, i8*, i32, ...)<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</blockquote></div><br></body></html>