mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
Fix bug in exception table allocation (PR13678)
Patch by Michael Muller. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172214 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8c1e72e6ac
commit
dced3cdb04
@ -969,14 +969,24 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
|||||||
SavedBufferBegin = BufferBegin;
|
SavedBufferBegin = BufferBegin;
|
||||||
SavedBufferEnd = BufferEnd;
|
SavedBufferEnd = BufferEnd;
|
||||||
SavedCurBufferPtr = CurBufferPtr;
|
SavedCurBufferPtr = CurBufferPtr;
|
||||||
|
uint8_t *FrameRegister;
|
||||||
|
|
||||||
BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
|
while (true) {
|
||||||
ActualSize);
|
BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
|
||||||
BufferEnd = BufferBegin+ActualSize;
|
ActualSize);
|
||||||
EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
|
BufferEnd = BufferBegin+ActualSize;
|
||||||
uint8_t *EhStart;
|
EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
|
||||||
uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
|
uint8_t *EhStart;
|
||||||
EhStart);
|
FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, EhStart);
|
||||||
|
|
||||||
|
// If the buffer was large enough to hold the table then we are done.
|
||||||
|
if (CurBufferPtr != BufferEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Try again with twice as much space.
|
||||||
|
ActualSize = (CurBufferPtr - BufferBegin) * 2;
|
||||||
|
MemMgr->deallocateExceptionTable(BufferBegin);
|
||||||
|
}
|
||||||
MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
|
MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
|
||||||
FrameRegister);
|
FrameRegister);
|
||||||
BufferBegin = SavedBufferBegin;
|
BufferBegin = SavedBufferBegin;
|
||||||
|
@ -161,7 +161,7 @@ public:
|
|||||||
uintptr_t ActualSizeResult;
|
uintptr_t ActualSizeResult;
|
||||||
};
|
};
|
||||||
std::vector<StartExceptionTableCall> startExceptionTableCalls;
|
std::vector<StartExceptionTableCall> startExceptionTableCalls;
|
||||||
virtual uint8_t* startExceptionTable(const Function* F,
|
virtual uint8_t *startExceptionTable(const Function *F,
|
||||||
uintptr_t &ActualSize) {
|
uintptr_t &ActualSize) {
|
||||||
uintptr_t InitialActualSize = ActualSize;
|
uintptr_t InitialActualSize = ActualSize;
|
||||||
uint8_t *Result = Base->startExceptionTable(F, ActualSize);
|
uint8_t *Result = Base->startExceptionTable(F, ActualSize);
|
||||||
@ -203,14 +203,21 @@ bool LoadAssemblyInto(Module *M, const char *assembly) {
|
|||||||
|
|
||||||
class JITTest : public testing::Test {
|
class JITTest : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
|
virtual RecordingJITMemoryManager *createMemoryManager() {
|
||||||
|
return new RecordingJITMemoryManager;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
M = new Module("<main>", Context);
|
M = new Module("<main>", Context);
|
||||||
RJMM = new RecordingJITMemoryManager;
|
RJMM = createMemoryManager();
|
||||||
RJMM->setPoisonMemory(true);
|
RJMM->setPoisonMemory(true);
|
||||||
std::string Error;
|
std::string Error;
|
||||||
|
TargetOptions Options;
|
||||||
|
Options.JITExceptionHandling = true;
|
||||||
TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
|
TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
|
||||||
.setJITMemoryManager(RJMM)
|
.setJITMemoryManager(RJMM)
|
||||||
.setErrorStr(&Error).create());
|
.setErrorStr(&Error)
|
||||||
|
.setTargetOptions(Options).create());
|
||||||
ASSERT_TRUE(TheJIT.get() != NULL) << Error;
|
ASSERT_TRUE(TheJIT.get() != NULL) << Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +304,46 @@ TEST(JIT, GlobalInFunction) {
|
|||||||
|
|
||||||
#endif // !defined(__arm__) && !defined(__powerpc__)
|
#endif // !defined(__arm__) && !defined(__powerpc__)
|
||||||
|
|
||||||
|
// Regression test for a bug. The JITEmitter wasn't checking to verify that
|
||||||
|
// it hadn't run out of space while generating the DWARF exception information
|
||||||
|
// for an emitted function.
|
||||||
|
|
||||||
|
class ExceptionMemoryManagerMock : public RecordingJITMemoryManager {
|
||||||
|
public:
|
||||||
|
virtual uint8_t *startExceptionTable(const Function *F,
|
||||||
|
uintptr_t &ActualSize) {
|
||||||
|
// force an insufficient size the first time through.
|
||||||
|
bool ChangeActualSize = false;
|
||||||
|
if (ActualSize == 0)
|
||||||
|
ChangeActualSize = true;;
|
||||||
|
uint8_t *result =
|
||||||
|
RecordingJITMemoryManager::startExceptionTable(F, ActualSize);
|
||||||
|
if (ChangeActualSize)
|
||||||
|
ActualSize = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JITExceptionMemoryTest : public JITTest {
|
||||||
|
protected:
|
||||||
|
virtual RecordingJITMemoryManager *createMemoryManager() {
|
||||||
|
return new ExceptionMemoryManagerMock;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(JITExceptionMemoryTest, ExceptionTableOverflow) {
|
||||||
|
Function *F = Function::Create(TypeBuilder<void(void), false>::get(Context),
|
||||||
|
Function::ExternalLinkage,
|
||||||
|
"func1", M);
|
||||||
|
BasicBlock *Block = BasicBlock::Create(Context, "block", F);
|
||||||
|
IRBuilder<> Builder(Block);
|
||||||
|
Builder.CreateRetVoid();
|
||||||
|
TheJIT->getPointerToFunction(F);
|
||||||
|
ASSERT_TRUE(RJMM->startExceptionTableCalls.size() == 2);
|
||||||
|
ASSERT_TRUE(RJMM->deallocateExceptionTableCalls.size() == 1);
|
||||||
|
ASSERT_TRUE(RJMM->endExceptionTableCalls.size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
int PlusOne(int arg) {
|
int PlusOne(int arg) {
|
||||||
return arg + 1;
|
return arg + 1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user