mirror of
https://github.com/corda/corda.git
synced 2025-02-05 02:29:20 +00:00
rough sketch of refined compiler design
This commit is contained in:
parent
a51c4cef39
commit
b7ea937708
419
src/compiler.cpp
419
src/compiler.cpp
@ -16,53 +16,390 @@ using namespace vm;
|
||||
namespace {
|
||||
|
||||
class Context;
|
||||
class MyOperand;
|
||||
class ConstantValue;
|
||||
class AddressValue;
|
||||
class RegisterValue;
|
||||
class MemoryValue;
|
||||
class StackValue;
|
||||
class Event;
|
||||
class PushEvent;
|
||||
class Stack;
|
||||
|
||||
void NO_RETURN abort(Context* c);
|
||||
|
||||
class Value {
|
||||
// scratch
|
||||
|
||||
class Value: public Compiler::Operand {
|
||||
public:
|
||||
virtual ~Value() { }
|
||||
|
||||
virtual OperandType type(Context*) = 0;
|
||||
|
||||
virtual bool equals(Context*, Value*) { return false; }
|
||||
|
||||
virtual void preserve(Context*, Stack*, MyOperand*) { }
|
||||
virtual void acquire(Context*, Stack*, MyOperand*) { }
|
||||
virtual void release(Context*, MyOperand*) { }
|
||||
|
||||
virtual bool ready(Context*) { return true; }
|
||||
|
||||
virtual int registerValue(Context*) { return NoRegister; }
|
||||
virtual int64_t constantValue(Context* c) { abort(c); }
|
||||
|
||||
virtual void asAssemblerOperand(Context*,
|
||||
OperandType* type,
|
||||
Assembler::Operand** operand) = 0;
|
||||
};
|
||||
|
||||
class MyOperand: public Compiler::Operand {
|
||||
public:
|
||||
MyOperand(Value* value):
|
||||
event(0), value(value), target(0), push(0), pushed(false)
|
||||
Value(Site* site):
|
||||
reads(0), sites(site), source(0), target(0)
|
||||
{ }
|
||||
|
||||
Event* event;
|
||||
Value* value;
|
||||
Value* target;
|
||||
PushEvent* push;
|
||||
bool pushed;
|
||||
Read* reads;
|
||||
Site* sites;
|
||||
Site* source;
|
||||
Site* target;
|
||||
};
|
||||
|
||||
class Event {
|
||||
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;
|
||||
}
|
||||
|
||||
c->event = this;
|
||||
}
|
||||
|
||||
virtual ~Event() { }
|
||||
|
||||
virtual void compile(Context* c) = 0;
|
||||
|
||||
Event* next;
|
||||
Stack* stack;
|
||||
CodePromise* promises;
|
||||
};
|
||||
|
||||
class Stack {
|
||||
public:
|
||||
Stack(Value* value, unsigned size, unsigned index, Stack* next):
|
||||
value(value), size(size), index(index), next(next)
|
||||
{ }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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):
|
||||
@ -998,8 +1335,8 @@ class MoveEvent: public Event {
|
||||
return;
|
||||
}
|
||||
} else if (type == Move
|
||||
and (size == BytesPerWord
|
||||
or src->target->type(c) == Memory)
|
||||
and size == BytesPerWord
|
||||
and src->target->type(c) == Register
|
||||
and src->target->equals(c, src->value))
|
||||
{
|
||||
dst->value = src->value;
|
||||
|
Loading…
x
Reference in New Issue
Block a user