corda/src/compiler.cpp

3276 lines
76 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 {
2008-09-07 20:12:11 +00:00
const bool DebugAppend = true;
const bool DebugCompile = true;
const bool DebugStack = false;
const bool DebugRegisters = 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 RegisterSite;
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-08-30 20:12:27 +00:00
class Block;
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;
};
class Site {
public:
Site(): next(0) { }
virtual ~Site() { }
virtual Site* readTarget(Context*, Read*) { return this; }
2008-04-17 02:55:38 +00:00
virtual unsigned copyCost(Context*, Site*) = 0;
virtual bool match(Context*, uint8_t, uint64_t, int) = 0;
2008-07-17 23:34:38 +00:00
virtual void acquire(Context*, Stack*, Value**, 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-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;
Site* next;
};
class Stack: public Compiler::StackElement {
2008-04-17 22:07:32 +00:00
public:
2008-08-28 22:43:35 +00:00
Stack(unsigned index, unsigned size, Value* value, Stack* next):
index(index), size(size), padding(0), value(value), next(next)
2008-04-17 22:07:32 +00:00
{ }
unsigned index;
2008-08-28 22:43:35 +00:00
unsigned size;
unsigned padding;
2008-07-05 20:21:13 +00:00
Value* value;
2008-04-17 22:07:32 +00:00
Stack* next;
};
2008-09-20 23:42:46 +00:00
class ReadPair {
public:
Value* value;
MultiRead* read;
};
class MyState: public Compiler::State {
2008-04-17 22:07:32 +00:00
public:
2008-09-20 23:42:46 +00:00
MyState(Stack* stack, Value** locals, Event* predecessor,
unsigned logicalIp):
stack(stack),
2008-07-05 20:21:13 +00:00
locals(locals),
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-07-05 20:21:13 +00:00
Value** locals;
2008-09-20 23:42:46 +00:00
Event* predecessor;
unsigned logicalIp;
unsigned readCount;
ReadPair reads[0];
2008-04-17 22:07:32 +00:00
};
class LogicalInstruction {
public:
LogicalInstruction(int index, Stack* stack, Value** locals):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
locals(locals), machineOffset(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-07-05 20:21:13 +00:00
Value** locals;
Promise* machineOffset;
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),
2008-05-15 20:00:57 +00:00
freezeCount(0), reserved(false), pushed(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;
bool pushed;
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-07-05 20:21:13 +00:00
Read():
value(0), event(0), eventNext(0)
2008-04-17 22:07:32 +00:00
{ }
2008-07-05 20:21:13 +00:00
virtual ~Read() { }
2008-07-05 20:21:13 +00:00
virtual Site* pickSite(Context* c, Value* v) = 0;
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 unsigned size(Context* c) = 0;
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-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-09-20 23:42:46 +00:00
reads(0), lastRead(0), sites(site), source(0), target(target),
visited(false)
2008-04-17 22:07:32 +00:00
{ }
virtual ~Value() { }
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-09-20 23:42:46 +00:00
bool visited;
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),
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()))),
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),
state(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),
maxStackFootprint(0),
stackPadding(0),
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);
registers[i]->reserved = arch->reserved(i);
}
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;
Value** locals;
2008-09-20 23:42:46 +00:00
Event* predecessor;
2008-08-16 17:45:36 +00:00
LogicalInstruction** logicalCode;
Register** registers;
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;
MyState* state;
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;
unsigned maxStackFootprint;
unsigned stackPadding;
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>
(c->machineCode + pad(c->assembler->length()) + (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-20 23:42:46 +00:00
return c->logicalCode[n]->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;
}
}
unsigned
count(Cell* c)
{
unsigned n = 0;
for (; c; c = c->next) ++ n;
return n;
}
class Event {
public:
Event(Context* c):
next(0), stack(c->stack), locals(c->locals), promises(0),
2008-09-20 23:42:46 +00:00
reads(0), junctionSites(0), savedSites(0), predecessors(0),
successors(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
2008-09-20 23:42:46 +00:00
state(c->state), readCount(0)
{
assert(c, c->logicalIp >= 0);
if (c->lastEvent) {
c->lastEvent->next = this;
} else {
c->firstEvent = this;
}
c->lastEvent = this;
2008-09-20 23:42:46 +00:00
Event* p = c->predecessor;
if (p) {
predecessors = cons(c, p, 0);
p->successors = cons(c, this, p->successors);
}
2008-09-20 23:42:46 +00:00
c->predecessor = this;
if (logicalInstruction->firstEvent == 0) {
2008-08-30 20:12:27 +00:00
logicalInstruction->firstEvent = this;
2008-04-20 05:23:08 +00:00
}
2008-08-30 20:12:27 +00:00
logicalInstruction->lastEvent = this;
c->state = 0;
}
virtual ~Event() { }
virtual const char* name() = 0;
virtual void compile(Context* c) = 0;
2008-08-30 20:12:27 +00:00
virtual void compilePostsync(Context*) { }
Event* next;
Stack* stack;
2008-07-05 20:21:13 +00:00
Value** locals;
CodePromise* promises;
Read* reads;
2008-08-30 20:12:27 +00:00
Site** junctionSites;
Site** savedSites;
Cell* predecessors;
Cell* successors;
Block* block;
LogicalInstruction* logicalInstruction;
MyState* state;
unsigned readCount;
};
unsigned
alignedFrameSize(Context* c)
{
return c->arch->alignFrameSize
(c->localFootprint
- c->parameterFootprint
+ c->maxStackFootprint);
}
int
localOffset(Context* c, int v)
{
2008-09-08 02:21:11 +00:00
int parameterFootprint = c->parameterFootprint;
int frameSize = alignedFrameSize(c);
int offset = ((v < parameterFootprint) ?
(frameSize
+ parameterFootprint
+ (c->arch->frameFooterSize() * 2)
+ c->arch->frameHeaderSize()
- v - 1) :
(frameSize
+ parameterFootprint
+ c->arch->frameFooterSize()
- v - 1)) * BytesPerWord;
assert(c, offset >= 0);
return offset;
}
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-07-17 23:34:38 +00:00
addSite(Context* c, Stack* stack, Value** locals, unsigned size, Value* v,
Site* s)
2008-04-19 00:19:45 +00:00
{
if (not findSite(c, v, s)) {
// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), 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
{
for (Site** p = &(v->sites); *p;) {
if (s == *p) {
// fprintf(stderr, "remove site %p (%d) from %p\n", s, s->type(c), v);
2008-04-19 07:03:59 +00:00
s->release(c);
2008-04-18 00:39:41 +00:00
*p = (*p)->next;
break;
} else {
p = &((*p)->next);
}
}
}
2008-04-30 15:44:17 +00:00
void
removeMemorySites(Context* c, Value* v)
{
for (Site** p = &(v->sites); *p;) {
if ((*p)->type(c) == MemoryOperand) {
2008-05-15 20:00:57 +00:00
// fprintf(stderr, "remove site %p (%d) from %p\n", *p, (*p)->type(c), v);
2008-04-30 15:44:17 +00:00
(*p)->release(c);
*p = (*p)->next;
break;
} else {
p = &((*p)->next);
}
}
}
2008-04-19 07:03:59 +00:00
void
clearSites(Context* c, Value* v)
{
for (Site* s = v->sites; s; s = s->next) {
s->release(c);
}
v->sites = 0;
}
2008-07-05 20:21:13 +00:00
bool
valid(Read* r)
{
return r and r->valid();
}
bool
live(Value* v)
{
return valid(v->reads);
}
2008-04-19 00:19:45 +00:00
void
nextRead(Context* c, Value* v)
{
// fprintf(stderr, "pop read %p from %p; next: %p\n", v->reads, v, v->reads->next);
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
}
}
class ConstantSite: public Site {
public:
ConstantSite(Promise* value): value(value) { }
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;
}
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));
}
class AddressSite: public Site {
public:
AddressSite(Promise* address): address(address) { }
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;
}
Assembler::Address address;
};
AddressSite*
addressSite(Context* c, Promise* address)
{
return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address);
}
void
freeze(Register* r)
{
if (DebugRegisters) {
fprintf(stderr, "freeze %d to %d\n", r->number, r->freezeCount + 1);
}
++ r->freezeCount;
}
void
thaw(Register* r)
{
if (DebugRegisters) {
fprintf(stderr, "thaw %d to %d\n", r->number, r->freezeCount - 1);
}
-- r->freezeCount;
}
Register*
2008-07-17 23:34:38 +00:00
acquire(Context* c, uint32_t mask, Stack* stack, Value** locals,
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*
validate(Context* c, uint32_t mask, Stack* stack, Value** locals,
unsigned size, Value* value, RegisterSite* site, Register* current);
2008-05-15 20:00:57 +00:00
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);
}
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-07-17 23:34:38 +00:00
virtual void acquire(Context* c, Stack* stack, Value** locals, unsigned size,
Value* v)
{
low = ::validate(c, mask, stack, locals, size, v, this, low);
if (size > BytesPerWord) {
::freeze(low);
2008-07-17 23:34:38 +00:00
high = ::validate(c, mask >> 32, stack, locals, size, v, this, high);
::thaw(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-05-14 23:19:41 +00:00
virtual void freeze(Context* c UNUSED) {
assert(c, low);
::freeze(low);
if (high) {
::freeze(high);
}
}
2008-05-14 23:19:41 +00:00
virtual void thaw(Context* c UNUSED) {
assert(c, low);
::thaw(low);
if (high) {
::thaw(high);
}
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return RegisterOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
sync(c);
return &register_;
}
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 = ~static_cast<uint64_t>(0))
{
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;
}
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);
}
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
&& localOffset(c, frameIndex) == value.offset);
} else {
return false;
}
} else {
return false;
}
}
2008-07-17 23:34:38 +00:00
virtual void acquire(Context* c, Stack*, Value**, unsigned, Value*) {
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
}
}
virtual void release(Context* c) {
decrement(c, base);
if (index) {
decrement(c, index);
2008-04-19 00:19:45 +00:00
}
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return MemoryOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
sync(c);
return &value;
}
Register* base;
Register* index;
Assembler::Memory value;
};
MemorySite*
memorySite(Context* c, int base, int offset = 0, int index = NoRegister,
unsigned scale = 1)
{
return new (c->zone->allocate(sizeof(MemorySite)))
MemorySite(base, offset, index, scale);
}
MemorySite*
frameSite(Context* c, int frameIndex)
{
assert(c, frameIndex >= 0);
return memorySite(c, c->arch->stack(), localOffset(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
Site* s = r->pickSite(c, v);
if (s) return s;
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)) {
Read* r = v->reads;
2008-07-05 20:21:13 +00:00
Site* s = r->pickSite(c, v);
if (s) return s;
return r->allocateSite(c);
}
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,
int frameIndex)
2008-05-06 21:13:02 +00:00
{
2008-07-05 20:21:13 +00:00
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
for (Site* s = value->sites; s; s = s->next) {
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 {
abort(c);
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):
next_(0), size_(size), typeMask(typeMask), registerMask(registerMask),
2008-08-28 22:43:35 +00:00
frameIndex(frameIndex)
{ }
virtual Site* pickSite(Context* c, Value* value) {
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
}
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-08-30 20:12:27 +00:00
virtual unsigned size(Context*) {
return size_;
}
virtual void append(Context* c, Read* r) {
assert(c, next_ == 0);
next_ = r;
}
virtual Read* next(Context*) {
return next_;
}
Read* next_;
2008-08-30 20:12:27 +00:00
unsigned size_;
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)
{
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-07-05 20:21:13 +00:00
MultiRead():
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
{ }
virtual Site* pickSite(Context* c, Value* value) {
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-07-05 20:21:13 +00:00
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
}
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;
}
2008-08-30 20:12:27 +00:00
virtual unsigned size(Context* c) {
return static_cast<Read*>(reads->value)->size(c);
}
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 == 0) {
firstTarget = cell;
} else {
lastTarget->next = 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*
multiRead(Context* c)
{
return new (c->zone->allocate(sizeof(MultiRead))) MultiRead();
}
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*
pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
{
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
for (Site* s = sites; s; s = s->next) {
unsigned v = s->copyCost(c, target);
if (v < copyCost) {
site = s;
copyCost = v;
}
}
if (cost) *cost = copyCost;
return site;
}
bool
2008-07-05 20:21:13 +00:00
trySteal(Context* c, Register* r, Stack* stack, Value** locals)
{
assert(c, r->refCount == 0);
Value* v = r->value;
2008-07-17 23:34:38 +00:00
assert(c, v->reads);
if (DebugRegisters) {
fprintf(stderr, "try steal %d from %p: next: %p\n",
r->number, v, v->sites->next);
}
if (v->sites->next == 0) {
2008-07-17 23:34:38 +00:00
Site* saveSite = 0;
for (unsigned i = 0; i < c->localFootprint; ++i) {
2008-07-17 23:34:38 +00:00
if (locals[i] == v) {
saveSite = frameSite(c, i);
break;
}
}
2008-07-17 23:34:38 +00:00
if (saveSite == 0) {
for (Stack* s = stack; s; s = s->next) {
2008-07-17 23:34:38 +00:00
if (s->value == v) {
uint8_t typeMask;
uint64_t registerMask;
int frameIndex = AnyFrameIndex;
v->reads->intersect(&typeMask, &registerMask, &frameIndex);
if (frameIndex >= 0) {
saveSite = frameSite(c, frameIndex);
} else {
2008-08-28 22:43:35 +00:00
saveSite = frameSite(c, s->index + c->localFootprint);
2008-07-17 23:34:38 +00:00
}
break;
}
2008-05-18 01:26:36 +00:00
}
2008-07-17 23:34:38 +00:00
}
if (saveSite) {
2008-08-16 17:45:36 +00:00
apply(c, Move, r->size, r->site, r->size, saveSite);
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, r->size, v, saveSite);
} else {
2008-05-18 01:26:36 +00:00
if (DebugRegisters) {
fprintf(stderr, "unable to steal %d from %p\n", r->number, v);
}
return false;
}
}
removeSite(c, v, r->site);
return true;
}
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)
{
return used(c, r) and r->value->sites->next == 0;
}
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-07-17 23:34:38 +00:00
replace(Context* c, Stack* stack, Value** locals, Register* r)
{
uint32_t mask = (r->freezeCount? r->site->mask : ~0);
2008-05-15 20:00:57 +00:00
freeze(r);
2008-07-17 23:34:38 +00:00
Register* s = acquire(c, mask, stack, locals, r->size, r->value, r->site);
thaw(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;
}
Register*
2008-07-17 23:34:38 +00:00
acquire(Context* c, uint32_t mask, Stack* stack, Value** locals,
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-07-17 23:34:38 +00:00
fprintf(stderr, "acquire %d, value %p, site %p freeze count %d "
"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-08-28 22:43:35 +00:00
r = replace(c, stack, locals, r);
} else {
Value* oldValue = r->value;
if (oldValue
and oldValue != newValue
and findSite(c, oldValue, r->site))
{
2008-07-17 23:34:38 +00:00
if (not trySteal(c, r, stack, locals)) {
2008-08-28 22:43:35 +00:00
r = replace(c, stack, locals, r);
}
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-07-17 23:34:38 +00:00
validate(Context* c, uint32_t mask, Stack* stack, Value** locals,
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) {
current->size = size;
current->value = value;
current->site = site;
return current;
2008-05-18 01:26:36 +00:00
} else {
abort(c);
}
}
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
}
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)
{
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) {
//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
clean(Context* c, Value* v)
2008-07-05 20:21:13 +00:00
{
for (Site** s = &(v->sites); *s;) {
if ((*s)->match(c, 1 << MemoryOperand, 0, AnyFrameIndex)) {
s = &((*s)->next);
} else {
(*s)->release(c);
*s = (*s)->next;
2008-07-05 20:21:13 +00:00
}
}
}
2008-04-17 22:07:32 +00:00
void
clean(Context* c, Stack* stack, Value** locals, Read* reads)
{
2008-08-28 22:43:35 +00:00
for (unsigned i = 0; i < c->localFootprint; ++i) {
if (locals[i]) clean(c, locals[i]);
}
for (Stack* s = stack; s; s = s->next) {
clean(c, s->value);
}
for (Read* r = reads; r; r = r->eventNext) {
nextRead(c, r->value);
2008-08-28 22:43:35 +00:00
}
}
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);
}
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),
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 = alignedFrameSize(c) + c->parameterFootprint;
2008-04-19 00:19:45 +00:00
for (unsigned i = 0; i < argumentCount; ++i) {
Read* target;
2008-08-28 22:43:35 +00:00
if (index < c->arch->argumentRegisterCount()) {
int r = c->arch->argumentRegister(index);
target = fixedRegisterRead(c, s->size * BytesPerWord, r);
2008-05-15 20:00:57 +00:00
mask &= ~(1 << r);
2008-04-19 00:19:45 +00:00
} else {
2008-08-28 22:43:35 +00:00
frameIndex -= s->size;
target = read(c, s->size * BytesPerWord, 1 << MemoryOperand, 0,
frameIndex);
2008-04-19 00:19:45 +00:00
}
addRead(c, this, s->value, target);
2008-08-28 22:43:35 +00:00
index += s->size;
2008-04-19 00:19:45 +00:00
s = s->next;
}
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-05-15 20:00:57 +00:00
for (Stack* s = stack; s; s = s->next) {
frameIndex -= s->size;
if (footprint) {
addRead(c, this, s->value, read(c, s->size * BytesPerWord,
2008-08-28 22:43:35 +00:00
1 << MemoryOperand, 0, frameIndex));
} else {
2008-08-28 22:43:35 +00:00
unsigned index = s->index + c->localFootprint;
if (footprint == 0) {
assert(c, index <= frameIndex);
2008-08-28 22:43:35 +00:00
s->padding = frameIndex - index;
}
addRead(c, this, s->value, read(c, s->size * BytesPerWord,
2008-08-28 22:43:35 +00:00
1 << MemoryOperand, 0, index));
}
2008-08-28 22:43:35 +00:00
footprint -= s->size;
2008-05-15 20:00:57 +00:00
}
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) {
2008-08-30 20:12:27 +00:00
traceHandler->handleTrace(codePromise(c, c->assembler->offset()));
}
clean(c, stack, locals, reads);
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-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
{
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(CallEvent)))
2008-05-06 21:13:02 +00:00
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) {
nextRead(c, value);
}
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)
{
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
}
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) {
bool isLoad = not valid(src->reads->next(c));
2008-07-05 20:21:13 +00:00
bool isStore = not valid(dst->reads);
2008-07-05 20:21:13 +00:00
Site* target = targetOrRegister(c, dst);
unsigned cost = src->source->copyCost(c, target);
if (cost == 0 and (isLoad or isStore)) {
target = src->source;
}
2008-04-19 00:19:45 +00:00
assert(c, isLoad or isStore or target != src->source);
2008-05-18 01:26:36 +00:00
if (target == src->source) {
removeSite(c, src, target);
2008-05-18 01:26:36 +00:00
}
2008-04-19 00:19:45 +00:00
if (not isStore) {
2008-08-16 17:45:36 +00:00
addSite(c, stack, locals, dstSize, dst, target);
}
2008-08-28 22:43:35 +00:00
if (cost or type != Move) {
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
dstRead->intersect(&typeMask, &registerMask, &frameIndex);
if (target->match(c, typeMask, registerMask, frameIndex)) {
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-08-16 17:45:36 +00:00
addSite(c, stack, locals, dstSize, dst, tmpTarget);
2008-08-16 17:45:36 +00:00
apply(c, type, srcSize, src->source, dstSize, tmpTarget);
if (isStore) {
2008-05-18 01:26:36 +00:00
removeSite(c, dst, tmpTarget);
2008-08-16 17:45:36 +00:00
apply(c, Move, dstSize, tmpTarget, dstSize, target);
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
nextRead(c, 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
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(MoveEvent)))
2008-08-28 22:43:35 +00:00
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)
{
for (Site* s = v->sites; s; s = s->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
nextRead(c, first);
nextRead(c, 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
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(CompareEvent)))
2008-08-28 22:43:35 +00:00
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
}
void
2008-08-28 22:43:35 +00:00
preserve(Context* c, Stack* stack, Value** locals, unsigned size, Value* v,
Site* s, Read* read)
{
assert(c, v->sites == s);
2008-08-28 22:43:35 +00:00
Site* r = targetOrNull(c, v, read);
if (r == 0 or r == s) r = freeRegisterSite(c);
2008-07-17 23:34:38 +00:00
addSite(c, stack, locals, size, v, r);
2008-08-16 17:45:36 +00:00
apply(c, Move, size, s, size, r);
}
void
2008-08-28 22:43:35 +00:00
maybePreserve(Context* c, Stack* stack, Value** locals, unsigned size,
Value* v, Site* s)
{
if (valid(v->reads->next(c)) and v->sites->next == 0) {
preserve(c, stack, locals, size, v, s, v->reads->next(c));
}
}
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) {
2008-09-07 20:12:11 +00:00
Site* target;
if (c->arch->condensedAddressing()) {
maybePreserve(c, stack, locals, secondSize, second, second->source);
target = second->source;
} else {
target = resultRead->allocateSite(c);
addSite(c, stack, locals, resultSize, result, target);
}
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
nextRead(c, first);
nextRead(c, second);
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-08-28 22:43:35 +00:00
Stack*
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
{
return new (c->zone->allocate(sizeof(Stack)))
Stack(index, size, value, next);
}
Stack*
stack(Context* c, Value* value, unsigned size, Stack* next)
{
return stack
(c, value, size, (next ? next->index + next->size : 0), next);
}
2008-02-11 17:21:41 +00:00
void
2008-08-28 22:43:35 +00:00
push(Context* c, unsigned size, Value* v)
2008-02-11 17:21:41 +00:00
{
2008-08-28 22:43:35 +00:00
assert(c, ceiling(size, BytesPerWord));
c->stack = stack(c, v, ceiling(size, BytesPerWord), c->stack);
2008-08-28 22:43:35 +00:00
}
2008-08-28 22:43:35 +00:00
Value*
pop(Context* c, unsigned size UNUSED)
{
Stack* s = c->stack;
2008-08-28 22:43:35 +00:00
assert(c, ceiling(size, BytesPerWord) == s->size);
c->stack = s->next;
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-08-28 22:43:35 +00:00
::push(c, secondSize, second);
::push(c, firstSize, 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);
}
new (c->zone->allocate(sizeof(CombineEvent)))
2008-08-28 22:43:35 +00:00
CombineEvent
(c, type,
firstSize, first,
secondSize, second,
resultSize, result,
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex),
2008-09-07 20:12:11 +00:00
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,
Value* result, Read* read):
2008-04-17 02:55:38 +00:00
Event(c), type(type), size(size), value(value), result(result)
{
addRead(c, this, value, read);
2008-03-15 20:24:04 +00:00
}
virtual const char* name() {
return "TranslateEvent";
}
virtual void compile(Context* c) {
2008-08-28 22:43:35 +00:00
maybePreserve(c, stack, locals, size, value, value->source);
2008-08-28 22:43:35 +00:00
Site* target = targetOrRegister(c, result);
apply(c, type, size, value->source, size, target);
2008-04-19 00:19:45 +00:00
nextRead(c, value);
2008-04-18 00:39:41 +00:00
removeSite(c, value, value->source);
2008-07-05 20:21:13 +00:00
if (live(result)) {
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, size, result, value->source);
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-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-08-28 22:43:35 +00:00
// todo: respect resultTypeMask and resultRegisterMask
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(TranslateEvent)))
2008-08-28 22:43:35 +00:00
TranslateEvent
(c, type, size, value, result,
read(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex));
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-04-19 00:19:45 +00:00
nextRead(c, base);
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);
}
nextRead(c, 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
{
new (c->zone->allocate(sizeof(MemoryEvent)))
2008-04-17 20:48:26 +00:00
MemoryEvent(c, base, displacement, index, scale, result);
}
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
nextRead(c, address);
}
UnaryOperation type;
Value* address;
};
void
appendBranch(Context* c, UnaryOperation type, Value* address)
{
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();
nextRead(c, object);
nextRead(c, index);
}
Value* object;
unsigned lengthOffset;
Value* index;
intptr_t handler;
};
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler)
{
new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent
(c, object, lengthOffset, index, handler);
}
class ParameterEvent: public Event {
public:
ParameterEvent(Context* c, Value* value, unsigned size, int index):
Event(c), value(value), size(size), index(index)
{ }
virtual const char* name() {
return "ParameterEvent";
}
virtual void compile(Context* c) {
addSite(c, stack, locals, size, value, frameSite(c, index));
}
Value* value;
unsigned size;
int index;
};
void
appendParameter(Context* c, Value* value, unsigned size, int index)
{
new (c->zone->allocate(sizeof(ParameterEvent))) ParameterEvent
(c, value, size, index);
}
class DummyEvent: public Event {
public:
DummyEvent(Context* c):
Event(c)
{
stack = logicalInstruction->stack;
locals = logicalInstruction->locals;
}
virtual const char* name() {
return "DummyEvent";
}
virtual void compile(Context*) { }
};
void
appendDummy(Context* c)
{
new (c->zone->allocate(sizeof(DummyEvent))) DummyEvent(c);
}
2008-04-18 03:47:42 +00:00
Site*
2008-07-17 23:34:38 +00:00
readSource(Context* c, Stack* stack, Value** locals, Read* r)
2008-04-18 03:47:42 +00:00
{
2008-05-15 20:00:57 +00:00
if (r->value->sites == 0) {
return 0;
}
2008-08-30 20:12:27 +00:00
Site* site = r->pickSite(c, r->value);
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;
site = pick(c, r->value->sites, target, &copyCost);
assert(c, copyCost);
addSite(c, stack, locals, r->size(c), r->value, target);
apply(c, Move, r->size(c), site, r->size(c), target);
return target;
2008-04-17 02:55:38 +00:00
}
2007-12-11 21:26:59 +00:00
}
2008-07-23 23:58:29 +00:00
Site*
2008-08-30 20:12:27 +00:00
pickJunctionSite(Context* c, Value* v, Read* r)
2008-07-23 23:58:29 +00:00
{
Site* s = r->pickSite(c, v);
if (s) return s;
return r->allocateSite(c);
}
unsigned
frameFootprint(Context* c, Stack* s)
{
return c->localFootprint + (s ? (s->index + s->size) : 0);
}
2008-07-23 23:58:29 +00:00
unsigned
resolveJunctionSite(Context* c, Event* e, Event* successor, Value* v,
unsigned index, Site** frozenSites,
unsigned frozenSiteIndex)
{
assert(c, index < frameFootprint(c, successor->stack));
2008-07-23 23:58:29 +00:00
if (live(v)) {
2008-08-30 20:12:27 +00:00
Read* r = v->reads;
2008-07-23 23:58:29 +00:00
Site* original = e->junctionSites[index];
if (original == 0) {
2008-08-30 20:12:27 +00:00
e->junctionSites[index] = pickJunctionSite(c, v, r);
2008-07-23 23:58:29 +00:00
}
Site* target = e->junctionSites[index];
unsigned copyCost;
Site* site = pick(c, v->sites, target, &copyCost);
if (copyCost) {
2008-08-30 20:12:27 +00:00
addSite(c, successor->stack, successor->locals, r->size(c), v, target);
apply(c, Move, r->size(c), site, r->size(c), target);
2008-07-23 23:58:29 +00:00
}
if (original == 0) {
frozenSites[frozenSiteIndex++] = target;
target->freeze(c);
}
}
return frozenSiteIndex;
}
void
propagateJunctionSites(Context* c, Event* e, Site** sites)
{
for (Cell* pc = e->predecessors; pc; pc = pc->next) {
Event* p = static_cast<Event*>(pc->value);
if (p->junctionSites == 0) {
p->junctionSites = sites;
for (Cell* sc = p->successors; sc; sc = sc->next) {
Event* s = static_cast<Event*>(sc->value);
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
populateSiteTables(Context* c, Event* e)
{
Event* successor = static_cast<Event*>(e->successors->value);
2008-04-17 02:55:38 +00:00
2008-08-30 20:12:27 +00:00
unsigned frameFootprint = ::frameFootprint(c, successor->stack);
2008-04-17 02:55:38 +00:00
2008-08-30 20:12:27 +00:00
{ Site* frozenSites[frameFootprint];
2008-08-16 17:45:36 +00:00
unsigned frozenSiteIndex = 0;
2008-04-17 02:55:38 +00:00
2008-08-16 17:45:36 +00:00
if (e->junctionSites) {
2008-08-30 20:12:27 +00:00
for (unsigned i = 0; i < frameFootprint; ++i) {
2008-08-16 17:45:36 +00:00
Site* site = e->junctionSites[i];
if (site) {
frozenSites[frozenSiteIndex++] = site;
site->freeze(c);
}
}
} else {
for (Cell* sc = e->successors; sc; sc = sc->next) {
Event* s = static_cast<Event*>(sc->value);
if (s->predecessors->next) {
2008-08-30 20:12:27 +00:00
unsigned size = sizeof(Site*) * frameFootprint;
2008-08-16 17:45:36 +00:00
Site** junctionSites = static_cast<Site**>
(c->zone->allocate(size));
memset(junctionSites, 0, size);
2008-04-17 02:55:38 +00:00
2008-08-16 17:45:36 +00:00
propagateJunctionSites(c, s, junctionSites);
break;
2008-04-20 05:23:08 +00:00
}
2008-07-23 23:58:29 +00:00
}
2008-08-16 17:45:36 +00:00
}
2008-07-23 23:58:29 +00:00
2008-08-16 17:45:36 +00:00
if (e->junctionSites) {
2008-08-30 20:12:27 +00:00
for (unsigned i = 0; i < c->localFootprint; ++i) {
2008-08-16 17:45:36 +00:00
frozenSiteIndex = resolveJunctionSite
(c, e, successor, successor->locals[i], i, frozenSites,
frozenSiteIndex);
2008-08-16 17:45:36 +00:00
}
if (successor->stack) {
unsigned i = successor->stack->index + c->localFootprint;
for (Stack* stack = successor->stack; stack; stack = stack->next) {
frozenSiteIndex = resolveJunctionSite
(c, e, successor, stack->value, i, frozenSites, frozenSiteIndex);
i -= stack->size;
}
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
2008-08-16 17:45:36 +00:00
if (e->successors->next) {
2008-08-30 20:12:27 +00:00
unsigned size = sizeof(Site*) * frameFootprint;
2008-08-16 17:45:36 +00:00
Site** savedSites = static_cast<Site**>(c->zone->allocate(size));
2008-04-20 05:23:08 +00:00
2008-08-30 20:12:27 +00:00
for (unsigned i = 0; i < c->localFootprint; ++i) {
savedSites[i] = successor->locals[i]->sites;
2008-08-16 17:45:36 +00:00
}
if (successor->stack) {
unsigned i = successor->stack->index + c->localFootprint;
for (Stack* stack = successor->stack; stack; stack = stack->next) {
savedSites[i] = stack->value->sites;
fprintf(stderr, "save %p at %d of %d in %p\n",
savedSites[i], i, frameFootprint, savedSites);
i -= stack->size;
}
2008-08-16 17:45:36 +00:00
}
e->savedSites = savedSites;
2008-08-16 17:45:36 +00:00
}
}
2008-04-17 02:55:38 +00:00
2008-08-16 17:45:36 +00:00
void
setSites(Context* c, Event* e, Site** sites)
{
2008-08-30 20:12:27 +00:00
for (unsigned i = 0; i < c->localFootprint; ++i) {
2008-08-16 17:45:36 +00:00
Value* v = e->locals[i];
clearSites(c, v);
if (live(v)) {
addSite(c, 0, 0, v->reads->size(c), v, sites[i]);
}
2008-08-16 17:45:36 +00:00
}
2008-07-23 23:58:29 +00:00
if (e->stack) {
unsigned i = e->stack->index + c->localFootprint;
for (Stack* stack = e->stack; stack; stack = stack->next) {
Value* v = stack->value;
clearSites(c, v);
if (live(v)) {
addSite(c, 0, 0, v->reads->size(c), v, sites[i]);
}
i -= stack->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) {
r->value->source = readSource(c, e->stack, e->locals, r);
if (r->value->source) {
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
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):
2008-09-07 20:12:11 +00:00
head(head), 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;
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)
{
Assembler* a = c->assembler;
c->pass = CompilePass;
Block* firstBlock = block(c, c->firstEvent);
Block* block = firstBlock;
2008-08-30 20:12:27 +00:00
a->allocateFrame(alignedFrameSize(c));
2008-08-16 17:45:36 +00:00
for (Event* e = c->firstEvent; e; e = e->next) {
e->block = block;
if (DebugCompile) {
fprintf(stderr,
"compile %s at %d with %d preds, %d succs, %d stack\n",
e->name(), e->logicalInstruction->index,
count(e->predecessors), count(e->successors),
e->stack ? e->stack->index + e->stack->size : 0);
}
if (e->logicalInstruction->machineOffset == 0) {
e->logicalInstruction->machineOffset = a->offset();
}
MyState* state = e->state;
if (state) {
2008-09-20 23:42:46 +00:00
for (unsigned i = 0; i < state->readCount; ++i) {
ReadPair* p = state->reads[i];
p->value->reads = p->read->nextTarget();
}
}
2008-09-07 20:12:11 +00:00
if (e->predecessors) {
Event* predecessor = static_cast<Event*>(e->predecessors->value);
if (e->predecessors->next) {
setSites(c, e, predecessor->junctionSites);
} else if (predecessor->successors->next) {
setSites(c, e, predecessor->savedSites);
}
2008-08-16 17:45:36 +00:00
}
populateSources(c, e);
e->compile(c);
if (e->successors) {
populateSiteTables(c, e);
2008-07-23 23:58:29 +00:00
}
e->compilePostsync(c);
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
if (e->next == 0 or e->next->blockStart) {
block->nextInstruction = nextInstruction;
block->assemblerBlock = a->endBlock(e->next != 0);
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->nextInstruction) {
Block* next = block->nextInstruction->firstEvent->block;
2008-09-07 20:12:11 +00:00
next->start = block->assemblerBlock->resolve
(block->start, next->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-09-20 23:42:46 +00:00
allocateTargets(Context* c, MyState* state)
{
2008-09-20 23:42:46 +00:00
for (unsigned i = 0; i < state->readCount; ++i) {
ReadPair* p = state->reads[i];
p->value->lastRead = p->read;
p->read->allocateTarget(c);
}
}
MyState*
saveState(Context* c)
{
2008-09-20 23:42:46 +00:00
MyState* state = new
(c->zone->allocate(sizeof(MyState))
+ (c->zone->allocate(sizeof(ReadPair) * frameFootprint(c, c->stack))))
MyState(c->stack, c->locals, c->predecessor, c->logicalIp);
2008-09-20 23:42:46 +00:00
if (c->predecessor) {
c->state = state;
2008-09-20 23:42:46 +00:00
unsigned count = 0;
for (unsigned i = 0; i < c->localFootprint; ++i) {
2008-09-20 23:42:46 +00:00
Value* v = c->locals[i];
if (v and not v->visited) {
v->visited = true;
MultiRead* r = multiRead(c);
addRead(c, 0, c->locals[i], r);
2008-09-20 23:42:46 +00:00
ReadPair* p = state->reads + (count++);
p->value = v;
p->read = r;
}
}
for (Stack* s = c->stack; s; s = s->next) {
2008-09-20 23:42:46 +00:00
Value* v = s->value;
if (not v->visited) {
v->visited = true;
MultiRead* r = multiRead(c);
addRead(c, 0, s->value, r);
ReadPair* p = state->reads + (count++);
p->value = v;
p->read = r;
}
}
for (unsigned i = 0; i < count; ++i) {
state->reads[i]->value->visited = false;
}
2008-09-20 23:42:46 +00:00
state->readCount = count;
allocateTargets(c, state);
2008-04-20 19:35:36 +00:00
}
return state;
2008-04-20 19:35:36 +00:00
}
2008-02-11 17:21:41 +00:00
void
restoreState(Context* c, MyState* s)
2007-12-11 23:52:28 +00:00
{
if (c->logicalIp >= 0 and 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;
c->logicalIp = logicalIp;
2008-09-20 23:42:46 +00:00
if (c->predecessor) {
c->state = s;
2008-09-20 23:42:46 +00:00
allocateTargets(c, s);
2008-09-07 20:12:11 +00:00
}
}
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) {
// todo
expect(c, c->registers[r]->refCount == 0);
expect(c, c->registers[r]->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<MyState*>(state));
}
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
unsigned localFootprint, unsigned maxStackFootprint)
{
2008-02-11 17:21:41 +00:00
c.logicalCodeLength = logicalCodeLength;
c.parameterFootprint = parameterFootprint;
c.localFootprint = localFootprint;
c.maxStackFootprint = maxStackFootprint;
2008-08-16 17:45:36 +00:00
c.logicalCode = static_cast<LogicalInstruction**>
(c.zone->allocate(sizeof(LogicalInstruction*) * logicalCodeLength));
memset(c.logicalCode, 0, sizeof(LogicalInstruction*) * logicalCodeLength);
c.locals = static_cast<Value**>
(c.zone->allocate(sizeof(Value*) * localFootprint));
memset(c.locals, 0, sizeof(Value*) * localFootprint);
}
2008-02-11 17:21:41 +00:00
virtual void visitLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
Event* e = c.logicalCode[logicalIp]->firstEvent;
2008-09-20 23:42:46 +00:00
if (c.predecessor) {
c.predecessor->successors = cons(&c, e, c.predecessor->successors);
#error tbc
populateJunctionReads(&c, c.predecessor);
e->predecessors = cons(&c, c.predecessor, e->predecessors);
}
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);
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, " -- ip: %d\n", logicalIp);
}
2008-04-20 19:35:36 +00:00
if (c.logicalIp >= 0 and c.logicalCode[c.logicalIp]->lastEvent == 0) {
appendDummy(&c);
}
2008-04-20 19:35:36 +00:00
c.logicalCode[logicalIp] = new
(c.zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(logicalIp, c.stack, c.locals);
2008-04-20 19:35:36 +00:00
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
}
virtual Operand* stackTop() {
Site* s = frameSite(&c, c.stack->index);
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);
}
virtual void push(unsigned size) {
assert(&c, ceiling(size, BytesPerWord));
c.stack = ::stack(&c, value(&c), ceiling(size, BytesPerWord), c.stack);
}
virtual void push(unsigned size, Operand* value) {
2008-04-17 20:48:26 +00:00
::push(&c, size, static_cast<Value*>(value));
2007-12-22 00:26:55 +00:00
}
2007-12-09 22:45:43 +00:00
virtual Operand* pop(unsigned size) {
return ::pop(&c, size);
2007-12-08 23:22:13 +00:00
}
2008-07-05 20:21:13 +00:00
virtual void pushed() {
Value* v = value(&c);
c.stack = ::stack(&c, v, 1, c.stack);
}
2008-07-05 20:21:13 +00:00
virtual void popped() {
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
}
virtual unsigned size(StackElement* e) {
2008-08-28 22:43:35 +00:00
return static_cast<Stack*>(e)->size;
2008-07-05 20:21:13 +00:00
}
virtual unsigned padding(StackElement* e) {
2008-08-28 22:43:35 +00:00
return static_cast<Stack*>(e)->padding;
2007-12-08 23:22:13 +00:00
}
virtual Operand* peek(unsigned size UNUSED, unsigned index) {
Stack* s = c.stack;
for (unsigned i = index; i > 0;) {
2008-08-28 22:43:35 +00:00
i -= s->size;
s = s->next;
}
2008-08-28 22:43:35 +00:00
assert(&c, s->size == ceiling(size, BytesPerWord));
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-04-18 03:47:42 +00:00
::push(&c, argumentSizes[i], 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));
}
virtual void initParameter(unsigned size, unsigned index) {
assert(&c, index < c.parameterFootprint);
Value* v = value(&c);
appendParameter(&c, v, size, index);
c.locals[index] = v;
}
virtual void storeLocal(unsigned, Operand* src, unsigned index) {
assert(&c, index < c.localFootprint);
2008-05-20 19:11:42 +00:00
unsigned size = sizeof(Value*) * c.localFootprint;
Value** newLocals = static_cast<Value**>(c.zone->allocate(size));
memcpy(newLocals, c.locals, size);
c.locals = newLocals;
c.locals[index] = static_cast<Value*>(src);
}
virtual Operand* loadLocal(unsigned, unsigned index) {
assert(&c, index < c.localFootprint);
assert(&c, c.locals[index]);
2008-05-20 19:11:42 +00:00
return c.locals[index];
}
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), size, 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), size, 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-08-16 17:45:36 +00:00
return ::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-04-20 19:35:36 +00:00
*reinterpret_cast<intptr_t*>(dst + pad(c.assembler->length()) + 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