corda/src/compiler.cpp

2324 lines
53 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;
2007-12-09 22:45:43 +00:00
2008-03-15 23:54:20 +00:00
void NO_RETURN abort(Context* c);
// scratch
class Value: public Compiler::Operand {
public:
Value(Site* site):
reads(0), sites(site), source(0), target(0)
{ }
Read* reads;
Site* sites;
Site* source;
Site* target;
};
class Event {
2008-02-11 17:21:41 +00:00
public:
Event(Context* c): next(0), stack(c->state->stack), promises(0) {
assert(c, c->logicalIp >= 0);
if (c->event) {
c->event->next = this;
}
if (c->logicalCode[c->logicalIp].firstEvent == 0) {
c->logicalCode[c->logicalIp].firstEvent = this;
}
2007-12-11 21:26:59 +00:00
c->event = this;
}
virtual ~Event() { }
2008-03-16 19:38:43 +00:00
virtual void compile(Context* c) = 0;
2007-12-09 20:03:21 +00:00
Event* next;
Stack* stack;
CodePromise* promises;
2008-02-11 17:21:41 +00:00
};
2007-12-09 20:03:21 +00:00
class Stack {
2007-12-16 00:24:15 +00:00
public:
Stack(Value* value, unsigned size, unsigned index, Stack* next):
value(value), size(size), index(index), next(next)
2007-12-16 00:24:15 +00:00
{ }
Value* value;
unsigned size;
unsigned index;
Stack* next;
};
class CallEvent: public Event {
public:
CallEvent(Context* c, Value* address, void* indirection, unsigned flags,
TraceHandler* traceHandler, Value* result, unsigned resultSize,
unsigned argumentCount):
Event(c),
address(address),
indirection(indirection),
flags(flags),
traceHandler(traceHandler),
result(result)
{
addRead(c, address, BytesPerWord,
(indirection ? registerSite(c, c->assembler->returnLow()) : 0));
unsigned index = 0;
Stack* s = stack;
for (unsigned i = 0; i < argumentCount; ++i) {
addRead(c, s->value, s->size * BytesPerWord,
index < c->assembler->argumentRegisterCount() ?
registerSite(c, c->assembler->argumentRegister(index)) :
stackSite(c, s));
index += s->size;
s = s->next;
}
if (result) {
addWrite(c, result, resultSize);
}
}
virtual void compile(Context* c) {
fprintf(stderr, "CallEvent.compile\n");
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
if (indirection) {
apply(c, type, BytesPerWord,
constantSite(c, reinterpret_cast<intptr_t>(indirection)));
} else {
apply(c, type, BytesPerWord, address->source);
}
if (traceHandler) {
traceHandler->handleTrace
(new (c->zone->allocate(sizeof(CodePromise)))
CodePromise(c, c->assembler->length()));
}
}
Value* address;
void* indirection;
unsigned flags;
TraceHandler* traceHandler;
Value* result;
};
void
appendCall(Context* c, Value* address, void* indirection, unsigned flags,
TraceHandler* traceHandler, Value* result, unsigned argumentCount)
{
new (c->zone->allocate(sizeof(CallEvent)))
CallEvent(c, address, indirection, flags, traceHandler, result,
argumentCount);
}
class ReturnEvent: public Event {
public:
ReturnEvent(Context* c, unsigned size, Value* value):
Event(c), value(value)
{
if (value) {
addRead(c, value, size, registerSite
(c, c->assembler->returnLow(),
size > BytesPerWord ?
c->assembler->returnHigh() : NoRegister));
}
}
virtual void compile(Context* c) {
fprintf(stderr, "ReturnEvent.compile\n");
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);
c->assembler->apply(Return);
}
2008-02-11 17:21:41 +00:00
Value* value;
};
void
appendReturn(Context* c, unsigned size, MyOperand* value)
{
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
}
class MoveEvent: public Event {
public:
MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst):
Event(c), type(type), size(size), src(src), dst(dst)
{
addRead(c, src, size, 0);
addWrite(c, dst, size);
}
virtual void compile(Context* c) {
fprintf(stderr, "MoveEvent.compile\n");
apply(c, type, size, src->source, dst->target);
}
BinaryOperation type;
unsigned size;
Value* src;
Value* dst;
};
void
appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst)
{
new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent(c, type, size, src, dst);
}
class CompareEvent: public Event {
public:
CompareEvent(Context* c, unsigned size, Value* first, Value* second):
Event(c), size(size), first(first), second(second)
{
addRead(c, first, size, 0);
addRead(c, second, size, 0);
}
virtual void compile(Context* c) {
fprintf(stderr, "CompareEvent.compile\n");
apply(c, Compare, size, first->source, second->source);
}
unsigned size;
Value* first;
Value* second;
};
void
appendCompare(Context* c, unsigned size, Value* first, Value* second)
{
new (c->zone->allocate(sizeof(CompareEvent)))
CompareEvent(c, size, first, second);
}
class BranchEvent: public Event {
public:
BranchEvent(Context* c, UnaryOperation type, Value* address):
Event(c), type(type), address(address)
{
addRead(c, address, BytesPerWord, 0);
}
virtual void compile(Context* c) {
fprintf(stderr, "BranchEvent.compile\n");
apply(c, type, BytesPerWord, address->source);
}
UnaryOperation type;
Value* address;
};
void
appendBranch(Context* c, UnaryOperation type, Value* address)
{
new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address);
}
class JumpEvent: public Event {
public:
JumpEvent(Context* c, Value* address):
Event(c),
address(address)
{
addRead(c, address, BytesPerWord, 0);
}
virtual void compile(Context* c) {
fprintf(stderr, "JumpEvent.compile\n");
apply(c, Jump, BytesPerWord, address->source);
}
Value* address;
};
void
appendJump(Context* c, Value* address)
{
new (c->zone->allocate(sizeof(JumpEvent))) JumpEvent(c, address);
}
class CombineEvent: public Event {
public:
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result):
Event(c), type(type), size(size), first(first), second(second),
result(result)
{
Assembler::Register r1(NoRegister);
Assembler::Register r2(NoRegister);
c->assembler->getTargets(type, size, &r1, &r2);
addRead(c, first, size,
r1.low == NoRegister ? 0 : registerSite(c, r1.low, r1.high));
addRead(c, second, size,
r2.low == NoRegister ?
valueSite(c, result) : registerSite(c, r2.low, r2.high));
addWrite(c, result, size);
}
virtual void compile(Context* c) {
fprintf(stderr, "CombineEvent.compile\n");
apply(c, type, size, first->source, second->source);
}
BinaryOperation type;
unsigned size;
Value* first;
Value* second;
MyOperand* result;
};
void
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result)
{
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, first, second, result);
}
class TranslateEvent: public Event {
public:
TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result):
Event(c), type(type), size(size), value(value), result(result)
{
addRead(c, value, size, valueSite(c, result));
addWrite(c, result, size);
}
virtual void compile(Context* c) {
fprintf(stderr, "TranslateEvent.compile\n");
apply(c, type, size, value->source);
}
UnaryOperation type;
unsigned size;
Value* value;
Value* result;
};
void
appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result)
{
new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent(c, type, size, value, result);
}
class MemoryEvent: public Event {
public:
MemoryEvent(Context* c, Value* base, Value* index, Value* result):
Event(c), base(base), index(index), result(result)
{
addRead(c, base, BytesPerWord, anyRegisterSite(c));
if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c));
addWrite(c, BytesPerWord, size);
}
virtual void compile(Context*) {
fprintf(stderr, "MemoryEvent.compile\n");
}
Value* base;
Value* index;
Value* result;
};
void
appendMemory(Context* c, Value* base, Value* index, Value* result)
{
new (c->zone->allocate(sizeof(MemoryEvent)))
MemoryEvent(c, base, index, result);
}
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);
if (c->stackOffset) {
Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord));
a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
}
for (Event* e = c->firstEvent; e; e = e->next) {
LogicalInstruction* li = c->logicalCode + e->logicalIp;
li->machineOffset = a->length();
e->compile(c);
for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->length();
}
}
}
// end scratch
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*
2008-03-15 20:24:04 +00:00
freeRegister(Context* c, unsigned size, bool allowAcquired);
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; }
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
virtual int64_t constantValue(Context*) {
return value.value->value();
}
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
}
ResolvedPromise*
resolved(Context* c, int64_t value)
{
return new (c->zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value);
}
2008-02-11 17:21:41 +00:00
ConstantValue*
constant(Context* c, int64_t value)
2007-12-16 21:30:19 +00:00
{
return constant(c, resolved(c, 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; }
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
}
virtual void release(Context* c, MyOperand* a) {
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
}
2008-03-15 23:54:20 +00:00
virtual int registerValue(Context*) {
return register_.low;
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);
}
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
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)
{ }
virtual void preserve(Context* c, Stack* s, MyOperand*) {
base_->value->preserve(c, s, base_);
if (index_) {
index_->value->preserve(c, s, index_);
}
}
virtual void release(Context* c, MyOperand*) {
base_->value->release(c, base_);
if (index_) {
index_->value->release(c, index_);
}
}
2008-03-16 19:38:43 +00:00
virtual bool ready(Context* c) {
return base_->value->registerValue(c) != NoRegister
and (index_ == 0 or index_->value->registerValue(c) != NoRegister);
}
2008-02-11 17:21:41 +00:00
virtual int base(Context* c) {
2008-03-16 19:38:43 +00:00
int r = base_->value->registerValue(c);
assert(c, r != NoRegister);
return r;
}
2008-02-11 17:21:41 +00:00
virtual int index(Context* c) {
2008-03-16 19:38:43 +00:00
if (index_) {
int r = index_->value->registerValue(c);
assert(c, r != NoRegister);
return r;
} else {
return 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:
2008-03-15 23:54:20 +00:00
StackValue(Context* c, Stack* stack):
stack(stack),
value
(c->assembler->base(),
- (c->stackOffset + stack->index + 1) * BytesPerWord,
NoRegister, 0, 0)
{ }
2008-03-15 23:54:20 +00:00
virtual OperandType type(Context*) { return Memory; }
2008-03-15 23:54:20 +00:00
virtual void asAssemblerOperand(Context*,
OperandType* type,
Assembler::Operand** operand)
{
2008-03-15 23:54:20 +00:00
*type = Memory;
*operand = &value;
}
Stack* stack;
2008-03-15 23:54:20 +00:00
Assembler::Memory value;
};
StackValue*
stackValue(Context* c, Stack* stack)
{
2008-03-15 23:54:20 +00:00
return new (c->zone->allocate(sizeof(StackValue))) StackValue(c, 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) {
assert(c, c->logicalIp >= 0);
2008-02-11 17:21:41 +00:00
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;
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context* c) = 0;
2008-02-11 17:21:41 +00:00
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;
};
class NullEvent: public Event {
public:
NullEvent(Context* c):
Event(c)
{ }
virtual Value* target(Context*, MyOperand*) {
return 0;
}
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return 0;
}
virtual void compile(Context*) {
// ignore
}
};
void
setEvent(Context* c, MyOperand* a, Event* e)
{
if (a->event) {
a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c);
} else{
a->event = e;
}
}
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)
{
setEvent(c, a, 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 {
2008-03-15 20:24:04 +00:00
return 0;
2007-12-16 00:24:15 +00:00
}
}
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return size;
}
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-03-15 20:24:04 +00:00
if (a->target == 0) {
apply(c, Push, size, a->value);
a->value = 0;
} else {
if (not a->target->equals(c, a->value)) {
a->target->preserve(c, stack, a);
apply(c, Move, size, a->value, a->target);
}
2008-03-15 20:24:04 +00:00
a->value->release(c, a);
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) {
setEvent(c, a, 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-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return size;
}
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);
if (not a->target->equals(c, a->value)) {
apply(c, Move, size, a->value, a->target);
}
2008-03-15 23:54:20 +00:00
a->value->release(c, a);
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-03-16 19:38:43 +00:00
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];
if (s->operand->value) {
apply(c, Push, s->size * BytesPerWord, s->operand->value);
s->operand->value->release(c, s->operand);
} else {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
c->assembler->apply
(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
}
s->operand->pushed = true;
s->operand->value = stackValue(c, s);
}
}
void
syncStack(Context* c, Stack* start)
{
unsigned count = 0;
for (Stack* s = start; s and (not s->operand->pushed); 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 unsigned operandSize(Context*) {
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(Context*) {
active = true;
}
bool active;
};
void
appendPush(Context* c)
{
new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c);
}
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)
{
setEvent(c, address, 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-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return BytesPerWord;
}
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-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);
}
2008-03-15 20:24:04 +00:00
address->value->release(c, address);
2008-03-16 19:38:43 +00:00
if (result->event or (result->push and result->push->active)) {
2008-03-15 20:24:04 +00:00
result->value = register_
(c, c->assembler->returnLow(), c->assembler->returnHigh());
result->value->acquire(c, stack, result);
}
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
2008-03-15 20:24:04 +00:00
freeRegisterExcept(Context* c, int except, bool allowAcquired)
2007-12-11 21:26:59 +00:00
{
for (int i = c->assembler->registerCount(); i >= 0; --i) {
if (i != except
and (not c->registers[i].reserved)
2008-02-11 17:21:41 +00:00
and c->registers[i].operand == 0)
{
return i;
}
}
2008-03-15 20:24:04 +00:00
if (allowAcquired) {
for (int i = c->assembler->registerCount(); i >= 0; --i) {
if (i != except
and (not c->registers[i].reserved))
{
return i;
}
2008-02-11 17:21:41 +00:00
}
}
2008-02-11 17:21:41 +00:00
abort(c);
2007-12-11 21:26:59 +00:00
}
inline int
2008-03-15 20:24:04 +00:00
freeRegister(Context* c, bool allowAcquired)
{
2008-03-15 20:24:04 +00:00
return freeRegisterExcept(c, NoRegister, allowAcquired);
}
2008-02-11 17:21:41 +00:00
RegisterValue*
2008-03-15 20:24:04 +00:00
freeRegister(Context* c, unsigned size, bool allowAcquired)
{
2008-02-11 17:21:41 +00:00
if (BytesPerWord == 4 and size == 8) {
2008-03-15 20:24:04 +00:00
int low = freeRegister(c, allowAcquired);
return register_(c, low, freeRegisterExcept(c, low, allowAcquired));
2008-02-11 17:21:41 +00:00
} else {
2008-03-15 20:24:04 +00:00
return register_(c, freeRegister(c, allowAcquired));
2008-02-11 17:21:41 +00:00
}
}
class PopEvent: public Event {
public:
2008-03-15 23:54:20 +00:00
PopEvent(Context* c, unsigned count, bool ignore):
Event(c), count(count), ignore(ignore)
{ }
virtual Value* target(Context* c, MyOperand*) {
abort(c);
}
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context* c) {
abort(c);
}
virtual void compile(Context* c) {
fprintf(stderr, "PopEvent.compile\n");
2008-03-15 23:54:20 +00:00
Stack* s = stack;
unsigned ignored = 0;
for (unsigned i = count; i;) {
MyOperand* dst = s->operand;
if (dst->pushed) {
if (dst->event and (not ignore)) {
assert(c, ignored == 0);
2008-03-15 23:54:20 +00:00
Value* target = 0;
if (dst->event->operandSize(c) == BytesPerWord) {
target = dst->event->target(c, dst);
}
2008-03-16 19:38:43 +00:00
if (target == 0 or (not target->ready(c))) {
2008-03-15 23:54:20 +00:00
target = freeRegister(c, BytesPerWord * s->size, false);
}
2008-03-15 23:54:20 +00:00
target->acquire(c, 0, dst);
2008-03-16 19:38:43 +00:00
apply(c, Pop, BytesPerWord * s->size, target);
2008-03-15 23:54:20 +00:00
dst->value = target;
} else {
ignored += s->size;
}
}
i -= s->size;
s = s->next;
}
if (ignored) {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, ignored * BytesPerWord));
c->assembler->apply
(Add, BytesPerWord, Constant, &offset, Register, &stack);
}
}
2008-03-15 23:54:20 +00:00
unsigned count;
bool ignore;
};
void
2008-03-15 23:54:20 +00:00
appendPop(Context* c, unsigned count, bool ignore)
{
2008-03-15 23:54:20 +00:00
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
}
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)
{
setEvent(c, src, 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);
}
2008-03-15 20:24:04 +00:00
return 0;
}
virtual unsigned operandSize(Context*) {
return size;
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 if (type == Move
and size == BytesPerWord
and src->target->type(c) == Register
and src->target->equals(c, src->value))
{
2008-03-10 13:29:42 +00:00
dst->value = src->value;
return;
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
src->value->release(c, src);
2008-03-16 19:38:43 +00:00
if (src->target == 0 or (not src->target->ready(c))) {
src->target = freeRegister(c, size, false);
}
src->target->acquire(c, stack, dst);
2008-03-16 19:38:43 +00:00
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);
}
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context* c) {
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);
}
2008-03-16 19:38:43 +00:00
if (target == 0 or (not target->ready(c))) {
2008-03-15 20:24:04 +00:00
target = freeRegister(c, size, true);
}
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)
{
setEvent(c, a, this);
setEvent(c, b, 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-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return size;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "CompareEvent.compile\n");
2008-03-15 20:24:04 +00:00
apply(c, Compare, size, a->value, b->value);
2008-02-11 17:21:41 +00:00
a->value->release(c, a);
b->value->release(c, b);
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)
{
setEvent(c, address, 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-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return BytesPerWord;
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
fprintf(stderr, "BranchEvent.compile\n");
apply(c, type, BytesPerWord, address->value);
2008-03-15 20:24:04 +00:00
address->value->release(c, address);
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)
{
setEvent(c, address, this);
}
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return BytesPerWord;
}
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");
apply(c, Jump, BytesPerWord, address->value);
2008-03-15 20:24:04 +00:00
address->value->release(c, address);
2008-02-11 17:21:41 +00:00
}
2007-12-16 21:30:19 +00:00
2008-02-11 17:21:41 +00:00
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)
{
setEvent(c, a, this);
setEvent(c, b, this);
}
2007-12-20 01:42:12 +00:00
2008-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return size;
}
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);
2008-03-15 23:54:20 +00:00
if (v and 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);
2008-03-16 19:38:43 +00:00
if (b->target == 0 or (not b->target->ready(c))) {
2008-03-15 20:24:04 +00:00
b->target = freeRegister(c, BytesPerWord, true);
}
if (a->target and not a->target->equals(c, a->value)) {
apply(c, Move, size, a->value, a->target);
2008-03-15 20:24:04 +00:00
a->value->release(c, a);
a->value = a->target;
2008-03-15 20:24:04 +00:00
a->value->acquire(c, stack, a);
2008-02-11 17:21:41 +00:00
}
if (b->target and not b->target->equals(c, b->value)) {
apply(c, Move, size, b->value, b->target);
2008-03-15 20:24:04 +00:00
b->value->release(c, b);
b->value = b->target;
2008-03-15 20:24:04 +00:00
b->value->acquire(c, stack, b);
2008-02-11 17:21:41 +00:00
}
apply(c, type, size, a->value, b->value);
2008-03-15 20:24:04 +00:00
a->value->release(c, a);
b->value->release(c, b);
b->value->acquire(c, stack, result);
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)
{
setEvent(c, a, 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-03-15 20:24:04 +00:00
virtual unsigned operandSize(Context*) {
return size;
}
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-03-16 19:38:43 +00:00
if (not a->target->ready(c)) {
a->target = a->value;
}
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-03-15 23:54:20 +00:00
class MemoryEvent: public Event {
public:
MemoryEvent(Context* c, MyOperand* base, MyOperand* index,
MyOperand* result):
Event(c), base(base), index(index), result(result)
{
setEvent(c, base, this);
if (index) setEvent(c, index, this);
}
2007-12-18 00:22:37 +00:00
2008-03-15 23:54:20 +00:00
virtual unsigned operandSize(Context*) {
return BytesPerWord;
}
virtual Value* target(Context* c, MyOperand* v UNUSED) {
assert(c, v == base or v == index);
return 0;
}
virtual void compile(Context* c) {
fprintf(stderr, "MemoryEvent.compile\n");
if (base->value->type(c) != Register) {
base->target = freeRegister(c, BytesPerWord, true);
apply(c, Move, BytesPerWord, base->value, base->target);
base->value->release(c, base);
base->value = base->target;
}
if (index and index->value->type(c) != Register) {
index->target = freeRegister(c, BytesPerWord, true);
apply(c, Move, BytesPerWord, index->value, index->target);
index->value->release(c, index);
index->value = index->target;
}
}
MyOperand* base;
MyOperand* index;
MyOperand* result;
};
void
appendMemory(Context* c, MyOperand* a, MyOperand* b, MyOperand* result)
2008-02-11 17:21:41 +00:00
{
2008-03-15 23:54:20 +00:00
new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, a, b, result);
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;
2008-03-15 23:54:20 +00:00
for (Stack* s = stack; s and (not s->operand->pushed); s = s->next) {
2008-03-15 20:24:04 +00:00
if (s->operand == b) {
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);
}
2008-03-15 20:24:04 +00:00
unsigned
count(Stack* s)
{
unsigned c = 0;
while (s) {
++ c;
s = s->next;
}
return c;
}
void
2008-02-11 17:21:41 +00:00
pushState(Context* c)
{
2008-02-11 17:21:41 +00:00
c->state = new (c->zone->allocate(sizeof(State)))
State(c->state);
}
2008-02-11 17:21:41 +00:00
void
popState(Context* c)
2007-12-11 23:52:28 +00:00
{
2008-02-11 17:21:41 +00:00
c->state = new (c->zone->allocate(sizeof(State)))
State(c->state->next);
2007-12-11 23:52:28 +00:00
}
Stack*
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);
2008-03-15 23:54:20 +00:00
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);
2008-03-15 23:54:20 +00:00
appendPop(c, s->size, false);
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
2008-03-16 19:38:43 +00:00
markStack(Context* c, Stack* stack)
{
for (Stack* s = stack; s; s = s->next) {
if (s->operand->push) {
2008-03-16 19:38:43 +00:00
s->operand->push->markStack(c);
}
}
}
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);
if (c->stackOffset) {
Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord));
a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
}
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
LogicalInstruction* li = c->logicalCode + i;
li->machineOffset = a->length();
for (Event* e = li->firstEvent; e; e = e->next) {
2008-03-15 20:24:04 +00:00
fprintf(stderr, "compile event at ip %d with stack count %d\n",
i, count(e->stack));
e->compile(c);
for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->length();
}
2008-03-15 23:54:20 +00:00
if (e == li->lastEvent) break;
}
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
}
class Client: public Assembler::Client {
public:
Client(Context* c): c(c) { }
2008-03-15 21:02:19 +00:00
virtual int acquireTemporary(int r) {
if (r == NoRegister) {
r = freeRegisterExcept(c, NoRegister, false);
} else {
expect(c, not c->registers[r].reserved);
expect(c, c->registers[r].operand == 0);
}
c->registers[r].reserved = true;
return r;
}
virtual void releaseTemporary(int r) {
c->registers[r].reserved = false;
}
Context* c;
};
2007-12-08 23:22:13 +00:00
class MyCompiler: public Compiler {
public:
2008-02-11 17:21:41 +00:00
MyCompiler(System* s, Assembler* assembler, Zone* zone):
c(s, assembler, zone), client(&c)
{
assembler->setClient(&client);
}
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
virtual void pushState() {
::pushState(&c);
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void popState() {
2008-03-15 20:24:04 +00:00
::popState(&c);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void init(unsigned logicalCodeLength, unsigned stackOffset) {
c.logicalCodeLength = logicalCodeLength;
c.stackOffset = stackOffset;
c.logicalCode = static_cast<LogicalInstruction*>
(c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength));
memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength);
}
2008-02-11 17:21:41 +00:00
virtual void visitLogicalIp(unsigned logicalIp) {
if ((++ c.logicalCode[logicalIp].visits) == 1) {
c.junctions = new (c.zone->allocate(sizeof(Junction)))
Junction(logicalIp, c.junctions);
}
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void startLogicalIp(unsigned logicalIp) {
if (c.logicalIp >= 0) {
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(resolved(&c, value));
}
2008-02-11 17:21:41 +00:00
virtual Promise* poolAppendPromise(Promise* value) {
Promise* p = new (c.zone->allocate(sizeof(PoolPromise)))
PoolPromise(&c, c.constantCount);
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
ConstantPoolNode* constant
= new (c.zone->allocate(sizeof(ConstantPoolNode)))
ConstantPoolNode(value);
2007-12-16 00:24:15 +00:00
2008-02-11 17:21:41 +00:00
if (c.firstConstant) {
c.lastConstant->next = constant;
} else {
c.firstConstant = constant;
2007-12-16 00:24:15 +00:00
}
2008-02-11 17:21:41 +00:00
c.lastConstant = constant;
++ c.constantCount;
2008-02-11 17:21:41 +00:00
return p;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* constant(int64_t value) {
return promiseConstant(resolved(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* promiseConstant(Promise* value) {
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)
{
2008-03-15 23:54:20 +00:00
MyOperand* result = operand
(&c, ::memory
2008-02-11 17:21:41 +00:00
(&c, static_cast<MyOperand*>(base), displacement,
static_cast<MyOperand*>(index), scale, traceHandler));
2008-03-15 23:54:20 +00:00
appendMemory(&c, static_cast<MyOperand*>(base),
static_cast<MyOperand*>(index), result);
return result;
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 bool isConstant(Operand* a) {
return static_cast<MyOperand*>(a)->value
and static_cast<MyOperand*>(a)->value->type(&c) == Constant;
}
virtual int64_t constantValue(Operand* a) {
assert(&c, isConstant(a));
return static_cast<MyOperand*>(a)->value->constantValue(&c);
}
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-03-15 23:54:20 +00:00
markStack(&c);
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) {
2008-03-15 23:54:20 +00:00
for (unsigned i = 0; i < count; ++i) {
MyOperand* a = operand(&c);
::push(&c, BytesPerWord, a);
a->value = stackValue(&c, c.state->stack);
}
}
virtual void popped(unsigned count) {
2008-03-15 23:54:20 +00:00
appendPop(&c, count, true);
for (unsigned i = count; i;) {
Stack* s = c.state->stack;
c.state->stack = s->next;
i -= s->size;
}
2007-12-08 23:22:13 +00:00
}
virtual Operand* peek(unsigned size UNUSED, unsigned index) {
Stack* s = c.state->stack;
for (unsigned i = index; i > 0;) {
s = s->next;
i -= s->size;
}
assert(&c, s->size == ceiling(size, BytesPerWord));
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;
Client client;
2007-12-08 23:22:13 +00:00
};
} // namespace
namespace vm {
Compiler*
2008-02-11 17:21:41 +00:00
makeCompiler(System* system, Assembler* assembler, Zone* zone)
2007-12-08 23:22:13 +00:00
{
return new (zone->allocate(sizeof(MyCompiler)))
2008-02-11 17:21:41 +00:00
MyCompiler(system, assembler, zone);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
} // namespace vm