mirror of
https://github.com/corda/corda.git
synced 2025-03-02 20:49:06 +00:00
move Reads out of compile.cpp
This commit is contained in:
parent
b0abc4e1e5
commit
6d265374ec
1
makefile
1
makefile
@ -958,6 +958,7 @@ ifeq ($(process),compile)
|
||||
$(src)/codegen/compiler/site.cpp \
|
||||
$(src)/codegen/compiler/regalloc.cpp \
|
||||
$(src)/codegen/compiler/value.cpp \
|
||||
$(src)/codegen/compiler/read.cpp \
|
||||
$(src)/codegen/registers.cpp \
|
||||
$(src)/codegen/targets.cpp
|
||||
|
||||
|
@ -45,11 +45,6 @@ const unsigned StealRegisterReserveCount = 2;
|
||||
const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4);
|
||||
|
||||
class Stack;
|
||||
class Site;
|
||||
class ConstantSite;
|
||||
class AddressSite;
|
||||
class RegisterSite;
|
||||
class MemorySite;
|
||||
class Event;
|
||||
class PushEvent;
|
||||
class Read;
|
||||
@ -73,14 +68,6 @@ apply(Context* c, lir::TernaryOperation op,
|
||||
unsigned s2Size, Site* s2Low, Site* s2High,
|
||||
unsigned s3Size, Site* s3Low, Site* s3High);
|
||||
|
||||
class Cell {
|
||||
public:
|
||||
Cell(Cell* next, void* value): next(next), value(value) { }
|
||||
|
||||
Cell* next;
|
||||
void* value;
|
||||
};
|
||||
|
||||
class Local {
|
||||
public:
|
||||
Value* value;
|
||||
@ -106,7 +93,7 @@ class ForkElement {
|
||||
|
||||
class ForkState: public Compiler::State {
|
||||
public:
|
||||
ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor,
|
||||
ForkState(Stack* stack, Local* locals, Cell<Value>* saved, Event* predecessor,
|
||||
unsigned logicalIp):
|
||||
stack(stack),
|
||||
locals(locals),
|
||||
@ -118,7 +105,7 @@ class ForkState: public Compiler::State {
|
||||
|
||||
Stack* stack;
|
||||
Local* locals;
|
||||
Cell* saved;
|
||||
Cell<Value>* saved;
|
||||
Event* predecessor;
|
||||
unsigned logicalIp;
|
||||
unsigned readCount;
|
||||
@ -157,23 +144,6 @@ class ConstantPoolNode {
|
||||
ConstantPoolNode* next;
|
||||
};
|
||||
|
||||
int
|
||||
intersectFrameIndexes(int a, int b)
|
||||
{
|
||||
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
|
||||
if (a == AnyFrameIndex) return b;
|
||||
if (b == AnyFrameIndex) return a;
|
||||
if (a == b) return a;
|
||||
return NoFrameIndex;
|
||||
}
|
||||
|
||||
SiteMask
|
||||
intersect(const SiteMask& a, const SiteMask& b)
|
||||
{
|
||||
return SiteMask(a.typeMask & b.typeMask, a.registerMask & b.registerMask,
|
||||
intersectFrameIndexes(a.frameIndex, b.frameIndex));
|
||||
}
|
||||
|
||||
class PoolPromise: public Promise {
|
||||
public:
|
||||
PoolPromise(Context* c, int key): c(c), key(key) { }
|
||||
@ -254,29 +224,11 @@ class IpPromise: public Promise {
|
||||
int logicalIp;
|
||||
};
|
||||
|
||||
unsigned
|
||||
count(Cell* c)
|
||||
{
|
||||
unsigned count = 0;
|
||||
while (c) {
|
||||
++ count;
|
||||
c = c->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Cell*
|
||||
cons(Context* c, void* value, Cell* next)
|
||||
{
|
||||
return new (c->zone) Cell(next, value);
|
||||
}
|
||||
|
||||
Cell*
|
||||
reverseDestroy(Cell* cell)
|
||||
{
|
||||
Cell* previous = 0;
|
||||
template<class T>
|
||||
Cell<T>* reverseDestroy(Cell<T>* cell) {
|
||||
Cell<T>* previous = 0;
|
||||
while (cell) {
|
||||
Cell* next = cell->next;
|
||||
Cell<T>* next = cell->next;
|
||||
cell->next = previous;
|
||||
previous = cell;
|
||||
cell = next;
|
||||
@ -377,7 +329,7 @@ class Event {
|
||||
Snapshot* snapshots;
|
||||
Link* predecessors;
|
||||
Link* successors;
|
||||
Cell* visitLinks;
|
||||
Cell<Link>* visitLinks;
|
||||
Block* block;
|
||||
LogicalInstruction* logicalInstruction;
|
||||
unsigned readCount;
|
||||
@ -759,254 +711,6 @@ Promise* resolved(Context* c, int64_t value) {
|
||||
return new(c->zone) ResolvedPromise(value);
|
||||
}
|
||||
|
||||
MemorySite*
|
||||
memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister,
|
||||
unsigned scale = 1);
|
||||
|
||||
class MemorySite: public Site {
|
||||
public:
|
||||
MemorySite(int base, int offset, int index, unsigned scale):
|
||||
acquired(false), base(base), offset(offset), index(index), scale(scale)
|
||||
{ }
|
||||
|
||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
||||
if (acquired) {
|
||||
return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
|
||||
base, offset, index, scale);
|
||||
} else {
|
||||
return vm::snprintf(buffer, bufferSize, "memory unacquired");
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned copyCost(Context* c, Site* s) {
|
||||
assert(c, acquired);
|
||||
|
||||
if (s and
|
||||
(this == s or
|
||||
(s->type(c) == lir::MemoryOperand
|
||||
and static_cast<MemorySite*>(s)->base == base
|
||||
and static_cast<MemorySite*>(s)->offset == offset
|
||||
and static_cast<MemorySite*>(s)->index == index
|
||||
and static_cast<MemorySite*>(s)->scale == scale)))
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
return MemoryCopyCost;
|
||||
}
|
||||
}
|
||||
|
||||
bool conflicts(const SiteMask& mask) {
|
||||
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
|
||||
and (((1 << base) & mask.registerMask) == 0
|
||||
or (index != lir::NoRegister
|
||||
and ((1 << index) & mask.registerMask) == 0));
|
||||
}
|
||||
|
||||
virtual bool match(Context* c, const SiteMask& mask) {
|
||||
assert(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (mask.frameIndex >= 0) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
return static_cast<int>(frameIndexToOffset(c, mask.frameIndex))
|
||||
== offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool loneMatch(Context* c, const SiteMask& mask) {
|
||||
assert(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
|
||||
if (mask.frameIndex == AnyFrameIndex) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool matchNextWord(Context* c, Site* s, unsigned index) {
|
||||
if (s->type(c) == lir::MemoryOperand) {
|
||||
MemorySite* ms = static_cast<MemorySite*>(s);
|
||||
return ms->base == this->base
|
||||
and ((index == 1 and ms->offset == static_cast<int>
|
||||
(this->offset + TargetBytesPerWord))
|
||||
or (index == 0 and this->offset == static_cast<int>
|
||||
(ms->offset + TargetBytesPerWord)))
|
||||
and ms->index == this->index
|
||||
and ms->scale == this->scale;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void acquire(Context* c, Value* v) {
|
||||
c->registerResources[base].increment(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].increment(c);
|
||||
}
|
||||
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assert
|
||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::acquire
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
acquired = true;
|
||||
}
|
||||
|
||||
virtual void release(Context* c, Value* v) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assert
|
||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::release
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
c->registerResources[base].decrement(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].decrement(c);
|
||||
}
|
||||
|
||||
acquired = false;
|
||||
}
|
||||
|
||||
virtual void freeze(Context* c, Value* v) {
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
|
||||
} else {
|
||||
c->registerResources[base].increment(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].increment(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void thaw(Context* c, Value* v) {
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
|
||||
} else {
|
||||
c->registerResources[base].decrement(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].decrement(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool frozen(Context* c) {
|
||||
return base == c->arch->stack()
|
||||
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
|
||||
}
|
||||
|
||||
virtual lir::OperandType type(Context*) {
|
||||
return lir::MemoryOperand;
|
||||
}
|
||||
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
lir::Operand* result)
|
||||
{
|
||||
// todo: endianness?
|
||||
assert(c, high == this
|
||||
or (static_cast<MemorySite*>(high)->base == base
|
||||
and static_cast<MemorySite*>(high)->offset
|
||||
== static_cast<int>(offset + TargetBytesPerWord)
|
||||
and static_cast<MemorySite*>(high)->index == index
|
||||
and static_cast<MemorySite*>(high)->scale == scale));
|
||||
|
||||
assert(c, acquired);
|
||||
|
||||
new (result) lir::Memory(base, offset, index, scale);
|
||||
}
|
||||
|
||||
virtual Site* copy(Context* c) {
|
||||
return memorySite(c, base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* copyHalf(Context* c, bool add) {
|
||||
if (add) {
|
||||
return memorySite(c, base, offset + TargetBytesPerWord, index, scale);
|
||||
} else {
|
||||
return copy(c);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Site* copyLow(Context* c) {
|
||||
return copyHalf(c, c->arch->bigEndian());
|
||||
}
|
||||
|
||||
virtual Site* copyHigh(Context* c) {
|
||||
return copyHalf(c, not c->arch->bigEndian());
|
||||
}
|
||||
|
||||
virtual Site* makeNextWord(Context* c, unsigned index) {
|
||||
return memorySite
|
||||
(c, base, offset + ((index == 1) xor c->arch->bigEndian()
|
||||
? TargetBytesPerWord : -TargetBytesPerWord),
|
||||
this->index, scale);
|
||||
}
|
||||
|
||||
virtual SiteMask mask(Context* c) {
|
||||
return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack())
|
||||
? static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
: NoFrameIndex);
|
||||
}
|
||||
|
||||
virtual SiteMask nextWordMask(Context* c, unsigned index) {
|
||||
int frameIndex;
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, this->index == lir::NoRegister);
|
||||
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
|
||||
} else {
|
||||
frameIndex = NoFrameIndex;
|
||||
}
|
||||
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
||||
}
|
||||
|
||||
virtual bool isVolatile(Context* c) {
|
||||
return base != c->arch->stack();
|
||||
}
|
||||
|
||||
bool acquired;
|
||||
int base;
|
||||
int offset;
|
||||
int index;
|
||||
unsigned scale;
|
||||
};
|
||||
|
||||
MemorySite*
|
||||
memorySite(Context* c, int base, int offset, int index, unsigned scale)
|
||||
{
|
||||
return new(c->zone) MemorySite(base, offset, index, scale);
|
||||
}
|
||||
|
||||
MemorySite*
|
||||
frameSite(Context* c, int frameIndex)
|
||||
{
|
||||
assert(c, frameIndex >= 0);
|
||||
return memorySite
|
||||
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0);
|
||||
}
|
||||
|
||||
void
|
||||
move(Context* c, Value* value, Site* src, Site* dst);
|
||||
|
||||
@ -1073,45 +777,6 @@ pickTargetSite(Context* c, Read* read, bool intersectRead = false,
|
||||
}
|
||||
}
|
||||
|
||||
class SingleRead: public Read {
|
||||
public:
|
||||
SingleRead(const SiteMask& mask, Value* successor):
|
||||
next_(0), mask(mask), high_(0), successor_(successor)
|
||||
{ }
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned) {
|
||||
*mask = compiler::intersect(*mask, this->mask);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual Value* high(Context*) {
|
||||
return high_;
|
||||
}
|
||||
|
||||
virtual Value* successor() {
|
||||
return successor_;
|
||||
}
|
||||
|
||||
virtual bool valid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void append(Context* c UNUSED, Read* r) {
|
||||
assert(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
virtual Read* next(Context*) {
|
||||
return next_;
|
||||
}
|
||||
|
||||
Read* next_;
|
||||
SiteMask mask;
|
||||
Value* high_;
|
||||
Value* successor_;
|
||||
};
|
||||
|
||||
SingleRead*
|
||||
read(Context* c, const SiteMask& mask, Value* successor = 0)
|
||||
{
|
||||
@ -1137,7 +802,7 @@ pickSourceSite(Context* c, Read* read, Site* target = 0,
|
||||
SiteMask mask;
|
||||
|
||||
if (extraMask) {
|
||||
mask = intersect(mask, *extraMask);
|
||||
mask = mask.intersectionWith(*extraMask);
|
||||
}
|
||||
|
||||
if (intersectRead) {
|
||||
@ -1368,104 +1033,6 @@ fixedRegisterMask(int number)
|
||||
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
||||
}
|
||||
|
||||
class MultiRead: public Read {
|
||||
public:
|
||||
MultiRead():
|
||||
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||
{ }
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned depth) {
|
||||
if (depth > 0) {
|
||||
// short-circuit recursion to avoid poor performance in
|
||||
// deeply-nested branches
|
||||
return reads != 0;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
for (Cell** cell = &reads; *cell;) {
|
||||
Read* r = static_cast<Read*>((*cell)->value);
|
||||
bool valid = r->intersect(mask, depth + 1);
|
||||
if (valid) {
|
||||
result = true;
|
||||
cell = &((*cell)->next);
|
||||
} else {
|
||||
*cell = (*cell)->next;
|
||||
}
|
||||
}
|
||||
visited = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual Value* successor() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool valid() {
|
||||
bool result = false;
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
for (Cell** cell = &reads; *cell;) {
|
||||
Read* r = static_cast<Read*>((*cell)->value);
|
||||
if (r->valid()) {
|
||||
result = true;
|
||||
cell = &((*cell)->next);
|
||||
} else {
|
||||
*cell = (*cell)->next;
|
||||
}
|
||||
}
|
||||
visited = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void append(Context* c, Read* r) {
|
||||
Cell* cell = cons(c, r, 0);
|
||||
if (lastRead == 0) {
|
||||
reads = cell;
|
||||
} else {
|
||||
lastRead->next = cell;
|
||||
}
|
||||
lastRead = cell;
|
||||
|
||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||
|
||||
lastTarget->value = r;
|
||||
}
|
||||
|
||||
virtual Read* next(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
void allocateTarget(Context* c) {
|
||||
Cell* cell = cons(c, 0, 0);
|
||||
|
||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||
|
||||
if (lastTarget) {
|
||||
lastTarget->next = cell;
|
||||
} else {
|
||||
firstTarget = cell;
|
||||
}
|
||||
lastTarget = cell;
|
||||
}
|
||||
|
||||
Read* nextTarget() {
|
||||
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
||||
|
||||
Read* r = static_cast<Read*>(firstTarget->value);
|
||||
firstTarget = firstTarget->next;
|
||||
return r;
|
||||
}
|
||||
|
||||
Cell* reads;
|
||||
Cell* lastRead;
|
||||
Cell* firstTarget;
|
||||
Cell* lastTarget;
|
||||
bool visited;
|
||||
};
|
||||
|
||||
MultiRead*
|
||||
multiRead(Context* c)
|
||||
@ -1473,49 +1040,6 @@ multiRead(Context* c)
|
||||
return new(c->zone) MultiRead;
|
||||
}
|
||||
|
||||
class StubRead: public Read {
|
||||
public:
|
||||
StubRead():
|
||||
next_(0), read(0), visited(false), valid_(true)
|
||||
{ }
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned depth) {
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
if (read) {
|
||||
bool valid = read->intersect(mask, depth);
|
||||
if (not valid) {
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
visited = false;
|
||||
}
|
||||
return valid_;
|
||||
}
|
||||
|
||||
virtual Value* successor() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool valid() {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
virtual void append(Context* c UNUSED, Read* r) {
|
||||
assert(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
virtual Read* next(Context*) {
|
||||
return next_;
|
||||
}
|
||||
|
||||
Read* next_;
|
||||
Read* read;
|
||||
bool visited;
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
StubRead*
|
||||
stubRead(Context* c)
|
||||
{
|
||||
@ -2385,7 +1909,7 @@ pickMatchOrMove(Context* c, Read* r, Site* nextWord, unsigned index,
|
||||
}
|
||||
|
||||
return pickSiteOrMove
|
||||
(c, r->value, intersect(mask, nextWord->nextWordMask(c, index)),
|
||||
(c, r->value, mask.intersectionWith(nextWord->nextWordMask(c, index)),
|
||||
true, true);
|
||||
}
|
||||
|
||||
@ -4257,9 +3781,8 @@ captureBranchSnapshots(Context* c, Event* e)
|
||||
e->snapshots = makeSnapshots(c, el.value, e->snapshots);
|
||||
}
|
||||
|
||||
for (Cell* sv = e->successors->forkState->saved; sv; sv = sv->next) {
|
||||
e->snapshots = makeSnapshots
|
||||
(c, static_cast<Value*>(sv->value), e->snapshots);
|
||||
for (Cell<Value>* sv = e->successors->forkState->saved; sv; sv = sv->next) {
|
||||
e->snapshots = makeSnapshots(c, sv->value, e->snapshots);
|
||||
}
|
||||
|
||||
if (DebugControl) {
|
||||
@ -4577,9 +4100,8 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset)
|
||||
}
|
||||
|
||||
if (e->visitLinks) {
|
||||
for (Cell* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next)
|
||||
{
|
||||
visit(c, static_cast<Link*>(cell->value));
|
||||
for (Cell<Link>* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next) {
|
||||
visit(c, cell->value);
|
||||
}
|
||||
e->visitLinks = 0;
|
||||
}
|
||||
@ -4666,8 +4188,8 @@ saveState(Context* c)
|
||||
addForkElement(c, e.value, state, count++);
|
||||
}
|
||||
|
||||
for (Cell* sv = c->saved; sv; sv = sv->next) {
|
||||
addForkElement(c, static_cast<Value*>(sv->value), state, count++);
|
||||
for (Cell<Value>* sv = c->saved; sv; sv = sv->next) {
|
||||
addForkElement(c, sv->value, state, count++);
|
||||
}
|
||||
|
||||
state->readCount = count;
|
||||
|
@ -22,7 +22,6 @@ namespace compiler {
|
||||
|
||||
class Stack;
|
||||
class Local;
|
||||
class Cell;
|
||||
class Event;
|
||||
class LogicalInstruction;
|
||||
|
||||
@ -36,6 +35,25 @@ class ForkState;
|
||||
class MySubroutine;
|
||||
class Block;
|
||||
|
||||
template<class T>
|
||||
class Cell {
|
||||
public:
|
||||
Cell(Cell<T>* next, T* value): next(next), value(value) { }
|
||||
|
||||
Cell<T>* next;
|
||||
T* value;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
unsigned count(Cell<T>* c) {
|
||||
unsigned count = 0;
|
||||
while (c) {
|
||||
++ count;
|
||||
c = c->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
||||
@ -48,7 +66,7 @@ class Context {
|
||||
Compiler::Client* client;
|
||||
Stack* stack;
|
||||
Local* locals;
|
||||
Cell* saved;
|
||||
Cell<Value>* saved;
|
||||
Event* predecessor;
|
||||
LogicalInstruction** logicalCode;
|
||||
const RegisterFile* regFile;
|
||||
@ -78,6 +96,11 @@ inline Aborter* getAborter(Context* c) {
|
||||
return c->system;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Cell<T>* cons(Context* c, T* value, Cell<T>* next) {
|
||||
return new (c->zone) Cell<T>(next, value);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
183
src/codegen/compiler/read.cpp
Normal file
183
src/codegen/compiler/read.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/* Copyright (c) 2008-2012, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "target.h"
|
||||
|
||||
#include "codegen/compiler/context.h"
|
||||
#include "codegen/compiler/value.h"
|
||||
#include "codegen/compiler/site.h"
|
||||
#include "codegen/compiler/resource.h"
|
||||
#include "codegen/compiler/read.h"
|
||||
|
||||
namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
|
||||
SingleRead::SingleRead(const SiteMask& mask, Value* successor):
|
||||
next_(0), mask(mask), high_(0), successor_(successor)
|
||||
{ }
|
||||
|
||||
bool SingleRead::intersect(SiteMask* mask, unsigned) {
|
||||
*mask = mask->intersectionWith(this->mask);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Value* SingleRead::high(Context*) {
|
||||
return high_;
|
||||
}
|
||||
|
||||
Value* SingleRead::successor() {
|
||||
return successor_;
|
||||
}
|
||||
|
||||
bool SingleRead::valid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SingleRead::append(Context* c UNUSED, Read* r) {
|
||||
assert(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
Read* SingleRead::next(Context*) {
|
||||
return next_;
|
||||
}
|
||||
|
||||
MultiRead::MultiRead():
|
||||
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
|
||||
{ }
|
||||
|
||||
bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
if (depth > 0) {
|
||||
// short-circuit recursion to avoid poor performance in
|
||||
// deeply-nested branches
|
||||
return reads != 0;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
for (Cell<Read>** cell = &reads; *cell;) {
|
||||
Read* r = (*cell)->value;
|
||||
bool valid = r->intersect(mask, depth + 1);
|
||||
if (valid) {
|
||||
result = true;
|
||||
cell = &((*cell)->next);
|
||||
} else {
|
||||
*cell = (*cell)->next;
|
||||
}
|
||||
}
|
||||
visited = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Value* MultiRead::successor() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MultiRead::valid() {
|
||||
bool result = false;
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
for (Cell<Read>** cell = &reads; *cell;) {
|
||||
Read* r = (*cell)->value;
|
||||
if (r->valid()) {
|
||||
result = true;
|
||||
cell = &((*cell)->next);
|
||||
} else {
|
||||
*cell = (*cell)->next;
|
||||
}
|
||||
}
|
||||
visited = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MultiRead::append(Context* c, Read* r) {
|
||||
Cell<Read>* cell = cons<Read>(c, r, 0);
|
||||
if (lastRead == 0) {
|
||||
reads = cell;
|
||||
} else {
|
||||
lastRead->next = cell;
|
||||
}
|
||||
lastRead = cell;
|
||||
|
||||
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
|
||||
|
||||
lastTarget->value = r;
|
||||
}
|
||||
|
||||
Read* MultiRead::next(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
void MultiRead::allocateTarget(Context* c) {
|
||||
Cell<Read>* cell = cons<Read>(c, 0, 0);
|
||||
|
||||
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
|
||||
|
||||
if (lastTarget) {
|
||||
lastTarget->next = cell;
|
||||
} else {
|
||||
firstTarget = cell;
|
||||
}
|
||||
lastTarget = cell;
|
||||
}
|
||||
|
||||
Read* MultiRead::nextTarget() {
|
||||
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
|
||||
|
||||
Read* r = firstTarget->value;
|
||||
firstTarget = firstTarget->next;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
StubRead::StubRead():
|
||||
next_(0), read(0), visited(false), valid_(true)
|
||||
{ }
|
||||
|
||||
bool StubRead::intersect(SiteMask* mask, unsigned depth) {
|
||||
if (not visited) {
|
||||
visited = true;
|
||||
if (read) {
|
||||
bool valid = read->intersect(mask, depth);
|
||||
if (not valid) {
|
||||
read = 0;
|
||||
}
|
||||
}
|
||||
visited = false;
|
||||
}
|
||||
return valid_;
|
||||
}
|
||||
|
||||
Value* StubRead::successor() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool StubRead::valid() {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
void StubRead::append(Context* c UNUSED, Read* r) {
|
||||
assert(c, next_ == 0);
|
||||
next_ = r;
|
||||
}
|
||||
|
||||
Read* StubRead::next(Context*) {
|
||||
return next_;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
@ -15,6 +15,11 @@ namespace avian {
|
||||
namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
class Context;
|
||||
class SiteMask;
|
||||
class Value;
|
||||
class Event;
|
||||
|
||||
class Read {
|
||||
public:
|
||||
Read():
|
||||
@ -38,6 +43,74 @@ class Read {
|
||||
Read* eventNext;
|
||||
};
|
||||
|
||||
class SingleRead: public Read {
|
||||
public:
|
||||
SingleRead(const SiteMask& mask, Value* successor);
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned);
|
||||
|
||||
virtual Value* high(Context*);
|
||||
|
||||
virtual Value* successor();
|
||||
|
||||
virtual bool valid();
|
||||
|
||||
virtual void append(Context* c UNUSED, Read* r);
|
||||
|
||||
virtual Read* next(Context*);
|
||||
|
||||
Read* next_;
|
||||
SiteMask mask;
|
||||
Value* high_;
|
||||
Value* successor_;
|
||||
};
|
||||
|
||||
|
||||
class MultiRead: public Read {
|
||||
public:
|
||||
MultiRead();
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned depth);
|
||||
|
||||
virtual Value* successor();
|
||||
|
||||
virtual bool valid();
|
||||
|
||||
virtual void append(Context* c, Read* r);
|
||||
|
||||
virtual Read* next(Context* c);
|
||||
|
||||
void allocateTarget(Context* c);
|
||||
|
||||
Read* nextTarget();
|
||||
|
||||
Cell<Read>* reads;
|
||||
Cell<Read>* lastRead;
|
||||
Cell<Read>* firstTarget;
|
||||
Cell<Read>* lastTarget;
|
||||
bool visited;
|
||||
};
|
||||
|
||||
class StubRead: public Read {
|
||||
public:
|
||||
StubRead();
|
||||
|
||||
virtual bool intersect(SiteMask* mask, unsigned depth);
|
||||
|
||||
virtual Value* successor();
|
||||
|
||||
virtual bool valid();
|
||||
|
||||
virtual void append(Context* c UNUSED, Read* r);
|
||||
|
||||
virtual Read* next(Context*);
|
||||
|
||||
Read* next_;
|
||||
Read* read;
|
||||
bool visited;
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
|
@ -20,8 +20,27 @@ namespace codegen {
|
||||
namespace compiler {
|
||||
|
||||
|
||||
unsigned frameIndexToOffset(Context* c, unsigned frameIndex);
|
||||
|
||||
unsigned offsetToFrameIndex(Context* c, unsigned offset);
|
||||
|
||||
ResolvedPromise* resolved(Context* c, int64_t value);
|
||||
|
||||
|
||||
int intersectFrameIndexes(int a, int b) {
|
||||
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
|
||||
if (a == AnyFrameIndex) return b;
|
||||
if (b == AnyFrameIndex) return a;
|
||||
if (a == b) return a;
|
||||
return NoFrameIndex;
|
||||
}
|
||||
|
||||
|
||||
SiteMask SiteMask::intersectionWith(const SiteMask& b) {
|
||||
return SiteMask(typeMask & b.typeMask, registerMask & b.registerMask,
|
||||
intersectFrameIndexes(frameIndex, b.frameIndex));
|
||||
}
|
||||
|
||||
SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
|
||||
bool includeNextWord):
|
||||
c(c),
|
||||
@ -370,6 +389,238 @@ Site* freeRegisterSite(Context* c, uint32_t mask) {
|
||||
return new(c->zone) RegisterSite(mask, lir::NoRegister);
|
||||
}
|
||||
|
||||
MemorySite::MemorySite(int base, int offset, int index, unsigned scale):
|
||||
acquired(false), base(base), offset(offset), index(index), scale(scale)
|
||||
{ }
|
||||
|
||||
unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize) {
|
||||
if (acquired) {
|
||||
return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
|
||||
base, offset, index, scale);
|
||||
} else {
|
||||
return vm::snprintf(buffer, bufferSize, "memory unacquired");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned MemorySite::copyCost(Context* c, Site* s) {
|
||||
assert(c, acquired);
|
||||
|
||||
if (s and
|
||||
(this == s or
|
||||
(s->type(c) == lir::MemoryOperand
|
||||
and static_cast<MemorySite*>(s)->base == base
|
||||
and static_cast<MemorySite*>(s)->offset == offset
|
||||
and static_cast<MemorySite*>(s)->index == index
|
||||
and static_cast<MemorySite*>(s)->scale == scale)))
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
return MemoryCopyCost;
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::conflicts(const SiteMask& mask) {
|
||||
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
|
||||
and (((1 << base) & mask.registerMask) == 0
|
||||
or (index != lir::NoRegister
|
||||
and ((1 << index) & mask.registerMask) == 0));
|
||||
}
|
||||
|
||||
bool MemorySite::match(Context* c, const SiteMask& mask) {
|
||||
assert(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (mask.frameIndex >= 0) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
return static_cast<int>(frameIndexToOffset(c, mask.frameIndex))
|
||||
== offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
|
||||
assert(c, acquired);
|
||||
|
||||
if (mask.typeMask & (1 << lir::MemoryOperand)) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
|
||||
if (mask.frameIndex == AnyFrameIndex) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
|
||||
if (s->type(c) == lir::MemoryOperand) {
|
||||
MemorySite* ms = static_cast<MemorySite*>(s);
|
||||
return ms->base == this->base
|
||||
and ((index == 1 and ms->offset == static_cast<int>
|
||||
(this->offset + vm::TargetBytesPerWord))
|
||||
or (index == 0 and this->offset == static_cast<int>
|
||||
(ms->offset + vm::TargetBytesPerWord)))
|
||||
and ms->index == this->index
|
||||
and ms->scale == this->scale;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySite::acquire(Context* c, Value* v) {
|
||||
c->registerResources[base].increment(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].increment(c);
|
||||
}
|
||||
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assert
|
||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::acquire
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
acquired = true;
|
||||
}
|
||||
|
||||
void MemorySite::release(Context* c, Value* v) {
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, index == lir::NoRegister);
|
||||
assert
|
||||
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
|
||||
|
||||
compiler::release
|
||||
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
|
||||
}
|
||||
|
||||
c->registerResources[base].decrement(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].decrement(c);
|
||||
}
|
||||
|
||||
acquired = false;
|
||||
}
|
||||
|
||||
void MemorySite::freeze(Context* c, Value* v) {
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
|
||||
} else {
|
||||
c->registerResources[base].increment(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].increment(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySite::thaw(Context* c, Value* v) {
|
||||
if (base == c->arch->stack()) {
|
||||
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
|
||||
} else {
|
||||
c->registerResources[base].decrement(c);
|
||||
if (index != lir::NoRegister) {
|
||||
c->registerResources[index].decrement(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MemorySite::frozen(Context* c) {
|
||||
return base == c->arch->stack()
|
||||
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
|
||||
}
|
||||
|
||||
lir::OperandType MemorySite::type(Context*) {
|
||||
return lir::MemoryOperand;
|
||||
}
|
||||
|
||||
void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
lir::Operand* result)
|
||||
{
|
||||
// todo: endianness?
|
||||
assert(c, high == this
|
||||
or (static_cast<MemorySite*>(high)->base == base
|
||||
and static_cast<MemorySite*>(high)->offset
|
||||
== static_cast<int>(offset + vm::TargetBytesPerWord)
|
||||
and static_cast<MemorySite*>(high)->index == index
|
||||
and static_cast<MemorySite*>(high)->scale == scale));
|
||||
|
||||
assert(c, acquired);
|
||||
|
||||
new (result) lir::Memory(base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* MemorySite::copy(Context* c) {
|
||||
return memorySite(c, base, offset, index, scale);
|
||||
}
|
||||
|
||||
Site* MemorySite::copyHalf(Context* c, bool add) {
|
||||
if (add) {
|
||||
return memorySite(c, base, offset + vm::TargetBytesPerWord, index, scale);
|
||||
} else {
|
||||
return copy(c);
|
||||
}
|
||||
}
|
||||
|
||||
Site* MemorySite::copyLow(Context* c) {
|
||||
return copyHalf(c, c->arch->bigEndian());
|
||||
}
|
||||
|
||||
Site* MemorySite::copyHigh(Context* c) {
|
||||
return copyHalf(c, not c->arch->bigEndian());
|
||||
}
|
||||
|
||||
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
|
||||
return memorySite
|
||||
(c, base, offset + ((index == 1) xor c->arch->bigEndian()
|
||||
? vm::TargetBytesPerWord : -vm::TargetBytesPerWord),
|
||||
this->index, scale);
|
||||
}
|
||||
|
||||
SiteMask MemorySite::mask(Context* c) {
|
||||
return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack())
|
||||
? static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
: NoFrameIndex);
|
||||
}
|
||||
|
||||
SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
|
||||
int frameIndex;
|
||||
if (base == c->arch->stack()) {
|
||||
assert(c, this->index == lir::NoRegister);
|
||||
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
|
||||
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
|
||||
} else {
|
||||
frameIndex = NoFrameIndex;
|
||||
}
|
||||
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
||||
}
|
||||
|
||||
bool MemorySite::isVolatile(Context* c) {
|
||||
return base != c->arch->stack();
|
||||
}
|
||||
|
||||
|
||||
MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) {
|
||||
return new(c->zone) MemorySite(base, offset, index, scale);
|
||||
}
|
||||
|
||||
MemorySite* frameSite(Context* c, int frameIndex) {
|
||||
assert(c, frameIndex >= 0);
|
||||
return memorySite
|
||||
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
} // namespace avian
|
||||
|
@ -34,6 +34,8 @@ class SiteMask {
|
||||
typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
|
||||
{ }
|
||||
|
||||
SiteMask intersectionWith(const SiteMask& b);
|
||||
|
||||
uint8_t typeMask;
|
||||
uint32_t registerMask;
|
||||
int frameIndex;
|
||||
@ -240,6 +242,64 @@ class RegisterSite: public Site {
|
||||
Site* registerSite(Context* c, int number);
|
||||
Site* freeRegisterSite(Context* c, uint32_t mask);
|
||||
|
||||
|
||||
class MemorySite: public Site {
|
||||
public:
|
||||
MemorySite(int base, int offset, int index, unsigned scale);
|
||||
|
||||
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize);
|
||||
|
||||
virtual unsigned copyCost(Context* c, Site* s);
|
||||
|
||||
bool conflicts(const SiteMask& mask);
|
||||
|
||||
virtual bool match(Context* c, const SiteMask& mask);
|
||||
|
||||
virtual bool loneMatch(Context* c, const SiteMask& mask);
|
||||
|
||||
virtual bool matchNextWord(Context* c, Site* s, unsigned index);
|
||||
|
||||
virtual void acquire(Context* c, Value* v);
|
||||
|
||||
virtual void release(Context* c, Value* v);
|
||||
|
||||
virtual void freeze(Context* c, Value* v);
|
||||
|
||||
virtual void thaw(Context* c, Value* v);
|
||||
|
||||
virtual bool frozen(Context* c);
|
||||
|
||||
virtual lir::OperandType type(Context*);
|
||||
|
||||
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
|
||||
lir::Operand* result);
|
||||
|
||||
virtual Site* copy(Context* c);
|
||||
|
||||
Site* copyHalf(Context* c, bool add);
|
||||
|
||||
virtual Site* copyLow(Context* c);
|
||||
|
||||
virtual Site* copyHigh(Context* c);
|
||||
|
||||
virtual Site* makeNextWord(Context* c, unsigned index);
|
||||
|
||||
virtual SiteMask mask(Context* c);
|
||||
|
||||
virtual SiteMask nextWordMask(Context* c, unsigned index);
|
||||
|
||||
virtual bool isVolatile(Context* c);
|
||||
|
||||
bool acquired;
|
||||
int base;
|
||||
int offset;
|
||||
int index;
|
||||
unsigned scale;
|
||||
};
|
||||
|
||||
MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1);
|
||||
MemorySite* frameSite(Context* c, int frameIndex);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
Loading…
x
Reference in New Issue
Block a user