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,50 +32,16 @@
namespace pyston {
// TODO shouldn't be recording this in a global variable
static StackMap* cur_map = NULL;
StackMap* parseStackMap() {
StackMap* rtn = cur_map;
cur_map = NULL;
return rtn;
}
static uint64_t stackmap_address = 0;
class StackmapJITEventListener : public llvm::JITEventListener {
private:
public:
virtual void NotifyObjectEmitted(const llvm::object::ObjectFile&, const llvm::RuntimeDyld::LoadedObjectInfo& L);
};
// LLVM will silently not register the eh frames with libgcc if these functions don't exist;
// make sure that these functions exist.
// TODO I think this breaks it for windows, which apparently loads these dynamically?
// see llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp
extern "C" void __register_frame(void*);
extern "C" void __deregister_frame(void*);
extern void _force_link() {
__register_frame(nullptr);
__deregister_frame(nullptr);
}
void StackmapJITEventListener::NotifyObjectEmitted(const llvm::object::ObjectFile& Obj,
const llvm::RuntimeDyld::LoadedObjectInfo& L) {
// llvm::outs() << "An object has been emitted:\n";
llvm_error_code code;
for (const auto& sec : Obj.sections()) {
llvm::StringRef name;
code = sec.getName(name);
assert(!code);
if (name == ".llvm_stackmaps") {
uint64_t stackmap_address = L.getSectionLoadAddress(name);
assert(stackmap_address > 0);
StackMap* parseStackMap() {
if (!stackmap_address)
return NULL;
if (VERBOSITY() >= 3)
printf("Found the stackmaps at stackmap_address 0x%lx\n", stackmap_address);
assert(cur_map == NULL);
cur_map = new StackMap();
StackMap* cur_map = new StackMap();
union {
const int8_t* i8;
......@@ -108,8 +74,7 @@ void StackmapJITEventListener::NotifyObjectEmitted(const llvm::object::ObjectFil
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);
printf("function %d: offset 0x%lx, stack size 0x%lx\n", i, size_record.offset, size_record.stack_size);
}
if (VERBOSITY() >= 3)
......@@ -172,8 +137,42 @@ void StackmapJITEventListener::NotifyObjectEmitted(const llvm::object::ObjectFil
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);
stackmap_address = 0;
return cur_map;
}
class StackmapJITEventListener : public llvm::JITEventListener {
private:
public:
virtual void NotifyObjectEmitted(const llvm::object::ObjectFile&, const llvm::RuntimeDyld::LoadedObjectInfo& L);
};
// LLVM will silently not register the eh frames with libgcc if these functions don't exist;
// make sure that these functions exist.
// TODO I think this breaks it for windows, which apparently loads these dynamically?
// see llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp
extern "C" void __register_frame(void*);
extern "C" void __deregister_frame(void*);
extern void _force_link() {
__register_frame(nullptr);
__deregister_frame(nullptr);
}
void StackmapJITEventListener::NotifyObjectEmitted(const llvm::object::ObjectFile& Obj,
const llvm::RuntimeDyld::LoadedObjectInfo& L) {
// llvm::outs() << "An object has been emitted:\n";
llvm_error_code code;
for (const auto& sec : Obj.sections()) {
llvm::StringRef name;
code = sec.getName(name);
assert(!code);
if (name == ".llvm_stackmaps") {
assert(stackmap_address == 0);
stackmap_address = L.getSectionLoadAddress(name);
assert(stackmap_address > 0);
}
}
}
......
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