corda/src/compiler.cpp

837 lines
17 KiB
C++
Raw Normal View History

2007-12-08 23:22:13 +00:00
#include "compiler.h"
2007-12-09 20:03:21 +00:00
#include "vector.h"
2007-12-08 23:22:13 +00:00
using namespace vm;
namespace {
2007-12-09 20:03:21 +00:00
class IpMapping {
public:
IpMapping(unsigned ip, unsigned offset): ip(ip), offset(offset) { }
const unsigned ip;
const unsigned offset;
};
class Context {
public:
Context(System* s, void* indirectCaller):
s(s),
code(s, 1024),
virtualStack(s, BytesPerWord * 32),
operands(s, 8 * 1024),
ipTable(s, sizeof(IpMapping) * 512),
constantPool(s, BytesPerWord * 32),
registerPool(s, BytesPerWord * 8),
promises(s, 1024),
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller))
{ }
void dispose() {
promises.dispose();
constantPool.dispose();
registerPool.dispose();
ipTable.dispose();
operands.dispose();
virtualStack.dispose();
code.dispose();
}
System* s;
Vector code;
Vector<MyOperand*> virtualStack;
Vector operands;
Vector<IpMapping> ipTable;
Vector<MyOperand*> constantPool;
Vector<MyOperand*> registerPool;
Vector promises;
intptr_t indirectCaller;
};
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->system, v);
}
2007-12-08 23:22:13 +00:00
class MyPromise: public Promise {
public:
2007-12-09 20:03:21 +00:00
enum PromiseType {
PoolPromiseType,
CodePromiseType,
IpPromiseType
};
MyPromise(intptr_t value): resolved(false), value_(value) { }
2007-12-08 23:22:13 +00:00
virtual unsigned value(System* s) {
assert(s, resolved);
return value_;
}
2007-12-09 20:03:21 +00:00
virtual PromiseType type() = 0;
2007-12-08 23:22:13 +00:00
bool resolved;
2007-12-09 20:03:21 +00:00
intptr_t value_;
};
class PoolPromise: public MyPromise {
public:
PoolPromise(intptr_t value): MyPromise(value) { }
virtual PromiseType type() {
return PoolPromiseType;
}
};
class CodePromise: public MyPromise {
public:
PoolPromise(intptr_t value): MyPromise(value) { }
virtual PromiseType type() {
return CodePromiseType;
}
};
class IpPromise: public MyPromise {
public:
PoolPromise(intptr_t value): MyPromise(value) { }
virtual PromiseType type() {
return IpPromiseType;
}
};
class MyOperand: public Operand {
public:
enum OperandType {
ImmediateOperandType,
RegisterOperandType,
MemoryOperandType
};
virtual ~MyOperand() { }
virtual OperandType type() = 0;
virtual unsigned footprint() {
return BytesPerWord;
}
virtual unsigned size() = 0;
virtual void push(Context* c) { abort(c); }
virtual void mov(Context* c, MyOperand*) { abort(c); }
virtual void cmp(Context* c, MyOperand*) { abort(c); }
virtual void jl(Context* c) { abort(c); }
virtual void jg(Context* c) { abort(c); }
virtual void jle(Context* c) { abort(c); }
virtual void jge(Context* c) { abort(c); }
virtual void je(Context* c) { abort(c); }
virtual void jne(Context* c) { abort(c); }
virtual void jmp(Context* c) { abort(c); }
virtual void add(Context* c, MyOperand*) { abort(c); }
virtual void sub(Context* c, MyOperand*) { abort(c); }
virtual void mul(Context* c, MyOperand*) { abort(c); }
virtual void div(Context* c, MyOperand*) { abort(c); }
virtual void rem(Context* c, MyOperand*) { abort(c); }
virtual void shl(Context* c, MyOperand*) { abort(c); }
virtual void shr(Context* c, MyOperand*) { abort(c); }
virtual void ushr(Context* c, MyOperand*) { abort(c); }
virtual void and_(Context* c, MyOperand*) { abort(c); }
virtual void or_(Context* c, MyOperand*) { abort(c); }
virtual void xor_(Context* c, MyOperand*) { abort(c); }
virtual void neg(Context* c) { abort(c); }
};
class ImmediateOperand: public MyOperand {
public:
ImmediateOperand(intptr_t value):
value(value)
{ }
virtual OperandType type() {
return ImmediateOperandType;
}
virtual unsigned size() {
return sizeof(ImmediateOperand);
}
virtual void push(Context* c) {
if (isInt8(value)) {
c->code.append(0x6a);
c->code.append(value);
} else if (isInt32(value)) {
c->code.append(0x68);
c->code.append4(value);
} else {
RegisterOperand* tmp = temporary(c);
mov(c, tmp);
tmp->push(c);
release(c, tmp);
}
}
virtual void mov(Context* c, MyOperand* dst) {
switch (dst->type()) {
case RegisterOperandType:
rex(c);
c->code.append(0xb8 | registerValue(c, dst));
c->code.appendAddress(value);
break;
case MemoryOperandType:
rex(c);
encode(c, 0xc7, 0, 0x40, 0x80, rax,
asRegister(memoryBase(c, dst)),
memoryDisplacement(c, dst));
c->code.append4(v);
break;
default: abort(c);
}
}
intptr_t value;
};
class AbsoluteOperand: public MyOperand {
public:
AbsoluteOperand(Promise* value):
value(value)
{ }
virtual OperandType type() {
return AbsoluteOperandType;
}
virtual unsigned size() {
return sizeof(AbsoluteOperand);
}
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;
2007-12-08 23:22:13 +00:00
};
2007-12-09 20:03:21 +00:00
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
asRegister(Context* c, MyOperand* v)
{
if (v->type() == RegisterOperandType) {
return registerValue(v);
} else {
assert(c, v->type() == MemoryOperandType);
RegisterOperand* tmp = temporary(c);
v->mov(c, tmp);
Register r = tmp->value;
release(c, tmp);
return r;
}
}
class MemoryOperand: public MyOperand {
public:
MemoryOperand(MyOperand* base, int displacement, MyOperand* index,
unsigned scale):
base(base),
displacement(displacement),
index(index),
scale(scale)
{ }
virtual OperandType type() {
return MemoryOperandType;
}
virtual unsigned size() {
return sizeof(MemoryOperand);
}
virtual bool isStackReference() {
return false;
}
virtual void push(Context* c) {
assert(c, index == 0);
assert(c, scale == 0);
encode(c, 0xff, 0x30, 0x70, 0xb0, rax, asRegister(c, base), displacement);
}
virtual void mov(Context* c, MyOperand* dst) {
switch (dst->type()) {
case RegisterOperandType:
rex(c);
encode(c, 0x8b, 0, 0x40, 0x80, registerValue(c, dst),
base, displacement);
break;
case MemoryOperandType: {
RegisterOperand* tmp = temporary(c);
mov(c, tmp);
tmp->mov(c, dst);
release(c, tmp);
} break;
default: abort(t);
}
}
MyOperand* base;
int displacement;
MyOperand* index;
unsigned scale;
};
class StackOperand: public MemoryOperand {
public:
StackOperand(MyOperand* base, int displacement):
MemoryOperand(base, displacement, 0, 1)
{ }
virtual unsigned size() {
return sizeof(StackOperand);
}
virtual bool isStackReference() {
return true;
}
};
class SelectionOperand: public MyOperand {
public:
SelectionOperand(Compiler::SelectionType type, MyOperand* base):
type(type), base(base)
{ }
virtual OperandType type() {
return SelectionOperandType;
}
virtual unsigned footprint() {
if (type == Compiler::S8Selection) {
return 8;
} else {
return 4;
}
}
virtual unsigned size() {
return sizeof(SelectionOperand);
}
Compiler::SelectionType type;
MyOperand* base;
};
ImmediateOperand*
immediate(Context* c, intptr_t v)
{
return c->operands.push(ImmediateOperand(v));
}
AbsoluteOperand*
absolute(Context* c, intptr_t v)
{
return c->operands.push(AbsoluteOperand(v));
}
RegisterOperand*
register_(Context* c, Register v)
{
return c->operands.push(RegisterOperand(v));
}
MemoryOperand*
memory(Context* c, MyOperand* base, int displacement,
MyOperand* index, unsigned scale)
{
return c->operands.push(MemoryOperand(base, displacement, index, scale));
}
StackOperand*
stack(Context* c, int displacement)
{
return c->operands.push(StackOperand(register_(c, rbp), displacement));
}
MyOperand*
selection(Context* c, Compiler::SelectionType type, MyOperand* base)
{
if ((type == S4Selection and BytesPerWord == 4)
or (type == S8Selection and BytesPerWord == 8))
{
return base;
} else {
return c->operands.push(SelectionOperand(type, base));
}
}
bool
isStackReference(Context* c, MyOperand* v)
{
return v->type() == MemoryOperandType
and static_cast<MemoryOperand*>(v)->isStackReference();
}
void
flushStack(Context* c)
{
Stack newVirtualStack;
for (unsigned i = 0; i < c->virtualStack.length();) {
MyOperand* v = c->virtualStack.peek<MyOperand*>(i);
if (not isStackReference(c, v)) {
v->push(c);
if (v->footprint() / BytesPerWord == 2) {
newVirtualStack.push(stack(c, c->stackIndex + 4));
} else {
newVirtualStack.push(stack(c, c->stackIndex));
}
} else {
newVirtualStack.push(v, v->size());
}
i += v->size();
}
c->virtualStack.swap(&newVirtualStack);
}
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-09 20:03:21 +00:00
return c.promises.push(PoolPromise(constantPool.length() / BytesPerWord));
2007-12-08 23:22:13 +00:00
}
virtual Promise* codeOffset() {
2007-12-09 20:03:21 +00:00
return c.promises.push(CodePromise(code.length()));
2007-12-08 23:22:13 +00:00
}
virtual Operand* poolAppend(Operand* v) {
2007-12-09 20:03:21 +00:00
Operand* r = absolute(&c, poolOffset());
constantPool.push(static_cast<MyOperand*>(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-09 20:03:21 +00:00
c.virtualStack.push(static_cast<MyOperand*>(v));
2007-12-08 23:22:13 +00:00
}
virtual void push2(Operand* v) {
2007-12-09 20:03:21 +00:00
push(v);
if (BytesPerWord == 8) push(0);
2007-12-08 23:22:13 +00:00
}
virtual Operand* stack(unsigned index) {
2007-12-09 20:03:21 +00:00
return c.virtualStack.peek(stack.size() - index - 1);
2007-12-08 23:22:13 +00:00
}
virtual Operand* stack2(unsigned index) {
2007-12-09 20:03:21 +00:00
return c.virtualStack.peek(stack.size() - index - 1);
2007-12-08 23:22:13 +00:00
}
virtual Operand* pop() {
2007-12-09 20:03:21 +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-09 20:03:21 +00:00
pop(c)->mov(&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-09 20:03:21 +00:00
return ::temporary(&c);
2007-12-08 23:22:13 +00:00
}
virtual void release(Operand* v) {
2007-12-09 20:03:21 +00:00
assert(&c, static_cast<MyOperand>(v)->type() == RegisterOperandType);
return ::release(&c, static_cast<RegisterOperand*>(v));
2007-12-08 23:22:13 +00:00
}
virtual Operand* label() {
2007-12-09 20:03:21 +00:00
return absolute(&c, 0);
2007-12-08 23:22:13 +00:00
}
virtual void mark(Operand* label) {
2007-12-09 20:03:21 +00:00
setAbsoluteValue(&c, static_cast<MyOperand*>(label), codeOffset());
2007-12-08 23:22:13 +00:00
}
virtual Operand* call(Operand* v) {
2007-12-09 20:03:21 +00:00
flushStack(&c);
static_cast<MyOperand*>(v)->call(&c);
return register_(&c, rax);
2007-12-08 23:22:13 +00:00
}
virtual Operand* alignedCall(Operand* v) {
2007-12-09 20:03:21 +00:00
flushStack(&c);
static_cast<MyOperand*>(v)->alignedCall(&c);
return register_(&c, rax);
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 20:03:21 +00:00
pushArguments(&c, argumentCount, a);
2007-12-08 23:22:13 +00:00
va_end(a);
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(address)->mov(&c, register_(rax));
immediate(&c, indirectCaller)->call(&c);
2007-12-08 23:22:13 +00:00
2007-12-09 20:03:21 +00:00
popArguments(&c, argumentCount);
2007-12-08 23:22:13 +00:00
}
virtual Operand* indirectCallNoReturn
(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-09 20:03:21 +00:00
static_cast<MyOperand*>(address)->mov(&c, register_(rax));
immediate(&c, indirectCaller)->call(&c);
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 20:03:21 +00:00
pushArguments(&c, argumentCount, a);
2007-12-08 23:22:13 +00:00
va_end(a);
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(address)->call(&c);
2007-12-08 23:22:13 +00:00
2007-12-09 20:03:21 +00:00
popArguments(&c, argumentCount);
2007-12-08 23:22:13 +00:00
}
virtual void return_(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->mov(&c, register_(rax));
ret(c);
2007-12-08 23:22:13 +00:00
}
virtual void ret() {
2007-12-09 20:03:21 +00:00
ret(c);
2007-12-08 23:22:13 +00:00
}
virtual void mov(Operand* src, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(src)->mov(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void cmp(Operand* subtrahend, Operand* minuend) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(subtrahend)->mov
(&c, static_cast<MyOperand*>(minuend));
2007-12-08 23:22:13 +00:00
}
virtual void jl(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->jl(&c);
2007-12-08 23:22:13 +00:00
}
virtual void jg(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->jg(&c);
2007-12-08 23:22:13 +00:00
}
virtual void jle(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->jle(&c);
2007-12-08 23:22:13 +00:00
}
virtual void jge(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->jge(&c);
2007-12-08 23:22:13 +00:00
}
virtual void je(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->je(&c);
2007-12-08 23:22:13 +00:00
}
virtual void jne(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->jne(&c);
2007-12-08 23:22:13 +00:00
}
virtual void jmp(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->jmp(&c);
2007-12-08 23:22:13 +00:00
}
virtual void add(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->add(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void sub(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->sub(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void mul(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->mul(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void div(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->div(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void rem(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->rem(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void shl(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->shl(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void shr(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->shr(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void ushr(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->ushr(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void and_(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->and_(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void or_(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->or_(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void xor_(Operand* v, Operand* dst) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->xor_(&c, static_cast<MyOperand*>(dst));
2007-12-08 23:22:13 +00:00
}
virtual void neg(Operand* v) {
2007-12-09 20:03:21 +00:00
static_cast<MyOperand*>(v)->neg(&c);
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 20:03:21 +00:00
return memory(&c, base, displacement, index, scale);
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
virtual Operand* select(SelectionType type, Operand* v) {
return selection(&c, type, v);
2007-12-08 23:22:13 +00:00
}
virtual void prologue() {
2007-12-09 20:03:21 +00:00
register_(&c, rbp)->push(&c);
register_(&c, rsp)->mov(&c, register_(&c, rbp));
2007-12-08 23:22:13 +00:00
}
virtual void epilogue() {
2007-12-09 20:03:21 +00:00
register_(&c, rbp)->mov(&c, register_(&c, rsp));
register_(&c, rbp)->pop(&c);
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
virtual void startLogicalIp(unsigned ip) {
c.ipTable.push(IpMapping(ip, code.length()));
2007-12-08 23:22:13 +00:00
}
2007-12-09 20:03:21 +00:00
virtual Operand* logicalIp(unsigned ip) {
return absolute(&c, promises.push(IpPromise(ip)));
2007-12-08 23:22:13 +00:00
}
virtual unsigned logicalIpToOffset(unsigned ip) {
unsigned bottom = 0;
2007-12-09 20:03:21 +00:00
unsigned top = c.ipTable.size();
2007-12-08 23:22:13 +00:00
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
2007-12-09 20:03:21 +00:00
IpMapping* mapping = c.ipTable.get(middle);
2007-12-08 23:22:13 +00:00
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() {
2007-12-09 20:03:21 +00:00
return c.code.length();
2007-12-08 23:22:13 +00:00
}
virtual void writeTo(void* out) {
// todo
}
2007-12-09 20:03:21 +00:00
virtual void updateCall(void* returnAddress, void* newTarget) {
// todo
}
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
s->free(this);
}
2007-12-09 20:03:21 +00:00
Context c;
2007-12-08 23:22:13 +00:00
};
} // namespace
namespace vm {
Compiler*
makeCompiler(System* system, void* indirectCaller)
{
return new (system->allocate(sizeof(MyCompiler)))
MyCompiler(system, indirectCaller);
}
} // namespace vm