corda/src/compiler.cpp

1750 lines
40 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-02-11 17:21:41 +00:00
class Context;
class Value;
2008-04-17 22:07:32 +00:00
class Stack;
class Site;
class Event;
2008-04-18 00:39:41 +00:00
class Read;
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
apply(Context* c, UnaryOperation op, unsigned size, Site* a);
void
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b);
class Site {
public:
Site(): next(0) { }
virtual ~Site() { }
2008-04-18 00:39:41 +00:00
virtual Site* readTarget(Context*, Read*) { return this; }
2008-04-17 02:55:38 +00:00
virtual unsigned copyCost(Context*, Site*) = 0;
2008-04-17 02:55:38 +00:00
virtual void accept(Context* c, unsigned size, Site* src) {
apply(c, Move, size, src, this);
}
2008-04-17 02:55:38 +00:00
virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { }
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;
};
2008-04-17 22:07:32 +00:00
class Stack {
public:
Stack(Value* value, unsigned size, unsigned index, Stack* next):
value(value), size(size), index(index), next(next), pushed(false)
{ }
Value* value;
unsigned size;
unsigned index;
Stack* next;
bool pushed;
};
class State {
public:
State(State* s):
stack(s ? s->stack : 0),
next(s)
{ }
Stack* stack;
State* next;
};
class LogicalInstruction {
public:
unsigned visits;
Event* lastEvent;
unsigned machineOffset;
int predecessor;
};
class Register {
public:
Value* value;
Site* site;
unsigned size;
bool reserved;
};
class ConstantPoolNode {
public:
ConstantPoolNode(Promise* promise): promise(promise), next(0) { }
Promise* promise;
ConstantPoolNode* next;
};
class Junction {
public:
Junction(unsigned logicalIp, Junction* next):
logicalIp(logicalIp),
next(next)
{ }
unsigned logicalIp;
Junction* next;
};
class Read {
public:
Read(unsigned size, Value* value, Site* target, Read* next, Event* event,
Read* eventNext):
size(size), value(value), target(target), next(next), event(event),
eventNext(eventNext)
{ }
unsigned size;
Value* value;
Site* target;
Read* next;
Event* event;
Read* eventNext;
};
class Value: public Compiler::Operand {
public:
Value(Site* site):
2008-04-18 00:39:41 +00:00
reads(0), lastRead(0), sites(site), source(0)
2008-04-17 22:07:32 +00:00
{ }
Read* reads;
Read* lastRead;
Site* sites;
Site* source;
};
class Context {
public:
Context(System* system, Assembler* assembler, Zone* zone):
system(system),
assembler(assembler),
zone(zone),
logicalIp(-1),
state(new (zone->allocate(sizeof(State))) State(0)),
firstEvent(0),
lastEvent(0),
logicalCode(0),
logicalCodeLength(0),
stackOffset(0),
registers(static_cast<Register*>
(zone->allocate(sizeof(Register) * assembler->registerCount()))),
firstConstant(0),
lastConstant(0),
constantCount(0),
junctions(0),
machineCode(0)
{
memset(registers, 0, sizeof(Register) * assembler->registerCount());
registers[assembler->base()].reserved = true;
registers[assembler->stack()].reserved = true;
registers[assembler->thread()].reserved = true;
}
System* system;
Assembler* assembler;
Zone* zone;
int logicalIp;
State* state;
Event* firstEvent;
Event* lastEvent;
LogicalInstruction* logicalCode;
unsigned logicalCodeLength;
unsigned stackOffset;
Register* registers;
ConstantPoolNode* firstConstant;
ConstantPoolNode* lastConstant;
unsigned constantCount;
Junction* junctions;
uint8_t* machineCode;
};
void
addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
{
s->acquire(c, stack, size, v, s);
s->next = v->sites;
v->sites = s;
}
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
removeSite(Context*, Value* v, Site* s)
{
for (Site** p = &(v->sites); *p;) {
if (s == *p) {
*p = (*p)->next;
break;
} else {
p = &((*p)->next);
}
}
}
class ConstantSite: public Site {
public:
ConstantSite(Promise* value): value(value) { }
virtual unsigned copyCost(Context*, Site*) {
return 1;
}
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) { }
virtual unsigned copyCost(Context*, Site*) {
return 3;
}
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
2008-04-17 02:55:38 +00:00
acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue,
2008-04-17 22:07:32 +00:00
Site* newSite);
class RegisterSite: public Site {
public:
RegisterSite(int low, int high): register_(low, high) { }
virtual unsigned copyCost(Context* c, Site* s) {
if (s and
(this == s or
2008-04-17 22:07:32 +00:00
(s->type(c) == RegisterOperand
and static_cast<RegisterSite*>(s)->register_.low
== register_.low
and static_cast<RegisterSite*>(s)->register_.high
== register_.high)))
{
return 0;
} else {
return 2;
}
}
2008-04-17 02:55:38 +00:00
virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v,
Site* s)
{
::acquire(c, register_.low, stack, size, v, s);
if (register_.high >= 0) ::acquire(c, register_.high, stack, size, v, s);
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return RegisterOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context*) {
return &register_;
}
Assembler::Register register_;
};
RegisterSite*
registerSite(Context* c, int low, int high = NoRegister)
{
return new (c->zone->allocate(sizeof(RegisterSite)))
RegisterSite(low, high);
}
2008-04-17 22:07:32 +00:00
RegisterSite*
freeRegister(Context* c, unsigned size, bool allowAcquired);
class MemorySite: public Site {
public:
2008-04-17 02:55:38 +00:00
MemorySite(int base, int offset, int index, unsigned scale):
value(base, offset, index, scale)
{ }
virtual unsigned copyCost(Context* c, Site* s) {
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 OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return MemoryOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context*) {
return &value;
}
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);
}
2008-04-17 22:07:32 +00:00
class AbstractSite: public Site {
public:
2008-04-17 02:55:38 +00:00
virtual unsigned copyCost(Context* c, Site*) {
abort(c);
}
virtual void copyTo(Context* c, unsigned, Site*) {
abort(c);
}
virtual OperandType type(Context* c) {
abort(c);
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
abort(c);
}
};
2008-04-17 22:07:32 +00:00
class ValueSite: public AbstractSite {
2008-02-11 17:21:41 +00:00
public:
2008-04-17 22:07:32 +00:00
ValueSite(Value* value): value(value) { }
2008-03-16 19:38:43 +00:00
2008-04-18 00:39:41 +00:00
virtual Site* readTarget(Context* c, Read*) {
if (value->reads and value->reads->target) {
return value->reads->target->readTarget(c, value->reads);
} else {
return 0;
}
2008-04-17 02:55:38 +00:00
}
2007-12-09 20:03:21 +00:00
Value* value;
};
2008-04-17 22:07:32 +00:00
ValueSite*
valueSite(Context* c, Value* v)
{
return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v);
}
2008-04-17 22:07:32 +00:00
class AnyRegisterSite: public AbstractSite {
public:
2008-04-18 00:39:41 +00:00
virtual Site* readTarget(Context* c, Read* r) {
for (Site* s = r->value->sites; s; s = s->next) {
if (s->type(c) == RegisterOperand) {
return 0;
}
}
return freeRegister(c, r->size, true);
2008-04-17 22:07:32 +00:00
}
2008-04-17 22:07:32 +00:00
Value* value;
2008-04-17 02:55:38 +00:00
};
2008-04-17 22:07:32 +00:00
AnyRegisterSite*
anyRegisterSite(Context* c)
{
return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite();
}
class StackSite: public Site {
2008-04-17 02:55:38 +00:00
public:
2008-04-17 22:07:32 +00:00
StackSite(Stack* stack): stack(stack) { }
2008-04-17 22:07:32 +00:00
virtual unsigned copyCost(Context*, Site*) {
return 5;
}
2008-04-17 22:07:32 +00:00
virtual void accept(Context* c, unsigned size, Site* src) {
apply(c, Push, size, src);
}
2008-04-17 22:07:32 +00:00
virtual OperandType type(Context*) {
return StackOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
abort(c);
}
Stack* stack;
};
2008-04-17 22:07:32 +00:00
StackSite*
stackSite(Context* c, Stack* s)
{
return new (c->zone->allocate(sizeof(StackSite))) StackSite(s);
}
2008-04-17 02:55:38 +00:00
inline void NO_RETURN
abort(Context* c)
{
2008-04-17 02:55:38 +00:00
abort(c->system);
}
2008-04-17 02:55:38 +00:00
#ifndef NDEBUG
inline void
assert(Context* c, bool v)
{
2008-04-17 02:55:38 +00:00
assert(c->system, v);
}
2008-04-17 02:55:38 +00:00
#endif // not NDEBUG
2008-04-17 02:55:38 +00:00
inline void
expect(Context* c, bool v)
{
2008-04-17 02:55:38 +00:00
expect(c->system, v);
}
2008-04-17 20:48:26 +00:00
Value*
value(Context* c, Site* site = 0)
{
return new (c->zone->allocate(sizeof(Value))) Value(site);
}
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;
}
void
stackSync(Context* c, Stack* start, unsigned count)
{
Stack* segment[count];
unsigned index = count;
for (Stack* s = start; s and index; s = s->next) {
segment[--index] = s;
}
for (unsigned i = 0; i < count; ++i) {
Stack* s = segment[i];
if (s->value) {
apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites));
StackSite* site = stackSite(c, s);
site->next = s->value->sites;
s->value->sites = site;
} else {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
c->assembler->apply
(Subtract, BytesPerWord, ConstantOperand, &offset,
RegisterOperand, &stack);
}
s->pushed = true;
}
}
void
acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue,
Site* newSite)
{
Value* oldValue = c->registers[r].value;
2008-04-18 00:39:41 +00:00
if (oldValue and findSite(c, oldValue, c->registers[r].site)) {
2008-04-17 22:07:32 +00:00
if (oldValue->sites->next == 0 and oldValue->reads) {
unsigned count = 0;
Stack* start = 0;
for (Stack* s = stack; s and not s->pushed; s = s->next) {
if (s->value == oldValue) {
start = s;
}
if (start) {
++ count;
}
}
assert(c, start);
stackSync(c, start, count);
}
2008-04-18 00:39:41 +00:00
removeSite(c, oldValue, c->registers[r].site);
2008-04-17 22:07:32 +00:00
}
c->registers[r].size = newSize;
c->registers[r].value = newValue;
c->registers[r].site = newSite;
}
2008-04-17 02:55:38 +00:00
void
2008-04-17 22:07:32 +00:00
apply(Context* c, UnaryOperation op, unsigned size, Site* a)
2008-04-17 02:55:38 +00:00
{
OperandType type = a->type(c);
Assembler::Operand* operand = a->asAssemblerOperand(c);
2008-03-15 20:24:04 +00:00
2008-04-17 02:55:38 +00:00
c->assembler->apply(op, size, type, operand);
}
2008-04-17 02:55:38 +00:00
void
2008-04-17 22:07:32 +00:00
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b)
2008-04-17 02:55:38 +00:00
{
OperandType aType = a->type(c);
Assembler::Operand* aOperand = a->asAssemblerOperand(c);
2008-04-17 02:55:38 +00:00
OperandType bType = b->type(c);
Assembler::Operand* bOperand = b->asAssemblerOperand(c);
2008-02-17 22:29:04 +00:00
2008-04-17 02:55:38 +00:00
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
}
2008-04-17 02:55:38 +00:00
class PoolPromise: public Promise {
public:
PoolPromise(Context* c, int key): c(c), key(key) { }
2008-03-15 20:24:04 +00:00
2008-04-17 02:55:38 +00:00
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + pad(c->assembler->length()) + (key * BytesPerWord));
2008-03-15 20:24:04 +00:00
}
2008-04-17 02:55:38 +00:00
abort(c);
}
2008-03-15 20:24:04 +00:00
2008-04-17 02:55:38 +00:00
virtual bool resolved() {
return c->machineCode != 0;
}
2008-04-17 02:55:38 +00:00
Context* c;
int key;
2008-02-11 17:21:41 +00:00
};
2008-04-17 02:55:38 +00:00
class CodePromise: public Promise {
public:
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
2007-12-11 23:52:28 +00:00
2008-04-17 02:55:38 +00:00
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
2008-04-17 02:55:38 +00:00
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset);
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
abort(c);
}
2008-04-17 02:55:38 +00:00
virtual bool resolved() {
return c->machineCode != 0 and offset >= 0;
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
Context* c;
int offset;
CodePromise* next;
};
class IpPromise: public Promise {
public:
2008-04-17 02:55:38 +00:00
IpPromise(Context* c, int logicalIp):
c(c),
logicalIp(logicalIp)
{ }
2008-04-17 02:55:38 +00:00
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
}
abort(c);
}
2008-04-17 02:55:38 +00:00
virtual bool resolved() {
return c->machineCode != 0;
2008-03-15 20:24:04 +00:00
}
2008-04-17 02:55:38 +00:00
Context* c;
int logicalIp;
};
2008-04-17 02:55:38 +00:00
class Event {
public:
2008-04-17 22:07:32 +00:00
Event(Context* c):
2008-04-18 00:39:41 +00:00
next(0), stack(c->state->stack), promises(0), reads(0),
2008-04-17 22:07:32 +00:00
logicalIp(c->logicalIp)
{
2008-04-17 02:55:38 +00:00
assert(c, c->logicalIp >= 0);
2008-04-17 22:07:32 +00:00
if (c->lastEvent) {
c->lastEvent->next = this;
sequence = c->lastEvent->sequence + 1;
} else {
c->firstEvent = this;
sequence = 0;
2008-04-17 02:55:38 +00:00
}
2008-04-17 22:07:32 +00:00
c->lastEvent = this;
2008-04-17 02:55:38 +00:00
}
2008-04-17 22:07:32 +00:00
Event(Context*, Event* next):
2008-04-18 00:39:41 +00:00
next(next), stack(next->stack), promises(0), reads(0),
2008-04-17 22:07:32 +00:00
sequence(next->sequence), logicalIp(next->logicalIp)
{ }
2008-04-17 02:55:38 +00:00
virtual ~Event() { }
2008-03-16 19:38:43 +00:00
2008-04-17 02:55:38 +00:00
virtual void compile(Context* c) = 0;
2008-03-15 23:54:20 +00:00
2008-04-17 02:55:38 +00:00
Event* next;
Stack* stack;
CodePromise* promises;
2008-04-17 22:07:32 +00:00
Read* reads;
unsigned sequence;
unsigned logicalIp;
};
void
2008-04-17 20:48:26 +00:00
insertRead(Context* c, Event* thisEvent, Event* before, Value* v,
unsigned size, Site* target)
{
2008-04-17 02:55:38 +00:00
Read* r = new (c->zone->allocate(sizeof(Read)))
2008-04-17 22:07:32 +00:00
Read(size, v, target, 0, thisEvent, thisEvent->reads);
2008-04-17 20:48:26 +00:00
thisEvent->reads = r;
if (before) {
for (Read** p = &(v->reads); *p;) {
if ((*p)->event->sequence >= before->sequence) {
r->next = *p;
*p = r;
break;
} else {
p = &((*p)->next);
}
}
}
2008-04-17 02:55:38 +00:00
2008-04-17 20:48:26 +00:00
if (r->next == 0) {
if (v->lastRead) {
v->lastRead->next = r;
} else {
v->reads = r;
}
v->lastRead = r;
2008-04-17 02:55:38 +00:00
}
2008-04-17 20:48:26 +00:00
}
void
addRead(Context* c, Value* v, unsigned size, Site* target)
{
2008-04-17 22:07:32 +00:00
insertRead(c, c->lastEvent, 0, v, size, target);
}
2008-04-17 22:07:32 +00:00
void
push(Context* c, unsigned size, Value* v);
2008-04-17 02:55:38 +00:00
class CallEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-04-17 02:55:38 +00:00
CallEvent(Context* c, Value* address, void* indirection, unsigned flags,
2008-04-18 00:39:41 +00:00
TraceHandler* traceHandler, Value* result, unsigned,
2008-04-17 20:48:26 +00:00
Value** arguments, unsigned* argumentSizes,
2008-04-17 02:55:38 +00:00
unsigned argumentCount):
Event(c),
address(address),
indirection(indirection),
traceHandler(traceHandler),
2008-04-17 20:48:26 +00:00
result(result),
flags(flags),
footprint(0)
{
2008-04-17 02:55:38 +00:00
addRead(c, address, BytesPerWord,
(indirection ? registerSite(c, c->assembler->returnLow()) : 0));
2008-04-17 20:48:26 +00:00
for (int i = argumentCount - 1; i >= 0; --i) {
::push(c, argumentSizes[i], arguments[i]);
}
2008-04-17 02:55:38 +00:00
unsigned index = 0;
2008-04-17 22:07:32 +00:00
Stack* s = c->state->stack;
for (unsigned i = 0; i < argumentCount; ++i) {
2008-04-17 20:48:26 +00:00
Site* target;
if (index < c->assembler->argumentRegisterCount()) {
target = registerSite(c, c->assembler->argumentRegister(index));
} else {
target = stackSite(c, s);
footprint += s->size;
}
addRead(c, s->value, s->size * BytesPerWord, target);
2008-04-17 02:55:38 +00:00
index += s->size;
s = s->next;
}
2008-03-15 20:24:04 +00:00
2008-04-17 22:07:32 +00:00
c->state->stack = stack;
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-17 02:55:38 +00:00
fprintf(stderr, "CallEvent.compile\n");
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
if (indirection) {
apply(c, type, BytesPerWord,
constantSite(c, reinterpret_cast<intptr_t>(indirection)));
} else {
apply(c, type, BytesPerWord, address->source);
2008-02-11 17:21:41 +00:00
}
2008-04-18 00:39:41 +00:00
addSite(c, 0, 0, result, registerSite
(c, c->assembler->returnLow(), c->assembler->returnHigh()));
2008-04-17 02:55:38 +00:00
if (traceHandler) {
traceHandler->handleTrace
(new (c->zone->allocate(sizeof(CodePromise)))
CodePromise(c, c->assembler->length()));
2008-03-16 19:38:43 +00:00
}
2008-04-17 20:48:26 +00:00
if (footprint) {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, footprint * BytesPerWord));
c->assembler->apply
2008-04-17 22:07:32 +00:00
(Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack);
2008-04-17 20:48:26 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
Value* address;
void* indirection;
TraceHandler* traceHandler;
Value* result;
2008-04-17 20:48:26 +00:00
unsigned flags;
unsigned footprint;
2008-02-11 17:21:41 +00:00
};
2008-02-11 17:21:41 +00:00
void
2008-04-17 02:55:38 +00:00
appendCall(Context* c, Value* address, void* indirection, unsigned flags,
2008-04-17 22:07:32 +00:00
TraceHandler* traceHandler, Value* result, unsigned resultSize,
Value** arguments, unsigned* argumentSizes, unsigned argumentCount)
2008-02-11 17:21:41 +00:00
{
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(CallEvent)))
CallEvent(c, address, indirection, flags, traceHandler, result,
2008-04-17 22:07:32 +00:00
resultSize, arguments, argumentSizes, argumentCount);
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, value, size, registerSite
(c, c->assembler->returnLow(),
size > BytesPerWord ?
c->assembler->returnHigh() : NoRegister));
}
2008-03-15 20:24:04 +00:00
}
virtual void compile(Context* c) {
2008-04-17 02:55:38 +00:00
fprintf(stderr, "ReturnEvent.compile\n");
2008-04-17 02:55:38 +00:00
Assembler::Register base(c->assembler->base());
Assembler::Register stack(c->assembler->stack());
2008-04-17 22:07:32 +00:00
c->assembler->apply(Move, BytesPerWord, RegisterOperand, &base,
RegisterOperand, &stack);
c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &base);
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-18 00:39:41 +00:00
Site*
writeTarget(Context* c, unsigned size, Value* v)
{
if (v->sites) {
assert(c, v->sites->next == 0);
return v->sites;
} else if (v->reads and v->reads->target) {
Site* s = v->reads->target->readTarget(c, v->reads);
if (s) return s;
}
return freeRegister(c, size, true);
}
2008-04-17 02:55:38 +00:00
class MoveEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-04-17 02:55:38 +00:00
MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst):
Event(c), type(type), size(size), src(src), dst(dst)
{
2008-04-17 02:55:38 +00:00
addRead(c, src, size, 0);
2008-03-15 20:24:04 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-17 02:55:38 +00:00
fprintf(stderr, "MoveEvent.compile\n");
2008-03-15 20:24:04 +00:00
2008-04-18 00:39:41 +00:00
Site* target = writeTarget(c, size, dst);
apply(c, type, size, src->source, target);
addSite(c, stack, size, dst, target);
2007-12-11 21:26:59 +00:00
}
2008-04-17 02:55:38 +00:00
BinaryOperation type;
unsigned size;
2008-04-17 02:55:38 +00:00
Value* src;
Value* dst;
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
appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst)
2007-12-11 21:26:59 +00:00
{
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent(c, type, size, src, dst);
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
2008-04-17 02:55:38 +00:00
class CompareEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-04-17 02:55:38 +00:00
CompareEvent(Context* c, unsigned size, Value* first, Value* second):
Event(c), size(size), first(first), second(second)
{
2008-04-17 02:55:38 +00:00
addRead(c, first, size, 0);
addRead(c, second, size, 0);
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
2008-03-15 20:24:04 +00:00
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-17 02:55:38 +00:00
fprintf(stderr, "CompareEvent.compile\n");
2008-03-15 20:24:04 +00:00
2008-04-17 02:55:38 +00:00
apply(c, Compare, size, first->source, second->source);
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
{
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(CompareEvent)))
CompareEvent(c, size, first, second);
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
class BranchEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-04-17 02:55:38 +00:00
BranchEvent(Context* c, UnaryOperation type, Value* address):
Event(c), type(type), address(address)
{
2008-04-17 02:55:38 +00:00
addRead(c, address, BytesPerWord, 0);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-17 02:55:38 +00:00
fprintf(stderr, "BranchEvent.compile\n");
2008-03-15 20:24:04 +00:00
2008-04-17 02:55:38 +00:00
apply(c, type, BytesPerWord, address->source);
2008-02-11 17:21:41 +00:00
}
2007-12-16 21:30:19 +00:00
2008-04-17 02:55:38 +00:00
UnaryOperation type;
Value* address;
2008-02-11 17:21:41 +00:00
};
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
void
2008-04-17 02:55:38 +00:00
appendBranch(Context* c, UnaryOperation type, Value* address)
2008-02-11 17:21:41 +00:00
{
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address);
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
class CombineEvent: public Event {
public:
2008-04-17 02:55:38 +00:00
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result):
Event(c), type(type), size(size), first(first), second(second),
result(result)
{
2008-04-17 02:55:38 +00:00
Assembler::Register r1(NoRegister);
Assembler::Register r2(NoRegister);
c->assembler->getTargets(type, size, &r1, &r2);
2008-02-11 17:21:41 +00:00
2008-04-17 02:55:38 +00:00
addRead(c, first, size,
r1.low == NoRegister ? 0 : registerSite(c, r1.low, r1.high));
addRead(c, second, size,
r2.low == NoRegister ?
2008-04-17 22:07:32 +00:00
valueSite(c, result) :
static_cast<Site*>(registerSite(c, r2.low, r2.high)));
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "CombineEvent.compile\n");
2008-04-17 02:55:38 +00:00
apply(c, type, size, first->source, second->source);
2008-04-18 00:39:41 +00:00
removeSite(c, second, second->source);
addSite(c, 0, 0, result, second->source);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
BinaryOperation type;
unsigned size;
2008-04-17 02:55:38 +00:00
Value* first;
Value* second;
2008-04-17 22:07:32 +00:00
Value* result;
2008-02-11 17:21:41 +00:00
};
2008-02-11 17:21:41 +00:00
void
2008-04-17 02:55:38 +00:00
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result)
2008-02-11 17:21:41 +00:00
{
new (c->zone->allocate(sizeof(CombineEvent)))
2008-04-17 02:55:38 +00:00
CombineEvent(c, type, size, first, second, result);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
class TranslateEvent: public Event {
public:
2008-04-17 02:55:38 +00:00
TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result):
Event(c), type(type), size(size), value(value), result(result)
{
2008-04-17 02:55:38 +00:00
addRead(c, value, size, valueSite(c, result));
2008-03-15 20:24:04 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "TranslateEvent.compile\n");
2008-04-17 02:55:38 +00:00
apply(c, type, size, value->source);
2008-04-18 00:39:41 +00:00
removeSite(c, value, value->source);
addSite(c, 0, 0, result, value->source);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
UnaryOperation 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-04-17 02:55:38 +00:00
appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result)
2008-02-11 17:21:41 +00:00
{
new (c->zone->allocate(sizeof(TranslateEvent)))
2008-04-17 02:55:38 +00:00
TranslateEvent(c, type, size, value, result);
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
{
2008-04-17 02:55:38 +00:00
addRead(c, base, BytesPerWord, anyRegisterSite(c));
if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c));
2008-03-15 23:54:20 +00:00
}
2008-04-17 22:07:32 +00:00
virtual void compile(Context* c) {
2008-03-15 23:54:20 +00:00
fprintf(stderr, "MemoryEvent.compile\n");
2008-04-17 20:48:26 +00:00
int indexRegister;
if (index) {
2008-04-18 00:39:41 +00:00
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
addSite(c, 0, 0, result, memorySite
(c, baseRegister, displacement, indexRegister, scale));
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-17 22:07:32 +00:00
Site*
stackSyncSite(Context* c, unsigned index, unsigned size)
{
int high = NoRegister;
for (int i = c->assembler->registerCount(); i >= 0; --i) {
if (not c->registers[i].reserved) {
if (index == 0) {
if (size == 1) {
return registerSite(c, i, high);
} else {
high = i;
-- size;
}
} else {
-- index;
}
}
}
abort(c);
}
2008-04-17 20:48:26 +00:00
class StackSyncEvent: public Event {
public:
StackSyncEvent(Context* c, bool forCall):
Event(c)
{
unsigned i = 0;
for (Stack* s = stack; s; s = s->next) {
addRead(c, s->value, s->size * BytesPerWord,
forCall ? stackSite(c, s) : stackSyncSite(c, i, s->size));
i += s->size;
}
}
StackSyncEvent(Context* c, Event* next):
Event(c, next)
{
unsigned i = 0;
for (Stack* s = stack; s; s = s->next) {
insertRead(c, this, next, s->value, s->size * BytesPerWord,
stackSyncSite(c, i, s->size));
i += s->size;
}
}
2008-04-17 22:07:32 +00:00
virtual void compile(Context*) {
2008-04-17 20:48:26 +00:00
fprintf(stderr, "StackSyncEvent.compile\n");
for (Read* r = reads; r; r = r->eventNext) {
r->value->sites = r->target;
r->target->next = 0;
}
}
};
void
2008-04-17 22:07:32 +00:00
appendStackSync(Context* c, bool forCall = false)
2008-04-17 20:48:26 +00:00
{
new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c, forCall);
2008-04-17 02:55:38 +00:00
}
Site*
2008-04-18 00:39:41 +00:00
readSource(Context* c, Stack* stack, Read* r)
2008-04-17 02:55:38 +00:00
{
2008-04-18 00:39:41 +00:00
Site* target = (r->target ? r->target->readTarget(c, r) : 0);
unsigned copyCost;
Site* site = pick(c, r->value->sites, target, &copyCost);
if (site->type(c) == StackOperand) {
bool success = false;;
for (Stack* s = stack; s; s = s->next) {
if (s->pushed) {
target = writeTarget(c, s->size * BytesPerWord, s->value);
addSite(c, stack, s->size * BytesPerWord, s->value, target);
s->pushed = false;
if (s == static_cast<StackSite*>(site)->stack) {
site = pick(c, r->value->sites, target, &copyCost);
success = true;
break;
}
}
}
assert(c, success);
}
if (target) {
if (copyCost) {
addSite(c, stack, r->size, r->value, target);
target->accept(c, r->size, site);
}
return target;
2008-04-17 02:55:38 +00:00
} else {
2008-04-18 00:39:41 +00:00
return site;
2008-04-17 02:55:38 +00:00
}
2007-12-11 21:26:59 +00:00
}
void
2008-04-17 02:55:38 +00:00
compile(Context* c)
2007-12-11 21:26:59 +00:00
{
2008-04-17 02:55:38 +00:00
Assembler* a = c->assembler;
Assembler::Register base(a->base());
Assembler::Register stack(a->stack());
2008-04-17 22:07:32 +00:00
a->apply(Push, BytesPerWord, RegisterOperand, &base);
a->apply(Move, BytesPerWord, RegisterOperand, &stack,
RegisterOperand, &base);
2008-04-17 02:55:38 +00:00
if (c->stackOffset) {
Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord));
2008-04-17 22:07:32 +00:00
a->apply(Subtract, BytesPerWord, ConstantOperand, &offset,
RegisterOperand, &stack);
2008-04-17 02:55:38 +00:00
}
for (Event* e = c->firstEvent; e; e = e->next) {
LogicalInstruction* li = c->logicalCode + e->logicalIp;
li->machineOffset = a->length();
for (Read* r = e->reads; r; r = r->eventNext) {
2008-04-18 00:39:41 +00:00
r->value->source = readSource(c, e->stack, r);
2008-04-17 02:55:38 +00:00
r->value->reads = r->value->reads->next;
}
2008-04-17 02:55:38 +00:00
e->compile(c);
for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->length();
}
}
}
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-02-11 17:21:41 +00:00
pushState(Context* c)
{
2008-02-11 17:21:41 +00:00
c->state = new (c->zone->allocate(sizeof(State)))
State(c->state);
}
2008-02-11 17:21:41 +00:00
void
popState(Context* c)
2007-12-11 23:52:28 +00:00
{
2008-02-11 17:21:41 +00:00
c->state = new (c->zone->allocate(sizeof(State)))
State(c->state->next);
2007-12-11 23:52:28 +00:00
}
Stack*
2008-04-17 02:55:38 +00:00
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
{
return new (c->zone->allocate(sizeof(Stack)))
2008-04-17 02:55:38 +00:00
Stack(value, size, index, next);
}
2008-02-17 22:29:04 +00:00
Stack*
2008-04-17 02:55:38 +00:00
stack(Context* c, Value* value, unsigned size, Stack* next)
2008-02-17 22:29:04 +00:00
{
2008-04-17 22:07:32 +00:00
return stack(c, value, size, (next ? next->index + size : 0), next);
2008-02-17 22:29:04 +00:00
}
void
2008-04-17 02:55:38 +00:00
push(Context* c, unsigned size, Value* v)
{
assert(c, ceiling(size, BytesPerWord));
2008-04-17 02:55:38 +00:00
c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack);
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
2008-04-17 02:55:38 +00:00
Value*
pop(Context* c, unsigned size UNUSED)
2008-02-11 17:21:41 +00:00
{
Stack* s = c->state->stack;
assert(c, ceiling(size, BytesPerWord) == s->size);
2008-04-17 22:07:32 +00:00
//appendPop(c, s->size, false);
c->state->stack = s->next;
2008-04-17 02:55:38 +00:00
return s->value;
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
void
updateJunctions(Context* c)
{
for (Junction* j = c->junctions; j; j = j->next) {
LogicalInstruction* i = c->logicalCode + j->logicalIp;
if (i->predecessor >= 0) {
LogicalInstruction* p = c->logicalCode + i->predecessor;
2008-04-17 20:48:26 +00:00
p->lastEvent = p->lastEvent->next
= new (c->zone->allocate(sizeof(StackSyncEvent)))
StackSyncEvent(c, p->lastEvent->next);
2007-12-11 23:52:28 +00:00
}
}
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
2008-04-17 02:55:38 +00:00
int
freeRegisterExcept(Context* c, int except, bool allowAcquired)
2008-02-11 17:21:41 +00:00
{
2008-04-17 02:55:38 +00:00
for (int i = c->assembler->registerCount(); i >= 0; --i) {
if (i != except
and (not c->registers[i].reserved)
and c->registers[i].value == 0)
{
return i;
}
}
2008-04-17 02:55:38 +00:00
if (allowAcquired) {
for (int i = c->assembler->registerCount(); i >= 0; --i) {
if (i != except
and (not c->registers[i].reserved))
{
return i;
}
}
}
2008-04-17 02:55:38 +00:00
abort(c);
}
2008-04-17 02:55:38 +00:00
int
freeRegister(Context* c, bool allowAcquired)
{
return freeRegisterExcept(c, NoRegister, allowAcquired);
}
2008-03-15 23:54:20 +00:00
2008-04-17 02:55:38 +00:00
RegisterSite*
freeRegister(Context* c, unsigned size, bool allowAcquired)
{
if (BytesPerWord == 4 and size == 8) {
int low = freeRegister(c, allowAcquired);
return registerSite(c, low, freeRegisterExcept(c, low, allowAcquired));
} else {
return registerSite(c, freeRegister(c, allowAcquired));
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
}
class Client: public Assembler::Client {
public:
Client(Context* c): c(c) { }
2008-03-15 21:02:19 +00:00
virtual int acquireTemporary(int r) {
if (r == NoRegister) {
r = freeRegisterExcept(c, NoRegister, false);
} else {
expect(c, not c->registers[r].reserved);
2008-04-17 02:55:38 +00:00
expect(c, c->registers[r].value == 0);
2008-03-15 21:02:19 +00:00
}
c->registers[r].reserved = true;
return r;
}
virtual void releaseTemporary(int r) {
c->registers[r].reserved = false;
}
Context* c;
};
2007-12-08 23:22:13 +00:00
class MyCompiler: public Compiler {
public:
2008-02-11 17:21:41 +00:00
MyCompiler(System* s, Assembler* assembler, Zone* zone):
c(s, assembler, zone), client(&c)
{
assembler->setClient(&client);
}
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
virtual void pushState() {
::pushState(&c);
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void popState() {
2008-03-15 20:24:04 +00:00
::popState(&c);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void init(unsigned logicalCodeLength, unsigned stackOffset) {
c.logicalCodeLength = logicalCodeLength;
c.stackOffset = stackOffset;
c.logicalCode = static_cast<LogicalInstruction*>
(c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength));
memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength);
}
2008-02-11 17:21:41 +00:00
virtual void visitLogicalIp(unsigned logicalIp) {
if ((++ c.logicalCode[logicalIp].visits) == 1) {
c.junctions = new (c.zone->allocate(sizeof(Junction)))
Junction(logicalIp, c.junctions);
}
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void startLogicalIp(unsigned logicalIp) {
if (c.logicalIp >= 0) {
2008-04-17 22:07:32 +00:00
c.logicalCode[c.logicalIp].lastEvent = c.lastEvent;
2008-02-11 17:21:41 +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-17 20:48:26 +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-17 20:48:26 +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() {
2008-04-17 20:48:26 +00:00
return value(&c, registerSite(&c, c.assembler->stack()));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* base() {
2008-04-17 20:48:26 +00:00
return value(&c, registerSite(&c, c.assembler->base()));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* thread() {
2008-04-17 20:48:26 +00:00
return value(&c, registerSite(&c, c.assembler->thread()));
2007-12-08 23:22:13 +00:00
}
virtual bool isConstant(Operand* a) {
2008-04-17 22:07:32 +00:00
for (Site* s = static_cast<Value*>(a)->sites; s; s = s->next) {
if (s->type(&c) == ConstantOperand) return true;
}
return false;
}
virtual int64_t constantValue(Operand* a) {
2008-04-17 22:07:32 +00:00
for (Site* s = static_cast<Value*>(a)->sites; s; s = s->next) {
if (s->type(&c) == ConstantOperand) {
return static_cast<ConstantSite*>(s)->value.value->value();
}
}
abort(&c);
}
2007-12-08 23:22:13 +00:00
virtual Operand* label() {
2008-04-17 20:48:26 +00:00
return value(&c, ::constantSite(&c, static_cast<Promise*>(0)));
2007-12-08 23:22:13 +00:00
}
Promise* machineIp() {
2008-04-17 22:07:32 +00:00
return c.lastEvent->promises = new (c.zone->allocate(sizeof(CodePromise)))
CodePromise(&c, c.lastEvent->promises);
}
2007-12-08 23:22:13 +00:00
virtual void mark(Operand* label) {
2008-04-17 20:48:26 +00:00
appendStackSync(&c);
2008-03-15 23:54:20 +00:00
2008-04-17 22:07:32 +00:00
for (Site* s = static_cast<Value*>(label)->sites; s; s = s->next) {
if (s->type(&c) == ConstantOperand) {
static_cast<ConstantSite*>(s)->value.value = machineIp();
return;
}
}
abort(&c);
2007-12-08 23:22:13 +00:00
}
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
}
virtual void pushed(unsigned count) {
2008-03-15 23:54:20 +00:00
for (unsigned i = 0; i < count; ++i) {
2008-04-17 20:48:26 +00:00
Value* a = value(&c);
2008-03-15 23:54:20 +00:00
::push(&c, BytesPerWord, a);
2008-04-17 20:48:26 +00:00
a->sites = stackSite(&c, c.state->stack);
2008-03-15 23:54:20 +00:00
}
}
virtual void popped(unsigned count) {
2008-04-17 22:07:32 +00:00
// appendPop(&c, count, true);
2008-03-15 23:54:20 +00:00
for (unsigned i = count; i;) {
Stack* s = c.state->stack;
c.state->stack = s->next;
i -= s->size;
}
2007-12-08 23:22:13 +00:00
}
virtual Operand* peek(unsigned size UNUSED, unsigned index) {
Stack* s = c.state->stack;
for (unsigned i = index; i > 0;) {
s = s->next;
i -= s->size;
}
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,
void* indirection,
unsigned flags,
TraceHandler* traceHandler,
2008-04-17 20:48:26 +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];
unsigned 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);
2008-04-17 20:48:26 +00:00
appendStackSync(&c, true);
Value* result = value(&c);
appendCall(&c, static_cast<Value*>(address), indirection, flags,
traceHandler, result, resultSize, arguments, argumentSizes,
index);
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 store(unsigned size, Operand* src, Operand* dst) {
2008-04-17 20:48:26 +00:00
appendMove(&c, Move, size, static_cast<Value*>(src),
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), 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), 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, Move4To8, 0, static_cast<Value*>(src), dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
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
appendStackSync(&c);
2007-12-08 23:22:13 +00:00
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
appendStackSync(&c);
2007-12-08 23:22:13 +00:00
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
appendStackSync(&c);
2007-12-08 23:22:13 +00:00
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
appendStackSync(&c);
2007-12-08 23:22:13 +00:00
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
appendStackSync(&c);
2007-12-08 23:22:13 +00:00
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
appendStackSync(&c);
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 20:48:26 +00:00
appendStackSync(&c);
2007-12-09 22:45:43 +00:00
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),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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, size, static_cast<Value*>(a),
static_cast<Value*>(b), 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, size, static_cast<Value*>(a),
static_cast<Value*>(b), 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, size, static_cast<Value*>(a),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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),
static_cast<Value*>(b), 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() {
updateJunctions(&c);
::compile(&c);
return c.assembler->length();
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) {
*reinterpret_cast<intptr_t*>(dst + pad(c.assembler->length()) + (i++))
2008-02-11 17:21:41 +00:00
= n->promise->value();
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-02-11 17:21:41 +00:00
makeCompiler(System* system, Assembler* assembler, Zone* zone)
2007-12-08 23:22:13 +00:00
{
return new (zone->allocate(sizeof(MyCompiler)))
2008-02-11 17:21:41 +00:00
MyCompiler(system, assembler, zone);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
} // namespace vm