.. code-block:: none
Header {
- uint8 : Stack Map Version (current version is 1)
+ uint8 : Stack Map Version (current version is 2)
uint8 : Reserved (expected to be 0)
uint16 : Reserved (expected to be 0)
}
StkSizeRecord[NumFunctions] {
uint64 : Function Address
uint64 : Stack Size
+ uint64 : Record Count
}
Constants[NumConstants] {
uint64 : LargeConstant
the code. LLVM does not maintain any mapping between those values and
any higher-level entity. The runtime must be able to interpret the
stack map record given only the ID, offset, and the order of the
-locations, which LLVM preserves.
+locations, records, and functions, which LLVM preserves.
Note that this is quite different from the goal of debug information,
which is a best-effort attempt to track the location of named
some code for each backend. Today, only a subset of LLVM's backends
are supported. The currently supported architectures are X86_64,
PowerPC, and Aarch64.
-
void reset() {
CSInfos.clear();
ConstPool.clear();
- FnStackSize.clear();
+ FnInfos.clear();
}
/// \brief Generate a stackmap record for a stackmap instruction.
typedef SmallVector<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
typedef MapVector<uint64_t, uint64_t> ConstantPool;
- typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap;
+
+ struct FunctionInfo {
+ uint64_t StackSize;
+ uint64_t RecordCount;
+ FunctionInfo() : StackSize(0), RecordCount(1) {}
+ explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize), RecordCount(1) {}
+ };
struct CallsiteInfo {
const MCExpr *CSOffsetExpr;
LiveOuts(std::move(LiveOuts)) {}
};
+ typedef MapVector<const MCSymbol *, FunctionInfo> FnInfoMap;
typedef std::vector<CallsiteInfo> CallsiteInfoList;
AsmPrinter &AP;
CallsiteInfoList CSInfos;
ConstantPool ConstPool;
- FnStackSizeMap FnStackSize;
+ FnInfoMap FnInfos;
MachineInstr::const_mop_iterator
parseOperand(MachineInstr::const_mop_iterator MOI,
namespace llvm {
template <support::endianness Endianness>
-class StackMapV1Parser {
+class StackMapV2Parser {
public:
template <typename AccessorT>
/// Accessor for function records.
class FunctionAccessor {
- friend class StackMapV1Parser;
+ friend class StackMapV2Parser;
public:
/// Get the function address.
}
/// Get the function's stack size.
- uint32_t getStackSize() const {
+ uint64_t getStackSize() const {
return read<uint64_t>(P + sizeof(uint64_t));
}
+
+ /// Get the number of callsite records.
+ uint64_t getRecordCount() const {
+ return read<uint64_t>(P + (2 * sizeof(uint64_t)));
+ }
private:
FunctionAccessor(const uint8_t *P) : P(P) {}
- const static int FunctionAccessorSize = 2 * sizeof(uint64_t);
+ const static int FunctionAccessorSize = 3 * sizeof(uint64_t);
FunctionAccessor next() const {
return FunctionAccessor(P + FunctionAccessorSize);
/// Accessor for constants.
class ConstantAccessor {
- friend class StackMapV1Parser;
+ friend class StackMapV2Parser;
public:
/// Return the value of this constant.
/// Accessor for location records.
class LocationAccessor {
- friend class StackMapV1Parser;
+ friend class StackMapV2Parser;
friend class RecordAccessor;
public:
/// Accessor for stackmap live-out fields.
class LiveOutAccessor {
- friend class StackMapV1Parser;
+ friend class StackMapV2Parser;
friend class RecordAccessor;
public:
/// Accessor for stackmap records.
class RecordAccessor {
- friend class StackMapV1Parser;
+ friend class StackMapV2Parser;
public:
typedef AccessorIterator<LocationAccessor> location_iterator;
const uint8_t *P;
};
- /// Construct a parser for a version-1 stackmap. StackMap data will be read
+ /// Construct a parser for a version-2 stackmap. StackMap data will be read
/// from the given array.
- StackMapV1Parser(ArrayRef<uint8_t> StackMapSection)
+ StackMapV2Parser(ArrayRef<uint8_t> StackMapSection)
: StackMapSection(StackMapSection) {
ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
- assert(StackMapSection[0] == 1 &&
- "StackMapV1Parser can only parse version 1 stackmaps");
+ assert(StackMapSection[0] == 2 &&
+ "StackMapV2Parser can only parse version 2 stackmaps");
unsigned CurrentRecordOffset =
ConstantsListOffset + getNumConstants() * ConstantSize;
typedef AccessorIterator<ConstantAccessor> constant_iterator;
typedef AccessorIterator<RecordAccessor> record_iterator;
- /// Get the version number of this stackmap. (Always returns 1).
- unsigned getVersion() const { return 1; }
+ /// Get the version number of this stackmap. (Always returns 2).
+ unsigned getVersion() const { return 2; }
/// Get the number of functions in the stack map.
uint32_t getNumFunctions() const {
static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
- static const unsigned FunctionSize = 2 * sizeof(uint64_t);
+ static const unsigned FunctionSize = 3 * sizeof(uint64_t);
static const unsigned ConstantSize = sizeof(uint64_t);
std::size_t getFunctionOffset(unsigned FunctionIndex) const {
#define DEBUG_TYPE "stackmaps"
static cl::opt<int> StackMapVersion(
- "stackmap-version", cl::init(1),
- cl::desc("Specify the stackmap encoding version (default = 1)"));
+ "stackmap-version", cl::init(2),
+ cl::desc("Specify the stackmap encoding version (default = 2)"));
const char *StackMaps::WSMP = "Stack Maps: ";
}
StackMaps::StackMaps(AsmPrinter &AP) : AP(AP) {
- if (StackMapVersion != 1)
+ if (StackMapVersion != 2)
llvm_unreachable("Unsupported stackmap version!");
}
CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
std::move(LiveOuts));
- // Record the stack size of the current function.
+ // Record the stack size of the current function and update callsite count.
const MachineFrameInfo &MFI = AP.MF->getFrameInfo();
const TargetRegisterInfo *RegInfo = AP.MF->getSubtarget().getRegisterInfo();
bool HasDynamicFrameSize =
MFI.hasVarSizedObjects() || RegInfo->needsStackRealignment(*(AP.MF));
- FnStackSize[AP.CurrentFnSym] =
- HasDynamicFrameSize ? UINT64_MAX : MFI.getStackSize();
+ uint64_t FrameSize = HasDynamicFrameSize ? UINT64_MAX : MFI.getStackSize();
+
+ auto CurrentIt = FnInfos.find(AP.CurrentFnSym);
+ if (CurrentIt != FnInfos.end())
+ CurrentIt->second.RecordCount++;
+ else
+ FnInfos.insert(std::make_pair(AP.CurrentFnSym, FunctionInfo(FrameSize)));
}
void StackMaps::recordStackMap(const MachineInstr &MI) {
/// Emit the stackmap header.
///
/// Header {
-/// uint8 : Stack Map Version (currently 1)
+/// uint8 : Stack Map Version (currently 2)
/// uint8 : Reserved (expected to be 0)
/// uint16 : Reserved (expected to be 0)
/// }
OS.EmitIntValue(0, 2); // Reserved.
// Num functions.
- DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
- OS.EmitIntValue(FnStackSize.size(), 4);
+ DEBUG(dbgs() << WSMP << "#functions = " << FnInfos.size() << '\n');
+ OS.EmitIntValue(FnInfos.size(), 4);
// Num constants.
DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
OS.EmitIntValue(ConstPool.size(), 4);
/// StkSizeRecord[NumFunctions] {
/// uint64 : Function Address
/// uint64 : Stack Size
+/// uint64 : Record Count
/// }
void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
// Function Frame records.
DEBUG(dbgs() << WSMP << "functions:\n");
- for (auto const &FR : FnStackSize) {
+ for (auto const &FR : FnInfos) {
DEBUG(dbgs() << WSMP << "function addr: " << FR.first
- << " frame size: " << FR.second);
+ << " frame size: " << FR.second.StackSize
+ << " callsite count: " << FR.second.RecordCount << '\n');
OS.EmitSymbolValue(FR.first, 8);
- OS.EmitIntValue(FR.second, 8);
+ OS.EmitIntValue(FR.second.StackSize, 8);
+ OS.EmitIntValue(FR.second.RecordCount, 8);
}
}
// Bail out if there's no stack map data.
assert((!CSInfos.empty() || ConstPool.empty()) &&
"Expected empty constant pool too!");
- assert((!CSInfos.empty() || FnStackSize.empty()) &&
+ assert((!CSInfos.empty() || FnInfos.empty()) &&
"Expected empty function record too!");
if (CSInfos.empty())
return;
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad _test
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _property_access1
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _property_access2
; CHECK-NEXT: .quad 32
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _property_access3
; CHECK-NEXT: .quad 32
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _anyreg_test1
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _anyreg_test2
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _patchpoint_spilldef
; CHECK-NEXT: .quad 112
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _patchpoint_spillargs
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; test
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad _constantargs
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _osrinline
; CHECK-NEXT: .quad 32
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _osrcold
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _propertyRead
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _propertyWrite
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _jsVoidCall
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _jsIntCall
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _spilledValue
; CHECK-NEXT: .quad 160
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _spilledStackMapValue
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _liveConstant
; CHECK-NEXT: .quad 16
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _clobberLR
; CHECK-NEXT: .quad 112
+; CHECK-NEXT: .quad 1
; Num LargeConstants
; CHECK-NEXT: .quad 4294967295
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
}
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
-
; CHECK-LABEL: .section .llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad test
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad property_access1
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad property_access2
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad property_access3
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad anyreg_test1
; CHECK-NEXT: .quad 144
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad anyreg_test2
; CHECK-NEXT: .quad 144
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad patchpoint_spilldef
; CHECK-NEXT: .quad 256
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad patchpoint_spillargs
; CHECK-NEXT: .quad 288
+; CHECK-NEXT: .quad 1
; test
; CHECK-LABEL: .section .llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad constantargs
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad osrinline
; CHECK-NEXT: .quad 144
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad osrcold
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad propertyRead
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad propertyWrite
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad jsVoidCall
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad jsIntCall
; CHECK-NEXT: .quad 128
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad spilledValue
; CHECK-NEXT: .quad 304
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad spilledStackMapValue
; CHECK-NEXT: .quad 224
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad liveConstant
; CHECK-NEXT: .quad 64
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad clobberLR
; CHECK-NEXT: .quad 208
+; CHECK-NEXT: .quad 1
; Num LargeConstants
; CHECK-NEXT: .quad 4294967295
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad _test
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _property_access1
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _property_access2
; CHECK-NEXT: .quad 24
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _property_access3
; CHECK-NEXT: .quad 24
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _anyreg_test1
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _anyreg_test2
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _patchpoint_spilldef
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _patchpoint_spillargs
; CHECK-NEXT: .quad 88
+; CHECK-NEXT: .quad 1
; No constants
; Verify that the stackmap section got emitted:
; CHECK-LABEL: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad _constantargs
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _liveConstant
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _directFrameIdx
; CHECK-NEXT: .quad 40
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _longid
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 4
; Large Constants
; CHECK-NEXT: .quad 2147483648
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; version
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; reserved
; CHECK-NEXT: .byte 0
; reserved
; function address & stack size
; CHECK-NEXT: .quad _foo
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; function address & stack size
; CHECK-NEXT: .quad _bar
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; Constants Array:
; CHECK-NEXT: .quad 9223372036854775807
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad _stackmap_liveness
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 3
; CHECK-NEXT: .quad _mixed_liveness
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 2
define void @stackmap_liveness() {
entry:
; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad _constantargs
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _osrinline
; CHECK-NEXT: .quad 24
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _osrcold
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _propertyRead
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _propertyWrite
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _jsVoidCall
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _jsIntCall
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _spilledValue
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _spilledStackMapValue
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _spillSubReg
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _subRegOffset
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _liveConstant
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _directFrameIdx
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 2
; CHECK-NEXT: .quad _longid
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 4
; CHECK-NEXT: .quad _clobberScratch
; CHECK-NEXT: .quad 56
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad _needsStackRealignment
; CHECK-NEXT: .quad -1
+; CHECK-NEXT: .quad 1
; Large Constants
; CHECK-NEXT: .quad 2147483648
; CHECK-LABEL: .section .llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad test
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad test2
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
; Large Constants
; Statepoint ID only
; CHECK: .short 0
; CHECK: .short 0
; CHECK: .p2align 3
-
; CHECK-LABEL: .section .llvm_stackmaps
; CHECK-NEXT: __LLVM_StackMaps:
; Header
-; CHECK-NEXT: .byte 1
+; CHECK-NEXT: .byte 2
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; Num Functions
; Functions and stack size
; CHECK-NEXT: .quad test
; CHECK-NEXT: .quad 40
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad test_derived_arg
; CHECK-NEXT: .quad 40
+; CHECK-NEXT: .quad 1
; CHECK-NEXT: .quad test_id
; CHECK-NEXT: .quad 8
+; CHECK-NEXT: .quad 1
;
; test
; CHECK: .short 0
; CHECK: .short 0
; CHECK: .p2align 3
-
RUN: llvm-readobj -stackmap %p/Inputs/stackmap-test.macho-x86-64 | FileCheck %s
-CHECK: LLVM StackMap Version: 1
-CHECK-NEXT: Num Functions: 1
-CHECK-NEXT: Function address: 0, stack size: 16
-CHECK-NEXT: Num Constants: 1
-CHECK-NEXT: #1: 10000000000
-CHECK-NEXT: Num Records: 1
-CHECK-NEXT: Record ID: 2, instruction offset: 1
-CHECK-NEXT: 5 locations:
+; Note: the macho object file in this test was generated in the following way:
+; llc -mtriple=x86_64-apple-darwin %p/test/CodeGen/X86/stackmap.ll -o stackmap.s
+; clang -c stackmap.s -o %p/test/Object/Inputs/stackmap-test.macho-x86-64
+
+CHECK: LLVM StackMap Version: 2
+CHECK-NEXT: Num Functions: 16
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 24, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 56, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 56, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 56, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 56, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 56, callsite record count: 2
+CHECK-NEXT: Function address: 0, stack size: 8, callsite record count: 4
+CHECK-NEXT: Function address: 0, stack size: 56, callsite record count: 1
+CHECK-NEXT: Function address: 0, stack size: 18446744073709551615, callsite record count: 1
+CHECK-NEXT: Num Constants: 3
+CHECK-NEXT: #1: 2147483648
+CHECK-NEXT: #2: 4294967295
+CHECK-NEXT: #3: 4294967296
+CHECK-NEXT: Num Records: 20
+CHECK-NEXT: Record ID: 1, instruction offset: 4
+CHECK-NEXT: 12 locations:
+CHECK-NEXT: #1: Constant 4294967295
+CHECK-NEXT: #2: Constant 4294967295
+CHECK-NEXT: #3: Constant 65536
+CHECK-NEXT: #4: Constant 2000000000
+CHECK-NEXT: #5: Constant 2147483647
+CHECK-NEXT: #6: Constant 4294967295
+CHECK-NEXT: #7: Constant 4294967295
+CHECK-NEXT: #8: Constant 0
+CHECK-NEXT: #9: ConstantIndex #0 (2147483648)
+CHECK-NEXT: #10: ConstantIndex #1 (4294967295)
+CHECK-NEXT: #11: ConstantIndex #2 (4294967296)
+CHECK-NEXT: #12: Constant 4294967295
+CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
+
+CHECK: Record ID: 3, instruction offset: 22
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Register R#3
+CHECK-NEXT: #2: Register R#14
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 4, instruction offset: 10
+CHECK-NEXT: 2 locations:
CHECK-NEXT: #1: Register R#5
-CHECK-NEXT: #2: Constant 10
-CHECK-NEXT: #3: ConstantIndex #0 (10000000000)
-CHECK-NEXT: #4: Direct R#4 + -8
-CHECK-NEXT: #5: Indirect [R#6 + -16]
+CHECK-NEXT: #2: Register R#4
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 5, instruction offset: 4
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Register R#0
+CHECK-NEXT: #2: Register R#5
+CHECK-NEXT: 2 live-outs: [ R#0 (8-bytes) R#7 (8-bytes) ]
+
+CHECK: Record ID: 6, instruction offset: 4
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Register R#4
+CHECK-NEXT: #2: Register R#2
CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
+
+CHECK: Record ID: 7, instruction offset: 10
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Register R#2
+CHECK-NEXT: #2: Register R#8
+CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
+
+CHECK: Record ID: 8, instruction offset: 10
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Register R#2
+CHECK-NEXT: #2: Register R#8
+CHECK-NEXT: 2 live-outs: [ R#0 (8-bytes) R#7 (8-bytes) ]
+
+CHECK: Record ID: 11, instruction offset: 42
+CHECK-NEXT: 17 locations:
+CHECK-NEXT: #1: Register R#9
+CHECK-NEXT: #2: Register R#14
+CHECK-NEXT: #3: Register R#10
+CHECK-NEXT: #4: Register R#3
+CHECK-NEXT: #5: Register R#0
+CHECK-NEXT: #6: Register R#13
+CHECK-NEXT: #7: Register R#12
+CHECK-NEXT: #8: Register R#15
+CHECK-NEXT: #9: Indirect [R#6 + 72]
+CHECK-NEXT: #10: Indirect [R#6 + 80]
+CHECK-NEXT: #11: Indirect [R#6 + 88]
+CHECK-NEXT: #12: Indirect [R#6 + 96]
+CHECK-NEXT: #13: Indirect [R#6 + 104]
+CHECK-NEXT: #14: Indirect [R#6 + 112]
+CHECK-NEXT: #15: Indirect [R#6 + 120]
+CHECK-NEXT: #16: Indirect [R#6 + 128]
+CHECK-NEXT: #17: Indirect [R#6 + 136]
+CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
+
+CHECK: Record ID: 12, instruction offset: 62
+CHECK-NEXT: 17 locations:
+CHECK-NEXT: #1: Register R#0
+CHECK-NEXT: #2: Register R#14
+CHECK-NEXT: #3: Register R#10
+CHECK-NEXT: #4: Register R#9
+CHECK-NEXT: #5: Register R#8
+CHECK-NEXT: #6: Register R#4
+CHECK-NEXT: #7: Register R#1
+CHECK-NEXT: #8: Register R#2
+CHECK-NEXT: #9: Register R#5
+CHECK-NEXT: #10: Register R#3
+CHECK-NEXT: #11: Register R#13
+CHECK-NEXT: #12: Register R#12
+CHECK-NEXT: #13: Register R#15
+CHECK-NEXT: #14: Indirect [R#6 + 112]
+CHECK-NEXT: #15: Indirect [R#6 + 120]
+CHECK-NEXT: #16: Indirect [R#6 + 128]
+CHECK-NEXT: #17: Indirect [R#6 + 136]
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 13, instruction offset: 50
+CHECK-NEXT: 1 locations:
+CHECK-NEXT: #1: Indirect [R#6 + -48]
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 14, instruction offset: 24
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Register R#0
+CHECK-NEXT: #2: Register R#3
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 15, instruction offset: 4
+CHECK-NEXT: 1 locations:
+CHECK-NEXT: #1: Constant 33
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 16, instruction offset: 32
+CHECK-NEXT: 1 locations:
+CHECK-NEXT: #1: Direct R#6 + -32
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 17, instruction offset: 32
+CHECK-NEXT: 2 locations:
+CHECK-NEXT: #1: Direct R#6 + -8
+CHECK-NEXT: #2: Direct R#6 + -40
+CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
+
+CHECK: Record ID: 4294967295, instruction offset: 4
+CHECK-NEXT: 0 locations:
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 4294967296, instruction offset: 4
+CHECK-NEXT: 0 locations:
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 9223372036854775807, instruction offset: 4
+CHECK-NEXT: 0 locations:
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 18446744073709551615, instruction offset: 4
+CHECK-NEXT: 0 locations:
+CHECK-NEXT: 1 live-outs: [ R#7 (8-bytes) ]
+
+CHECK: Record ID: 16, instruction offset: 18
+CHECK-NEXT: 1 locations:
+CHECK-NEXT: #1: Indirect [R#6 + -44]
+CHECK-NEXT: 0 live-outs: [ ]
+
+CHECK: Record ID: 0, instruction offset: 26
+CHECK-NEXT: 0 locations:
+CHECK-NEXT: 0 live-outs: [ ]
if (Obj->isLittleEndian())
prettyPrintStackMap(
llvm::outs(),
- StackMapV1Parser<support::little>(StackMapContentsArray));
+ StackMapV2Parser<support::little>(StackMapContentsArray));
else
prettyPrintStackMap(llvm::outs(),
- StackMapV1Parser<support::big>(StackMapContentsArray));
+ StackMapV2Parser<support::big>(StackMapContentsArray));
}
void llvm::dumpCodeViewMergedTypes(
ArrayRef<uint8_t> StackMapContentsArray =
unwrapOrError(Obj->getSectionContents(StackMapSection));
- prettyPrintStackMap(llvm::outs(), StackMapV1Parser<ELFT::TargetEndianness>(
+ prettyPrintStackMap(llvm::outs(), StackMapV2Parser<ELFT::TargetEndianness>(
StackMapContentsArray));
}
if (Obj->isLittleEndian())
prettyPrintStackMap(
llvm::outs(),
- StackMapV1Parser<support::little>(StackMapContentsArray));
+ StackMapV2Parser<support::little>(StackMapContentsArray));
else
prettyPrintStackMap(llvm::outs(),
- StackMapV1Parser<support::big>(StackMapContentsArray));
+ StackMapV2Parser<support::big>(StackMapContentsArray));
}
void MachODumper::printMachODataInCode() {
// Functions:
for (const auto &F : SMP.functions())
OS << "\n Function address: " << F.getFunctionAddress()
- << ", stack size: " << F.getStackSize();
+ << ", stack size: " << F.getStackSize()
+ << ", callsite record count: " << F.getRecordCount();
// Constants:
OS << "\nNum Constants: " << SMP.getNumConstants();