corda/src/compiler.cpp

4921 lines
116 KiB
C++
Raw Normal View History

/* Copyright (c) 2008, 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 "compiler.h"
2008-02-11 17:21:41 +00:00
#include "assembler.h"
2007-12-08 23:22:13 +00:00
using namespace vm;
namespace {
const bool DebugAppend = false;
const bool DebugCompile = false;
2008-11-02 22:25:51 +00:00
const bool DebugRegisters = false;
const bool DebugFrameIndexes = false;
2008-11-02 22:25:51 +00:00
const bool DebugFrame = false;
const bool DebugControl = false;
const bool DebugReads = false;
2008-12-12 01:09:36 +00:00
const bool DebugSites = false;
const bool DebugMoves = false;
2008-04-19 21:52:45 +00:00
const int AnyFrameIndex = -2;
const int NoFrameIndex = -1;
2008-02-11 17:21:41 +00:00
class Context;
class Value;
2008-04-17 22:07:32 +00:00
class Stack;
class Site;
class ConstantSite;
class AddressSite;
class RegisterSite;
class MemorySite;
2008-04-17 22:07:32 +00:00
class Event;
2008-04-18 03:47:42 +00:00
class PushEvent;
2008-04-18 00:39:41 +00:00
class Read;
class MultiRead;
2008-09-22 14:28:18 +00:00
class StubRead;
2008-08-30 20:12:27 +00:00
class Block;
2008-11-01 22:16:18 +00:00
class Snapshot;
2007-12-09 22:45:43 +00:00
void NO_RETURN abort(Context*);
2008-03-15 23:54:20 +00:00
2008-04-17 22:07:32 +00:00
void
2008-08-16 17:45:36 +00:00
apply(Context* c, UnaryOperation op,
unsigned s1Size, Site* s1);
2008-04-17 22:07:32 +00:00
void
2008-08-16 17:45:36 +00:00
apply(Context* c, BinaryOperation op,
unsigned s1Size, Site* s1,
unsigned s2Size, Site* s2);
void
apply(Context* c, TernaryOperation op,
unsigned s1Size, Site* s1,
unsigned s2Size, Site* s2,
unsigned s3Size, Site* s3);
2008-04-17 22:07:32 +00:00
enum ConstantCompare {
CompareNone,
CompareLess,
CompareGreater,
CompareEqual
};
class Cell {
public:
Cell(Cell* next, void* value): next(next), value(value) { }
Cell* next;
void* value;
};
2008-09-24 00:01:42 +00:00
class Local {
public:
Value* value;
2008-11-02 22:25:51 +00:00
unsigned footprint;
2008-09-24 00:01:42 +00:00
};
class Site {
public:
Site(): next(0) { }
virtual Site* readTarget(Context*, Read*) { return this; }
2008-04-17 02:55:38 +00:00
2008-10-04 17:26:35 +00:00
virtual void toString(Context*, char*, unsigned) = 0;
virtual unsigned copyCost(Context*, Site*) = 0;
virtual bool match(Context*, uint8_t, uint64_t, int) = 0;
2008-09-24 00:01:42 +00:00
virtual void acquire(Context*, Stack*, Local*, unsigned, Value*) { }
2008-04-17 02:55:38 +00:00
2008-04-19 00:19:45 +00:00
virtual void release(Context*) { }
virtual void freeze(Context*) { }
virtual void thaw(Context*) { }
2008-10-15 00:45:31 +00:00
virtual bool usesRegister(Context*, int) { return false; }
2008-04-17 22:07:32 +00:00
virtual OperandType type(Context*) = 0;
2008-04-17 02:55:38 +00:00
virtual Assembler::Operand* asAssemblerOperand(Context*) = 0;
virtual Site* copy(Context*) = 0;
2008-10-04 17:26:35 +00:00
Site* next;
};
class Stack: public Compiler::StackElement {
2008-04-17 22:07:32 +00:00
public:
2008-11-02 22:25:51 +00:00
Stack(unsigned index, unsigned footprint, Value* value, Stack* next):
index(index), footprint(footprint), value(value), next(next)
2008-04-17 22:07:32 +00:00
{ }
unsigned index;
2008-11-02 22:25:51 +00:00
unsigned footprint;
2008-07-05 20:21:13 +00:00
Value* value;
2008-04-17 22:07:32 +00:00
Stack* next;
};
class SavedValue {
public:
SavedValue(unsigned footprint, Value* value, SavedValue* next):
footprint(footprint), value(value), next(next)
{ }
unsigned footprint;
Value* value;
SavedValue* next;
};
2008-11-02 20:35:35 +00:00
class ForkElement {
2008-09-22 14:28:18 +00:00
public:
Value* value;
MultiRead* read;
2008-11-02 20:35:35 +00:00
bool local;
2008-09-22 14:28:18 +00:00
};
class ForkState: public Compiler::State {
2008-04-17 22:07:32 +00:00
public:
ForkState(Stack* stack, Local* locals, SavedValue* saved, Event* predecessor,
unsigned logicalIp):
stack(stack),
2008-07-05 20:21:13 +00:00
locals(locals),
saved(saved),
2008-09-20 23:42:46 +00:00
predecessor(predecessor),
logicalIp(logicalIp),
readCount(0)
2008-04-17 22:07:32 +00:00
{ }
Stack* stack;
2008-09-24 00:01:42 +00:00
Local* locals;
SavedValue* saved;
2008-09-20 23:42:46 +00:00
Event* predecessor;
unsigned logicalIp;
unsigned readCount;
2008-11-02 20:35:35 +00:00
ForkElement elements[0];
2008-04-17 22:07:32 +00:00
};
class MySubroutine: public Compiler::Subroutine {
public:
MySubroutine(): forkState(0) { }
ForkState* forkState;
};
2008-04-17 22:07:32 +00:00
class LogicalInstruction {
public:
2008-09-24 00:01:42 +00:00
LogicalInstruction(int index, Stack* stack, Local* locals):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
locals(locals), machineOffset(0), subroutine(0), index(index)
2008-09-07 20:12:11 +00:00
{ }
2008-04-19 07:03:59 +00:00
Event* firstEvent;
2008-04-17 22:07:32 +00:00
Event* lastEvent;
2008-04-20 19:35:36 +00:00
LogicalInstruction* immediatePredecessor;
Stack* stack;
2008-09-24 00:01:42 +00:00
Local* locals;
Promise* machineOffset;
MySubroutine* subroutine;
2008-08-30 20:12:27 +00:00
int index;
2008-04-17 22:07:32 +00:00
};
class Register {
public:
Register(int number):
value(0), site(0), number(number), size(0), refCount(0),
freezeCount(0), reserved(false)
{ }
2008-04-17 22:07:32 +00:00
Value* value;
RegisterSite* site;
int number;
2008-04-17 22:07:32 +00:00
unsigned size;
unsigned refCount;
unsigned freezeCount;
2008-04-17 22:07:32 +00:00
bool reserved;
};
class FrameResource {
public:
Value* value;
MemorySite* site;
unsigned size;
2008-12-12 01:09:36 +00:00
unsigned freezeCount;
2008-11-17 15:20:48 +00:00
bool includeNeighbor;
2008-04-17 22:07:32 +00:00
};
class ConstantPoolNode {
public:
ConstantPoolNode(Promise* promise): promise(promise), next(0) { }
Promise* promise;
ConstantPoolNode* next;
};
class Read {
public:
2008-09-24 00:01:42 +00:00
Read(unsigned size):
value(0), event(0), eventNext(0), size(size)
2008-04-17 22:07:32 +00:00
{ }
2008-07-05 20:21:13 +00:00
2008-11-02 20:35:35 +00:00
virtual Site* pickSite(Context* c, Value* v, bool includeBuddies) = 0;
2008-07-05 20:21:13 +00:00
virtual Site* allocateSite(Context* c) = 0;
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
2008-07-05 20:21:13 +00:00
int* frameIndex) = 0;
virtual bool valid() = 0;
2008-08-30 20:12:27 +00:00
virtual void append(Context* c, Read* r) = 0;
virtual Read* next(Context* c) = 0;
2008-08-28 22:43:35 +00:00
Value* value;
Event* event;
Read* eventNext;
2008-09-24 00:01:42 +00:00
unsigned size;
2008-04-17 22:07:32 +00:00
};
2008-08-28 22:43:35 +00:00
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;
}
2008-04-17 22:07:32 +00:00
class Value: public Compiler::Operand {
public:
Value(Site* site, Site* target):
2008-11-01 19:14:13 +00:00
reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this),
2008-11-17 15:20:48 +00:00
local(false), thief(false)
2008-04-17 22:07:32 +00:00
{ }
virtual void addPredecessor(Context*, Event*) { }
2008-04-17 22:07:32 +00:00
Read* reads;
Read* lastRead;
Site* sites;
Site* source;
2008-04-19 20:41:31 +00:00
Site* target;
2008-11-01 19:14:13 +00:00
Value* buddy;
bool local;
2008-11-17 15:20:48 +00:00
bool thief;
2008-04-17 22:07:32 +00:00
};
2008-07-05 20:21:13 +00:00
enum Pass {
ScanPass,
CompilePass
};
2008-04-17 22:07:32 +00:00
class Context {
public:
Context(System* system, Assembler* assembler, Zone* zone,
Compiler::Client* client):
2008-04-17 22:07:32 +00:00
system(system),
assembler(assembler),
arch(assembler->arch()),
2008-04-17 22:07:32 +00:00
zone(zone),
client(client),
stack(0),
locals(0),
saved(0),
2008-09-20 23:42:46 +00:00
predecessor(0),
2008-04-17 22:07:32 +00:00
logicalCode(0),
registers
(static_cast<Register**>
(zone->allocate(sizeof(Register*) * arch->registerCount()))),
frameResources(0),
2008-04-17 22:07:32 +00:00
firstConstant(0),
lastConstant(0),
2008-08-30 20:12:27 +00:00
machineCode(0),
firstEvent(0),
lastEvent(0),
forkState(0),
subroutine(0),
2008-12-12 01:09:36 +00:00
forfeitedSite(0),
2008-08-30 20:12:27 +00:00
logicalIp(-1),
2008-04-17 22:07:32 +00:00
constantCount(0),
2008-08-30 20:12:27 +00:00
logicalCodeLength(0),
parameterFootprint(0),
localFootprint(0),
2008-09-23 21:18:41 +00:00
machineCodeSize(0),
alignedFrameSize(0),
availableRegisterCount(arch->registerCount()),
2008-07-05 20:21:13 +00:00
constantCompare(CompareNone),
2008-08-30 20:12:27 +00:00
pass(ScanPass)
2008-04-17 22:07:32 +00:00
{
for (unsigned i = 0; i < arch->registerCount(); ++i) {
registers[i] = new (zone->allocate(sizeof(Register))) Register(i);
if (arch->reserved(i)) {
registers[i]->reserved = true;
-- availableRegisterCount;
}
}
2008-04-17 22:07:32 +00:00
}
System* system;
Assembler* assembler;
Assembler::Architecture* arch;
2008-04-17 22:07:32 +00:00
Zone* zone;
Compiler::Client* client;
Stack* stack;
2008-09-24 00:01:42 +00:00
Local* locals;
SavedValue* saved;
2008-09-20 23:42:46 +00:00
Event* predecessor;
2008-08-16 17:45:36 +00:00
LogicalInstruction** logicalCode;
Register** registers;
FrameResource* frameResources;
2008-04-17 22:07:32 +00:00
ConstantPoolNode* firstConstant;
ConstantPoolNode* lastConstant;
2008-08-30 20:12:27 +00:00
uint8_t* machineCode;
Event* firstEvent;
Event* lastEvent;
ForkState* forkState;
MySubroutine* subroutine;
2008-12-12 01:09:36 +00:00
Site* forfeitedSite;
2008-08-30 20:12:27 +00:00
int logicalIp;
2008-04-17 22:07:32 +00:00
unsigned constantCount;
2008-08-30 20:12:27 +00:00
unsigned logicalCodeLength;
unsigned parameterFootprint;
unsigned localFootprint;
2008-09-23 21:18:41 +00:00
unsigned machineCodeSize;
unsigned alignedFrameSize;
unsigned availableRegisterCount;
ConstantCompare constantCompare;
2008-07-05 20:21:13 +00:00
Pass pass;
2008-04-17 22:07:32 +00:00
};
class PoolPromise: public Promise {
public:
PoolPromise(Context* c, int key): c(c), key(key) { }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
2008-09-23 21:18:41 +00:00
(c->machineCode + pad(c->machineCodeSize) + (key * BytesPerWord));
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0;
}
Context* c;
int key;
};
class CodePromise: public Promise {
public:
2008-08-30 20:12:27 +00:00
CodePromise(Context* c, CodePromise* next):
c(c), offset(0), next(next)
{ }
CodePromise(Context* c, Promise* offset):
2008-08-30 20:12:27 +00:00
c(c), offset(offset), next(0)
{ }
virtual int64_t value() {
if (resolved()) {
2008-08-30 20:12:27 +00:00
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
}
abort(c);
}
virtual bool resolved() {
2008-08-30 20:12:27 +00:00
return c->machineCode != 0 and offset and offset->resolved();
}
Context* c;
Promise* offset;
CodePromise* next;
};
2008-09-07 20:12:11 +00:00
unsigned
machineOffset(Context* c, int logicalIp)
{
2008-09-22 14:28:18 +00:00
return c->logicalCode[logicalIp]->machineOffset->value();
2008-09-07 20:12:11 +00:00
}
class IpPromise: public Promise {
public:
IpPromise(Context* c, int logicalIp):
c(c),
logicalIp(logicalIp)
{ }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
2008-09-07 20:12:11 +00:00
(c->machineCode + machineOffset(c, logicalIp));
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0;
}
Context* c;
int logicalIp;
};
inline void NO_RETURN
abort(Context* c)
{
abort(c->system);
}
#ifndef NDEBUG
inline void
assert(Context* c, bool v)
{
assert(c->system, v);
}
#endif // not NDEBUG
inline void
expect(Context* c, bool v)
{
expect(c->system, v);
}
2008-09-07 20:12:11 +00:00
Cell*
cons(Context* c, void* value, Cell* next)
{
return new (c->zone->allocate(sizeof(Cell))) Cell(next, value);
}
Cell*
append(Context* c, Cell* first, Cell* second)
{
if (first) {
if (second) {
Cell* start = cons(c, first->value, second);
Cell* end = start;
for (Cell* cell = first->next; cell; cell = cell->next) {
Cell* n = cons(c, cell->value, second);
end->next = n;
end = n;
}
return start;
} else {
return first;
}
} else {
return second;
}
}
2008-10-15 00:45:31 +00:00
Cell*
reverseDestroy(Cell* cell)
{
Cell* previous = 0;
while (cell) {
Cell* next = cell->next;
cell->next = previous;
previous = cell;
cell = next;
}
return previous;
}
2008-09-22 14:28:18 +00:00
class StubReadPair {
public:
Value* value;
StubRead* read;
};
class JunctionState {
public:
JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { }
unsigned frameFootprint;
StubReadPair reads[0];
};
class Link {
public:
Link(Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState):
predecessor(predecessor), nextPredecessor(nextPredecessor),
successor(successor), nextSuccessor(nextSuccessor), forkState(forkState),
junctionState(0)
{ }
Event* predecessor;
Link* nextPredecessor;
Event* successor;
Link* nextSuccessor;
ForkState* forkState;
JunctionState* junctionState;
};
Link*
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState)
{
return new (c->zone->allocate(sizeof(Link))) Link
(predecessor, nextPredecessor, successor, nextSuccessor, forkState);
}
unsigned
countPredecessors(Link* link)
{
unsigned c = 0;
for (; link; link = link->nextPredecessor) ++ c;
return c;
}
Link*
lastPredecessor(Link* link)
{
while (link->nextPredecessor) link = link->nextPredecessor;
return link;
}
unsigned
countSuccessors(Link* link)
{
unsigned c = 0;
for (; link; link = link->nextSuccessor) ++ c;
return c;
}
class Event {
public:
Event(Context* c):
next(0), stackBefore(c->stack), localsBefore(c->locals),
stackAfter(0), localsAfter(0), promises(0), reads(0),
2008-11-01 22:16:18 +00:00
junctionSites(0), snapshots(0), predecessors(0), successors(0),
2008-10-15 00:45:31 +00:00
visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
readCount(0)
{ }
virtual const char* name() = 0;
virtual void compile(Context* c) = 0;
2008-08-30 20:12:27 +00:00
virtual bool isBranch() { return false; }
Event* next;
2008-10-04 17:26:35 +00:00
Stack* stackBefore;
Local* localsBefore;
Stack* stackAfter;
Local* localsAfter;
CodePromise* promises;
Read* reads;
2008-08-30 20:12:27 +00:00
Site** junctionSites;
2008-11-01 22:16:18 +00:00
Snapshot* snapshots;
Link* predecessors;
Link* successors;
2008-10-15 00:45:31 +00:00
Cell* visitLinks;
2008-08-30 20:12:27 +00:00
Block* block;
LogicalInstruction* logicalInstruction;
unsigned readCount;
};
int
2008-11-02 22:25:51 +00:00
frameIndex(Context* c, int index, unsigned footprint)
{
2008-11-02 22:25:51 +00:00
return c->alignedFrameSize + c->parameterFootprint - index - footprint;
}
unsigned
frameIndexToOffset(Context* c, unsigned frameIndex)
{
return ((frameIndex >= c->alignedFrameSize) ?
(frameIndex
+ (c->arch->frameFooterSize() * 2)
+ c->arch->frameHeaderSize()) :
(frameIndex
+ c->arch->frameFooterSize())) * BytesPerWord;
}
unsigned
offsetToFrameIndex(Context* c, unsigned offset)
{
unsigned normalizedOffset = offset / BytesPerWord;
return ((normalizedOffset
>= c->alignedFrameSize
+ c->arch->frameFooterSize()) ?
(normalizedOffset
- (c->arch->frameFooterSize() * 2)
- c->arch->frameHeaderSize()) :
(normalizedOffset
- c->arch->frameFooterSize()));
}
2008-11-01 19:14:13 +00:00
class FrameIterator {
public:
class Element {
public:
2008-11-02 22:25:51 +00:00
Element(Value* value, unsigned localIndex, unsigned footprint):
value(value), localIndex(localIndex), footprint(footprint)
2008-11-01 19:14:13 +00:00
{ }
Value* const value;
const unsigned localIndex;
2008-11-02 22:25:51 +00:00
const unsigned footprint;
2008-11-01 19:14:13 +00:00
};
FrameIterator(Context* c, Stack* stack, Local* locals):
stack(stack), locals(locals), localIndex(c->localFootprint - 1)
{ }
bool hasMore() {
while (localIndex >= 0 and locals[localIndex].value == 0) -- localIndex;
return stack != 0 or localIndex >= 0;
}
Element next(Context* c) {
Value* v;
unsigned li;
2008-11-02 22:25:51 +00:00
unsigned footprint;
2008-11-01 19:14:13 +00:00
if (stack) {
Stack* s = stack;
v = s->value;
li = s->index + c->localFootprint;
2008-11-02 22:25:51 +00:00
footprint = s->footprint;
2008-11-01 19:14:13 +00:00
stack = stack->next;
} else {
Local* l = locals + localIndex;
v = l->value;
li = localIndex;
2008-11-02 22:25:51 +00:00
footprint = l->footprint;
2008-11-01 19:14:13 +00:00
-- localIndex;
}
2008-11-02 22:25:51 +00:00
return Element(v, li, footprint);
2008-11-01 19:14:13 +00:00
}
Stack* stack;
Local* locals;
int localIndex;
};
int
frameIndex(Context* c, FrameIterator::Element* element)
{
2008-11-02 22:25:51 +00:00
return frameIndex(c, element->localIndex, element->footprint);
2008-11-01 19:14:13 +00:00
}
class SiteIterator {
public:
2008-11-02 20:35:35 +00:00
SiteIterator(Value* v, bool includeBuddies = true):
2008-11-01 19:14:13 +00:00
originalValue(v),
currentValue(v),
2008-11-02 20:35:35 +00:00
includeBuddies(includeBuddies),
2008-11-01 19:14:13 +00:00
next_(findNext(&(v->sites))),
previous(0)
{ }
Site** findNext(Site** p) {
if (*p) {
return p;
} else {
2008-11-02 20:35:35 +00:00
if (includeBuddies) {
for (Value* v = currentValue->buddy;
v != originalValue;
v = v->buddy)
{
if (v->sites) {
currentValue = v;
return &(v->sites);
}
2008-11-01 19:14:13 +00:00
}
}
return 0;
}
}
bool hasMore() {
if (previous) {
next_ = findNext(&((*previous)->next));
previous = 0;
}
return next_ != 0;
}
Site* next() {
previous = next_;
return *previous;
}
void remove(Context* c) {
(*previous)->release(c);
*previous = (*previous)->next;
next_ = findNext(previous);
previous = 0;
}
Value* originalValue;
Value* currentValue;
2008-11-02 20:35:35 +00:00
bool includeBuddies;
2008-11-01 19:14:13 +00:00
Site** next_;
Site** previous;
};
2008-11-01 22:16:18 +00:00
bool
hasMoreThanOneSite(Value* v)
{
SiteIterator it(v);
if (it.hasMore()) {
it.next();
return it.hasMore();
} else {
return false;
}
}
bool
hasSite(Value* v)
{
SiteIterator it(v);
return it.hasMore();
}
2008-04-18 00:39:41 +00:00
bool
findSite(Context*, Value* v, Site* site)
{
for (Site* s = v->sites; s; s = s->next) {
if (s == site) return true;
}
return false;
}
void
2008-09-24 00:01:42 +00:00
addSite(Context* c, Stack* stack, Local* locals, unsigned size, Value* v,
2008-07-17 23:34:38 +00:00
Site* s)
2008-04-19 00:19:45 +00:00
{
if (not findSite(c, v, s)) {
2008-12-12 01:09:36 +00:00
if (DebugSites) {
char buffer[256]; s->toString(c, buffer, 256);
fprintf(stderr, "add site %s to %p\n", buffer, v);
}
2008-07-17 23:34:38 +00:00
s->acquire(c, stack, locals, size, v);
s->next = v->sites;
v->sites = s;
2008-04-19 00:19:45 +00:00
}
}
2008-04-18 00:39:41 +00:00
void
2008-04-19 07:03:59 +00:00
removeSite(Context* c, Value* v, Site* s)
2008-04-18 00:39:41 +00:00
{
2008-11-01 19:14:13 +00:00
for (SiteIterator it(v); it.hasMore();) {
if (s == it.next()) {
2008-12-12 01:09:36 +00:00
if (DebugSites) {
char buffer[256]; s->toString(c, buffer, 256);
fprintf(stderr, "remove site %s from %p\n", buffer, v);
}
2008-11-01 19:14:13 +00:00
it.remove(c);
2008-04-30 15:44:17 +00:00
break;
}
}
2008-12-12 01:09:36 +00:00
if (DebugSites) {
fprintf(stderr, "%p has more: %d\n", v, hasSite(v));
}
assert(c, not findSite(c, v, s));
2008-04-30 15:44:17 +00:00
}
2008-04-19 07:03:59 +00:00
void
clearSites(Context* c, Value* v)
{
2008-12-12 01:09:36 +00:00
if (DebugSites) {
fprintf(stderr, "clear sites for %p\n", v);
}
2008-11-01 22:16:18 +00:00
for (SiteIterator it(v); it.hasMore();) {
it.next();
it.remove(c);
2008-04-19 07:03:59 +00:00
}
}
2008-07-05 20:21:13 +00:00
bool
valid(Read* r)
{
return r and r->valid();
}
2008-11-01 22:16:18 +00:00
Read*
2008-07-05 20:21:13 +00:00
live(Value* v)
{
2008-11-01 22:16:18 +00:00
if (valid(v->reads)) return v->reads;
2008-11-01 19:14:13 +00:00
for (Value* p = v->buddy; p != v; p = p->buddy) {
2008-11-01 22:16:18 +00:00
if (valid(p->reads)) return p->reads;
2008-11-01 19:14:13 +00:00
}
2008-11-01 22:16:18 +00:00
return 0;
2008-11-01 19:14:13 +00:00
}
2008-11-01 22:16:18 +00:00
Read*
2008-11-01 19:14:13 +00:00
liveNext(Context* c, Value* v)
{
2008-11-01 22:16:18 +00:00
Read* r = v->reads->next(c);
if (valid(r)) return r;
2008-11-01 19:14:13 +00:00
for (Value* p = v->buddy; p != v; p = p->buddy) {
2008-11-01 22:16:18 +00:00
if (valid(p->reads)) return p->reads;
2008-11-01 19:14:13 +00:00
}
2008-11-01 22:16:18 +00:00
return 0;
2008-07-05 20:21:13 +00:00
}
2008-04-19 00:19:45 +00:00
void
2008-11-12 01:09:45 +00:00
nextRead(Context* c, Event* e UNUSED, Value* v)
2008-04-19 00:19:45 +00:00
{
2008-09-25 00:48:32 +00:00
assert(c, e == v->reads->event);
2008-12-12 01:09:36 +00:00
if (DebugReads) {
fprintf(stderr, "pop read %p from %p next %p event %p (%s)\n",
v->reads, v, v->reads->next(c), e, (e ? e->name() : 0));
}
2008-04-19 07:03:59 +00:00
v->reads = v->reads->next(c);
2008-07-05 20:21:13 +00:00
if (not live(v)) {
2008-04-19 07:03:59 +00:00
clearSites(c, v);
2008-04-19 00:19:45 +00:00
}
}
ConstantSite*
constantSite(Context* c, Promise* value);
class ConstantSite: public Site {
public:
ConstantSite(Promise* value): value(value) { }
2008-10-04 17:26:35 +00:00
virtual void toString(Context*, char* buffer, unsigned bufferSize) {
if (value.value->resolved()) {
snprintf(buffer, bufferSize, "constant %"LLD, value.value->value());
2008-10-04 17:26:35 +00:00
} else {
snprintf(buffer, bufferSize, "constant unresolved");
}
}
2008-04-18 18:36:57 +00:00
virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : 1);
}
virtual bool match(Context*, uint8_t typeMask, uint64_t, int) {
return typeMask & (1 << ConstantOperand);
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return ConstantOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context*) {
return &value;
}
virtual Site* copy(Context* c) {
return constantSite(c, value.value);
}
Assembler::Constant value;
};
ConstantSite*
constantSite(Context* c, Promise* value)
{
return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value);
}
ResolvedPromise*
resolved(Context* c, int64_t value)
{
return new (c->zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value);
}
ConstantSite*
constantSite(Context* c, int64_t value)
{
return constantSite(c, resolved(c, value));
}
AddressSite*
addressSite(Context* c, Promise* address);
class AddressSite: public Site {
public:
AddressSite(Promise* address): address(address) { }
2008-10-04 17:26:35 +00:00
virtual void toString(Context*, char* buffer, unsigned bufferSize) {
if (address.address->resolved()) {
snprintf(buffer, bufferSize, "address %"LLD, address.address->value());
2008-10-04 17:26:35 +00:00
} else {
snprintf(buffer, bufferSize, "address unresolved");
}
}
2008-04-18 18:36:57 +00:00
virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : 3);
}
virtual bool match(Context*, uint8_t typeMask, uint64_t, int) {
return typeMask & (1 << AddressOperand);
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return AddressOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context*) {
return &address;
}
virtual Site* copy(Context* c) {
return addressSite(c, address.address);
}
Assembler::Address address;
};
AddressSite*
addressSite(Context* c, Promise* address)
{
return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address);
}
void
freeze(Context* c, Register* r)
{
if (DebugRegisters) {
fprintf(stderr, "freeze %d to %d for %p\n",
r->number, r->freezeCount + 1, r->value);
}
++ r->freezeCount;
if (r->freezeCount == 1) {
assert(c, c->availableRegisterCount);
-- c->availableRegisterCount;
}
}
void
thaw(Context* c, Register* r)
{
assert(c, r->freezeCount);
if (DebugRegisters) {
fprintf(stderr, "thaw %d to %d\n", r->number, r->freezeCount - 1);
}
-- r->freezeCount;
if (r->freezeCount == 0) {
++ c->availableRegisterCount;
}
}
Register*
2008-09-24 00:01:42 +00:00
acquire(Context* c, uint32_t mask, Stack* stack, Local* locals,
2008-07-17 23:34:38 +00:00
unsigned newSize, Value* newValue, RegisterSite* newSite);
2008-04-19 00:19:45 +00:00
void
release(Context* c, Register* r);
2008-04-19 00:19:45 +00:00
2008-05-15 20:00:57 +00:00
Register*
2008-09-24 00:01:42 +00:00
validate(Context* c, uint32_t mask, Stack* stack, Local* locals,
unsigned size, Value* value, RegisterSite* site, Register* current);
2008-05-15 20:00:57 +00:00
RegisterSite*
freeRegisterSite(Context* c, uint64_t mask = ~static_cast<uint64_t>(0));
class RegisterSite: public Site {
public:
RegisterSite(uint64_t mask, Register* low = 0, Register* high = 0):
mask(mask), low(low), high(high), register_(NoRegister, NoRegister)
{ }
2008-05-14 23:19:41 +00:00
void sync(Context* c UNUSED) {
assert(c, low);
register_.low = low->number;
register_.high = (high? high->number : NoRegister);
}
2008-10-04 17:26:35 +00:00
virtual void toString(Context* c, char* buffer, unsigned bufferSize) {
if (low) {
sync(c);
2008-12-12 01:09:36 +00:00
snprintf(buffer, bufferSize, "%p register %d %d",
this, register_.low, register_.high);
2008-10-04 17:26:35 +00:00
} else {
2008-12-12 01:09:36 +00:00
snprintf(buffer, bufferSize, "%p register unacquired", this);
2008-10-04 17:26:35 +00:00
}
}
virtual unsigned copyCost(Context* c, Site* s) {
sync(c);
if (s and
(this == s or
2008-04-17 22:07:32 +00:00
(s->type(c) == RegisterOperand
and (static_cast<RegisterSite*>(s)->mask
& (static_cast<uint64_t>(1) << register_.low))
and (register_.high == NoRegister
or (static_cast<RegisterSite*>(s)->mask
& (static_cast<uint64_t>(1) << (register_.high + 32)))))))
{
return 0;
} else {
return 2;
}
}
virtual bool match(Context* c, uint8_t typeMask, uint64_t registerMask, int)
{
if ((typeMask & (1 << RegisterOperand)) and low) {
sync(c);
return ((static_cast<uint64_t>(1) << register_.low) & registerMask)
and (register_.high == NoRegister
or ((static_cast<uint64_t>(1) << (register_.high + 32))
& registerMask));
} else {
return false;
}
}
2008-09-24 00:01:42 +00:00
virtual void acquire(Context* c, Stack* stack, Local* locals, unsigned size,
2008-07-17 23:34:38 +00:00
Value* v)
{
low = ::validate(c, mask, stack, locals, size, v, this, low);
if (size > BytesPerWord) {
::freeze(c, low);
2008-07-17 23:34:38 +00:00
high = ::validate(c, mask >> 32, stack, locals, size, v, this, high);
::thaw(c, low);
}
2008-04-19 00:19:45 +00:00
}
virtual void release(Context* c) {
assert(c, low);
::release(c, low);
if (high) {
::release(c, high);
}
}
2008-11-17 15:20:48 +00:00
virtual void freeze(Context* c) {
assert(c, low);
::freeze(c, low);
if (high) {
::freeze(c, high);
}
}
2008-11-17 15:20:48 +00:00
virtual void thaw(Context* c) {
assert(c, low);
::thaw(c, low);
if (high) {
::thaw(c, high);
}
}
2008-10-15 00:45:31 +00:00
virtual bool usesRegister(Context* c, int r) {
sync(c);
return register_.low == r or register_.high == r;
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return RegisterOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
sync(c);
return &register_;
}
virtual Site* copy(Context* c) {
uint64_t mask;
if (low) {
sync(c);
mask = static_cast<uint64_t>(1) << register_.low;
if (register_.high != NoRegister) {
mask |= static_cast<uint64_t>(1) << (register_.high + 32);
}
} else {
mask = this->mask;
2008-10-04 17:26:35 +00:00
}
return freeRegisterSite(c, mask);
2008-10-04 17:26:35 +00:00
}
uint64_t mask;
Register* low;
Register* high;
Assembler::Register register_;
};
RegisterSite*
registerSite(Context* c, int low, int high = NoRegister)
{
2008-04-19 00:19:45 +00:00
assert(c, low != NoRegister);
assert(c, low < static_cast<int>(c->arch->registerCount()));
2008-04-19 00:19:45 +00:00
assert(c, high == NoRegister
or high < static_cast<int>(c->arch->registerCount()));
2008-04-19 00:19:45 +00:00
Register* hr;
if (high == NoRegister) {
hr = 0;
} else {
hr = c->registers[high];
}
return new (c->zone->allocate(sizeof(RegisterSite)))
RegisterSite(~static_cast<uint64_t>(0), c->registers[low], hr);
}
2008-04-17 22:07:32 +00:00
RegisterSite*
freeRegisterSite(Context* c, uint64_t mask)
{
return new (c->zone->allocate(sizeof(RegisterSite)))
RegisterSite(mask);
}
2008-04-17 22:07:32 +00:00
Register*
increment(Context* c, int i)
{
Register* r = c->registers[i];
if (DebugRegisters) {
fprintf(stderr, "increment %d to %d\n", r->number, r->refCount + 1);
}
++ r->refCount;
return r;
}
void
2008-05-14 23:19:41 +00:00
decrement(Context* c UNUSED, Register* r)
{
assert(c, r->refCount > 0);
if (DebugRegisters) {
fprintf(stderr, "decrement %d to %d\n", r->number, r->refCount - 1);
}
-- r->refCount;
}
void
acquireFrameIndex(Context* c, int index, Stack* stack, Local* locals,
unsigned newSize, Value* newValue, MemorySite* newSite,
2008-11-17 15:20:48 +00:00
bool includeNeighbor);
void
2008-11-17 15:20:48 +00:00
releaseFrameIndex(Context* c, int index);
void
freezeFrameIndex(Context* c, int index);
void
thawFrameIndex(Context* c, int index);
MemorySite*
memorySite(Context* c, int base, int offset = 0, int index = NoRegister,
unsigned scale = 1);
class MemorySite: public Site {
public:
2008-04-17 02:55:38 +00:00
MemorySite(int base, int offset, int index, unsigned scale):
base(0), index(0), value(base, offset, index, scale)
{ }
2008-05-14 23:19:41 +00:00
void sync(Context* c UNUSED) {
assert(c, base);
value.base = base->number;
value.index = (index? index->number : NoRegister);
}
2008-10-04 17:26:35 +00:00
virtual void toString(Context* c, char* buffer, unsigned bufferSize) {
if (base) {
sync(c);
2008-11-02 20:35:35 +00:00
snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
2008-10-04 17:26:35 +00:00
value.base, value.offset, value.index, value.scale);
} else {
snprintf(buffer, bufferSize, "memory unacquired");
}
}
virtual unsigned copyCost(Context* c, Site* s) {
sync(c);
if (s and
(this == s or
2008-04-17 22:07:32 +00:00
(s->type(c) == MemoryOperand
and static_cast<MemorySite*>(s)->value.base == value.base
and static_cast<MemorySite*>(s)->value.offset == value.offset
and static_cast<MemorySite*>(s)->value.index == value.index
and static_cast<MemorySite*>(s)->value.scale == value.scale)))
{
return 0;
} else {
return 4;
}
}
virtual bool match(Context* c, uint8_t typeMask, uint64_t, int frameIndex) {
if (typeMask & (1 << MemoryOperand)) {
sync(c);
if (value.base == c->arch->stack()) {
assert(c, value.index == NoRegister);
return frameIndex == AnyFrameIndex
|| (frameIndex != NoFrameIndex
&& static_cast<int>(frameIndexToOffset(c, frameIndex))
== value.offset);
} else {
2008-10-19 00:15:57 +00:00
return true;
}
} else {
return false;
}
}
virtual void acquire(Context* c, Stack* stack, Local* locals, unsigned size,
Value* v)
{
base = increment(c, value.base);
2008-04-19 00:19:45 +00:00
if (value.index != NoRegister) {
index = increment(c, value.index);
2008-04-19 00:19:45 +00:00
}
if (value.base == c->arch->stack()) {
assert(c, value.index == NoRegister);
acquireFrameIndex
(c, offsetToFrameIndex(c, value.offset), stack, locals, size, v,
2008-11-17 15:20:48 +00:00
this, true);
}
2008-04-19 00:19:45 +00:00
}
virtual void release(Context* c) {
if (value.base == c->arch->stack()) {
assert(c, value.index == NoRegister);
releaseFrameIndex(c, offsetToFrameIndex(c, value.offset));
}
decrement(c, base);
if (index) {
decrement(c, index);
2008-04-19 00:19:45 +00:00
}
}
2008-11-17 15:20:48 +00:00
virtual void freeze(Context* c) {
if (value.base == c->arch->stack()) {
freezeFrameIndex(c, offsetToFrameIndex(c, value.offset));
}
}
virtual void thaw(Context* c) {
if (value.base == c->arch->stack()) {
thawFrameIndex(c, offsetToFrameIndex(c, value.offset));
}
}
2008-10-15 00:45:31 +00:00
virtual bool usesRegister(Context* c, int r) {
sync(c);
return value.base == r or value.index == r;
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return MemoryOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
sync(c);
return &value;
}
virtual Site* copy(Context* c) {
return memorySite(c, value.base, value.offset, value.index, value.scale);
}
Register* base;
Register* index;
Assembler::Memory value;
};
MemorySite*
memorySite(Context* c, int base, int offset, int index, unsigned scale)
{
return new (c->zone->allocate(sizeof(MemorySite)))
MemorySite(base, offset, index, scale);
}
MemorySite*
frameSite(Context* c, int frameIndex)
{
assert(c, frameIndex >= 0);
2008-10-19 00:15:57 +00:00
return memorySite
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex));
}
2008-07-05 20:21:13 +00:00
Site*
targetOrNull(Context* c, Value* v, Read* r)
{
2008-07-05 20:21:13 +00:00
if (v->target) {
return v->target;
2008-05-22 17:15:18 +00:00
} else {
2008-07-05 20:21:13 +00:00
return r->allocateSite(c);
2008-05-22 17:15:18 +00:00
}
}
2008-07-05 20:21:13 +00:00
Site*
targetOrNull(Context* c, Value* v)
{
2008-07-05 20:21:13 +00:00
if (v->target) {
return v->target;
} else if (live(v)) {
2008-11-01 19:14:13 +00:00
return v->reads->allocateSite(c);
2008-07-05 20:21:13 +00:00
}
return 0;
}
2008-05-06 21:13:02 +00:00
Site*
2008-07-05 20:21:13 +00:00
pickSite(Context* c, Value* value, uint8_t typeMask, uint64_t registerMask,
2008-11-02 20:35:35 +00:00
int frameIndex, bool includeBuddies)
2008-05-06 21:13:02 +00:00
{
2008-07-05 20:21:13 +00:00
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
2008-11-02 20:35:35 +00:00
for (SiteIterator it(value, includeBuddies); it.hasMore();) {
2008-11-01 19:14:13 +00:00
Site* s = it.next();
2008-07-05 20:21:13 +00:00
if (s->match(c, typeMask, registerMask, frameIndex)) {
unsigned v = s->copyCost(c, 0);
if (v < copyCost) {
site = s;
copyCost = v;
}
}
2008-05-06 21:13:02 +00:00
}
2008-07-05 20:21:13 +00:00
return site;
2008-05-06 21:13:02 +00:00
}
Site*
2008-07-05 20:21:13 +00:00
allocateSite(Context* c, uint8_t typeMask, uint64_t registerMask,
int frameIndex)
2008-05-06 21:13:02 +00:00
{
2008-07-05 20:21:13 +00:00
if ((typeMask & (1 << RegisterOperand)) and registerMask) {
return freeRegisterSite(c, registerMask);
} else if (frameIndex >= 0) {
return frameSite(c, frameIndex);
} else {
2008-09-24 00:01:42 +00:00
return 0;
2008-05-06 21:13:02 +00:00
}
}
2008-08-28 22:43:35 +00:00
class SingleRead: public Read {
public:
SingleRead(unsigned size, uint8_t typeMask, uint64_t registerMask,
int frameIndex):
2008-09-24 00:01:42 +00:00
Read(size), next_(0), typeMask(typeMask), registerMask(registerMask),
2008-08-28 22:43:35 +00:00
frameIndex(frameIndex)
{ }
2008-11-02 20:35:35 +00:00
virtual Site* pickSite(Context* c, Value* value, bool includeBuddies) {
return ::pickSite
(c, value, typeMask, registerMask, frameIndex, includeBuddies);
2008-08-28 22:43:35 +00:00
}
virtual Site* allocateSite(Context* c) {
return ::allocateSite(c, typeMask, registerMask, frameIndex);
}
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
2008-08-28 22:43:35 +00:00
int* frameIndex)
{
*typeMask &= this->typeMask;
*registerMask &= this->registerMask;
*frameIndex = intersectFrameIndexes(*frameIndex, this->frameIndex);
return true;
2008-08-28 22:43:35 +00:00
}
virtual bool valid() {
return true;
}
2008-11-12 01:09:45 +00:00
virtual void append(Context* c UNUSED, Read* r) {
assert(c, next_ == 0);
next_ = r;
}
virtual Read* next(Context*) {
return next_;
}
Read* next_;
2008-08-28 22:43:35 +00:00
uint8_t typeMask;
uint64_t registerMask;
int frameIndex;
};
Read*
read(Context* c, unsigned size, uint8_t typeMask, uint64_t registerMask,
int frameIndex)
{
assert(c, (typeMask != 1 << MemoryOperand) or frameIndex >= 0);
2008-08-28 22:43:35 +00:00
return new (c->zone->allocate(sizeof(SingleRead)))
SingleRead(size, typeMask, registerMask, frameIndex);
}
Read*
anyRegisterRead(Context* c, unsigned size)
{
return read(c, size, 1 << RegisterOperand, ~static_cast<uint64_t>(0),
NoFrameIndex);
}
Read*
registerOrConstantRead(Context* c, unsigned size)
{
return read(c, size, (1 << RegisterOperand) | (1 << ConstantOperand),
~static_cast<uint64_t>(0), NoFrameIndex);
}
Read*
fixedRegisterRead(Context* c, unsigned size, int low, int high = NoRegister)
{
uint64_t mask;
if (high == NoRegister) {
mask = (~static_cast<uint64_t>(0) << 32)
| (static_cast<uint64_t>(1) << low);
} else {
mask = (static_cast<uint64_t>(1) << (high + 32))
| (static_cast<uint64_t>(1) << low);
}
return read(c, size, 1 << RegisterOperand, mask, NoFrameIndex);
}
2008-07-05 20:21:13 +00:00
class MultiRead: public Read {
2008-05-06 21:13:02 +00:00
public:
2008-09-24 00:01:42 +00:00
MultiRead(unsigned size):
Read(size), reads(0), lastRead(0), firstTarget(0), lastTarget(0),
visited(false)
{ }
2008-11-02 20:35:35 +00:00
virtual Site* pickSite(Context* c, Value* value, bool includeBuddies) {
2008-07-05 20:21:13 +00:00
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
intersect(&typeMask, &registerMask, &frameIndex);
2008-11-02 20:35:35 +00:00
return ::pickSite
(c, value, typeMask, registerMask, frameIndex, includeBuddies);
2008-07-05 20:21:13 +00:00
}
virtual Site* allocateSite(Context* c) {
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
intersect(&typeMask, &registerMask, &frameIndex);
return ::allocateSite(c, typeMask, registerMask, frameIndex);
}
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
2008-07-05 20:21:13 +00:00
int* frameIndex)
{
bool result = false;
if (not visited) {
visited = true;
for (Cell** cell = &reads; *cell;) {
Read* r = static_cast<Read*>((*cell)->value);
bool valid = r->intersect(typeMask, registerMask, frameIndex);
if (valid) {
result = true;
cell = &((*cell)->next);
} else {
*cell = (*cell)->next;
}
}
visited = false;
}
return result;
2008-07-05 20:21:13 +00:00
}
2008-07-05 20:21:13 +00:00
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;
}
2008-07-05 20:21:13 +00:00
}
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;
lastTarget->value = r;
}
virtual Read* next(Context* c) {
abort(c);
}
void allocateTarget(Context* c) {
Cell* cell = cons(c, 0, 0);
if (lastTarget) {
lastTarget->next = cell;
} else {
firstTarget = cell;
}
lastTarget = cell;
}
Read* nextTarget() {
Read* r = static_cast<Read*>(firstTarget->value);
firstTarget = firstTarget->next;
return r;
}
2008-07-05 20:21:13 +00:00
Cell* reads;
Cell* lastRead;
Cell* firstTarget;
Cell* lastTarget;
bool visited;
};
2008-07-05 20:21:13 +00:00
MultiRead*
2008-09-24 00:01:42 +00:00
multiRead(Context* c, unsigned size)
{
2008-09-24 00:01:42 +00:00
return new (c->zone->allocate(sizeof(MultiRead))) MultiRead(size);
}
class StubRead: public Read {
public:
2008-09-24 00:01:42 +00:00
StubRead(unsigned size):
2008-12-12 01:09:36 +00:00
Read(size), next_(0), read(0), visited(false), valid_(true)
{ }
2008-11-02 20:35:35 +00:00
virtual Site* pickSite(Context* c, Value* value, bool includeBuddies) {
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
intersect(&typeMask, &registerMask, &frameIndex);
2008-11-02 20:35:35 +00:00
return ::pickSite
(c, value, typeMask, registerMask, frameIndex, includeBuddies);
}
virtual Site* allocateSite(Context* c) {
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
intersect(&typeMask, &registerMask, &frameIndex);
return ::allocateSite(c, typeMask, registerMask, frameIndex);
}
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
int* frameIndex)
{
if (not visited) {
visited = true;
if (read) {
bool valid = read->intersect(typeMask, registerMask, frameIndex);
if (not valid) {
read = 0;
}
}
visited = false;
}
2008-12-12 01:09:36 +00:00
return valid_;
}
virtual bool valid() {
2008-12-12 01:09:36 +00:00
return valid_;
}
2008-11-12 01:09:45 +00:00
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;
2008-12-12 01:09:36 +00:00
bool valid_;
};
StubRead*
2008-09-24 00:01:42 +00:00
stubRead(Context* c, unsigned size)
{
2008-09-24 00:01:42 +00:00
return new (c->zone->allocate(sizeof(StubRead))) StubRead(size);
}
Site*
targetOrRegister(Context* c, Value* v)
{
Site* s = targetOrNull(c, v);
if (s) {
return s;
} else {
return freeRegisterSite(c);
}
}
2008-04-17 22:07:32 +00:00
Site*
2008-11-01 19:14:13 +00:00
targetOrRegister(Context* c, Value* v, Read* r)
{
Site* s = targetOrNull(c, v, r);
if (s) {
return s;
} else {
return freeRegisterSite(c);
}
}
Site*
2008-11-02 20:35:35 +00:00
pick(Context* c, Value* value, Site* target, unsigned* cost,
bool includeBuddies)
2008-04-17 22:07:32 +00:00
{
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
2008-11-02 20:35:35 +00:00
for (SiteIterator it(value, includeBuddies); it.hasMore();) {
2008-11-01 19:14:13 +00:00
Site* s = it.next();
2008-04-17 22:07:32 +00:00
unsigned v = s->copyCost(c, target);
if (v < copyCost) {
site = s;
copyCost = v;
}
}
if (cost) *cost = copyCost;
return site;
}
void
move(Context* c, Stack* stack, Local* locals, unsigned size, Value* value,
Site* src, Site* dst)
{
src->freeze(c);
addSite(c, stack, locals, size, value, dst);
src->thaw(c);
if (dst->type(c) == MemoryOperand
and (src->type(c) == MemoryOperand
or src->type(c) == AddressOperand))
{
2008-12-12 01:09:36 +00:00
src->freeze(c);
Site* tmp = freeRegisterSite(c);
addSite(c, stack, locals, size, value, tmp);
2008-12-12 01:09:36 +00:00
src->thaw(c);
if (DebugMoves) {
char srcb[256]; src->toString(c, srcb, 256);
char tmpb[256]; tmp->toString(c, tmpb, 256);
fprintf(stderr, "move %s to %s for %p\n", srcb, tmpb, value);
}
apply(c, Move, size, src, size, tmp);
2008-12-12 01:09:36 +00:00
src = tmp;
}
if (DebugMoves) {
char srcb[256]; src->toString(c, srcb, 256);
char dstb[256]; dst->toString(c, dstb, 256);
fprintf(stderr, "move %s to %s for %p\n", srcb, dstb, value);
}
apply(c, Move, size, src, size, dst);
}
2008-10-15 00:45:31 +00:00
void
toString(Context* c, Site* sites, char* buffer, unsigned size)
{
2008-11-01 19:14:13 +00:00
if (sites) {
sites->toString(c, buffer, size);
if (sites->next) {
unsigned length = strlen(buffer);
assert(c, length + 2 < size);
memcpy(buffer + length, ", ", 2);
length += 2;
toString(c, sites->next, buffer + length, size - length);
2008-11-01 19:14:13 +00:00
}
2008-11-01 22:16:18 +00:00
} else {
assert(c, size);
*buffer = 0;
2008-10-15 00:45:31 +00:00
}
}
bool
find(Value* needle, Value* haystack)
{
if (haystack) {
if (needle == haystack) return true;
for (Value* p = haystack->buddy; p != haystack; p = p->buddy) {
if (needle == p) return true;
}
}
return false;
}
2008-12-20 18:13:58 +00:00
bool
frameIndexAvailable(Context* c, int index)
{
return c->frameResources[index].freezeCount == 0;
}
bool
2008-11-17 15:20:48 +00:00
save(Context* c, Site* src, Value* v, unsigned size, Stack* stack,
2008-12-20 18:13:58 +00:00
Local* locals)
2008-11-17 15:20:48 +00:00
{
int index = NoFrameIndex;
for (unsigned li = 0; li < c->localFootprint; ++li) {
Local* local = locals + li;
if (find(v, local->value)) {
int fi = frameIndex(c, li, local->footprint);
2008-12-20 18:13:58 +00:00
if (frameIndexAvailable(c, fi)) {
2008-11-17 15:20:48 +00:00
index = fi;
break;
}
2008-11-17 15:20:48 +00:00
}
}
2008-11-17 15:20:48 +00:00
if (index == NoFrameIndex) {
for (Stack* s = stack; s; s = s->next) {
if (find(v, s->value)) {
int fi = ::frameIndex
(c, s->index + c->localFootprint, s->footprint);
2008-12-20 18:13:58 +00:00
if (frameIndexAvailable(c, fi)) {
2008-11-17 15:20:48 +00:00
index = fi;
break;
2008-07-17 23:34:38 +00:00
}
2008-05-18 01:26:36 +00:00
}
2008-11-17 15:20:48 +00:00
}
}
2008-07-17 23:34:38 +00:00
2008-11-17 15:20:48 +00:00
if (index != NoFrameIndex) {
move(c, stack, locals, size, v, src, frameSite(c, index));
return true;
} else {
if (DebugRegisters or DebugFrameIndexes) {
fprintf(stderr, "unable to save %p\n", v);
}
return false;
}
}
bool
registerAvailable(Context* c, uint32_t mask)
{
for (int i = c->arch->registerCount() - 1; i >= 0; --i) {
if ((1 << i) & mask) {
Register* r = c->registers[i];
if (not (r->reserved or r->freezeCount)) {
return true;
} else if ((static_cast<uint32_t>(1) << i) == mask) {
return false;
}
}
}
return false;
}
bool
available(Context* c, unsigned size, uint8_t typeMask, uint64_t registerMask,
int frameIndex)
{
return
((typeMask & (1 << RegisterOperand))
and registerMask
and (size <= BytesPerWord or registerAvailable(c, registerMask >> 32))
and registerAvailable(c, registerMask))
or ((typeMask & (1 << MemoryOperand))
and (frameIndex == AnyFrameIndex
or (frameIndex >= 0 and frameIndexAvailable(c, frameIndex))));
}
2008-11-17 15:20:48 +00:00
bool
trySteal(Context* c, Site* site, Value* thief, Value* victim, unsigned size,
2008-12-20 18:13:58 +00:00
Stack* stack, Local* locals)
2008-11-17 15:20:48 +00:00
{
bool success = true;
if (not hasMoreThanOneSite(victim)) {
thief->thief = true;
Read* read = live(victim);
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
read->intersect(&typeMask, &registerMask, &frameIndex);
if (pickSite(c, victim, typeMask, registerMask, frameIndex, true)
or victim->thief)
{
2008-12-20 18:13:58 +00:00
success = save(c, site, victim, size, stack, locals);
2008-11-17 15:20:48 +00:00
} else {
if (available(c, size, typeMask, registerMask, frameIndex)) {
Site* s = allocateSite(c, typeMask, registerMask, frameIndex);
2008-11-17 15:20:48 +00:00
move(c, stack, locals, size, victim, site, s);
success = true;
} else {
2008-12-20 18:13:58 +00:00
success = save(c, site, victim, size, stack, locals);
2008-05-18 01:26:36 +00:00
}
}
2008-11-17 15:20:48 +00:00
thief->thief = false;
}
2008-11-17 15:20:48 +00:00
if (success) {
removeSite(c, victim, site);
}
2008-11-17 15:20:48 +00:00
return success;
}
bool
2008-11-17 15:20:48 +00:00
trySteal(Context* c, Register* r, Value* thief, Stack* stack, Local* locals)
{
assert(c, r->refCount == 0);
Value* v = r->value;
2008-11-01 19:14:13 +00:00
assert(c, live(v));
if (DebugRegisters) {
2008-11-01 22:16:18 +00:00
fprintf(stderr, "try steal %d from %p\n", r->number, v);
}
2008-12-20 18:13:58 +00:00
return trySteal(c, r->site, thief, r->value, r->size, stack, locals);
}
2008-04-21 00:21:48 +00:00
bool
used(Context* c, Register* r)
{
Value* v = r->value;
return v and findSite(c, v, r->site);
}
bool
usedExclusively(Context* c, Register* r)
{
2008-11-01 22:16:18 +00:00
return used(c, r) and not hasMoreThanOneSite(r->value);
}
void
releaseRegister(Context* c, Value* v, unsigned frameIndex,
unsigned sizeInBytes, int r)
{
Site* source = 0;
2008-12-12 01:09:36 +00:00
bool remaining = false;
for (SiteIterator it(v); it.hasMore();) {
Site* s = it.next();
if (s->usesRegister(c, r)) {
if (DebugRegisters) {
char buffer[256]; s->toString(c, buffer, 256);
fprintf(stderr, "%p (%s) in %p at %d uses %d\n",
s, buffer, v, frameIndex, r);
}
source = s;
it.remove(c);
} else {
if (DebugRegisters) {
char buffer[256]; s->toString(c, buffer, 256);
fprintf(stderr, "%p (%s) in %p at %d does not use %d\n",
s, buffer, v, frameIndex, r);
}
2008-12-12 01:09:36 +00:00
if (s != c->forfeitedSite) {
remaining = true;
}
}
}
if (live(v) and not remaining) {
move(c, c->stack, c->locals, sizeInBytes, v, source,
frameSite(c, frameIndex));
}
if (DebugRegisters) {
char buffer[256]; toString(c, v->sites, buffer, 256);
fprintf(stderr, "%p is left with %s\n", v, buffer);
}
}
unsigned
footprintSizeInBytes(unsigned footprint)
{
if (BytesPerWord == 8) {
return 8;
} else {
return footprint * 4;
}
}
2008-12-12 01:09:36 +00:00
bool
remainingForfeited(Context* c, Value* v, Site* toRemove)
{
for (SiteIterator it(v); it.hasMore();) {
Site* s = it.next();
if (not (s == toRemove or s == c->forfeitedSite)) {
return false;
}
}
return true;
}
void
releaseRegister(Context* c, int r)
{
Register* reg = c->registers[r];
2008-12-12 01:09:36 +00:00
if (used(c, reg)
and (not usedExclusively(c, reg))
and (not remainingForfeited(c, reg->value, reg->site)))
{
removeSite(c, reg->value, reg->site);
2008-12-12 01:09:36 +00:00
if (reg->refCount == 0) return;
}
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
releaseRegister(c, e.value, frameIndex(c, &e),
footprintSizeInBytes(e.footprint), r);
}
}
unsigned
registerCost(Context* c, Register* r)
{
if (r->reserved or r->freezeCount) {
return 6;
}
unsigned cost = 0;
if (used(c, r)) {
++ cost;
if (usedExclusively(c, r)) {
cost += 2;
}
}
if (r->refCount) {
cost += 2;
}
return cost;
}
Register*
pickRegister(Context* c, uint32_t mask)
{
Register* register_ = 0;
unsigned cost = 5;
for (int i = c->arch->registerCount() - 1; i >= 0; --i) {
if ((1 << i) & mask) {
Register* r = c->registers[i];
if ((static_cast<uint32_t>(1) << i) == mask) {
return r;
}
unsigned myCost = registerCost(c, r);
if (myCost < cost) {
register_ = r;
cost = myCost;
}
}
}
expect(c, register_);
return register_;
}
void
swap(Context* c, Register* a, Register* b)
{
assert(c, a != b);
assert(c, a->number != b->number);
Assembler::Register ar(a->number);
Assembler::Register br(b->number);
c->assembler->apply
2008-08-16 17:45:36 +00:00
(Swap, BytesPerWord, RegisterOperand, &ar,
BytesPerWord, RegisterOperand, &br);
c->registers[a->number] = b;
c->registers[b->number] = a;
int t = a->number;
a->number = b->number;
b->number = t;
}
Register*
2008-11-17 15:44:35 +00:00
replace(Context* c, Register* r, Value* newValue, Stack* stack, Local* locals)
{
uint32_t mask = (r->freezeCount? r->site->mask : ~0);
2008-05-15 20:00:57 +00:00
freeze(c, r);
2008-11-17 15:44:35 +00:00
Register* s = acquire(c, mask, stack, locals, r->size, newValue, r->site);
thaw(c, r);
2008-05-15 20:00:57 +00:00
2008-05-18 01:26:36 +00:00
if (DebugRegisters) {
fprintf(stderr, "replace %d with %d\n", r->number, s->number);
}
swap(c, r, s);
2008-05-15 20:00:57 +00:00
return s;
}
bool
buddies(Value* a, Value* b)
{
if (a == b) return true;
for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) return true;
}
return false;
}
Register*
2008-09-24 00:01:42 +00:00
acquire(Context* c, uint32_t mask, Stack* stack, Local* locals,
2008-07-17 23:34:38 +00:00
unsigned newSize, Value* newValue, RegisterSite* newSite)
2008-04-17 22:07:32 +00:00
{
Register* r = pickRegister(c, mask);
if (r->reserved) return r;
2008-04-19 00:19:45 +00:00
if (DebugRegisters) {
2008-10-04 17:26:35 +00:00
fprintf(stderr, "acquire %d value %p site %p freeze count %d "
2008-07-17 23:34:38 +00:00
"ref count %d used %d used exclusively %d\n",
r->number, newValue, newSite, r->freezeCount, r->refCount,
used(c, r), usedExclusively(c, r));
}
2008-04-19 00:19:45 +00:00
if (r->refCount) {
2008-11-17 15:44:35 +00:00
r = replace(c, r, newValue, stack, locals);
} else {
Value* oldValue = r->value;
if (oldValue
and oldValue != newValue
and findSite(c, oldValue, r->site))
{
if (buddies(oldValue, newValue)) {
removeSite(c, oldValue, r->site);
} else if (r->freezeCount) {
abort(c);
} else if (not trySteal(c, r, newValue, stack, locals)) {
2008-11-17 15:44:35 +00:00
r = replace(c, r, newValue, stack, locals);
}
2008-04-17 22:07:32 +00:00
}
}
r->size = newSize;
r->value = newValue;
r->site = newSite;
2008-04-21 00:21:48 +00:00
return r;
2008-04-17 22:07:32 +00:00
}
2008-04-19 00:19:45 +00:00
void
release(Context*, Register* r)
2008-04-19 00:19:45 +00:00
{
if (DebugRegisters) {
fprintf(stderr, "release %d\n", r->number);
}
r->size = 0;
r->value = 0;
r->site = 0;
2008-04-19 00:19:45 +00:00
}
2008-05-15 20:00:57 +00:00
Register*
2008-09-24 00:01:42 +00:00
validate(Context* c, uint32_t mask, Stack* stack, Local* locals,
2008-07-17 23:34:38 +00:00
unsigned size, Value* value, RegisterSite* site, Register* current)
2008-05-15 20:00:57 +00:00
{
if (current and (mask & (1 << current->number))) {
if (current->reserved or current->value == value) {
return current;
}
if (current->value == 0) {
2008-10-04 17:26:35 +00:00
if (DebugRegisters) {
fprintf(stderr,
"validate acquire %d value %p site %p freeze count %d "
"ref count %d\n",
current->number, value, site, current->freezeCount,
current->refCount);
}
current->size = size;
current->value = value;
current->site = site;
return current;
}
}
2008-07-17 23:34:38 +00:00
Register* r = acquire(c, mask, stack, locals, size, value, site);
if (current and current != r) {
2008-05-15 20:00:57 +00:00
release(c, current);
Assembler::Register rr(r->number);
Assembler::Register cr(current->number);
c->assembler->apply
2008-08-16 17:45:36 +00:00
(Move, BytesPerWord, RegisterOperand, &cr,
BytesPerWord, RegisterOperand, &rr);
2008-05-15 20:00:57 +00:00
}
return r;
2008-05-15 20:00:57 +00:00
}
bool
2008-11-17 15:20:48 +00:00
trySteal(Context* c, FrameResource* r, Value* thief, Stack* stack,
Local* locals)
{
2008-11-01 22:16:18 +00:00
assert(c, live(r->value));
2008-10-04 17:26:35 +00:00
2008-12-20 18:13:58 +00:00
int index = r - c->frameResources;
2008-10-04 17:26:35 +00:00
if (DebugFrameIndexes) {
fprintf(stderr,
"try steal frame index %d offset 0x%x from value %p site %p\n",
index, frameIndexToOffset(c, index), r->value, r->site);
}
2008-12-20 18:13:58 +00:00
freezeFrameIndex(c, index);
if (r->includeNeighbor) {
freezeFrameIndex(c, index + 1);
}
bool success = trySteal(c, r->site, thief, r->value, r->size, stack, locals);
if (r->includeNeighbor) {
thawFrameIndex(c, index + 1);
}
thawFrameIndex(c, index);
return success;
}
void
acquireFrameIndex(Context* c, int frameIndex, Stack* stack, Local* locals,
unsigned newSize, Value* newValue, MemorySite* newSite,
2008-11-17 15:20:48 +00:00
bool includeNeighbor)
{
assert(c, frameIndex >= 0);
assert(c, frameIndex < static_cast<int>
(c->alignedFrameSize + c->parameterFootprint));
2008-10-04 17:26:35 +00:00
if (DebugFrameIndexes) {
fprintf(stderr,
"acquire frame index %d offset 0x%x value %p site %p\n",
frameIndex, frameIndexToOffset(c, frameIndex), newValue, newSite);
2008-10-04 17:26:35 +00:00
}
FrameResource* r = c->frameResources + frameIndex;
2008-11-17 15:20:48 +00:00
includeNeighbor &= newSize > BytesPerWord;
if (includeNeighbor) {
acquireFrameIndex
(c, frameIndex + 1, stack, locals, newSize, newValue, newSite, false);
}
Value* oldValue = r->value;
if (oldValue
and oldValue != newValue
and findSite(c, oldValue, r->site))
{
if (buddies(oldValue, newValue)) {
removeSite(c, oldValue, r->site);
} else if (r->freezeCount) {
abort(c);
} else if (not trySteal(c, r, newValue, stack, locals)) {
abort(c);
}
}
2008-11-17 15:20:48 +00:00
r->includeNeighbor = includeNeighbor;
r->size = newSize;
r->value = newValue;
2008-10-04 17:26:35 +00:00
r->site = newSite;
}
void
2008-11-17 15:20:48 +00:00
releaseFrameIndex(Context* c, int frameIndex)
{
assert(c, frameIndex >= 0);
assert(c, frameIndex < static_cast<int>
(c->alignedFrameSize + c->parameterFootprint));
2008-10-04 17:26:35 +00:00
if (DebugFrameIndexes) {
fprintf(stderr, "release frame index %d offset 0x%x\n",
frameIndex, frameIndexToOffset(c, frameIndex));
2008-10-04 17:26:35 +00:00
}
FrameResource* r = c->frameResources + frameIndex;
2008-11-17 15:20:48 +00:00
if (r->includeNeighbor) {
releaseFrameIndex(c, frameIndex + 1);
}
r->size = 0;
r->value = 0;
r->site = 0;
}
2008-11-17 15:20:48 +00:00
void
freezeFrameIndex(Context* c, int frameIndex)
{
assert(c, frameIndex >= 0);
assert(c, frameIndex < static_cast<int>
(c->alignedFrameSize + c->parameterFootprint));
FrameResource* r = c->frameResources + frameIndex;
if (r->includeNeighbor) {
freezeFrameIndex(c, frameIndex + 1);
}
if (DebugFrameIndexes) {
fprintf(stderr, "freeze frame index %d offset 0x%x\n",
frameIndex, frameIndexToOffset(c, frameIndex));
}
2008-11-17 15:20:48 +00:00
2008-12-12 01:09:36 +00:00
++ r->freezeCount;
2008-11-17 15:20:48 +00:00
}
void
thawFrameIndex(Context* c, int frameIndex)
{
assert(c, frameIndex >= 0);
assert(c, frameIndex < static_cast<int>
(c->alignedFrameSize + c->parameterFootprint));
FrameResource* r = c->frameResources + frameIndex;
2008-12-12 01:09:36 +00:00
assert(c, r->freezeCount);
2008-11-17 15:20:48 +00:00
if (r->includeNeighbor) {
thawFrameIndex(c, frameIndex + 1);
}
if (DebugFrameIndexes) {
fprintf(stderr, "thaw frame index %d offset 0x%x\n",
frameIndex, frameIndexToOffset(c, frameIndex));
}
2008-11-17 15:20:48 +00:00
2008-12-12 01:09:36 +00:00
-- r->freezeCount;
2008-11-17 15:20:48 +00:00
}
2008-04-17 02:55:38 +00:00
void
2008-08-16 17:45:36 +00:00
apply(Context* c, UnaryOperation op,
unsigned s1Size, Site* s1)
{
OperandType s1Type = s1->type(c);
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
c->assembler->apply(op, s1Size, s1Type, s1Operand);
}
void
apply(Context* c, BinaryOperation op,
unsigned s1Size, Site* s1,
unsigned s2Size, Site* s2)
2008-04-17 02:55:38 +00:00
{
2008-08-16 17:45:36 +00:00
OperandType s1Type = s1->type(c);
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
OperandType s2Type = s2->type(c);
Assembler::Operand* s2Operand = s2->asAssemblerOperand(c);
2008-03-15 20:24:04 +00:00
2008-08-16 17:45:36 +00:00
c->assembler->apply(op, s1Size, s1Type, s1Operand,
s2Size, s2Type, s2Operand);
2008-04-17 02:55:38 +00:00
}
2008-04-17 02:55:38 +00:00
void
2008-08-16 17:45:36 +00:00
apply(Context* c, TernaryOperation op,
unsigned s1Size, Site* s1,
unsigned s2Size, Site* s2,
unsigned s3Size, Site* s3)
2008-04-17 02:55:38 +00:00
{
2008-08-16 17:45:36 +00:00
OperandType s1Type = s1->type(c);
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
2008-08-16 17:45:36 +00:00
OperandType s2Type = s2->type(c);
Assembler::Operand* s2Operand = s2->asAssemblerOperand(c);
2008-02-17 22:29:04 +00:00
2008-08-16 17:45:36 +00:00
OperandType s3Type = s3->type(c);
Assembler::Operand* s3Operand = s3->asAssemblerOperand(c);
c->assembler->apply(op, s1Size, s1Type, s1Operand,
s2Size, s2Type, s2Operand,
s3Size, s3Type, s3Operand);
2008-04-17 02:55:38 +00:00
}
void
addRead(Context* c, Event* e, Value* v, Read* r)
{
if (DebugReads) {
fprintf(stderr, "add read %p to %p last %p event %p (%s)\n", r, v, v->lastRead, e, (e ? e->name() : 0));
}
2008-09-25 00:48:32 +00:00
2008-08-28 22:43:35 +00:00
r->value = v;
if (e) {
r->event = e;
r->eventNext = e->reads;
e->reads = r;
++ e->readCount;
}
2008-04-17 02:55:38 +00:00
if (v->lastRead) {
2008-12-12 01:09:36 +00:00
// if (DebugReads) {
// fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
// }
v->lastRead->append(c, r);
} else {
v->reads = r;
2008-04-17 02:55:38 +00:00
}
v->lastRead = r;
}
2008-07-05 20:21:13 +00:00
void
2008-10-06 00:50:59 +00:00
clean(Context* c, Value* v, unsigned popIndex)
2008-07-05 20:21:13 +00:00
{
2008-11-01 22:16:18 +00:00
for (SiteIterator it(v); it.hasMore();) {
Site* s = it.next();
if (not (s->match(c, 1 << MemoryOperand, 0, AnyFrameIndex)
and offsetToFrameIndex
(c, static_cast<MemorySite*>(s)->value.offset)
>= popIndex))
2008-10-06 00:50:59 +00:00
{
2008-11-02 22:25:51 +00:00
// char buffer[256]; s->toString(c, buffer, 256);
// fprintf(stderr, "remove %s from %p at %d pop index %d\n",
// buffer, v, offsetToFrameIndex
// (c, static_cast<MemorySite*>(s)->value.offset), popIndex);
2008-11-01 22:16:18 +00:00
it.remove(c);
2008-07-05 20:21:13 +00:00
}
}
}
2008-04-17 22:07:32 +00:00
void
2008-10-06 00:50:59 +00:00
clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads,
unsigned popIndex)
{
2008-11-01 19:14:13 +00:00
for (FrameIterator it(c, stack, locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
clean(c, e.value, popIndex);
}
for (Read* r = reads; r; r = r->eventNext) {
2008-09-25 00:48:32 +00:00
nextRead(c, e, r->value);
}
}
CodePromise*
codePromise(Context* c, Event* e)
{
return e->promises = new (c->zone->allocate(sizeof(CodePromise)))
CodePromise(c, e->promises);
}
CodePromise*
codePromise(Context* c, Promise* offset)
{
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
}
void
append(Context* c, Event* e);
void
saveLocals(Context* c, Event* e)
{
for (unsigned li = 0; li < c->localFootprint; ++li) {
Local* local = e->localsBefore + li;
if (local->value) {
if (DebugReads) {
fprintf(stderr, "local save read %p of footprint %d at %d of %d\n",
local->value, local->footprint,
::frameIndex(c, li, local->footprint),
c->alignedFrameSize + c->parameterFootprint);
}
addRead(c, e, local->value, read
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
0, ::frameIndex(c, li, local->footprint)));
}
}
}
2008-04-17 02:55:38 +00:00
class CallEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-05-06 21:13:02 +00:00
CallEvent(Context* c, Value* address, unsigned flags,
2008-04-18 04:16:20 +00:00
TraceHandler* traceHandler, Value* result, unsigned resultSize,
Stack* argumentStack, unsigned argumentCount,
unsigned stackArgumentFootprint):
2008-04-17 02:55:38 +00:00
Event(c),
address(address),
traceHandler(traceHandler),
2008-04-17 20:48:26 +00:00
result(result),
popIndex(0),
padIndex(0),
padding(0),
2008-04-17 20:48:26 +00:00
flags(flags),
resultSize(resultSize)
{
2008-05-15 20:00:57 +00:00
uint32_t mask = ~0;
2008-04-19 00:19:45 +00:00
Stack* s = argumentStack;
2008-04-21 00:21:48 +00:00
unsigned index = 0;
unsigned frameIndex = 0;
2008-11-08 22:36:38 +00:00
if (argumentCount) {
unsigned ai = 0;
while (true) {
Read* target;
if (index < c->arch->argumentRegisterCount()) {
int r = c->arch->argumentRegister(index);
2008-11-08 22:36:38 +00:00
if (DebugReads) {
fprintf(stderr, "reg %d arg read %p\n", r, s->value);
}
2008-11-08 22:36:38 +00:00
target = fixedRegisterRead(c, footprintSizeInBytes(s->footprint), r);
mask &= ~(1 << r);
} else {
if (DebugReads) {
fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value);
}
target = read(c, footprintSizeInBytes(s->footprint),
1 << MemoryOperand, 0, frameIndex);
frameIndex += s->footprint;
}
2008-11-08 22:36:38 +00:00
addRead(c, this, s->value, target);
index += s->footprint;
2008-11-08 22:36:38 +00:00
if ((++ ai) < argumentCount) {
s = s->next;
} else {
break;
}
2008-04-19 00:19:45 +00:00
}
}
if (DebugReads) {
fprintf(stderr, "address read %p\n", address);
}
addRead(c, this, address, read
2008-08-28 22:43:35 +00:00
(c, BytesPerWord, ~0, (static_cast<uint64_t>(mask) << 32) | mask,
AnyFrameIndex));
2008-05-15 20:00:57 +00:00
int footprint = stackArgumentFootprint;
2008-10-04 17:26:35 +00:00
for (Stack* s = stackBefore; s; s = s->next) {
2008-09-23 21:18:41 +00:00
if (footprint > 0) {
if (DebugReads) {
2008-11-08 22:36:38 +00:00
fprintf(stderr, "stack arg read %p of footprint %d at %d of %d\n",
s->value, s->footprint, frameIndex,
c->alignedFrameSize + c->parameterFootprint);
}
2008-09-25 00:48:32 +00:00
addRead(c, this, s->value, read
2008-11-02 22:25:51 +00:00
(c, footprintSizeInBytes(s->footprint),
2008-09-25 00:48:32 +00:00
1 << MemoryOperand, 0, frameIndex));
2008-11-08 22:36:38 +00:00
} else {
unsigned logicalIndex = ::frameIndex
2008-11-08 22:36:38 +00:00
(c, s->index + c->localFootprint, s->footprint);
if (DebugReads) {
2008-11-08 22:36:38 +00:00
fprintf(stderr, "stack save read %p of footprint %d at %d of %d\n",
s->value, s->footprint, logicalIndex,
2008-11-08 22:36:38 +00:00
c->alignedFrameSize + c->parameterFootprint);
}
2008-09-23 21:18:41 +00:00
addRead(c, this, s->value, read
2008-11-08 22:36:38 +00:00
(c, footprintSizeInBytes(s->footprint), 1 << MemoryOperand,
0, logicalIndex));
}
2008-11-08 22:36:38 +00:00
2008-11-02 22:25:51 +00:00
footprint -= s->footprint;
2008-11-08 22:36:38 +00:00
if (footprint == 0) {
unsigned logicalIndex = ::frameIndex
(c, s->index + c->localFootprint, s->footprint);
assert(c, logicalIndex >= frameIndex);
padding = logicalIndex - frameIndex;
padIndex = s->index + c->localFootprint;
2008-11-08 22:36:38 +00:00
}
frameIndex += s->footprint;
2008-05-15 20:00:57 +00:00
}
2008-09-25 00:48:32 +00:00
popIndex = ::frameIndex
(c, (stackBefore
? stackBefore->index
+ stackBefore->footprint
- stackArgumentFootprint
: 0)
+ c->localFootprint, 0);
saveLocals(c, this);
2008-02-11 17:21:41 +00:00
}
virtual const char* name() {
return "CallEvent";
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
apply(c, (flags & Compiler::Aligned) ? AlignedCall : Call, BytesPerWord,
address->source);
if (traceHandler) {
traceHandler->handleTrace(codePromise(c, c->assembler->offset()),
padIndex, padding);
}
2008-10-06 00:50:59 +00:00
clean(c, this, stackBefore, localsBefore, reads, popIndex);
2008-04-19 00:19:45 +00:00
2008-07-05 20:21:13 +00:00
if (resultSize and live(result)) {
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, resultSize, result, registerSite
2008-08-28 22:43:35 +00:00
(c, c->arch->returnLow(),
2008-04-19 00:19:45 +00:00
resultSize > BytesPerWord ?
2008-08-28 22:43:35 +00:00
c->arch->returnHigh() : NoRegister));
2008-04-19 00:19:45 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
Value* address;
TraceHandler* traceHandler;
Value* result;
2008-10-06 00:50:59 +00:00
unsigned popIndex;
unsigned padIndex;
unsigned padding;
2008-04-17 20:48:26 +00:00
unsigned flags;
2008-04-18 04:16:20 +00:00
unsigned resultSize;
2008-02-11 17:21:41 +00:00
};
2008-02-11 17:21:41 +00:00
void
2008-05-06 21:13:02 +00:00
appendCall(Context* c, Value* address, unsigned flags,
2008-04-18 04:16:20 +00:00
TraceHandler* traceHandler, Value* result, unsigned resultSize,
Stack* argumentStack, unsigned argumentCount,
unsigned stackArgumentFootprint)
2008-02-11 17:21:41 +00:00
{
append(c, new (c->zone->allocate(sizeof(CallEvent)))
CallEvent(c, address, flags, traceHandler, result,
resultSize, argumentStack, argumentCount,
stackArgumentFootprint));
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
class ReturnEvent: public Event {
public:
2008-04-17 02:55:38 +00:00
ReturnEvent(Context* c, unsigned size, Value* value):
Event(c), value(value)
{
if (value) {
addRead(c, this, value, fixedRegisterRead
2008-08-28 22:43:35 +00:00
(c, size, c->arch->returnLow(),
2008-04-17 02:55:38 +00:00
size > BytesPerWord ?
2008-08-28 22:43:35 +00:00
c->arch->returnHigh() : NoRegister));
2008-04-17 02:55:38 +00:00
}
2008-03-15 20:24:04 +00:00
}
virtual const char* name() {
return "ReturnEvent";
}
virtual void compile(Context* c) {
2008-04-19 00:19:45 +00:00
if (value) {
2008-09-25 00:48:32 +00:00
nextRead(c, this, value);
2008-04-19 00:19:45 +00:00
}
2008-08-28 22:43:35 +00:00
c->assembler->popFrame();
2008-04-17 02:55:38 +00:00
c->assembler->apply(Return);
}
2008-04-17 02:55:38 +00:00
Value* value;
};
void
2008-04-17 22:07:32 +00:00
appendReturn(Context* c, unsigned size, Value* value)
{
append(c, new (c->zone->allocate(sizeof(ReturnEvent)))
ReturnEvent(c, size, value));
}
void
preserve(Context* c, Stack* stack, Local* locals, unsigned size, Value* v,
Site* s, Read* read)
{
2008-11-01 19:14:13 +00:00
Site* r = targetOrRegister(c, v, read);
move(c, stack, locals, size, v, s, r);
}
void
maybePreserve(Context* c, Stack* stack, Local* locals, unsigned size,
Value* v, Site* s)
{
2008-11-01 22:16:18 +00:00
Read* r = liveNext(c, v);
if (r and not hasMoreThanOneSite(v)) {
preserve(c, stack, locals, size, v, s, r);
}
}
void
addBuddy(Value* original, Value* buddy)
{
buddy->buddy = original;
Value* p = original;
while (p->buddy != original) p = p->buddy;
p->buddy = buddy;
// fprintf(stderr, "add buddy %p to", buddy);
// for (Value* p = buddy->buddy; p != buddy; p = p->buddy) {
// fprintf(stderr, " %p", p);
// }
// fprintf(stderr, "\n");
}
2008-04-17 02:55:38 +00:00
class MoveEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-08-16 17:45:36 +00:00
MoveEvent(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
2008-08-28 22:43:35 +00:00
unsigned dstSize, Value* dst, Read* srcRead, Read* dstRead):
2008-08-16 17:45:36 +00:00
Event(c), type(type), srcSize(srcSize), src(src), dstSize(dstSize),
2008-08-28 22:43:35 +00:00
dst(dst), dstRead(dstRead)
{
addRead(c, this, src, srcRead);
2008-03-15 20:24:04 +00:00
}
virtual const char* name() {
return "MoveEvent";
}
2008-03-15 20:24:04 +00:00
virtual void compile(Context* c) {
2008-11-01 19:14:13 +00:00
bool isStore = not live(dst);
2008-07-05 20:21:13 +00:00
Site* target = targetOrRegister(c, dst);
unsigned cost = src->source->copyCost(c, target);
if (srcSize != dstSize) cost = 1;
2008-10-19 00:15:57 +00:00
if (cost == 0) {
target = src->source;
addBuddy(src, dst);
if (DebugMoves) {
char dstb[256]; target->toString(c, dstb, 256);
fprintf(stderr, "null move in %s for %p to %p\n", dstb, src, dst);
}
}
2008-04-19 00:19:45 +00:00
addSite(c, stackBefore, localsBefore, dstSize, dst, target);
if (cost) {
2008-08-28 22:43:35 +00:00
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
dstRead->intersect(&typeMask, &registerMask, &frameIndex);
bool useTemporary = ((target->type(c) == MemoryOperand
and src->source->type(c) == MemoryOperand)
or (srcSize != dstSize
and target->type(c) != RegisterOperand));
2008-10-04 17:26:35 +00:00
if (target->match(c, typeMask, registerMask, frameIndex)
and not useTemporary)
2008-10-04 17:26:35 +00:00
{
if (DebugMoves) {
char srcb[256]; src->source->toString(c, srcb, 256);
char dstb[256]; target->toString(c, dstb, 256);
fprintf(stderr, "move %s to %s for %p to %p\n",
srcb, dstb, src, dst);
}
2008-10-19 00:15:57 +00:00
2008-08-16 17:45:36 +00:00
apply(c, type, srcSize, src->source, dstSize, target);
} else {
2008-08-28 22:43:35 +00:00
assert(c, typeMask & (1 << RegisterOperand));
2008-08-28 22:43:35 +00:00
Site* tmpTarget = freeRegisterSite(c, registerMask);
2008-10-04 17:26:35 +00:00
addSite(c, stackBefore, localsBefore, dstSize, dst, tmpTarget);
if (DebugMoves) {
char srcb[256]; src->source->toString(c, srcb, 256);
char dstb[256]; tmpTarget->toString(c, dstb, 256);
fprintf(stderr, "move %s to %s for %p to %p\n",
srcb, dstb, src, dst);
}
2008-10-19 00:15:57 +00:00
2008-08-16 17:45:36 +00:00
apply(c, type, srcSize, src->source, dstSize, tmpTarget);
if (useTemporary or isStore) {
if (DebugMoves) {
char srcb[256]; tmpTarget->toString(c, srcb, 256);
char dstb[256]; target->toString(c, dstb, 256);
fprintf(stderr, "move %s to %s for %p to %p\n",
srcb, dstb, src, dst);
}
2008-10-19 00:15:57 +00:00
2008-08-16 17:45:36 +00:00
apply(c, Move, dstSize, tmpTarget, dstSize, target);
if (isStore) {
removeSite(c, dst, tmpTarget);
}
2008-05-18 01:26:36 +00:00
} else {
removeSite(c, dst, target);
}
}
}
if (isStore) {
2008-04-20 19:35:36 +00:00
removeSite(c, dst, target);
}
2008-05-18 01:26:36 +00:00
2008-09-25 00:48:32 +00:00
nextRead(c, this, src);
2007-12-11 21:26:59 +00:00
}
2008-04-17 02:55:38 +00:00
BinaryOperation type;
2008-08-16 17:45:36 +00:00
unsigned srcSize;
2008-04-17 02:55:38 +00:00
Value* src;
2008-08-16 17:45:36 +00:00
unsigned dstSize;
2008-04-17 02:55:38 +00:00
Value* dst;
2008-08-28 22:43:35 +00:00
Read* dstRead;
2008-02-11 17:21:41 +00:00
};
2007-12-11 21:26:59 +00:00
void
2008-08-28 22:43:35 +00:00
appendMove(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
unsigned dstSize, Value* dst)
2007-12-11 21:26:59 +00:00
{
bool thunk;
2008-08-28 22:43:35 +00:00
uint8_t srcTypeMask;
uint64_t srcRegisterMask;
uint8_t dstTypeMask;
uint64_t dstRegisterMask;
2008-08-28 22:43:35 +00:00
c->arch->plan(type, srcSize, &srcTypeMask, &srcRegisterMask,
dstSize, &dstTypeMask, &dstRegisterMask,
&thunk);
assert(c, not thunk); // todo
append(c, new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent
(c, type, srcSize, src, dstSize, dst,
read(c, srcSize, srcTypeMask, srcRegisterMask, AnyFrameIndex),
read(c, dstSize, dstTypeMask, dstRegisterMask, AnyFrameIndex)));
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
ConstantSite*
findConstantSite(Context* c, Value* v)
{
2008-11-01 22:16:18 +00:00
for (SiteIterator it(v); it.hasMore();) {
Site* s = it.next();
if (s->type(c) == ConstantOperand) {
return static_cast<ConstantSite*>(s);
}
}
return 0;
}
2008-04-17 02:55:38 +00:00
class CompareEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
CompareEvent(Context* c, unsigned size, Value* first, Value* second,
2008-08-28 22:43:35 +00:00
Read* firstRead, Read* secondRead):
2008-04-17 02:55:38 +00:00
Event(c), size(size), first(first), second(second)
{
addRead(c, this, first, firstRead);
addRead(c, this, second, secondRead);
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
virtual const char* name() {
return "CompareEvent";
}
2008-03-15 20:24:04 +00:00
virtual void compile(Context* c) {
ConstantSite* firstConstant = findConstantSite(c, first);
ConstantSite* secondConstant = findConstantSite(c, second);
if (firstConstant and secondConstant) {
int64_t d = firstConstant->value.value->value()
- secondConstant->value.value->value();
if (d < 0) {
c->constantCompare = CompareLess;
} else if (d > 0) {
c->constantCompare = CompareGreater;
} else {
c->constantCompare = CompareEqual;
}
} else {
c->constantCompare = CompareNone;
2008-08-16 17:45:36 +00:00
apply(c, Compare, size, first->source, size, second->source);
}
2008-04-19 00:19:45 +00:00
2008-09-25 00:48:32 +00:00
nextRead(c, this, first);
nextRead(c, this, second);
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
2008-04-17 02:55:38 +00:00
unsigned size;
Value* first;
Value* second;
2008-02-11 17:21:41 +00:00
};
2007-12-11 21:26:59 +00:00
void
2008-04-17 02:55:38 +00:00
appendCompare(Context* c, unsigned size, Value* first, Value* second)
2007-12-11 21:26:59 +00:00
{
bool thunk;
2008-08-28 22:43:35 +00:00
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t secondTypeMask;
uint64_t secondRegisterMask;
2008-08-28 22:43:35 +00:00
c->arch->plan(Compare, size, &firstTypeMask, &firstRegisterMask,
size, &secondTypeMask, &secondRegisterMask,
&thunk);
assert(c, not thunk); // todo
append(c, new (c->zone->allocate(sizeof(CompareEvent)))
CompareEvent
(c, size, first, second,
read(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex),
read(c, size, secondTypeMask, secondRegisterMask, AnyFrameIndex)));
2008-02-11 17:21:41 +00:00
}
class CombineEvent: public Event {
public:
2008-08-16 17:45:36 +00:00
CombineEvent(Context* c, TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result,
2008-09-07 20:12:11 +00:00
Read* firstRead,
Read* secondRead,
Read* resultRead):
2008-08-16 17:45:36 +00:00
Event(c), type(type), firstSize(firstSize), first(first),
secondSize(secondSize), second(second), resultSize(resultSize),
2008-09-07 20:12:11 +00:00
result(result), resultRead(resultRead)
{
addRead(c, this, first, firstRead);
addRead(c, this, second, secondRead);
2008-02-11 17:21:41 +00:00
}
virtual const char* name() {
return "CombineEvent";
}
virtual void compile(Context* c) {
first->source->freeze(c);
2008-09-07 20:12:11 +00:00
Site* target;
if (c->arch->condensedAddressing()) {
2008-10-04 17:26:35 +00:00
maybePreserve(c, stackBefore, localsBefore, secondSize, second,
second->source);
2008-09-07 20:12:11 +00:00
target = second->source;
if (liveNext(c, second)) {
c->forfeitedSite = target;
}
2008-09-07 20:12:11 +00:00
} else {
target = resultRead->allocateSite(c);
2008-10-04 17:26:35 +00:00
addSite(c, stackBefore, localsBefore, resultSize, result, target);
2008-09-07 20:12:11 +00:00
}
first->source->thaw(c);
2008-10-04 17:26:35 +00:00
// fprintf(stderr, "combine %p and %p into %p\n", first, second, result);
2008-08-16 17:45:36 +00:00
apply(c, type, firstSize, first->source, secondSize, second->source,
resultSize, target);
2008-04-19 00:19:45 +00:00
2008-09-25 00:48:32 +00:00
nextRead(c, this, first);
nextRead(c, this, second);
2008-09-23 21:18:41 +00:00
2008-11-11 00:07:44 +00:00
if (c->arch->condensedAddressing()) {
2008-12-12 01:09:36 +00:00
c->forfeitedSite = 0;
removeSite(c, second, target);
2008-11-11 00:07:44 +00:00
if (live(result)) {
addSite(c, 0, 0, resultSize, result, target);
}
2008-09-23 21:18:41 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-08-28 22:43:35 +00:00
TernaryOperation type;
2008-08-16 17:45:36 +00:00
unsigned firstSize;
2008-04-17 02:55:38 +00:00
Value* first;
2008-08-16 17:45:36 +00:00
unsigned secondSize;
2008-04-17 02:55:38 +00:00
Value* second;
2008-08-16 17:45:36 +00:00
unsigned resultSize;
2008-04-17 22:07:32 +00:00
Value* result;
2008-09-07 20:12:11 +00:00
Read* resultRead;
2008-02-11 17:21:41 +00:00
};
2008-05-06 21:13:02 +00:00
Value*
value(Context* c, Site* site = 0, Site* target = 0)
{
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
}
2008-11-01 19:14:13 +00:00
void
2008-11-01 22:16:18 +00:00
removeBuddy(Context* c, Value* v)
2008-11-01 19:14:13 +00:00
{
if (v->buddy != v) {
2008-11-02 22:25:51 +00:00
// fprintf(stderr, "remove buddy %p from", v);
// for (Value* p = v->buddy; p != v; p = p->buddy) {
// fprintf(stderr, " %p", p);
// }
// fprintf(stderr, "\n");
2008-11-01 19:14:13 +00:00
Value* next = v->buddy;
v->buddy = v;
Value* p = next;
while (p->buddy != v) p = p->buddy;
p->buddy = next;
2008-11-01 22:16:18 +00:00
if (not live(next)) {
clearSites(c, next);
}
if (not live(v)) {
clearSites(c, v);
}
2008-11-01 19:14:13 +00:00
}
}
2008-11-01 22:16:18 +00:00
Site*
copy(Context* c, Site* s)
{
Site* start = 0;
Site* end = 0;
for (; s; s = s->next) {
Site* n = s->copy(c);
if (end) {
end->next = n;
} else {
start = n;
}
end = n;
}
return start;
}
class Snapshot {
public:
Snapshot(Context* c, Value* value, Snapshot* next):
value(value), buddy(value->buddy), sites(copy(c, value->sites)), next(next)
{ }
Value* value;
Value* buddy;
Site* sites;
Snapshot* next;
};
Snapshot*
snapshot(Context* c, Value* value, Snapshot* next)
{
2008-11-02 22:25:51 +00:00
if (DebugControl) {
char buffer[256]; toString(c, value->sites, buffer, 256);
fprintf(stderr, "snapshot %p buddy %p sites %s\n",
value, value->buddy, buffer);
}
2008-11-01 22:16:18 +00:00
return new (c->zone->allocate(sizeof(Snapshot))) Snapshot(c, value, next);
}
Snapshot*
makeSnapshots(Context* c, Value* value, Snapshot* next)
{
next = snapshot(c, value, next);
for (Value* p = value->buddy; p != value; p = p->buddy) {
next = snapshot(c, p, next);
}
return next;
}
2008-08-28 22:43:35 +00:00
Stack*
stack(Context* c, Value* value, unsigned footprint, unsigned index,
Stack* next)
2008-08-28 22:43:35 +00:00
{
return new (c->zone->allocate(sizeof(Stack)))
Stack(index, footprint, value, next);
2008-08-28 22:43:35 +00:00
}
Stack*
stack(Context* c, Value* value, unsigned footprint, Stack* next)
2008-08-28 22:43:35 +00:00
{
return stack
(c, value, footprint, (next ? next->index + next->footprint : 0), next);
}
SavedValue*
savedValue(Context* c, Value* value, unsigned footprint, SavedValue* next)
{
return new (c->zone->allocate(sizeof(SavedValue)))
SavedValue(footprint, value, next);
2008-08-28 22:43:35 +00:00
}
2008-11-02 20:35:35 +00:00
Value*
maybeBuddy(Context* c, Value* v, unsigned sizeInBytes);
2008-02-11 17:21:41 +00:00
void
2008-11-02 22:25:51 +00:00
push(Context* c, unsigned footprint, Value* v)
2008-02-11 17:21:41 +00:00
{
2008-11-02 22:25:51 +00:00
assert(c, footprint);
2008-11-02 22:25:51 +00:00
v = maybeBuddy(c, v, footprintSizeInBytes(footprint));
2008-11-02 20:35:35 +00:00
2008-11-02 22:25:51 +00:00
if (DebugFrame) {
fprintf(stderr, "push %p of footprint %d\n", v, footprint);
}
2008-11-02 20:35:35 +00:00
2008-11-01 19:14:13 +00:00
v->local = true;
2008-11-02 22:25:51 +00:00
c->stack = stack(c, v, footprint, c->stack);
2008-08-28 22:43:35 +00:00
}
2008-08-28 22:43:35 +00:00
Value*
2008-11-02 22:25:51 +00:00
pop(Context* c, unsigned footprint UNUSED)
2008-08-28 22:43:35 +00:00
{
Stack* s = c->stack;
2008-11-02 22:25:51 +00:00
assert(c, footprint == s->footprint);
2008-11-02 20:35:35 +00:00
assert(c, s->value->local);
2008-11-02 22:25:51 +00:00
if (DebugFrame) {
fprintf(stderr, "pop %p of size %d\n", s->value, footprint);
}
2008-08-28 22:43:35 +00:00
c->stack = s->next;
2008-11-01 19:14:13 +00:00
s->value->local = false;
2008-08-28 22:43:35 +00:00
return s->value;
}
void
appendCombine(Context* c, TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result)
{
bool thunk;
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t secondTypeMask;
uint64_t secondRegisterMask;
uint8_t resultTypeMask;
uint64_t resultRegisterMask;
c->arch->plan(type, firstSize, &firstTypeMask, &firstRegisterMask,
secondSize, &secondTypeMask, &secondRegisterMask,
resultSize, &resultTypeMask, &resultRegisterMask,
&thunk);
2008-05-16 00:35:17 +00:00
2008-08-28 22:43:35 +00:00
if (thunk) {
Stack* oldStack = c->stack;
2008-11-02 22:25:51 +00:00
::push(c, ceiling(secondSize, BytesPerWord), second);
::push(c, ceiling(firstSize, BytesPerWord), first);
2008-04-18 03:47:42 +00:00
Stack* argumentStack = c->stack;
c->stack = oldStack;
2008-08-28 22:43:35 +00:00
appendCall
(c, value(c, constantSite(c, c->client->getThunk(type, resultSize))),
0, 0, result, resultSize, argumentStack, 2, 0);
} else {
2008-09-07 20:12:11 +00:00
Read* resultRead = read
(c, resultSize, resultTypeMask, resultRegisterMask, AnyFrameIndex);
Read* secondRead;
if (c->arch->condensedAddressing()) {
secondRead = resultRead;
} else {
secondRead = read
(c, secondSize, secondTypeMask, secondRegisterMask, AnyFrameIndex);
}
append
(c, new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent
(c, type,
firstSize, first,
secondSize, second,
resultSize, result,
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex),
secondRead,
resultRead));
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
class TranslateEvent: public Event {
public:
2008-08-28 22:43:35 +00:00
TranslateEvent(Context* c, BinaryOperation type, unsigned size, Value* value,
2008-10-15 00:45:31 +00:00
Value* result, Read* valueRead, Read* resultRead):
Event(c), type(type), size(size), value(value), result(result),
resultRead(resultRead)
{
2008-10-15 00:45:31 +00:00
addRead(c, this, value, valueRead);
2008-03-15 20:24:04 +00:00
}
virtual const char* name() {
return "TranslateEvent";
}
virtual void compile(Context* c) {
2008-10-15 00:45:31 +00:00
Site* target;
if (c->arch->condensedAddressing()) {
maybePreserve(c, stackBefore, localsBefore, size, value, value->source);
target = value->source;
if (liveNext(c, value)) {
c->forfeitedSite = target;
}
2008-10-15 00:45:31 +00:00
} else {
target = resultRead->allocateSite(c);
addSite(c, stackBefore, localsBefore, size, result, target);
}
2008-08-28 22:43:35 +00:00
apply(c, type, size, value->source, size, target);
2008-04-19 00:19:45 +00:00
2008-09-25 00:48:32 +00:00
nextRead(c, this, value);
2008-04-19 00:19:45 +00:00
2008-11-11 00:07:44 +00:00
if (c->arch->condensedAddressing()) {
2008-12-12 01:09:36 +00:00
c->forfeitedSite = 0;
removeSite(c, value, target);
2008-11-11 00:07:44 +00:00
if (live(result)) {
addSite(c, 0, 0, size, result, target);
}
2008-04-21 00:21:48 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-08-28 22:43:35 +00:00
BinaryOperation type;
unsigned size;
2008-04-17 02:55:38 +00:00
Value* value;
Value* result;
2008-10-15 00:45:31 +00:00
Read* resultRead;
2008-02-11 17:21:41 +00:00
};
2008-02-11 17:21:41 +00:00
void
2008-08-28 22:43:35 +00:00
appendTranslate(Context* c, BinaryOperation type, unsigned size, Value* value,
2008-04-17 02:55:38 +00:00
Value* result)
2008-02-11 17:21:41 +00:00
{
bool thunk;
2008-08-28 22:43:35 +00:00
uint8_t firstTypeMask;
uint64_t firstRegisterMask;
uint8_t resultTypeMask;
uint64_t resultRegisterMask;
2008-08-28 22:43:35 +00:00
c->arch->plan(type, size, &firstTypeMask, &firstRegisterMask,
size, &resultTypeMask, &resultRegisterMask,
&thunk);
assert(c, not thunk); // todo
2008-10-15 00:45:31 +00:00
Read* resultRead = read
(c, size, resultTypeMask, resultRegisterMask, AnyFrameIndex);
Read* firstRead;
if (c->arch->condensedAddressing()) {
firstRead = resultRead;
} else {
firstRead = read
(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex);
}
2008-08-28 22:43:35 +00:00
// todo: respect resultTypeMask and resultRegisterMask
append(c, new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent
2008-10-15 00:45:31 +00:00
(c, type, size, value, result, firstRead, resultRead));
2008-02-11 17:21:41 +00:00
}
2008-03-15 23:54:20 +00:00
class MemoryEvent: public Event {
public:
2008-04-17 20:48:26 +00:00
MemoryEvent(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result):
Event(c), base(base), displacement(displacement), index(index),
scale(scale), result(result)
2008-03-15 23:54:20 +00:00
{
addRead(c, this, base, anyRegisterRead(c, BytesPerWord));
if (index) addRead(c, this, index, registerOrConstantRead(c, BytesPerWord));
}
virtual const char* name() {
return "MemoryEvent";
2008-03-15 23:54:20 +00:00
}
2008-04-17 22:07:32 +00:00
virtual void compile(Context* c) {
2008-04-17 20:48:26 +00:00
int indexRegister;
int displacement = this->displacement;
unsigned scale = this->scale;
2008-04-17 20:48:26 +00:00
if (index) {
ConstantSite* constant = findConstantSite(c, index);
if (constant) {
indexRegister = NoRegister;
displacement += (constant->value.value->value() * scale);
scale = 1;
} else {
assert(c, index->source->type(c) == RegisterOperand);
indexRegister = static_cast<RegisterSite*>
(index->source)->register_.low;
}
2008-04-17 20:48:26 +00:00
} else {
indexRegister = NoRegister;
}
2008-04-18 00:39:41 +00:00
assert(c, base->source->type(c) == RegisterOperand);
int baseRegister = static_cast<RegisterSite*>(base->source)->register_.low;
2008-04-17 20:48:26 +00:00
2008-09-25 00:48:32 +00:00
nextRead(c, this, base);
2008-04-19 00:19:45 +00:00
if (index) {
if (BytesPerWord == 8 and indexRegister != NoRegister) {
2008-08-28 22:43:35 +00:00
apply(c, Move, 4, index->source, 8, index->source);
}
2008-09-25 00:48:32 +00:00
nextRead(c, this, index);
2008-04-19 00:19:45 +00:00
}
2008-04-19 21:52:45 +00:00
result->target = memorySite
(c, baseRegister, displacement, indexRegister, scale);
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, 0, result, result->target);
2008-03-15 23:54:20 +00:00
}
2008-04-17 02:55:38 +00:00
Value* base;
2008-04-17 20:48:26 +00:00
int displacement;
2008-04-17 02:55:38 +00:00
Value* index;
2008-04-17 20:48:26 +00:00
unsigned scale;
2008-04-17 02:55:38 +00:00
Value* result;
2008-03-15 23:54:20 +00:00
};
void
2008-04-17 20:48:26 +00:00
appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result)
2008-04-17 02:55:38 +00:00
{
append(c, new (c->zone->allocate(sizeof(MemoryEvent)))
MemoryEvent(c, base, displacement, index, scale, result));
2008-04-17 20:48:26 +00:00
}
2008-04-20 05:23:08 +00:00
class BranchEvent: public Event {
public:
BranchEvent(Context* c, UnaryOperation type, Value* address):
Event(c), type(type), address(address)
{
2008-09-20 23:42:46 +00:00
address->addPredecessor(c, this);
addRead(c, this, address, read
(c, BytesPerWord, ~0, ~static_cast<uint64_t>(0), AnyFrameIndex));
2008-04-20 05:23:08 +00:00
}
virtual const char* name() {
return "BranchEvent";
}
2008-04-20 05:23:08 +00:00
virtual void compile(Context* c) {
bool jump;
UnaryOperation type = this->type;
if (type != Jump) {
switch (c->constantCompare) {
case CompareLess:
switch (type) {
case JumpIfLess:
case JumpIfLessOrEqual:
case JumpIfNotEqual:
jump = true;
type = Jump;
break;
default:
jump = false;
}
break;
case CompareGreater:
switch (type) {
case JumpIfGreater:
case JumpIfGreaterOrEqual:
case JumpIfNotEqual:
jump = true;
type = Jump;
break;
default:
jump = false;
}
break;
case CompareEqual:
switch (type) {
case JumpIfEqual:
case JumpIfLessOrEqual:
case JumpIfGreaterOrEqual:
jump = true;
type = Jump;
break;
default:
jump = false;
}
break;
case CompareNone:
jump = true;
break;
default: abort(c);
}
} else {
jump = true;
}
if (jump) {
apply(c, type, BytesPerWord, address->source);
}
2008-04-20 05:23:08 +00:00
2008-09-25 00:48:32 +00:00
nextRead(c, this, address);
2008-04-20 05:23:08 +00:00
}
virtual bool isBranch() { return true; }
2008-04-20 05:23:08 +00:00
UnaryOperation type;
Value* address;
};
void
appendBranch(Context* c, UnaryOperation type, Value* address)
{
append(c, new (c->zone->allocate(sizeof(BranchEvent)))
BranchEvent(c, type, address));
2008-04-18 03:47:42 +00:00
}
class BoundsCheckEvent: public Event {
public:
BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler):
Event(c), object(object), lengthOffset(lengthOffset), index(index),
handler(handler)
{
addRead(c, this, object, anyRegisterRead(c, BytesPerWord));
addRead(c, this, index, registerOrConstantRead(c, BytesPerWord));
}
virtual const char* name() {
return "BoundsCheckEvent";
}
virtual void compile(Context* c) {
Assembler* a = c->assembler;
ConstantSite* constant = findConstantSite(c, index);
2008-08-30 20:12:27 +00:00
CodePromise* nextPromise = codePromise
(c, static_cast<Promise*>(0));
CodePromise* outOfBoundsPromise = 0;
if (constant) {
expect(c, constant->value.value->value() >= 0);
} else {
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
2008-08-30 20:12:27 +00:00
apply(c, Compare, 4, constantSite(c, resolved(c, 0)), 4, index->source);
Assembler::Constant outOfBoundsConstant(outOfBoundsPromise);
a->apply
(JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant);
}
assert(c, object->source->type(c) == RegisterOperand);
int base = static_cast<RegisterSite*>(object->source)->register_.low;
Site* length = memorySite(c, base, lengthOffset);
2008-08-30 20:12:27 +00:00
length->acquire(c, 0, 0, 0, 0);
2008-08-30 20:12:27 +00:00
apply(c, Compare, 4, index->source, 4, length);
length->release(c);
Assembler::Constant nextConstant(nextPromise);
a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant);
if (constant == 0) {
2008-08-30 20:12:27 +00:00
outOfBoundsPromise->offset = a->offset();
}
Assembler::Constant handlerConstant(resolved(c, handler));
a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant);
2008-08-30 20:12:27 +00:00
nextPromise->offset = a->offset();
2008-09-25 00:48:32 +00:00
nextRead(c, this, object);
nextRead(c, this, index);
}
Value* object;
unsigned lengthOffset;
Value* index;
intptr_t handler;
};
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler)
{
append(c, new (c->zone->allocate(sizeof(BoundsCheckEvent)))
BoundsCheckEvent(c, object, lengthOffset, index, handler));
}
2008-09-25 00:48:32 +00:00
class FrameSiteEvent: public Event {
public:
2008-09-25 00:48:32 +00:00
FrameSiteEvent(Context* c, Value* value, unsigned size, int index):
Event(c), value(value), size(size), index(index)
{ }
virtual const char* name() {
2008-09-25 00:48:32 +00:00
return "FrameSiteEvent";
}
virtual void compile(Context* c) {
if (live(value)) {
addSite(c, stackBefore, localsBefore, size, value, frameSite(c, index));
}
}
Value* value;
unsigned size;
int index;
};
void
2008-09-25 00:48:32 +00:00
appendFrameSite(Context* c, Value* value, unsigned size, int index)
{
append(c, new (c->zone->allocate(sizeof(FrameSiteEvent)))
FrameSiteEvent(c, value, size, index));
}
unsigned
frameFootprint(Context* c, Stack* s)
{
2008-11-02 22:25:51 +00:00
return c->localFootprint + (s ? (s->index + s->footprint) : 0);
}
void
2008-10-15 00:45:31 +00:00
visit(Context* c, Link* link)
{
2008-12-12 01:09:36 +00:00
// fprintf(stderr, "visit link from %d to %d fork %p junction %p\n",
// link->predecessor->logicalInstruction->index,
2008-12-12 01:09:36 +00:00
// link->successor->logicalInstruction->index,
// link->forkState,
// link->junctionState);
ForkState* forkState = link->forkState;
if (forkState) {
for (unsigned i = 0; i < forkState->readCount; ++i) {
2008-11-02 20:35:35 +00:00
ForkElement* p = forkState->elements + i;
Value* v = p->value;
v->reads = p->read->nextTarget();
// fprintf(stderr, "next read %p for %p\n", v->reads, v);
if (not live(v)) {
clearSites(c, v);
}
}
}
JunctionState* junctionState = link->junctionState;
if (junctionState) {
for (unsigned i = 0; i < junctionState->frameFootprint; ++i) {
StubReadPair* p = junctionState->reads + i;
if (p->value) {
assert(c, p->value->reads == p->read);
nextRead(c, 0, p->value);
}
}
}
}
2008-11-01 19:14:13 +00:00
class BuddyEvent: public Event {
public:
BuddyEvent(Context* c, Value* original, Value* buddy, unsigned size):
Event(c), original(original), buddy(buddy)
{
addRead(c, this, original,
read(c, size, ~0, ~static_cast<uint64_t>(0), AnyFrameIndex));
}
virtual const char* name() {
return "BuddyEvent";
}
virtual void compile(Context* c) {
2008-12-12 01:09:36 +00:00
// fprintf(stderr, "original %p buddy %p\n", original, buddy);
assert(c, hasSite(original));
addBuddy(original, buddy);
2008-11-01 19:14:13 +00:00
nextRead(c, this, original);
}
Value* original;
Value* buddy;
};
void
appendBuddy(Context* c, Value* original, Value* buddy, unsigned size)
{
append(c, new (c->zone->allocate(sizeof(BuddyEvent)))
BuddyEvent(c, original, buddy, size));
}
class SaveLocalsEvent: public Event {
public:
SaveLocalsEvent(Context* c):
Event(c)
{
saveLocals(c, this);
}
virtual const char* name() {
return "SaveLocalsEvent";
}
virtual void compile(Context* c) {
for (Read* r = reads; r; r = r->eventNext) {
nextRead(c, this, r->value);
}
}
};
void
appendSaveLocals(Context* c)
{
append(c, new (c->zone->allocate(sizeof(SaveLocalsEvent)))
SaveLocalsEvent(c));
}
class DummyEvent: public Event {
public:
DummyEvent(Context* c):
Event(c)
{ }
virtual const char* name() {
return "DummyEvent";
}
virtual void compile(Context*) { }
};
void
appendDummy(Context* c)
{
Stack* stack = c->stack;
Local* locals = c->locals;
LogicalInstruction* i = c->logicalCode[c->logicalIp];
c->stack = i->stack;
c->locals = i->locals;
append(c, new (c->zone->allocate(sizeof(DummyEvent))) DummyEvent(c));
c->stack = stack;
c->locals = locals;
}
void
append(Context* c, Event* e)
{
LogicalInstruction* i = c->logicalCode[c->logicalIp];
if (c->stack != i->stack or c->locals != i->locals) {
appendDummy(c);
}
if (DebugAppend) {
fprintf(stderr, " -- append %s at %d with %d stack before\n",
e->name(), e->logicalInstruction->index, c->stack ?
2008-11-02 22:25:51 +00:00
c->stack->index + c->stack->footprint : 0);
}
if (c->lastEvent) {
c->lastEvent->next = e;
} else {
c->firstEvent = e;
}
c->lastEvent = e;
Event* p = c->predecessor;
if (p) {
Link* link = ::link(c, p, e->predecessors, e, p->successors, c->forkState);
e->predecessors = link;
p->successors = link;
}
c->forkState = 0;
c->predecessor = e;
if (e->logicalInstruction->firstEvent == 0) {
e->logicalInstruction->firstEvent = e;
}
e->logicalInstruction->lastEvent = e;
}
2008-04-18 03:47:42 +00:00
Site*
2008-09-24 00:01:42 +00:00
readSource(Context* c, Stack* stack, Local* locals, Read* r)
2008-04-18 03:47:42 +00:00
{
2008-11-02 20:35:35 +00:00
if (not hasSite(r->value)) return 0;
if (DebugReads) {
char buffer[256]; toString(c, r->value->sites, buffer, 256);
fprintf(stderr, "read source for %p from %s\n", r->value, buffer);
}
2008-05-15 20:00:57 +00:00
2008-11-02 20:35:35 +00:00
Site* site = r->pickSite(c, r->value, true);
2008-04-18 03:47:42 +00:00
2008-08-30 20:12:27 +00:00
if (site) {
2008-04-18 00:39:41 +00:00
return site;
2008-08-30 20:12:27 +00:00
} else {
Site* target = r->allocateSite(c);
unsigned copyCost;
2008-11-02 20:35:35 +00:00
site = pick(c, r->value, target, &copyCost, true);
2008-08-30 20:12:27 +00:00
assert(c, copyCost);
2008-10-04 17:26:35 +00:00
move(c, stack, locals, r->size, r->value, site, target);
2008-08-30 20:12:27 +00:00
return target;
2008-04-17 02:55:38 +00:00
}
2007-12-11 21:26:59 +00:00
}
bool
acceptJunctionSite(Context* c, Site* s)
{
return s
and (c->availableRegisterCount > 1 or s->type(c) != RegisterOperand);
}
2008-07-23 23:58:29 +00:00
Site*
pickJunctionSite(Context* c, Value* v, Read* r, unsigned frameIndex)
2008-07-23 23:58:29 +00:00
{
2008-11-02 20:35:35 +00:00
Site* s = r->pickSite(c, v, false);
if (not acceptJunctionSite(c, s)) {
2008-11-02 20:35:35 +00:00
s = pick(c, v, 0, 0, false);
}
2008-10-04 17:26:35 +00:00
if (acceptJunctionSite(c, s) and s->match
2008-11-02 20:35:35 +00:00
(c, (1 << RegisterOperand) | (1 << MemoryOperand), ~0, AnyFrameIndex))
{
return s;
}
s = r->allocateSite(c);
2008-10-04 17:26:35 +00:00
if (acceptJunctionSite(c, s)) {
2008-11-02 20:35:35 +00:00
return s;
}
2008-11-01 19:14:13 +00:00
2008-11-02 20:35:35 +00:00
if (c->availableRegisterCount > 1) {
return freeRegisterSite(c);
} else {
return frameSite(c, frameIndex);
}
2008-07-23 23:58:29 +00:00
}
unsigned
resolveJunctionSite(Context* c, Event* e, Value* v,
unsigned siteIndex, unsigned frameIndex,
2008-10-04 17:26:35 +00:00
Site** frozenSites, unsigned frozenSiteIndex)
2008-07-23 23:58:29 +00:00
{
assert(c, siteIndex < frameFootprint(c, e->stackAfter));
2008-07-23 23:58:29 +00:00
if (live(v)) {
2008-11-01 22:16:18 +00:00
assert(c, hasSite(v));
2008-09-25 00:48:32 +00:00
Read* r = live(v);
Site* original = e->junctionSites[siteIndex];
Site* target;
2008-07-23 23:58:29 +00:00
if (original) {
target = original;
} else {
target = pickJunctionSite(c, v, r, frameIndex);
2008-07-23 23:58:29 +00:00
}
unsigned copyCost;
2008-11-02 20:35:35 +00:00
Site* site = pick(c, v, target, &copyCost, true);
2008-11-01 22:16:18 +00:00
if (copyCost or not (original or findSite(c, v, site))) {
if (original) {
target = target->copy(c);
}
2008-10-04 17:26:35 +00:00
move(c, e->stackAfter, e->localsAfter, r->size, v, site, target);
2008-09-25 00:48:32 +00:00
} else {
target = site;
2008-07-23 23:58:29 +00:00
}
if (original == 0) {
frozenSites[frozenSiteIndex++] = target;
target->freeze(c);
e->junctionSites[siteIndex] = target->copy(c);
2008-07-23 23:58:29 +00:00
}
2008-11-02 22:25:51 +00:00
if (DebugControl) {
char buffer[256]; target->toString(c, buffer, 256);
2008-11-11 00:07:44 +00:00
fprintf(stderr, "resolved junction site local %d frame %d %s %p\n",
siteIndex, frameIndex, buffer, v);
2008-11-02 22:25:51 +00:00
}
2008-12-12 01:09:36 +00:00
} else if (DebugControl) {
fprintf(stderr, "skip dead junction site local %d frame %d %p\n",
siteIndex, frameIndex, v);
2008-07-23 23:58:29 +00:00
}
return frozenSiteIndex;
}
void
propagateJunctionSites(Context* c, Event* e, Site** sites)
{
for (Link* pl = e->predecessors; pl; pl = pl->nextPredecessor) {
Event* p = pl->predecessor;
2008-07-23 23:58:29 +00:00
if (p->junctionSites == 0) {
p->junctionSites = sites;
for (Link* sl = p->successors; sl; sl = sl->nextSuccessor) {
Event* s = sl->successor;
2008-08-30 20:12:27 +00:00
propagateJunctionSites(c, s, sites);
2008-07-23 23:58:29 +00:00
}
}
}
}
2008-08-16 17:45:36 +00:00
void
2008-12-12 01:09:36 +00:00
resolveJunctionSites(Context* c, Event* e)
2008-08-16 17:45:36 +00:00
{
2008-10-04 17:26:35 +00:00
unsigned frameFootprint = ::frameFootprint(c, e->stackAfter);
2008-12-12 01:09:36 +00:00
Site* frozenSites[frameFootprint];
unsigned frozenSiteIndex = 0;
2008-04-17 02:55:38 +00:00
2008-12-12 01:09:36 +00:00
if (e->junctionSites) {
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
FrameIterator::Element el = it.next(c);
if (e->junctionSites[el.localIndex]) {
frozenSiteIndex = resolveJunctionSite
(c, e, el.value, el.localIndex, frameIndex(c, &el), frozenSites,
frozenSiteIndex);
2008-08-16 17:45:36 +00:00
}
2008-12-12 01:09:36 +00:00
}
} else {
for (Link* sl = e->successors; sl; sl = sl->nextSuccessor) {
Event* s = sl->successor;
if (s->predecessors->nextPredecessor) {
unsigned size = sizeof(Site*) * frameFootprint;
Site** junctionSites = static_cast<Site**>
(c->zone->allocate(size));
memset(junctionSites, 0, size);
propagateJunctionSites(c, s, junctionSites);
break;
2008-07-23 23:58:29 +00:00
}
2008-08-16 17:45:36 +00:00
}
2008-12-12 01:09:36 +00:00
}
2008-07-23 23:58:29 +00:00
2008-12-12 01:09:36 +00:00
if (e->junctionSites) {
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
FrameIterator::Element el = it.next(c);
if (e->junctionSites[el.localIndex] == 0) {
frozenSiteIndex = resolveJunctionSite
(c, e, el.value, el.localIndex, frameIndex(c, &el), frozenSites,
frozenSiteIndex);
2008-10-06 00:50:59 +00:00
}
2008-12-12 01:09:36 +00:00
}
2008-12-12 01:09:36 +00:00
if (DebugControl) {
fprintf(stderr, "resolved junction sites %p at %d\n",
e->junctionSites, e->logicalInstruction->index);
}
2008-11-02 20:35:35 +00:00
2008-08-16 17:45:36 +00:00
while (frozenSiteIndex) {
frozenSites[--frozenSiteIndex]->thaw(c);
}
}
2008-12-12 01:09:36 +00:00
}
2008-07-23 23:58:29 +00:00
2008-12-12 01:09:36 +00:00
void
captureBranchSnapshots(Context* c, Event* e)
{
if (e->successors->nextSuccessor) {
2008-11-01 19:14:13 +00:00
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
FrameIterator::Element el = it.next(c);
e->snapshots = makeSnapshots(c, el.value, e->snapshots);
}
for (SavedValue* sv = e->successors->forkState->saved; sv; sv = sv->next) {
e->snapshots = makeSnapshots(c, sv->value, e->snapshots);
2008-08-16 17:45:36 +00:00
}
2008-11-02 22:25:51 +00:00
if (DebugControl) {
fprintf(stderr, "captured snapshots %p at %d\n",
e->snapshots, e->logicalInstruction->index);
}
2008-11-01 22:16:18 +00:00
}
2008-08-16 17:45:36 +00:00
}
2008-04-17 02:55:38 +00:00
2008-12-12 01:09:36 +00:00
void
populateSiteTables(Context* c, Event* e)
{
resolveJunctionSites(c, e);
captureBranchSnapshots(c, e);
2008-12-12 01:09:36 +00:00
}
void
2008-11-01 22:16:18 +00:00
setSites(Context* c, Event* e, Value* v, Site* s, unsigned size)
{
assert(c, live(v));
for (; s; s = s->next) {
2008-11-01 22:16:18 +00:00
addSite(c, e->stackBefore, e->localsBefore, size, v, s->copy(c));
}
2008-11-02 22:25:51 +00:00
if (DebugControl) {
char buffer[256]; toString(c, v->sites, buffer, 256);
fprintf(stderr, "set sites %s for %p\n", buffer, v);
}
}
2008-08-16 17:45:36 +00:00
void
2008-11-01 22:16:18 +00:00
resetFrame(Context* c, Event* e)
2008-08-16 17:45:36 +00:00
{
2008-11-01 19:14:13 +00:00
for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) {
FrameIterator::Element el = it.next(c);
clearSites(c, el.value);
}
2008-11-01 22:16:18 +00:00
}
void
setSites(Context* c, Event* e, Site** sites)
{
resetFrame(c, e);
2008-11-01 19:14:13 +00:00
for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) {
FrameIterator::Element el = it.next(c);
2008-11-01 22:16:18 +00:00
if (sites[el.localIndex]) {
Read* r = live(el.value);
if (r) {
setSites(c, e, el.value, sites[el.localIndex], r->size);
}
}
}
}
void
removeBuddies(Context* c)
{
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
FrameIterator::Element el = it.next(c);
removeBuddy(c, el.value);
}
}
2008-11-01 22:16:18 +00:00
void
restore(Context* c, Event* e, Snapshot* snapshots)
{
for (Snapshot* s = snapshots; s; s = s->next) {
2008-11-02 22:25:51 +00:00
// char buffer[256]; toString(c, s->sites, buffer, 256);
// fprintf(stderr, "restore %p buddy %p sites %s\n",
// s->value, s->value->buddy, buffer);
2008-11-01 22:16:18 +00:00
s->value->buddy = s->buddy;
}
resetFrame(c, e);
for (Snapshot* s = snapshots; s; s = s->next) {
if (live(s->value)) {
Read* r = live(s->value);
2008-11-02 20:35:35 +00:00
if (r and s->sites and s->value->sites == 0) {
2008-11-01 22:16:18 +00:00
setSites(c, e, s->value, s->sites, r->size);
}
}
}
2008-08-16 17:45:36 +00:00
}
2008-07-23 23:58:29 +00:00
2008-08-16 17:45:36 +00:00
void
populateSources(Context* c, Event* e)
{
Site* frozenSites[e->readCount];
unsigned frozenSiteIndex = 0;
for (Read* r = e->reads; r; r = r->eventNext) {
2008-10-04 17:26:35 +00:00
r->value->source = readSource(c, e->stackBefore, e->localsBefore, r);
2008-08-16 17:45:36 +00:00
if (r->value->source) {
if (DebugReads) {
char buffer[256]; r->value->source->toString(c, buffer, 256);
fprintf(stderr, "freeze source %s for %p\n",
buffer, r->value);
}
2008-12-12 01:09:36 +00:00
2008-08-16 17:45:36 +00:00
assert(c, frozenSiteIndex < e->readCount);
frozenSites[frozenSiteIndex++] = r->value->source;
r->value->source->freeze(c);
2008-07-23 23:58:29 +00:00
}
2008-08-16 17:45:36 +00:00
}
while (frozenSiteIndex) {
frozenSites[--frozenSiteIndex]->thaw(c);
}
}
2008-07-23 23:58:29 +00:00
void
setStubRead(Context* c, StubReadPair* p, Value* v, unsigned size)
{
2008-11-01 19:14:13 +00:00
if (v) {
StubRead* r = stubRead(c, size);
if (DebugReads) {
fprintf(stderr, "add stub read %p to %p\n", r, v);
}
addRead(c, 0, v, r);
p->value = v;
p->read = r;
}
}
void
populateJunctionReads(Context* c, Link* link)
{
JunctionState* state = new
(c->zone->allocate
(sizeof(JunctionState)
+ (sizeof(StubReadPair) * frameFootprint(c, c->stack))))
JunctionState(frameFootprint(c, c->stack));
2008-09-22 14:28:18 +00:00
memset(state->reads, 0, sizeof(StubReadPair) * frameFootprint(c, c->stack));
link->junctionState = state;
2008-11-01 19:14:13 +00:00
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
setStubRead(c, state->reads + e.localIndex, e.value,
footprintSizeInBytes(e.footprint));
}
}
void
updateJunctionReads(Context* c, JunctionState* state)
{
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
StubReadPair* p = state->reads + e.localIndex;
if (p->value and p->read->read == 0) {
Read* r = live(e.value);
2008-12-12 01:09:36 +00:00
if (r) {
if (DebugReads) {
fprintf(stderr, "stub read %p for %p valid: %p\n",
p->read, p->value, r);
}
2008-12-12 01:09:36 +00:00
p->read->read = r;
}
}
}
for (unsigned i = 0; i < frameFootprint(c, c->stack); ++i) {
StubReadPair* p = state->reads + i;
if (p->value and p->read->read == 0) {
if (DebugReads) {
fprintf(stderr, "stub read %p for %p invalid\n", p->read, p->value);
}
p->read->valid_ = false;
}
}
}
2008-08-16 17:45:36 +00:00
LogicalInstruction*
next(Context* c, LogicalInstruction* i)
{
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
i = c->logicalCode[n];
if (i) return i;
2008-08-16 17:45:36 +00:00
}
return 0;
}
2008-07-23 23:58:29 +00:00
2008-08-16 17:45:36 +00:00
class Block {
public:
Block(Event* head):
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
2008-08-16 17:45:36 +00:00
{ }
2008-07-23 23:58:29 +00:00
2008-08-16 17:45:36 +00:00
Event* head;
Block* nextBlock;
2008-08-16 17:45:36 +00:00
LogicalInstruction* nextInstruction;
2008-09-07 20:12:11 +00:00
Assembler::Block* assemblerBlock;
2008-08-16 17:45:36 +00:00
unsigned start;
};
2008-07-23 23:58:29 +00:00
2008-08-16 17:45:36 +00:00
Block*
block(Context* c, Event* head)
{
return new (c->zone->allocate(sizeof(Block))) Block(head);
}
unsigned
compile(Context* c)
{
if (c->logicalCode[c->logicalIp]->lastEvent == 0) {
appendDummy(c);
}
2008-08-16 17:45:36 +00:00
Assembler* a = c->assembler;
c->pass = CompilePass;
Block* firstBlock = block(c, c->firstEvent);
Block* block = firstBlock;
a->allocateFrame(c->alignedFrameSize);
2008-08-16 17:45:36 +00:00
for (Event* e = c->firstEvent; e; e = e->next) {
if (DebugCompile) {
fprintf(stderr,
" -- compile %s at %d with %d preds %d succs %d stack\n",
e->name(), e->logicalInstruction->index,
countPredecessors(e->predecessors),
countSuccessors(e->successors),
2008-10-04 17:26:35 +00:00
e->stackBefore ?
e->stackBefore->index + e->stackBefore->footprint : 0);
}
2008-10-15 00:45:31 +00:00
e->block = block;
c->stack = e->stackBefore;
c->locals = e->localsBefore;
if (e->logicalInstruction->machineOffset == 0) {
e->logicalInstruction->machineOffset = a->offset();
}
2008-09-07 20:12:11 +00:00
if (e->predecessors) {
2008-10-15 00:45:31 +00:00
visit(c, lastPredecessor(e->predecessors));
Event* first = e->predecessors->predecessor;
if (e->predecessors->nextPredecessor) {
for (Link* pl = e->predecessors;
pl->nextPredecessor;
pl = pl->nextPredecessor)
{
updateJunctionReads(c, pl->junctionState);
}
2008-11-02 22:25:51 +00:00
if (DebugControl) {
fprintf(stderr, "set sites to junction sites %p at %d\n",
first->junctionSites, first->logicalInstruction->index);
}
setSites(c, e, first->junctionSites);
removeBuddies(c);
} else if (first->successors->nextSuccessor) {
2008-11-02 22:25:51 +00:00
if (DebugControl) {
fprintf(stderr, "restore snapshots %p at %d\n",
first->snapshots, first->logicalInstruction->index);
}
2008-11-01 22:16:18 +00:00
restore(c, e, first->snapshots);
2008-09-07 20:12:11 +00:00
}
2008-08-16 17:45:36 +00:00
}
populateSources(c, e);
bool branch = e->isBranch();
if (branch and e->successors) {
populateSiteTables(c, e);
}
2008-08-16 17:45:36 +00:00
e->compile(c);
if ((not branch) and e->successors) {
2008-08-16 17:45:36 +00:00
populateSiteTables(c, e);
2008-07-23 23:58:29 +00:00
}
2008-10-15 00:45:31 +00:00
if (e->visitLinks) {
for (Cell* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next)
{
visit(c, static_cast<Link*>(cell->value));
}
e->visitLinks = 0;
}
2008-08-16 17:45:36 +00:00
2008-07-23 23:58:29 +00:00
for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->offset();
2008-04-17 02:55:38 +00:00
}
2008-09-20 23:42:46 +00:00
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
if (e->next == 0
or (e->next->logicalInstruction != e->logicalInstruction
and (e->logicalInstruction->lastEvent == e
or e->next->logicalInstruction != nextInstruction)))
{
Block* b = e->logicalInstruction->firstEvent->block;
if (b != block) {
while (b->nextBlock) b = b->nextBlock;
b->nextBlock = block;
}
2008-09-20 23:42:46 +00:00
block->nextInstruction = nextInstruction;
block->assemblerBlock = a->endBlock(e->next != 0);
// fprintf(stderr, "end block %p at %d\n", block->assemblerBlock, e->logicalInstruction->index);
2008-09-20 23:42:46 +00:00
if (e->next) {
block = ::block(c, e->next);
2008-08-16 17:45:36 +00:00
}
}
2008-04-17 02:55:38 +00:00
}
2008-08-16 17:45:36 +00:00
block = firstBlock;
while (block->nextBlock or block->nextInstruction) {
Block* next = block->nextBlock
? block->nextBlock
: block->nextInstruction->firstEvent->block;
2008-09-07 20:12:11 +00:00
next->start = block->assemblerBlock->resolve
(block->start, next->assemblerBlock);
// fprintf(stderr, "resolve block %p\n", block->assemblerBlock);
2008-08-16 17:45:36 +00:00
block = next;
}
2008-09-07 20:12:11 +00:00
return block->assemblerBlock->resolve(block->start, 0);
}
2008-03-15 20:24:04 +00:00
unsigned
count(Stack* s)
{
unsigned c = 0;
while (s) {
++ c;
s = s->next;
}
return c;
}
void
2008-11-02 20:35:35 +00:00
restore(Context* c, ForkState* state)
{
2008-09-20 23:42:46 +00:00
for (unsigned i = 0; i < state->readCount; ++i) {
2008-11-02 20:35:35 +00:00
ForkElement* p = state->elements + i;
2008-09-20 23:42:46 +00:00
p->value->lastRead = p->read;
p->read->allocateTarget(c);
2008-11-02 20:35:35 +00:00
p->value->local = p->local;
}
}
void
addForkElement(Context* c, Value* v, unsigned size, ForkState* state,
unsigned index)
{
2008-11-02 20:35:35 +00:00
MultiRead* r = multiRead(c, size);
if (DebugReads) {
fprintf(stderr, "add multi read %p to %p\n", r, v);
}
2008-11-02 20:35:35 +00:00
addRead(c, 0, v, r);
ForkElement* p = state->elements + index;
2008-11-02 20:35:35 +00:00
p->value = v;
p->local = v->local;
p->read = r;
}
unsigned
count(SavedValue* sv)
{
unsigned count = 0;
while (sv) {
++ count;
sv = sv->next;
}
return count;
}
ForkState*
saveState(Context* c)
{
unsigned elementCount = frameFootprint(c, c->stack) + count(c->saved);
ForkState* state = new
2008-09-22 14:28:18 +00:00
(c->zone->allocate
(sizeof(ForkState) + (sizeof(ForkElement) * elementCount)))
ForkState(c->stack, c->locals, c->saved, c->predecessor, c->logicalIp);
2008-09-20 23:42:46 +00:00
if (c->predecessor) {
c->forkState = state;
2008-09-20 23:42:46 +00:00
unsigned count = 0;
2008-11-01 19:14:13 +00:00
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
addForkElement
(c, e.value, footprintSizeInBytes(e.footprint), state, count++);
}
2008-11-02 20:35:35 +00:00
for (SavedValue* sv = c->saved; sv; sv = sv->next) {
addForkElement
(c, sv->value, footprintSizeInBytes(sv->footprint), state, count++);
}
2008-09-20 23:42:46 +00:00
state->readCount = count;
2008-11-02 20:35:35 +00:00
restore(c, state);
2008-04-20 19:35:36 +00:00
}
c->saved = 0;
return state;
2008-04-20 19:35:36 +00:00
}
2008-02-11 17:21:41 +00:00
void
restoreState(Context* c, ForkState* s)
2007-12-11 23:52:28 +00:00
{
if (c->logicalCode[c->logicalIp]->lastEvent == 0) {
appendDummy(c);
}
c->stack = s->stack;
c->locals = s->locals;
2008-09-20 23:42:46 +00:00
c->predecessor = s->predecessor;
2008-09-22 14:28:18 +00:00
c->logicalIp = s->logicalIp;
2008-09-20 23:42:46 +00:00
if (c->predecessor) {
c->forkState = s;
2008-11-02 20:35:35 +00:00
restore(c, s);
2008-09-07 20:12:11 +00:00
}
}
2008-11-01 19:14:13 +00:00
Value*
maybeBuddy(Context* c, Value* v, unsigned sizeInBytes)
{
if (v->local) {
Value* n = value(c);
appendBuddy(c, v, n, sizeInBytes);
return n;
} else {
return v;
}
}
class Client: public Assembler::Client {
public:
Client(Context* c): c(c) { }
2008-05-06 21:13:02 +00:00
virtual int acquireTemporary(uint32_t mask) {
int r = pickRegister(c, mask)->number;
2008-04-30 15:44:17 +00:00
save(r);
increment(c, r);
return r;
}
virtual void releaseTemporary(int r) {
decrement(c, c->registers[r]);
2008-04-30 15:44:17 +00:00
restore(r);
}
virtual void save(int r) {
2008-10-15 00:45:31 +00:00
Register* reg = c->registers[r];
if (reg->refCount or reg->value) {
releaseRegister(c, r);
}
assert(c, reg->refCount == 0);
assert(c, reg->value == 0);
}
virtual void restore(int) {
// todo
}
Context* c;
};
2007-12-08 23:22:13 +00:00
class MyCompiler: public Compiler {
public:
MyCompiler(System* s, Assembler* assembler, Zone* zone,
Compiler::Client* compilerClient):
c(s, assembler, zone, compilerClient), client(&c)
{
assembler->setClient(&client);
}
2007-12-08 23:22:13 +00:00
virtual State* saveState() {
return ::saveState(&c);
}
virtual void restoreState(State* state) {
::restoreState(&c, static_cast<ForkState*>(state));
}
virtual Subroutine* startSubroutine() {
return c.subroutine = new (c.zone->allocate(sizeof(MySubroutine)))
MySubroutine;
}
virtual void endSubroutine(Subroutine* subroutine) {
MySubroutine* sr = static_cast<MySubroutine*>(subroutine);
if (sr->forkState) {
::restoreState(&c, sr->forkState);
} else {
sr->forkState = ::saveState(&c);
}
}
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize)
{
2008-02-11 17:21:41 +00:00
c.logicalCodeLength = logicalCodeLength;
c.parameterFootprint = parameterFootprint;
c.localFootprint = localFootprint;
c.alignedFrameSize = alignedFrameSize;
unsigned frameResourceSize = sizeof(FrameResource)
* (alignedFrameSize + parameterFootprint);
c.frameResources = static_cast<FrameResource*>
(c.zone->allocate(frameResourceSize));
memset(c.frameResources, 0, frameResourceSize);
// leave room for logical instruction -1
unsigned codeSize = sizeof(LogicalInstruction*)
* (logicalCodeLength + 1);
2008-08-16 17:45:36 +00:00
c.logicalCode = static_cast<LogicalInstruction**>
(c.zone->allocate(codeSize));
memset(c.logicalCode, 0, codeSize);
c.logicalCode++;
2008-09-24 00:01:42 +00:00
c.locals = static_cast<Local*>
(c.zone->allocate(sizeof(Local) * localFootprint));
2008-09-24 00:01:42 +00:00
memset(c.locals, 0, sizeof(Local) * localFootprint);
c.logicalCode[-1] = new
(c.zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(-1, c.stack, c.locals);
}
2008-02-11 17:21:41 +00:00
virtual void visitLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
if (c.logicalCode[c.logicalIp]->lastEvent == 0) {
appendDummy(&c);
}
Event* e = c.logicalCode[logicalIp]->firstEvent;
2008-10-04 17:26:35 +00:00
Event* p = c.predecessor;
if (p) {
2008-11-08 22:36:38 +00:00
// fprintf(stderr, "visit %d pred %d\n", logicalIp,
// p->logicalInstruction->index);
2008-10-04 17:26:35 +00:00
p->stackAfter = c.stack;
p->localsAfter = c.locals;
Link* link = ::link
(&c, p, e->predecessors, e, p->successors, c.forkState);
e->predecessors = link;
p->successors = link;
2008-10-15 00:45:31 +00:00
c.lastEvent->visitLinks = cons(&c, link, c.lastEvent->visitLinks);
2008-11-02 22:25:51 +00:00
// fprintf(stderr, "populate junction reads for %d to %d\n",
// p->logicalInstruction->index, logicalIp);
2008-12-12 01:09:36 +00:00
populateJunctionReads(&c, link);
}
if (c.subroutine) {
c.subroutine->forkState
= c.logicalCode[logicalIp]->subroutine->forkState;
c.subroutine = 0;
}
2008-12-12 01:09:36 +00:00
c.forkState = 0;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void startLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
assert(&c, c.logicalCode[logicalIp] == 0);
if (c.logicalCode[c.logicalIp]->lastEvent == 0) {
appendDummy(&c);
}
2008-04-20 19:35:36 +00:00
2008-10-06 00:50:59 +00:00
Event* p = c.predecessor;
if (p) {
p->stackAfter = c.stack;
p->localsAfter = c.locals;
}
c.logicalCode[logicalIp] = new
(c.zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(logicalIp, c.stack, c.locals);
2008-04-20 19:35:36 +00:00
if (c.subroutine) {
c.logicalCode[logicalIp]->subroutine = c.subroutine;
c.subroutine = 0;
}
2008-02-11 17:21:41 +00:00
c.logicalIp = logicalIp;
}
2008-02-11 17:21:41 +00:00
virtual Promise* machineIp(unsigned logicalIp) {
return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp);
}
2008-02-11 17:21:41 +00:00
virtual Promise* poolAppend(intptr_t value) {
return poolAppendPromise(resolved(&c, value));
}
2008-02-11 17:21:41 +00:00
virtual Promise* poolAppendPromise(Promise* value) {
Promise* p = new (c.zone->allocate(sizeof(PoolPromise)))
PoolPromise(&c, c.constantCount);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
ConstantPoolNode* constant
= new (c.zone->allocate(sizeof(ConstantPoolNode)))
ConstantPoolNode(value);
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
if (c.firstConstant) {
c.lastConstant->next = constant;
} else {
c.firstConstant = constant;
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
c.lastConstant = constant;
++ c.constantCount;
2008-02-11 17:21:41 +00:00
return p;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* constant(int64_t value) {
return promiseConstant(resolved(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* promiseConstant(Promise* value) {
2008-04-20 19:35:36 +00:00
return ::value(&c, ::constantSite(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* address(Promise* address) {
2008-04-20 19:35:36 +00:00
return value(&c, ::addressSite(&c, address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* memory(Operand* base,
int displacement = 0,
Operand* index = 0,
unsigned scale = 1)
2008-02-11 17:21:41 +00:00
{
2008-04-17 22:07:32 +00:00
Value* result = value(&c);
2008-03-15 23:54:20 +00:00
2008-04-17 20:48:26 +00:00
appendMemory(&c, static_cast<Value*>(base), displacement,
static_cast<Value*>(index), scale, result);
2008-03-15 23:54:20 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* stack() {
Site* s = registerSite(&c, c.arch->stack());
return value(&c, s, s);
2007-12-08 23:22:13 +00:00
}
virtual Operand* thread() {
Site* s = registerSite(&c, c.arch->thread());
return value(&c, s, s);
2007-12-08 23:22:13 +00:00
}
Promise* machineIp() {
2008-08-16 17:45:36 +00:00
return codePromise(&c, c.logicalCode[c.logicalIp]->lastEvent);
}
2008-11-02 22:25:51 +00:00
virtual void push(unsigned footprint) {
assert(&c, footprint);
2008-11-02 20:35:35 +00:00
Value* v = value(&c);
v->local = true;
2008-11-02 22:25:51 +00:00
c.stack = ::stack(&c, v, footprint, c.stack);
}
2008-11-02 22:25:51 +00:00
virtual void push(unsigned footprint, Operand* value) {
::push(&c, footprint, static_cast<Value*>(value));
2007-12-22 00:26:55 +00:00
}
2007-12-09 22:45:43 +00:00
virtual void save(unsigned footprint, Operand* value) {
c.saved = savedValue(&c, static_cast<Value*>(value), footprint, c.saved);
}
2008-11-02 22:25:51 +00:00
virtual Operand* pop(unsigned footprint) {
return ::pop(&c, footprint);
2007-12-08 23:22:13 +00:00
}
2008-07-05 20:21:13 +00:00
virtual void pushed() {
Value* v = value(&c);
2008-11-02 20:35:35 +00:00
v->local = true;
2008-09-25 00:48:32 +00:00
appendFrameSite
2008-10-04 17:26:35 +00:00
(&c, v, BytesPerWord,
frameIndex(&c, (c.stack ? c.stack->index : 0) + c.localFootprint, 1));
2008-09-25 00:48:32 +00:00
c.stack = ::stack(&c, v, 1, c.stack);
}
2008-07-05 20:21:13 +00:00
virtual void popped() {
2008-11-02 20:35:35 +00:00
assert(&c, c.stack->value->local);
c.stack = c.stack->next;
2008-07-05 20:21:13 +00:00
}
virtual StackElement* top() {
return c.stack;
2008-07-05 20:21:13 +00:00
}
2008-11-02 22:25:51 +00:00
virtual unsigned footprint(StackElement* e) {
return static_cast<Stack*>(e)->footprint;
2008-07-05 20:21:13 +00:00
}
2008-11-11 00:07:44 +00:00
virtual unsigned index(StackElement* e) {
return static_cast<Stack*>(e)->index;
}
2008-11-02 22:25:51 +00:00
virtual Operand* peek(unsigned footprint UNUSED, unsigned index) {
Stack* s = c.stack;
for (unsigned i = index; i > 0;) {
2008-11-02 22:25:51 +00:00
i -= s->footprint;
s = s->next;
}
2008-11-02 22:25:51 +00:00
assert(&c, s->footprint == footprint);
2008-04-17 20:48:26 +00:00
return s->value;
}
2008-02-11 17:21:41 +00:00
virtual Operand* call(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
2008-04-18 04:16:20 +00:00
unsigned resultSize,
2008-02-11 17:21:41 +00:00
unsigned argumentCount,
...)
{
va_list a; va_start(a, argumentCount);
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
unsigned footprint = 0;
unsigned size = BytesPerWord;
2008-04-17 20:48:26 +00:00
Value* arguments[argumentCount];
unsigned argumentSizes[argumentCount];
int index = 0;
2008-02-11 17:21:41 +00:00
for (unsigned i = 0; i < argumentCount; ++i) {
2008-04-17 20:48:26 +00:00
Value* o = va_arg(a, Value*);
if (o) {
2008-04-17 20:48:26 +00:00
arguments[index] = o;
argumentSizes[index] = size;
size = BytesPerWord;
2008-04-17 20:48:26 +00:00
++ index;
} else {
size = 8;
}
++ footprint;
}
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
va_end(a);
Stack* oldStack = c.stack;
2008-07-05 20:21:13 +00:00
Stack* bottomArgument = 0;
2008-04-18 03:47:42 +00:00
for (int i = index - 1; i >= 0; --i) {
2008-11-02 22:25:51 +00:00
::push(&c, ceiling(argumentSizes[i], BytesPerWord), arguments[i]);
2008-07-05 20:21:13 +00:00
if (i == index - 1) {
bottomArgument = c.stack;
2008-07-05 20:21:13 +00:00
}
2008-04-18 03:47:42 +00:00
}
Stack* argumentStack = c.stack;
c.stack = oldStack;
2008-04-18 03:47:42 +00:00
2008-07-05 20:21:13 +00:00
Value* result = value(&c);
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
resultSize, argumentStack, index, 0);
2008-07-05 20:21:13 +00:00
return result;
}
virtual Operand* stackCall(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
unsigned argumentFootprint)
{
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
2008-07-05 20:21:13 +00:00
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
resultSize, c.stack, 0, argumentFootprint);
2008-02-11 17:21:41 +00:00
return result;
}
virtual void return_(unsigned size, Operand* value) {
2008-04-17 20:48:26 +00:00
appendReturn(&c, size, static_cast<Value*>(value));
}
2008-11-02 22:25:51 +00:00
virtual void initLocal(unsigned footprint, unsigned index) {
2008-09-25 00:48:32 +00:00
assert(&c, index < c.localFootprint);
2008-09-24 00:01:42 +00:00
Value* v = value(&c);
2008-11-02 22:25:51 +00:00
if (DebugFrame) {
fprintf(stderr, "init local %p of footprint %d at %d (%d)\n",
v, footprint, index, frameIndex(&c, index, footprint));
}
appendFrameSite
2008-11-02 22:25:51 +00:00
(&c, v, footprintSizeInBytes(footprint),
frameIndex(&c, index, footprint));
2008-09-24 00:01:42 +00:00
Local* local = c.locals + index;
local->value = v;
2008-11-02 20:35:35 +00:00
v->local = true;
2008-11-02 22:25:51 +00:00
local->footprint = footprint;
}
2008-09-25 00:48:32 +00:00
virtual void initLocalsFromLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
unsigned footprint = sizeof(Local) * c.localFootprint;
Local* newLocals = static_cast<Local*>(c.zone->allocate(footprint));
memset(newLocals, 0, footprint);
c.locals = newLocals;
2008-09-24 00:01:42 +00:00
2008-09-25 00:48:32 +00:00
Event* e = c.logicalCode[logicalIp]->firstEvent;
for (unsigned i = 0; i < c.localFootprint; ++i) {
2008-10-04 17:26:35 +00:00
Local* local = e->localsBefore + i;
2008-09-25 00:48:32 +00:00
if (local->value) {
2008-11-02 22:25:51 +00:00
initLocal(local->footprint, i);
2008-09-25 00:48:32 +00:00
}
}
}
2008-11-02 22:25:51 +00:00
virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) {
assert(&c, index < c.localFootprint);
2008-05-20 19:11:42 +00:00
2008-11-01 19:14:13 +00:00
Local* local = c.locals + index;
if (local->value) local->value->local = false;
2008-11-02 22:25:51 +00:00
unsigned sizeInBytes = sizeof(Local) * c.localFootprint;
Local* newLocals = static_cast<Local*>(c.zone->allocate(sizeInBytes));
memcpy(newLocals, c.locals, sizeInBytes);
c.locals = newLocals;
2008-11-01 19:14:13 +00:00
local = c.locals + index;
2008-11-02 22:25:51 +00:00
local->value = maybeBuddy
(&c, static_cast<Value*>(src), footprintSizeInBytes(footprint));
2008-11-02 20:35:35 +00:00
2008-11-11 00:07:44 +00:00
if (footprint == 2) {
Local* clobber = local + 1;
clobber->value = 0;
clobber->footprint = 0;
}
2008-11-02 22:25:51 +00:00
if (DebugFrame) {
fprintf(stderr, "store local %p of footprint %d at %d\n",
local->value, footprint, index);
}
2008-11-02 20:35:35 +00:00
2008-11-01 19:14:13 +00:00
local->value->local = true;
2008-11-02 22:25:51 +00:00
local->footprint = footprint;
}
2008-11-02 22:25:51 +00:00
virtual Operand* loadLocal(unsigned footprint UNUSED, unsigned index) {
assert(&c, index < c.localFootprint);
2008-09-24 00:01:42 +00:00
assert(&c, c.locals[index].value);
2008-11-02 20:35:35 +00:00
assert(&c, c.locals[index].value->local);
2008-11-02 22:25:51 +00:00
assert(&c, c.locals[index].footprint == footprint);
2008-05-20 19:11:42 +00:00
2008-11-02 22:25:51 +00:00
if (DebugFrame) {
fprintf(stderr, "load local %p of size %d at %d\n",
c.locals[index].value, footprint, index);
}
2008-09-25 00:48:32 +00:00
2008-09-24 00:01:42 +00:00
return c.locals[index].value;
}
virtual void saveLocals() {
appendSaveLocals(&c);
}
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler)
{
appendBoundsCheck(&c, static_cast<Value*>(object),
lengthOffset, static_cast<Value*>(index), handler);
}
virtual void store(unsigned size, Operand* src, Operand* dst) {
2008-04-17 20:48:26 +00:00
appendMove(&c, Move, size, static_cast<Value*>(src),
size, static_cast<Value*>(dst));
}
virtual Operand* load(unsigned size, Operand* src) {
2008-04-17 20:48:26 +00:00
Value* dst = value(&c);
appendMove(&c, Move, size, static_cast<Value*>(src),
max(size, BytesPerWord), dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
virtual Operand* loadz(unsigned size, Operand* src) {
2008-04-17 20:48:26 +00:00
Value* dst = value(&c);
appendMove(&c, MoveZ, size, static_cast<Value*>(src),
max(size, BytesPerWord), dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* load4To8(Operand* src) {
2008-04-17 20:48:26 +00:00
Value* dst = value(&c);
appendMove(&c, Move, 4, static_cast<Value*>(src), 8, dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
virtual Operand* lcmp(Operand* a, Operand* b) {
Value* result = value(&c);
appendCombine(&c, LongCompare, 8, static_cast<Value*>(a),
8, static_cast<Value*>(b), 8, result);
return result;
}
virtual void cmp(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
appendCompare(&c, size, static_cast<Value*>(a),
static_cast<Value*>(b));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jl(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfLess, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jg(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfGreater, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jle(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfLessOrEqual, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jge(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfGreaterOrEqual, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void je(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfEqual, static_cast<Value*>(address));
}
2008-02-11 17:21:41 +00:00
virtual void jne(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfNotEqual, static_cast<Value*>(address));
}
2008-02-11 17:21:41 +00:00
virtual void jmp(Operand* address) {
2008-04-17 22:07:32 +00:00
appendBranch(&c, Jump, static_cast<Value*>(address));
2007-12-09 22:45:43 +00:00
}
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Add, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-09 22:45:43 +00:00
}
virtual Operand* sub(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Subtract, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* mul(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Multiply, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* div(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Divide, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-22 00:26:55 +00:00
}
virtual Operand* rem(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Remainder, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* shl(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, ShiftLeft, BytesPerWord, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* shr(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, ShiftRight, BytesPerWord, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* ushr(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, UnsignedShiftRight, BytesPerWord, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* and_(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, And, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* or_(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Or, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Xor, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* neg(unsigned size, Operand* a) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendTranslate(&c, Negate, size, static_cast<Value*>(a), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual unsigned compile() {
2008-09-23 21:18:41 +00:00
return c.machineCodeSize = ::compile(&c);
2007-12-11 23:52:28 +00:00
}
virtual unsigned poolSize() {
return c.constantCount * BytesPerWord;
2007-12-11 00:48:09 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void writeTo(uint8_t* dst) {
c.machineCode = dst;
c.assembler->writeTo(dst);
2007-12-11 23:52:28 +00:00
2008-02-11 17:21:41 +00:00
int i = 0;
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
2008-09-23 21:18:41 +00:00
*reinterpret_cast<intptr_t*>(dst + pad(c.machineCodeSize) + i)
2008-02-11 17:21:41 +00:00
= n->promise->value();
2008-04-20 19:35:36 +00:00
i += BytesPerWord;
2007-12-16 00:24:15 +00:00
}
2007-12-08 23:22:13 +00:00
}
virtual void dispose() {
2008-02-11 17:21:41 +00:00
// ignore
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
Context c;
::Client client;
2007-12-08 23:22:13 +00:00
};
} // namespace
namespace vm {
Compiler*
2008-05-06 21:13:02 +00:00
makeCompiler(System* system, Assembler* assembler, Zone* zone,
Compiler::Client* client)
2007-12-08 23:22:13 +00:00
{
return new (zone->allocate(sizeof(MyCompiler)))
MyCompiler(system, assembler, zone, client);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
} // namespace vm