corda/src/compiler.cpp

1572 lines
37 KiB
C++
Raw Normal View History

#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 MyOperand;
class ConstantValue;
class AddressValue;
class RegisterValue;
class MemoryValue;
class Event;
enum SyncType {
SyncForCall,
SyncForJump
2007-12-09 22:45:43 +00:00
};
2008-02-11 17:21:41 +00:00
class Value {
public:
virtual ~Value() { }
2008-02-11 17:21:41 +00:00
virtual bool equals(Value*) { return false; }
virtual bool equals(RegisterValue*) { return false; }
2007-12-11 21:26:59 +00:00
2008-02-11 17:21:41 +00:00
virtual void preserve(Context*) { }
virtual void acquire(Context*, MyOperand*) { }
virtual void release(Context*, MyOperand*) { }
2008-02-11 17:21:41 +00:00
virtual RegisterValue* toRegister(Context*, unsigned size) = 0;
2007-12-09 20:03:21 +00:00
2008-02-11 17:21:41 +00:00
virtual void asAssemblerOperand(Context*,
OperandType* type,
Assembler::Operand** operand) = 0;
};
2007-12-09 20:03:21 +00:00
2008-02-11 17:21:41 +00:00
class MyOperand: public Compiler::Operand {
2007-12-16 00:24:15 +00:00
public:
2008-02-11 17:21:41 +00:00
MyOperand(unsigned size, Value* value):
size(size), event(0), value(value), target(0), index(0), next(0)
2007-12-16 00:24:15 +00:00
{ }
2008-02-11 17:21:41 +00:00
unsigned size;
Event* event;
Value* value;
Value* target;
unsigned index;
MyOperand* next;
2007-12-16 00:24:15 +00:00
};
2008-02-11 17:21:41 +00:00
class State {
2007-12-08 23:22:13 +00:00
public:
2008-02-11 17:21:41 +00:00
State(State* s):
stack(s ? s->stack : 0),
next(s)
{ }
2008-02-11 17:21:41 +00:00
MyOperand* stack;
State* next;
2007-12-09 20:03:21 +00:00
};
2008-02-11 17:21:41 +00:00
class LogicalInstruction {
public:
2008-02-11 17:21:41 +00:00
unsigned visits;
Event* firstEvent;
Event* lastEvent;
unsigned machineOffset;
int predecessor;
2007-12-11 21:26:59 +00:00
};
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
class RegisterElement {
2007-12-11 21:26:59 +00:00
public:
2008-02-11 17:21:41 +00:00
bool reserved;
MyOperand* operand;
2007-12-11 21:26:59 +00:00
};
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
class ConstantPoolNode {
2007-12-16 00:24:15 +00:00
public:
2008-02-11 17:21:41 +00:00
ConstantPoolNode(Promise* promise): promise(promise), next(0) { }
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
Promise* promise;
ConstantPoolNode* next;
2007-12-16 00:24:15 +00:00
};
2008-02-11 17:21:41 +00:00
class Junction {
2007-12-16 21:30:19 +00:00
public:
2008-02-11 17:21:41 +00:00
Junction(unsigned logicalIp, Junction* next):
logicalIp(logicalIp),
next(next)
{ }
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
unsigned logicalIp;
Junction* next;
2007-12-16 21:30:19 +00:00
};
class Context {
public:
2008-02-11 17:21:41 +00:00
Context(System* system, Assembler* assembler, Zone* zone):
system(system),
assembler(assembler),
zone(zone),
2008-02-11 17:21:41 +00:00
logicalIp(-1),
state(new (zone->allocate(sizeof(State))) State(0)),
event(0),
logicalCode(0),
logicalCodeLength(0),
stackOffset(0),
registers(static_cast<RegisterElement*>
(zone->allocate
(sizeof(RegisterElement) * assembler->registerCount()))),
firstConstant(0),
lastConstant(0),
constantCount(0),
junctions(0),
machineCode(0)
2007-12-16 21:30:19 +00:00
{
2008-02-11 17:21:41 +00:00
memset(registers, 0, sizeof(RegisterElement) * assembler->registerCount());
registers[assembler->base()].reserved = true;
registers[assembler->stack()].reserved = true;
registers[assembler->thread()].reserved = true;
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
System* system;
Assembler* assembler;
Zone* zone;
2008-02-11 17:21:41 +00:00
int logicalIp;
State* state;
Event* event;
LogicalInstruction* logicalCode;
unsigned logicalCodeLength;
unsigned stackOffset;
RegisterElement* registers;
ConstantPoolNode* firstConstant;
ConstantPoolNode* lastConstant;
unsigned constantCount;
Junction* junctions;
uint8_t* machineCode;
2007-12-16 21:30:19 +00:00
};
inline void NO_RETURN
abort(Context* c)
{
2008-02-11 17:21:41 +00:00
abort(c->system);
2007-12-16 21:30:19 +00:00
}
#ifndef NDEBUG
inline void
assert(Context* c, bool v)
{
2008-02-11 17:21:41 +00:00
assert(c->system, v);
2007-12-16 21:30:19 +00:00
}
#endif // not NDEBUG
inline void
expect(Context* c, bool v)
{
2008-02-11 17:21:41 +00:00
expect(c->system, v);
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
void
apply(Context* c, UnaryOperation op, unsigned size, Value* a)
{
OperandType type;
Assembler::Operand* operand;
a->asAssemblerOperand(c, &type, &operand);
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
c->assembler->apply(op, size, type, operand);
}
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
void
apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b)
{
OperandType aType;
Assembler::Operand* aOperand;
a->asAssemblerOperand(c, &aType, &aOperand);
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
OperandType bType;
Assembler::Operand* bOperand;
b->asAssemblerOperand(c, &bType, &bOperand);
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
}
2008-02-11 17:21:41 +00:00
class PoolPromise: public Promise {
2007-12-16 21:30:19 +00:00
public:
2008-02-11 17:21:41 +00:00
PoolPromise(Context* c, int key): c(c), key(key) { }
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + c->assembler->length() + key);
2007-12-16 21:30:19 +00:00
}
abort(c);
}
2008-02-11 17:21:41 +00:00
virtual bool resolved() {
return c->machineCode != 0;
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
Context* c;
int key;
2007-12-16 21:30:19 +00:00
};
2008-02-11 17:21:41 +00:00
class CodePromise: public Promise {
2007-12-16 21:30:19 +00:00
public:
2008-02-11 17:21:41 +00:00
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset);
2007-12-16 21:30:19 +00:00
}
abort(c);
}
2008-02-11 17:21:41 +00:00
virtual bool resolved() {
return c->machineCode != 0 and offset >= 0;
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
Context* c;
int offset;
CodePromise* next;
2007-12-16 21:30:19 +00:00
};
2008-02-11 17:21:41 +00:00
class IpPromise: public Promise {
2007-12-16 21:30:19 +00:00
public:
2008-02-11 17:21:41 +00:00
IpPromise(Context* c, int logicalIp):
c(c),
2007-12-16 21:30:19 +00:00
logicalIp(logicalIp)
{ }
2008-02-11 17:21:41 +00:00
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
2007-12-16 21:30:19 +00:00
}
abort(c);
}
2008-02-11 17:21:41 +00:00
virtual bool resolved() {
return c->machineCode != 0;
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
Context* c;
int logicalIp;
2007-12-16 21:30:19 +00:00
};
2008-02-11 17:21:41 +00:00
RegisterValue*
freeRegister(Context* c, unsigned size);
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
class ConstantValue: public Value {
public:
ConstantValue(Promise* value): value(value) { }
2007-12-17 01:46:46 +00:00
2008-02-11 17:21:41 +00:00
virtual RegisterValue* toRegister(Context* c, unsigned size);
2008-02-11 17:21:41 +00:00
virtual void asAssemblerOperand(Context*,
OperandType* type,
Assembler::Operand** operand)
{
*type = Constant;
*operand = &value;
}
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
Assembler::Constant value;
2007-12-16 21:30:19 +00:00
};
2008-02-11 17:21:41 +00:00
ConstantValue*
constant(Context* c, Promise* value)
2007-12-16 21:30:19 +00:00
{
2008-02-11 17:21:41 +00:00
return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value);
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
ConstantValue*
constant(Context* c, int64_t value)
2007-12-16 21:30:19 +00:00
{
2008-02-11 17:21:41 +00:00
return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value));
2007-12-16 21:30:19 +00:00
}
2008-02-11 17:21:41 +00:00
class AddressValue: public Value {
2007-12-19 01:28:55 +00:00
public:
2008-02-11 17:21:41 +00:00
AddressValue(Promise* address): address(address) { }
2007-12-19 01:28:55 +00:00
2008-02-11 17:21:41 +00:00
virtual RegisterValue* toRegister(Context* c, unsigned size);
2008-02-11 17:21:41 +00:00
virtual void asAssemblerOperand(Context*,
OperandType* type,
Assembler::Operand** operand)
{
*type = Address;
*operand = &address;
2007-12-19 01:28:55 +00:00
}
2008-02-11 17:21:41 +00:00
Assembler::Address address;
};
2007-12-19 01:28:55 +00:00
2008-02-11 17:21:41 +00:00
AddressValue*
address(Context* c, Promise* address)
{
return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address);
}
2008-02-11 17:21:41 +00:00
void preserve(Context* c, int reg);
2007-12-19 01:28:55 +00:00
2008-02-11 17:21:41 +00:00
class RegisterValue: public Value {
2007-12-09 20:03:21 +00:00
public:
2008-02-11 17:21:41 +00:00
RegisterValue(int low, int high): register_(low, high) { }
2007-12-09 20:03:21 +00:00
2008-02-11 17:21:41 +00:00
virtual bool equals(Value* o) { return o->equals(this); }
2008-02-11 17:21:41 +00:00
virtual bool equals(RegisterValue* o) {
return o->register_.low == register_.low
and o->register_.high == register_.high;
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void preserve(Context* c) {
::preserve(c, register_.low);
if (register_.high >= 0) ::preserve(c, register_.high);
}
2008-02-11 17:21:41 +00:00
virtual void acquire(Context* c, MyOperand* a) {
preserve(c);
c->registers[register_.low].operand = a;
if (register_.high >= 0) c->registers[register_.high].operand = a;
2007-12-09 20:03:21 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void release(Context* c, MyOperand* a UNUSED) {
assert(c, a == c->registers[register_.low].operand);
2007-12-09 20:03:21 +00:00
2008-02-11 17:21:41 +00:00
c->registers[register_.low].operand = 0;
if (register_.high >= 0) c->registers[register_.high].operand = 0;
2007-12-09 20:03:21 +00:00
}
2008-02-11 17:21:41 +00:00
virtual RegisterValue* toRegister(Context*, unsigned) {
return this;
2007-12-09 22:45:43 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void asAssemblerOperand(Context*,
OperandType* type,
Assembler::Operand** operand)
{
*type = Register;
*operand = &register_;
}
2008-02-11 17:21:41 +00:00
Assembler::Register register_;
2007-12-09 22:45:43 +00:00
};
2008-02-11 17:21:41 +00:00
RegisterValue*
register_(Context* c, int low, int high = NoRegister)
{
return new (c->zone->allocate(sizeof(RegisterValue)))
RegisterValue(low, high);
}
2007-12-09 20:03:21 +00:00
2008-02-11 17:21:41 +00:00
class MemoryValue: public Value {
2007-12-09 20:03:21 +00:00
public:
2008-02-11 17:21:41 +00:00
MemoryValue(int base, int offset, int index, unsigned scale,
TraceHandler* traceHandler):
value(base, offset, index, scale, traceHandler)
{ }
2008-02-11 17:21:41 +00:00
virtual RegisterValue* toRegister(Context* c, unsigned size) {
RegisterValue* v = freeRegister(c, size);
apply(c, Move, size, this, v);
return v;
}
2008-02-11 17:21:41 +00:00
virtual int base(Context*) {
return value.base;
}
2008-02-11 17:21:41 +00:00
virtual int index(Context*) {
return value.index;
}
2008-02-11 17:21:41 +00:00
virtual void asAssemblerOperand(Context* c,
OperandType* type,
Assembler::Operand** operand)
{
value.base = base(c);
value.index = index(c);
*type = Memory;
*operand = &value;
2007-12-30 22:24:48 +00:00
}
2008-02-11 17:21:41 +00:00
Assembler::Memory value;
};
2008-02-11 17:21:41 +00:00
MemoryValue*
memory(Context* c, int base, int offset, int index, unsigned scale,
TraceHandler* traceHandler)
2007-12-09 20:03:21 +00:00
{
2008-02-11 17:21:41 +00:00
return new (c->zone->allocate(sizeof(MemoryValue)))
MemoryValue(base, offset, index, scale, traceHandler);
2007-12-09 20:03:21 +00:00
}
2008-02-11 17:21:41 +00:00
int
toRegister(Context* c, MyOperand* a)
{
2008-02-11 17:21:41 +00:00
assert(c, a->size == BytesPerWord);
2008-02-11 17:21:41 +00:00
return a->value->toRegister(c, a->size)->register_.low;
}
2008-02-11 17:21:41 +00:00
class AbstractMemoryValue: public MemoryValue {
public:
2008-02-11 17:21:41 +00:00
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
unsigned scale, TraceHandler* traceHandler):
MemoryValue(NoRegister, offset, NoRegister, scale, traceHandler),
base_(base), index_(index)
{ }
2008-02-11 17:21:41 +00:00
virtual int base(Context* c) {
return ::toRegister(c, base_);
}
2008-02-11 17:21:41 +00:00
virtual int index(Context* c) {
return index_ ? ::toRegister(c, base_) : NoRegister;
}
2008-02-11 17:21:41 +00:00
MyOperand* base_;
MyOperand* index_;
};
2008-02-11 17:21:41 +00:00
AbstractMemoryValue*
memory(Context* c, MyOperand* base, int offset, MyOperand* index,
unsigned scale, TraceHandler* traceHandler)
{
return new (c->zone->allocate(sizeof(AbstractMemoryValue)))
AbstractMemoryValue(base, offset, index, scale, traceHandler);
}
class Event {
public:
2008-02-11 17:21:41 +00:00
Event(Context* c): next(0), stack(c->state->stack), promises(0) {
if (c->event) {
c->event->next = this;
}
2008-02-11 17:21:41 +00:00
if (c->logicalCode[c->logicalIp].firstEvent == 0) {
c->logicalCode[c->logicalIp].firstEvent = this;
}
2008-02-11 17:21:41 +00:00
c->event = this;
}
2008-02-11 17:21:41 +00:00
Event(Event* next): next(next) { }
2008-02-11 17:21:41 +00:00
virtual ~Event() { }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* value) = 0;
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) = 0;
virtual void compile(Context* c) = 0;
2008-02-11 17:21:41 +00:00
Event* next;
MyOperand* stack;
CodePromise* promises;
};
2008-02-11 17:21:41 +00:00
class ArgumentEvent: public Event {
public:
2008-02-11 17:21:41 +00:00
ArgumentEvent(Context* c, MyOperand* a, unsigned index):
Event(c), a(a), index(index)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == a);
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
if (index < c->assembler->argumentRegisterCount()) {
return register_(c, c->assembler->argumentRegister(index));
} else {
return memory(c, c->assembler->base(),
(v->index + c->stackOffset) * BytesPerWord,
NoRegister, 0, 0);
2007-12-16 00:24:15 +00:00
}
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == a);
a = new_;
new_->target = old->target;
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
a->value->release(c, a);
a->target->preserve(c);
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
if (not a->target->equals(a->value)) {
apply(c, Move, a->size, a->value, a->target);
2007-12-16 00:24:15 +00:00
}
}
2008-02-11 17:21:41 +00:00
MyOperand* a;
unsigned index;
2007-12-16 00:24:15 +00:00
};
void
2008-02-11 17:21:41 +00:00
appendArgument(Context* c, MyOperand* value, unsigned index)
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(ArgumentEvent)))
ArgumentEvent(c, value, index);
}
2008-02-11 17:21:41 +00:00
class ReturnEvent: public Event {
public:
ReturnEvent(Context* c, MyOperand* a):
Event(c), a(a)
{ }
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == a);
2008-02-11 17:21:41 +00:00
return register_(c, c->assembler->returnLow(), c->assembler->returnHigh());
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == a);
a = new_;
a->target = old->target;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
if (a) {
a->value->release(c, a);
if (not a->target->equals(a->value)) {
apply(c, Move, a->size, a->value, a->target);
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
c->assembler->apply(Return);
}
2008-02-11 17:21:41 +00:00
MyOperand* a;
};
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
void
appendReturn(Context* c, MyOperand* value)
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, value);
}
2008-02-11 17:21:41 +00:00
class SyncForCallEvent: public Event {
public:
SyncForCallEvent(Context* c, MyOperand* src, MyOperand* dst):
Event(c), src(src), dst(dst)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == src);
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
return memory(c, c->assembler->base(),
(v->index + c->stackOffset) * BytesPerWord,
NoRegister, 0, 0);
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == src);
src = new_;
src->target = old->target;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
src->value->release(c, src);
2007-12-09 22:45:43 +00:00
2008-02-11 17:21:41 +00:00
if (not src->target->equals(src->value)) {
apply(c, Move, src->size, src->value, src->target);
}
2007-12-09 22:45:43 +00:00
}
2008-02-11 17:21:41 +00:00
MyOperand* src;
MyOperand* dst;
};
2007-12-09 20:03:21 +00:00
2007-12-11 00:48:09 +00:00
void
2008-02-11 17:21:41 +00:00
appendSyncForCall(Context* c, MyOperand* src, MyOperand* dst)
2007-12-11 00:48:09 +00:00
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(SyncForCallEvent)))
SyncForCallEvent(c, src, dst);
2007-12-11 00:48:09 +00:00
}
2008-02-11 17:21:41 +00:00
class SyncForJumpEvent: public Event {
public:
SyncForJumpEvent(Context* c, MyOperand* src, MyOperand* dst):
Event(c), src(src), dst(dst)
{ }
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
SyncForJumpEvent(Event* next, MyOperand* src, MyOperand* dst):
Event(next), src(src), dst(dst)
{ }
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == src);
2007-12-11 00:48:09 +00:00
2008-02-11 17:21:41 +00:00
if (BytesPerWord == 4 and v->size == 8) {
return register_(c, c->assembler->stackSyncRegister(v->index),
c->assembler->stackSyncRegister(v->index + 4));
} else {
return register_(c, c->assembler->stackSyncRegister(v->index));
}
2007-12-11 00:48:09 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == src);
src = new_;
src->target = old->target;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
src->value->release(c, src);
src->target->acquire(c, dst);
2007-12-18 00:22:37 +00:00
2008-02-11 17:21:41 +00:00
if (not src->target->equals(src->value)) {
apply(c, Move, src->size, src->value, src->target);
}
2008-02-11 17:21:41 +00:00
dst->value = src->target;
}
2008-02-11 17:21:41 +00:00
MyOperand* src;
MyOperand* dst;
};
2007-12-11 21:26:59 +00:00
void
2008-02-11 17:21:41 +00:00
appendSyncForJump(Context* c, MyOperand* src, MyOperand* dst)
2007-12-11 21:26:59 +00:00
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(SyncForJumpEvent)))
SyncForJumpEvent(c, src, dst);
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
class CallEvent: public Event {
public:
CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags,
TraceHandler* traceHandler, MyOperand* result,
unsigned stackOffset):
Event(c),
address(address),
indirection(indirection),
flags(flags),
traceHandler(traceHandler),
result(result),
stackOffset(stackOffset)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == address);
2007-12-15 01:11:01 +00:00
2008-02-11 17:21:41 +00:00
if (indirection) {
return register_
(c, c->assembler->returnLow(), c->assembler->returnHigh());
} else {
2008-02-11 17:21:41 +00:00
return 0;
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == address);
address = new_;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
address->value->release(c, address);
2008-02-11 17:21:41 +00:00
if (result->event) {
result->value = register_
(c, c->assembler->returnLow(), c->assembler->returnHigh());
result->value->acquire(c, result);
}
2008-02-11 17:21:41 +00:00
apply(c, LoadAddress, BytesPerWord, register_(c, c->assembler->stack()),
memory(c, c->assembler->base(), stackOffset * BytesPerWord,
NoRegister, 0, 0));
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
if (indirection) {
if (not address->target->equals(address->value)) {
apply(c, Move, address->size, address->value, address->target);
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
apply(c, Call, BytesPerWord,
constant(c, reinterpret_cast<intptr_t>(indirection)));
} else {
2008-02-11 17:21:41 +00:00
apply(c, Call, address->size, address->value);
}
}
2008-02-11 17:21:41 +00:00
MyOperand* address;
void* indirection;
unsigned flags;
TraceHandler* traceHandler;
MyOperand* result;
unsigned stackOffset;
};
2007-12-11 23:52:28 +00:00
void
2008-02-11 17:21:41 +00:00
appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags,
TraceHandler* traceHandler, MyOperand* result,
unsigned stackOffset)
2007-12-11 23:52:28 +00:00
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(CallEvent)))
CallEvent(c, address, indirection, flags, traceHandler, result,
stackOffset);
2007-12-11 23:52:28 +00:00
}
2008-02-11 17:21:41 +00:00
int
freeRegister(Context* c)
2007-12-11 21:26:59 +00:00
{
2008-02-11 17:21:41 +00:00
for (unsigned i = 0; i < c->assembler->registerCount(); ++i) {
if ((not c->registers[i].reserved)
and c->registers[i].operand == 0)
{
return i;
}
}
2008-02-11 17:21:41 +00:00
for (unsigned i = 0; i < c->assembler->registerCount(); ++i) {
if (not c->registers[i].reserved) {
return i;
}
}
2008-02-11 17:21:41 +00:00
abort(c);
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
RegisterValue*
freeRegister(Context* c, unsigned size)
{
2008-02-11 17:21:41 +00:00
if (BytesPerWord == 4 and size == 8) {
return register_(c, freeRegister(c), freeRegister(c));
} else {
return register_(c, freeRegister(c));
}
}
2008-02-11 17:21:41 +00:00
class MoveEvent: public Event {
public:
MoveEvent(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst):
Event(c), type(type), src(src), dst(dst)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == src);
if (dst->value) {
return dst->value;
} else {
return v->event->target(c, dst);
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == src);
src = new_;
src->target = old->target;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
if (src->target == 0) {
if (dst->value) {
src->target = dst->value;
} else {
src->target = freeRegister(c, src->size);
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
src->value->release(c, src);
src->target->acquire(c, dst);
2008-02-11 17:21:41 +00:00
apply(c, type, src->size, src->value, src->target);
2008-02-11 17:21:41 +00:00
dst->value = src->target;
}
2008-02-11 17:21:41 +00:00
BinaryOperation type;
MyOperand* src;
MyOperand* dst;
};
2008-02-11 17:21:41 +00:00
void
appendMove(Context* c, BinaryOperation type, MyOperand* src, MyOperand* dst)
{
new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, src, dst);
}
2008-02-11 17:21:41 +00:00
class CompareEvent: public Event {
public:
CompareEvent(Context* c, MyOperand* a, MyOperand* b):
Event(c), a(a), b(b)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == a or v == b);
2008-02-11 17:21:41 +00:00
return 0;
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
if (old == a) {
a = new_;
a->target = old->target;
} else {
2008-02-11 17:21:41 +00:00
assert(c, old == b);
b = new_;
b->target = old->target;
}
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
a->value->release(c, a);
b->value->release(c, b);
2008-02-11 17:21:41 +00:00
apply(c, Compare, a->size, a->value, b->value);
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
MyOperand* a;
MyOperand* b;
};
2007-12-11 21:26:59 +00:00
void
2008-02-11 17:21:41 +00:00
appendCompare(Context* c, MyOperand* a, MyOperand* b)
2007-12-11 21:26:59 +00:00
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, a, b);
}
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
class BranchEvent: public Event {
public:
BranchEvent(Context* c, UnaryOperation type, MyOperand* address):
Event(c), type(type), address(address)
{ }
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == address);
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
return 0;
}
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == address);
address = new_;
address->target = old->target;
}
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
address->value->release(c, address);
2008-02-11 17:21:41 +00:00
apply(c, type, address->size, address->value);
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
UnaryOperation type;
MyOperand* address;
};
2007-12-11 21:26:59 +00:00
void
2008-02-11 17:21:41 +00:00
appendBranch(Context* c, UnaryOperation type, MyOperand* address)
2007-12-11 21:26:59 +00:00
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address);
}
class JumpEvent: public Event {
public:
JumpEvent(Context* c, MyOperand* address):
Event(c),
address(address)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == address);
2008-02-11 17:21:41 +00:00
return 0;
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == address);
address = new_;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
address->value->release(c, address);
2008-02-11 17:21:41 +00:00
apply(c, Jump, address->size, address->value);
}
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
MyOperand* address;
unsigned stackOffset;
bool alignCall;
TraceHandler* traceHandler;
};
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
void
appendJump(Context* c, MyOperand* address)
{
new (c->zone->allocate(sizeof(BranchEvent))) JumpEvent(c, address);
}
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
class CombineEvent: public Event {
public:
CombineEvent(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b,
MyOperand* result):
Event(c), type(type), a(a), b(b), result(result)
{ }
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
Assembler::Register ar(NoRegister);
Assembler::Register br(NoRegister);
c->assembler->getTargets(type, v->size, &ar, &br);
if (v == a) {
if (ar.low == NoRegister) {
return 0;
} else {
2008-02-11 17:21:41 +00:00
return register_(c, ar.low, ar.high);
}
} else {
2008-02-11 17:21:41 +00:00
assert(c, v == b);
if (br.low == NoRegister) {
return result->event->target(c, result);
} else {
2008-02-11 17:21:41 +00:00
return register_(c, br.low, br.high);
2007-12-16 21:30:19 +00:00
}
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
if (old == a) {
a = new_;
a->target = old->target;
} else {
assert(c, old == b);
b = new_;
b->target = old->target;
}
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
a->value->release(c, a);
b->value->release(c, b);
b->value->acquire(c, result);
2008-02-11 17:21:41 +00:00
if (a->target and not a->target->equals(a->value)) {
apply(c, Move, a->size, a->value, a->target);
}
if (b->target and not b->target->equals(b->value)) {
apply(c, Move, b->size, b->value, b->target);
}
2008-02-11 17:21:41 +00:00
apply(c, type, a->size, a->value, b->value);
2008-02-11 17:21:41 +00:00
result->value = b->value;
}
2008-02-11 17:21:41 +00:00
BinaryOperation type;
MyOperand* a;
MyOperand* b;
MyOperand* result;
};
2008-02-11 17:21:41 +00:00
void
appendCombine(Context* c, BinaryOperation type, MyOperand* a, MyOperand* b,
MyOperand* result)
{
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, a, b, result);
}
2008-02-11 17:21:41 +00:00
class TranslateEvent: public Event {
public:
TranslateEvent(Context* c, UnaryOperation type, MyOperand* a,
MyOperand* result):
Event(c), type(type), a(a), result(result)
{ }
2008-02-11 17:21:41 +00:00
virtual Value* target(Context* c, MyOperand* v) {
assert(c, v == a);
Assembler::Register r(NoRegister);
c->assembler->getTargets(type, v->size, &r);
2008-02-11 17:21:41 +00:00
if (r.low == NoRegister) {
return result->event->target(c, result);
} else {
2008-02-11 17:21:41 +00:00
return register_(c, r.low, r.high);
}
2008-02-11 17:21:41 +00:00
}
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
assert(c, old == a);
a = new_;
a->target = old->target;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
result->value->acquire(c, result);
2008-02-11 17:21:41 +00:00
apply(c, type, a->size, a->value);
2008-02-11 17:21:41 +00:00
result->value = a->value;
}
2008-02-11 17:21:41 +00:00
UnaryOperation type;
MyOperand* a;
MyOperand* result;
};
2008-02-11 17:21:41 +00:00
void
appendTranslate(Context* c, UnaryOperation type, MyOperand* a,
MyOperand* result)
{
new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent(c, type, a, result);
}
2008-02-11 17:21:41 +00:00
RegisterValue*
ConstantValue::toRegister(Context* c, unsigned size)
{
RegisterValue* v = freeRegister(c, size);
apply(c, Move, size, this, v);
return v;
}
2007-12-18 00:22:37 +00:00
2008-02-11 17:21:41 +00:00
RegisterValue*
AddressValue::toRegister(Context* c, unsigned size)
{
RegisterValue* v = freeRegister(c, size);
apply(c, Move, size, this, v);
return v;
2007-12-11 21:26:59 +00:00
}
void
2008-02-11 17:21:41 +00:00
preserve(Context* c, int reg)
2007-12-11 21:26:59 +00:00
{
2008-02-11 17:21:41 +00:00
MyOperand* a = c->registers[reg].operand;
if (a) {
MemoryValue* dst = memory
(c, c->assembler->base(), (a->index + c->stackOffset) * BytesPerWord,
-1, 0, 0);
2007-12-11 21:26:59 +00:00
2008-02-11 17:21:41 +00:00
apply(c, Move, a->size, a->value, dst);
2007-12-11 21:26:59 +00:00
2008-02-11 17:21:41 +00:00
a->value = dst;
c->registers[reg].operand = 0;
2007-12-11 21:26:59 +00:00
}
}
2008-02-11 17:21:41 +00:00
MyOperand*
operand(Context* c, unsigned size, Value* value = 0)
{
2008-02-11 17:21:41 +00:00
return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(size, value);
}
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
}
void
2008-02-11 17:21:41 +00:00
push(Context* c, MyOperand* o)
{
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(o)->next = c->state->stack;
c->state->stack = static_cast<MyOperand*>(o);
}
2007-12-11 23:52:28 +00:00
2008-02-11 17:21:41 +00:00
MyOperand*
pop(Context* c)
{
MyOperand* o = c->state->stack;
c->state->stack = o->next;
return o;
}
2007-12-15 01:11:01 +00:00
2008-02-11 17:21:41 +00:00
void
syncStack(Context* c, SyncType type)
{
MyOperand* top = 0;
MyOperand* new_ = 0;
for (MyOperand* old = c->state->stack; old; old = old->next) {
MyOperand* n = operand(c, old->size, 0);
if (new_) {
new_->next = n;
2007-12-15 01:11:01 +00:00
} else {
2008-02-11 17:21:41 +00:00
top = n;
2007-12-15 01:11:01 +00:00
}
2008-02-11 17:21:41 +00:00
new_ = n;
new_->index = old->index;
2008-02-11 17:21:41 +00:00
if (type == SyncForCall) {
appendSyncForCall(c, old, new_);
} else {
appendSyncForJump(c, old, new_);
}
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
2008-02-11 17:21:41 +00:00
c->state->stack = top;
}
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-02-11 17:21:41 +00:00
MyOperand* new_ = 0;
for (MyOperand* old = i->firstEvent->stack; old; old = old->next) {
MyOperand* n = operand(c, old->size, 0);
if (new_) new_->next = n;
new_ = n;
new_->index = old->index;
2008-02-11 17:21:41 +00:00
if (old->event) {
old->event->replace(c, old, new_);
}
2008-02-11 17:21:41 +00:00
p->lastEvent = p->lastEvent->next = new
(c->zone->allocate(sizeof(SyncForJumpEvent)))
SyncForJumpEvent(p->lastEvent->next, old, new_);
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-02-11 17:21:41 +00:00
void
compile(Context* c)
{
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
fprintf(stderr, "compile ip %d\n", i);
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
fprintf(stderr, "compile ip %d event\n", i);
e->compile(c);
if (e == c->logicalCode[i].lastEvent) break;
}
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
}
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)
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() {
::pushState(&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) {
c.logicalCode[c.logicalIp].lastEvent = c.event;
}
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(new (c.zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(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(new (c.zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* constant8(int64_t value) {
return promiseConstant8(new (c.zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value));
}
2008-02-11 17:21:41 +00:00
virtual Operand* promiseConstant(Promise* value) {
return operand(&c, BytesPerWord, ::constant(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* promiseConstant8(Promise* value) {
return operand(&c, 8, ::constant(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* address(Promise* address) {
return operand(&c, BytesPerWord, ::address(&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,
TraceHandler* traceHandler = 0)
{
return operand
(&c, BytesPerWord, ::memory
(&c, static_cast<MyOperand*>(base), displacement,
static_cast<MyOperand*>(index), scale, traceHandler));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* stack() {
return operand(&c, BytesPerWord, register_(&c, c.assembler->stack()));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* base() {
return operand(&c, BytesPerWord, register_(&c, c.assembler->base()));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* thread() {
return operand(&c, BytesPerWord, register_(&c, c.assembler->thread()));
2007-12-08 23:22:13 +00:00
}
virtual Operand* label() {
2008-02-11 17:21:41 +00:00
return operand(&c, BytesPerWord, ::constant(&c, static_cast<Promise*>(0)));
2007-12-08 23:22:13 +00:00
}
Promise* machineIp() {
2008-02-11 17:21:41 +00:00
return c.event->promises = new (c.zone->allocate(sizeof(CodePromise)))
CodePromise(&c, c.event->promises);
}
2007-12-08 23:22:13 +00:00
virtual void mark(Operand* label) {
2008-02-11 17:21:41 +00:00
static_cast<ConstantValue*>(static_cast<MyOperand*>(label)->value)->value
= machineIp();
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void push(Operand* value) {
::push(&c, static_cast<MyOperand*>(value));
2007-12-22 00:26:55 +00:00
}
2007-12-09 22:45:43 +00:00
2008-02-11 17:21:41 +00:00
virtual Operand* pop() {
return ::pop(&c);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void push(unsigned count) {
for (unsigned i = 0; i < count; ++i) ::push(&c, 0);
}
2008-02-11 17:21:41 +00:00
virtual void pop(unsigned count) {
for (unsigned i = 0; i < count; ++i) ::pop(&c);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* peek(unsigned index) {
MyOperand* a = c.state->stack;
for (; index; --index) a = a->next;
return a;
}
2008-02-11 17:21:41 +00:00
virtual Operand* call(Operand* address,
void* indirection,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
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;
for (unsigned i = 0; i < argumentCount; ++i) {
MyOperand* o = va_arg(a, MyOperand*);
footprint += o->size;
appendArgument(&c, o, i);
}
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
va_end(a);
2008-02-11 17:21:41 +00:00
syncStack(&c, SyncForCall);
2008-02-11 17:21:41 +00:00
unsigned stackOffset = c.stackOffset + c.state->stack->index
+ (footprint > c.assembler->argumentRegisterCount() ?
footprint - c.assembler->argumentRegisterCount() : 0);
2008-02-11 17:21:41 +00:00
MyOperand* result = operand(&c, resultSize, 0);
appendCall(&c, static_cast<MyOperand*>(address), indirection, flags,
traceHandler, result, stackOffset);
return result;
}
2008-02-11 17:21:41 +00:00
virtual void return_(Operand* value) {
appendReturn(&c, static_cast<MyOperand*>(value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void store(Operand* src, Operand* dst) {
appendMove(&c, Move, static_cast<MyOperand*>(src),
static_cast<MyOperand*>(dst));
}
2008-02-11 17:21:41 +00:00
virtual void store1(Operand* src, Operand* dst) {
appendMove(&c, Move1, static_cast<MyOperand*>(src),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(dst));
}
2008-02-11 17:21:41 +00:00
virtual void store2(Operand* src, Operand* dst) {
appendMove(&c, Move2, static_cast<MyOperand*>(src),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void store4(Operand* src, Operand* dst) {
appendMove(&c, Move4, static_cast<MyOperand*>(src),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void store8(Operand* src, Operand* dst) {
appendMove(&c, Move8, static_cast<MyOperand*>(src),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* load(Operand* src) {
MyOperand* dst = operand(&c, BytesPerWord);
appendMove(&c, Move, static_cast<MyOperand*>(src), dst);
return dst;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* load1(Operand* src) {
MyOperand* dst = operand(&c, BytesPerWord);
appendMove(&c, Move1ToW, static_cast<MyOperand*>(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* load2(Operand* src) {
MyOperand* dst = operand(&c, BytesPerWord);
appendMove(&c, Move2ToW, static_cast<MyOperand*>(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* load2z(Operand* src) {
MyOperand* dst = operand(&c, BytesPerWord);
appendMove(&c, Move2zToW, static_cast<MyOperand*>(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* load4(Operand* src) {
if (BytesPerWord == 4) {
return load(src);
} else {
return load4To8(src);
}
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* load8(Operand* src) {
MyOperand* dst = operand(&c, 8);
appendMove(&c, Move8, static_cast<MyOperand*>(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) {
MyOperand* dst = operand(&c, 8);
appendMove(&c, Move4To8, static_cast<MyOperand*>(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 void cmp(Operand* a, Operand* b) {
appendCompare(&c, static_cast<MyOperand*>(a), static_cast<MyOperand*>(b));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jl(Operand* address) {
syncStack(&c, SyncForJump);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
appendBranch(&c, JumpIfLess, static_cast<MyOperand*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jg(Operand* address) {
syncStack(&c, SyncForJump);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
appendBranch(&c, JumpIfGreater, static_cast<MyOperand*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jle(Operand* address) {
syncStack(&c, SyncForJump);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
appendBranch(&c, JumpIfLessOrEqual, static_cast<MyOperand*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jge(Operand* address) {
syncStack(&c, SyncForJump);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
appendBranch(&c, JumpIfGreaterOrEqual, static_cast<MyOperand*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void je(Operand* address) {
syncStack(&c, SyncForJump);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
appendBranch(&c, JumpIfEqual, static_cast<MyOperand*>(address));
}
2008-02-11 17:21:41 +00:00
virtual void jne(Operand* address) {
syncStack(&c, SyncForJump);
2008-02-11 17:21:41 +00:00
appendBranch(&c, JumpIfNotEqual, static_cast<MyOperand*>(address));
}
2008-02-11 17:21:41 +00:00
virtual void jmp(Operand* address) {
syncStack(&c, SyncForJump);
2007-12-09 22:45:43 +00:00
2008-02-11 17:21:41 +00:00
appendJump(&c, static_cast<MyOperand*>(address));
2007-12-09 22:45:43 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* add(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Add, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
2007-12-09 22:45:43 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* sub(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Subtract, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
}
2008-02-11 17:21:41 +00:00
virtual Operand* mul(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Multiply, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* div(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Divide, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
2007-12-22 00:26:55 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* rem(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Remainder, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
}
2008-02-11 17:21:41 +00:00
virtual Operand* shl(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, ShiftLeft, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
}
2008-02-11 17:21:41 +00:00
virtual Operand* shr(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, ShiftRight, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
}
2008-02-11 17:21:41 +00:00
virtual Operand* ushr(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, UnsignedShiftRight, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* and_(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, And, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* or_(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Or, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
}
2008-02-11 17:21:41 +00:00
virtual Operand* xor_(Operand* a, Operand* b) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendCombine(&c, Xor, static_cast<MyOperand*>(a),
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* neg(Operand* a) {
MyOperand* result = operand(&c, static_cast<MyOperand*>(a)->size);
appendTranslate(&c, Negate, static_cast<MyOperand*>(a), result);
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() {
2008-02-11 17:21:41 +00:00
return c.constantCount;
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 + c.assembler->length() + (i++))
= 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;
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