diff --git a/src/assembler.h b/src/assembler.h index 7992f7c892..ceac55c18b 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -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, diff --git a/src/compiler.cpp b/src/compiler.cpp index 0a0a088c53..88bfbaa0bc 100644 --- a/src/compiler.cpp +++ b/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(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(result)->low = number; - } + int highNumber; + if (high) { + highNumber = static_cast(high)->number; + assert(c, highNumber != NoRegister); + } else { + highNumber = NoRegister; + } - virtual void asAssemblerOperandHigh(Context* c UNUSED, - Assembler::Operand* result) - { - assert(c, number != NoRegister); - - static_cast(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(high)->base == base + and static_cast(high)->offset + == static_cast(offset + BytesPerWord) + and static_cast(high)->index == index + and static_cast(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(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(src)->high); - - storeLocal(1, static_cast(src)->high, index); - } - - ++ index; - } - - Local* local = c.locals + index; - - unsigned sizeInBytes = sizeof(Local) * c.localFootprint; - Local* newLocals = static_cast(c.zone->allocate(sizeInBytes)); - memcpy(newLocals, c.locals, sizeInBytes); - c.locals = newLocals; - - local = c.locals + index; - local->value = maybeBuddy(&c, static_cast(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(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() { diff --git a/src/x86.cpp b/src/x86.cpp index 22fb3455ef..267f865749 100644 --- a/src/x86.cpp +++ b/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) {