corda/src/compiler.cpp

1976 lines
41 KiB
C++
Raw Normal View History

2007-12-08 23:22:13 +00:00
#include "compiler.h"
2007-12-09 20:03:21 +00:00
#include "vector.h"
2007-12-11 00:48:09 +00:00
#include "zone.h"
2007-12-08 23:22:13 +00:00
using namespace vm;
namespace {
2007-12-09 22:45:43 +00:00
enum Register {
rax = 0,
rcx = 1,
rdx = 2,
rbx = 3,
rsp = 4,
rbp = 5,
rsi = 6,
rdi = 7,
r8 = 8,
r9 = 9,
r10 = 10,
r11 = 11,
r12 = 12,
r13 = 13,
r14 = 14,
r15 = 15,
};
enum SelectionType {
S1Selection,
S2Selection,
Z2Selection,
S4Selection,
S8Selection
};
const bool Verbose = true;
2007-12-11 21:26:59 +00:00
const unsigned RegisterCount = BytesPerWord * 2;
class Context;
class ImmediateOperand;
2007-12-11 23:52:28 +00:00
class AbsoluteOperand;
2007-12-11 21:26:59 +00:00
class RegisterOperand;
class MemoryOperand;
class StackOperand;
class CodePromise;
class MyPromise;
2007-12-11 21:26:59 +00:00
void NO_RETURN abort(Context*);
#ifndef NDEBUG
void assert(Context*, bool);
#endif // not NDEBUG
2007-12-09 20:03:21 +00:00
2007-12-11 00:48:09 +00:00
inline bool
isInt8(intptr_t v)
2007-12-09 20:03:21 +00:00
{
2007-12-11 00:48:09 +00:00
return v == static_cast<int8_t>(v);
2007-12-09 20:03:21 +00:00
}
2007-12-11 00:48:09 +00:00
inline bool
isInt32(intptr_t v)
2007-12-09 20:03:21 +00:00
{
2007-12-11 00:48:09 +00:00
return v == static_cast<int32_t>(v);
2007-12-09 20:03:21 +00:00
}
class Task {
2007-12-08 23:22:13 +00:00
public:
Task(Task* next): next(next) { }
2007-12-08 23:22:13 +00:00
virtual ~Task() { }
2007-12-11 23:52:28 +00:00
virtual void run(Context*, unsigned) = 0;
Task* next;
2007-12-09 20:03:21 +00:00
};
class Event {
public:
Event(Event* next): next(next), task(0), offset(-1) {
if (next) {
count = next->count + 1;
} else {
count = 1;
}
}
virtual ~Event() { }
2007-12-09 20:03:21 +00:00
virtual void run(Context*) { }
2007-12-11 23:52:28 +00:00
Event* next;
Task* task;
int offset;
unsigned count;
2007-12-11 21:26:59 +00:00
};
2007-12-11 00:48:09 +00:00
class Segment {
2007-12-11 21:26:59 +00:00
public:
Segment(int logicalIp, Event* event):
logicalIp(logicalIp), event(event)
{ }
int logicalIp;
Event* event;
2007-12-11 21:26:59 +00:00
};
2007-12-11 00:48:09 +00:00
2007-12-09 20:03:21 +00:00
class MyOperand: public Operand {
public:
2007-12-11 00:48:09 +00:00
enum Operation {
push,
pop,
call,
alignedCall,
ret,
mov,
cmp,
jl,
jg,
jle,
jge,
je,
jne,
jmp,
add,
sub,
mul,
div,
rem,
shl,
shr,
ushr,
and_,
or_,
xor_,
neg
2007-12-09 20:03:21 +00:00
};
virtual ~MyOperand() { }
virtual unsigned footprint() {
return BytesPerWord;
}
2007-12-11 00:48:09 +00:00
virtual Register asRegister(Context* c) { abort(c); }
2007-12-09 22:45:43 +00:00
2007-12-11 00:48:09 +00:00
virtual void release(Context*) { /* ignore */ }
2007-12-09 20:03:21 +00:00
virtual void setLabelValue(Context* c, CodePromise*) { abort(c); }
2007-12-09 20:03:21 +00:00
virtual void apply(Context*, Operation) = 0;
2007-12-09 20:03:21 +00:00
virtual void apply(Context*, Operation, MyOperand*) = 0;
virtual void apply(Context*, Operation, SelectionType) = 0;
2007-12-09 20:03:21 +00:00
virtual void apply(Context*, Operation, MyOperand*, SelectionType) = 0;
2007-12-09 20:03:21 +00:00
virtual void accept(Context* c, Operation, RegisterOperand*) = 0;
2007-12-09 20:03:21 +00:00
virtual void accept(Context* c, Operation, ImmediateOperand*) = 0;
2007-12-11 23:52:28 +00:00
virtual void accept(Context* c, Operation, AbsoluteOperand*) = 0;
virtual void accept(Context* c, Operation, MemoryOperand*) = 0;
virtual void accept(Context* c, Operation, MemoryOperand*, SelectionType)
= 0;
2007-12-09 20:03:21 +00:00
};
class RegisterOperand: public MyOperand {
public:
RegisterOperand(Register value):
value(value), reserved(false)
2007-12-09 20:03:21 +00:00
{ }
2007-12-11 21:26:59 +00:00
virtual Register asRegister(Context*) {
return value;
}
void acquire(Context* c UNUSED) {
assert(c, not reserved);
// fprintf(stderr, "acquire %d\n", value);
reserved = true;
}
2007-12-11 00:48:09 +00:00
virtual void release(Context* c UNUSED) {
assert(c, reserved);
// fprintf(stderr, "release %d\n", value);
2007-12-11 00:48:09 +00:00
reserved = false;
2007-12-09 20:03:21 +00:00
}
2007-12-11 21:26:59 +00:00
virtual void apply(Context*, Operation);
2007-12-09 20:03:21 +00:00
2007-12-11 00:48:09 +00:00
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this);
2007-12-09 20:03:21 +00:00
}
virtual void apply(Context* c, Operation, SelectionType) { abort(c); }
virtual void apply(Context* c, Operation, MyOperand*, SelectionType)
{ abort(c); }
2007-12-11 21:26:59 +00:00
virtual void accept(Context*, Operation, RegisterOperand*);
virtual void accept(Context*, Operation, ImmediateOperand*);
2007-12-11 23:52:28 +00:00
virtual void accept(Context*, Operation, AbsoluteOperand*);
2007-12-11 21:26:59 +00:00
virtual void accept(Context*, Operation, MemoryOperand*);
virtual void accept(Context*, Operation, MemoryOperand*, SelectionType);
2007-12-11 21:26:59 +00:00
2007-12-09 20:03:21 +00:00
Register value;
2007-12-11 00:48:09 +00:00
bool reserved;
2007-12-08 23:22:13 +00:00
};
2007-12-09 22:45:43 +00:00
class ImmediateOperand: public MyOperand {
public:
ImmediateOperand(intptr_t value):
2007-12-09 22:45:43 +00:00
value(value)
{ }
2007-12-09 20:03:21 +00:00
2007-12-11 21:26:59 +00:00
virtual void apply(Context* c, Operation operation);
2007-12-09 22:45:43 +00:00
virtual void apply(Context* c, Operation, SelectionType) { abort(c); }
2007-12-11 00:48:09 +00:00
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this);
2007-12-09 22:45:43 +00:00
}
virtual void apply(Context* c, Operation, MyOperand*, SelectionType)
{ abort(c); }
virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); }
virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); }
virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*, SelectionType)
{ abort(c); }
intptr_t value;
};
class AddressOperand: public MyOperand {
public:
AddressOperand(MyPromise* promise):
promise(promise)
{ }
virtual void setLabelValue(Context*, CodePromise*);
virtual void apply(Context*, Operation);
virtual void apply(Context* c, Operation, MyOperand*) { abort(c); }
virtual void apply(Context* c, Operation, SelectionType) { abort(c); }
virtual void apply(Context* c, Operation, MyOperand*, SelectionType)
{ abort(c); }
virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); }
virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); }
virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*, SelectionType)
{ abort(c); }
MyPromise* promise;
2007-12-09 22:45:43 +00:00
};
class AbsoluteOperand: public MyOperand {
public:
AbsoluteOperand(MyPromise* promise):
promise(promise)
2007-12-09 22:45:43 +00:00
{ }
virtual void apply(Context*, Operation);
2007-12-11 21:26:59 +00:00
2007-12-11 23:52:28 +00:00
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this);
}
virtual void apply(Context* c, Operation, SelectionType) { abort(c); }
virtual void apply(Context* c, Operation, MyOperand*, SelectionType)
{ abort(c); }
virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); }
virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); }
virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*, SelectionType)
{ abort(c); }
MyPromise* promise;
2007-12-09 22:45:43 +00:00
};
2007-12-09 20:03:21 +00:00
class MemoryOperand: public MyOperand {
public:
MemoryOperand(MyOperand* base, int displacement, MyOperand* index,
unsigned scale):
base(base),
displacement(displacement),
index(index),
scale(scale)
{ }
2007-12-09 20:03:21 +00:00
virtual Register asRegister(Context*);
2007-12-11 21:26:59 +00:00
virtual void apply(Context*, Operation);
2007-12-11 00:48:09 +00:00
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
operand->accept(c, operation, this);
2007-12-09 20:03:21 +00:00
}
virtual void apply(Context* c, Operation, SelectionType);
virtual void apply(Context* c, Operation operation, MyOperand* operand,
SelectionType selection)
{
operand->accept(c, operation, this, selection);
}
2007-12-11 21:26:59 +00:00
virtual void accept(Context*, Operation, RegisterOperand*);
virtual void accept(Context*, Operation, ImmediateOperand*);
virtual void accept(Context*, Operation, AbsoluteOperand*);
2007-12-11 21:26:59 +00:00
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*, SelectionType);
2007-12-09 20:03:21 +00:00
MyOperand* base;
int displacement;
MyOperand* index;
unsigned scale;
};
class SelectionOperand: public MyOperand {
public:
2007-12-09 22:45:43 +00:00
SelectionOperand(SelectionType type, MyOperand* base):
selectionType(type), base(base)
2007-12-09 20:03:21 +00:00
{ }
virtual unsigned footprint() {
2007-12-09 22:45:43 +00:00
if (selectionType == S8Selection) {
2007-12-09 20:03:21 +00:00
return 8;
} else {
return 4;
}
}
virtual void apply(Context* c, Operation operation) {
base->apply(c, operation, selectionType);
}
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
base->apply(c, operation, operand, selectionType);
}
virtual void apply(Context* c, Operation, SelectionType) { abort(c); }
virtual void apply(Context* c, Operation, MyOperand*, SelectionType)
{ abort(c); }
virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); }
virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); }
virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
virtual void accept(Context* c, Operation, MemoryOperand*, SelectionType)
{ abort(c); }
2007-12-11 00:48:09 +00:00
SelectionType selectionType;
MyOperand* base;
};
class WrapperOperand: public MyOperand {
2007-12-11 00:48:09 +00:00
public:
WrapperOperand(MyOperand* base):
base(base)
{ }
2007-12-09 20:03:21 +00:00
virtual unsigned footprint() {
return base->footprint();
2007-12-11 23:52:28 +00:00
}
virtual Register asRegister(Context* c) {
return base->asRegister(c);
}
virtual void apply(Context* c, Operation operation) {
base->apply(c, operation);
}
2007-12-13 00:18:31 +00:00
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
base->apply(c, operation, operand);
}
virtual void apply(Context* c, Operation operation, SelectionType selection)
{
base->apply(c, operation, selection);
}
virtual void apply(Context* c, Operation operation, MyOperand* operand,
SelectionType selection)
{
base->apply(c, operation, operand, selection);
}
2007-12-11 21:26:59 +00:00
virtual void accept(Context* c, Operation operation,
RegisterOperand* operand)
{
base->accept(c, operation, operand);
}
virtual void accept(Context* c, Operation operation,
ImmediateOperand* operand)
{
base->accept(c, operation, operand);
}
virtual void accept(Context* c, Operation operation,
AbsoluteOperand* operand)
{
base->accept(c, operation, operand);
}
virtual void accept(Context* c, Operation operation, MemoryOperand* operand)
{
base->accept(c, operation, operand);
}
virtual void accept(Context* c, Operation operation, MemoryOperand* operand,
SelectionType selection)
{
base->accept(c, operation, operand, selection);
}
2007-12-09 20:03:21 +00:00
MyOperand* base;
};
class StackOperand: public WrapperOperand {
public:
StackOperand(MyOperand* base, int index, StackOperand* next):
WrapperOperand(base), index(index), next(next)
{ }
2007-12-11 00:48:09 +00:00
int index;
StackOperand* next;
2007-12-09 20:03:21 +00:00
};
class TemporaryOperand: public WrapperOperand {
public:
TemporaryOperand(MyOperand* base):
WrapperOperand(base)
{ }
virtual unsigned footprint() {
return BytesPerWord;
}
virtual void release(Context* c) {
base->release(c);
base = 0;
}
};
2007-12-11 00:48:09 +00:00
class Context {
public:
Context(System* s, void* indirectCaller):
s(s),
constantPool(s, BytesPerWord * 32),
plan(s, 1024),
code(s, 1024),
2007-12-11 00:48:09 +00:00
zone(s, 8 * 1024),
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
segmentTable(0),
2007-12-11 00:48:09 +00:00
stack(0),
reserved(0),
codeLength(-1)
2007-12-11 00:48:09 +00:00
{
plan.appendAddress(new (zone.allocate(sizeof(Segment))) Segment
(-1, new (zone.allocate(sizeof(Event))) Event(0)));
2007-12-11 21:26:59 +00:00
for (unsigned i = 0; i < RegisterCount; ++i) {
2007-12-11 00:48:09 +00:00
registers[i] = new (zone.allocate(sizeof(RegisterOperand)))
RegisterOperand(static_cast<Register>(i));
}
registers[rsp]->acquire(this);
registers[rbp]->acquire(this);
registers[rbx]->acquire(this);
2007-12-11 00:48:09 +00:00
}
void dispose() {
zone.dispose();
plan.dispose();
2007-12-11 00:48:09 +00:00
code.dispose();
constantPool.dispose();
if (segmentTable) s->free(segmentTable);
2007-12-11 00:48:09 +00:00
}
System* s;
Vector constantPool;
Vector plan;
Vector code;
2007-12-11 00:48:09 +00:00
Zone zone;
intptr_t indirectCaller;
Segment** segmentTable;
2007-12-11 00:48:09 +00:00
StackOperand* stack;
unsigned reserved;
int codeLength;
2007-12-11 21:26:59 +00:00
RegisterOperand* registers[RegisterCount];
2007-12-11 00:48:09 +00:00
};
inline void NO_RETURN
abort(Context* c)
{
abort(c->s);
}
#ifndef NDEBUG
inline void
assert(Context* c, bool v)
{
assert(c->s, v);
}
#endif // not NDEBUG
inline void
expect(Context* c, bool v)
{
expect(c->s, v);
}
class MyPromise: public Promise {
public:
virtual intptr_t value(Compiler*);
virtual intptr_t value(Context*) = 0;
virtual bool resolved(Context*) = 0;
};
class ResolvedPromise: public MyPromise {
public:
ResolvedPromise(intptr_t value): value_(value) { }
virtual intptr_t value(Context*) {
return value_;
}
virtual bool resolved(Context*) {
return true;
}
intptr_t value_;
};
class PoolPromise: public MyPromise {
public:
PoolPromise(intptr_t key): key(key) { }
virtual intptr_t value(Context* c) {
if (resolved(c)) {
return c->codeLength + key;
}
abort(c);
}
virtual bool resolved(Context* c) {
return c->codeLength >= 0;
}
intptr_t key;
};
class CodePromise: public MyPromise {
public:
CodePromise(bool absolute):
offset(-1), absolute(absolute)
{ }
virtual intptr_t value(Context* c) {
if (resolved(c)) {
if (absolute) {
return reinterpret_cast<intptr_t>(c->code.data + offset);
} else {
return offset;
}
}
abort(c);
}
virtual bool resolved(Context*) {
return offset >= 0;
}
intptr_t offset;
bool absolute;
};
class IpPromise: public MyPromise {
public:
IpPromise(intptr_t logicalIp, bool absolute):
logicalIp(logicalIp), absolute(absolute)
{ }
virtual intptr_t value(Context* c) {
if (resolved(c)) {
unsigned bottom = 0;
unsigned top = c->plan.length() / BytesPerWord;
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
Segment* s = c->segmentTable[middle];
if (logicalIp == s->logicalIp) {
if (absolute) {
return reinterpret_cast<intptr_t>
(c->code.data + s->event->offset);
} else {
return s->event->offset;
}
} else if (logicalIp < s->logicalIp) {
top = middle;
} else if (logicalIp > s->logicalIp) {
bottom = middle + 1;
}
}
}
abort(c);
}
virtual bool resolved(Context* c) {
return c->codeLength >= 0;
}
intptr_t logicalIp;
bool absolute;
};
AddressOperand*
address(Context* c, MyPromise* p)
{
return new (c->zone.allocate(sizeof(AddressOperand))) AddressOperand(p);
}
2007-12-09 20:03:21 +00:00
ImmediateOperand*
immediate(Context* c, intptr_t v)
{
return new (c->zone.allocate(sizeof(ImmediateOperand))) ImmediateOperand(v);
2007-12-09 20:03:21 +00:00
}
AbsoluteOperand*
2007-12-11 00:48:09 +00:00
absolute(Context* c, MyPromise* v)
2007-12-09 20:03:21 +00:00
{
2007-12-11 00:48:09 +00:00
return new (c->zone.allocate(sizeof(AbsoluteOperand))) AbsoluteOperand(v);
2007-12-09 20:03:21 +00:00
}
RegisterOperand*
register_(Context* c, Register v)
{
2007-12-11 00:48:09 +00:00
return c->registers[v];
2007-12-09 20:03:21 +00:00
}
MemoryOperand*
memory(Context* c, MyOperand* base, int displacement,
MyOperand* index, unsigned scale)
{
2007-12-11 00:48:09 +00:00
return new (c->zone.allocate(sizeof(MemoryOperand)))
MemoryOperand(base, displacement, index, scale);
2007-12-09 20:03:21 +00:00
}
MyOperand*
selection(Context* c, SelectionType type, MyOperand* base)
{
if ((type == S4Selection and BytesPerWord == 4)
or (type == S8Selection and BytesPerWord == 8))
{
return base;
} else {
return new (c->zone.allocate(sizeof(SelectionOperand)))
SelectionOperand(type, base);
}
}
Segment*
currentSegment(Context* c)
2007-12-11 21:26:59 +00:00
{
Segment* s; c->plan.get(c->plan.length() - BytesPerWord, &s, BytesPerWord);
return s;
2007-12-11 21:26:59 +00:00
}
2007-12-11 00:48:09 +00:00
RegisterOperand*
temporary(Context* c)
2007-12-11 00:48:09 +00:00
{
2007-12-11 21:26:59 +00:00
// we don't yet support using r9-r15
for (int i = 8/*RegisterCount*/ - 1; i >= 0; --i) {
2007-12-11 00:48:09 +00:00
if (not c->registers[i]->reserved) {
c->registers[i]->acquire(c);
return c->registers[i];
2007-12-11 00:48:09 +00:00
}
}
abort(c);
2007-12-11 00:48:09 +00:00
}
RegisterOperand*
acquire(Context* c, Register v)
{
RegisterOperand* r = register_(c, v);
r->acquire(c);
return r;
}
void
apply(Context* c, MyOperand::Operation op)
{
switch (op) {
case MyOperand::ret:
c->code.append(0xc3);
break;
default: abort(c);
}
}
class OpEvent: public Event {
public:
OpEvent(MyOperand::Operation operation, Event* next):
Event(next), operation(operation)
{ }
virtual void run(Context* c) {
apply(c, operation);
}
MyOperand::Operation operation;
};
class UnaryOpEvent: public Event {
public:
UnaryOpEvent(MyOperand::Operation operation, Operand* operand, Event* next):
Event(next),
operation(operation),
operand(static_cast<MyOperand*>(operand))
{ }
virtual void run(Context* c) {
if (Verbose and c->codeLength >= 0) {
fprintf(stderr, "unary %d\n", operation);
}
operand->apply(c, operation);
}
MyOperand::Operation operation;
MyOperand* operand;
};
class BinaryOpEvent: public Event {
public:
BinaryOpEvent(MyOperand::Operation operation, Operand* a, Operand* b,
Event* next):
Event(next),
operation(operation),
a(static_cast<MyOperand*>(a)),
b(static_cast<MyOperand*>(b))
{ }
virtual void run(Context* c) {
if (Verbose and c->codeLength >= 0) {
fprintf(stderr, "binary %d\n", operation);
}
a->apply(c, operation, b);
}
MyOperand::Operation operation;
MyOperand* a;
MyOperand* b;
};
class AcquireEvent: public Event {
public:
AcquireEvent(TemporaryOperand* operand, Event* next):
Event(next),
operand(operand)
{ }
virtual void run(Context* c) {
if (Verbose and c->codeLength >= 0) {
fprintf(stderr, "acquire\n");
}
operand->base = temporary(c);
}
TemporaryOperand* operand;
};
class ReleaseEvent: public Event {
public:
ReleaseEvent(Operand* operand, Event* next):
Event(next),
operand(static_cast<MyOperand*>(operand))
{ }
virtual void run(Context* c) {
if (Verbose and c->codeLength >= 0) {
fprintf(stderr, "release\n");
}
operand->release(c);
}
MyOperand* operand;
};
void
appendOperation(Context* c, MyOperand::Operation operation)
{
Segment* s = currentSegment(c);
s->event = new (c->zone.allocate(sizeof(OpEvent)))
OpEvent(operation, s->event);
}
void
appendOperation(Context* c, MyOperand::Operation operation, Operand* operand)
{
Segment* s = currentSegment(c);
s->event = new (c->zone.allocate(sizeof(UnaryOpEvent)))
UnaryOpEvent(operation, operand, s->event);
}
void
appendOperation(Context* c, MyOperand::Operation operation, Operand* a, Operand* b)
{
Segment* s = currentSegment(c);
s->event = new (c->zone.allocate(sizeof(BinaryOpEvent)))
BinaryOpEvent(operation, a, b, s->event);
}
void
appendAcquire(Context* c, TemporaryOperand* operand)
{
Segment* s = currentSegment(c);
s->event = new (c->zone.allocate(sizeof(AcquireEvent)))
AcquireEvent(operand, s->event);
}
void
appendRelease(Context* c, Operand* operand)
{
Segment* s = currentSegment(c);
s->event = new (c->zone.allocate(sizeof(ReleaseEvent)))
ReleaseEvent(operand, s->event);
}
2007-12-11 00:48:09 +00:00
StackOperand*
pushed(Context* c)
2007-12-11 00:48:09 +00:00
{
int index = (c->stack ?
c->stack->index + (c->stack->footprint() / BytesPerWord) :
0);
MyOperand* base = memory
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1);
return c->stack = new (c->zone.allocate(sizeof(StackOperand)))
StackOperand(base, index, c->stack);
2007-12-11 00:48:09 +00:00
}
void
push(Context* c, int count)
{
appendOperation
(c, MyOperand::sub, immediate(c, count * BytesPerWord), register_(c, rsp));
2007-12-13 00:18:31 +00:00
while (count) {
-- count;
pushed(c);
}
}
StackOperand*
push(Context* c, MyOperand* v)
{
appendOperation(c, MyOperand::push, v);
return pushed(c);
}
void
pop(Context* c, int count)
{
appendOperation
(c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp));
2007-12-13 00:18:31 +00:00
while (count) {
count -= (c->stack->footprint() / BytesPerWord);
assert(c, count >= 0);
c->stack = c->stack->next;
}
}
2007-12-11 00:48:09 +00:00
void
pop(Context* c, MyOperand* dst)
{
appendOperation(c, MyOperand::pop, dst);
2007-12-11 00:48:09 +00:00
c->stack = c->stack->next;
2007-12-09 20:03:21 +00:00
}
Register
gpRegister(Context* c, unsigned index)
{
switch (index) {
case 0:
return rdi;
case 1:
return rsi;
case 2:
return rdx;
case 3:
return rcx;
case 4:
return r8;
case 5:
return r9;
default:
abort(c);
}
2007-12-09 22:45:43 +00:00
}
unsigned
pushArguments(Context* c, unsigned count, va_list list)
{
MyOperand* arguments[count];
unsigned footprint = 0;
for (unsigned i = 0; i < count; ++i) {
arguments[i] = va_arg(list, MyOperand*);
footprint += pad(arguments[i]->footprint());
}
const int GprCount = 6;
2007-12-09 22:45:43 +00:00
for (int i = count - 1; i >= 0; --i) {
if (BytesPerWord == 8 and i < GprCount) {
appendOperation
(c, MyOperand::mov, arguments[i], register_(c, gpRegister(c, i)));
} else {
appendOperation(c, MyOperand::push, arguments[i]);
}
2007-12-09 22:45:43 +00:00
}
if (BytesPerWord == 8) {
if (footprint > GprCount * BytesPerWord) {
return footprint - GprCount * BytesPerWord;
} else {
return 0;
}
} else {
return footprint;
}
2007-12-09 20:03:21 +00:00
}
2007-12-11 00:48:09 +00:00
void
rex(Context* c)
{
if (BytesPerWord == 8) {
c->code.append(0x48);
}
}
void
encode(Context* c, uint8_t instruction, int a, Register b,
int32_t displacement, int index, unsigned scale)
2007-12-11 00:48:09 +00:00
{
c->code.append(instruction);
uint8_t width;
if (displacement == 0 and b != rbp) {
width = 0;
} else if (isInt8(displacement)) {
width = 0x40;
2007-12-11 00:48:09 +00:00
} else {
width = 0x80;
2007-12-11 00:48:09 +00:00
}
if (index == -1) {
c->code.append(width | (a << 3) | b);
if (b == rsp) {
c->code.append(0x24);
}
} else {
assert(c, b != rsp);
c->code.append(width | (a << 3) | 4);
c->code.append((log(scale) << 6) | (index << 3) | b);
2007-12-11 00:48:09 +00:00
}
if (displacement == 0 and b != rbp) {
2007-12-11 00:48:09 +00:00
// do nothing
} else if (isInt8(displacement)) {
c->code.append(displacement);
2007-12-11 00:48:09 +00:00
} else {
c->code.append4(displacement);
2007-12-11 00:48:09 +00:00
}
}
void
encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex)
{
Register r = b->base->asRegister(c);
int index = b->index ? b->index->asRegister(c) : -1;
if (rex) {
::rex(c);
}
encode(c, instruction, a, r, b->displacement, index, b->scale);
}
2007-12-11 21:26:59 +00:00
void
RegisterOperand::apply(Context* c, Operation operation)
{
switch (operation) {
case call:
c->code.append(0xff);
c->code.append(0xd0 | value);
2007-12-11 21:26:59 +00:00
break;
case jmp:
c->code.append(0xff);
c->code.append(0xe0 | value);
break;
case pop:
c->code.append(0x58 | value);
break;
case push:
c->code.append(0x50 | value);
2007-12-11 21:26:59 +00:00
break;
default: abort(c);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
RegisterOperand* operand)
{
switch (operation) {
case add:
rex(c);
c->code.append(0x01);
c->code.append(0xc0 | (operand->value << 3) | value);
break;
case cmp:
rex(c);
c->code.append(0x39);
c->code.append(0xc0 | (operand->value << 3) | value);
break;
2007-12-11 21:26:59 +00:00
case mov:
if (value != operand->value) {
rex(c);
c->code.append(0x89);
c->code.append(0xc0 | (operand->value << 3) | value);
}
break;
default: abort(c);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
ImmediateOperand* operand)
{
switch (operation) {
case add: {
if (operand->value) {
assert(c, isInt8(operand->value)); // todo
rex(c);
c->code.append(0x83);
c->code.append(0xc0 | value);
c->code.append(operand->value);
}
} break;
case and_: {
if (operand->value) {
rex(c);
if (isInt8(operand->value)) {
c->code.append(0x83);
c->code.append(0xe0 | value);
c->code.append(operand->value);
} else {
assert(c, isInt32(operand->value));
c->code.append(0x81);
c->code.append(0xe0 | value);
c->code.append(operand->value);
}
}
} break;
case cmp: {
assert(c, isInt8(operand->value)); // todo
2007-12-13 00:18:31 +00:00
rex(c);
c->code.append(0x83);
c->code.append(0xf8 | value);
c->code.append(operand->value);
} break;
case mov: {
2007-12-11 23:52:28 +00:00
rex(c);
c->code.append(0xb8 | value);
c->code.appendAddress(operand->value);
} break;
2007-12-11 23:52:28 +00:00
case sub: {
if (operand->value) {
assert(c, isInt8(operand->value)); // todo
2007-12-11 21:26:59 +00:00
2007-12-11 23:52:28 +00:00
rex(c);
c->code.append(0x83);
c->code.append(0xe8 | value);
c->code.append(operand->value);
2007-12-11 23:52:28 +00:00
}
} break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
MemoryOperand* operand)
{
switch (operation) {
case cmp: {
encode(c, 0x3b, value, operand, true);
} break;
2007-12-13 00:18:31 +00:00
case mov: {
encode(c, 0x8b, value, operand, true);
} break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
void
RegisterOperand::accept(Context* c, Operation operation,
MemoryOperand* operand, SelectionType selection)
{
switch (operation) {
case mov: {
switch (selection) {
case S1Selection:
c->code.append(0x0f);
encode(c, 0xbe, value, operand, false);
break;
2007-12-11 23:52:28 +00:00
case S2Selection:
c->code.append(0x0f);
encode(c, 0xbf, value, operand, false);
break;
2007-12-11 23:52:28 +00:00
case Z2Selection:
c->code.append(0x0f);
encode(c, 0xb7, value, operand, false);
break;
case S4Selection:
encode(c, 0x63, value, operand, true);
break;
default: abort(c);
}
} break;
default: abort(c);
}
}
ImmediateOperand*
value(Context* c, AbsoluteOperand* operand)
{
if (c->codeLength >= 0) {
return immediate
(c, reinterpret_cast<intptr_t>
(c->code.data + operand->promise->value(c)));
} else {
return immediate(c, 0);
}
}
2007-12-11 23:52:28 +00:00
void
RegisterOperand::accept(Context* c, Operation operation,
AbsoluteOperand* operand)
{
switch (operation) {
2007-12-13 00:18:31 +00:00
case cmp: {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, ::value(c, operand));
2007-12-13 00:18:31 +00:00
accept(c, cmp, memory(c, tmp, 0, 0, 1));
tmp->release(c);
} break;
2007-12-11 23:52:28 +00:00
case mov: {
accept(c, mov, ::value(c, operand));
2007-12-11 23:52:28 +00:00
accept(c, mov, memory(c, this, 0, 0, 1));
} break;
default: abort(c);
}
}
void
unconditional(Context* c, unsigned jump, AddressOperand* operand)
2007-12-11 21:26:59 +00:00
{
intptr_t v;
if (c->codeLength >= 0) {
uint8_t* instruction = c->code.data + c->code.length();
v = reinterpret_cast<uint8_t*>(operand->promise->value(c))
- instruction - 5;
} else {
v = 0;
}
c->code.append(jump);
c->code.append4(v);
}
void
conditional(Context* c, unsigned condition, AddressOperand* operand)
{
intptr_t v;
if (c->codeLength >= 0) {
uint8_t* instruction = c->code.data + c->code.length();
v = reinterpret_cast<uint8_t*>(operand->promise->value(c))
- instruction - 6;
} else {
v = 0;
}
c->code.append(0x0f);
c->code.append(condition);
c->code.append4(v);
2007-12-11 21:26:59 +00:00
}
void
AddressOperand::setLabelValue(Context*, CodePromise* p)
{
promise = p;
}
void
AddressOperand::apply(Context* c, Operation operation)
2007-12-11 21:26:59 +00:00
{
switch (operation) {
case alignedCall: {
while ((c->code.length() + 1) % 4) {
c->code.append(0x90);
}
apply(c, call);
} break;
case call:
unconditional(c, 0xe8, this);
break;
case jmp:
unconditional(c, 0xe9, this);
break;
case je:
conditional(c, 0x84, this);
break;
case jne:
conditional(c, 0x85, this);
break;
case jg:
conditional(c, 0x8f, this);
break;
case jge:
conditional(c, 0x8d, this);
break;
case jl:
conditional(c, 0x8c, this);
break;
case jle:
conditional(c, 0x8e, this);
break;
default: abort(c);
}
}
void
ImmediateOperand::apply(Context* c, Operation operation)
{
switch (operation) {
case alignedCall:
case call:
case jmp:
address(c, new (c->zone.allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value))->apply(c, operation);
break;
case push: {
if (isInt8(value)) {
c->code.append(0x6a);
c->code.append(value);
} else if (isInt32(value)) {
c->code.append(0x68);
c->code.append4(value);
} else {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, this);
tmp->apply(c, push);
tmp->release(c);
}
} break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
void
absoluteApply(Context* c, MyOperand::Operation operation,
AbsoluteOperand* operand)
{
RegisterOperand* tmp = temporary(c);
tmp->accept(c, MyOperand::mov, value(c, operand));
memory(c, tmp, 0, 0, 1)->apply(c, operation);
tmp->release(c);
}
2007-12-11 21:26:59 +00:00
void
AbsoluteOperand::apply(Context* c, Operation operation)
{
switch (operation) {
case push:
absoluteApply(c, operation, this);
break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
Register
MemoryOperand::asRegister(Context* c)
2007-12-11 21:26:59 +00:00
{
RegisterOperand* tmp = temporary(c);
2007-12-11 21:26:59 +00:00
tmp->accept(c, mov, this);
tmp->release(c);
return tmp->value;
2007-12-11 21:26:59 +00:00
}
void
MemoryOperand::apply(Context* c, Operation operation)
{
switch (operation) {
case call:
encode(c, 0xff, 2, this, false);
break;
case neg:
encode(c, 0xf7, 2, this, true);
break;
2007-12-11 23:52:28 +00:00
case pop:
encode(c, 0x8f, 0, this, false);
2007-12-11 23:52:28 +00:00
break;
case push:
encode(c, 0xff, 6, this, false);
break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
void
MemoryOperand::apply(Context* c, Operation operation, SelectionType selection)
{
switch (operation) {
case push: {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, this, selection);
tmp->apply(c, operation);
tmp->release(c);
} break;
default: abort(c);
}
}
2007-12-11 21:26:59 +00:00
void
MemoryOperand::accept(Context* c, Operation operation,
RegisterOperand* operand)
{
switch (operation) {
case add: {
encode(c, 0x01, operand->value, this, true);
} break;
case div: {
RegisterOperand* tmp = acquire(c, rax);
tmp->accept(c, mov, this);
rex(c);
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | operand->value);
accept(c, mov, tmp);
tmp->release(c);
} break;
case mov: {
encode(c, 0x89, operand->value, this, true);
} break;
2007-12-11 21:26:59 +00:00
case sub: {
encode(c, 0x29, operand->value, this, true);
} break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
void
MemoryOperand::accept(Context* c, Operation operation,
ImmediateOperand* operand)
{
switch (operation) {
case add: {
unsigned i = (isInt8(operand->value) ? 0x83 : 0x81);
encode(c, i, 0, this, true);
if (isInt8(operand->value)) {
c->code.append(operand->value);
} else if (isInt32(operand->value)) {
c->code.append4(operand->value);
} else {
abort(c);
}
} break;
case mov: {
assert(c, isInt32(operand->value)); // todo
2007-12-11 21:26:59 +00:00
encode(c, 0xc7, 0, this, true);
c->code.append4(operand->value);
} break;
2007-12-11 21:26:59 +00:00
default: abort(c);
}
}
void
MemoryOperand::accept(Context* c, Operation operation,
AbsoluteOperand* operand)
{
switch (operation) {
case mov: {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, operand);
accept(c, mov, tmp);
tmp->release(c);
} break;
default: abort(c);
}
}
void
MemoryOperand::accept(Context* c, Operation operation,
MemoryOperand* operand, SelectionType selection)
{
switch (operation) {
case mov: {
RegisterOperand* tmp = temporary(c);
tmp->accept(c, mov, operand, selection);
accept(c, mov, tmp);
tmp->release(c);
} break;
default: abort(c);
}
}
int
compareSegmentPointers(const void* a, const void* b)
2007-12-11 23:52:28 +00:00
{
return (*static_cast<Segment* const*>(a))->logicalIp
- (*static_cast<Segment* const*>(b))->logicalIp;
2007-12-11 23:52:28 +00:00
}
void
writeCode(Context* c)
{
unsigned tableSize = (c->plan.length() / BytesPerWord);
if (c->codeLength < 0) {
c->segmentTable = static_cast<Segment**>(c->s->allocate(c->plan.length()));
for (unsigned i = 0; i < tableSize; ++i) {
c->plan.get(i * BytesPerWord, c->segmentTable + i, BytesPerWord);
}
qsort(c->segmentTable, tableSize, BytesPerWord, compareSegmentPointers);
2007-12-11 23:52:28 +00:00
}
for (unsigned i = 0; i < tableSize; ++i) {
Segment* s = c->segmentTable[i];
if (Verbose and c->codeLength >= 0) {
fprintf(stderr, "\nip %d\n", s->logicalIp);
}
Event* events[s->event->count];
unsigned ei = s->event->count;
for (Event* e = s->event; e; e = e->next) {
events[--ei] = e;
}
2007-12-11 23:52:28 +00:00
for (unsigned ei = 0; ei < s->event->count; ++ei) {
if (Verbose and c->codeLength >= 0) {
fprintf(stderr, "address %p\n", c->code.data + c->code.length());
}
events[ei]->offset = c->code.length();
events[ei]->run(c);
if (c->codeLength < 0) {
for (Task* t = events[ei]->task; t; t = t->next) {
t->run(c, c->code.length());
}
2007-12-11 23:52:28 +00:00
}
}
}
c->codeLength = pad(c->code.length());
2007-12-11 23:52:28 +00:00
}
class CodePromiseTask: public Task {
public:
CodePromiseTask(CodePromise* promise, Task* next):
Task(next), promise(promise)
{ }
2007-12-11 23:52:28 +00:00
virtual void run(Context* c UNUSED, unsigned offset) {
promise->offset = offset;
2007-12-11 23:52:28 +00:00
}
CodePromise* promise;
};
2007-12-11 23:52:28 +00:00
2007-12-08 23:22:13 +00:00
class MyCompiler: public Compiler {
public:
MyCompiler(System* s, void* indirectCaller):
2007-12-09 20:03:21 +00:00
c(s, indirectCaller)
2007-12-08 23:22:13 +00:00
{ }
virtual Promise* poolOffset() {
2007-12-11 00:48:09 +00:00
return new (c.zone.allocate(sizeof(PoolPromise)))
PoolPromise(c.constantPool.length());
2007-12-08 23:22:13 +00:00
}
virtual Promise* codeOffset() {
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise)))
CodePromise(false);
2007-12-11 21:26:59 +00:00
Segment* s = currentSegment(&c);
s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
CodePromiseTask(p, s->event->task);
2007-12-11 21:26:59 +00:00
return p;
2007-12-08 23:22:13 +00:00
}
virtual Operand* poolAppend(Operand* v) {
2007-12-11 00:48:09 +00:00
Operand* r = absolute(&c, static_cast<MyPromise*>(poolOffset()));
c.constantPool.appendAddress(v);
2007-12-08 23:22:13 +00:00
return r;
}
virtual Operand* constant(intptr_t v) {
2007-12-09 20:03:21 +00:00
return immediate(&c, v);
2007-12-08 23:22:13 +00:00
}
virtual void push(unsigned count) {
::push(&c, count);
}
2007-12-08 23:22:13 +00:00
virtual void push(Operand* v) {
2007-12-11 00:48:09 +00:00
::push(&c, static_cast<MyOperand*>(v));
2007-12-08 23:22:13 +00:00
}
virtual void push2(Operand* v) {
2007-12-09 20:03:21 +00:00
push(v);
if (BytesPerWord == 8) push(immediate(&c, 0));
2007-12-08 23:22:13 +00:00
}
virtual Operand* stack(unsigned index) {
2007-12-11 00:48:09 +00:00
StackOperand* s = c.stack;
unsigned i = 0;
if (s->footprint() / BytesPerWord == 2) ++ i;
for (; i < index; ++i) {
s = s->next;
if (s->footprint() / BytesPerWord == 2) ++ i;
}
2007-12-08 23:22:13 +00:00
2007-12-11 00:48:09 +00:00
return s;
2007-12-08 23:22:13 +00:00
}
virtual void pop(unsigned count) {
::pop(&c, count);
}
2007-12-08 23:22:13 +00:00
virtual Operand* pop() {
Operand* tmp = static_cast<MyOperand*>(temporary());
pop(tmp);
return tmp;
2007-12-08 23:22:13 +00:00
}
virtual Operand* pop2() {
if (BytesPerWord == 8) pop(1);
2007-12-09 20:03:21 +00:00
return pop();
2007-12-08 23:22:13 +00:00
}
virtual void pop(Operand* dst) {
2007-12-11 00:48:09 +00:00
::pop(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void pop2(Operand* dst) {
if (BytesPerWord == 8) pop(1);
2007-12-09 20:03:21 +00:00
pop(dst);
2007-12-08 23:22:13 +00:00
}
virtual Operand* stack() {
2007-12-09 20:03:21 +00:00
return register_(&c, rsp);
2007-12-08 23:22:13 +00:00
}
virtual Operand* base() {
2007-12-09 20:03:21 +00:00
return register_(&c, rbp);
2007-12-08 23:22:13 +00:00
}
virtual Operand* thread() {
2007-12-09 20:03:21 +00:00
return register_(&c, rbx);
2007-12-08 23:22:13 +00:00
}
virtual Operand* indirectTarget() {
2007-12-09 20:03:21 +00:00
return register_(&c, rax);
2007-12-08 23:22:13 +00:00
}
virtual Operand* temporary() {
TemporaryOperand* r = new (c.zone.allocate(sizeof(TemporaryOperand)))
TemporaryOperand(0);
appendAcquire(&c, r);
return r;
2007-12-08 23:22:13 +00:00
}
virtual void release(Operand* v) {
appendRelease(&c, v);
2007-12-08 23:22:13 +00:00
}
virtual Operand* label() {
return address(&c, 0);
2007-12-08 23:22:13 +00:00
}
virtual void mark(Operand* label) {
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise)))
CodePromise(true);
Segment* s = currentSegment(&c);
s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
CodePromiseTask(p, s->event->task);
static_cast<MyOperand*>(label)->setLabelValue(&c, p);
2007-12-08 23:22:13 +00:00
}
virtual Operand* indirectCall
(Operand* address, unsigned argumentCount, ...)
{
va_list a; va_start(a, argumentCount);
2007-12-09 22:45:43 +00:00
unsigned footprint = pushArguments(&c, argumentCount, a);
2007-12-08 23:22:13 +00:00
va_end(a);
mov(address, register_(&c, rax));
call(immediate(&c, c.indirectCaller));
2007-12-11 00:48:09 +00:00
add(immediate(&c, footprint), register_(&c, rsp));
2007-12-09 22:45:43 +00:00
return register_(&c, rax);
2007-12-08 23:22:13 +00:00
}
2007-12-09 22:45:43 +00:00
virtual void indirectCallNoReturn
2007-12-08 23:22:13 +00:00
(Operand* address, unsigned argumentCount, ...)
{
va_list a; va_start(a, argumentCount);
2007-12-09 20:03:21 +00:00
pushArguments(&c, argumentCount, a);
2007-12-08 23:22:13 +00:00
va_end(a);
mov(address, register_(&c, rax));
2007-12-11 00:48:09 +00:00
call(immediate(&c, c.indirectCaller));
2007-12-08 23:22:13 +00:00
}
virtual Operand* directCall
(Operand* address, unsigned argumentCount, ...)
{
va_list a; va_start(a, argumentCount);
2007-12-09 22:45:43 +00:00
unsigned footprint = pushArguments(&c, argumentCount, a);
2007-12-08 23:22:13 +00:00
va_end(a);
call(address);
2007-12-08 23:22:13 +00:00
add(immediate(&c, footprint), register_(&c, rsp));
2007-12-09 22:45:43 +00:00
return register_(&c, rax);
2007-12-08 23:22:13 +00:00
}
virtual void return_(Operand* v) {
mov(v, register_(&c, rax));
epilogue();
2007-12-09 22:45:43 +00:00
ret();
2007-12-08 23:22:13 +00:00
}
2007-12-11 00:48:09 +00:00
virtual Operand* call(Operand* v) {
appendOperation(&c, MyOperand::call, v);
2007-12-11 00:48:09 +00:00
return register_(&c, rax);
}
virtual Operand* alignedCall(Operand* v) {
appendOperation(&c, MyOperand::alignedCall, v);
2007-12-11 00:48:09 +00:00
return register_(&c, rax);
}
2007-12-08 23:22:13 +00:00
virtual void ret() {
appendOperation(&c, MyOperand::ret);
2007-12-08 23:22:13 +00:00
}
virtual void mov(Operand* src, Operand* dst) {
appendOperation(&c, MyOperand::mov, src, dst);
2007-12-08 23:22:13 +00:00
}
virtual void cmp(Operand* subtrahend, Operand* minuend) {
appendOperation(&c, MyOperand::cmp, subtrahend, minuend);
2007-12-08 23:22:13 +00:00
}
virtual void jl(Operand* v) {
appendOperation(&c, MyOperand::jl, v);
2007-12-08 23:22:13 +00:00
}
virtual void jg(Operand* v) {
appendOperation(&c, MyOperand::jg, v);
2007-12-08 23:22:13 +00:00
}
virtual void jle(Operand* v) {
appendOperation(&c, MyOperand::jle, v);
2007-12-08 23:22:13 +00:00
}
virtual void jge(Operand* v) {
appendOperation(&c, MyOperand::jge, v);
2007-12-08 23:22:13 +00:00
}
virtual void je(Operand* v) {
appendOperation(&c, MyOperand::je, v);
2007-12-08 23:22:13 +00:00
}
virtual void jne(Operand* v) {
appendOperation(&c, MyOperand::jne, v);
2007-12-08 23:22:13 +00:00
}
virtual void jmp(Operand* v) {
appendOperation(&c, MyOperand::jmp, v);
2007-12-08 23:22:13 +00:00
}
virtual void add(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::add, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void sub(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::sub, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void mul(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::mul, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void div(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::div, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void rem(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::rem, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void shl(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::shl, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void shr(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::shr, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void ushr(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::ushr, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void and_(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::and_, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void or_(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::or_, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void xor_(Operand* v, Operand* dst) {
appendOperation(&c, MyOperand::xor_, v, dst);
2007-12-08 23:22:13 +00:00
}
virtual void neg(Operand* v) {
appendOperation(&c, MyOperand::neg, v);
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
virtual Operand* memory(Operand* base, int displacement,
2007-12-08 23:22:13 +00:00
Operand* index, unsigned scale)
{
2007-12-09 22:45:43 +00:00
return ::memory(&c, static_cast<MyOperand*>(base), displacement,
static_cast<MyOperand*>(index), scale);
}
virtual Operand* select1(Operand* v) {
return selection(&c, S1Selection, static_cast<MyOperand*>(v));
2007-12-09 22:45:43 +00:00
}
virtual Operand* select2(Operand* v) {
return selection(&c, S2Selection, static_cast<MyOperand*>(v));
2007-12-09 22:45:43 +00:00
}
virtual Operand* select2z(Operand* v) {
return selection(&c, Z2Selection, static_cast<MyOperand*>(v));
2007-12-09 22:45:43 +00:00
}
virtual Operand* select4(Operand* v) {
return selection(&c, S4Selection, static_cast<MyOperand*>(v));
2007-12-08 23:22:13 +00:00
}
2007-12-09 22:45:43 +00:00
virtual Operand* select8(Operand* v) {
return selection(&c, S8Selection, static_cast<MyOperand*>(v));
2007-12-08 23:22:13 +00:00
}
virtual void prologue() {
appendOperation(&c, MyOperand::push, register_(&c, rbp));
appendOperation
(&c, MyOperand::mov, register_(&c, rsp), register_(&c, rbp));
2007-12-08 23:22:13 +00:00
}
virtual void reserve(unsigned size) {
appendOperation
(&c, MyOperand::sub, immediate(&c, size * BytesPerWord),
register_(&c, rsp));
c.reserved = size;
}
2007-12-08 23:22:13 +00:00
virtual void epilogue() {
appendOperation
(&c, MyOperand::mov, register_(&c, rbp), register_(&c, rsp));
appendOperation(&c, MyOperand::pop, register_(&c, rbp));
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
virtual void startLogicalIp(unsigned ip) {
c.plan.appendAddress
(new (c.zone.allocate(sizeof(Segment)))
Segment(ip, new (c.zone.allocate(sizeof(Event))) Event(0)));
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
virtual Operand* logicalIp(unsigned ip) {
return address
(&c, new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, true));
2007-12-08 23:22:13 +00:00
}
2007-12-11 00:48:09 +00:00
virtual Promise* logicalIpToOffset(unsigned ip) {
return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, false);
2007-12-11 00:48:09 +00:00
}
2007-12-08 23:22:13 +00:00
2007-12-11 23:52:28 +00:00
virtual unsigned codeSize() {
if (c.codeLength < 0) {
assert(&c, c.code.length() == 0);
writeCode(&c);
}
return c.codeLength;
2007-12-11 23:52:28 +00:00
}
virtual unsigned poolSize() {
return c.constantPool.length();
2007-12-11 00:48:09 +00:00
}
2007-12-11 21:26:59 +00:00
virtual void writeTo(uint8_t* out) {
c.code.wrap(out, codeSize());
writeCode(&c);
2007-12-11 23:52:28 +00:00
memcpy(out + codeSize(),
c.constantPool.data,
c.constantPool.length());
2007-12-08 23:22:13 +00:00
}
2007-12-11 00:48:09 +00:00
virtual void updateCall(void* returnAddress, void* newTarget) {
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
assert(&c, *instruction == 0xE8);
2007-12-11 23:52:28 +00:00
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
2007-12-11 00:48:09 +00:00
int32_t v = static_cast<uint8_t*>(newTarget)
- static_cast<uint8_t*>(returnAddress);
memcpy(instruction + 1, &v, 4);
2007-12-09 20:03:21 +00:00
}
2007-12-08 23:22:13 +00:00
virtual void dispose() {
2007-12-09 20:03:21 +00:00
c.dispose();
2007-12-08 23:22:13 +00:00
2007-12-09 22:45:43 +00:00
c.s->free(this);
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
};
intptr_t
2007-12-11 23:52:28 +00:00
MyPromise::value(Compiler* compiler)
2007-12-11 00:48:09 +00:00
{
2007-12-11 23:52:28 +00:00
return value(&(static_cast<MyCompiler*>(compiler)->c));
2007-12-11 00:48:09 +00:00
}
2007-12-08 23:22:13 +00:00
} // namespace
namespace vm {
Compiler*
makeCompiler(System* system, void* indirectCaller)
{
return new (system->allocate(sizeof(MyCompiler)))
MyCompiler(system, indirectCaller);
}
} // namespace v