mirror of
https://github.com/corda/corda.git
synced 2025-02-02 01:08:09 +00:00
fix instruction offset calculation in powerpc.cpp
The previous code did not take into account any padding embedded in a basic block due to inline jump tables, which led to invalid code generation in large methods
This commit is contained in:
parent
195bafa9b3
commit
b76cbbfa56
@ -196,7 +196,7 @@ class MyBlock: public Assembler::Block {
|
|||||||
MyBlock(Context* context, unsigned offset):
|
MyBlock(Context* context, unsigned offset):
|
||||||
context(context), next(0), jumpOffsetHead(0), jumpOffsetTail(0),
|
context(context), next(0), jumpOffsetHead(0), jumpOffsetTail(0),
|
||||||
lastJumpOffsetTail(0), jumpEventHead(0), jumpEventTail(0),
|
lastJumpOffsetTail(0), jumpEventHead(0), jumpEventTail(0),
|
||||||
lastEventOffset(0), offset(offset), start(~0), size(0)
|
lastEventOffset(0), offset(offset), start(~0), size(0), resolved(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual unsigned resolve(unsigned start, Assembler::Block* next) {
|
virtual unsigned resolve(unsigned start, Assembler::Block* next) {
|
||||||
@ -205,6 +205,8 @@ class MyBlock: public Assembler::Block {
|
|||||||
|
|
||||||
::resolve(this);
|
::resolve(this);
|
||||||
|
|
||||||
|
this->resolved = true;
|
||||||
|
|
||||||
return start + size + padding(this, size);
|
return start + size + padding(this, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,6 +221,7 @@ class MyBlock: public Assembler::Block {
|
|||||||
unsigned offset;
|
unsigned offset;
|
||||||
unsigned start;
|
unsigned start;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
|
bool resolved;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Task;
|
class Task;
|
||||||
@ -326,13 +329,14 @@ class Offset: public Promise {
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved() {
|
||||||
return block->start != static_cast<unsigned>(~0);
|
return block->resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value() {
|
||||||
assert(c, resolved());
|
assert(c, resolved());
|
||||||
|
|
||||||
return block->start + (offset - block->offset);
|
unsigned o = offset - block->offset;
|
||||||
|
return block->start + padding(block, o) + o;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
@ -495,38 +499,24 @@ appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head,
|
|||||||
b->jumpEventTail = e;
|
b->jumpEventTail = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
needJump(MyBlock* b)
|
||||||
|
{
|
||||||
|
return b->next or (not bounded(2, 16, b->size));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
padding(MyBlock* b, unsigned offset)
|
padding(MyBlock* b, unsigned offset)
|
||||||
{
|
{
|
||||||
unsigned total = 0;
|
unsigned total = 0;
|
||||||
for (JumpEvent** e = &(b->jumpEventHead); *e;) {
|
for (JumpEvent* e = b->jumpEventHead; e; e = e->next) {
|
||||||
if ((*e)->offset <= offset) {
|
if (e->offset <= offset) {
|
||||||
for (JumpOffset** o = &((*e)->jumpOffsetHead); *o;) {
|
for (JumpOffset* o = e->jumpOffsetHead; o; o = o->next) {
|
||||||
if ((*o)->task->promise->resolved()
|
|
||||||
and (*o)->task->instructionOffset->resolved())
|
|
||||||
{
|
|
||||||
int32_t v = reinterpret_cast<uint8_t*>((*o)->task->promise->value())
|
|
||||||
- (b->context->result + (*o)->task->instructionOffset->value());
|
|
||||||
|
|
||||||
if (bounded(2, 16, v)) {
|
|
||||||
// this conditional jump needs no indirection -- a direct
|
|
||||||
// jump will suffice
|
|
||||||
*o = (*o)->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
total += BytesPerWord;
|
total += BytesPerWord;
|
||||||
o = &((*o)->next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*e)->jumpOffsetHead == 0) {
|
if (needJump(b)) {
|
||||||
*e = (*e)->next;
|
total += BytesPerWord;
|
||||||
} else {
|
|
||||||
if (b->next) {
|
|
||||||
total += BytesPerWord;
|
|
||||||
}
|
|
||||||
e = &((*e)->next);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -541,6 +531,32 @@ resolve(MyBlock* b)
|
|||||||
{
|
{
|
||||||
Context* c = b->context;
|
Context* c = b->context;
|
||||||
|
|
||||||
|
for (JumpEvent** e = &(b->jumpEventHead); *e;) {
|
||||||
|
for (JumpOffset** o = &((*e)->jumpOffsetHead); *o;) {
|
||||||
|
if ((*o)->task->promise->resolved()
|
||||||
|
and (*o)->task->instructionOffset->resolved())
|
||||||
|
{
|
||||||
|
int32_t v = reinterpret_cast<uint8_t*>((*o)->task->promise->value())
|
||||||
|
- (c->result + (*o)->task->instructionOffset->value());
|
||||||
|
|
||||||
|
if (bounded(2, 16, v)) {
|
||||||
|
// this conditional jump needs no indirection -- a direct
|
||||||
|
// jump will suffice
|
||||||
|
*o = (*o)->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
o = &((*o)->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*e)->jumpOffsetHead == 0) {
|
||||||
|
*e = (*e)->next;
|
||||||
|
} else {
|
||||||
|
e = &((*e)->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (b->jumpOffsetHead) {
|
if (b->jumpOffsetHead) {
|
||||||
if (c->jumpOffsetTail) {
|
if (c->jumpOffsetTail) {
|
||||||
c->jumpOffsetTail->next = b->jumpOffsetHead;
|
c->jumpOffsetTail->next = b->jumpOffsetHead;
|
||||||
@ -2680,7 +2696,7 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
uint8_t* address = dst + dstOffset + jumpTableSize;
|
uint8_t* address = dst + dstOffset + jumpTableSize;
|
||||||
|
|
||||||
if (b->next) {
|
if (needJump(b)) {
|
||||||
address += BytesPerWord;
|
address += BytesPerWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2691,7 +2707,7 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
assert(&c, jumpTableSize);
|
assert(&c, jumpTableSize);
|
||||||
|
|
||||||
if (b->next) {
|
if (needJump(b)) {
|
||||||
write4(dst + dstOffset, ::b(jumpTableSize + BytesPerWord));
|
write4(dst + dstOffset, ::b(jumpTableSize + BytesPerWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user