corda/src/compiler.cpp

1751 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 MyOperand;
class ConstantValue;
class AddressValue;
class RegisterValue;
class MemoryValue;
class StackValue;
2008-02-11 17:21:41 +00:00
class Event;
class PushEvent;
class Stack;
2007-12-09 22:45:43 +00:00
2008-02-11 17:21:41 +00:00
class Value {
public:
virtual ~Value() { }
virtual OperandType type(Context*) = 0;
virtual bool equals(Context*, Value*) { return false; }
2007-12-11 21:26:59 +00:00
virtual void preserve(Context*, Stack*, MyOperand*) { }
virtual void acquire(Context*, Stack*, MyOperand*) { }
2008-02-11 17:21:41 +00:00
virtual void release(Context*, MyOperand*) { }
virtual RegisterValue* toRegister(Context*) = 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:
MyOperand(Value* value):
event(0), value(value), target(0), push(0), pushedValue(0)
2007-12-16 00:24:15 +00:00
{ }
2008-02-11 17:21:41 +00:00
Event* event;
Value* value;
Value* target;
PushEvent* push;
StackValue* pushedValue;
};
class Stack {
public:
Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next):
operand(operand), size(size), index(index), next(next)
{ }
MyOperand* operand;
unsigned size;
2008-02-11 17:21:41 +00:00
unsigned index;
Stack* 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)
{ }
Stack* stack;
2008-02-11 17:21:41 +00:00
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 + pad(c->assembler->length()) + (key * BytesPerWord));
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
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
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
virtual OperandType type(Context*) { return Constant; }
virtual RegisterValue* toRegister(Context* c);
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
virtual OperandType type(Context*) { return Address; }
virtual RegisterValue* toRegister(Context* c);
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);
}
void preserve(Context*, Stack*, int, MyOperand*);
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
virtual OperandType type(Context*) { return Register; }
virtual bool equals(Context* c, Value* o) {
return this == o or
(o->type(c) == Register
and static_cast<RegisterValue*>(o)->register_.low == register_.low
and static_cast<RegisterValue*>(o)->register_.high == register_.high);
2007-12-11 21:26:59 +00:00
}
virtual void preserve(Context* c, Stack* s, MyOperand* a) {
::preserve(c, s, register_.low, a);
if (register_.high >= 0) ::preserve(c, s, register_.high, a);
}
virtual void acquire(Context* c, Stack* s, MyOperand* a) {
if (a != c->registers[register_.low].operand) {
fprintf(stderr, "%p acquire %d\n", a, register_.low);
preserve(c, s, a);
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) {
if (a == c->registers[register_.low].operand) {
fprintf(stderr, "%p release %d\n", a, register_.low);
2007-12-09 20:03:21 +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
}
virtual RegisterValue* toRegister(Context*) {
2008-02-11 17:21:41 +00:00
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)
{ }
virtual OperandType type(Context*) { return Memory; }
virtual bool equals(Context* c, Value* o) {
return this == o or
(o->type(c) == Memory
and static_cast<MemoryValue*>(o)->value.base == value.base
and static_cast<MemoryValue*>(o)->value.offset == value.offset
and static_cast<MemoryValue*>(o)->value.index == value.index
and static_cast<MemoryValue*>(o)->value.scale == value.scale);
}
virtual RegisterValue* toRegister(Context* c) {
RegisterValue* v = freeRegister(c, BytesPerWord);
apply(c, Move, BytesPerWord, this, v);
2008-02-11 17:21:41 +00:00
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)
{
return a->value->toRegister(c)->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 StackValue: public Value {
public:
StackValue(Stack* stack): stack(stack) { }
virtual OperandType type(Context* c) { abort(c); }
virtual RegisterValue* toRegister(Context* c) {
return MemoryValue
(c->assembler->base(), (c->stackOffset + stack->index) * BytesPerWord,
NoRegister, 0, 0)
.toRegister(c);
}
virtual void asAssemblerOperand(Context* c,
OperandType*,
Assembler::Operand**)
{
abort(c);
}
Stack* stack;
};
StackValue*
stackValue(Context* c, Stack* stack)
{
return new (c->zone->allocate(sizeof(StackValue))) StackValue(stack);
}
2008-02-11 17:21:41 +00:00
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 compile(Context* c) = 0;
virtual bool isCritical(Context*) { return false; }
2008-02-11 17:21:41 +00:00
Event* next;
Stack* stack;
2008-02-11 17:21:41 +00:00
CodePromise* promises;
};
2008-02-11 17:21:41 +00:00
class ArgumentEvent: public Event {
public:
ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index):
Event(c), size(size), a(a), index(index)
{
assert(c, a->event == 0);
a->event = this;
}
virtual Value* target(Context* c, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
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(),
2008-02-17 22:29:04 +00:00
-(index + ((c->stackOffset + 1) * BytesPerWord)),
2008-02-11 17:21:41 +00:00
NoRegister, 0, 0);
2007-12-16 00:24:15 +00:00
}
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "ArgumentEvent.compile\n");
if (a->target == 0) a->target = target(c, a);
2008-02-11 17:21:41 +00:00
a->value->release(c, a);
a->target->preserve(c, stack, a);
2007-12-16 00:24:15 +00:00
if (not a->target->equals(c, a->value)) {
apply(c, Move, size, a->value, a->target);
2007-12-16 00:24:15 +00:00
}
}
unsigned size;
2008-02-11 17:21:41 +00:00
MyOperand* a;
unsigned index;
2007-12-16 00:24:15 +00:00
};
void
appendArgument(Context* c, unsigned size, MyOperand* value, unsigned index)
{
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(ArgumentEvent)))
ArgumentEvent(c, size, value, index);
}
2008-02-11 17:21:41 +00:00
class ReturnEvent: public Event {
public:
ReturnEvent(Context* c, unsigned size, MyOperand* a):
Event(c), size(size), a(a)
{
if (a) {
assert(c, a->event == 0);
a->event = this;
}
}
2007-12-16 00:24:15 +00:00
virtual Value* target(Context* c, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
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 compile(Context* c) {
fprintf(stderr, "ReturnEvent.compile\n");
if (a) {
if (a->target == 0) a->target = target(c, a);
a->value->release(c, a);
if (not a->target->equals(c, a->value)) {
apply(c, Move, size, a->value, a->target);
}
2008-02-11 17:21:41 +00:00
}
Assembler::Register base(c->assembler->base());
Assembler::Register stack(c->assembler->stack());
c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack);
c->assembler->apply(Pop, BytesPerWord, Register, &base);
2008-02-11 17:21:41 +00:00
c->assembler->apply(Return);
}
unsigned size;
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, unsigned size, MyOperand* value)
{
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
}
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):
2008-02-11 17:21:41 +00:00
Event(c),
address(address),
indirection(indirection),
flags(flags),
traceHandler(traceHandler),
result(result)
{
assert(c, address->event == 0);
address->event = this;
}
virtual Value* target(Context* c, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
assert(c, v == address);
2007-12-15 01:11:01 +00:00
2008-02-11 17:21:41 +00:00
if (indirection) {
2008-02-17 22:29:04 +00:00
return register_(c, c->assembler->returnLow(), NoRegister);
} 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 compile(Context* c) {
fprintf(stderr, "CallEvent.compile\n");
if (indirection and address->target == 0) {
address->target = target(c, address);
}
2008-02-11 17:21:41 +00:00
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, stack, result);
}
2007-12-16 00:24:15 +00:00
2008-02-17 22:29:04 +00:00
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
2008-02-11 17:21:41 +00:00
if (indirection) {
if (not address->target->equals(c, address->value)) {
apply(c, Move, BytesPerWord, address->value, address->target);
2007-12-16 00:24:15 +00:00
}
2008-02-17 22:29:04 +00:00
apply(c, type, BytesPerWord,
2008-02-11 17:21:41 +00:00
constant(c, reinterpret_cast<intptr_t>(indirection)));
} else {
2008-02-17 22:29:04 +00:00
apply(c, type, BytesPerWord, address->value);
}
if (traceHandler) {
traceHandler->handleTrace
(new (c->zone->allocate(sizeof(CodePromise)))
CodePromise(c, c->assembler->length()));
}
}
2008-02-11 17:21:41 +00:00
MyOperand* address;
void* indirection;
unsigned flags;
TraceHandler* traceHandler;
MyOperand* result;
};
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)
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);
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
{
for (int i = c->assembler->registerCount(); i >= 0; --i) {
2008-02-11 17:21:41 +00:00
if ((not c->registers[i].reserved)
and c->registers[i].operand == 0)
{
return i;
}
}
for (int i = c->assembler->registerCount(); i >= 0; --i) {
2008-02-11 17:21:41 +00:00
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));
}
}
void
syncStack(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];
s->operand->value->release(c, s->operand);
apply(c, Push, s->size * BytesPerWord, s->operand->value);
s->operand->pushedValue = stackValue(c, s);
}
}
void
syncStack(Context* c, Stack* start)
{
unsigned count = 0;
for (Stack* s = start; s and s->operand->pushedValue == 0; s = s->next) {
++ count;
}
syncStack(c, start, count);
}
class PushEvent: public Event {
public:
PushEvent(Context* c):
Event(c), active(false)
{
assert(c, stack->operand->push == 0);
stack->operand->push = this;
}
virtual Value* target(Context*, MyOperand*) {
return 0;
}
virtual void compile(Context* c) {
fprintf(stderr, "PushEvent.compile\n");
if (active) {
fprintf(stderr, "PushEvent.compile: active\n");
syncStack(c, stack);
}
}
void markStack() {
active = true;
}
bool active;
};
void
appendPush(Context* c)
{
new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c);
}
class PopEvent: public Event {
public:
PopEvent(Context* c):
Event(c)
{ }
virtual Value* target(Context* c, MyOperand*) {
abort(c);
}
virtual void compile(Context* c) {
fprintf(stderr, "PopEvent.compile\n");
MyOperand* dst = stack->operand;
if (dst->event and dst->pushedValue) {
Value* target = dst->target;
if (target == 0) {
if (dst->event) {
target = dst->event->target(c, dst);
}
if (target == 0) {
target = freeRegister(c, BytesPerWord * stack->size);
}
}
target->acquire(c, 0, dst);
apply(c, Pop, BytesPerWord * stack->size, target);
dst->value = target;
}
}
};
void
appendPop(Context* c)
{
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c);
}
bool
safeToSkipMove(Context* c, MyOperand* a, Event* e)
{
for (; a->push and a->push != e; e = e->next) {
if (e->isCritical(c)) return false;
}
return true;
}
2008-02-11 17:21:41 +00:00
class MoveEvent: public Event {
public:
MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src,
MyOperand* dst):
Event(c), type(type), size(size), src(src), dst(dst)
{
assert(c, src->event == 0);
src->event = this;
}
virtual Value* target(Context* c, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
assert(c, v == src);
if (dst->value) {
return dst->value;
} else if (dst->event) {
return dst->event->target(c, dst);
} else {
return 0;
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "MoveEvent.compile\n");
if (src->target == 0) src->target = target(c, src);
2008-02-11 17:21:41 +00:00
if (src->target == 0) {
2008-03-10 13:29:42 +00:00
if (type == Move
and size == BytesPerWord
and safeToSkipMove(c, dst, next))
2008-03-10 13:29:42 +00:00
{
dst->value = src->value;
return;
} else {
src->target = freeRegister(c, size);
}
} else if (type == Move
and size == BytesPerWord
and src->target->equals(c, src->value))
{
2008-03-10 13:29:42 +00:00
dst->value = src->value;
return;
} else if ((src->value->type(c) == Address
or src->value->type(c) == Memory)
and src->target->type(c) == Memory)
{
RegisterValue* tmp = freeRegister(c, size);
tmp->preserve(c, stack, 0);
apply(c, Move, size, src->value, tmp);
src->value = tmp;
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, stack, dst);
apply(c, type, size, src->value, src->target);
2008-02-11 17:21:41 +00:00
dst->value = src->target;
}
virtual bool isCritical(Context* c) {
if (src->target == 0) src->target = target(c, src);
return src->target != 0;
}
2008-02-11 17:21:41 +00:00
BinaryOperation type;
unsigned size;
2008-02-11 17:21:41 +00:00
MyOperand* src;
MyOperand* dst;
};
2008-02-11 17:21:41 +00:00
void
appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src,
MyOperand* dst)
2008-02-11 17:21:41 +00:00
{
new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent(c, type, size, src, dst);
2008-02-11 17:21:41 +00:00
}
class DupEvent: public Event {
public:
DupEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst):
Event(c), size(size), src(src), dst(dst)
{ }
virtual Value* target(Context* c, MyOperand*) {
abort(c);
}
virtual void compile(Context* c) {
fprintf(stderr, "DupEvent.compile\n");
Value* value = src->value;
assert(c, dst->value == 0);
Value* target = 0;
if (safeToSkipMove(c, dst, next)) {
dst->value = src->value;
return;
}
if (dst->event) {
target = dst->event->target(c, dst);
}
if (target == 0) {
target = freeRegister(c, size);
}
target->acquire(c, stack, dst);
apply(c, Move, size, value, target);
dst->value = target;
}
unsigned size;
MyOperand* src;
MyOperand* dst;
};
void
appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst)
{
new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst);
}
2008-02-11 17:21:41 +00:00
class CompareEvent: public Event {
public:
CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b):
Event(c), size(size), a(a), b(b)
{
assert(c, a->event == 0);
a->event = this;
assert(c, b->event == 0);
b->event = this;
}
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
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 compile(Context* c) {
fprintf(stderr, "CompareEvent.compile\n");
2008-02-11 17:21:41 +00:00
a->value->release(c, a);
b->value->release(c, b);
apply(c, Compare, size, a->value, b->value);
2007-12-11 21:26:59 +00:00
}
unsigned size;
2008-02-11 17:21:41 +00:00
MyOperand* a;
MyOperand* b;
};
2007-12-11 21:26:59 +00:00
void
appendCompare(Context* c, unsigned size, MyOperand* a, MyOperand* b)
2007-12-11 21:26:59 +00:00
{
new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, a, b);
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 BranchEvent: public Event {
public:
BranchEvent(Context* c, UnaryOperation type, MyOperand* address):
Event(c), type(type), address(address)
{
assert(c, address->event == 0);
address->event = this;
}
2007-12-20 01:42:12 +00:00
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
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 compile(Context* c) {
fprintf(stderr, "BranchEvent.compile\n");
2008-02-11 17:21:41 +00:00
address->value->release(c, address);
apply(c, type, BytesPerWord, 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)
{
assert(c, address->event == 0);
address->event = this;
}
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
assert(c, v == address);
2008-02-11 17:21:41 +00:00
return 0;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "JumpEvent.compile\n");
2008-02-11 17:21:41 +00:00
address->value->release(c, address);
apply(c, Jump, BytesPerWord, address->value);
2008-02-11 17:21:41 +00:00
}
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
MyOperand* address;
};
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, unsigned size, MyOperand* a,
MyOperand* b, MyOperand* result):
Event(c), type(type), size(size), a(a), b(b), result(result)
{
assert(c, a->event == 0);
a->event = this;
assert(c, b->event == 0);
b->event = this;
}
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, size, &ar, &br);
2008-02-11 17:21:41 +00:00
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) {
if (result->event) {
Value* v = result->event->target(c, result);
if (v->type(c) == Register) {
return v;
} else {
return 0;
}
} else {
return 0;
}
} 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 compile(Context* c) {
fprintf(stderr, "CombineEvent.compile\n");
if (a->target == 0) a->target = target(c, a);
if (b->target == 0) b->target = target(c, b);
if (b->target == 0) {
b->target = freeRegister(c, BytesPerWord);
}
if (a->target and not a->target->equals(c, a->value)) {
a->value->release(c, a);
apply(c, Move, size, a->value, a->target);
a->value = a->target;
2008-02-11 17:21:41 +00:00
}
if (b->target and not b->target->equals(c, b->value)) {
b->value->release(c, b);
apply(c, Move, size, b->value, b->target);
b->value = b->target;
2008-02-11 17:21:41 +00:00
}
b->value->acquire(c, stack, result);
apply(c, type, 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;
unsigned size;
2008-02-11 17:21:41 +00:00
MyOperand* a;
MyOperand* b;
MyOperand* result;
};
2008-02-11 17:21:41 +00:00
void
appendCombine(Context* c, BinaryOperation type, unsigned size, MyOperand* a,
MyOperand* b, MyOperand* result)
2008-02-11 17:21:41 +00:00
{
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, a, b, result);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
class TranslateEvent: public Event {
public:
TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
2008-02-11 17:21:41 +00:00
MyOperand* result):
Event(c), type(type), size(size), a(a), result(result)
{
assert(c, a->event == 0);
a->event = this;
}
virtual Value* target(Context* c, MyOperand* v UNUSED) {
2008-02-11 17:21:41 +00:00
assert(c, v == a);
Assembler::Register r(NoRegister);
c->assembler->getTargets(type, 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 compile(Context* c) {
fprintf(stderr, "TranslateEvent.compile\n");
if (a->target == 0) a->target = target(c, a);
result->value->acquire(c, stack, result);
if (a->target and not a->target->equals(c, a->value)) {
apply(c, Move, size, a->value, a->target);
}
apply(c, type, 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;
unsigned size;
2008-02-11 17:21:41 +00:00
MyOperand* a;
MyOperand* result;
};
2008-02-11 17:21:41 +00:00
void
appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
2008-02-11 17:21:41 +00:00
MyOperand* result)
{
new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent(c, type, size, a, result);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
RegisterValue*
ConstantValue::toRegister(Context* c)
2008-02-11 17:21:41 +00:00
{
RegisterValue* v = freeRegister(c, BytesPerWord);
apply(c, Move, BytesPerWord, this, v);
2008-02-11 17:21:41 +00:00
return v;
}
2007-12-18 00:22:37 +00:00
2008-02-11 17:21:41 +00:00
RegisterValue*
AddressValue::toRegister(Context* c)
2008-02-11 17:21:41 +00:00
{
RegisterValue* v = freeRegister(c, BytesPerWord);
apply(c, Move, BytesPerWord, this, v);
2008-02-11 17:21:41 +00:00
return v;
2007-12-11 21:26:59 +00:00
}
void
preserve(Context* c, Stack* stack, int reg, MyOperand* a)
2007-12-11 21:26:59 +00:00
{
MyOperand* b = c->registers[reg].operand;
if (b and a != b) {
fprintf(stderr, "%p preserve %d for %p\n", a, reg, b);
2007-12-11 21:26:59 +00:00
unsigned count = 0;
Stack* start = 0;
for (Stack* s = stack; s and s->operand->pushedValue == 0; s = s->next) {
if (s->operand == a) {
start = s;
}
if (start) {
++ count;
}
}
assert(c, start);
2007-12-11 21:26:59 +00:00
syncStack(c, start, count);
2007-12-11 21:26:59 +00:00
}
}
2008-02-11 17:21:41 +00:00
MyOperand*
operand(Context* c, Value* value = 0)
{
return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(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
}
Stack*
stack(Context* c, MyOperand* operand, unsigned size, unsigned index,
Stack* next)
{
return new (c->zone->allocate(sizeof(Stack)))
Stack(operand, size, index, next);
}
2008-02-17 22:29:04 +00:00
Stack*
stack(Context* c, MyOperand* operand, unsigned size, Stack* next)
{
return stack(c, operand, size, (next ? next->index + size : 0), next);
}
void
push(Context* c, unsigned size, MyOperand* o)
{
assert(c, ceiling(size, BytesPerWord));
2008-02-17 22:29:04 +00:00
c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack);
appendPush(c);
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
2008-02-11 17:21:41 +00:00
MyOperand*
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);
appendPop(c);
c->state->stack = s->next;
return s->operand;
2008-02-11 17:21:41 +00:00
}
2007-12-15 01:11:01 +00:00
void
markStack(Context*, Stack* stack)
{
for (Stack* s = stack; s; s = s->next) {
if (s->operand->push) {
s->operand->push->markStack();
}
}
}
void
markStack(Context* c)
{
markStack(c, c->state->stack);
}
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;
markStack(c, p->lastEvent->stack);
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)
{
Assembler* a = c->assembler;
Assembler::Register base(a->base());
Assembler::Register stack(a->stack());
a->apply(Push, BytesPerWord, Register, &base);
a->apply(Move, BytesPerWord, Register, &stack, Register, &base);
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) {
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* promiseConstant(Promise* value) {
return operand(&c, ::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, ::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, ::memory
2008-02-11 17:21:41 +00:00
(&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, 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, 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, register_(&c, c.assembler->thread()));
2007-12-08 23:22:13 +00:00
}
virtual Operand* label() {
return operand(&c, ::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
}
virtual void push(unsigned size, Operand* value) {
::push(&c, size, static_cast<MyOperand*>(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) {
for (unsigned i = 0; i < count; ++i) ::push(&c, BytesPerWord, operand(&c));
}
virtual void popped(unsigned count) {
for (unsigned i = count; i > 0;) {
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));
return s->operand;
}
2008-02-11 17:21:41 +00:00
virtual Operand* call(Operand* address,
void* indirection,
unsigned flags,
TraceHandler* traceHandler,
unsigned,
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-02-11 17:21:41 +00:00
for (unsigned i = 0; i < argumentCount; ++i) {
MyOperand* o = va_arg(a, MyOperand*);
if (o) {
appendArgument(&c, size, o, footprint);
size = BytesPerWord;
} else {
size = 8;
}
++ footprint;
}
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
va_end(a);
markStack(&c);
MyOperand* result = operand(&c);
2008-02-11 17:21:41 +00:00
appendCall(&c, static_cast<MyOperand*>(address), indirection, flags,
traceHandler, result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual void return_(unsigned size, Operand* value) {
appendReturn(&c, size, static_cast<MyOperand*>(value));
}
virtual void store(unsigned size, Operand* src, Operand* dst) {
appendMove(&c, Move, size, static_cast<MyOperand*>(src),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(dst));
}
virtual Operand* load(unsigned size, Operand* src) {
MyOperand* dst = operand(&c);
appendMove(&c, Move, size, static_cast<MyOperand*>(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) {
MyOperand* dst = operand(&c);
appendMove(&c, MoveZ, size, 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);
appendMove(&c, Move4To8, 0, static_cast<MyOperand*>(src), dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
virtual Operand* dup(unsigned size, Operand* src) {
MyOperand* dst = operand(&c);
appendDup(&c, size, static_cast<MyOperand*>(src), dst);
return dst;
}
virtual void cmp(unsigned size, Operand* a, Operand* b) {
appendCompare(&c, size, 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) {
markStack(&c);
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) {
markStack(&c);
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) {
markStack(&c);
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) {
markStack(&c);
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) {
markStack(&c);
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) {
markStack(&c);
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) {
markStack(&c);
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
}
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Add, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
2007-12-09 22:45:43 +00:00
}
virtual Operand* sub(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Subtract, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
}
virtual Operand* mul(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Multiply, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* div(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Divide, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
2007-12-22 00:26:55 +00:00
}
virtual Operand* rem(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Remainder, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
}
virtual Operand* shl(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, ShiftLeft, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
}
virtual Operand* shr(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, ShiftRight, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
}
virtual Operand* ushr(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, UnsignedShiftRight, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* and_(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, And, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* or_(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Or, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
}
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) {
MyOperand* result = operand(&c);
appendCombine(&c, Xor, size, static_cast<MyOperand*>(a),
2008-02-11 17:21:41 +00:00
static_cast<MyOperand*>(b), result);
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* neg(unsigned size, Operand* a) {
MyOperand* result = operand(&c);
appendTranslate(&c, Negate, size, static_cast<MyOperand*>(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;
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