Commit b6ebc815 authored by Marius Wachtler's avatar Marius Wachtler

LLVM: Add support for symbolic entries in the stackmap constant table

parent 23c27d2d
From a27e2f111d85c2e55c5a9672b9ef39494b4d7fd8 Mon Sep 17 00:00:00 2001
From: Marius Wachtler <undingen@gmail.com>
Date: Wed, 15 Apr 2015 09:40:51 +0200
Subject: [PATCH] Add support for symbolic entries in the stackmap constant
table
---
include/llvm/CodeGen/StackMaps.h | 18 ++++++++++--
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 9 ++++++
lib/CodeGen/StackMaps.cpp | 36 +++++++++++++++++++++---
test/CodeGen/X86/stackmap.ll | 26 +++++++++++++++--
4 files changed, 79 insertions(+), 10 deletions(-)
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 4e48afe..30cae3b 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -136,9 +136,13 @@ public:
unsigned Size;
unsigned Reg;
int64_t Offset;
- Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {}
+ const MCSymbol *Sym;
+ Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0), Sym(0) {}
Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset)
- : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}
+ : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset), Sym(0) {}
+ Location(const MCSymbol *Sym)
+ : LocType(LocationType::Constant), Size(sizeof(int64_t)), Reg(0),
+ Offset(0), Sym(Sym) {}
};
struct LiveOutReg {
@@ -160,13 +164,19 @@ public:
// 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;
+ typedef enum {
+ DirectMemRefOp,
+ IndirectMemRefOp,
+ ConstantOp,
+ ConstantGVOp
+ } OpType;
StackMaps(AsmPrinter &AP);
void reset() {
CSInfos.clear();
ConstPool.clear();
+ ConstSymPool.clear();
FnStackSize.clear();
}
@@ -191,6 +201,7 @@ private:
typedef SmallVector<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec;
typedef MapVector<uint64_t, uint64_t> ConstantPool;
+ typedef MapVector<const MCSymbol *, const MCSymbol *> ConstantSymMap;
typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap;
struct CallsiteInfo {
@@ -210,6 +221,7 @@ private:
AsmPrinter &AP;
CallsiteInfoList CSInfos;
ConstantPool ConstPool;
+ ConstantSymMap ConstSymPool;
FnStackSizeMap FnStackSize;
MachineInstr::const_mop_iterator
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index c0a8299..98cc692 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7122,6 +7122,15 @@ static void addStackMapLiveVars(ImmutableCallSite CS, unsigned StartIdx,
const TargetLowering &TLI = Builder.DAG.getTargetLoweringInfo();
Ops.push_back(
Builder.DAG.getTargetFrameIndex(FI->getIndex(), TLI.getPointerTy()));
+ } else if (auto *GA = dyn_cast<GlobalAddressSDNode>(OpVal)) {
+ if (GA->getValueType(0) != MVT::i64)
+ Ops.push_back(OpVal);
+ else {
+ Ops.push_back(
+ Builder.DAG.getTargetConstant(StackMaps::ConstantGVOp, MVT::i64));
+ Ops.push_back(Builder.DAG.getTargetGlobalAddress(GA->getGlobal(),
+ SDLoc(GA), MVT::i64));
+ }
} else
Ops.push_back(OpVal);
}
diff --git a/lib/CodeGen/StackMaps.cpp b/lib/CodeGen/StackMaps.cpp
index 0797d56..7151166 100644
--- a/lib/CodeGen/StackMaps.cpp
+++ b/lib/CodeGen/StackMaps.cpp
@@ -107,6 +107,16 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
Locs.push_back(Location(Location::Constant, sizeof(int64_t), 0, Imm));
break;
}
+ case StackMaps::ConstantGVOp: {
+ ++MOI;
+ assert(MOI->isGlobal() && "Expected a global value operand.");
+ const GlobalValue *GV = MOI->getGlobal();
+ assert(GV);
+ MCSymbol *Sym = AP.TM.getSymbol(GV, *AP.Mang);
+ assert(Sym);
+ Locs.push_back(Location(Sym));
+ break;
+ }
}
return ++MOI;
}
@@ -226,7 +236,7 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
I != E; ++I) {
// Constants are encoded as sign-extended integers.
// -1 is directly encoded as .long 0xFFFFFFFF with no constant pool.
- if (I->LocType == Location::Constant && !isInt<32>(I->Offset)) {
+ if (I->LocType == Location::Constant && !isInt<32>(I->Offset) && !I->Sym) {
I->LocType = Location::ConstantIndex;
// ConstPool is intentionally a MapVector of 'uint64_t's (as
// opposed to 'int64_t's). We should never be in a situation
@@ -243,6 +253,17 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
}
}
+ // Convert constant symbols to ConstantIndex entries.
+ for (LocationVec::iterator I = Locations.begin(), E = Locations.end(); I != E;
+ ++I) {
+ if (I->LocType == Location::Constant && I->Sym) {
+ I->LocType = Location::ConstantIndex;
+ auto Result = ConstSymPool.insert(std::make_pair(I->Sym, I->Sym));
+ // The symbolic entries will be emitted after the ConstPool entries.
+ I->Offset = ConstPool.size() + Result.first - ConstSymPool.begin();
+ }
+ }
+
// Create an expression to calculate the offset of the callsite from function
// entry.
const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
@@ -325,8 +346,9 @@ void StackMaps::emitStackmapHeader(MCStreamer &OS) {
DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
OS.EmitIntValue(FnStackSize.size(), 4);
// Num constants.
- DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
- OS.EmitIntValue(ConstPool.size(), 4);
+ auto NumConst = ConstPool.size() + ConstSymPool.size();
+ DEBUG(dbgs() << WSMP << "#constants = " << NumConst << '\n');
+ OS.EmitIntValue(NumConst, 4);
// Num callsites.
DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
OS.EmitIntValue(CSInfos.size(), 4);
@@ -359,6 +381,10 @@ void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
OS.EmitIntValue(ConstEntry.second, 8);
}
+ for (auto ConstEntry : ConstSymPool) {
+ DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
+ OS.EmitSymbolValue(ConstEntry.second, 8);
+ }
}
/// Emit the callsite info for each callsite.
@@ -511,7 +537,8 @@ void StackMaps::emitCallsiteEntries(MCStreamer &OS,
void StackMaps::serializeToStackMapSection() {
(void) WSMP;
// Bail out if there's no stack map data.
- assert((!CSInfos.empty() || (CSInfos.empty() && ConstPool.empty())) &&
+ assert((!CSInfos.empty() ||
+ (CSInfos.empty() && ConstPool.empty() && ConstSymPool.empty())) &&
"Expected empty constant pool too!");
assert((!CSInfos.empty() || (CSInfos.empty() && FnStackSize.empty())) &&
"Expected empty function record too!");
@@ -541,4 +568,5 @@ void StackMaps::serializeToStackMapSection() {
// Clean up.
CSInfos.clear();
ConstPool.clear();
+ ConstSymPool.clear();
}
diff --git a/test/CodeGen/X86/stackmap.ll b/test/CodeGen/X86/stackmap.ll
index 5e356f3..59fa50f 100644
--- a/test/CodeGen/X86/stackmap.ll
+++ b/test/CodeGen/X86/stackmap.ll
@@ -11,7 +11,7 @@
; Num Functions
; CHECK-NEXT: .long 16
; Num LargeConstants
-; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 5
; Num Callsites
; CHECK-NEXT: .long 20
@@ -53,6 +53,8 @@
; CHECK-NEXT: .quad 2147483648
; CHECK-NEXT: .quad 4294967295
; CHECK-NEXT: .quad 4294967296
+; CHECK-NEXT: .quad _constSym1
+; CHECK-NEXT: .quad _constSym2
; Callsites
; Constant arguments
@@ -60,7 +62,7 @@
; CHECK-NEXT: .quad 1
; CHECK-NEXT: .long L{{.*}}-_constantargs
; CHECK-NEXT: .short 0
-; CHECK-NEXT: .short 12
+; CHECK-NEXT: .short 15
; SmallConstant
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 8
@@ -116,16 +118,34 @@
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 2
+; LargeConstant at index 3
+; CHECK-NEXT: .byte 5
+; CHECK-NEXT: .byte 8
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .long 3
+; LargeConstant at index 3
+; CHECK-NEXT: .byte 5
+; CHECK-NEXT: .byte 8
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .long 3
+; LargeConstant at index 4
+; CHECK-NEXT: .byte 5
+; CHECK-NEXT: .byte 8
+; CHECK-NEXT: .short 0
+; CHECK-NEXT: .long 4
; SmallConstant
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long -1
+
+@constSym1 = external constant i64
+@constSym2 = external constant i64
define void @constantargs() {
entry:
%0 = inttoptr i64 12345 to i8*
- tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64 -1)
+ tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64* @constSym1, i64* @constSym1, i64* @constSym2, i64 -1)
ret void
}
--
2.1.0
......@@ -32,11 +32,113 @@
namespace pyston {
// TODO shouldn't be recording this in a global variable
static StackMap* cur_map = NULL;
static uint64_t stackmap_address = 0;
StackMap* parseStackMap() {
StackMap* rtn = cur_map;
cur_map = NULL;
return rtn;
if (!stackmap_address)
return NULL;
if (VERBOSITY() >= 3)
printf("Found the stackmaps at stackmap_address 0x%lx\n", stackmap_address);
StackMap* cur_map = new StackMap();
union {
const int8_t* i8;
const int16_t* i16;
const int32_t* i32;
const int64_t* i64;
const uint8_t* u8;
const uint16_t* u16;
const uint32_t* u32;
const uint64_t* u64;
const StackMap::Record::Location* record_loc;
const StackMap::Record::LiveOut* record_liveout;
const StackMap::StackSizeRecord* size_record;
} ptr;
const int8_t* start_ptr = ptr.i8 = (const int8_t*)stackmap_address;
cur_map->header = *ptr.u32++; // header
#if LLVMREV < 200481
int nfunctions = 0;
#else
int nfunctions = *ptr.u32++;
#endif
int nconstants = *ptr.u32++;
int nrecords = *ptr.u32++;
if (VERBOSITY() >= 3)
printf("%d functions\n", nfunctions);
for (int i = 0; i < nfunctions; i++) {
const StackMap::StackSizeRecord& size_record = *ptr.size_record++;
cur_map->stack_size_records.push_back(size_record);
if (VERBOSITY() >= 3)
printf("function %d: offset 0x%lx, stack size 0x%lx\n", i, size_record.offset, size_record.stack_size);
}
if (VERBOSITY() >= 3)
printf("%d constants\n", nconstants);
for (int i = 0; i < nconstants; i++) {
uint64_t constant = *ptr.u64++;
if (VERBOSITY() >= 3)
printf("Constant %d: %ld\n", i, constant);
cur_map->constants.push_back(constant);
}
if (VERBOSITY() >= 3)
printf("%d records\n", nrecords);
for (int i = 0; i < nrecords; i++) {
StackMap::Record* record = new StackMap::Record();
cur_map->records.push_back(record);
record->id = *ptr.u64++;
record->offset = *ptr.u32++;
record->flags = *ptr.u16++; // reserved (record flags)
int numlocations = *ptr.u16++;
if (VERBOSITY() >= 3)
printf("Stackmap record %ld at 0x%x has %d locations:\n", record->id, record->offset, numlocations);
for (int j = 0; j < numlocations; j++) {
assert(sizeof(StackMap::Record::Location) == sizeof(*ptr.u64));
const StackMap::Record::Location& r = *ptr.record_loc++;
record->locations.push_back(r);
// from http://lxr.free-electrons.com/source/tools/perf/arch/x86/util/dwarf-regs.c
// TODO this probably can be fetched more portably from the llvm target files
const char* dwarf_reg_names[] = {
"%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
};
if (VERBOSITY() >= 3) {
if (r.type == 1) {
printf("Location %d: type %d (reg), reg %d (%s), offset %d\n", j, r.type, r.regnum,
dwarf_reg_names[r.regnum], r.offset);
} else {
printf("Location %d: type %d, reg %d, offset %d\n", j, r.type, r.regnum, r.offset);
}
}
}
ptr.u16++; // padding
int num_live_outs = *ptr.u16++;
for (int i = 0; i < num_live_outs; i++) {
const StackMap::Record::LiveOut& r = *ptr.record_liveout++;
record->live_outs.push_back(r);
if (VERBOSITY() >= 3) {
printf("Live out %d: reg #%d (?), size %d\n", i, r.regnum, r.size);
}
}
if (num_live_outs % 2 == 0)
ptr.u32++; // pad to 8-byte boundary
}
stackmap_address = 0;
return cur_map;
}
class StackmapJITEventListener : public llvm::JITEventListener {
......@@ -68,112 +170,9 @@ void StackmapJITEventListener::NotifyObjectEmitted(const llvm::object::ObjectFil
assert(!code);
if (name == ".llvm_stackmaps") {
uint64_t stackmap_address = L.getSectionLoadAddress(name);
assert(stackmap_address == 0);
stackmap_address = L.getSectionLoadAddress(name);
assert(stackmap_address > 0);
if (VERBOSITY() >= 3)
printf("Found the stackmaps at stackmap_address 0x%lx\n", stackmap_address);
assert(cur_map == NULL);
cur_map = new StackMap();
union {
const int8_t* i8;
const int16_t* i16;
const int32_t* i32;
const int64_t* i64;
const uint8_t* u8;
const uint16_t* u16;
const uint32_t* u32;
const uint64_t* u64;
const StackMap::Record::Location* record_loc;
const StackMap::Record::LiveOut* record_liveout;
const StackMap::StackSizeRecord* size_record;
} ptr;
const int8_t* start_ptr = ptr.i8 = (const int8_t*)stackmap_address;
cur_map->header = *ptr.u32++; // header
#if LLVMREV < 200481
int nfunctions = 0;
#else
int nfunctions = *ptr.u32++;
#endif
int nconstants = *ptr.u32++;
int nrecords = *ptr.u32++;
if (VERBOSITY() >= 3)
printf("%d functions\n", nfunctions);
for (int i = 0; i < nfunctions; i++) {
const StackMap::StackSizeRecord& size_record = *ptr.size_record++;
cur_map->stack_size_records.push_back(size_record);
if (VERBOSITY() >= 3)
printf("function %d: offset 0x%lx, stack size 0x%lx\n", i, size_record.offset,
size_record.stack_size);
}
if (VERBOSITY() >= 3)
printf("%d constants\n", nconstants);
for (int i = 0; i < nconstants; i++) {
uint64_t constant = *ptr.u64++;
if (VERBOSITY() >= 3)
printf("Constant %d: %ld\n", i, constant);
cur_map->constants.push_back(constant);
}
if (VERBOSITY() >= 3)
printf("%d records\n", nrecords);
for (int i = 0; i < nrecords; i++) {
StackMap::Record* record = new StackMap::Record();
cur_map->records.push_back(record);
record->id = *ptr.u64++;
record->offset = *ptr.u32++;
record->flags = *ptr.u16++; // reserved (record flags)
int numlocations = *ptr.u16++;
if (VERBOSITY() >= 3)
printf("Stackmap record %ld at 0x%x has %d locations:\n", record->id, record->offset, numlocations);
for (int j = 0; j < numlocations; j++) {
assert(sizeof(StackMap::Record::Location) == sizeof(*ptr.u64));
const StackMap::Record::Location& r = *ptr.record_loc++;
record->locations.push_back(r);
// from http://lxr.free-electrons.com/source/tools/perf/arch/x86/util/dwarf-regs.c
// TODO this probably can be fetched more portably from the llvm target files
const char* dwarf_reg_names[] = {
"%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
};
if (VERBOSITY() >= 3) {
if (r.type == 1) {
printf("Location %d: type %d (reg), reg %d (%s), offset %d\n", j, r.type, r.regnum,
dwarf_reg_names[r.regnum], r.offset);
} else {
printf("Location %d: type %d, reg %d, offset %d\n", j, r.type, r.regnum, r.offset);
}
}
}
ptr.u16++; // padding
int num_live_outs = *ptr.u16++;
for (int i = 0; i < num_live_outs; i++) {
const StackMap::Record::LiveOut& r = *ptr.record_liveout++;
record->live_outs.push_back(r);
if (VERBOSITY() >= 3) {
printf("Live out %d: reg #%d (?), size %d\n", i, r.regnum, r.size);
}
}
if (num_live_outs % 2 == 0)
ptr.u32++; // pad to 8-byte boundary
}
uint64_t stackmap_size = sec.getSize();
ASSERT(ptr.i8 - start_ptr == stackmap_size, "%ld %ld", ptr.i8 - start_ptr, stackmap_size);
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment