mirror of
https://github.com/corda/corda.git
synced 2025-03-12 23:44:13 +00:00
various bugfixes involving multiword values
This commit is contained in:
parent
d0676d0303
commit
8b1801c465
@ -97,6 +97,43 @@ class ResolvedPromise: public Promise {
|
||||
int64_t value_;
|
||||
};
|
||||
|
||||
class ShiftMaskPromise: public Promise {
|
||||
public:
|
||||
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
|
||||
base(base), shift(shift), mask(mask)
|
||||
{ }
|
||||
|
||||
virtual int64_t value() {
|
||||
return (base->value() >> shift) & mask;
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return base->resolved();
|
||||
}
|
||||
|
||||
Promise* base;
|
||||
unsigned shift;
|
||||
int64_t mask;
|
||||
};
|
||||
|
||||
class CombinedPromise: public Promise {
|
||||
public:
|
||||
CombinedPromise(Promise* low, Promise* high):
|
||||
low(low), high(high)
|
||||
{ }
|
||||
|
||||
virtual int64_t value() {
|
||||
return low->value() | (high->value() << 32);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return low->resolved() and high->resolved();
|
||||
}
|
||||
|
||||
Promise* low;
|
||||
Promise* high;
|
||||
};
|
||||
|
||||
class TraceHandler {
|
||||
public:
|
||||
virtual void handleTrace(Promise* address, unsigned padIndex,
|
||||
|
329
src/compiler.cpp
329
src/compiler.cpp
@ -118,12 +118,14 @@ class Site {
|
||||
|
||||
virtual OperandType type(Context*) = 0;
|
||||
|
||||
virtual void asAssemblerOperandLow(Context*, Assembler::Operand* result) = 0;
|
||||
|
||||
virtual void asAssemblerOperandHigh(Context*, Assembler::Operand*) { }
|
||||
virtual void asAssemblerOperand(Context*, Site*, Assembler::Operand*) = 0;
|
||||
|
||||
virtual Site* copy(Context*) = 0;
|
||||
|
||||
virtual Site* copyLow(Context*) = 0;
|
||||
|
||||
virtual Site* copyHigh(Context*) = 0;
|
||||
|
||||
Site* next;
|
||||
};
|
||||
|
||||
@ -1199,6 +1201,20 @@ release(Context* c, Resource* resource, Value* value, Site* site);
|
||||
ConstantSite*
|
||||
constantSite(Context* c, Promise* value);
|
||||
|
||||
ShiftMaskPromise*
|
||||
shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(ShiftMaskPromise)))
|
||||
ShiftMaskPromise(base, shift, mask);
|
||||
}
|
||||
|
||||
CombinedPromise*
|
||||
combinedPromise(Context* c, Promise* low, Promise* high)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(CombinedPromise)))
|
||||
CombinedPromise(low, high);
|
||||
}
|
||||
|
||||
class ConstantSite: public Site {
|
||||
public:
|
||||
ConstantSite(Promise* value): value(value) { }
|
||||
@ -1224,14 +1240,28 @@ class ConstantSite: public Site {
|
||||
return ConstantOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperandLow(Context*, Assembler::Operand* result) {
|
||||
new (result) Assembler::Constant(value);
|
||||
virtual void asAssemblerOperand(Context* c, Site* high,
|
||||
Assembler::Operand* result)
|
||||
{
|
||||
Promise* v = value;
|
||||
if (high) {
|
||||
v = combinedPromise(c, value, static_cast<ConstantSite*>(high)->value);
|
||||
}
|
||||
new (result) Assembler::Constant(v);
|
||||
}
|
||||
|
||||
virtual Site* copy(Context* c) {
|
||||
return constantSite(c, value);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
Promise* value;
|
||||
};
|
||||
|
||||
@ -1282,7 +1312,11 @@ class AddressSite: public Site {
|
||||
return AddressOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperandLow(Context*, Assembler::Operand* result) {
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
Assembler::Operand* result)
|
||||
{
|
||||
assert(c, high == 0);
|
||||
|
||||
new (result) Assembler::Address(address);
|
||||
}
|
||||
|
||||
@ -1290,6 +1324,14 @@ class AddressSite: public Site {
|
||||
return addressSite(c, address);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Promise* address;
|
||||
};
|
||||
|
||||
@ -1383,20 +1425,20 @@ class RegisterSite: public Site {
|
||||
return RegisterOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperandLow(Context* c UNUSED,
|
||||
Assembler::Operand* result)
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high,
|
||||
Assembler::Operand* result)
|
||||
{
|
||||
assert(c, number != NoRegister);
|
||||
|
||||
static_cast<Assembler::Register*>(result)->low = number;
|
||||
}
|
||||
int highNumber;
|
||||
if (high) {
|
||||
highNumber = static_cast<RegisterSite*>(high)->number;
|
||||
assert(c, highNumber != NoRegister);
|
||||
} else {
|
||||
highNumber = NoRegister;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperandHigh(Context* c UNUSED,
|
||||
Assembler::Operand* result)
|
||||
{
|
||||
assert(c, number != NoRegister);
|
||||
|
||||
static_cast<Assembler::Register*>(result)->high = number;
|
||||
new (result) Assembler::Register(number, highNumber);
|
||||
}
|
||||
|
||||
virtual Site* copy(Context* c) {
|
||||
@ -1411,6 +1453,14 @@ class RegisterSite: public Site {
|
||||
return freeRegisterSite(c, mask);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
uint32_t mask;
|
||||
int number;
|
||||
};
|
||||
@ -1537,9 +1587,16 @@ class MemorySite: public Site {
|
||||
return MemoryOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperandLow(Context* c UNUSED,
|
||||
Assembler::Operand* result)
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
Assembler::Operand* result)
|
||||
{
|
||||
assert(c, high == 0
|
||||
or (static_cast<MemorySite*>(high)->base == base
|
||||
and static_cast<MemorySite*>(high)->offset
|
||||
== static_cast<int>(offset + BytesPerWord)
|
||||
and static_cast<MemorySite*>(high)->index == index
|
||||
and static_cast<MemorySite*>(high)->scale == scale));
|
||||
|
||||
assert(c, acquired);
|
||||
|
||||
new (result) Assembler::Memory(base, offset, index, scale);
|
||||
@ -1549,6 +1606,14 @@ class MemorySite: public Site {
|
||||
return memorySite(c, base, offset, index, scale);
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
return copy(c);
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
return memorySite(c, base, offset + BytesPerWord, index, scale);
|
||||
}
|
||||
|
||||
bool acquired;
|
||||
int base;
|
||||
int offset;
|
||||
@ -1929,14 +1994,13 @@ void
|
||||
asAssemblerOperand(Context* c, Site* low, Site* high,
|
||||
Assembler::Operand* result)
|
||||
{
|
||||
low->asAssemblerOperandLow(c, result);
|
||||
if (high) {
|
||||
high->asAssemblerOperandHigh(c, result);
|
||||
}
|
||||
low->asAssemblerOperand(c, high, result);
|
||||
}
|
||||
|
||||
class OperandUnion: public Assembler::Operand {
|
||||
// must be large enough to hold any operand type:
|
||||
// must be large enough and aligned properly to hold any operand
|
||||
// type (we'd use an actual union type here, except that classes
|
||||
// with constructors cannot be used in a union):
|
||||
uintptr_t padding[4];
|
||||
};
|
||||
|
||||
@ -2217,7 +2281,7 @@ class CallEvent: public Event {
|
||||
|
||||
if (resultSize and live(result)) {
|
||||
addSite(c, result, registerSite(c, c->arch->returnLow()));
|
||||
if (resultSize > BytesPerWord) {
|
||||
if (resultSize > BytesPerWord and live(result->high)) {
|
||||
addSite(c, result->high, registerSite(c, c->arch->returnHigh()));
|
||||
}
|
||||
}
|
||||
@ -2385,6 +2449,48 @@ maybeMove(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
|
||||
}
|
||||
}
|
||||
|
||||
Value*
|
||||
value(Context* c, Site* site = 0, Site* target = 0)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
|
||||
}
|
||||
|
||||
void
|
||||
split(Context* c, Value* v)
|
||||
{
|
||||
assert(c, v->high == 0);
|
||||
|
||||
v->high = value(c);
|
||||
for (SiteIterator it(v); it.hasMore();) {
|
||||
Site* s = it.next();
|
||||
removeSite(c, v, s);
|
||||
|
||||
addSite(c, v, s->copyLow(c));
|
||||
addSite(c, v->high, s->copyHigh(c));
|
||||
|
||||
char s1[256]; s->toString(c, s1, 256);
|
||||
char s2[256]; v->sites->toString(c, s2, 256);
|
||||
char s3[256]; v->high->sites->toString(c, s3, 256);
|
||||
fprintf(stderr, "split %s into %s for %p and %s for %p\n", s1, s2, v, s3, v->high);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
maybeSplit(Context* c, Value* v)
|
||||
{
|
||||
if (v->high == 0) {
|
||||
split(c, v);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grow(Context* c, Value* v)
|
||||
{
|
||||
assert(c, v->high == 0);
|
||||
|
||||
v->high = value(c);
|
||||
}
|
||||
|
||||
class MoveEvent: public Event {
|
||||
public:
|
||||
MoveEvent(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
|
||||
@ -2396,8 +2502,13 @@ class MoveEvent: public Event {
|
||||
{
|
||||
addRead(c, this, src, read(c, srcLowMask));
|
||||
if (srcSize > BytesPerWord) {
|
||||
maybeSplit(c, src);
|
||||
addRead(c, this, src->high, read(c, srcHighMask));
|
||||
}
|
||||
|
||||
if (dstSize > BytesPerWord) {
|
||||
grow(c, dst);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
@ -2648,6 +2759,11 @@ class CombineEvent: public Event {
|
||||
if (secondSize > BytesPerWord) {
|
||||
addRead(c, this, second->high, read(c, secondHighMask));
|
||||
}
|
||||
|
||||
if (resultSize > BytesPerWord) {
|
||||
grow(c, result);
|
||||
fprintf(stderr, "grew %p into %p\n", result, result->high);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
@ -2682,7 +2798,8 @@ class CombineEvent: public Event {
|
||||
|
||||
if (live(result)) {
|
||||
addSite(c, result, low);
|
||||
if (resultSize > BytesPerWord) {
|
||||
fprintf(stderr, "result %p high %p\n", result, result->high);
|
||||
if (resultSize > BytesPerWord and live(result->high)) {
|
||||
addSite(c, result->high, high);
|
||||
}
|
||||
}
|
||||
@ -2700,12 +2817,6 @@ class CombineEvent: public Event {
|
||||
SiteMask resultHighMask;
|
||||
};
|
||||
|
||||
Value*
|
||||
value(Context* c, Site* site = 0, Site* target = 0)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
|
||||
}
|
||||
|
||||
void
|
||||
removeBuddy(Context* c, Value* v)
|
||||
{
|
||||
@ -2795,31 +2906,41 @@ stack(Context* c, Value* value, Stack* next)
|
||||
Value*
|
||||
maybeBuddy(Context* c, Value* v);
|
||||
|
||||
void
|
||||
Value*
|
||||
push(Context* c, unsigned footprint, Value* v)
|
||||
{
|
||||
assert(c, footprint);
|
||||
|
||||
Value* high;
|
||||
if (footprint > 1) {
|
||||
assert(c, footprint == 2);
|
||||
assert(c, (BytesPerWord == 8) xor (v->high != 0));
|
||||
push(c, 1, v->high);
|
||||
|
||||
if (BytesPerWord == 4 and v->high == 0) {
|
||||
split(c, v);
|
||||
}
|
||||
|
||||
high = push(c, 1, v->high);
|
||||
} else {
|
||||
high = v->high;
|
||||
}
|
||||
|
||||
if (v) {
|
||||
v = maybeBuddy(c, v);
|
||||
v->high = high;
|
||||
}
|
||||
|
||||
Stack* s = stack(c, v, c->stack);
|
||||
|
||||
if (DebugFrame) {
|
||||
fprintf(stderr, "push %p\n", v);
|
||||
fprintf(stderr, "push %p fp %d high %p\n", v, footprint, v->high);
|
||||
}
|
||||
|
||||
if (v) {
|
||||
v->home = frameIndex(c, s->index + c->localFootprint);
|
||||
}
|
||||
c->stack = s;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Value*
|
||||
@ -2831,7 +2952,7 @@ pop(Context* c, unsigned footprint)
|
||||
assert(c, s->value == 0 or s->value->home >= 0);
|
||||
|
||||
if (DebugFrame) {
|
||||
fprintf(stderr, "pop %p\n", s->value);
|
||||
fprintf(stderr, "pop %p fp %d high %p\n", s->value, footprint, s->value->high);
|
||||
}
|
||||
|
||||
c->stack = s->next;
|
||||
@ -2845,7 +2966,69 @@ pop(Context* c, unsigned footprint)
|
||||
}
|
||||
|
||||
return s->value;
|
||||
}
|
||||
|
||||
Value*
|
||||
storeLocal(Context* c, unsigned footprint, Value* v, unsigned index)
|
||||
{
|
||||
assert(c, index + footprint <= c->localFootprint);
|
||||
|
||||
Value* high;
|
||||
if (footprint > 1) {
|
||||
assert(c, footprint == 2);
|
||||
|
||||
if (BytesPerWord == 4) {
|
||||
assert(c, v->high);
|
||||
|
||||
high = storeLocal(c, 1, v->high, index);
|
||||
}
|
||||
|
||||
++ index;
|
||||
} else {
|
||||
high = v->high;
|
||||
}
|
||||
|
||||
v = maybeBuddy(c, v);
|
||||
v->high = high;
|
||||
|
||||
Local* local = c->locals + index;
|
||||
|
||||
unsigned sizeInBytes = sizeof(Local) * c->localFootprint;
|
||||
Local* newLocals = static_cast<Local*>(c->zone->allocate(sizeInBytes));
|
||||
memcpy(newLocals, c->locals, sizeInBytes);
|
||||
c->locals = newLocals;
|
||||
|
||||
local = c->locals + index;
|
||||
local->value = v;
|
||||
|
||||
if (DebugFrame) {
|
||||
fprintf(stderr, "store local %p at %d\n", local->value, index);
|
||||
}
|
||||
|
||||
local->value->home = frameIndex(c, index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Value*
|
||||
loadLocal(Context* c, unsigned footprint UNUSED, unsigned index)
|
||||
{
|
||||
assert(c, index + footprint <= c->localFootprint);
|
||||
|
||||
if (footprint > 1) {
|
||||
assert(c, footprint == 2);
|
||||
|
||||
++ index;
|
||||
}
|
||||
|
||||
assert(c, c->locals[index].value);
|
||||
assert(c, c->locals[index].value->home >= 0);
|
||||
|
||||
if (DebugFrame) {
|
||||
fprintf(stderr, "load local %p at %d\n", c->locals[index].value, index);
|
||||
}
|
||||
|
||||
return c->locals[index].value;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2878,7 +3061,9 @@ appendCombine(Context* c, TernaryOperation type,
|
||||
|
||||
appendCall
|
||||
(c, value(c, constantSite(c, c->client->getThunk(type, resultSize))),
|
||||
0, 0, result, resultSize, argumentStack, 2, 0);
|
||||
0, 0, result, resultSize, argumentStack,
|
||||
ceiling(secondSize, BytesPerWord) + ceiling(firstSize, BytesPerWord),
|
||||
0);
|
||||
} else {
|
||||
append
|
||||
(c, new (c->zone->allocate(sizeof(CombineEvent)))
|
||||
@ -2910,6 +3095,7 @@ class TranslateEvent: public Event {
|
||||
addRead(c, this, value, read(c, valueLowMask));
|
||||
if (size > BytesPerWord) {
|
||||
addRead(c, this, value->high, read(c, valueHighMask));
|
||||
grow(c, result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2940,7 +3126,7 @@ class TranslateEvent: public Event {
|
||||
|
||||
if (live(result)) {
|
||||
addSite(c, result, low);
|
||||
if (size > BytesPerWord) {
|
||||
if (size > BytesPerWord and live(result->high)) {
|
||||
addSite(c, result->high, high);
|
||||
}
|
||||
}
|
||||
@ -3028,10 +3214,22 @@ class MemoryEvent: public Event {
|
||||
popRead(c, this, index);
|
||||
}
|
||||
|
||||
result->target = memorySite
|
||||
(c, baseRegister, displacement, indexRegister, scale);
|
||||
Site* site = memorySite
|
||||
(c, baseRegister, displacement, indexRegister, scale);
|
||||
|
||||
addSite(c, result, result->target);
|
||||
result->target = site;
|
||||
if (live(result)) {
|
||||
addSite(c, result, site);
|
||||
}
|
||||
|
||||
if (result->high) {
|
||||
Site* high = site->copyHigh(c);
|
||||
|
||||
result->high->target = high;
|
||||
if (live(result->high)) {
|
||||
addSite(c, result->high, high);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Value* base;
|
||||
@ -4614,54 +4812,11 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) {
|
||||
assert(&c, index + footprint <= c.localFootprint);
|
||||
|
||||
if (footprint > 1) {
|
||||
assert(&c, footprint == 2);
|
||||
|
||||
if (BytesPerWord == 4) {
|
||||
assert(&c, static_cast<Value*>(src)->high);
|
||||
|
||||
storeLocal(1, static_cast<Value*>(src)->high, index);
|
||||
}
|
||||
|
||||
++ index;
|
||||
}
|
||||
|
||||
Local* local = c.locals + index;
|
||||
|
||||
unsigned sizeInBytes = sizeof(Local) * c.localFootprint;
|
||||
Local* newLocals = static_cast<Local*>(c.zone->allocate(sizeInBytes));
|
||||
memcpy(newLocals, c.locals, sizeInBytes);
|
||||
c.locals = newLocals;
|
||||
|
||||
local = c.locals + index;
|
||||
local->value = maybeBuddy(&c, static_cast<Value*>(src));
|
||||
|
||||
if (DebugFrame) {
|
||||
fprintf(stderr, "store local %p at %d\n", local->value, index);
|
||||
}
|
||||
|
||||
local->value->home = frameIndex(&c, index);
|
||||
::storeLocal(&c, footprint, static_cast<Value*>(src), index);
|
||||
}
|
||||
|
||||
virtual Operand* loadLocal(unsigned footprint UNUSED, unsigned index) {
|
||||
assert(&c, index + footprint <= c.localFootprint);
|
||||
|
||||
if (footprint > 1) {
|
||||
assert(&c, footprint == 2);
|
||||
|
||||
++ index;
|
||||
}
|
||||
|
||||
assert(&c, c.locals[index].value);
|
||||
assert(&c, c.locals[index].value->home >= 0);
|
||||
|
||||
if (DebugFrame) {
|
||||
fprintf(stderr, "load local %p at %d\n", c.locals[index].value, index);
|
||||
}
|
||||
|
||||
return c.locals[index].value;
|
||||
virtual Operand* loadLocal(unsigned footprint, unsigned index) {
|
||||
return ::loadLocal(&c, footprint, index);
|
||||
}
|
||||
|
||||
virtual void saveLocals() {
|
||||
|
19
src/x86.cpp
19
src/x86.cpp
@ -905,25 +905,6 @@ moveCR(Context* c, unsigned, Assembler::Constant* a,
|
||||
}
|
||||
}
|
||||
|
||||
class ShiftMaskPromise: public Promise {
|
||||
public:
|
||||
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
|
||||
base(base), shift(shift), mask(mask)
|
||||
{ }
|
||||
|
||||
virtual int64_t value() {
|
||||
return (base->value() >> shift) & mask;
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return base->resolved();
|
||||
}
|
||||
|
||||
Promise* base;
|
||||
unsigned shift;
|
||||
int64_t mask;
|
||||
};
|
||||
|
||||
ShiftMaskPromise*
|
||||
shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user