summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2008-08-07 01:30:15 +0000
committerDale Johannesen <dalej@apple.com>2008-08-07 01:30:15 +0000
commitdd947ea3c5e020c33c58a31939561265b980a3ad (patch)
tree1ed06d324e47916a3ffaecc9f5d8978562c16a56 /lib/ExecutionEngine
parent39fd6e81b1b0de8b820155dc6a0dae226c109de6 (diff)
downloadllvm-dd947ea3c5e020c33c58a31939561265b980a3ad.tar.gz
llvm-dd947ea3c5e020c33c58a31939561265b980a3ad.tar.bz2
llvm-dd947ea3c5e020c33c58a31939561265b980a3ad.tar.xz
Rewrite JIT handling of GlobalVariables so they
are allocated in the same buffer as the code, jump tables, etc. The default JIT memory manager does not handle buffer overflow well. I didn't introduce this and I'm not attempting to fix it here, but it is more likely to be hit now since we're putting more stuff in the buffer. This affects one test that I know of so far, MultiSource/Benchmarks/NPB-serial/is. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54442 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp2
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp22
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp176
-rw-r--r--lib/ExecutionEngine/JIT/JITMemoryManager.cpp2
4 files changed, 179 insertions, 23 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index 94136d54af..b3dfe01069 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -819,6 +819,8 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result,
// specified memory location...
//
void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
+ DOUT << "Initializing " << Addr;
+ DEBUG(Init->dump());
if (isa<UndefValue>(Init)) {
return;
} else if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) {
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index 940434c731..d4f190bfc7 100644
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/lib/ExecutionEngine/JIT/JIT.cpp
@@ -415,30 +415,22 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
cerr << "Could not resolve external global address: "
<< GV->getName() << "\n";
abort();
+ addGlobalMapping(GV, Ptr);
}
} else {
- // If the global hasn't been emitted to memory yet, allocate space. We will
- // actually initialize the global after current function has finished
- // compilation.
+ // If the global hasn't been emitted to memory yet, allocate space and
+ // emit it into memory. It goes in the same array as the generated
+ // code, jump tables, etc.
const Type *GlobalType = GV->getType()->getElementType();
size_t S = getTargetData()->getABITypeSize(GlobalType);
size_t A = getTargetData()->getPreferredAlignment(GV);
- if (A <= 8) {
- Ptr = malloc(S);
- } else {
- // Allocate S+A bytes of memory, then use an aligned pointer within that
- // space.
- Ptr = malloc(S+A);
- unsigned MisAligned = ((intptr_t)Ptr & (A-1));
- Ptr = (char*)Ptr + (MisAligned ? (A-MisAligned) : 0);
- }
- jitstate->getPendingGlobals(locked).push_back(GV);
+ Ptr = MCE->allocateSpace(S, A);
+ addGlobalMapping(GV, Ptr);
+ EmitGlobalVariable(GV);
}
- addGlobalMapping(GV, Ptr);
return Ptr;
}
-
/// recompileAndRelinkFunction - This method is used to force a function
/// which has already been compiled, to be compiled again, possibly
/// after it has been modified. Then the entry to the old copy is overwritten
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index cbfaa09e36..d38f9f90e2 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -15,9 +15,9 @@
#define DEBUG_TYPE "jit"
#include "JIT.h"
#include "JITDwarfEmitter.h"
-#include "llvm/Constant.h"
+#include "llvm/Constants.h"
#include "llvm/Module.h"
-#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -25,6 +25,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetJITInfo.h"
#include "llvm/Target/TargetMachine.h"
@@ -36,6 +37,7 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include <algorithm>
+#include <set>
using namespace llvm;
STATISTIC(NumBytes, "Number of bytes of machine code compiled");
@@ -467,6 +469,9 @@ namespace {
/// MMI - Machine module info for exception informations
MachineModuleInfo* MMI;
+ // GVSet - a set to keep track of which globals have been seen
+ std::set<const GlobalVariable*> GVSet;
+
public:
JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit) {
MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
@@ -541,6 +546,10 @@ namespace {
void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
bool NoNeedStub);
+ unsigned addSizeOfGlobal(const GlobalVariable *GV, unsigned Size);
+ unsigned addSizeOfGlobalsInConstantVal(const Constant *C, unsigned Size);
+ unsigned addSizeOfGlobalsInInitializer(const Constant *Init, unsigned Size);
+ unsigned GetSizeOfGlobalsInBytes(MachineFunction &MF);
};
}
@@ -618,9 +627,154 @@ static uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) {
return Size + Alignment;
}
+/// addSizeOfGlobal - add the size of the global (plus any alignment padding)
+/// into the running total Size.
+
+unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) {
+ const Type *ElTy = GV->getType()->getElementType();
+ size_t GVSize = (size_t)TheJIT->getTargetData()->getABITypeSize(ElTy);
+ size_t GVAlign =
+ (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV);
+ DOUT << "Adding in size " << GVSize << " alignment " << GVAlign;
+ DEBUG(GV->dump());
+ // Assume code section ends with worst possible alignment, so first
+ // variable needs maximal padding.
+ if (Size==0)
+ Size = 1;
+ Size = ((Size+GVAlign-1)/GVAlign)*GVAlign;
+ Size += GVSize;
+ return Size;
+}
+
+/// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet
+/// but are referenced from the constant; put them in GVSet and add their
+/// size into the running total Size.
+
+unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C,
+ unsigned Size) {
+ // If its undefined, return the garbage.
+ if (isa<UndefValue>(C))
+ return Size;
+
+ // If the value is a ConstantExpr
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+ Constant *Op0 = CE->getOperand(0);
+ switch (CE->getOpcode()) {
+ case Instruction::GetElementPtr:
+ case Instruction::Trunc:
+ case Instruction::ZExt:
+ case Instruction::SExt:
+ case Instruction::FPTrunc:
+ case Instruction::FPExt:
+ case Instruction::UIToFP:
+ case Instruction::SIToFP:
+ case Instruction::FPToUI:
+ case Instruction::FPToSI:
+ case Instruction::PtrToInt:
+ case Instruction::IntToPtr:
+ case Instruction::BitCast: {
+ Size = addSizeOfGlobalsInConstantVal(Op0, Size);
+ break;
+ }
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::UDiv:
+ case Instruction::SDiv:
+ case Instruction::URem:
+ case Instruction::SRem:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor: {
+ Size = addSizeOfGlobalsInConstantVal(Op0, Size);
+ Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size);
+ break;
+ }
+ default: {
+ cerr << "ConstantExpr not handled: " << *CE << "\n";
+ abort();
+ }
+ }
+ }
+
+ if (C->getType()->getTypeID() == Type::PointerTyID)
+ if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C))
+ if (GVSet.insert(GV).second)
+ Size = addSizeOfGlobal(GV, Size);
+
+ return Size;
+}
+
+/// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet
+/// but are referenced from the given initializer.
+
+unsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init,
+ unsigned Size) {
+ if (!isa<UndefValue>(Init) &&
+ !isa<ConstantVector>(Init) &&
+ !isa<ConstantAggregateZero>(Init) &&
+ !isa<ConstantArray>(Init) &&
+ !isa<ConstantStruct>(Init) &&
+ Init->getType()->isFirstClassType())
+ Size = addSizeOfGlobalsInConstantVal(Init, Size);
+ return Size;
+}
+
+/// GetSizeOfGlobalsInBytes - walk the code for the function, looking for
+/// globals; then walk the initializers of those globals looking for more.
+/// If their size has not been considered yet, add it into the running total
+/// Size.
+
+unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) {
+ unsigned Size = 0;
+ GVSet.clear();
+
+ for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
+ MBB != E; ++MBB) {
+ for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
+ I != E; ++I) {
+ const TargetInstrDesc &Desc = I->getDesc();
+ const MachineInstr &MI = *I;
+ unsigned NumOps = Desc.getNumOperands();
+ for (unsigned CurOp = 0; CurOp < NumOps; CurOp++) {
+ const MachineOperand &MO = MI.getOperand(CurOp);
+ if (MO.isGlobalAddress()) {
+ GlobalValue* V = MO.getGlobal();
+ const GlobalVariable *GV = dyn_cast<const GlobalVariable>(V);
+ if (!GV)
+ continue;
+ // If seen in previous function, it will have an entry here.
+ if (TheJIT->getPointerToGlobalIfAvailable(GV))
+ continue;
+ // If seen earlier in this function, it will have an entry here.
+ // FIXME: it should be possible to combine these tables, by
+ // assuming the addresses of the new globals in this module
+ // start at 0 (or something) and adjusting them after codegen
+ // complete. Another possibility is to grab a marker bit in GV.
+ if (GVSet.insert(GV).second)
+ // A variable as yet unseen. Add in its size.
+ Size = addSizeOfGlobal(GV, Size);
+ }
+ }
+ }
+ }
+ DOUT << "About to look through initializers\n";
+ // Look for more globals that are referenced only from initializers.
+ // GVSet.end is computed each time because the set can grow as we go.
+ for (std::set<const GlobalVariable *>::iterator I = GVSet.begin();
+ I != GVSet.end(); I++) {
+ const GlobalVariable* GV = *I;
+ if (GV->hasInitializer())
+ Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size);
+ }
+
+ return Size;
+}
+
void JITEmitter::startFunction(MachineFunction &F) {
uintptr_t ActualSize = 0;
if (MemMgr->NeedsExactSize()) {
+ DOUT << "ExactSize\n";
const TargetInstrInfo* TII = F.getTarget().getInstrInfo();
MachineJumpTableInfo *MJTI = F.getJumpTableInfo();
MachineConstantPool *MCP = F.getConstantPool();
@@ -647,6 +801,13 @@ void JITEmitter::startFunction(MachineFunction &F) {
// Add the function size
ActualSize += TII->GetFunctionSizeInBytes(F);
+
+ DOUT << "ActualSize before globals " << ActualSize << "\n";
+ // Add the size of the globals that will be allocated after this function.
+ // These are all the ones referenced from this function that were not
+ // previously allocated.
+ ActualSize += GetSizeOfGlobalsInBytes(F);
+ DOUT << "ActualSize after globals " << ActualSize << "\n";
}
BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
@@ -679,10 +840,6 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
// other per-function data.
unsigned char *FnStart =
(unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction());
- unsigned char *FnEnd = CurBufferPtr;
-
- MemMgr->endFunctionBody(F.getFunction(), BufferBegin, FnEnd);
- NumBytes += FnEnd-FnStart;
if (!Relocations.empty()) {
NumRelos += Relocations.size();
@@ -734,6 +891,11 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
Relocations.size(), MemMgr->getGOTBase());
}
+ unsigned char *FnEnd = CurBufferPtr;
+
+ MemMgr->endFunctionBody(F.getFunction(), BufferBegin, FnEnd);
+ NumBytes += FnEnd-FnStart;
+
// Update the GOT entry for F to point to the new code.
if (MemMgr->isManagingGOT()) {
unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin);
@@ -962,7 +1124,7 @@ void *JIT::getPointerToFunctionOrStub(Function *F) {
/// freeMachineCodeForFunction - release machine code memory for given Function.
///
void JIT::freeMachineCodeForFunction(Function *F) {
-
+
// Delete translation for this from the ExecutionEngine, so it will get
// retranslated next time it is used.
void *OldPtr = updateGlobalMapping(F, 0);
diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
index 248291634c..d2d5c2f8e0 100644
--- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
+++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
@@ -290,7 +290,7 @@ namespace {
assert(FunctionEnd > FunctionStart);
assert(FunctionStart == (unsigned char *)(CurBlock+1) &&
"Mismatched function start/end!");
-
+
uintptr_t BlockSize = FunctionEnd - (unsigned char *)CurBlock;
FunctionBlocks[F] = CurBlock;