2008-02-19 18:06:52 +00:00
|
|
|
/* Copyright (c) 2008, Avian Contributors
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
|
|
|
|
2008-02-12 00:20:32 +00:00
|
|
|
#include "compiler.h"
|
2008-02-11 17:21:41 +00:00
|
|
|
#include "assembler.h"
|
2007-12-08 23:22:13 +00:00
|
|
|
|
|
|
|
using namespace vm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Context;
|
|
|
|
class MyOperand;
|
|
|
|
class ConstantValue;
|
|
|
|
class AddressValue;
|
|
|
|
class RegisterValue;
|
|
|
|
class MemoryValue;
|
|
|
|
class Event;
|
2008-03-09 21:27:51 +00:00
|
|
|
class Stack;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Value {
|
|
|
|
public:
|
|
|
|
virtual ~Value() { }
|
2007-12-14 18:27:56 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual OperandType type(Context*) = 0;
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual bool equals(Context*, Value*) { return false; }
|
2007-12-11 21:26:59 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual void preserve(Context*, Stack*, MyOperand*) { }
|
|
|
|
virtual void acquire(Context*, Stack*, MyOperand*) { }
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void release(Context*, MyOperand*) { }
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Stack* stackPosition(Context*) { return 0; }
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual RegisterValue* toRegister(Context*) = 0;
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void asAssemblerOperand(Context*,
|
|
|
|
OperandType* type,
|
|
|
|
Assembler::Operand** operand) = 0;
|
|
|
|
};
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class MyOperand: public Compiler::Operand {
|
2007-12-16 00:24:15 +00:00
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
MyOperand(Value* value):
|
2008-02-17 20:57:40 +00:00
|
|
|
event(0), value(value), target(0)
|
2007-12-16 00:24:15 +00:00
|
|
|
{ }
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
Event* event;
|
|
|
|
Value* value;
|
|
|
|
Value* target;
|
2008-02-17 20:57:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Stack {
|
|
|
|
public:
|
|
|
|
Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next):
|
|
|
|
operand(operand), size(size), index(index), next(next)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
MyOperand* operand;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned index;
|
2008-02-17 20:57:40 +00:00
|
|
|
Stack* next;
|
2007-12-16 00:24:15 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class State {
|
2007-12-08 23:22:13 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
State(State* s):
|
|
|
|
stack(s ? s->stack : 0),
|
|
|
|
next(s)
|
|
|
|
{ }
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
Stack* stack;
|
2008-02-11 17:21:41 +00:00
|
|
|
State* next;
|
2007-12-09 20:03:21 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class LogicalInstruction {
|
2007-12-12 22:19:13 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned visits;
|
|
|
|
Event* firstEvent;
|
|
|
|
Event* lastEvent;
|
|
|
|
unsigned machineOffset;
|
|
|
|
int predecessor;
|
2007-12-11 21:26:59 +00:00
|
|
|
};
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class RegisterElement {
|
2007-12-11 21:26:59 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
bool reserved;
|
|
|
|
MyOperand* operand;
|
2007-12-11 21:26:59 +00:00
|
|
|
};
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class ConstantPoolNode {
|
2007-12-16 00:24:15 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
ConstantPoolNode(Promise* promise): promise(promise), next(0) { }
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Promise* promise;
|
|
|
|
ConstantPoolNode* next;
|
2007-12-16 00:24:15 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Junction {
|
2007-12-16 21:30:19 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
Junction(unsigned logicalIp, Junction* next):
|
|
|
|
logicalIp(logicalIp),
|
|
|
|
next(next)
|
|
|
|
{ }
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned logicalIp;
|
|
|
|
Junction* next;
|
2007-12-16 21:30:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Context {
|
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
Context(System* system, Assembler* assembler, Zone* zone):
|
|
|
|
system(system),
|
|
|
|
assembler(assembler),
|
2007-12-31 22:40:56 +00:00
|
|
|
zone(zone),
|
2008-02-11 17:21:41 +00:00
|
|
|
logicalIp(-1),
|
|
|
|
state(new (zone->allocate(sizeof(State))) State(0)),
|
|
|
|
event(0),
|
|
|
|
logicalCode(0),
|
|
|
|
logicalCodeLength(0),
|
|
|
|
stackOffset(0),
|
|
|
|
registers(static_cast<RegisterElement*>
|
|
|
|
(zone->allocate
|
|
|
|
(sizeof(RegisterElement) * assembler->registerCount()))),
|
|
|
|
firstConstant(0),
|
|
|
|
lastConstant(0),
|
|
|
|
constantCount(0),
|
|
|
|
junctions(0),
|
|
|
|
machineCode(0)
|
2007-12-16 21:30:19 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
memset(registers, 0, sizeof(RegisterElement) * assembler->registerCount());
|
|
|
|
|
|
|
|
registers[assembler->base()].reserved = true;
|
|
|
|
registers[assembler->stack()].reserved = true;
|
|
|
|
registers[assembler->thread()].reserved = true;
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
System* system;
|
|
|
|
Assembler* assembler;
|
2007-12-31 22:40:56 +00:00
|
|
|
Zone* zone;
|
2008-02-11 17:21:41 +00:00
|
|
|
int logicalIp;
|
|
|
|
State* state;
|
|
|
|
Event* event;
|
|
|
|
LogicalInstruction* logicalCode;
|
|
|
|
unsigned logicalCodeLength;
|
|
|
|
unsigned stackOffset;
|
|
|
|
RegisterElement* registers;
|
|
|
|
ConstantPoolNode* firstConstant;
|
|
|
|
ConstantPoolNode* lastConstant;
|
|
|
|
unsigned constantCount;
|
|
|
|
Junction* junctions;
|
|
|
|
uint8_t* machineCode;
|
2007-12-16 21:30:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
inline void NO_RETURN
|
|
|
|
abort(Context* c)
|
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
abort(c->system);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
inline void
|
|
|
|
assert(Context* c, bool v)
|
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c->system, v);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
#endif // not NDEBUG
|
|
|
|
|
|
|
|
inline void
|
|
|
|
expect(Context* c, bool v)
|
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
expect(c->system, v);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
|
|
|
apply(Context* c, UnaryOperation op, unsigned size, Value* a)
|
|
|
|
{
|
|
|
|
OperandType type;
|
|
|
|
Assembler::Operand* operand;
|
|
|
|
a->asAssemblerOperand(c, &type, &operand);
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c->assembler->apply(op, size, type, operand);
|
|
|
|
}
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
|
|
|
apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b)
|
|
|
|
{
|
|
|
|
OperandType aType;
|
|
|
|
Assembler::Operand* aOperand;
|
|
|
|
a->asAssemblerOperand(c, &aType, &aOperand);
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
OperandType bType;
|
|
|
|
Assembler::Operand* bOperand;
|
|
|
|
b->asAssemblerOperand(c, &bType, &bOperand);
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class PoolPromise: public Promise {
|
2007-12-16 21:30:19 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
PoolPromise(Context* c, int key): c(c), key(key) { }
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int64_t value() {
|
|
|
|
if (resolved()) {
|
|
|
|
return reinterpret_cast<intptr_t>
|
2008-02-17 20:57:40 +00:00
|
|
|
(c->machineCode + pad(c->assembler->length()) + key);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual bool resolved() {
|
|
|
|
return c->machineCode != 0;
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Context* c;
|
|
|
|
int key;
|
2007-12-16 21:30:19 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class CodePromise: public Promise {
|
2007-12-16 21:30:19 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int64_t value() {
|
|
|
|
if (resolved()) {
|
|
|
|
return reinterpret_cast<intptr_t>(c->machineCode + offset);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual bool resolved() {
|
|
|
|
return c->machineCode != 0 and offset >= 0;
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Context* c;
|
|
|
|
int offset;
|
|
|
|
CodePromise* next;
|
2007-12-16 21:30:19 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class IpPromise: public Promise {
|
2007-12-16 21:30:19 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
IpPromise(Context* c, int logicalIp):
|
|
|
|
c(c),
|
2007-12-16 21:30:19 +00:00
|
|
|
logicalIp(logicalIp)
|
|
|
|
{ }
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int64_t value() {
|
|
|
|
if (resolved()) {
|
|
|
|
return reinterpret_cast<intptr_t>
|
|
|
|
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual bool resolved() {
|
|
|
|
return c->machineCode != 0;
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Context* c;
|
|
|
|
int logicalIp;
|
2007-12-16 21:30:19 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
RegisterValue*
|
|
|
|
freeRegister(Context* c, unsigned size);
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class ConstantValue: public Value {
|
|
|
|
public:
|
|
|
|
ConstantValue(Promise* value): value(value) { }
|
2007-12-17 01:46:46 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual OperandType type(Context*) { return Constant; }
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual RegisterValue* toRegister(Context* c);
|
2007-12-20 00:02:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void asAssemblerOperand(Context*,
|
|
|
|
OperandType* type,
|
|
|
|
Assembler::Operand** operand)
|
|
|
|
{
|
|
|
|
*type = Constant;
|
|
|
|
*operand = &value;
|
|
|
|
}
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Assembler::Constant value;
|
2007-12-16 21:30:19 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
ConstantValue*
|
|
|
|
constant(Context* c, Promise* value)
|
2007-12-16 21:30:19 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
ConstantValue*
|
|
|
|
constant(Context* c, int64_t value)
|
2007-12-16 21:30:19 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise)))
|
|
|
|
ResolvedPromise(value));
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class AddressValue: public Value {
|
2007-12-19 01:28:55 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
AddressValue(Promise* address): address(address) { }
|
2007-12-19 01:28:55 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual OperandType type(Context*) { return Address; }
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual RegisterValue* toRegister(Context* c);
|
2007-12-20 00:02:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void asAssemblerOperand(Context*,
|
|
|
|
OperandType* type,
|
|
|
|
Assembler::Operand** operand)
|
|
|
|
{
|
|
|
|
*type = Address;
|
|
|
|
*operand = &address;
|
2007-12-19 01:28:55 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Assembler::Address address;
|
|
|
|
};
|
2007-12-19 01:28:55 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
AddressValue*
|
|
|
|
address(Context* c, Promise* address)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address);
|
|
|
|
}
|
2007-12-20 00:02:32 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
void preserve(Context*, Stack*, int, MyOperand*);
|
2007-12-19 01:28:55 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class RegisterValue: public Value {
|
2007-12-09 20:03:21 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
RegisterValue(int low, int high): register_(low, high) { }
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual OperandType type(Context*) { return Register; }
|
2007-12-20 00:02:32 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual bool equals(Context* c, Value* o) {
|
2008-02-17 20:57:40 +00:00
|
|
|
return this == o or
|
2008-03-09 21:27:51 +00:00
|
|
|
(o->type(c) == Register
|
2008-02-17 20:57:40 +00:00
|
|
|
and static_cast<RegisterValue*>(o)->register_.low == register_.low
|
|
|
|
and static_cast<RegisterValue*>(o)->register_.high == register_.high);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual void preserve(Context* c, Stack* s, MyOperand* a) {
|
|
|
|
::preserve(c, s, register_.low, a);
|
|
|
|
if (register_.high >= 0) ::preserve(c, s, register_.high, a);
|
2007-12-17 20:55:31 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual void acquire(Context* c, Stack* s, MyOperand* a) {
|
2008-02-17 20:57:40 +00:00
|
|
|
if (a != c->registers[register_.low].operand) {
|
|
|
|
fprintf(stderr, "%p acquire %d\n", a, register_.low);
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
preserve(c, s, a);
|
2008-02-17 20:57:40 +00:00
|
|
|
c->registers[register_.low].operand = a;
|
|
|
|
if (register_.high >= 0) c->registers[register_.high].operand = a;
|
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void release(Context* c, MyOperand* a UNUSED) {
|
2008-02-17 20:57:40 +00:00
|
|
|
if (a == c->registers[register_.low].operand) {
|
|
|
|
fprintf(stderr, "%p release %d\n", a, register_.low);
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
c->registers[register_.low].operand = 0;
|
|
|
|
if (register_.high >= 0) c->registers[register_.high].operand = 0;
|
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual RegisterValue* toRegister(Context*) {
|
2008-02-11 17:21:41 +00:00
|
|
|
return this;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void asAssemblerOperand(Context*,
|
|
|
|
OperandType* type,
|
|
|
|
Assembler::Operand** operand)
|
|
|
|
{
|
|
|
|
*type = Register;
|
|
|
|
*operand = ®ister_;
|
2007-12-17 20:55:31 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Assembler::Register register_;
|
2007-12-09 22:45:43 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
RegisterValue*
|
|
|
|
register_(Context* c, int low, int high = NoRegister)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(RegisterValue)))
|
|
|
|
RegisterValue(low, high);
|
|
|
|
}
|
2007-12-09 20:03:21 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class MemoryValue: public Value {
|
2007-12-09 20:03:21 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
MemoryValue(int base, int offset, int index, unsigned scale,
|
|
|
|
TraceHandler* traceHandler):
|
|
|
|
value(base, offset, index, scale, traceHandler)
|
2007-12-14 00:27:09 +00:00
|
|
|
{ }
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual OperandType type(Context*) { return Memory; }
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual bool equals(Context* c, Value* o) {
|
2008-02-17 20:57:40 +00:00
|
|
|
return this == o or
|
2008-03-09 21:27:51 +00:00
|
|
|
(o->type(c) == Memory
|
2008-02-17 20:57:40 +00:00
|
|
|
and static_cast<MemoryValue*>(o)->value.base == value.base
|
|
|
|
and static_cast<MemoryValue*>(o)->value.offset == value.offset
|
|
|
|
and static_cast<MemoryValue*>(o)->value.index == value.index
|
|
|
|
and static_cast<MemoryValue*>(o)->value.scale == value.scale);
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual RegisterValue* toRegister(Context* c) {
|
|
|
|
RegisterValue* v = freeRegister(c, BytesPerWord);
|
|
|
|
apply(c, Move, BytesPerWord, this, v);
|
2008-02-11 17:21:41 +00:00
|
|
|
return v;
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int base(Context*) {
|
|
|
|
return value.base;
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int index(Context*) {
|
|
|
|
return value.index;
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void asAssemblerOperand(Context* c,
|
|
|
|
OperandType* type,
|
|
|
|
Assembler::Operand** operand)
|
|
|
|
{
|
|
|
|
value.base = base(c);
|
|
|
|
value.index = index(c);
|
|
|
|
*type = Memory;
|
|
|
|
*operand = &value;
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Assembler::Memory value;
|
2007-12-14 00:27:09 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MemoryValue*
|
|
|
|
memory(Context* c, int base, int offset, int index, unsigned scale,
|
|
|
|
TraceHandler* traceHandler)
|
2007-12-09 20:03:21 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
return new (c->zone->allocate(sizeof(MemoryValue)))
|
|
|
|
MemoryValue(base, offset, index, scale, traceHandler);
|
2007-12-09 20:03:21 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
int
|
|
|
|
toRegister(Context* c, MyOperand* a)
|
2007-12-14 00:27:09 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
return a->value->toRegister(c)->register_.low;
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class AbstractMemoryValue: public MemoryValue {
|
2007-12-14 00:27:09 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index,
|
|
|
|
unsigned scale, TraceHandler* traceHandler):
|
|
|
|
MemoryValue(NoRegister, offset, NoRegister, scale, traceHandler),
|
|
|
|
base_(base), index_(index)
|
2007-12-14 00:27:09 +00:00
|
|
|
{ }
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int base(Context* c) {
|
|
|
|
return ::toRegister(c, base_);
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual int index(Context* c) {
|
|
|
|
return index_ ? ::toRegister(c, base_) : NoRegister;
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* base_;
|
|
|
|
MyOperand* index_;
|
2007-12-14 00:27:09 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
AbstractMemoryValue*
|
|
|
|
memory(Context* c, MyOperand* base, int offset, MyOperand* index,
|
|
|
|
unsigned scale, TraceHandler* traceHandler)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(AbstractMemoryValue)))
|
|
|
|
AbstractMemoryValue(base, offset, index, scale, traceHandler);
|
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
class StackValue: public Value {
|
|
|
|
public:
|
|
|
|
StackValue(Stack* stack): stack(stack) { }
|
|
|
|
|
|
|
|
virtual OperandType type(Context* c) { abort(c); }
|
|
|
|
|
|
|
|
virtual RegisterValue* toRegister(Context* c) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Stack* stackPosition(Context*) { return stack; }
|
|
|
|
|
|
|
|
virtual void asAssemblerOperand(Context* c,
|
|
|
|
OperandType*,
|
|
|
|
Assembler::Operand**)
|
|
|
|
{
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
Stack* stack;
|
|
|
|
};
|
|
|
|
|
|
|
|
StackValue*
|
|
|
|
stackValue(Context* c, Stack* stack)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(StackValue))) StackValue(stack);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Event {
|
2007-12-14 00:27:09 +00:00
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
Event(Context* c): next(0), stack(c->state->stack), promises(0) {
|
|
|
|
if (c->event) {
|
|
|
|
c->event->next = this;
|
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (c->logicalCode[c->logicalIp].firstEvent == 0) {
|
|
|
|
c->logicalCode[c->logicalIp].firstEvent = this;
|
2007-12-14 18:27:56 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
c->event = this;
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Event(Event* next): next(next) { }
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual ~Event() { }
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* value) = 0;
|
|
|
|
virtual void compile(Context* c) = 0;
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Event* next;
|
2008-02-17 20:57:40 +00:00
|
|
|
Stack* stack;
|
2008-02-11 17:21:41 +00:00
|
|
|
CodePromise* promises;
|
2007-12-14 00:27:09 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class ArgumentEvent: public Event {
|
2007-12-14 00:27:09 +00:00
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index):
|
|
|
|
Event(c), size(size), a(a), index(index)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
a->event = this;
|
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == a);
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (index < c->assembler->argumentRegisterCount()) {
|
|
|
|
return register_(c, c->assembler->argumentRegister(index));
|
|
|
|
} else {
|
|
|
|
return memory(c, c->assembler->base(),
|
2008-02-17 22:29:04 +00:00
|
|
|
-(index + ((c->stackOffset + 1) * BytesPerWord)),
|
2008-02-11 17:21:41 +00:00
|
|
|
NoRegister, 0, 0);
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "ArgumentEvent.compile\n");
|
|
|
|
|
|
|
|
if (a->target == 0) a->target = target(c, a);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
a->value->release(c, a);
|
2008-03-09 21:27:51 +00:00
|
|
|
a->target->preserve(c, stack, a);
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
if (not a->target->equals(c, a->value)) {
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Move, size, a->value, a->target);
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* a;
|
|
|
|
unsigned index;
|
2007-12-16 00:24:15 +00:00
|
|
|
};
|
|
|
|
|
2007-12-14 00:27:09 +00:00
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
appendArgument(Context* c, unsigned size, MyOperand* value, unsigned index)
|
2007-12-14 00:27:09 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
new (c->zone->allocate(sizeof(ArgumentEvent)))
|
2008-02-12 02:06:12 +00:00
|
|
|
ArgumentEvent(c, size, value, index);
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class ReturnEvent: public Event {
|
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
ReturnEvent(Context* c, unsigned size, MyOperand* a):
|
|
|
|
Event(c), size(size), a(a)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
if (a) {
|
|
|
|
a->event = this;
|
|
|
|
}
|
|
|
|
}
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == a);
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
return register_(c, c->assembler->returnLow(), c->assembler->returnHigh());
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "ReturnEvent.compile\n");
|
|
|
|
|
2008-02-12 00:20:32 +00:00
|
|
|
if (a) {
|
2008-02-17 20:57:40 +00:00
|
|
|
if (a->target == 0) a->target = target(c, a);
|
|
|
|
|
2008-02-12 00:20:32 +00:00
|
|
|
a->value->release(c, a);
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
if (not a->target->equals(c, a->value)) {
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Move, size, a->value, a->target);
|
2008-02-12 00:20:32 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2008-02-12 00:20:32 +00:00
|
|
|
|
2008-02-12 15:21:51 +00:00
|
|
|
Assembler::Register base(c->assembler->base());
|
|
|
|
Assembler::Register stack(c->assembler->stack());
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-02-12 15:21:51 +00:00
|
|
|
c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack);
|
|
|
|
c->assembler->apply(Pop, BytesPerWord, Register, &base);
|
2008-02-11 17:21:41 +00:00
|
|
|
c->assembler->apply(Return);
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* a;
|
|
|
|
};
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
appendReturn(Context* c, unsigned size, MyOperand* value)
|
2007-12-12 22:19:13 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
|
2007-12-12 22:19:13 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
void
|
|
|
|
syncStack(Context* c, Stack* start, unsigned count)
|
|
|
|
{
|
|
|
|
Stack* segment[count];
|
|
|
|
unsigned index = count;
|
|
|
|
for (Stack* s = start; s; s = s->next) {
|
|
|
|
segment[--index] = s;
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
Stack* s = segment[i];
|
|
|
|
s->operand->value->release(c, s->operand);
|
|
|
|
apply(c, Push, s->size, s->operand->value);
|
|
|
|
s->operand->value = stackValue(c, s);
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
class SyncStackEvent: public Event {
|
2008-02-11 17:21:41 +00:00
|
|
|
public:
|
2008-03-09 21:27:51 +00:00
|
|
|
SyncStackEvent(Context* c):
|
|
|
|
Event(c)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-03-09 21:27:51 +00:00
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
|
|
|
s->operand->event = this;
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
SyncStackEvent(Context* c, Event* next):
|
|
|
|
Event(c)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-03-09 21:27:51 +00:00
|
|
|
stack = next->stack;
|
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
|
|
|
s->operand->event = this;
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context*, MyOperand*) {
|
|
|
|
return 0;
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-03-09 21:27:51 +00:00
|
|
|
fprintf(stderr, "SyncEvent.compile\n");
|
2007-12-18 00:22:37 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
unsigned count = 0;
|
|
|
|
for (Stack* s = stack;
|
|
|
|
s and s->operand->value->stackPosition(c) == 0;
|
|
|
|
s = s->next)
|
|
|
|
{
|
|
|
|
++ count;
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-31 22:40:56 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
syncStack(c, stack, count);
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-14 01:59:56 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
void
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(Context* c) {
|
|
|
|
new (c->zone->allocate(sizeof(SyncStackEvent))) SyncStackEvent(c);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class CallEvent: public Event {
|
|
|
|
public:
|
|
|
|
CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags,
|
2008-03-09 21:27:51 +00:00
|
|
|
TraceHandler* traceHandler, MyOperand* result):
|
2008-02-11 17:21:41 +00:00
|
|
|
Event(c),
|
|
|
|
address(address),
|
|
|
|
indirection(indirection),
|
|
|
|
flags(flags),
|
|
|
|
traceHandler(traceHandler),
|
2008-03-09 21:27:51 +00:00
|
|
|
result(result)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
address->event = this;
|
|
|
|
}
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == address);
|
2007-12-15 01:11:01 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (indirection) {
|
2008-02-17 22:29:04 +00:00
|
|
|
return register_(c, c->assembler->returnLow(), NoRegister);
|
2007-12-20 16:02:00 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
return 0;
|
2007-12-20 16:02:00 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "CallEvent.compile\n");
|
|
|
|
|
|
|
|
if (indirection and address->target == 0) {
|
|
|
|
address->target = target(c, address);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
address->value->release(c, address);
|
2007-12-12 01:19:03 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (result->event) {
|
|
|
|
result->value = register_
|
|
|
|
(c, c->assembler->returnLow(), c->assembler->returnHigh());
|
2008-03-09 21:27:51 +00:00
|
|
|
result->value->acquire(c, stack, result);
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-02-17 22:29:04 +00:00
|
|
|
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (indirection) {
|
2008-03-09 21:27:51 +00:00
|
|
|
if (not address->target->equals(c, address->value)) {
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Move, BytesPerWord, address->value, address->target);
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
2008-02-17 22:29:04 +00:00
|
|
|
apply(c, type, BytesPerWord,
|
2008-02-11 17:21:41 +00:00
|
|
|
constant(c, reinterpret_cast<intptr_t>(indirection)));
|
2007-12-23 18:48:22 +00:00
|
|
|
} else {
|
2008-02-17 22:29:04 +00:00
|
|
|
apply(c, type, BytesPerWord, address->value);
|
2007-12-23 18:48:22 +00:00
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
|
|
|
if (traceHandler) {
|
|
|
|
traceHandler->handleTrace
|
|
|
|
(new (c->zone->allocate(sizeof(CodePromise)))
|
|
|
|
CodePromise(c, c->assembler->length()));
|
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* address;
|
|
|
|
void* indirection;
|
|
|
|
unsigned flags;
|
|
|
|
TraceHandler* traceHandler;
|
|
|
|
MyOperand* result;
|
|
|
|
};
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2007-12-11 23:52:28 +00:00
|
|
|
void
|
2008-02-11 17:21:41 +00:00
|
|
|
appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags,
|
2008-03-09 21:27:51 +00:00
|
|
|
TraceHandler* traceHandler, MyOperand* result)
|
2007-12-11 23:52:28 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
new (c->zone->allocate(sizeof(CallEvent)))
|
2008-03-09 21:27:51 +00:00
|
|
|
CallEvent(c, address, indirection, flags, traceHandler, result);
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
int
|
|
|
|
freeRegister(Context* c)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
2008-02-17 20:57:40 +00:00
|
|
|
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
2008-02-11 17:21:41 +00:00
|
|
|
if ((not c->registers[i].reserved)
|
|
|
|
and c->registers[i].operand == 0)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
2008-01-09 00:23:10 +00:00
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
for (int i = c->assembler->registerCount(); i >= 0; --i) {
|
2008-02-11 17:21:41 +00:00
|
|
|
if (not c->registers[i].reserved) {
|
|
|
|
return i;
|
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
2008-01-09 00:23:10 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
abort(c);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
RegisterValue*
|
|
|
|
freeRegister(Context* c, unsigned size)
|
2007-12-14 00:27:09 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
if (BytesPerWord == 4 and size == 8) {
|
|
|
|
return register_(c, freeRegister(c), freeRegister(c));
|
|
|
|
} else {
|
|
|
|
return register_(c, freeRegister(c));
|
|
|
|
}
|
2007-12-14 00:27:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class MoveEvent: public Event {
|
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src,
|
|
|
|
MyOperand* dst):
|
|
|
|
Event(c), type(type), size(size), src(src), dst(dst)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
src->event = this;
|
|
|
|
}
|
2007-12-12 01:19:03 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == src);
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2008-02-12 00:20:32 +00:00
|
|
|
if (dst->value) {
|
|
|
|
return dst->value;
|
2008-02-17 20:57:40 +00:00
|
|
|
} else if (dst->event) {
|
|
|
|
return dst->event->target(c, dst);
|
2008-02-12 00:20:32 +00:00
|
|
|
} else {
|
2008-02-17 20:57:40 +00:00
|
|
|
return 0;
|
2008-02-12 00:20:32 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "MoveEvent.compile\n");
|
|
|
|
|
|
|
|
if (src->target == 0) src->target = target(c, src);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (src->target == 0) {
|
2008-02-17 20:57:40 +00:00
|
|
|
src->target = freeRegister(c, size);
|
2008-03-09 21:27:51 +00:00
|
|
|
} else if (type == Move
|
|
|
|
and size == BytesPerWord
|
|
|
|
and src->target->equals(c, src->value))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
} else if (src->value->type(c) == Memory
|
|
|
|
and src->target->type(c) == Memory)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
RegisterValue* tmp = freeRegister(c, size);
|
2008-03-09 21:27:51 +00:00
|
|
|
tmp->preserve(c, stack, 0);
|
2008-02-17 20:57:40 +00:00
|
|
|
apply(c, Move, size, src->value, tmp);
|
|
|
|
src->value = tmp;
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
src->value->release(c, src);
|
2008-03-09 21:27:51 +00:00
|
|
|
src->target->acquire(c, stack, dst);
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, type, size, src->value, src->target);
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
dst->value = src->target;
|
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
BinaryOperation type;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* src;
|
|
|
|
MyOperand* dst;
|
|
|
|
};
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src,
|
|
|
|
MyOperand* dst)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
new (c->zone->allocate(sizeof(MoveEvent)))
|
|
|
|
MoveEvent(c, type, size, src, dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
class DupEvent: public Event {
|
|
|
|
public:
|
|
|
|
DupEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst):
|
|
|
|
Event(c), size(size), src(src), dst(dst)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual Value* target(Context* c, MyOperand*) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void compile(Context* c) {
|
|
|
|
fprintf(stderr, "DupEvent.compile\n");
|
|
|
|
|
|
|
|
Value* value = src->value;
|
|
|
|
Value* target = dst->value;
|
|
|
|
|
|
|
|
if (target == 0) {
|
|
|
|
if (dst->event) {
|
|
|
|
target = dst->event->target(c, dst);
|
2008-03-09 21:27:51 +00:00
|
|
|
}
|
|
|
|
if (target == 0) {
|
2008-02-17 20:57:40 +00:00
|
|
|
target = freeRegister(c, size);
|
|
|
|
}
|
2008-03-09 21:27:51 +00:00
|
|
|
} else if (value->type(c) == Memory and target->type(c) == Memory) {
|
2008-02-17 20:57:40 +00:00
|
|
|
RegisterValue* tmp = freeRegister(c, size);
|
2008-03-09 21:27:51 +00:00
|
|
|
tmp->preserve(c, stack, 0);
|
2008-02-17 20:57:40 +00:00
|
|
|
apply(c, Move, size, value, tmp);
|
|
|
|
value = tmp;
|
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
target->acquire(c, stack, dst);
|
2008-02-17 20:57:40 +00:00
|
|
|
|
|
|
|
apply(c, Move, size, value, target);
|
|
|
|
|
|
|
|
dst->value = target;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned size;
|
|
|
|
MyOperand* src;
|
|
|
|
MyOperand* dst;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst)
|
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst);
|
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
class PopEvent: public Event {
|
|
|
|
public:
|
|
|
|
PopEvent(Context* c):
|
|
|
|
Event(c)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual Value* target(Context* c, MyOperand*) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void compile(Context* c) {
|
|
|
|
fprintf(stderr, "PopEvent.compile\n");
|
|
|
|
|
|
|
|
MyOperand* dst = stack->operand;
|
|
|
|
if (dst->value->stackPosition(c)) {
|
|
|
|
Value* target = dst->target;
|
|
|
|
|
|
|
|
if (target == 0) {
|
|
|
|
if (dst->event) {
|
|
|
|
target = dst->event->target(c, dst);
|
|
|
|
}
|
|
|
|
if (target == 0) {
|
|
|
|
target = freeRegister(c, BytesPerWord * stack->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
target->acquire(c, 0, dst);
|
|
|
|
|
|
|
|
apply(c, Pop, BytesPerWord * stack->size, target);
|
|
|
|
|
|
|
|
dst->value = target;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendPop(Context* c)
|
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class CompareEvent: public Event {
|
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b):
|
|
|
|
Event(c), size(size), a(a), b(b)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
a->event = this;
|
|
|
|
b->event = this;
|
|
|
|
}
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == a or v == b);
|
2007-12-14 00:27:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
return 0;
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "CompareEvent.compile\n");
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
a->value->release(c, a);
|
|
|
|
b->value->release(c, b);
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Compare, size, a->value, b->value);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* a;
|
|
|
|
MyOperand* b;
|
|
|
|
};
|
2007-12-11 21:26:59 +00:00
|
|
|
|
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
appendCompare(Context* c, unsigned size, MyOperand* a, MyOperand* b)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, a, b);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class BranchEvent: public Event {
|
|
|
|
public:
|
|
|
|
BranchEvent(Context* c, UnaryOperation type, MyOperand* address):
|
|
|
|
Event(c), type(type), address(address)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
address->event = this;
|
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == address);
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "BranchEvent.compile\n");
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
address->value->release(c, address);
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, type, BytesPerWord, address->value);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
UnaryOperation type;
|
|
|
|
MyOperand* address;
|
|
|
|
};
|
2007-12-11 21:26:59 +00:00
|
|
|
|
|
|
|
void
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(Context* c, UnaryOperation type, MyOperand* address)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address);
|
|
|
|
}
|
|
|
|
|
|
|
|
class JumpEvent: public Event {
|
|
|
|
public:
|
|
|
|
JumpEvent(Context* c, MyOperand* address):
|
|
|
|
Event(c),
|
|
|
|
address(address)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
address->event = this;
|
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == address);
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "JumpEvent.compile\n");
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
address->value->release(c, address);
|
2007-12-14 18:27:56 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Jump, BytesPerWord, address->value);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* address;
|
|
|
|
};
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
|
|
|
appendJump(Context* c, MyOperand* address)
|
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(BranchEvent))) JumpEvent(c, address);
|
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class CombineEvent: public Event {
|
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
CombineEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* a,
|
|
|
|
MyOperand* b, MyOperand* result):
|
|
|
|
Event(c), type(type), size(size), a(a), b(b), result(result)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
a->event = this;
|
|
|
|
b->event = this;
|
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* v) {
|
|
|
|
Assembler::Register ar(NoRegister);
|
|
|
|
Assembler::Register br(NoRegister);
|
2008-02-17 20:57:40 +00:00
|
|
|
c->assembler->getTargets(type, size, &ar, &br);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
if (v == a) {
|
|
|
|
if (ar.low == NoRegister) {
|
|
|
|
return 0;
|
2008-01-18 22:01:50 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
return register_(c, ar.low, ar.high);
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == b);
|
|
|
|
|
|
|
|
if (br.low == NoRegister) {
|
2008-02-17 20:57:40 +00:00
|
|
|
if (result->event) {
|
|
|
|
Value* v = result->event->target(c, result);
|
2008-03-09 21:27:51 +00:00
|
|
|
if (v->type(c) == Register) {
|
2008-02-17 20:57:40 +00:00
|
|
|
return v;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2007-12-26 16:56:14 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
return register_(c, br.low, br.high);
|
2007-12-16 21:30:19 +00:00
|
|
|
}
|
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-16 23:52:38 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "CombineEvent.compile\n");
|
|
|
|
|
|
|
|
if (a->target == 0) a->target = target(c, a);
|
|
|
|
if (b->target == 0) b->target = target(c, b);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
a->value->release(c, a);
|
|
|
|
b->value->release(c, b);
|
2008-03-09 21:27:51 +00:00
|
|
|
b->value->acquire(c, stack, result);
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
if (a->target and not a->target->equals(c, a->value)) {
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Move, size, a->value, a->target);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2008-03-09 21:27:51 +00:00
|
|
|
if (b->target and not b->target->equals(c, b->value)) {
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, Move, size, b->value, b->target);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
apply(c, type, size, a->value, b->value);
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
result->value = b->value;
|
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
BinaryOperation type;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* a;
|
|
|
|
MyOperand* b;
|
|
|
|
MyOperand* result;
|
|
|
|
};
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
appendCombine(Context* c, BinaryOperation type, unsigned size, MyOperand* a,
|
|
|
|
MyOperand* b, MyOperand* result)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(CombineEvent)))
|
2008-02-12 02:06:12 +00:00
|
|
|
CombineEvent(c, type, size, a, b, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class TranslateEvent: public Event {
|
|
|
|
public:
|
2008-02-12 02:06:12 +00:00
|
|
|
TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* result):
|
2008-02-12 02:06:12 +00:00
|
|
|
Event(c), type(type), size(size), a(a), result(result)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
|
|
|
a->event = this;
|
|
|
|
}
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(c, v == a);
|
|
|
|
|
|
|
|
Assembler::Register r(NoRegister);
|
2008-02-17 20:57:40 +00:00
|
|
|
c->assembler->getTargets(type, size, &r);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (r.low == NoRegister) {
|
|
|
|
return result->event->target(c, result);
|
2008-01-07 23:30:45 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
return register_(c, r.low, r.high);
|
2008-01-07 23:30:45 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-02-17 20:57:40 +00:00
|
|
|
fprintf(stderr, "TranslateEvent.compile\n");
|
|
|
|
|
|
|
|
if (a->target == 0) a->target = target(c, a);
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
result->value->acquire(c, stack, result);
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
if (a->target and not a->target->equals(c, a->value)) {
|
2008-02-17 20:57:40 +00:00
|
|
|
apply(c, Move, size, a->value, a->target);
|
|
|
|
}
|
|
|
|
apply(c, type, size, a->value);
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
result->value = a->value;
|
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
UnaryOperation type;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* a;
|
|
|
|
MyOperand* result;
|
|
|
|
};
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a,
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand* result)
|
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(TranslateEvent)))
|
2008-02-12 02:06:12 +00:00
|
|
|
TranslateEvent(c, type, size, a, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
RegisterValue*
|
2008-02-12 02:06:12 +00:00
|
|
|
ConstantValue::toRegister(Context* c)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
RegisterValue* v = freeRegister(c, BytesPerWord);
|
|
|
|
apply(c, Move, BytesPerWord, this, v);
|
2008-02-11 17:21:41 +00:00
|
|
|
return v;
|
|
|
|
}
|
2007-12-18 00:22:37 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
RegisterValue*
|
2008-02-12 02:06:12 +00:00
|
|
|
AddressValue::toRegister(Context* c)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
RegisterValue* v = freeRegister(c, BytesPerWord);
|
|
|
|
apply(c, Move, BytesPerWord, this, v);
|
2008-02-11 17:21:41 +00:00
|
|
|
return v;
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-03-09 21:27:51 +00:00
|
|
|
preserve(Context* c, Stack* stack, int reg, MyOperand* a)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
2008-02-17 20:57:40 +00:00
|
|
|
MyOperand* b = c->registers[reg].operand;
|
|
|
|
if (b and a != b) {
|
|
|
|
fprintf(stderr, "%p preserve %d for %p\n", a, reg, b);
|
2007-12-11 21:26:59 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
unsigned count = 0;
|
|
|
|
Stack* start = 0;
|
|
|
|
for (Stack* s = stack;
|
|
|
|
s and s->operand->value->stackPosition(c) == 0;
|
|
|
|
s = s->next)
|
|
|
|
{
|
|
|
|
if (s->operand == a) {
|
|
|
|
start = s;
|
|
|
|
}
|
|
|
|
if (start) {
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
assert(c, start);
|
2007-12-11 21:26:59 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
syncStack(c, start, count);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand*
|
2008-02-12 02:06:12 +00:00
|
|
|
operand(Context* c, Value* value = 0)
|
2007-12-12 00:27:04 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(value);
|
2007-12-12 00:27:04 +00:00
|
|
|
}
|
|
|
|
|
2007-12-14 18:27:56 +00:00
|
|
|
void
|
2008-02-11 17:21:41 +00:00
|
|
|
pushState(Context* c)
|
2007-12-14 18:27:56 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
c->state = new (c->zone->allocate(sizeof(State)))
|
|
|
|
State(c->state);
|
2007-12-14 18:27:56 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
|
|
|
popState(Context* c)
|
2007-12-11 23:52:28 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
c->state = new (c->zone->allocate(sizeof(State)))
|
|
|
|
State(c->state->next);
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
Stack*
|
|
|
|
stack(Context* c, MyOperand* operand, unsigned size, unsigned index,
|
|
|
|
Stack* next)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Stack)))
|
|
|
|
Stack(operand, size, index, next);
|
|
|
|
}
|
|
|
|
|
2008-02-17 22:29:04 +00:00
|
|
|
Stack*
|
|
|
|
stack(Context* c, MyOperand* operand, unsigned size, Stack* next)
|
|
|
|
{
|
|
|
|
return stack(c, operand, size, (next ? next->index + size : 0), next);
|
|
|
|
}
|
|
|
|
|
2007-12-14 00:27:09 +00:00
|
|
|
void
|
2008-02-12 02:06:12 +00:00
|
|
|
push(Context* c, unsigned size, MyOperand* o)
|
2007-12-12 22:19:13 +00:00
|
|
|
{
|
2008-02-17 20:57:40 +00:00
|
|
|
assert(c, ceiling(size, BytesPerWord));
|
|
|
|
|
2008-02-17 22:29:04 +00:00
|
|
|
c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-11 23:52:28 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MyOperand*
|
2008-02-12 02:06:12 +00:00
|
|
|
pop(Context* c, unsigned size UNUSED)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-02-17 20:57:40 +00:00
|
|
|
Stack* s = c->state->stack;
|
|
|
|
assert(c, ceiling(size, BytesPerWord) == s->size);
|
2008-02-12 02:06:12 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
appendPop(c);
|
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
c->state->stack = s->next;
|
|
|
|
return s->operand;
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-15 01:11:01 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
|
|
|
updateJunctions(Context* c)
|
|
|
|
{
|
|
|
|
for (Junction* j = c->junctions; j; j = j->next) {
|
|
|
|
LogicalInstruction* i = c->logicalCode + j->logicalIp;
|
|
|
|
|
|
|
|
if (i->predecessor >= 0) {
|
|
|
|
LogicalInstruction* p = c->logicalCode + i->predecessor;
|
2007-12-14 18:27:56 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
Event* e = new (c->zone->allocate(sizeof(SyncStackEvent)))
|
|
|
|
SyncStackEvent(c, p->lastEvent->next);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
p->lastEvent = p->lastEvent->next = e;
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-11 23:52:28 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
|
|
|
compile(Context* c)
|
|
|
|
{
|
2008-02-12 15:21:51 +00:00
|
|
|
Assembler* a = c->assembler;
|
|
|
|
|
|
|
|
Assembler::Register base(a->base());
|
|
|
|
Assembler::Register stack(a->stack());
|
|
|
|
a->apply(Push, BytesPerWord, Register, &base);
|
|
|
|
a->apply(Move, BytesPerWord, Register, &stack, Register, &base);
|
|
|
|
|
2008-02-12 00:20:32 +00:00
|
|
|
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
|
|
|
fprintf(stderr, "compile ip %d\n", i);
|
|
|
|
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
|
|
|
|
e->compile(c);
|
|
|
|
|
|
|
|
if (e == c->logicalCode[i].lastEvent) break;
|
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
class MyCompiler: public Compiler {
|
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
MyCompiler(System* s, Assembler* assembler, Zone* zone):
|
|
|
|
c(s, assembler, zone)
|
2007-12-08 23:22:13 +00:00
|
|
|
{ }
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void pushState() {
|
|
|
|
::pushState(&c);
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void popState() {
|
|
|
|
::pushState(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void init(unsigned logicalCodeLength, unsigned stackOffset) {
|
|
|
|
c.logicalCodeLength = logicalCodeLength;
|
|
|
|
c.stackOffset = stackOffset;
|
|
|
|
c.logicalCode = static_cast<LogicalInstruction*>
|
|
|
|
(c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength));
|
|
|
|
memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength);
|
2007-12-17 20:55:31 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void visitLogicalIp(unsigned logicalIp) {
|
|
|
|
if ((++ c.logicalCode[logicalIp].visits) == 1) {
|
|
|
|
c.junctions = new (c.zone->allocate(sizeof(Junction)))
|
|
|
|
Junction(logicalIp, c.junctions);
|
2007-12-17 20:55:31 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void startLogicalIp(unsigned logicalIp) {
|
|
|
|
if (c.logicalIp >= 0) {
|
|
|
|
c.logicalCode[c.logicalIp].lastEvent = c.event;
|
|
|
|
}
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c.logicalIp = logicalIp;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* machineIp(unsigned logicalIp) {
|
|
|
|
return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp);
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* poolAppend(intptr_t value) {
|
|
|
|
return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise)))
|
|
|
|
ResolvedPromise(value));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* poolAppendPromise(Promise* value) {
|
|
|
|
Promise* p = new (c.zone->allocate(sizeof(PoolPromise)))
|
|
|
|
PoolPromise(&c, c.constantCount);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
ConstantPoolNode* constant
|
|
|
|
= new (c.zone->allocate(sizeof(ConstantPoolNode)))
|
|
|
|
ConstantPoolNode(value);
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (c.firstConstant) {
|
|
|
|
c.lastConstant->next = constant;
|
|
|
|
} else {
|
|
|
|
c.firstConstant = constant;
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
c.lastConstant = constant;
|
|
|
|
++ c.constantCount;
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
return p;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* constant(int64_t value) {
|
|
|
|
return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise)))
|
|
|
|
ResolvedPromise(value));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* promiseConstant(Promise* value) {
|
2008-02-12 02:06:12 +00:00
|
|
|
return operand(&c, ::constant(&c, value));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* address(Promise* address) {
|
2008-02-12 02:06:12 +00:00
|
|
|
return operand(&c, ::address(&c, address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* memory(Operand* base,
|
|
|
|
int displacement = 0,
|
|
|
|
Operand* index = 0,
|
|
|
|
unsigned scale = 1,
|
|
|
|
TraceHandler* traceHandler = 0)
|
|
|
|
{
|
|
|
|
return operand
|
2008-02-12 02:06:12 +00:00
|
|
|
(&c, ::memory
|
2008-02-11 17:21:41 +00:00
|
|
|
(&c, static_cast<MyOperand*>(base), displacement,
|
|
|
|
static_cast<MyOperand*>(index), scale, traceHandler));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* stack() {
|
2008-02-12 02:06:12 +00:00
|
|
|
return operand(&c, register_(&c, c.assembler->stack()));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* base() {
|
2008-02-12 02:06:12 +00:00
|
|
|
return operand(&c, register_(&c, c.assembler->base()));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* thread() {
|
2008-02-12 02:06:12 +00:00
|
|
|
return operand(&c, register_(&c, c.assembler->thread()));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* label() {
|
2008-02-12 02:06:12 +00:00
|
|
|
return operand(&c, ::constant(&c, static_cast<Promise*>(0)));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
Promise* machineIp() {
|
2008-02-11 17:21:41 +00:00
|
|
|
return c.event->promises = new (c.zone->allocate(sizeof(CodePromise)))
|
|
|
|
CodePromise(&c, c.event->promises);
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
virtual void mark(Operand* label) {
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<ConstantValue*>(static_cast<MyOperand*>(label)->value)->value
|
|
|
|
= machineIp();
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void push(unsigned size, Operand* value) {
|
|
|
|
::push(&c, size, static_cast<MyOperand*>(value));
|
2007-12-22 00:26:55 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* pop(unsigned size) {
|
|
|
|
return ::pop(&c, size);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void pushed(unsigned count) {
|
|
|
|
for (unsigned i = 0; i < count; ++i) ::push(&c, BytesPerWord, operand(&c));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void popped(unsigned count) {
|
2008-02-17 20:57:40 +00:00
|
|
|
for (unsigned i = count; i > 0;) {
|
|
|
|
Stack* s = c.state->stack;
|
|
|
|
c.state->stack = s->next;
|
|
|
|
i -= s->size;
|
2008-02-12 02:06:12 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Operand* peek(unsigned size UNUSED, unsigned index) {
|
2008-02-17 20:57:40 +00:00
|
|
|
Stack* s = c.state->stack;
|
|
|
|
for (unsigned i = index; i > 0;) {
|
|
|
|
s = s->next;
|
|
|
|
i -= s->size;
|
|
|
|
}
|
|
|
|
assert(&c, s->size == ceiling(size, BytesPerWord));
|
|
|
|
return s->operand;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* call(Operand* address,
|
|
|
|
void* indirection,
|
|
|
|
unsigned flags,
|
|
|
|
TraceHandler* traceHandler,
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned,
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned argumentCount,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list a; va_start(a, argumentCount);
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned footprint = 0;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size = BytesPerWord;
|
2008-02-11 17:21:41 +00:00
|
|
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
|
|
|
MyOperand* o = va_arg(a, MyOperand*);
|
2008-02-12 02:06:12 +00:00
|
|
|
if (o) {
|
|
|
|
appendArgument(&c, size, o, footprint);
|
|
|
|
size = BytesPerWord;
|
|
|
|
} else {
|
|
|
|
size = 8;
|
|
|
|
}
|
|
|
|
++ footprint;
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
va_end(a);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
MyOperand* result = operand(&c);
|
2008-02-11 17:21:41 +00:00
|
|
|
appendCall(&c, static_cast<MyOperand*>(address), indirection, flags,
|
2008-03-09 21:27:51 +00:00
|
|
|
traceHandler, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void return_(unsigned size, Operand* value) {
|
|
|
|
appendReturn(&c, size, static_cast<MyOperand*>(value));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void store(unsigned size, Operand* src, Operand* dst) {
|
|
|
|
appendMove(&c, Move, size, static_cast<MyOperand*>(src),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(dst));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* load(unsigned size, Operand* src) {
|
|
|
|
MyOperand* dst = operand(&c);
|
|
|
|
appendMove(&c, Move, size, static_cast<MyOperand*>(src), dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* loadz(unsigned size, Operand* src) {
|
|
|
|
MyOperand* dst = operand(&c);
|
|
|
|
appendMove(&c, MoveZ, size, static_cast<MyOperand*>(src), dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* load4To8(Operand* src) {
|
2008-02-12 02:06:12 +00:00
|
|
|
MyOperand* dst = operand(&c);
|
|
|
|
appendMove(&c, Move4To8, 0, static_cast<MyOperand*>(src), dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
virtual Operand* dup(unsigned size, Operand* src) {
|
|
|
|
MyOperand* dst = operand(&c);
|
|
|
|
appendDup(&c, size, static_cast<MyOperand*>(src), dst);
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void cmp(unsigned size, Operand* a, Operand* b) {
|
|
|
|
appendCompare(&c, size, static_cast<MyOperand*>(a),
|
|
|
|
static_cast<MyOperand*>(b));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jl(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(&c, JumpIfLess, static_cast<MyOperand*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jg(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(&c, JumpIfGreater, static_cast<MyOperand*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jle(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(&c, JumpIfLessOrEqual, static_cast<MyOperand*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jge(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(&c, JumpIfGreaterOrEqual, static_cast<MyOperand*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void je(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(&c, JumpIfEqual, static_cast<MyOperand*>(address));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jne(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendBranch(&c, JumpIfNotEqual, static_cast<MyOperand*>(address));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jmp(Operand* address) {
|
2008-03-09 21:27:51 +00:00
|
|
|
appendSyncStack(&c);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
appendJump(&c, static_cast<MyOperand*>(address));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Add, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* sub(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Subtract, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* mul(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Multiply, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* div(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Divide, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-22 00:26:55 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* rem(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Remainder, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* shl(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, ShiftLeft, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* shr(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, ShiftRight, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* ushr(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, UnsignedShiftRight, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* and_(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, And, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* or_(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Or, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-12 18:59:45 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendCombine(&c, Xor, size, static_cast<MyOperand*>(a),
|
2008-02-11 17:21:41 +00:00
|
|
|
static_cast<MyOperand*>(b), result);
|
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* neg(unsigned size, Operand* a) {
|
|
|
|
MyOperand* result = operand(&c);
|
|
|
|
appendTranslate(&c, Negate, size, static_cast<MyOperand*>(a), result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual unsigned compile() {
|
|
|
|
updateJunctions(&c);
|
|
|
|
::compile(&c);
|
|
|
|
return c.assembler->length();
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual unsigned poolSize() {
|
2008-02-11 17:21:41 +00:00
|
|
|
return c.constantCount;
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void writeTo(uint8_t* dst) {
|
|
|
|
c.machineCode = dst;
|
|
|
|
c.assembler->writeTo(dst);
|
2007-12-11 23:52:28 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
int i = 0;
|
|
|
|
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
2008-02-17 20:57:40 +00:00
|
|
|
*reinterpret_cast<intptr_t*>(dst + pad(c.assembler->length()) + (i++))
|
2008-02-11 17:21:41 +00:00
|
|
|
= n->promise->value();
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dispose() {
|
2008-02-11 17:21:41 +00:00
|
|
|
// ignore
|
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
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
|
|
|
Compiler*
|
2008-02-11 17:21:41 +00:00
|
|
|
makeCompiler(System* system, Assembler* assembler, Zone* zone)
|
2007-12-08 23:22:13 +00:00
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
return new (zone->allocate(sizeof(MyCompiler)))
|
2008-02-11 17:21:41 +00:00
|
|
|
MyCompiler(system, assembler, zone);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
} // namespace vm
|