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,
|
|
|
|
};
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
class IpTask {
|
|
|
|
public:
|
2007-12-11 23:52:28 +00:00
|
|
|
enum Priority {
|
|
|
|
LowPriority,
|
|
|
|
HighPriority
|
|
|
|
};
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
IpTask(IpTask* next): next(next) { }
|
|
|
|
|
|
|
|
virtual ~IpTask() { }
|
|
|
|
|
|
|
|
virtual void run(Context* c, unsigned ip, unsigned start, unsigned end,
|
|
|
|
uint8_t* code, unsigned offset) = 0;
|
2007-12-11 23:52:28 +00:00
|
|
|
|
|
|
|
virtual Priority priority() {
|
|
|
|
return LowPriority;
|
|
|
|
}
|
2007-12-11 21:26:59 +00:00
|
|
|
|
|
|
|
IpTask* next;
|
|
|
|
};
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
class IpMapping {
|
|
|
|
public:
|
2007-12-11 21:26:59 +00:00
|
|
|
IpMapping(int ip, int start):
|
|
|
|
ip(ip), start(start), end(-1), task(0)
|
|
|
|
{ }
|
2007-12-11 00:48:09 +00:00
|
|
|
|
|
|
|
const int ip;
|
|
|
|
const int start;
|
|
|
|
int end;
|
2007-12-11 21:26:59 +00:00
|
|
|
IpTask* task;
|
2007-12-11 00:48:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int
|
|
|
|
compareIpMappingPointers(const void* a, const void* b)
|
2007-12-09 20:03:21 +00:00
|
|
|
{
|
2007-12-11 00:48:09 +00:00
|
|
|
return (*static_cast<IpMapping* const*>(a))->ip
|
|
|
|
- (*static_cast<IpMapping* const*>(b))->ip;
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
class MyPromise: public Promise {
|
|
|
|
public:
|
2007-12-11 21:26:59 +00:00
|
|
|
MyPromise(intptr_t key): key(key) { }
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual unsigned value(Compiler*);
|
|
|
|
|
|
|
|
virtual unsigned value(Context*) = 0;
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
intptr_t key;
|
2007-12-09 20:03:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class PoolPromise: public MyPromise {
|
|
|
|
public:
|
2007-12-11 21:26:59 +00:00
|
|
|
PoolPromise(intptr_t key): MyPromise(key) { }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual unsigned value(Context*);
|
2007-12-09 20:03:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class CodePromise: public MyPromise {
|
|
|
|
public:
|
2007-12-11 21:26:59 +00:00
|
|
|
CodePromise(intptr_t key): MyPromise(key) { }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual unsigned value(Context*);
|
2007-12-09 20:03:21 +00:00
|
|
|
};
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
class CodePromiseTask: public IpTask {
|
2007-12-09 20:03:21 +00:00
|
|
|
public:
|
2007-12-11 21:26:59 +00:00
|
|
|
CodePromiseTask(CodePromise* p, IpTask* next): IpTask(next), p(p) { }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual void run(Context*, unsigned, unsigned start, unsigned, uint8_t*,
|
|
|
|
unsigned offset)
|
|
|
|
{
|
|
|
|
p->key = offset + (p->key - start);
|
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual Priority priority() {
|
|
|
|
return HighPriority;
|
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
CodePromise* p;
|
|
|
|
};
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
class IpPromise: public MyPromise {
|
|
|
|
public:
|
|
|
|
IpPromise(intptr_t key): MyPromise(key) { }
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual unsigned value(Context*);
|
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 StackOperand* logicalPush(Context* c) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void logicalFlush(Context*, StackOperand*) { /* ignore */ }
|
2007-12-09 22:45:43 +00:00
|
|
|
|
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
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void setAbsolute(Context* c, intptr_t) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void apply(Context* c, Operation) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void apply(Context* c, Operation, MyOperand*) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void accept(Context* c, Operation, ImmediateOperand*) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual void accept(Context* c, Operation, AbsoluteOperand*) { abort(c); }
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void accept(Context* c, Operation, MemoryOperand*) { abort(c); }
|
2007-12-09 20:03:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class RegisterOperand: public MyOperand {
|
|
|
|
public:
|
|
|
|
RegisterOperand(Register value):
|
2007-12-11 00:48:09 +00:00
|
|
|
value(value), reserved(false), stack(0)
|
2007-12-09 20:03:21 +00:00
|
|
|
{ }
|
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual StackOperand* logicalPush(Context* c);
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void logicalFlush(Context* c UNUSED, StackOperand* s UNUSED) {
|
|
|
|
assert(c, stack == s);
|
|
|
|
stack = 0;
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual Register asRegister(Context*) {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void release(Context* c UNUSED) {
|
|
|
|
assert(c, reserved);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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*);
|
|
|
|
|
2007-12-09 20:03:21 +00:00
|
|
|
Register value;
|
2007-12-11 00:48:09 +00:00
|
|
|
bool reserved;
|
|
|
|
StackOperand* stack;
|
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):
|
|
|
|
value(value)
|
|
|
|
{ }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual StackOperand* logicalPush(Context* c);
|
|
|
|
|
|
|
|
virtual void apply(Context* c, Operation operation);
|
2007-12-09 22:45:43 +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 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class AbsoluteOperand: public MyOperand {
|
|
|
|
public:
|
2007-12-11 00:48:09 +00:00
|
|
|
AbsoluteOperand(MyPromise* value):
|
2007-12-09 22:45:43 +00:00
|
|
|
value(value)
|
|
|
|
{ }
|
|
|
|
|
2007-12-12 00:27:04 +00:00
|
|
|
virtual StackOperand* logicalPush(Context* c);
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual void apply(Context* c, Operation operation);
|
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual void apply(Context* c, Operation operation, MyOperand* operand) {
|
|
|
|
operand->accept(c, operation, this);
|
|
|
|
}
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
virtual void setAbsolute(Context*, intptr_t v) {
|
2007-12-11 21:26:59 +00:00
|
|
|
value->key = v;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
MyPromise* value;
|
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-11 21:26:59 +00:00
|
|
|
virtual StackOperand* logicalPush(Context* c);
|
|
|
|
|
|
|
|
virtual void apply(Context* c, Operation 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
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual void accept(Context*, Operation, RegisterOperand*);
|
|
|
|
virtual void accept(Context*, Operation, ImmediateOperand*);
|
2007-12-12 00:27:04 +00:00
|
|
|
virtual void accept(Context*, Operation, AbsoluteOperand*);
|
2007-12-11 21:26:59 +00:00
|
|
|
|
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
|
|
|
enum SelectionType {
|
|
|
|
S1Selection,
|
|
|
|
S2Selection,
|
|
|
|
Z2Selection,
|
|
|
|
S4Selection,
|
|
|
|
S8Selection
|
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
SelectionType selectionType;
|
|
|
|
MyOperand* base;
|
|
|
|
};
|
|
|
|
|
|
|
|
class StackOperand: public MyOperand {
|
|
|
|
public:
|
|
|
|
StackOperand(MyOperand* base, StackOperand* next):
|
|
|
|
base(base), next(next), flushed(false)
|
|
|
|
{
|
|
|
|
if (next) {
|
|
|
|
index = next->index + (next->footprint() / BytesPerWord);
|
|
|
|
} else {
|
|
|
|
index = 0;
|
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual StackOperand* logicalPush(Context* c) {
|
|
|
|
return base->logicalPush(c);
|
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual void accept(Context* c, Operation operation,
|
|
|
|
RegisterOperand* operand)
|
|
|
|
{
|
|
|
|
base->accept(c, operation, operand);
|
|
|
|
}
|
|
|
|
|
2007-12-09 20:03:21 +00:00
|
|
|
MyOperand* base;
|
2007-12-11 00:48:09 +00:00
|
|
|
StackOperand* next;
|
|
|
|
int index;
|
|
|
|
bool flushed;
|
2007-12-09 20:03:21 +00:00
|
|
|
};
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
class Context {
|
|
|
|
public:
|
|
|
|
Context(System* s, void* indirectCaller):
|
|
|
|
s(s),
|
|
|
|
code(s, 1024),
|
|
|
|
constantPool(s, BytesPerWord * 32),
|
|
|
|
ipMappings(s, 1024),
|
|
|
|
zone(s, 8 * 1024),
|
|
|
|
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
|
|
|
|
stack(0),
|
2007-12-11 21:26:59 +00:00
|
|
|
ipTable(0)
|
2007-12-11 00:48:09 +00:00
|
|
|
{
|
2007-12-11 21:26:59 +00:00
|
|
|
ipMappings.appendAddress
|
|
|
|
(new (zone.allocate(sizeof(IpMapping))) IpMapping(-1, 0));
|
|
|
|
|
|
|
|
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]->reserved = true;
|
|
|
|
registers[rbp]->reserved = true;
|
|
|
|
registers[rbx]->reserved = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dispose() {
|
|
|
|
zone.dispose();
|
|
|
|
ipMappings.dispose();
|
|
|
|
constantPool.dispose();
|
|
|
|
code.dispose();
|
2007-12-11 21:26:59 +00:00
|
|
|
if (ipTable) s->free(ipTable);
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
|
|
|
Vector code;
|
|
|
|
Vector constantPool;
|
|
|
|
Vector ipMappings;
|
|
|
|
Zone zone;
|
|
|
|
intptr_t indirectCaller;
|
|
|
|
StackOperand* stack;
|
2007-12-11 21:26:59 +00:00
|
|
|
IpMapping** ipTable;
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-12-09 20:03:21 +00:00
|
|
|
ImmediateOperand*
|
|
|
|
immediate(Context* c, intptr_t v)
|
|
|
|
{
|
2007-12-11 00:48:09 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
IpMapping*
|
|
|
|
currentMapping(Context* c)
|
|
|
|
{
|
|
|
|
IpMapping* mapping;
|
|
|
|
c->ipMappings.get
|
|
|
|
(c->ipMappings.length() - BytesPerWord, &mapping, BytesPerWord);
|
|
|
|
return mapping;
|
|
|
|
}
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
void
|
|
|
|
flush(Context* c, StackOperand* s)
|
2007-12-09 20:03:21 +00:00
|
|
|
{
|
2007-12-11 00:48:09 +00:00
|
|
|
s->base->apply(c, MyOperand::push);
|
|
|
|
|
|
|
|
s->base->logicalFlush(c, s);
|
|
|
|
|
|
|
|
s->base = memory
|
|
|
|
(c, register_(c, rbp), - (s->index + 1) * BytesPerWord, 0, 1);
|
|
|
|
s->flushed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegisterOperand*
|
2007-12-11 21:26:59 +00:00
|
|
|
temporary(Context* c, bool reserve)
|
2007-12-11 00:48:09 +00:00
|
|
|
{
|
|
|
|
RegisterOperand* r = 0;
|
2007-12-11 21:26:59 +00:00
|
|
|
// we don't yet support using r9-r15
|
|
|
|
for (unsigned i = 0; i < 8/*RegisterCount*/; ++i) {
|
2007-12-11 00:48:09 +00:00
|
|
|
if (not c->registers[i]->reserved) {
|
2007-12-11 21:26:59 +00:00
|
|
|
if (c->registers[i]->stack == 0) {
|
|
|
|
if (reserve) c->registers[i]->reserved = true;
|
2007-12-11 00:48:09 +00:00
|
|
|
return c->registers[i];
|
|
|
|
} else if (r == 0 or r->stack->index > c->registers[i]->stack->index) {
|
|
|
|
r = c->registers[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r) {
|
|
|
|
flush(c, r->stack);
|
|
|
|
return r;
|
|
|
|
} else {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StackOperand*
|
|
|
|
push(Context* c, MyOperand* base)
|
|
|
|
{
|
|
|
|
return base->logicalPush(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pop(Context* c, MyOperand* dst)
|
|
|
|
{
|
|
|
|
if (c->stack->flushed) {
|
|
|
|
dst->apply(c, MyOperand::pop);
|
|
|
|
} else {
|
|
|
|
c->stack->base->apply(c, MyOperand::mov, dst);
|
2007-12-12 00:08:55 +00:00
|
|
|
c->stack->base->logicalFlush(c, c->stack);
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
c->stack = c->stack->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyOperand*
|
|
|
|
pop(Context* c)
|
|
|
|
{
|
2007-12-11 21:26:59 +00:00
|
|
|
MyOperand* r;
|
2007-12-11 00:48:09 +00:00
|
|
|
if (c->stack->flushed) {
|
2007-12-11 21:26:59 +00:00
|
|
|
RegisterOperand* tmp = temporary(c, true);
|
2007-12-11 00:48:09 +00:00
|
|
|
tmp->apply(c, MyOperand::pop);
|
2007-12-11 21:26:59 +00:00
|
|
|
r = tmp;
|
2007-12-11 00:48:09 +00:00
|
|
|
} else {
|
2007-12-11 21:26:59 +00:00
|
|
|
r = c->stack->base;
|
2007-12-12 00:08:55 +00:00
|
|
|
c->stack->base->logicalFlush(c, c->stack);
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
c->stack = c->stack->next;
|
2007-12-11 21:26:59 +00:00
|
|
|
return r;
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MyOperand*
|
2007-12-09 22:45:43 +00:00
|
|
|
selection(Context* c, SelectionOperand::SelectionType type, MyOperand* base)
|
2007-12-09 20:03:21 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
if ((type == SelectionOperand::S4Selection and BytesPerWord == 4)
|
|
|
|
or (type == SelectionOperand::S8Selection and BytesPerWord == 8))
|
2007-12-09 20:03:21 +00:00
|
|
|
{
|
|
|
|
return base;
|
|
|
|
} else {
|
2007-12-11 00:48:09 +00:00
|
|
|
return new (c->zone.allocate(sizeof(SelectionOperand)))
|
|
|
|
SelectionOperand(type, base);
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
flushStack(Context* c)
|
|
|
|
{
|
2007-12-11 00:48:09 +00:00
|
|
|
if (c->stack) {
|
|
|
|
StackOperand* stack[c->stack->index + 1];
|
|
|
|
int index = c->stack->index + 1;
|
|
|
|
for (StackOperand* s = c->stack; s and not s->flushed; s = s->next) {
|
|
|
|
stack[-- index] = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; index < c->stack->index + 1; ++ index) {
|
|
|
|
flush(c, stack[index]);
|
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
2007-12-09 23:06:47 +00:00
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2007-12-09 23:06:47 +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)
|
|
|
|
{
|
2007-12-09 23:06:47 +00:00
|
|
|
flushStack(c);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyOperand* arguments[count];
|
|
|
|
unsigned footprint = 0;
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
arguments[i] = va_arg(list, MyOperand*);
|
|
|
|
footprint += pad(arguments[i]->footprint());
|
|
|
|
}
|
|
|
|
|
2007-12-09 23:06:47 +00:00
|
|
|
const int GprCount = 6;
|
2007-12-09 22:45:43 +00:00
|
|
|
for (int i = count - 1; i >= 0; --i) {
|
2007-12-09 23:06:47 +00:00
|
|
|
if (BytesPerWord == 8 and i < GprCount) {
|
2007-12-11 00:48:09 +00:00
|
|
|
arguments[i]->apply(c, MyOperand::mov, register_(c, gpRegister(c, i)));
|
2007-12-09 23:06:47 +00:00
|
|
|
} else {
|
2007-12-11 00:48:09 +00:00
|
|
|
arguments[i]->apply(c, MyOperand::push);
|
2007-12-09 23:06:47 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 23:06:47 +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
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
StackOperand*
|
|
|
|
RegisterOperand::logicalPush(Context* c)
|
|
|
|
{
|
|
|
|
if (reserved or stack) {
|
|
|
|
RegisterOperand* tmp = temporary(c, false);
|
|
|
|
tmp->accept(c, mov, this);
|
|
|
|
c->stack = new (c->zone.allocate(sizeof(StackOperand)))
|
|
|
|
StackOperand(tmp, c->stack);
|
|
|
|
tmp->stack = c->stack;
|
|
|
|
} else {
|
|
|
|
c->stack = new (c->zone.allocate(sizeof(StackOperand)))
|
|
|
|
StackOperand(this, c->stack);
|
|
|
|
stack = c->stack;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->stack;
|
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
void
|
|
|
|
RegisterOperand::apply(Context* c, Operation operation)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case push:
|
|
|
|
c->code.append(0x50 | value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case pop:
|
|
|
|
c->code.append(0x58 | value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case jmp:
|
|
|
|
c->code.append(0xff);
|
|
|
|
c->code.append(0xe0 | value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case call:
|
|
|
|
c->code.append(0xff);
|
|
|
|
c->code.append(0xd0 | value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterOperand::accept(Context* c, Operation operation,
|
|
|
|
RegisterOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case mov:
|
|
|
|
if (value != operand->value) {
|
|
|
|
rex(c);
|
|
|
|
c->code.append(0x89);
|
|
|
|
c->code.append(0xc0 | (operand->value << 3) | value);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case add:
|
|
|
|
rex(c);
|
|
|
|
c->code.append(0x01);
|
|
|
|
c->code.append(0xc0 | (operand->value << 3) | value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterOperand::accept(Context* c, Operation operation,
|
|
|
|
ImmediateOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
2007-12-11 23:52:28 +00:00
|
|
|
case mov:
|
|
|
|
rex(c);
|
|
|
|
c->code.append(0xb8 | value);
|
|
|
|
c->code.appendAddress(operand->value);
|
|
|
|
break;
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
case sub:
|
2007-12-11 23:52:28 +00:00
|
|
|
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 21:26:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterOperand::accept(Context* c, Operation operation,
|
|
|
|
MemoryOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case mov:
|
|
|
|
rex(c);
|
|
|
|
encode(c, 0x8b, 0, 0x40, 0x80, value, operand->base->asRegister(c),
|
|
|
|
operand->displacement);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
class AbsoluteMovTask: public IpTask {
|
|
|
|
public:
|
|
|
|
AbsoluteMovTask(unsigned start, MyPromise* promise, IpTask* next):
|
|
|
|
IpTask(next), start(start), promise(promise)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual void run(Context* c UNUSED, unsigned, unsigned start, unsigned,
|
|
|
|
uint8_t* code, unsigned offset)
|
|
|
|
{
|
|
|
|
uint8_t* instruction = code + offset + (this->start - start);
|
|
|
|
intptr_t v = reinterpret_cast<intptr_t>(code + promise->value(c));
|
|
|
|
memcpy(instruction + (BytesPerWord / 8) + 1, &v, BytesPerWord);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned start;
|
|
|
|
MyPromise* promise;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterOperand::accept(Context* c, Operation operation,
|
|
|
|
AbsoluteOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case mov: {
|
|
|
|
IpMapping* mapping = currentMapping(c);
|
|
|
|
mapping->task = new (c->zone.allocate(sizeof(AbsoluteMovTask)))
|
|
|
|
AbsoluteMovTask(c->code.length(), operand->value, mapping->task);
|
|
|
|
|
|
|
|
accept(c, mov, immediate(c, 0));
|
|
|
|
accept(c, mov, memory(c, this, 0, 0, 1));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
class DirectCallTask: public IpTask {
|
|
|
|
public:
|
|
|
|
DirectCallTask(unsigned start, uint8_t* address, IpTask* next):
|
|
|
|
IpTask(next), start(start), address(address)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual void run(Context* c UNUSED, unsigned, unsigned start, unsigned,
|
|
|
|
uint8_t* code, unsigned offset)
|
|
|
|
{
|
|
|
|
uint8_t* instruction = code + offset + (this->start - start);
|
2007-12-11 23:52:28 +00:00
|
|
|
assert(c, *instruction == 0xe8);
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
intptr_t v = address - instruction;
|
|
|
|
assert(c, isInt32(v));
|
2007-12-11 23:52:28 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
int32_t v32 = v;
|
|
|
|
memcpy(instruction + 1, &v32, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned start;
|
|
|
|
uint8_t* address;
|
|
|
|
};
|
|
|
|
|
|
|
|
StackOperand*
|
|
|
|
ImmediateOperand::logicalPush(Context* c)
|
|
|
|
{
|
|
|
|
return c->stack = new (c->zone.allocate(sizeof(StackOperand)))
|
|
|
|
StackOperand(this, c->stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ImmediateOperand::apply(Context* c, Operation operation)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case call: {
|
|
|
|
IpMapping* mapping = currentMapping(c);
|
|
|
|
mapping->task = new (c->zone.allocate(sizeof(DirectCallTask)))
|
|
|
|
DirectCallTask
|
|
|
|
(c->code.length(), reinterpret_cast<uint8_t*>(value), mapping->task);
|
|
|
|
|
|
|
|
c->code.append(0xE8);
|
|
|
|
c->code.append4(0);
|
|
|
|
} break;
|
2007-12-11 23:52:28 +00:00
|
|
|
|
|
|
|
case alignedCall: {
|
|
|
|
while ((c->code.length() + 1) % 4) {
|
|
|
|
c->code.append(0x90);
|
|
|
|
}
|
|
|
|
apply(c, call);
|
|
|
|
} break;
|
2007-12-11 21:26:59 +00:00
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-12 00:27:04 +00:00
|
|
|
StackOperand*
|
|
|
|
AbsoluteOperand::logicalPush(Context* c)
|
|
|
|
{
|
|
|
|
return c->stack = new (c->zone.allocate(sizeof(StackOperand)))
|
|
|
|
StackOperand(this, c->stack);
|
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
void
|
|
|
|
AbsoluteOperand::apply(Context* c, Operation operation)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StackOperand*
|
|
|
|
MemoryOperand::logicalPush(Context* c)
|
|
|
|
{
|
|
|
|
RegisterOperand* tmp = temporary(c, false);
|
|
|
|
tmp->accept(c, mov, this);
|
|
|
|
c->stack = new (c->zone.allocate(sizeof(StackOperand)))
|
|
|
|
StackOperand(tmp, c->stack);
|
|
|
|
tmp->stack = c->stack;
|
|
|
|
return c->stack;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MemoryOperand::apply(Context* c, Operation operation)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
2007-12-11 23:52:28 +00:00
|
|
|
case pop:
|
|
|
|
encode(c, 0x8f, 0, 0x40, 0x80, rax, base->asRegister(c), displacement);
|
|
|
|
break;
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MemoryOperand::accept(Context* c, Operation operation,
|
|
|
|
RegisterOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case mov:
|
|
|
|
rex(c);
|
|
|
|
encode(c, 0x89, 0, 0x40, 0x80, operand->value, base->asRegister(c),
|
|
|
|
displacement);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MemoryOperand::accept(Context* c, Operation operation,
|
|
|
|
ImmediateOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case mov:
|
|
|
|
assert(c, isInt32(operand->value)); // todo
|
|
|
|
|
|
|
|
rex(c);
|
|
|
|
encode(c, 0xc7, 0, 0x40, 0x80, rax, base->asRegister(c), displacement);
|
|
|
|
c->code.append4(operand->value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-12 00:27:04 +00:00
|
|
|
void
|
|
|
|
MemoryOperand::accept(Context* c, Operation operation,
|
|
|
|
AbsoluteOperand* operand)
|
|
|
|
{
|
|
|
|
switch (operation) {
|
|
|
|
case mov: {
|
|
|
|
RegisterOperand* tmp = temporary(c, true);
|
|
|
|
|
|
|
|
tmp->accept(c, mov, operand);
|
|
|
|
accept(c, mov, tmp);
|
|
|
|
|
|
|
|
tmp->release(c);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
unsigned
|
|
|
|
PoolPromise::value(Context* c)
|
|
|
|
{
|
|
|
|
if (c->ipTable) {
|
|
|
|
return c->code.length() + key;
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
CodePromise::value(Context* c)
|
|
|
|
{
|
|
|
|
if (c->ipTable) {
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
IpPromise::value(Context* c)
|
|
|
|
{
|
|
|
|
if (c->ipTable) {
|
|
|
|
unsigned bottom = 0;
|
|
|
|
unsigned top = c->ipMappings.length() / BytesPerWord;
|
|
|
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
|
|
|
unsigned middle = bottom + (span / 2);
|
|
|
|
IpMapping* mapping = c->ipTable[middle];
|
|
|
|
|
|
|
|
if (key == mapping->ip) {
|
|
|
|
return mapping->start;
|
|
|
|
} else if (key < mapping->ip) {
|
|
|
|
top = middle;
|
|
|
|
} else if (key > mapping->ip) {
|
|
|
|
bottom = middle + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runTasks(Context* c, uint8_t* out, IpTask::Priority priority)
|
|
|
|
{
|
|
|
|
uint8_t* p = out;
|
|
|
|
for (unsigned i = 0; i < c->ipMappings.length() / BytesPerWord; ++i) {
|
|
|
|
IpMapping* mapping = c->ipTable[i];
|
|
|
|
int length = mapping->end - mapping->start;
|
|
|
|
|
|
|
|
for (IpTask* t = mapping->task; t; t = t->next) {
|
|
|
|
if (t->priority() == priority) {
|
|
|
|
t->run(c, mapping->ip, mapping->start, mapping->end, out, p - out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p += length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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() {
|
2007-12-11 21:26:59 +00:00
|
|
|
if (c.code.length() == 0) {
|
|
|
|
return new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0);
|
|
|
|
} else {
|
|
|
|
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise)))
|
|
|
|
CodePromise(c.code.length());
|
|
|
|
|
|
|
|
IpMapping* mapping = currentMapping(&c);
|
|
|
|
mapping->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
|
|
|
|
CodePromiseTask(p, mapping->task);
|
|
|
|
|
|
|
|
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(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);
|
2007-12-09 23:06:47 +00:00
|
|
|
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 Operand* pop() {
|
2007-12-11 00:48:09 +00:00
|
|
|
return ::pop(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* pop2() {
|
2007-12-09 20:03:21 +00:00
|
|
|
if (BytesPerWord == 8) pop();
|
|
|
|
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) {
|
2007-12-09 20:03:21 +00:00
|
|
|
if (BytesPerWord == 8) pop();
|
|
|
|
pop(dst);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* stack() {
|
2007-12-09 20:03:21 +00:00
|
|
|
flushStack(&c);
|
|
|
|
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() {
|
2007-12-11 21:26:59 +00:00
|
|
|
return ::temporary(&c, true);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->release(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* label() {
|
2007-12-11 00:48:09 +00:00
|
|
|
return absolute
|
|
|
|
(&c, new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void mark(Operand* label) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(label)->setAbsolute(&c, c.code.length());
|
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);
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(address)->apply
|
|
|
|
(&c, MyOperand::mov, register_(&c, rax));
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
immediate(&c, c.indirectCaller)->apply(&c, MyOperand::call);
|
|
|
|
|
|
|
|
immediate(&c, footprint)->apply(&c, MyOperand::sub, 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);
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(address)->apply
|
|
|
|
(&c, MyOperand::mov, register_(&c, rax));
|
|
|
|
|
|
|
|
immediate(&c, c.indirectCaller)->apply(&c, MyOperand::call);
|
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);
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(address)->apply(&c, MyOperand::call);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
immediate(&c, footprint)->apply(&c, MyOperand::sub, 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) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::mov, register_(&c, rax));
|
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) {
|
|
|
|
flushStack(&c);
|
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::call);
|
|
|
|
return register_(&c, rax);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* alignedCall(Operand* v) {
|
|
|
|
flushStack(&c);
|
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::alignedCall);
|
|
|
|
return register_(&c, rax);
|
|
|
|
}
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
virtual void ret() {
|
2007-12-09 22:45:43 +00:00
|
|
|
::ret(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void mov(Operand* src, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(src)->apply
|
|
|
|
(&c, MyOperand::mov, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void cmp(Operand* subtrahend, Operand* minuend) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(subtrahend)->apply
|
|
|
|
(&c, MyOperand::cmp, static_cast<MyOperand*>(minuend));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void jl(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::jl);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void jg(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::jg);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void jle(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::jle);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void jge(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::jge);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void je(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::je);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void jne(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::jne);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void jmp(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::jmp);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void add(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::add, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void sub(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::sub, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void mul(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::mul, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void div(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::div, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void rem(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::rem, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void shl(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::shl, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void shr(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::shr, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void ushr(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::ushr, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void and_(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::and_, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void or_(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::or_, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void xor_(Operand* v, Operand* dst) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply
|
|
|
|
(&c, MyOperand::xor_, static_cast<MyOperand*>(dst));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void neg(Operand* v) {
|
2007-12-11 00:48:09 +00:00
|
|
|
static_cast<MyOperand*>(v)->apply(&c, MyOperand::neg);
|
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, 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));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual Operand* select8(Operand* v) {
|
|
|
|
return selection(&c, SelectionOperand::S8Selection,
|
|
|
|
static_cast<MyOperand*>(v));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void prologue() {
|
2007-12-11 00:48:09 +00:00
|
|
|
register_(&c, rbp)->apply(&c, MyOperand::push);
|
|
|
|
register_(&c, rsp)->apply(&c, MyOperand::mov, register_(&c, rbp));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void epilogue() {
|
2007-12-11 00:48:09 +00:00
|
|
|
register_(&c, rbp)->apply(&c, MyOperand::mov, register_(&c, rsp));
|
2007-12-11 21:26:59 +00:00
|
|
|
register_(&c, rbp)->apply(&c, MyOperand::pop);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 20:03:21 +00:00
|
|
|
virtual void startLogicalIp(unsigned ip) {
|
2007-12-11 21:26:59 +00:00
|
|
|
c.ipMappings.appendAddress
|
|
|
|
(new (c.zone.allocate(sizeof(IpMapping)))
|
|
|
|
IpMapping(ip, c.code.length()));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 20:03:21 +00:00
|
|
|
virtual Operand* logicalIp(unsigned ip) {
|
2007-12-11 00:48:09 +00:00
|
|
|
return absolute(&c, static_cast<MyPromise*>(logicalIpToOffset(ip)));
|
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);
|
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual unsigned codeSize() {
|
|
|
|
return c.code.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
unsigned tableSize = (c.ipMappings.length() / BytesPerWord);
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
c.ipTable = static_cast<IpMapping**>
|
|
|
|
(c.s->allocate(c.ipMappings.length()));
|
2007-12-11 00:48:09 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < tableSize; ++i) {
|
2007-12-11 21:26:59 +00:00
|
|
|
IpMapping* mapping;
|
|
|
|
c.ipMappings.get(i * BytesPerWord, &mapping, BytesPerWord);
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
if (i + 1 < tableSize) {
|
|
|
|
IpMapping* next;
|
|
|
|
c.ipMappings.get((i + 1) * BytesPerWord, &next, BytesPerWord);
|
|
|
|
mapping->end = next->start;
|
2007-12-11 00:48:09 +00:00
|
|
|
} else {
|
|
|
|
mapping->end = c.code.length();
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
c.ipTable[i] = mapping;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
qsort(c.ipTable, tableSize, BytesPerWord, compareIpMappingPointers);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
uint8_t* p = out;
|
2007-12-11 00:48:09 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < tableSize; ++i) {
|
2007-12-11 21:26:59 +00:00
|
|
|
IpMapping* mapping = c.ipTable[i];
|
2007-12-11 00:48:09 +00:00
|
|
|
int length = mapping->end - mapping->start;
|
2007-12-11 21:26:59 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
memcpy(p, c.code.data + mapping->start, length);
|
2007-12-11 21:26:59 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
p += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(p, c.constantPool.data, c.constantPool.length());
|
2007-12-11 23:52:28 +00:00
|
|
|
|
|
|
|
runTasks(&c, out, IpTask::HighPriority);
|
|
|
|
runTasks(&c, out, IpTask::LowPriority);
|
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
|
|
|
};
|
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
unsigned
|
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);
|
|
|
|
}
|
|
|
|
|
2007-12-12 00:08:55 +00:00
|
|
|
} // namespace v
|