mirror of
https://github.com/corda/corda.git
synced 2025-06-02 07:30:53 +00:00
more work on new compiler
This commit is contained in:
parent
7bb69b1c56
commit
dc04c63491
122
src/assember.h
122
src/assember.h
@ -3,9 +3,23 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
enum OperationType {
|
enum Operation {
|
||||||
|
Return
|
||||||
|
};
|
||||||
|
|
||||||
|
enum UnaryOperation {
|
||||||
Call,
|
Call,
|
||||||
Return,
|
JumpIfLess,
|
||||||
|
JumpIfGreater,
|
||||||
|
JumpIfLessOrEqual,
|
||||||
|
JumpIfGreaterOrEqual,
|
||||||
|
JumpIfEqual,
|
||||||
|
JumpIfNotEqual,
|
||||||
|
Jump,
|
||||||
|
Negate
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BinaryOperation {
|
||||||
Move,
|
Move,
|
||||||
Store1,
|
Store1,
|
||||||
Store2,
|
Store2,
|
||||||
@ -16,13 +30,6 @@ enum OperationType {
|
|||||||
Load2z,
|
Load2z,
|
||||||
Load4,
|
Load4,
|
||||||
Load8,
|
Load8,
|
||||||
JumpIfLess,
|
|
||||||
JumpIfGreater,
|
|
||||||
JumpIfLessOrEqual,
|
|
||||||
JumpIfGreaterOrEqual,
|
|
||||||
JumpIfEqual,
|
|
||||||
JumpIfNotEqual,
|
|
||||||
Jump,
|
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
Multiply,
|
Multiply,
|
||||||
@ -33,12 +40,66 @@ enum OperationType {
|
|||||||
UnsignedShiftRight,
|
UnsignedShiftRight,
|
||||||
And,
|
And,
|
||||||
Or,
|
Or,
|
||||||
Xor,
|
Xor
|
||||||
Negate
|
};
|
||||||
|
|
||||||
|
enum OperandType {
|
||||||
|
Constant,
|
||||||
|
Address,
|
||||||
|
Register,
|
||||||
|
Memory
|
||||||
|
};
|
||||||
|
|
||||||
|
const int NoRegister = -1;
|
||||||
|
const int AnyRegister = -2;
|
||||||
|
|
||||||
|
class Promise {
|
||||||
|
public:
|
||||||
|
virtual int64_t value() = 0;
|
||||||
|
virtual bool resolved() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Assembler {
|
class Assembler {
|
||||||
public:
|
public:
|
||||||
|
class Operand { };
|
||||||
|
|
||||||
|
class Constant: public Operand {
|
||||||
|
public:
|
||||||
|
Constant(Promise* value): value(value) { }
|
||||||
|
|
||||||
|
Promise* value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Address: public Operand {
|
||||||
|
public:
|
||||||
|
Address(Promise* address): address(address) { }
|
||||||
|
|
||||||
|
Promise* address;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Register: public Operand {
|
||||||
|
public:
|
||||||
|
Register(int low, int high): low(low), high(high) { }
|
||||||
|
|
||||||
|
int low;
|
||||||
|
int high;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Memory: public Operand {
|
||||||
|
public:
|
||||||
|
Memory(int base, int offset, int index, unsigned scale,
|
||||||
|
TraceHandler* traceHandler):
|
||||||
|
base(base), offset(offset), index(index), scale(scale),
|
||||||
|
traceHandler(traceHandler)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
int base;
|
||||||
|
int offset;
|
||||||
|
int index;
|
||||||
|
unsigned scale;
|
||||||
|
TraceHandler* traceHandler;
|
||||||
|
};
|
||||||
|
|
||||||
virtual unsigned registerCount() = 0;
|
virtual unsigned registerCount() = 0;
|
||||||
|
|
||||||
virtual int base() = 0;
|
virtual int base() = 0;
|
||||||
@ -52,38 +113,23 @@ class Assembler {
|
|||||||
|
|
||||||
virtual int stackSyncRegister(unsigned index) = 0;
|
virtual int stackSyncRegister(unsigned index) = 0;
|
||||||
|
|
||||||
virtual void getTargets(OperationType op, unsigned size,
|
virtual void getTargets(BinaryOperation op, unsigned size,
|
||||||
int* aLow, int* aHigh,
|
Register* a, Register* b) = 0;
|
||||||
int* bLow, int* bHigh) = 0;
|
|
||||||
|
|
||||||
virtual void appendC(OperationType op, unsigned size, Promise* value) = 0;
|
virtual void apply(Operation op) = 0;
|
||||||
virtual void appendR(OperationType op, unsigned size, int low, int high) = 0;
|
|
||||||
virtual void appendM(OperationType op, unsigned size, int base, int offset,
|
|
||||||
int index, unsigned scale,
|
|
||||||
TraceHandler* traceHandler) = 0;
|
|
||||||
|
|
||||||
virtual void appendCR(OperationType op, unsigned size, Promise* aValue,
|
virtual void apply(UnaryOperation op, unsigned size, OperandType type,
|
||||||
int bLow, int bHigh) = 0;
|
Operand* operand) = 0;
|
||||||
virtual void appendRR(OperationType op, unsigned size, int aLow, int aHigh,
|
|
||||||
int bLow, int bHigh) = 0;
|
|
||||||
virtual void appendMR(OperationType op, unsigned size,
|
|
||||||
int aBase, int aOffset, int aIndex, unsigned aScale,
|
|
||||||
TraceHandler* aTraceHandler,
|
|
||||||
int bLow, int bHigh) = 0;
|
|
||||||
|
|
||||||
virtual void appendCM(OperationType op, unsigned size, Promise* aValue,
|
virtual void apply(BinaryOperation op, unsigned size, OperandType aType,
|
||||||
int bBase, int bOffset, int bIndex, unsigned bScale,
|
OperandType bType, Operand* a, Operand* b) = 0;
|
||||||
TraceHandler* bTraceHandler) = 0;
|
|
||||||
virtual void appendRM(OperationType op, unsigned size, int aLow, int aHigh,
|
virtual void writeTo(uint8_t* dst) = 0;
|
||||||
int bBase, int bOffset, int bIndex, unsigned bScale,
|
|
||||||
TraceHandler* bTraceHandler) = 0;
|
|
||||||
virtual void appendMM(OperationType op, unsigned size,
|
|
||||||
int aBase, int aOffset, int aIndex, unsigned aScale,
|
|
||||||
TraceHandler* aTraceHandler,
|
|
||||||
int bBase, int bOffset, int bIndex, unsigned bScale,
|
|
||||||
TraceHandler* bTraceHandler) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Assembler*
|
||||||
|
makeAssembler(System* system, Allocator* allocator, Zone* zone);
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//ASSEMBLER_H
|
#endif//ASSEMBLER_H
|
||||||
|
@ -8,35 +8,31 @@ namespace {
|
|||||||
class Context;
|
class Context;
|
||||||
class MyOperand;
|
class MyOperand;
|
||||||
class ConstantValue;
|
class ConstantValue;
|
||||||
|
class AddressValue;
|
||||||
class RegisterValue;
|
class RegisterValue;
|
||||||
class MemoryValue;
|
class MemoryValue;
|
||||||
class Event;
|
class Event;
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
virtual bool equals(Value* o);
|
virtual bool equals(Value* o) { return false; }
|
||||||
virtual bool equals(ConstantValue* o) { return false; }
|
|
||||||
virtual bool equals(RegisterValue* o) { return false; }
|
virtual bool equals(RegisterValue* o) { return false; }
|
||||||
virtual bool equals(ConstantValue* o) { return false; }
|
|
||||||
|
|
||||||
virtual void preserve(Context*) { }
|
virtual void preserve(Context*) { }
|
||||||
virtual void acquire(Context*, MyOperand*) { }
|
virtual void acquire(Context*, MyOperand*) { }
|
||||||
virtual void release(Context*, MyOperand*) { }
|
virtual void release(Context*, MyOperand*) { }
|
||||||
|
|
||||||
virtual void apply(Context*, OperationType op) = 0;
|
virtual RegisterValue* toRegister(Context*, unsigned size) = 0;
|
||||||
virtual void apply(Context*, OperationType op, unsigned size, Value* b) = 0;
|
|
||||||
virtual void accept(Context*, OperationType op, unsigned size,
|
virtual void asAssemblerOperand(Context*,
|
||||||
ConstantValue* a) = 0;
|
OperandType* type,
|
||||||
virtual void accept(Context*, OperationType op, unsigned size,
|
Assembler::Operand** operand) = 0;
|
||||||
RegisterValue* a) = 0;
|
|
||||||
virtual void accept(Context*, OperationType op, unsigned size,
|
|
||||||
MemoryValue* a) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyOperand: public Operand {
|
class MyOperand: public Operand {
|
||||||
public:
|
public:
|
||||||
MyOperand(unsigned size):
|
MyOperand(unsigned size, Value* value):
|
||||||
size(size), event(0), value(0), index(0), next(0)
|
size(size), event(0), value(value), index(0), next(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned size;
|
unsigned size;
|
||||||
@ -72,7 +68,8 @@ class Register {
|
|||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
Context(Assembler* assembler, Zone* zone):
|
Context(System* s, Assembler* assembler, Zone* zone):
|
||||||
|
system(system),
|
||||||
assembler(assembler),
|
assembler(assembler),
|
||||||
zone(zone),
|
zone(zone),
|
||||||
logicalIp(-1),
|
logicalIp(-1),
|
||||||
@ -80,7 +77,10 @@ class Context {
|
|||||||
event(0),
|
event(0),
|
||||||
logicalCode(0),
|
logicalCode(0),
|
||||||
registers(static_cast<Register*>
|
registers(static_cast<Register*>
|
||||||
(zone->allocate(sizeof(Register) * assembler->registerCount())))
|
(zone->allocate(sizeof(Register) * assembler->registerCount()))),
|
||||||
|
firstConstant(0),
|
||||||
|
lastConstant(0),
|
||||||
|
constantCount(0)
|
||||||
{
|
{
|
||||||
memset(registers, 0, sizeof(Register) * assembler->registerCount());
|
memset(registers, 0, sizeof(Register) * assembler->registerCount());
|
||||||
|
|
||||||
@ -89,6 +89,7 @@ class Context {
|
|||||||
registers[assembler->thread()].reserved = true;
|
registers[assembler->thread()].reserved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System* system;
|
||||||
Assembler* assembler;
|
Assembler* assembler;
|
||||||
Zone* zone;
|
Zone* zone;
|
||||||
unsigned logicalIp;
|
unsigned logicalIp;
|
||||||
@ -96,37 +97,145 @@ class Context {
|
|||||||
Event* event;
|
Event* event;
|
||||||
LogicalInstruction* logicalCode;
|
LogicalInstruction* logicalCode;
|
||||||
Register* registers;
|
Register* registers;
|
||||||
|
Constant* firstConstant;
|
||||||
|
Constant* lastConstant;
|
||||||
|
unsigned constantCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
apply(Context* c, UnaryOperand op, unsigned size, Value* a)
|
||||||
|
{
|
||||||
|
OperandType type;
|
||||||
|
Assembler::Operand* operand;
|
||||||
|
a->asAssemblerOperand(&type, &operand);
|
||||||
|
|
||||||
|
c->assembler->apply(op, size, type, operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
apply(Context* c, BinaryOperand op, unsigned size, Value* a, Value* b)
|
||||||
|
{
|
||||||
|
OperandType aType;
|
||||||
|
Assembler::Operand* aOperand;
|
||||||
|
a->asAssemblerOperand(&aType, &aOperand);
|
||||||
|
|
||||||
|
OperandType bType;
|
||||||
|
Assembler::Operand* bOperand;
|
||||||
|
b->asAssemblerOperand(&bType, &bOperand);
|
||||||
|
|
||||||
|
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResolvedPromise: public Promise {
|
||||||
|
public:
|
||||||
|
ResolvedPromise(int64_t value): value_(value) { }
|
||||||
|
|
||||||
|
virtual int64_t value() {
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool resolved() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PoolPromise: public Promise {
|
||||||
|
public:
|
||||||
|
PoolPromise(Context* c, int key): c(c), key(key) { }
|
||||||
|
|
||||||
|
virtual int64_t value() {
|
||||||
|
if (resolved(c)) {
|
||||||
|
return reinterpret_cast<intptr_t>(c->code + c->codeLength + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool resolved() {
|
||||||
|
return c->code != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
|
int key;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CodePromise: public Promise {
|
||||||
|
public:
|
||||||
|
CodePromise(Context* c): c(c), offset(-1) { }
|
||||||
|
|
||||||
|
virtual int64_t value() {
|
||||||
|
if (resolved(c)) {
|
||||||
|
return reinterpret_cast<intptr_t>(c->code + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool resolved(Context* c) {
|
||||||
|
return c->code != 0 and offset >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
|
int offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IpPromise: public Promise {
|
||||||
|
public:
|
||||||
|
IpPromise(Context* c, int logicalIp):
|
||||||
|
c(c),
|
||||||
|
logicalIp(logicalIp)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual int64_t value() {
|
||||||
|
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) {
|
||||||
|
return reinterpret_cast<intptr_t>(c->code + s->offset);
|
||||||
|
} else if (logicalIp < s->logicalIp) {
|
||||||
|
top = middle;
|
||||||
|
} else if (logicalIp > s->logicalIp) {
|
||||||
|
bottom = middle + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool resolved() {
|
||||||
|
return c->code != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
|
int logicalIp;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConstantValue: public Value {
|
class ConstantValue: public Value {
|
||||||
public:
|
public:
|
||||||
ConstantValue(Promise* value): value(value) { }
|
ConstantValue(Promise* value): value(value) { }
|
||||||
|
|
||||||
virtual bool equals(Value* o) { return o->equals(this); }
|
virtual RegisterValue* toRegister(Context* c, unsigned size) {
|
||||||
|
RegisterValue* v = freeRegister(c, size);
|
||||||
virtual bool equals(ConstantValue* o) { return o->value == value; }
|
apply(c, Move, size, this, v);
|
||||||
|
return v;
|
||||||
virtual void apply(Context* c, OperationType op, unsigned size) {
|
|
||||||
c->assembler->appendC(op, size, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Context* c, OperationType op, unsigned size, Value* b) {
|
virtual void asAssemblerOperand(Context*,
|
||||||
b->accept(c, op, size, this);
|
OperandType* type,
|
||||||
|
void** operand)
|
||||||
|
{
|
||||||
|
*type = Constant;
|
||||||
|
*operand = &value;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType, unsigned, ConstantValue*) {
|
Assembler::Constant value;
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType, unsigned, RegisterValue*) {
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType, unsigned, MemoryValue*) {
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise* value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstantValue*
|
ConstantValue*
|
||||||
@ -135,58 +244,75 @@ constant(Context* c, Promise* value)
|
|||||||
return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value);
|
return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AddressValue: public Value {
|
||||||
|
public:
|
||||||
|
AddressValue(Promise* address): address(address) { }
|
||||||
|
|
||||||
|
virtual RegisterValue* toRegister(Context* c, unsigned size) {
|
||||||
|
RegisterValue* v = freeRegister(c, size);
|
||||||
|
apply(c, Move, size, this, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void asAssemblerOperand(Context*,
|
||||||
|
OperandType* type,
|
||||||
|
void** operand)
|
||||||
|
{
|
||||||
|
*type = Address;
|
||||||
|
*operand = &address;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assembler::Address address;
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressValue*
|
||||||
|
address(Context* c, Promise* address)
|
||||||
|
{
|
||||||
|
return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address);
|
||||||
|
}
|
||||||
|
|
||||||
void preserve(Context* c, int reg);
|
void preserve(Context* c, int reg);
|
||||||
|
|
||||||
class RegisterValue: public Value {
|
class RegisterValue: public Value {
|
||||||
public:
|
public:
|
||||||
RegisterValue(int low, int high): low(low), high(high) { }
|
RegisterValue(int low, int high): register_(low, high) { }
|
||||||
|
|
||||||
virtual bool equals(Value* o) { return o->equals(this); }
|
virtual bool equals(Value* o) { return o->equals(this); }
|
||||||
|
|
||||||
virtual bool equals(RegisterValue* o) {
|
virtual bool equals(RegisterValue* o) {
|
||||||
return o->low == low and o->high == high;
|
return o->register_.low == register_.low
|
||||||
|
and o->register_.high == register_.high;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void preserve(Context* c) {
|
virtual void preserve(Context* c) {
|
||||||
::preserve(c, low);
|
::preserve(c, register_.low);
|
||||||
if (high >= 0) ::preserve(c, high);
|
if (high >= 0) ::preserve(c, register_.high);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void acquire(Context* c, MyOperand* a) {
|
virtual void acquire(Context* c, MyOperand* a) {
|
||||||
preserve(c);
|
preserve(c);
|
||||||
c->registers[low].operand = a;
|
c->registers[register_.low].operand = a;
|
||||||
if (high >= 0) c->registers[high].operand = a;
|
if (high >= 0) c->registers[register_.high].operand = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void release(Context* c, MyOperand* a) {
|
virtual void release(Context* c, MyOperand* a) {
|
||||||
c->registers[low].operand = 0;
|
c->registers[register_.low].operand = 0;
|
||||||
if (high >= 0) c->registers[high].operand = 0;
|
if (high >= 0) c->registers[register_.high].operand = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Context* c, OperationType op, unsigned size) {
|
virtual RegisterValue* toRegister(Context*, unsigned) {
|
||||||
c->assembler->appendR(op, size, low, high);
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Context* c, OperationType op, unsigned size, Value* b) {
|
virtual void asAssemblerOperand(Context*,
|
||||||
b->accept(c, op, size, this);
|
OperandType* type,
|
||||||
}
|
void** operand)
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType op, unsigned size,
|
|
||||||
ConstantValue* a)
|
|
||||||
{
|
{
|
||||||
c->assembler->appendCR(op, size, a->value, low, high);
|
*type = Register;
|
||||||
|
*operand = ®ister_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType op, unsigned size,
|
Assembler::Register register_;
|
||||||
RegisterValue* a)
|
|
||||||
{
|
|
||||||
c->assembler->appendRR(op, size, a->low, a->high, low, high);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType op, unsigned size,
|
|
||||||
MemoryValue* a);
|
|
||||||
|
|
||||||
unsigned low;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RegisterValue*
|
RegisterValue*
|
||||||
@ -200,54 +326,34 @@ class MemoryValue: public Value {
|
|||||||
public:
|
public:
|
||||||
MemoryValue(int base, int offset, int index, unsigned scale,
|
MemoryValue(int base, int offset, int index, unsigned scale,
|
||||||
TraceHandler* traceHandler):
|
TraceHandler* traceHandler):
|
||||||
base(base), offset(offset), index(index), scale(scale),
|
value(base, offset, index. scale, traceHandler)
|
||||||
traceHandler(traceHandler)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool equals(Value* o) { return o->equals(this); }
|
virtual RegisterValue* toRegister(Context* c, unsigned size) {
|
||||||
|
RegisterValue* v = freeRegister(c, size);
|
||||||
virtual bool equals(MemoryValue* o) {
|
apply(c, Move, size, this, v);
|
||||||
return o->base == base
|
return v;
|
||||||
and o->offset == offset
|
|
||||||
and o->index == index
|
|
||||||
and o->scale == scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Context* c, OperationType op, unsigned size) {
|
virtual int base(Context* c) {
|
||||||
c->assembler->appendM(op, size, base, offset, index, scale, traceHandler);
|
return value.base;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Context* c, OperationType op, unsigned size, Value* b) {
|
virtual int index(Context* c) {
|
||||||
b->accept(c, op, size, this);
|
return value.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType op, unsigned size,
|
virtual void asAssemblerrOperand(Context* c,
|
||||||
ConstantValue* a)
|
OperandType* type,
|
||||||
|
Assembler::Operand** operand)
|
||||||
{
|
{
|
||||||
c->assembler->appendCM(op, size, a->value,
|
value.base = base(c);
|
||||||
base, offset, index, scale, traceHandler);
|
value.index = index(c);
|
||||||
|
*type = Memory;
|
||||||
|
*operand = &value;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType op, unsigned size,
|
Assembler::Memory value;
|
||||||
RegisterValue* a)
|
|
||||||
{
|
|
||||||
c->assembler->appendRM(op, size, a->low, a->high,
|
|
||||||
base, offset, index, scale, traceHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void accept(Context* c, OperationType op, unsigned size,
|
|
||||||
MemoryValue* a)
|
|
||||||
{
|
|
||||||
c->assembler->appendMM
|
|
||||||
(op, size, a->base, a->offset, a->index, a->scale, a->traceHandler,
|
|
||||||
base, offset, index, scale, traceHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
int base;
|
|
||||||
int offset;
|
|
||||||
int index;
|
|
||||||
unsigned scale;
|
|
||||||
TraceHandler* traceHandler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryValue*
|
MemoryValue*
|
||||||
@ -258,6 +364,34 @@ memory(Context* c, int base, int offset, int index, unsigned scale,
|
|||||||
MemoryValue(base, offset, index, scale, traceHandler);
|
MemoryValue(base, offset, index, scale, traceHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AbstractMemoryValue: public MemoryValue {
|
||||||
|
public:
|
||||||
|
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
|
||||||
|
unsigned scale, TraceHandler* traceHandler):
|
||||||
|
MemoryValue(NoRegister, offset, NoRegister, scale, traceHandler)
|
||||||
|
base_(base), index_(index)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual int base(Context* c) {
|
||||||
|
return base_->toRegister(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int index(Context* c) {
|
||||||
|
return index_ ? index_->toRegister(c) : NoRegister;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyOperand* base_;
|
||||||
|
MyOperand* index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractMemoryValue*
|
||||||
|
memory(Context* c, MyOperand* base, int offset, MyOperand* index,
|
||||||
|
unsigned scale, TraceHandler* traceHandler)
|
||||||
|
{
|
||||||
|
return new (c->zone->allocate(sizeof(AbstractMemoryValue)))
|
||||||
|
AbstractMemoryValue(base, offset, index, scale, traceHandler);
|
||||||
|
}
|
||||||
|
|
||||||
class Event {
|
class Event {
|
||||||
public:
|
public:
|
||||||
Event(Context* c): next(0) {
|
Event(Context* c): next(0) {
|
||||||
@ -310,7 +444,7 @@ class ArgumentEvent: public Event {
|
|||||||
a->target->preserve(c);
|
a->target->preserve(c);
|
||||||
|
|
||||||
if (not a->target->equals(a->value)) {
|
if (not a->target->equals(a->value)) {
|
||||||
a->value->apply(c, Move, a->size, a->target);
|
apply(c, Move, a->size, a->value, a->target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,8 +481,9 @@ class ReturnEvent: public Event {
|
|||||||
a->value->release(c, a);
|
a->value->release(c, a);
|
||||||
|
|
||||||
if (not a->target->equals(a->value)) {
|
if (not a->target->equals(a->value)) {
|
||||||
a->value->apply(c, Move, a->size, a->target);
|
apply(c, Move, a->size, a->value, a->target);
|
||||||
}
|
}
|
||||||
|
c->assembler->apply(Return);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyOperand* a;
|
MyOperand* a;
|
||||||
@ -383,7 +518,7 @@ class SyncForCallEvent: public Event {
|
|||||||
src->value->release(c, src);
|
src->value->release(c, src);
|
||||||
|
|
||||||
if (not src->target->equals(src->value)) {
|
if (not src->target->equals(src->value)) {
|
||||||
src->value->apply(c, Move, src->size, src->target);
|
apply(c, Move, src->size, src->value, src->target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +565,7 @@ class SyncForJumpEvent: public Event {
|
|||||||
src->target->acquire(c, dst);
|
src->target->acquire(c, dst);
|
||||||
|
|
||||||
if (not src->target->equals(src->value)) {
|
if (not src->target->equals(src->value)) {
|
||||||
src->value->apply(c, Move, src->size, src->target);
|
apply(c, Move, src->size, src->value, src->target);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->value = src->target;
|
dst->value = src->target;
|
||||||
@ -480,12 +615,11 @@ class CallEvent: public Event {
|
|||||||
result->value->acquire(c, result);
|
result->value->acquire(c, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
register_(c, StackRegister)->accept
|
apply(c, LoadAddress, BytesPerWord, register_(c, StackRegister),
|
||||||
(c, LoadAddress, BytesPerWord,
|
memory(c, c->assembler->base(), stackOffset * BytesPerWord,
|
||||||
memory(c, c->assembler->base(), stackOffset * BytesPerWord,
|
NoRegister, 0, 0));
|
||||||
NoRegister, 0, 0));
|
|
||||||
|
|
||||||
address->value->apply(c, Call);
|
apply(c, Call, address->size, address->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyOperand* address;
|
MyOperand* address;
|
||||||
@ -522,6 +656,16 @@ freeRegister(Context* c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegisterValue*
|
||||||
|
freeRegister(Context* c, unsigned size)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
|
return register_(c, freeRegister(c), freeRegister(c));
|
||||||
|
} else {
|
||||||
|
return register_(c, freeRegister(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MoveEvent: public Event {
|
class MoveEvent: public Event {
|
||||||
public:
|
public:
|
||||||
MoveEvent(Context* c, OperationType type, MyOperand* src, MyOperand* dst):
|
MoveEvent(Context* c, OperationType type, MyOperand* src, MyOperand* dst):
|
||||||
@ -542,17 +686,13 @@ class MoveEvent: public Event {
|
|||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
if (src->target == 0) {
|
if (src->target == 0) {
|
||||||
if (BytesPerWord == 4 and src->size == 8) {
|
src->target = freeRegister(c, src->size);
|
||||||
src->target = register_(c, freeRegister(c), freeRegister(c));
|
|
||||||
} else {
|
|
||||||
src->target = register_(c, freeRegister(c));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src->value->release(c, src);
|
src->value->release(c, src);
|
||||||
src->target->acquire(c, dst);
|
src->target->acquire(c, dst);
|
||||||
|
|
||||||
src->value->apply(c, type, src->size, src->target);
|
apply(c, type, src->size, src->value, src->target);
|
||||||
|
|
||||||
dst->value = src->target;
|
dst->value = src->target;
|
||||||
}
|
}
|
||||||
@ -597,8 +737,8 @@ class BranchEvent: public Event {
|
|||||||
b->value->release(c, b);
|
b->value->release(c, b);
|
||||||
address->value->release(c, address);
|
address->value->release(c, address);
|
||||||
|
|
||||||
a->value->apply(c, Compare, a->size, b->value);
|
apply(c, Compare, a->size, a->value, b->value);
|
||||||
address->value->apply(c, type, address->size);
|
apply(c, type, address->size, address->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
OperationType type;
|
OperationType type;
|
||||||
@ -636,7 +776,7 @@ class JumpEvent: public Event {
|
|||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
address->value->release(c, address);
|
address->value->release(c, address);
|
||||||
|
|
||||||
address->value->apply(c, Jump, address->size);
|
apply(c, Jump, address->size, address->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyOperand* address;
|
MyOperand* address;
|
||||||
@ -660,7 +800,7 @@ class CombineEvent: public Event {
|
|||||||
|
|
||||||
virtual Value* target(Context* c, MyOperand* v) {
|
virtual Value* target(Context* c, MyOperand* v) {
|
||||||
int aLow, aHigh, bLow, bHigh;
|
int aLow, aHigh, bLow, bHigh;
|
||||||
c->assembler->getTargets(op, v->size, &aLow, &aHigh, &bLow, &bHigh);
|
c->assembler->getTargets(type, v->size, &aLow, &aHigh, &bLow, &bHigh);
|
||||||
|
|
||||||
if (v == a) {
|
if (v == a) {
|
||||||
if (aLow == NoRegister) {
|
if (aLow == NoRegister) {
|
||||||
@ -696,9 +836,13 @@ class CombineEvent: public Event {
|
|||||||
b->value->acquire(c, result);
|
b->value->acquire(c, result);
|
||||||
|
|
||||||
if (a->target and not a->target->equals(a->value)) {
|
if (a->target and not a->target->equals(a->value)) {
|
||||||
a->value->apply(c, Move, a->size, a->target);
|
apply(c, Move, a->size, a->value, a->target);
|
||||||
}
|
}
|
||||||
a->value->apply(c, type, a->size, b->value);
|
if (b->target and not b->target->equals(b->value)) {
|
||||||
|
apply(c, Move, b->size, b->value, b->target);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(c, type, a->size, a->value, b->value);
|
||||||
|
|
||||||
result->value = b->value;
|
result->value = b->value;
|
||||||
}
|
}
|
||||||
@ -727,7 +871,14 @@ class TranslateEvent: public Event {
|
|||||||
virtual Value* target(Context* c, MyOperand* v) {
|
virtual Value* target(Context* c, MyOperand* v) {
|
||||||
assert(c, v == a);
|
assert(c, v == a);
|
||||||
|
|
||||||
return result->event->target(c, result);
|
int low, high;
|
||||||
|
c->assembler->getTargets(type, v->size, &low, &high);
|
||||||
|
|
||||||
|
if (low == NoRegister) {
|
||||||
|
return result->event->target(c, result);
|
||||||
|
} else {
|
||||||
|
return register_(c, low, high);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
|
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
|
||||||
@ -739,7 +890,7 @@ class TranslateEvent: public Event {
|
|||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
result->value->acquire(c, result);
|
result->value->acquire(c, result);
|
||||||
|
|
||||||
a->value->apply(c, type, a->size);
|
apply(c, type, a->size, a->value);
|
||||||
|
|
||||||
result->value = b->value;
|
result->value = b->value;
|
||||||
}
|
}
|
||||||
@ -769,14 +920,6 @@ class Junction {
|
|||||||
Junction* next;
|
Junction* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
RegisterValue::accept(Context* c, OperationType op, unsigned size,
|
|
||||||
MemoryValue* a)
|
|
||||||
{
|
|
||||||
c->assembler->appendMR(op, size, a->base, a->offset, a->index, a->scale,
|
|
||||||
a->traceHandler, low, high);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
preserve(Context* c, int reg)
|
preserve(Context* c, int reg)
|
||||||
{
|
{
|
||||||
@ -790,7 +933,8 @@ preserve(Context* c, int reg)
|
|||||||
(Move, a->size,
|
(Move, a->size,
|
||||||
static_cast<RegisterValue*>(a->value)->low,
|
static_cast<RegisterValue*>(a->value)->low,
|
||||||
static_cast<RegisterValue*>(a->value)->high,
|
static_cast<RegisterValue*>(a->value)->high,
|
||||||
dst->base, dst->offset, dst->index, dst->scale, dst->traceHandler);
|
dst->base(c), dst->offset, dst->index(c), dst->scale,
|
||||||
|
dst->traceHandler);
|
||||||
|
|
||||||
a->value = dst;
|
a->value = dst;
|
||||||
c->registers[reg].operand = 0;
|
c->registers[reg].operand = 0;
|
||||||
@ -798,9 +942,9 @@ preserve(Context* c, int reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MyOperand*
|
MyOperand*
|
||||||
operand(Context* c)
|
operand(Context* c, unsigned size, Value* value)
|
||||||
{
|
{
|
||||||
return new (c->zone->allocate(sizeof(MyOperand))) MyOperand;
|
return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -838,7 +982,7 @@ syncStack(Context* c, MoveType type)
|
|||||||
MyOperand* top = 0;
|
MyOperand* top = 0;
|
||||||
MyOperand* new_ = 0;
|
MyOperand* new_ = 0;
|
||||||
for (MyOperand* old = c->state->stack; old; old = old->next) {
|
for (MyOperand* old = c->state->stack; old; old = old->next) {
|
||||||
MyOperand* n = operand(c);
|
MyOperand* n = operand(c, old->size, 0);
|
||||||
if (new_) {
|
if (new_) {
|
||||||
new_->next = n;
|
new_->next = n;
|
||||||
} else {
|
} else {
|
||||||
@ -868,7 +1012,7 @@ updateJunctions(Context* c)
|
|||||||
|
|
||||||
MyOperand* new_ = 0;
|
MyOperand* new_ = 0;
|
||||||
for (MyOperand* old = i->firstEvent->stack; old; old = old->next) {
|
for (MyOperand* old = i->firstEvent->stack; old; old = old->next) {
|
||||||
MyOperand* n = operand(c);
|
MyOperand* n = operand(c, old->size, 0);
|
||||||
if (new_) new_->next = n;
|
if (new_) new_->next = n;
|
||||||
new_ = n;
|
new_ = n;
|
||||||
new_->index = old->index;
|
new_->index = old->index;
|
||||||
@ -931,7 +1075,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* machineIp(unsigned logicalIp) {
|
virtual Promise* machineIp(unsigned logicalIp) {
|
||||||
return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(logicalIp);
|
return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* poolAppend(intptr_t value) {
|
virtual Promise* poolAppend(intptr_t value) {
|
||||||
@ -940,25 +1084,36 @@ class MyCompiler: public Compiler {
|
|||||||
|
|
||||||
virtual Promise* poolAppendPromise(Promise* value) {
|
virtual Promise* poolAppendPromise(Promise* value) {
|
||||||
Promise* p = new (c.zone->allocate(sizeof(PoolPromise)))
|
Promise* p = new (c.zone->allocate(sizeof(PoolPromise)))
|
||||||
PoolPromise(c.constantPool.length());
|
PoolPromise(&c, c.constantPool.length());
|
||||||
c.constantPool.appendAddress(value);
|
|
||||||
|
Constant* constant = new (c.zone->allocate(sizeof(Constant)))
|
||||||
|
Constant(value);
|
||||||
|
|
||||||
|
if (c.firstConstant) {
|
||||||
|
c.lastConstant->next = constant;
|
||||||
|
} else {
|
||||||
|
c.firstConstant = constant;
|
||||||
|
}
|
||||||
|
c.lastConstant = constant;
|
||||||
|
++ c.constantCount;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual intptr_t valueOf(Promise* promise) {
|
|
||||||
return static_cast<MyPromise*>(promise)->value(&c);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Operand* constant(int64_t value) {
|
virtual Operand* constant(int64_t value) {
|
||||||
return immediate(&c, value);
|
return operand
|
||||||
|
(&c, ::constant(&c, new (c.zone->allocate(sizeof(ResolvedPromise)))
|
||||||
|
ResolvedPromise(&c, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* promiseConstant(Promise* value) {
|
virtual Operand* promiseConstant(Promise* value) {
|
||||||
return address(&c, static_cast<MyPromise*>(value));
|
return operand
|
||||||
|
(&c, ::constant(&c, static_cast<Promise*>(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* absolute(Promise* address) {
|
virtual Operand* absolute(Promise* address) {
|
||||||
return ::absolute(&c, static_cast<MyPromise*>(address));
|
return operand
|
||||||
|
(&c, ::absolute(&c, static_cast<Promise*>(address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* memory(Operand* base,
|
virtual Operand* memory(Operand* base,
|
||||||
@ -967,33 +1122,35 @@ class MyCompiler: public Compiler {
|
|||||||
unsigned scale = 1,
|
unsigned scale = 1,
|
||||||
TraceHandler* traceHandler = 0)
|
TraceHandler* traceHandler = 0)
|
||||||
{
|
{
|
||||||
return memory(&c, base, displacement, index, scale, traceHandler);
|
return operand
|
||||||
|
(&c, memory(&c, static_cast<MyOperand*>(base), displacement,
|
||||||
|
static_cast<MyOperand*>(index), scale, traceHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* stack() {
|
virtual Operand* stack() {
|
||||||
return register_(&c, rsp);
|
return operand(&c, BytesPerWord, register_(&c, c.machine->stack()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* base() {
|
virtual Operand* base() {
|
||||||
return register_(&c, rbp);
|
return operand(&c, BytesPerWord, register_(&c, c.machine->base()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* thread() {
|
virtual Operand* thread() {
|
||||||
return register_(&c, rbx);
|
return operand(&c, BytesPerWord, register_(&c, c.machine->thread()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* label() {
|
virtual Operand* label() {
|
||||||
return address(&c, 0);
|
return operand(&c, BytesPerWord, ::constant(&c, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise* machineIp() {
|
Promise* machineIp() {
|
||||||
return c.event->promises = new (c.zone->allocate(sizeof(CodePromise)))
|
return c.event->promises = new (c.zone->allocate(sizeof(CodePromise)))
|
||||||
CodePromise(c.event->promises);
|
CodePromise(&c, c.event->promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void mark(Operand* label) {
|
virtual void mark(Operand* label) {
|
||||||
static_cast<MyOperand*>(label)->setLabelValue
|
static_cast<ConstantValue*>(static_cast<MyOperand*>(label))->value
|
||||||
(&c, static_cast<MyPromise*>(machineIp()));
|
= machineIp();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void push(Operand* value) {
|
virtual void push(Operand* value) {
|
||||||
@ -1033,7 +1190,7 @@ class MyCompiler: public Compiler {
|
|||||||
(argumentFootprint > GprParameterCount ?
|
(argumentFootprint > GprParameterCount ?
|
||||||
argumentFootprint - GprParameterCount : 0) : argumentFootprint);
|
argumentFootprint - GprParameterCount : 0) : argumentFootprint);
|
||||||
|
|
||||||
MyOperand* result = operand(&c, resultSize);
|
MyOperand* result = operand(&c, resultSize, 0);
|
||||||
appendCall(&c, static_cast<MyOperand*>(address), result, stackOffset,
|
appendCall(&c, static_cast<MyOperand*>(address), result, stackOffset,
|
||||||
alignCall, traceHandler);
|
alignCall, traceHandler);
|
||||||
return result;
|
return result;
|
||||||
@ -1230,29 +1387,18 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned poolSize() {
|
virtual unsigned poolSize() {
|
||||||
return c.constantPool.length();
|
return c.constantCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void writeTo(uint8_t* dst) {
|
virtual void writeTo(uint8_t* dst) {
|
||||||
c.code.wrap(dst, codeSize());
|
c.assembler->writeTo(dst);
|
||||||
writeCode(&c);
|
|
||||||
|
|
||||||
for (Constant* n = c.constantPool.front(); n; n = n->next) {
|
for (Constant* n = c.firstConstant; n; n = n->next) {
|
||||||
*reinterpret_cast<intptr_t*>(dst + c.codeLength + i)
|
*reinterpret_cast<intptr_t*>(dst + c.code.length() + i)
|
||||||
= n->promise->value(this);
|
= n->promise->value(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateCall(void* returnAddress, void* newTarget) {
|
|
||||||
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
|
||||||
assert(&c, *instruction == 0xE8);
|
|
||||||
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
|
||||||
|
|
||||||
int32_t v = static_cast<uint8_t*>(newTarget)
|
|
||||||
- static_cast<uint8_t*>(returnAddress);
|
|
||||||
memcpy(instruction + 1, &v, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
c.dispose();
|
c.dispose();
|
||||||
}
|
}
|
||||||
@ -1265,11 +1411,10 @@ class MyCompiler: public Compiler {
|
|||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Compiler*
|
Compiler*
|
||||||
makeCompiler(System* system, Allocator* allocator, Zone* zone,
|
makeCompiler(System* system, Zone* zone)
|
||||||
void* indirectCaller)
|
|
||||||
{
|
{
|
||||||
return new (zone->allocate(sizeof(MyCompiler)))
|
return new (zone->allocate(sizeof(MyCompiler)))
|
||||||
MyCompiler(system, allocator, zone, indirectCaller);
|
MyCompiler(system, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace v
|
} // namespace vm
|
||||||
|
155
src/x86.cpp
Normal file
155
src/x86.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#include "assembler.h"
|
||||||
|
|
||||||
|
using namespace vm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Task {
|
||||||
|
public:
|
||||||
|
virtual void run(uint8_t* code) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyAssembler: public Assembler {
|
||||||
|
public:
|
||||||
|
MyAssembler(System* s): s(s), code(s, s, 1024), tasks(0) { }
|
||||||
|
|
||||||
|
virtual unsigned registerCount() {
|
||||||
|
return BytesPerWord == 4 ? 8 : 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int base() {
|
||||||
|
return rbp;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int stack() {
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int thread() {
|
||||||
|
return rbx;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int returnLow() {
|
||||||
|
return rax;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int returnHigh() {
|
||||||
|
return (BytesPerWord == 4 ? rdx : NoRegister);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned argumentRegisterCount() {
|
||||||
|
return (BytesPerWord == 4 ? 0 : 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int argumentRegister(unsigned index) {
|
||||||
|
assert(s, BytesPerWord == 8);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int stackSyncRegister(unsigned index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return rax;
|
||||||
|
case 1:
|
||||||
|
return rcx;
|
||||||
|
case 2:
|
||||||
|
return rdx;
|
||||||
|
case 3:
|
||||||
|
return rsi;
|
||||||
|
case 4:
|
||||||
|
return rdi;
|
||||||
|
default:
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getTargets(OperationType op, unsigned size,
|
||||||
|
int* aLow, int* aHigh,
|
||||||
|
int* bLow, int* bHigh)
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
*aLow = NoRegister;
|
||||||
|
*aHigh = NoRegister;
|
||||||
|
*bLow = NoRegister;
|
||||||
|
*bHigh = NoRegister;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(Operation op) {
|
||||||
|
// todo
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(UnaryOperation op, unsigned size, OperandType type,
|
||||||
|
Operand* operand)
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(BinaryOperation op, unsigned size, OperandType aType,
|
||||||
|
OperandType bType, Operand* a, Operand* b)
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
abort(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void writeTo(uint8_t* dst) {
|
||||||
|
memcpy(dst, code.data, code.length());
|
||||||
|
|
||||||
|
for (Task* t = tasks; t; t = t->next) {
|
||||||
|
t->run(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System* s;
|
||||||
|
Vector code;
|
||||||
|
Task* tasks;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
|
||||||
|
Assembler*
|
||||||
|
makeAssembler(System* system, Zone* zone)
|
||||||
|
{
|
||||||
|
return new (zone->allocate(sizeof(MyAssembler)))
|
||||||
|
MyAssembler(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vm
|
Loading…
x
Reference in New Issue
Block a user