corda/src/compiler.cpp

1802 lines
43 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 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() { }
virtual OperandType type() = 0;
2008-02-11 17:21:41 +00:00
virtual bool equals(Value*) { return false; }
2007-12-11 21:26:59 +00:00
virtual void preserve(Context*, MyOperand*) { }
2008-02-11 17:21:41 +00:00
virtual void acquire(Context*, MyOperand*) { }
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)
2007-12-16 00:24:15 +00:00
{ }
2008-02-11 17:21:41 +00:00
Event* event;
Value* value;
Value* target;
};
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);
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() { 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() { 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* c, int reg, MyOperand* a);
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() { return Register; }
virtual bool equals(Value* o) {
return this == o or
(o->type() == 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, MyOperand* a) {
::preserve(c, register_.low, a);
if (register_.high >= 0) ::preserve(c, register_.high, a);
}
2008-02-11 17:21:41 +00:00
virtual void acquire(Context* c, MyOperand* a) {
if (a != c->registers[register_.low].operand) {
fprintf(stderr, "%p acquire %d\n", a, register_.low);
preserve(c, 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() { return Memory; }
virtual bool equals(Value* o) {
return this == o or
(o->type() == 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 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;
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;
}
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(),
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 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) {
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, a);
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, 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
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) {
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(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 SyncForCallEvent: public Event {
public:
SyncForCallEvent(Context* c, unsigned size, unsigned index, MyOperand* src,
MyOperand* dst):
Event(c), size(size), index(index), src(src), dst(dst)
{
assert(c, src->event == 0);
src->event = this;
}
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(),
2008-02-17 22:29:04 +00:00
-(index + ((c->stackOffset + 1) * BytesPerWord)),
2008-02-11 17:21:41 +00:00
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) {
fprintf(stderr, "SyncForCallEvent.compile\n");
if (src->target == 0) src->target = target(c, src);
2008-02-11 17:21:41 +00:00
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)) {
if (src->value->type() == Memory and src->target->type() == Memory) {
RegisterValue* tmp = freeRegister(c, size);
tmp->preserve(c, 0);
apply(c, Move, size, src->value, tmp);
src->value = tmp;
}
apply(c, Move, size, src->value, src->target);
}
dst->value = src->target;
2007-12-09 22:45:43 +00:00
}
unsigned size;
unsigned index;
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
appendSyncForCall(Context* c, unsigned size, unsigned index, 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, size, index, 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, unsigned size, unsigned index, MyOperand* src,
MyOperand* dst):
Event(c), size(size), index(index), src(src), dst(dst)
{
assert(c, src->event == 0);
src->event = this;
}
2007-12-11 00:48:09 +00:00
SyncForJumpEvent(Context* c, Event* next, unsigned size, unsigned index,
MyOperand* src, MyOperand* dst):
Event(next), size(size), index(index), src(src), dst(dst)
{
assert(c, src->event == 0);
src->event = this;
}
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
if (BytesPerWord == 4 and size == 8) {
return register_
(c, c->assembler->stackSyncRegister(index / BytesPerWord),
c->assembler->stackSyncRegister((index / BytesPerWord) + 1));
2008-02-11 17:21:41 +00:00
} else {
return register_
(c, c->assembler->stackSyncRegister(index / BytesPerWord));
2008-02-11 17:21:41 +00:00
}
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) {
fprintf(stderr, "SyncForJumpEvent.compile\n");
if (src->target == 0) src->target = target(c, src);
2008-02-11 17:21:41 +00:00
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, size, src->value, src->target);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
dst->value = src->target;
}
unsigned size;
unsigned index;
2008-02-11 17:21:41 +00:00
MyOperand* src;
MyOperand* dst;
};
2007-12-11 21:26:59 +00:00
void
appendSyncForJump(Context* c, unsigned size, unsigned index, 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, size, index, 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)
{
assert(c, address->event == 0);
address->event = this;
}
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) {
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 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) {
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, result);
}
if (stackOffset != c->stackOffset) {
2008-02-17 22:29:04 +00:00
apply(c, LoadAddress, BytesPerWord,
memory(c, c->assembler->base(),
-((stackOffset + 1) * BytesPerWord),
NoRegister, 0, 0),
register_(c, c->assembler->stack()));
}
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) {
2008-02-17 22:29:04 +00:00
if (not address->target->equals(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;
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
{
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));
}
}
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;
}
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 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 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) {
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) {
src->target = freeRegister(c, size);
} else if (src->value->type() == Memory and src->target->type() == Memory)
{
RegisterValue* tmp = freeRegister(c, size);
tmp->preserve(c, 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, dst);
apply(c, type, 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;
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 replace(Context* c, MyOperand*, MyOperand*) {
abort(c);
}
virtual void compile(Context* c) {
fprintf(stderr, "DupEvent.compile\n");
Value* value = src->value;
Value* target = dst->value;
if (target == 0) {
if (dst->event) {
target = dst->event->target(c, dst);
} else {
target = freeRegister(c, size);
}
} else if (value->type() == Memory and target->type() == Memory) {
RegisterValue* tmp = freeRegister(c, size);
tmp->preserve(c, 0);
apply(c, Move, size, value, tmp);
value = tmp;
}
target->acquire(c, 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;
}
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) {
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
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) {
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;
}
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) {
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;
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, 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() == 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 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) {
fprintf(stderr, "CombineEvent.compile\n");
if (a->target == 0) a->target = target(c, a);
if (b->target == 0) b->target = target(c, b);
2008-02-11 17:21:41 +00:00
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, size, a->value, a->target);
2008-02-11 17:21:41 +00:00
}
if (b->target and not b->target->equals(b->value)) {
apply(c, Move, size, b->value, b->target);
2008-02-11 17:21:41 +00:00
}
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;
}
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, 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) {
fprintf(stderr, "TranslateEvent.compile\n");
if (a->target == 0) a->target = target(c, a);
2008-02-11 17:21:41 +00:00
result->value->acquire(c, result);
if (a->target and not a->target->equals(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, 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
abort(c);
// MemoryValue* dst = memory
// (c, c->assembler->base(), (b->index + c->stackOffset) * BytesPerWord,
// -1, 0, 0);
// apply(c, Move, b->size, b->value, dst);
2007-12-11 21:26:59 +00:00
// b->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, 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));
assert(c, o->event == 0);
2008-02-17 22:29:04 +00:00
c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack);
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);
c->state->stack = s->next;
return s->operand;
2008-02-11 17:21:41 +00:00
}
2007-12-15 01:11:01 +00:00
2008-02-11 17:21:41 +00:00
void
syncStack(Context* c, SyncType type)
{
Stack* newStack = 0;
for (Stack* s = c->state->stack; s; s = s->next) {
MyOperand* old = s->operand;
MyOperand* new_ = operand(c);
Stack* ns = stack(c, new_, s->size, s->index, 0);
if (newStack) {
newStack->next = ns;
2007-12-15 01:11:01 +00:00
} else {
newStack = c->state->stack = ns;
2007-12-15 01:11:01 +00:00
}
2008-02-11 17:21:41 +00:00
if (type == SyncForCall) {
appendSyncForCall
(c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_);
2008-02-11 17:21:41 +00:00
} else {
appendSyncForJump
(c, s->size * BytesPerWord, s->index * BytesPerWord, old, new_);
}
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;
for (Stack* s = c->state->stack; s; s = s->next) {
MyOperand* old = s->operand;
MyOperand* new_ = operand(c);
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
(c, p->lastEvent->next, s->size * BytesPerWord,
s->index * BytesPerWord, 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)
{
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, 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);
2008-02-11 17:21:41 +00:00
syncStack(&c, SyncForCall);
unsigned stackOffset = c.stackOffset
2008-02-17 22:29:04 +00:00
+ (c.state->stack ? c.state->stack->index + c.state->stack->size : 0)
+ (footprint > c.assembler->argumentRegisterCount() ?
footprint - c.assembler->argumentRegisterCount() : 0);
MyOperand* result = operand(&c);
2008-02-11 17:21:41 +00:00
appendCall(&c, static_cast<MyOperand*>(address), indirection, flags,
traceHandler, result, stackOffset);
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) {
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
}
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() {
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 + 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