#include "compiler.h" using namespace vm; namespace { class MyPromise: public Promise { public: MyPromise(int value): resolved(false), value_(value) { } virtual unsigned value(System* s) { assert(s, resolved); return value_; } bool resolved; int value_; }; class MyCompiler: public Compiler { public: MyCompiler(System* s, void* indirectCaller): s(s), indirectCaller(reinterpret_cast(indirectCaller)) { } virtual Promise* poolOffset() { return promises.push(PoolPromise(constantPool.length() / BytesPerWord)); } virtual Promise* codeOffset() { return promises.push(CodePromise(code.length())); } virtual Operand* poolAppend(Operand* v) { Operand* r = operands.push (PoolEntry(constantPool.length() / BytesPerWord)); constantPool.push(v); return r; } virtual Operand* constant(intptr_t v) { return operands.push(Constant(v)); } virtual void push(Operand* v) { stack_.push(v); } virtual void push2(Operand* v) { stack_.push(v); stack_.push(0); } virtual Operand* stack(unsigned index) { return stack_.peek(stack.size() - index - 1); } virtual Operand* stack2(unsigned index) { return stack_.peek(stack.size() - index - 1); } virtual Operand* pop() { return stack_.pop(); } virtual Operand* pop2() { stack_.pop(); return stack_.pop(); } virtual void pop(Operand* dst) { mov(stack_.pop(), dst); } virtual void pop2(Operand* dst) { stack_.pop(); mov(stack_.pop(), dst); } virtual Operand* stack() { flushStack(); return operands.push(Register(rsp)); } virtual Operand* base() { return operands.push(Register(rbp)); } virtual Operand* thread() { return operands.push(Register(rbx)); } virtual Operand* indirectTarget() { return operands.push(Register(rax)); } virtual Operand* temporary() { return registerPool.pop(); } virtual void release(Operand* v) { return registerPool.push(v); } virtual Operand* label() { return operands.push(Label()); } virtual void mark(Operand* label) { setLabelValue(s, label, codeOffset()); } virtual Operand* call(Operand* v) { flushStack(); static_cast(v)->call(a); return operands.push(Register(rax)); } virtual Operand* alignedCall(Operand* v) { flushStack(); static_cast(v)->alignedCall(a); return operands.push(Register(rax)); } virtual Operand* indirectCall (Operand* address, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); pushArguments(argumentCount, a); va_end(a); mov(address, operands.push(Register(rax))); constant(indirectCaller)->call(a); popArguments(argumentCount); } virtual Operand* indirectCallNoReturn (Operand* address, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); pushArguments(argumentCount, a); va_end(a); mov(address, operands.push(Register(rax))); constant(indirectCaller)->call(a); } virtual Operand* directCall (Operand* address, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); pushArguments(argumentCount, a); va_end(a); static_cast(address)->call(a); popArguments(argumentCount); } virtual void return_(Operand* v) { mov(v, operands.push(Register(rax))); a->ret(); } virtual void ret() { a->ret(); } virtual void mov(Operand* src, Operand* dst) { static_cast(src)->mov(a, static_cast(dst)); } virtual void cmp(Operand* subtrahend, Operand* minuend) { static_cast(subtrahend)->mov (a, static_cast(minuend)); } virtual void jl(Operand* v) { static_cast(v)->jl(a); } virtual void jg(Operand* v) { static_cast(v)->jg(a); } virtual void jle(Operand* v) { static_cast(v)->jle(a); } virtual void jge(Operand* v) { static_cast(v)->jge(a); } virtual void je(Operand* v) { static_cast(v)->je(a); } virtual void jne(Operand* v) { static_cast(v)->jne(a); } virtual void jmp(Operand* v) { static_cast(v)->jmp(a); } virtual void add(Operand* v, Operand* dst) { static_cast(v)->add(a, static_cast(dst)); } virtual void sub(Operand* v, Operand* dst) { static_cast(v)->sub(a, static_cast(dst)); } virtual void mul(Operand* v, Operand* dst) { static_cast(v)->mul(a, static_cast(dst)); } virtual void div(Operand* v, Operand* dst) { static_cast(v)->div(a, static_cast(dst)); } virtual void rem(Operand* v, Operand* dst) { static_cast(v)->rem(a, static_cast(dst)); } virtual void shl(Operand* v, Operand* dst) { static_cast(v)->shl(a, static_cast(dst)); } virtual void shr(Operand* v, Operand* dst) { static_cast(v)->shr(a, static_cast(dst)); } virtual void ushr(Operand* v, Operand* dst) { static_cast(v)->ushr(a, static_cast(dst)); } virtual void and_(Operand* v, Operand* dst) { static_cast(v)->and_(a, static_cast(dst)); } virtual void or_(Operand* v, Operand* dst) { static_cast(v)->or_(a, static_cast(dst)); } virtual void xor_(Operand* v, Operand* dst) { static_cast(v)->xor_(a, static_cast(dst)); } virtual void neg(Operand* v) { static_cast(v)->neg(a); } virtual Operand* memory(Operand* base) { return operands.push(Memory(base, 0, 0, 1)); } virtual Operand* memory(Operand* base, unsigned displacement) { return operands.push(Memory(base, displacement, 0, 1)); } virtual Operand* memory(Operand* base, unsigned displacement, Operand* index, unsigned scale) { return operands.push(Memory(base, displacement, index, scale)); } virtual Operand* select1(Operand* v) { return operands.push(Selection(S1Selection, v)); } virtual Operand* select2(Operand* v) { return operands.push(Selection(S2Selection, v)); } virtual Operand* select2z(Operand* v) { return operands.push(Selection(Z2Selection, v)); } virtual Operand* select4(Operand* v) { return operands.push(Selection(S4Selection, v)); } virtual Operand* select8(Operand* v) { return operands.push(Selection(S8Selection, v)); } virtual void prologue() { a->push(rbp); a->mov(rsp, rbp); } virtual void epilogue() { a->mov(rbp, rsp); a->pop(rbp); } virtual void startLogicalIp(unsigned v) { ipTable.append(IpMapping(v, code.length())); } virtual Operand* logicalIp(unsigned v) { return operands.push(Label(promises.push(IpPromise(v)))); } virtual unsigned logicalIpToOffset(unsigned ip) { unsigned bottom = 0; unsigned top = ipTable.size(); for (unsigned span = top - bottom; span; span = top - bottom) { unsigned middle = bottom + (span / 2); IpMapping* mapping = ipTable.get(middle); if (ip == mapping->ip) { return mapping->offset; } else if (ip < mapping->ip) { top = middle; } else if (ip > mapping->ip) { bottom = middle + 1; } } abort(s); } virtual unsigned size() { return code.length(); } virtual void writeTo(void* out) { // todo } virtual void updateCall(void* returnAddress, void* newTarget); virtual void dispose() { promises.dispose(); constantPool.dispose(); registerPool.dispose(); ipTable.dispose(); operands.dispose(); code.dispose(); s->free(this); } System* s; Stack code; Stack operands; Stack ipTable; Stack constantPool; Stack registerPool; Stack promises; intptr_t indirectCaller; }; } // namespace namespace vm { Compiler* makeCompiler(System* system, void* indirectCaller) { return new (system->allocate(sizeof(MyCompiler))) MyCompiler(system, indirectCaller); } } // namespace vm