mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +00:00
more JIT compiler progress
This commit is contained in:
parent
5b5a4fe8d7
commit
f8cda0cd85
6
makefile
6
makefile
@ -161,6 +161,12 @@ interpreter-sources = \
|
|||||||
interpreter-asm-sources = $(src)/$(asm).S
|
interpreter-asm-sources = $(src)/$(asm).S
|
||||||
|
|
||||||
ifeq ($(process),compile)
|
ifeq ($(process),compile)
|
||||||
|
interpreter-depends += \
|
||||||
|
$(src)/compiler.h \
|
||||||
|
$(src)/vector.h
|
||||||
|
|
||||||
|
interpreter-sources += $(src)/compiler.cpp
|
||||||
|
|
||||||
interpreter-asm-sources += $(src)/compile.S
|
interpreter-asm-sources += $(src)/compile.S
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
7475
src/compile.cpp
7475
src/compile.cpp
File diff suppressed because it is too large
Load Diff
3673
src/compile2.cpp
3673
src/compile2.cpp
File diff suppressed because it is too large
Load Diff
427
src/compiler.cpp
427
src/compiler.cpp
@ -5,6 +5,25 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
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 IpMapping {
|
class IpMapping {
|
||||||
public:
|
public:
|
||||||
IpMapping(unsigned ip, unsigned offset): ip(ip), offset(offset) { }
|
IpMapping(unsigned ip, unsigned offset): ip(ip), offset(offset) { }
|
||||||
@ -24,7 +43,8 @@ class Context {
|
|||||||
constantPool(s, BytesPerWord * 32),
|
constantPool(s, BytesPerWord * 32),
|
||||||
registerPool(s, BytesPerWord * 8),
|
registerPool(s, BytesPerWord * 8),
|
||||||
promises(s, 1024),
|
promises(s, 1024),
|
||||||
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller))
|
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
|
||||||
|
stackIndex(- BytesPerWord)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -39,13 +59,14 @@ class Context {
|
|||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
Vector code;
|
Vector code;
|
||||||
Vector<MyOperand*> virtualStack;
|
Vector virtualStack;
|
||||||
Vector operands;
|
Vector operands;
|
||||||
Vector<IpMapping> ipTable;
|
Vector ipTable;
|
||||||
Vector<MyOperand*> constantPool;
|
Vector constantPool;
|
||||||
Vector<MyOperand*> registerPool;
|
Vector registerPool;
|
||||||
Vector promises;
|
Vector promises;
|
||||||
intptr_t indirectCaller;
|
intptr_t indirectCaller;
|
||||||
|
int stackIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void NO_RETURN
|
inline void NO_RETURN
|
||||||
@ -65,7 +86,7 @@ assert(Context* c, bool v)
|
|||||||
inline void
|
inline void
|
||||||
expect(Context* c, bool v)
|
expect(Context* c, bool v)
|
||||||
{
|
{
|
||||||
expect(c->system, v);
|
expect(c->s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyPromise: public Promise {
|
class MyPromise: public Promise {
|
||||||
@ -78,7 +99,7 @@ class MyPromise: public Promise {
|
|||||||
|
|
||||||
MyPromise(intptr_t value): resolved(false), value_(value) { }
|
MyPromise(intptr_t value): resolved(false), value_(value) { }
|
||||||
|
|
||||||
virtual unsigned value(System* s) {
|
virtual unsigned value(System* s UNUSED) {
|
||||||
assert(s, resolved);
|
assert(s, resolved);
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
@ -100,7 +121,7 @@ class PoolPromise: public MyPromise {
|
|||||||
|
|
||||||
class CodePromise: public MyPromise {
|
class CodePromise: public MyPromise {
|
||||||
public:
|
public:
|
||||||
PoolPromise(intptr_t value): MyPromise(value) { }
|
CodePromise(intptr_t value): MyPromise(value) { }
|
||||||
|
|
||||||
virtual PromiseType type() {
|
virtual PromiseType type() {
|
||||||
return CodePromiseType;
|
return CodePromiseType;
|
||||||
@ -109,7 +130,7 @@ class CodePromise: public MyPromise {
|
|||||||
|
|
||||||
class IpPromise: public MyPromise {
|
class IpPromise: public MyPromise {
|
||||||
public:
|
public:
|
||||||
PoolPromise(intptr_t value): MyPromise(value) { }
|
IpPromise(intptr_t value): MyPromise(value) { }
|
||||||
|
|
||||||
virtual PromiseType type() {
|
virtual PromiseType type() {
|
||||||
return IpPromiseType;
|
return IpPromiseType;
|
||||||
@ -120,8 +141,10 @@ class MyOperand: public Operand {
|
|||||||
public:
|
public:
|
||||||
enum OperandType {
|
enum OperandType {
|
||||||
ImmediateOperandType,
|
ImmediateOperandType,
|
||||||
|
AbsoluteOperandType,
|
||||||
RegisterOperandType,
|
RegisterOperandType,
|
||||||
MemoryOperandType
|
MemoryOperandType,
|
||||||
|
SelectionOperandType
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~MyOperand() { }
|
virtual ~MyOperand() { }
|
||||||
@ -136,10 +159,16 @@ class MyOperand: public Operand {
|
|||||||
|
|
||||||
virtual void push(Context* c) { abort(c); }
|
virtual void push(Context* c) { abort(c); }
|
||||||
|
|
||||||
|
virtual void pop(Context* c) { abort(c); }
|
||||||
|
|
||||||
virtual void mov(Context* c, MyOperand*) { abort(c); }
|
virtual void mov(Context* c, MyOperand*) { abort(c); }
|
||||||
|
|
||||||
virtual void cmp(Context* c, MyOperand*) { abort(c); }
|
virtual void cmp(Context* c, MyOperand*) { abort(c); }
|
||||||
|
|
||||||
|
virtual void call(Context* c) { abort(c); }
|
||||||
|
|
||||||
|
virtual void alignedCall(Context* c) { abort(c); }
|
||||||
|
|
||||||
virtual void jl(Context* c) { abort(c); }
|
virtual void jl(Context* c) { abort(c); }
|
||||||
|
|
||||||
virtual void jg(Context* c) { abort(c); }
|
virtual void jg(Context* c) { abort(c); }
|
||||||
@ -179,6 +208,141 @@ class MyOperand: public Operand {
|
|||||||
virtual void neg(Context* c) { abort(c); }
|
virtual void neg(Context* c) { abort(c); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
isInt8(intptr_t v)
|
||||||
|
{
|
||||||
|
return v == static_cast<int8_t>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
isInt32(intptr_t v)
|
||||||
|
{
|
||||||
|
return v == static_cast<int32_t>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Register
|
||||||
|
registerValue(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
Promise*
|
||||||
|
absoluteValue(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
void
|
||||||
|
setAbsoluteValue(Context* c, MyOperand* v, Promise* value);
|
||||||
|
|
||||||
|
MyOperand*
|
||||||
|
memoryBase(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
int
|
||||||
|
memoryDisplacement(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
MyOperand*
|
||||||
|
memoryIndex(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
memoryScale(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
Register
|
||||||
|
asRegister(Context* c, MyOperand* v);
|
||||||
|
|
||||||
|
void
|
||||||
|
rex(Context* c)
|
||||||
|
{
|
||||||
|
if (BytesPerWord == 8) {
|
||||||
|
c->code.append(0x48);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ret(Context* c)
|
||||||
|
{
|
||||||
|
c->code.append(0xc3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encode(Context* c, uint8_t instruction, uint8_t zeroPrefix,
|
||||||
|
uint8_t bytePrefix, uint8_t wordPrefix,
|
||||||
|
Register a, Register b, int32_t offset)
|
||||||
|
{
|
||||||
|
c->code.append(instruction);
|
||||||
|
|
||||||
|
uint8_t prefix;
|
||||||
|
if (offset == 0 and b != rbp) {
|
||||||
|
prefix = zeroPrefix;
|
||||||
|
} else if (isInt8(offset)) {
|
||||||
|
prefix = bytePrefix;
|
||||||
|
} else {
|
||||||
|
prefix = wordPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->code.append(prefix | (a << 3) | b);
|
||||||
|
|
||||||
|
if (b == rsp) {
|
||||||
|
c->code.append(0x24);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == 0 and b != rbp) {
|
||||||
|
// do nothing
|
||||||
|
} else if (isInt8(offset)) {
|
||||||
|
c->code.append(offset);
|
||||||
|
} else {
|
||||||
|
c->code.append4(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RegisterOperand: public MyOperand {
|
||||||
|
public:
|
||||||
|
RegisterOperand(Register value):
|
||||||
|
value(value)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual OperandType type() {
|
||||||
|
return RegisterOperandType;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned size() {
|
||||||
|
return sizeof(RegisterOperand);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void push(Context* c) {
|
||||||
|
c->code.append(0x50 | value);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void mov(Context* c, MyOperand* dst) {
|
||||||
|
switch (dst->type()) {
|
||||||
|
case RegisterOperandType:
|
||||||
|
if (value != registerValue(c, dst)) {
|
||||||
|
rex(c);
|
||||||
|
c->code.append(0x89);
|
||||||
|
c->code.append(0xc0 | (value << 3) | registerValue(c, dst));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MemoryOperandType:
|
||||||
|
rex(c);
|
||||||
|
encode(c, 0x89, 0, 0x40, 0x80, value,
|
||||||
|
asRegister(c, memoryBase(c, dst)),
|
||||||
|
memoryDisplacement(c, dst));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: abort(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Register value;
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterOperand*
|
||||||
|
temporary(Context* c)
|
||||||
|
{
|
||||||
|
return c->registerPool.pop<RegisterOperand*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release(Context* c, RegisterOperand* v)
|
||||||
|
{
|
||||||
|
c->registerPool.push(v);
|
||||||
|
}
|
||||||
|
|
||||||
class ImmediateOperand: public MyOperand {
|
class ImmediateOperand: public MyOperand {
|
||||||
public:
|
public:
|
||||||
ImmediateOperand(intptr_t value):
|
ImmediateOperand(intptr_t value):
|
||||||
@ -219,9 +383,9 @@ class ImmediateOperand: public MyOperand {
|
|||||||
case MemoryOperandType:
|
case MemoryOperandType:
|
||||||
rex(c);
|
rex(c);
|
||||||
encode(c, 0xc7, 0, 0x40, 0x80, rax,
|
encode(c, 0xc7, 0, 0x40, 0x80, rax,
|
||||||
asRegister(memoryBase(c, dst)),
|
asRegister(c, memoryBase(c, dst)),
|
||||||
memoryDisplacement(c, dst));
|
memoryDisplacement(c, dst));
|
||||||
c->code.append4(v);
|
c->code.append4(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: abort(c);
|
default: abort(c);
|
||||||
@ -248,98 +412,13 @@ class AbsoluteOperand: public MyOperand {
|
|||||||
Promise* value;
|
Promise* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegisterOperand: public MyOperand {
|
|
||||||
public:
|
|
||||||
RegisterOperand(Register value):
|
|
||||||
value(value)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual OperandType type() {
|
|
||||||
return RegisterOperandType;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual unsigned size() {
|
|
||||||
return sizeof(RegisterOperand);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void push(Context* c) {
|
|
||||||
c->code.append(0x50 | value);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void mov(Context* c, MyOperand* dst) {
|
|
||||||
switch (dst->type()) {
|
|
||||||
case RegisterOperandType:
|
|
||||||
if (value != registerValue(c, dst)) {
|
|
||||||
rex(c);
|
|
||||||
c->code.append(0x89);
|
|
||||||
c->code.append(0xc0 | (value << 3) | registerValue(c, dst));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MemoryOperandType:
|
|
||||||
rex(c);
|
|
||||||
encode(c, 0x89, 0, 0x40, 0x80, src,
|
|
||||||
asRegister(memoryBase(c, dst)),
|
|
||||||
memoryDisplacement(c, dst));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: abort(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Register value;
|
|
||||||
};
|
|
||||||
|
|
||||||
RegisterOperand*
|
|
||||||
temporary(Context* c)
|
|
||||||
{
|
|
||||||
return c->registerPool.pop<RegisterOperand*>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
release(Context* c, RegisterOperand* v)
|
|
||||||
{
|
|
||||||
return c->registerPool.push(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
encode(Context* c, uint8_t instruction, uint8_t zeroPrefix,
|
|
||||||
uint8_t bytePrefix, uint8_t wordPrefix,
|
|
||||||
Register a, Register b, int32_t offset)
|
|
||||||
{
|
|
||||||
c->code.append(instruction);
|
|
||||||
|
|
||||||
uint8_t prefix;
|
|
||||||
if (offset == 0 and b != rbp) {
|
|
||||||
prefix = zeroPrefix;
|
|
||||||
} else if (isByte(offset)) {
|
|
||||||
prefix = bytePrefix;
|
|
||||||
} else {
|
|
||||||
prefix = wordPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->code.append(prefix | (a << 3) | b);
|
|
||||||
|
|
||||||
if (b == rsp) {
|
|
||||||
c->code.append(0x24);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset == 0 and b != rbp) {
|
|
||||||
// do nothing
|
|
||||||
} else if (isInt8(offset)) {
|
|
||||||
c->code.append(offset);
|
|
||||||
} else {
|
|
||||||
c->code.append4(offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Register
|
Register
|
||||||
asRegister(Context* c, MyOperand* v)
|
asRegister(Context* c, MyOperand* v)
|
||||||
{
|
{
|
||||||
if (v->type() == RegisterOperandType) {
|
if (v->type() == MyOperand::RegisterOperandType) {
|
||||||
return registerValue(v);
|
return registerValue(c, v);
|
||||||
} else {
|
} else {
|
||||||
assert(c, v->type() == MemoryOperandType);
|
assert(c, v->type() == MyOperand::MemoryOperandType);
|
||||||
|
|
||||||
RegisterOperand* tmp = temporary(c);
|
RegisterOperand* tmp = temporary(c);
|
||||||
v->mov(c, tmp);
|
v->mov(c, tmp);
|
||||||
@ -383,7 +462,7 @@ class MemoryOperand: public MyOperand {
|
|||||||
case RegisterOperandType:
|
case RegisterOperandType:
|
||||||
rex(c);
|
rex(c);
|
||||||
encode(c, 0x8b, 0, 0x40, 0x80, registerValue(c, dst),
|
encode(c, 0x8b, 0, 0x40, 0x80, registerValue(c, dst),
|
||||||
base, displacement);
|
asRegister(c, base), displacement);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MemoryOperandType: {
|
case MemoryOperandType: {
|
||||||
@ -393,7 +472,7 @@ class MemoryOperand: public MyOperand {
|
|||||||
release(c, tmp);
|
release(c, tmp);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,8 +499,16 @@ class StackOperand: public MemoryOperand {
|
|||||||
|
|
||||||
class SelectionOperand: public MyOperand {
|
class SelectionOperand: public MyOperand {
|
||||||
public:
|
public:
|
||||||
SelectionOperand(Compiler::SelectionType type, MyOperand* base):
|
enum SelectionType {
|
||||||
type(type), base(base)
|
S1Selection,
|
||||||
|
S2Selection,
|
||||||
|
Z2Selection,
|
||||||
|
S4Selection,
|
||||||
|
S8Selection
|
||||||
|
};
|
||||||
|
|
||||||
|
SelectionOperand(SelectionType type, MyOperand* base):
|
||||||
|
selectionType(type), base(base)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual OperandType type() {
|
virtual OperandType type() {
|
||||||
@ -429,7 +516,7 @@ class SelectionOperand: public MyOperand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned footprint() {
|
virtual unsigned footprint() {
|
||||||
if (type == Compiler::S8Selection) {
|
if (selectionType == S8Selection) {
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
return 4;
|
return 4;
|
||||||
@ -440,7 +527,7 @@ class SelectionOperand: public MyOperand {
|
|||||||
return sizeof(SelectionOperand);
|
return sizeof(SelectionOperand);
|
||||||
}
|
}
|
||||||
|
|
||||||
Compiler::SelectionType type;
|
SelectionType selectionType;
|
||||||
MyOperand* base;
|
MyOperand* base;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -451,7 +538,7 @@ immediate(Context* c, intptr_t v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AbsoluteOperand*
|
AbsoluteOperand*
|
||||||
absolute(Context* c, intptr_t v)
|
absolute(Context* c, Promise* v)
|
||||||
{
|
{
|
||||||
return c->operands.push(AbsoluteOperand(v));
|
return c->operands.push(AbsoluteOperand(v));
|
||||||
}
|
}
|
||||||
@ -476,10 +563,10 @@ stack(Context* c, int displacement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MyOperand*
|
MyOperand*
|
||||||
selection(Context* c, Compiler::SelectionType type, MyOperand* base)
|
selection(Context* c, SelectionOperand::SelectionType type, MyOperand* base)
|
||||||
{
|
{
|
||||||
if ((type == S4Selection and BytesPerWord == 4)
|
if ((type == SelectionOperand::S4Selection and BytesPerWord == 4)
|
||||||
or (type == S8Selection and BytesPerWord == 8))
|
or (type == SelectionOperand::S8Selection and BytesPerWord == 8))
|
||||||
{
|
{
|
||||||
return base;
|
return base;
|
||||||
} else {
|
} else {
|
||||||
@ -488,18 +575,18 @@ selection(Context* c, Compiler::SelectionType type, MyOperand* base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isStackReference(Context* c, MyOperand* v)
|
isStackReference(Context*, MyOperand* v)
|
||||||
{
|
{
|
||||||
return v->type() == MemoryOperandType
|
return v->type() == MyOperand::MemoryOperandType
|
||||||
and static_cast<MemoryOperand*>(v)->isStackReference();
|
and static_cast<MemoryOperand*>(v)->isStackReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flushStack(Context* c)
|
flushStack(Context* c)
|
||||||
{
|
{
|
||||||
Stack newVirtualStack;
|
Vector newVirtualStack(c->s, c->virtualStack.length() * 2);
|
||||||
for (unsigned i = 0; i < c->virtualStack.length();) {
|
for (unsigned i = 0; i < c->virtualStack.length();) {
|
||||||
MyOperand* v = c->virtualStack.peek<MyOperand*>(i);
|
MyOperand* v = c->virtualStack.peek<MyOperand>(i);
|
||||||
|
|
||||||
if (not isStackReference(c, v)) {
|
if (not isStackReference(c, v)) {
|
||||||
v->push(c);
|
v->push(c);
|
||||||
@ -510,13 +597,30 @@ flushStack(Context* c)
|
|||||||
newVirtualStack.push(stack(c, c->stackIndex));
|
newVirtualStack.push(stack(c, c->stackIndex));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newVirtualStack.push(v, v->size());
|
newVirtualStack.append(v, v->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
i += v->size();
|
i += v->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
c->virtualStack.swap(&newVirtualStack);
|
c->virtualStack.update(&newVirtualStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = count - 1; i >= 0; --i) {
|
||||||
|
arguments[i]->push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return footprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyCompiler: public Compiler {
|
class MyCompiler: public Compiler {
|
||||||
@ -526,16 +630,17 @@ class MyCompiler: public Compiler {
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual Promise* poolOffset() {
|
virtual Promise* poolOffset() {
|
||||||
return c.promises.push(PoolPromise(constantPool.length() / BytesPerWord));
|
return c.promises.push
|
||||||
|
(PoolPromise(c.constantPool.length() / BytesPerWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* codeOffset() {
|
virtual Promise* codeOffset() {
|
||||||
return c.promises.push(CodePromise(code.length()));
|
return c.promises.push(CodePromise(c.code.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* poolAppend(Operand* v) {
|
virtual Operand* poolAppend(Operand* v) {
|
||||||
Operand* r = absolute(&c, poolOffset());
|
Operand* r = absolute(&c, poolOffset());
|
||||||
constantPool.push(static_cast<MyOperand*>(v));
|
c.constantPool.push(static_cast<MyOperand*>(v));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,15 +658,16 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* stack(unsigned index) {
|
virtual Operand* stack(unsigned index) {
|
||||||
return c.virtualStack.peek(stack.size() - index - 1);
|
return c.virtualStack.peek<MyOperand>
|
||||||
|
(c.virtualStack.length() - ((index + 1) * BytesPerWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* stack2(unsigned index) {
|
virtual Operand* stack2(unsigned index) {
|
||||||
return c.virtualStack.peek(stack.size() - index - 1);
|
return stack(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* pop() {
|
virtual Operand* pop() {
|
||||||
return pop(c);
|
return c.virtualStack.pop<MyOperand*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* pop2() {
|
virtual Operand* pop2() {
|
||||||
@ -570,7 +676,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void pop(Operand* dst) {
|
virtual void pop(Operand* dst) {
|
||||||
pop(c)->mov(&c, static_cast<MyOperand*>(dst));
|
c.virtualStack.pop<MyOperand*>()->mov(&c, static_cast<MyOperand*>(dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pop2(Operand* dst) {
|
virtual void pop2(Operand* dst) {
|
||||||
@ -628,45 +734,49 @@ class MyCompiler: public Compiler {
|
|||||||
(Operand* address, unsigned argumentCount, ...)
|
(Operand* address, unsigned argumentCount, ...)
|
||||||
{
|
{
|
||||||
va_list a; va_start(a, argumentCount);
|
va_list a; va_start(a, argumentCount);
|
||||||
pushArguments(&c, argumentCount, a);
|
unsigned footprint = pushArguments(&c, argumentCount, a);
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
static_cast<MyOperand*>(address)->mov(&c, register_(rax));
|
static_cast<MyOperand*>(address)->mov(&c, register_(&c, rax));
|
||||||
immediate(&c, indirectCaller)->call(&c);
|
immediate(&c, c.indirectCaller)->call(&c);
|
||||||
|
|
||||||
popArguments(&c, argumentCount);
|
immediate(&c, footprint)->sub(&c, register_(&c, rsp));
|
||||||
|
|
||||||
|
return register_(&c, rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* indirectCallNoReturn
|
virtual void indirectCallNoReturn
|
||||||
(Operand* address, unsigned argumentCount, ...)
|
(Operand* address, unsigned argumentCount, ...)
|
||||||
{
|
{
|
||||||
va_list a; va_start(a, argumentCount);
|
va_list a; va_start(a, argumentCount);
|
||||||
pushArguments(&c, argumentCount, a);
|
pushArguments(&c, argumentCount, a);
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
static_cast<MyOperand*>(address)->mov(&c, register_(rax));
|
static_cast<MyOperand*>(address)->mov(&c, register_(&c, rax));
|
||||||
immediate(&c, indirectCaller)->call(&c);
|
immediate(&c, c.indirectCaller)->call(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* directCall
|
virtual Operand* directCall
|
||||||
(Operand* address, unsigned argumentCount, ...)
|
(Operand* address, unsigned argumentCount, ...)
|
||||||
{
|
{
|
||||||
va_list a; va_start(a, argumentCount);
|
va_list a; va_start(a, argumentCount);
|
||||||
pushArguments(&c, argumentCount, a);
|
unsigned footprint = pushArguments(&c, argumentCount, a);
|
||||||
va_end(a);
|
va_end(a);
|
||||||
|
|
||||||
static_cast<MyOperand*>(address)->call(&c);
|
static_cast<MyOperand*>(address)->call(&c);
|
||||||
|
|
||||||
popArguments(&c, argumentCount);
|
immediate(&c, footprint)->sub(&c, register_(&c, rsp));
|
||||||
|
|
||||||
|
return register_(&c, rax);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void return_(Operand* v) {
|
virtual void return_(Operand* v) {
|
||||||
static_cast<MyOperand*>(v)->mov(&c, register_(rax));
|
static_cast<MyOperand*>(v)->mov(&c, register_(&c, rax));
|
||||||
ret(c);
|
ret();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ret() {
|
virtual void ret() {
|
||||||
ret(c);
|
::ret(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void mov(Operand* src, Operand* dst) {
|
virtual void mov(Operand* src, Operand* dst) {
|
||||||
@ -757,11 +867,33 @@ class MyCompiler: public Compiler {
|
|||||||
virtual Operand* memory(Operand* base, int displacement,
|
virtual Operand* memory(Operand* base, int displacement,
|
||||||
Operand* index, unsigned scale)
|
Operand* index, unsigned scale)
|
||||||
{
|
{
|
||||||
return memory(&c, base, displacement, index, scale);
|
return ::memory(&c, static_cast<MyOperand*>(base), displacement,
|
||||||
|
static_cast<MyOperand*>(index), scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* select(SelectionType type, Operand* v) {
|
virtual Operand* select1(Operand* v) {
|
||||||
return selection(&c, type, v);
|
return selection(&c, SelectionOperand::S1Selection,
|
||||||
|
static_cast<MyOperand*>(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Operand* select2(Operand* v) {
|
||||||
|
return selection(&c, SelectionOperand::S2Selection,
|
||||||
|
static_cast<MyOperand*>(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Operand* select2z(Operand* v) {
|
||||||
|
return selection(&c, SelectionOperand::Z2Selection,
|
||||||
|
static_cast<MyOperand*>(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Operand* select4(Operand* v) {
|
||||||
|
return selection(&c, SelectionOperand::S4Selection,
|
||||||
|
static_cast<MyOperand*>(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Operand* select8(Operand* v) {
|
||||||
|
return selection(&c, SelectionOperand::S8Selection,
|
||||||
|
static_cast<MyOperand*>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void prologue() {
|
virtual void prologue() {
|
||||||
@ -775,19 +907,20 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void startLogicalIp(unsigned ip) {
|
virtual void startLogicalIp(unsigned ip) {
|
||||||
c.ipTable.push(IpMapping(ip, code.length()));
|
c.ipTable.push(IpMapping(ip, c.code.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* logicalIp(unsigned ip) {
|
virtual Operand* logicalIp(unsigned ip) {
|
||||||
return absolute(&c, promises.push(IpPromise(ip)));
|
return absolute(&c, c.promises.push(IpPromise(ip)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned logicalIpToOffset(unsigned ip) {
|
virtual unsigned logicalIpToOffset(unsigned ip) {
|
||||||
unsigned bottom = 0;
|
unsigned bottom = 0;
|
||||||
unsigned top = c.ipTable.size();
|
unsigned top = c.ipTable.length() / sizeof(IpMapping);
|
||||||
for (unsigned span = top - bottom; span; span = top - bottom) {
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
||||||
unsigned middle = bottom + (span / 2);
|
unsigned middle = bottom + (span / 2);
|
||||||
IpMapping* mapping = c.ipTable.get(middle);
|
IpMapping* mapping = c.ipTable.peek<IpMapping>
|
||||||
|
(middle * sizeof(IpMapping));
|
||||||
|
|
||||||
if (ip == mapping->ip) {
|
if (ip == mapping->ip) {
|
||||||
return mapping->offset;
|
return mapping->offset;
|
||||||
@ -798,25 +931,25 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abort(s);
|
abort(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned size() {
|
virtual unsigned size() {
|
||||||
return c.code.length();
|
return c.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void writeTo(void* out) {
|
virtual void writeTo(void*) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateCall(void* returnAddress, void* newTarget) {
|
virtual void updateCall(void*, void*) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
c.dispose();
|
c.dispose();
|
||||||
|
|
||||||
s->free(this);
|
c.s->free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context c;
|
Context c;
|
||||||
|
@ -16,14 +16,6 @@ class Promise {
|
|||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
enum SelectionType {
|
|
||||||
S1Selection,
|
|
||||||
S2Selection,
|
|
||||||
Z2Selection,
|
|
||||||
S4Selection,
|
|
||||||
S8Selection
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~Compiler() { }
|
virtual ~Compiler() { }
|
||||||
|
|
||||||
virtual Promise* poolOffset() = 0;
|
virtual Promise* poolOffset() = 0;
|
||||||
@ -56,7 +48,7 @@ class Compiler {
|
|||||||
virtual Operand* alignedCall(Operand*) = 0;
|
virtual Operand* alignedCall(Operand*) = 0;
|
||||||
virtual Operand* indirectCall
|
virtual Operand* indirectCall
|
||||||
(Operand* address, unsigned argumentCount, ...) = 0;
|
(Operand* address, unsigned argumentCount, ...) = 0;
|
||||||
virtual Operand* indirectCallNoReturn
|
virtual void indirectCallNoReturn
|
||||||
(Operand* address, unsigned argumentCount, ...) = 0;
|
(Operand* address, unsigned argumentCount, ...) = 0;
|
||||||
virtual Operand* directCall
|
virtual Operand* directCall
|
||||||
(Operand* address, unsigned argumentCount, ...) = 0;
|
(Operand* address, unsigned argumentCount, ...) = 0;
|
||||||
@ -89,7 +81,11 @@ class Compiler {
|
|||||||
virtual Operand* memory(Operand* base, int displacement = 0,
|
virtual Operand* memory(Operand* base, int displacement = 0,
|
||||||
Operand* index = 0, unsigned scale = 1) = 0;
|
Operand* index = 0, unsigned scale = 1) = 0;
|
||||||
|
|
||||||
virtual Operand* select(SelectionType, Operand*) = 0;
|
virtual Operand* select1(Operand*) = 0;
|
||||||
|
virtual Operand* select2(Operand*) = 0;
|
||||||
|
virtual Operand* select2z(Operand*) = 0;
|
||||||
|
virtual Operand* select4(Operand*) = 0;
|
||||||
|
virtual Operand* select8(Operand*) = 0;
|
||||||
|
|
||||||
virtual void prologue() = 0;
|
virtual void prologue() = 0;
|
||||||
virtual void epilogue() = 0;
|
virtual void epilogue() = 0;
|
||||||
|
5198
src/old-compile.cpp
Normal file
5198
src/old-compile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
47
src/vector.h
47
src/vector.h
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
template <class T = uint8_t>
|
|
||||||
class Vector {
|
class Vector {
|
||||||
public:
|
public:
|
||||||
Vector(System* s, unsigned minimumCapacity):
|
Vector(System* s, unsigned minimumCapacity):
|
||||||
@ -40,15 +39,13 @@ class Vector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void get(unsigned offset, void* dst, unsigned size) {
|
void get(unsigned offset, void* dst, unsigned size) {
|
||||||
assert(s, offset >= 0);
|
|
||||||
assert(s, offset + size <= position);
|
assert(s, offset + size <= position);
|
||||||
mempcy(dst, data + offset, size);
|
memcpy(dst, data + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(unsigned offset, const void* src, unsigned size) {
|
void set(unsigned offset, const void* src, unsigned size) {
|
||||||
assert(s, offset >= 0);
|
|
||||||
assert(s, offset + size <= position);
|
assert(s, offset + size <= position);
|
||||||
mempcy(data + offset, src, size);
|
memcpy(data + offset, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop(void* dst, unsigned size) {
|
void pop(void* dst, unsigned size) {
|
||||||
@ -56,14 +53,19 @@ class Vector {
|
|||||||
position -= size;
|
position -= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* append(const void* p, unsigned size) {
|
void* allocate(unsigned size) {
|
||||||
ensure(size);
|
ensure(size);
|
||||||
void* r = data + position;
|
void* r = data + position;
|
||||||
memcpy(r, p, size);
|
|
||||||
position += size;
|
position += size;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* append(const void* p, unsigned size) {
|
||||||
|
void* r = allocate(size);
|
||||||
|
memcpy(r, p, size);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void append(uint8_t v) {
|
void append(uint8_t v) {
|
||||||
append(&v, 1);
|
append(&v, 1);
|
||||||
}
|
}
|
||||||
@ -80,16 +82,35 @@ class Vector {
|
|||||||
append(&v, BytesPerWord);
|
append(&v, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class C = T>
|
unsigned length() {
|
||||||
C* push(const C& v) {
|
return position;
|
||||||
return static_cast<C*>(append(&v, sizeof(C)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class C = T>
|
template <class T>
|
||||||
C pop() {
|
T* peek(unsigned offset) {
|
||||||
C r; pop(&r, sizeof(C));
|
assert(s, offset + sizeof(T) <= position);
|
||||||
|
return reinterpret_cast<T*>(data + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T* push(const T& v) {
|
||||||
|
return static_cast<T*>(append(&v, sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T pop() {
|
||||||
|
T r; pop(&r, sizeof(T));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update(Vector* v) {
|
||||||
|
dispose();
|
||||||
|
|
||||||
|
data = v->data;
|
||||||
|
position = v->position;
|
||||||
|
capacity = v->capacity;
|
||||||
|
minimumCapacity = v->minimumCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
|
Loading…
Reference in New Issue
Block a user