corda/src/compiler.cpp

3014 lines
69 KiB
C++
Raw Normal View History

/* 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. */
#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 {
const bool DebugAppend = false;
const bool DebugCompile = false;
const bool DebugStack = false;
const bool DebugRegisters = false;
2008-04-19 21:52:45 +00:00
2008-02-11 17:21:41 +00:00
class Context;
class Value;
2008-04-17 22:07:32 +00:00
class Stack;
class Site;
class RegisterSite;
2008-04-17 22:07:32 +00:00
class Event;
2008-04-18 03:47:42 +00:00
class PushEvent;
2008-04-18 00:39:41 +00:00
class Read;
2007-12-09 22:45:43 +00:00
void NO_RETURN abort(Context*);
2008-03-15 23:54:20 +00:00
2008-04-17 22:07:32 +00:00
void
apply(Context* c, UnaryOperation op, unsigned size, Site* a);
void
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b);
enum ConstantCompare {
CompareNone,
CompareLess,
CompareGreater,
CompareEqual
};
class Site {
public:
Site(): next(0) { }
virtual ~Site() { }
virtual Site* readTarget(Context*, Read*) { return this; }
2008-04-17 02:55:38 +00:00
virtual unsigned copyCost(Context*, Site*) = 0;
2008-07-17 23:34:38 +00:00
virtual void acquire(Context*, Stack*, Value**, unsigned, Value*) { }
2008-04-17 02:55:38 +00:00
2008-04-19 00:19:45 +00:00
virtual void release(Context*) { }
virtual void freeze(Context*) { }
virtual void thaw(Context*) { }
2008-04-17 22:07:32 +00:00
virtual OperandType type(Context*) = 0;
2008-04-17 02:55:38 +00:00
virtual Assembler::Operand* asAssemblerOperand(Context*) = 0;
Site* next;
};
2008-07-05 20:21:13 +00:00
class Stack: public StackElement {
2008-04-17 22:07:32 +00:00
public:
2008-07-05 20:21:13 +00:00
Stack(unsigned index, Value* value, Stack* next):
index(index), value(value), next(next)
2008-04-17 22:07:32 +00:00
{ }
unsigned index;
2008-07-05 20:21:13 +00:00
Value* value;
2008-04-17 22:07:32 +00:00
Stack* next;
};
class State {
public:
2008-07-05 20:21:13 +00:00
State(State* next, Stack* stack, Value** locals):
stack(stack),
2008-07-05 20:21:13 +00:00
locals(locals),
next(next)
2008-04-17 22:07:32 +00:00
{ }
Stack* stack;
2008-07-05 20:21:13 +00:00
Value** locals;
2008-04-17 22:07:32 +00:00
State* next;
};
class LogicalInstruction {
public:
2008-04-19 07:03:59 +00:00
Event* firstEvent;
2008-04-17 22:07:32 +00:00
Event* lastEvent;
2008-04-20 19:35:36 +00:00
LogicalInstruction* immediatePredecessor;
Stack* stack;
2008-07-05 20:21:13 +00:00
Value** locals;
2008-04-17 22:07:32 +00:00
unsigned machineOffset;
2008-04-20 19:35:36 +00:00
bool stackSaved;
2008-04-17 22:07:32 +00:00
};
class Register {
public:
Register(int number):
value(0), site(0), number(number), size(0), refCount(0),
2008-05-15 20:00:57 +00:00
freezeCount(0), reserved(false), pushed(false)
{ }
2008-04-17 22:07:32 +00:00
Value* value;
RegisterSite* site;
int number;
2008-04-17 22:07:32 +00:00
unsigned size;
unsigned refCount;
unsigned freezeCount;
2008-04-17 22:07:32 +00:00
bool reserved;
bool pushed;
2008-04-17 22:07:32 +00:00
};
class ConstantPoolNode {
public:
ConstantPoolNode(Promise* promise): promise(promise), next(0) { }
Promise* promise;
ConstantPoolNode* next;
};
class Junction {
public:
Junction(unsigned logicalIp, Junction* next):
logicalIp(logicalIp),
next(next)
{ }
unsigned logicalIp;
Junction* next;
};
class Read {
public:
2008-07-05 20:21:13 +00:00
Read():
next(0), event(0), eventNext(0)
2008-04-17 22:07:32 +00:00
{ }
Read* next;
Event* event;
Read* eventNext;
2008-07-05 20:21:13 +00:00
virtual Site* pickSite(Context* c, Value* v) = 0;
virtual Site* allocateSite(Context* c) = 0;
virtual void intersect(uint8_t* typeMask, uint64_t* registerMask,
int* frameIndex) = 0;
virtual bool valid() = 0;
2008-04-17 22:07:32 +00:00
};
class Value: public Compiler::Operand {
public:
Value(Site* site, Site* target):
reads(0), lastRead(0), sites(site), source(0), target(target)
2008-04-17 22:07:32 +00:00
{ }
Read* reads;
Read* lastRead;
Site* sites;
Site* source;
2008-04-19 20:41:31 +00:00
Site* target;
2008-04-17 22:07:32 +00:00
};
2008-07-05 20:21:13 +00:00
enum Pass {
ScanPass,
CompilePass
};
2008-04-17 22:07:32 +00:00
class Context {
public:
Context(System* system, Assembler* assembler, Zone* zone,
Compiler::Client* client):
2008-04-17 22:07:32 +00:00
system(system),
assembler(assembler),
zone(zone),
client(client),
2008-04-17 22:07:32 +00:00
logicalIp(-1),
state(new (zone->allocate(sizeof(State))) State(0, 0)),
2008-04-17 22:07:32 +00:00
logicalCode(0),
logicalCodeLength(0),
parameterFootprint(0),
localFootprint(0),
registers
(static_cast<Register**>
(zone->allocate(sizeof(Register*) * assembler->registerCount()))),
2008-04-17 22:07:32 +00:00
firstConstant(0),
lastConstant(0),
constantCount(0),
2008-04-19 07:03:59 +00:00
nextSequence(0),
2008-04-17 22:07:32 +00:00
junctions(0),
2008-04-20 05:23:08 +00:00
machineCode(0),
stackReset(false),
2008-07-05 20:21:13 +00:00
constantCompare(CompareNone),
pass(ScanPass),
stackPadding(0)
2008-04-17 22:07:32 +00:00
{
for (unsigned i = 0; i < assembler->registerCount(); ++i) {
registers[i] = new (zone->allocate(sizeof(Register))) Register(i);
}
registers[assembler->base()]->reserved = true;
registers[assembler->stack()]->reserved = true;
registers[assembler->thread()]->reserved = true;
2008-04-17 22:07:32 +00:00
}
System* system;
Assembler* assembler;
Zone* zone;
Compiler::Client* client;
2008-04-17 22:07:32 +00:00
int logicalIp;
State* state;
LogicalInstruction* logicalCode;
unsigned logicalCodeLength;
unsigned parameterFootprint;
unsigned localFootprint;
Register** registers;
2008-04-17 22:07:32 +00:00
ConstantPoolNode* firstConstant;
ConstantPoolNode* lastConstant;
unsigned constantCount;
2008-04-19 07:03:59 +00:00
unsigned nextSequence;
2008-04-17 22:07:32 +00:00
Junction* junctions;
uint8_t* machineCode;
2008-04-20 05:23:08 +00:00
bool stackReset;
ConstantCompare constantCompare;
2008-07-05 20:21:13 +00:00
Pass pass;
unsigned stackPadding;
2008-04-17 22:07:32 +00:00
};
class PoolPromise: public Promise {
public:
PoolPromise(Context* c, int key): c(c), key(key) { }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + pad(c->assembler->length()) + (key * BytesPerWord));
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0;
}
Context* c;
int key;
};
class CodePromise: public Promise {
public:
CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { }
CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset);
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0 and offset >= 0;
}
Context* c;
int offset;
CodePromise* next;
};
class IpPromise: public Promise {
public:
IpPromise(Context* c, int logicalIp):
c(c),
logicalIp(logicalIp)
{ }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0;
}
Context* c;
int logicalIp;
};
inline void NO_RETURN
abort(Context* c)
{
abort(c->system);
}
#ifndef NDEBUG
inline void
assert(Context* c, bool v)
{
assert(c->system, v);
}
#endif // not NDEBUG
inline void
expect(Context* c, bool v)
{
expect(c->system, v);
}
class Event {
public:
Event(Context* c):
next(0), stack(c->state->stack), locals(c->locals), promises(0), reads(0),
readCount(0), sequence(c->nextSequence++), stackReset(c->stackReset)
{
assert(c, c->logicalIp >= 0);
2008-04-19 07:03:59 +00:00
LogicalInstruction* i = c->logicalCode + c->logicalIp;
if (i->lastEvent) {
i->lastEvent->next = this;
} else {
2008-04-19 07:03:59 +00:00
i->firstEvent = this;
}
2008-04-19 07:03:59 +00:00
i->lastEvent = this;
2008-04-20 05:23:08 +00:00
if (c->stackReset) {
2008-04-20 19:35:36 +00:00
// fprintf(stderr, "stack reset\n");
2008-04-20 05:23:08 +00:00
c->stackReset = false;
}
}
Event(Context*, unsigned sequence, Stack* stack, Local* locals):
next(0), stack(stack), locals(locals), promises(0), reads(0), readCount(0),
2008-04-20 19:35:36 +00:00
sequence(sequence), stackReset(false)
{ }
virtual ~Event() { }
virtual void compile(Context* c) = 0;
Event* next;
Stack* stack;
2008-07-05 20:21:13 +00:00
Value** locals;
CodePromise* promises;
Read* reads;
unsigned readCount;
unsigned sequence;
2008-04-20 05:23:08 +00:00
bool stackReset;
};
int
localOffset(Context* c, int v)
{
int parameterFootprint = c->parameterFootprint * BytesPerWord;
v *= BytesPerWord;
if (v < parameterFootprint) {
return (parameterFootprint - v - BytesPerWord) + (BytesPerWord * 2);
} else {
return -(v + BytesPerWord - parameterFootprint);
}
}
2008-04-18 00:39:41 +00:00
bool
findSite(Context*, Value* v, Site* site)
{
for (Site* s = v->sites; s; s = s->next) {
if (s == site) return true;
}
return false;
}
void
2008-07-17 23:34:38 +00:00
addSite(Context* c, Stack* stack, Value** locals, unsigned size, Value* v,
Site* s)
2008-04-19 00:19:45 +00:00
{
if (not findSite(c, v, s)) {
// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), v);
2008-07-17 23:34:38 +00:00
s->acquire(c, stack, locals, size, v);
s->next = v->sites;
v->sites = s;
2008-04-19 00:19:45 +00:00
}
}
2008-04-18 00:39:41 +00:00
void
2008-04-19 07:03:59 +00:00
removeSite(Context* c, Value* v, Site* s)
2008-04-18 00:39:41 +00:00
{
for (Site** p = &(v->sites); *p;) {
if (s == *p) {
// fprintf(stderr, "remove site %p (%d) from %p\n", s, s->type(c), v);
2008-04-19 07:03:59 +00:00
s->release(c);
2008-04-18 00:39:41 +00:00
*p = (*p)->next;
break;
} else {
p = &((*p)->next);
}
}
}
2008-04-30 15:44:17 +00:00
void
removeMemorySites(Context* c, Value* v)
{
for (Site** p = &(v->sites); *p;) {
if ((*p)->type(c) == MemoryOperand) {
2008-05-15 20:00:57 +00:00
// fprintf(stderr, "remove site %p (%d) from %p\n", *p, (*p)->type(c), v);
2008-04-30 15:44:17 +00:00
(*p)->release(c);
*p = (*p)->next;
break;
} else {
p = &((*p)->next);
}
}
}
2008-04-19 07:03:59 +00:00
void
clearSites(Context* c, Value* v)
{
for (Site* s = v->sites; s; s = s->next) {
s->release(c);
}
v->sites = 0;
}
2008-07-05 20:21:13 +00:00
bool
valid(Read* r)
{
return r and r->valid();
}
bool
live(Value* v)
{
return valid(v->reads);
}
2008-04-19 00:19:45 +00:00
void
nextRead(Context* c, Value* v)
{
// fprintf(stderr, "pop read %p from %p; next: %p\n", v->reads, v, v->reads->next);
2008-04-19 07:03:59 +00:00
2008-04-19 00:19:45 +00:00
v->reads = v->reads->next;
2008-07-05 20:21:13 +00:00
if (not live(v)) {
2008-04-19 07:03:59 +00:00
clearSites(c, v);
2008-04-19 00:19:45 +00:00
}
}
class ConstantSite: public Site {
public:
ConstantSite(Promise* value): value(value) { }
2008-04-18 18:36:57 +00:00
virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : 1);
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return ConstantOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context*) {
return &value;
}
Assembler::Constant value;
};
ConstantSite*
constantSite(Context* c, Promise* value)
{
return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value);
}
ResolvedPromise*
resolved(Context* c, int64_t value)
{
return new (c->zone->allocate(sizeof(ResolvedPromise)))
ResolvedPromise(value);
}
ConstantSite*
constantSite(Context* c, int64_t value)
{
return constantSite(c, resolved(c, value));
}
class AddressSite: public Site {
public:
AddressSite(Promise* address): address(address) { }
2008-04-18 18:36:57 +00:00
virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : 3);
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return AddressOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context*) {
return &address;
}
Assembler::Address address;
};
AddressSite*
addressSite(Context* c, Promise* address)
{
return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address);
}
void
freeze(Register* r)
{
if (DebugRegisters) {
fprintf(stderr, "freeze %d to %d\n", r->number, r->freezeCount + 1);
}
++ r->freezeCount;
}
void
thaw(Register* r)
{
if (DebugRegisters) {
fprintf(stderr, "thaw %d to %d\n", r->number, r->freezeCount - 1);
}
-- r->freezeCount;
}
Register*
2008-07-17 23:34:38 +00:00
acquire(Context* c, uint32_t mask, Stack* stack, Value** locals,
unsigned newSize, Value* newValue, RegisterSite* newSite);
2008-04-19 00:19:45 +00:00
void
release(Context* c, Register* r);
2008-04-19 00:19:45 +00:00
2008-05-15 20:00:57 +00:00
Register*
validate(Context* c, uint32_t mask, Stack* stack, unsigned size,
Value* value, RegisterSite* site, Register* current);
2008-05-15 20:00:57 +00:00
class RegisterSite: public Site {
public:
RegisterSite(uint64_t mask, Register* low = 0, Register* high = 0):
mask(mask), low(low), high(high), register_(NoRegister, NoRegister)
{ }
2008-05-14 23:19:41 +00:00
void sync(Context* c UNUSED) {
assert(c, low);
register_.low = low->number;
register_.high = (high? high->number : NoRegister);
}
virtual unsigned copyCost(Context* c, Site* s) {
sync(c);
if (s and
(this == s or
2008-04-17 22:07:32 +00:00
(s->type(c) == RegisterOperand
and (static_cast<RegisterSite*>(s)->mask
& (static_cast<uint64_t>(1) << register_.low))
and (register_.high == NoRegister
or (static_cast<RegisterSite*>(s)->mask
& (static_cast<uint64_t>(1) << (register_.high + 32)))))))
{
return 0;
} else {
return 2;
}
}
2008-07-17 23:34:38 +00:00
virtual void acquire(Context* c, Stack* stack, Value** locals, unsigned size,
Value* v)
{
low = ::validate(c, mask, stack, locals, size, v, this, low);
if (size > BytesPerWord) {
::freeze(low);
2008-07-17 23:34:38 +00:00
high = ::validate(c, mask >> 32, stack, locals, size, v, this, high);
::thaw(low);
}
2008-04-19 00:19:45 +00:00
}
virtual void release(Context* c) {
assert(c, low);
::release(c, low);
if (high) {
::release(c, high);
}
}
2008-05-14 23:19:41 +00:00
virtual void freeze(Context* c UNUSED) {
assert(c, low);
::freeze(low);
if (high) {
::freeze(high);
}
}
2008-05-14 23:19:41 +00:00
virtual void thaw(Context* c UNUSED) {
assert(c, low);
::thaw(low);
if (high) {
::thaw(high);
}
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return RegisterOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
sync(c);
return &register_;
}
uint64_t mask;
Register* low;
Register* high;
Assembler::Register register_;
};
RegisterSite*
registerSite(Context* c, int low, int high = NoRegister)
{
2008-04-19 00:19:45 +00:00
assert(c, low != NoRegister);
assert(c, low < static_cast<int>(c->assembler->registerCount()));
assert(c, high == NoRegister
or high < static_cast<int>(c->assembler->registerCount()));
Register* hr;
if (high == NoRegister) {
hr = 0;
} else {
hr = c->registers[high];
}
return new (c->zone->allocate(sizeof(RegisterSite)))
RegisterSite(~static_cast<uint64_t>(0), c->registers[low], hr);
}
2008-04-17 22:07:32 +00:00
RegisterSite*
freeRegisterSite(Context* c, uint64_t mask = ~static_cast<uint64_t>(0))
{
return new (c->zone->allocate(sizeof(RegisterSite)))
RegisterSite(mask);
}
2008-04-17 22:07:32 +00:00
RegisterSite*
fixedRegisterSite(Context* c, int low, int high = NoRegister)
{
2008-05-18 03:32:14 +00:00
uint64_t mask;
if (high == NoRegister) {
mask = (~static_cast<uint64_t>(0) << 32)
| (static_cast<uint64_t>(1) << low);
} else {
mask = (static_cast<uint64_t>(1) << (high + 32))
| (static_cast<uint64_t>(1) << low);
}
return new (c->zone->allocate(sizeof(RegisterSite)))
RegisterSite(mask);
}
Register*
increment(Context* c, int i)
{
Register* r = c->registers[i];
if (DebugRegisters) {
fprintf(stderr, "increment %d to %d\n", r->number, r->refCount + 1);
}
++ r->refCount;
return r;
}
void
2008-05-14 23:19:41 +00:00
decrement(Context* c UNUSED, Register* r)
{
assert(c, r->refCount > 0);
if (DebugRegisters) {
fprintf(stderr, "decrement %d to %d\n", r->number, r->refCount - 1);
}
-- r->refCount;
}
class MemorySite: public Site {
public:
2008-04-17 02:55:38 +00:00
MemorySite(int base, int offset, int index, unsigned scale):
2008-07-05 20:21:13 +00:00
base(0), index(0), offsetPromise(0), value(base, offset, index, scale)
{ }
2008-05-14 23:19:41 +00:00
void sync(Context* c UNUSED) {
assert(c, base);
value.base = base->number;
value.index = (index? index->number : NoRegister);
}
virtual unsigned copyCost(Context* c, Site* s) {
sync(c);
if (s and
(this == s or
2008-04-17 22:07:32 +00:00
(s->type(c) == MemoryOperand
and static_cast<MemorySite*>(s)->value.base == value.base
and static_cast<MemorySite*>(s)->value.offset == value.offset
and static_cast<MemorySite*>(s)->value.index == value.index
and static_cast<MemorySite*>(s)->value.scale == value.scale)))
{
return 0;
} else {
return 4;
}
}
2008-07-17 23:34:38 +00:00
virtual void acquire(Context* c, Stack*, Value**, unsigned, Value*) {
base = increment(c, value.base);
2008-04-19 00:19:45 +00:00
if (value.index != NoRegister) {
index = increment(c, value.index);
2008-04-19 00:19:45 +00:00
}
}
virtual void release(Context* c) {
decrement(c, base);
if (index) {
decrement(c, index);
2008-04-19 00:19:45 +00:00
}
}
virtual OperandType type(Context*) {
2008-04-17 22:07:32 +00:00
return MemoryOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
sync(c);
return &value;
}
Register* base;
Register* index;
Assembler::Memory value;
};
MemorySite*
memorySite(Context* c, int base, int offset = 0, int index = NoRegister,
unsigned scale = 1)
{
return new (c->zone->allocate(sizeof(MemorySite)))
MemorySite(base, offset, index, scale);
}
2008-07-05 20:21:13 +00:00
Site*
targetOrNull(Context* c, Value* v, Read* r)
{
2008-07-05 20:21:13 +00:00
if (v->target) {
return v->target;
2008-05-22 17:15:18 +00:00
} else {
2008-07-05 20:21:13 +00:00
Site* s = r->pickSite(c, v);
if (s) return s;
return r->allocateSite(c);
2008-05-22 17:15:18 +00:00
}
}
2008-07-05 20:21:13 +00:00
Site*
targetOrNull(Context* c, Value* v)
{
2008-07-05 20:21:13 +00:00
if (v->target) {
return v->target;
} else if (live(v)) {
Site* s = r->pickSite(c, v);
if (s) return s;
return r->allocateSite(c);
}
return 0;
}
2008-05-06 21:13:02 +00:00
Site*
2008-07-05 20:21:13 +00:00
pickSite(Context* c, Value* value, uint8_t typeMask, uint64_t registerMask,
int frameIndex)
2008-05-06 21:13:02 +00:00
{
2008-07-05 20:21:13 +00:00
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
for (Site* s = value->sites; s; s = s->next) {
if (s->match(c, typeMask, registerMask, frameIndex)) {
unsigned v = s->copyCost(c, 0);
if (v < copyCost) {
site = s;
copyCost = v;
}
}
2008-05-06 21:13:02 +00:00
}
2008-07-05 20:21:13 +00:00
return site;
2008-05-06 21:13:02 +00:00
}
Site*
2008-07-05 20:21:13 +00:00
allocateSite(Context* c, uint8_t typeMask, uint64_t registerMask,
int frameIndex)
2008-05-06 21:13:02 +00:00
{
2008-07-05 20:21:13 +00:00
if ((typeMask & (1 << RegisterOperand)) and registerMask) {
return freeRegisterSite(c, registerMask);
} else if (frameIndex >= 0) {
return frameSite(c, frameIndex);
} else {
abort(c);
2008-05-06 21:13:02 +00:00
}
}
2008-07-05 20:21:13 +00:00
class TargetRead: public Read {
public:
2008-07-05 20:21:13 +00:00
TargetRead(Value* target, uint8_t typeMask, uint64_t registerMask,
int frameIndex):
target(target), registerMask(registerMask), typeMask(typeMask),
frameIndex(frameIndex)
{ }
virtual Site* pickSite(Context* c, Value* value) {
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
2008-05-06 21:13:02 +00:00
}
2008-07-05 20:21:13 +00:00
virtual Site* allocateSite(Context* c) {
if (target) {
Site* s = targetOrNull(c, target);
if (s and s->match(c, typeMask, registerMask, frameIndex)) {
return s;
}
}
return ::allocateSite(c, typeMask, registerMask, frameIndex);
2008-05-06 21:13:02 +00:00
}
2008-07-05 20:21:13 +00:00
virtual void intersect(uint8_t* typeMask, uint64_t* registerMask,
int* frameIndex)
{
*typeMask &= this->typeMask;
*registerMask &= this->registerMask;
if (*frameIndex == AnyFrameIndex) {
*frameIndex = this->frameIndex;
} else if (this->frameIndex != AnyFrameIndex
and *frameIndex != this->frameIndex)
{
*frameIndex = NoFrameIndex;
}
2008-05-06 21:13:02 +00:00
}
2008-07-05 20:21:13 +00:00
virtual bool valid() {
return true;
2008-05-06 21:13:02 +00:00
}
2008-07-05 20:21:13 +00:00
Value* target;
uint64_t registerMask;
uint8_t typeMask;
int frameIndex;
2008-05-06 21:13:02 +00:00
};
2008-07-05 20:21:13 +00:00
TargetRead*
targetRead(Context* c, Value* target = 0,
uint8_t typeMask = ~static_cast<uint8_t>(0),
uint64_t registerMask = ~static_cast<uint64_t>(0),
int frameIndex = NoFrameIndex)
{
return new (c->zone->allocate(sizeof(TargetRead)))
TargetRead(target, typeMask, registerMask);
}
class MultiRead: public Read {
2008-05-06 21:13:02 +00:00
public:
2008-07-05 20:21:13 +00:00
MultiRead():
reads(0)
{ }
2008-07-05 20:21:13 +00:00
virtual Site* pickSite(Context* c) {
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
intersect(&typeMask, &registerMask, &frameIndex);
2008-07-05 20:21:13 +00:00
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
}
virtual Site* allocateSite(Context* c) {
uint8_t typeMask = ~static_cast<uint8_t>(0);
uint64_t registerMask = ~static_cast<uint64_t>(0);
int frameIndex = AnyFrameIndex;
intersect(&typeMask, &registerMask, &frameIndex);
return ::allocateSite(c, typeMask, registerMask, frameIndex);
}
virtual void intersect(uint8_t* typeMask, uint64_t* registerMask,
int* frameIndex)
{
for (Cell* cell = reads; cell; cell = cell->next) {
Read* r = static_cast<Read*>(cell->value);
r->intersect(&typeMask, &registerMask, &frameIndex);
}
2008-07-05 20:21:13 +00:00
}
2008-07-05 20:21:13 +00:00
virtual bool valid() {
for (Cell* cell = reads; cell; cell = cell->next) {
Read* r = static_cast<Read*>(cell->value);
if (r->valid()) {
return true;
}
}
2008-07-05 20:21:13 +00:00
return false;
}
2008-07-05 20:21:13 +00:00
Cell* reads;
};
2008-07-05 20:21:13 +00:00
MultiRead*
multiRead(Context* c)
{
2008-07-05 20:21:13 +00:00
return new (c->zone->allocate(sizeof(MultiRead))) MultiRead;
}
2008-05-06 21:13:02 +00:00
VirtualSite*
anyRegisterSite(Context* c)
{
2008-05-06 21:13:02 +00:00
return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast<uint64_t>(0));
}
VirtualSite*
registerOrConstantSite(Context* c)
{
return virtualSite(c, 0, (1 << RegisterOperand) | (1 << ConstantOperand),
~static_cast<uint64_t>(0));
}
Site*
targetOrRegister(Context* c, Value* v)
{
Site* s = targetOrNull(c, v);
if (s) {
return s;
} else {
return freeRegisterSite(c);
}
}
2008-04-17 22:07:32 +00:00
Site*
pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
{
Site* site = 0;
unsigned copyCost = 0xFFFFFFFF;
for (Site* s = sites; s; s = s->next) {
unsigned v = s->copyCost(c, target);
if (v < copyCost) {
site = s;
copyCost = v;
}
}
if (cost) *cost = copyCost;
return site;
}
bool
2008-07-05 20:21:13 +00:00
trySteal(Context* c, Register* r, Stack* stack, Value** locals)
{
assert(c, r->refCount == 0);
Value* v = r->value;
2008-07-17 23:34:38 +00:00
assert(c, v->reads);
if (DebugRegisters) {
fprintf(stderr, "try steal %d from %p: next: %p\n",
r->number, v, v->sites->next);
}
if (v->sites->next == 0) {
2008-07-17 23:34:38 +00:00
Site* saveSite = 0;
for (unsigned i = 0; i < localFootprint; ++i) {
if (locals[i] == v) {
saveSite = frameSite(c, i);
break;
}
}
2008-07-17 23:34:38 +00:00
if (saveSite == 0) {
for (Stack* s = stack; s and (not s->pushed); s = s->next) {
if (s->value == v) {
uint8_t typeMask;
uint64_t registerMask;
int frameIndex = AnyFrameIndex;
v->reads->intersect(&typeMask, &registerMask, &frameIndex);
if (frameIndex >= 0) {
saveSite = frameSite(c, frameIndex);
} else {
saveSite = stackSite(c, s);
}
break;
}
2008-05-18 01:26:36 +00:00
}
2008-07-17 23:34:38 +00:00
}
if (saveSite) {
apply(c, Move, r->size, r->site, saveSite);
addSite(c, 0, 0, r->size, v, saveSite);
} else {
2008-05-18 01:26:36 +00:00
if (DebugRegisters) {
fprintf(stderr, "unable to steal %d from %p\n", r->number, v);
}
return false;
}
}
removeSite(c, v, r->site);
return true;
}
2008-04-21 00:21:48 +00:00
bool
used(Context* c, Register* r)
{
Value* v = r->value;
return v and findSite(c, v, r->site);
}
bool
usedExclusively(Context* c, Register* r)
{
return used(c, r) and r->value->sites->next == 0;
}
unsigned
registerCost(Context* c, Register* r)
{
if (r->reserved or r->freezeCount) {
return 6;
}
unsigned cost = 0;
if (used(c, r)) {
++ cost;
if (usedExclusively(c, r)) {
cost += 2;
}
}
if (r->refCount) {
cost += 2;
}
return cost;
}
Register*
pickRegister(Context* c, uint32_t mask)
{
Register* register_ = 0;
unsigned cost = 5;
for (int i = c->assembler->registerCount() - 1; i >= 0; --i) {
if ((1 << i) & mask) {
Register* r = c->registers[i];
if ((static_cast<uint32_t>(1) << i) == mask) {
return r;
}
unsigned myCost = registerCost(c, r);
if (myCost < cost) {
register_ = r;
cost = myCost;
}
}
}
expect(c, register_);
return register_;
}
void
swap(Context* c, Register* a, Register* b)
{
assert(c, a != b);
assert(c, a->number != b->number);
Assembler::Register ar(a->number);
Assembler::Register br(b->number);
c->assembler->apply
(Swap, BytesPerWord, RegisterOperand, &ar, RegisterOperand, &br);
c->registers[a->number] = b;
c->registers[b->number] = a;
int t = a->number;
a->number = b->number;
b->number = t;
}
Register*
2008-07-17 23:34:38 +00:00
replace(Context* c, Stack* stack, Value** locals, Register* r)
{
uint32_t mask = (r->freezeCount? r->site->mask : ~0);
2008-05-15 20:00:57 +00:00
freeze(r);
2008-07-17 23:34:38 +00:00
Register* s = acquire(c, mask, stack, locals, r->size, r->value, r->site);
thaw(r);
2008-05-15 20:00:57 +00:00
2008-05-18 01:26:36 +00:00
if (DebugRegisters) {
fprintf(stderr, "replace %d with %d\n", r->number, s->number);
}
swap(c, r, s);
2008-05-15 20:00:57 +00:00
return s;
}
Register*
2008-07-17 23:34:38 +00:00
acquire(Context* c, uint32_t mask, Stack* stack, Value** locals,
unsigned newSize, Value* newValue, RegisterSite* newSite)
2008-04-17 22:07:32 +00:00
{
Register* r = pickRegister(c, mask);
if (r->reserved) return r;
2008-04-19 00:19:45 +00:00
if (DebugRegisters) {
2008-07-17 23:34:38 +00:00
fprintf(stderr, "acquire %d, value %p, site %p freeze count %d "
"ref count %d used %d used exclusively %d\n",
r->number, newValue, newSite, r->freezeCount, r->refCount,
used(c, r), usedExclusively(c, r));
}
2008-04-19 00:19:45 +00:00
if (r->refCount) {
r = replace(c, stack, r);
} else {
Value* oldValue = r->value;
if (oldValue
and oldValue != newValue
and findSite(c, oldValue, r->site))
{
2008-07-17 23:34:38 +00:00
if (not trySteal(c, r, stack, locals)) {
r = replace(c, stack, r);
}
2008-04-17 22:07:32 +00:00
}
}
r->size = newSize;
r->value = newValue;
r->site = newSite;
2008-04-21 00:21:48 +00:00
return r;
2008-04-17 22:07:32 +00:00
}
2008-04-19 00:19:45 +00:00
void
release(Context*, Register* r)
2008-04-19 00:19:45 +00:00
{
if (DebugRegisters) {
fprintf(stderr, "release %d\n", r->number);
}
r->size = 0;
r->value = 0;
r->site = 0;
2008-04-19 00:19:45 +00:00
}
2008-05-15 20:00:57 +00:00
Register*
2008-07-17 23:34:38 +00:00
validate(Context* c, uint32_t mask, Stack* stack, Value** locals,
unsigned size, Value* value, RegisterSite* site, Register* current)
2008-05-15 20:00:57 +00:00
{
if (current and (mask & (1 << current->number))) {
if (current->reserved or current->value == value) {
return current;
}
if (current->value == 0) {
current->size = size;
current->value = value;
current->site = site;
return current;
2008-05-18 01:26:36 +00:00
} else {
abort(c);
}
}
2008-07-17 23:34:38 +00:00
Register* r = acquire(c, mask, stack, locals, size, value, site);
if (current and current != r) {
2008-05-15 20:00:57 +00:00
release(c, current);
Assembler::Register rr(r->number);
Assembler::Register cr(current->number);
c->assembler->apply
(Move, BytesPerWord, RegisterOperand, &cr, RegisterOperand, &rr);
}
return r;
2008-05-15 20:00:57 +00:00
}
2008-04-17 02:55:38 +00:00
void
2008-04-17 22:07:32 +00:00
apply(Context* c, UnaryOperation op, unsigned size, Site* a)
2008-04-17 02:55:38 +00:00
{
OperandType type = a->type(c);
Assembler::Operand* operand = a->asAssemblerOperand(c);
2008-03-15 20:24:04 +00:00
2008-04-17 02:55:38 +00:00
c->assembler->apply(op, size, type, operand);
}
2008-04-17 02:55:38 +00:00
void
2008-04-17 22:07:32 +00:00
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b)
2008-04-17 02:55:38 +00:00
{
OperandType aType = a->type(c);
Assembler::Operand* aOperand = a->asAssemblerOperand(c);
2008-04-17 02:55:38 +00:00
OperandType bType = b->type(c);
Assembler::Operand* bOperand = b->asAssemblerOperand(c);
2008-02-17 22:29:04 +00:00
2008-04-17 02:55:38 +00:00
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
}
void
2008-07-05 20:21:13 +00:00
insertRead(Context* c, Event* event, int sequence, Value* v, Read* r)
{
event->reads = r;
++ event->readCount;
2008-04-17 20:48:26 +00:00
2008-04-19 20:41:31 +00:00
// fprintf(stderr, "add read %p to %p\n", r, v);
2008-04-19 07:03:59 +00:00
2008-04-20 19:35:36 +00:00
if (sequence >= 0) {
2008-04-17 20:48:26 +00:00
for (Read** p = &(v->reads); *p;) {
2008-04-20 19:35:36 +00:00
if ((*p)->event->sequence > static_cast<unsigned>(sequence)) {
2008-04-17 20:48:26 +00:00
r->next = *p;
*p = r;
break;
} else {
p = &((*p)->next);
}
}
}
2008-04-17 02:55:38 +00:00
2008-04-17 20:48:26 +00:00
if (r->next == 0) {
if (v->lastRead) {
v->lastRead->next = r;
} else {
v->reads = r;
}
v->lastRead = r;
2008-04-17 02:55:38 +00:00
}
2008-04-17 20:48:26 +00:00
}
void
2008-07-05 20:21:13 +00:00
addRead(Context* c, Value* v, Read* r)
2008-04-17 20:48:26 +00:00
{
2008-07-05 20:21:13 +00:00
insertRead(c, c->logicalCode[c->logicalIp].lastEvent, -1, v, r);
}
2008-04-19 00:19:45 +00:00
Site*
pushSite(Context*, PushEvent*);
class PushEvent: public Event {
public:
2008-04-19 07:03:59 +00:00
PushEvent(Context* c, Stack* s):
Event(c), s(s), active(false)
2008-04-19 00:19:45 +00:00
{
2008-04-19 07:03:59 +00:00
assert(c, s->pushEvent == 0);
s->pushEvent = this;
2008-07-05 20:21:13 +00:00
addRead(c, s->value, s->geometry->size * BytesPerWord, pushSite(c, this));
2008-04-19 00:19:45 +00:00
}
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "PushEvent.compile active: %d\n", active);
2008-04-19 21:52:45 +00:00
}
2008-04-19 00:19:45 +00:00
if (active) {
2008-04-19 20:41:31 +00:00
pushNow(c, s);
2008-04-19 00:19:45 +00:00
}
2008-04-19 07:03:59 +00:00
nextRead(c, s->value);
2008-04-19 00:19:45 +00:00
}
virtual bool skipMove(unsigned size) {
return active and size >= BytesPerWord;
}
2008-04-19 07:03:59 +00:00
Stack* s;
2008-04-19 00:19:45 +00:00
bool active;
};
2008-07-05 20:21:13 +00:00
void
appendPush(Context* c, Stack* s)
{
if (DebugAppend) {
fprintf(stderr, "appendPush\n");
}
new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c, s);
}
void
appendPush(Context* c)
{
appendPush(c, c->state->stack);
}
class PushedEvent: public Event {
public:
PushedEvent(Context* c, Stack* s):
Event(c), s(s)
{ }
virtual void compile(Context* c) {
if (DebugCompile) {
fprintf(stderr, "PushedEvent.compile\n");
}
assert(c, c->stackPadding == 0);
assert(c, s->geometry->padding == 0);
s->pushSite = s->value->sites = pushSite(&c, s);
}
Stack* s;
};
void
appendPushed(Context* c, Stack* s)
{
if (DebugAppend) {
fprintf(stderr, "appendPushed\n");
}
new (c->zone->allocate(sizeof(PushedEvent))) PushedEvent(c, s);
}
2008-04-17 22:07:32 +00:00
void
push(Context* c, unsigned size, Value* v);
2008-04-19 20:41:31 +00:00
void
ignore(Context* c, unsigned count)
{
if (count) {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, count * BytesPerWord));
c->assembler->apply
(Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack);
}
}
void
cleanStack(Context* c, Stack* stack, Local* locals, Read* reads)
{
for (Local* l = locals; l; l = l->next) {
2008-05-20 19:11:42 +00:00
l->reuse = false;
}
for (Stack* s = stack; s; s = s->next) {
clearSites(c, s->value);
}
for (Stack* s = stack; s; s = s->next) {
if (s->pushSite) {
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, s->geometry->size * BytesPerWord, s->value,
s->pushSite);
}
}
for (Read* r = reads; r; r = r->eventNext) {
nextRead(c, r->value);
}
}
void
resetLocals(Context* c)
{
for (Local* l = c->locals; l; l = l->next) {
c->localTable[l->index] = 0;
}
c->locals = 0;
}
CodePromise*
codePromise(Context* c, Event* e)
{
return e->promises = new (c->zone->allocate(sizeof(CodePromise)))
CodePromise(c, e->promises);
}
CodePromise*
codePromise(Context* c, int offset)
{
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
}
2008-04-17 02:55:38 +00:00
class CallEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-05-06 21:13:02 +00:00
CallEvent(Context* c, Value* address, unsigned flags,
2008-04-18 04:16:20 +00:00
TraceHandler* traceHandler, Value* result, unsigned resultSize,
2008-07-05 20:21:13 +00:00
Stack* argumentStack, unsigned argumentCount, unsigned padding):
2008-04-17 02:55:38 +00:00
Event(c),
address(address),
traceHandler(traceHandler),
2008-04-17 20:48:26 +00:00
result(result),
flags(flags),
2008-04-18 04:16:20 +00:00
resultSize(resultSize),
2008-07-05 20:21:13 +00:00
argumentFootprint(0),
paddding(padding)
{
2008-05-15 20:00:57 +00:00
uint32_t mask = ~0;
2008-04-19 00:19:45 +00:00
Stack* s = argumentStack;
2008-04-21 00:21:48 +00:00
unsigned index = 0;
2008-04-19 00:19:45 +00:00
for (unsigned i = 0; i < argumentCount; ++i) {
Site* target;
2008-04-21 00:21:48 +00:00
if (index < c->assembler->argumentRegisterCount()) {
2008-05-15 20:00:57 +00:00
int r = c->assembler->argumentRegister(index);
target = fixedRegisterSite(c, r);
2008-05-15 20:00:57 +00:00
mask &= ~(1 << r);
2008-04-19 00:19:45 +00:00
} else {
target = 0;
s->pushEvent->active = true;
2008-07-05 20:21:13 +00:00
argumentFootprint += s->geometry->size;
2008-04-19 00:19:45 +00:00
}
2008-07-05 20:21:13 +00:00
addRead(c, s->value, s->geometry->size * BytesPerWord, target);
index += s->geometry->size;
2008-04-19 00:19:45 +00:00
s = s->next;
}
addRead(c, address, BytesPerWord, virtualSite
(c, 0, ~0, (static_cast<uint64_t>(mask) << 32) | mask));
2008-05-15 20:00:57 +00:00
for (Stack* s = stack; s; s = s->next) {
s->pushEvent->active = true;
2008-07-05 20:21:13 +00:00
addRead(c, s->value, s->geometry->size * BytesPerWord, virtualSite
2008-05-15 20:00:57 +00:00
(c, 0, ~0, (static_cast<uint64_t>(mask) << 32) | mask));
}
resetLocals(c);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "CallEvent.compile\n");
}
pushNow(c, stack);
2008-07-05 20:21:13 +00:00
pad(c, padding);
2008-04-17 02:55:38 +00:00
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
apply(c, type, BytesPerWord, address->source);
if (traceHandler) {
traceHandler->handleTrace(codePromise(c, c->assembler->length()));
}
cleanStack(c, stack, locals, reads);
2008-04-19 00:19:45 +00:00
2008-07-05 20:21:13 +00:00
if (resultSize and live(result)) {
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, resultSize, result, registerSite
2008-04-19 00:19:45 +00:00
(c, c->assembler->returnLow(),
resultSize > BytesPerWord ?
c->assembler->returnHigh() : NoRegister));
}
2008-04-18 00:39:41 +00:00
2008-04-19 07:03:59 +00:00
if (argumentFootprint and ((flags & Compiler::NoReturn) == 0)) {
2008-04-19 20:41:31 +00:00
ignore(c, argumentFootprint);
2008-04-17 20:48:26 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
Value* address;
TraceHandler* traceHandler;
Value* result;
2008-04-17 20:48:26 +00:00
unsigned flags;
2008-04-18 04:16:20 +00:00
unsigned resultSize;
2008-04-18 03:47:42 +00:00
unsigned argumentFootprint;
2008-07-05 20:21:13 +00:00
unsigned padding;
2008-02-11 17:21:41 +00:00
};
2008-02-11 17:21:41 +00:00
void
2008-05-06 21:13:02 +00:00
appendCall(Context* c, Value* address, unsigned flags,
2008-04-18 04:16:20 +00:00
TraceHandler* traceHandler, Value* result, unsigned resultSize,
2008-07-05 20:21:13 +00:00
Stack* argumentStack, unsigned argumentCount, unsigned padding)
2008-02-11 17:21:41 +00:00
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendCall\n");
}
2008-04-18 03:47:42 +00:00
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(CallEvent)))
2008-05-06 21:13:02 +00:00
CallEvent(c, address, flags, traceHandler, result,
2008-07-05 20:21:13 +00:00
resultSize, argumentStack, argumentCount, unsigned padding);
2008-02-11 17:21:41 +00:00
}
2008-04-17 02:55:38 +00:00
class ReturnEvent: public Event {
public:
2008-04-17 02:55:38 +00:00
ReturnEvent(Context* c, unsigned size, Value* value):
Event(c), value(value)
{
if (value) {
addRead(c, value, size, fixedRegisterSite
2008-04-17 02:55:38 +00:00
(c, c->assembler->returnLow(),
size > BytesPerWord ?
c->assembler->returnHigh() : NoRegister));
}
2008-03-15 20:24:04 +00:00
}
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "ReturnEvent.compile\n");
}
2008-04-19 00:19:45 +00:00
if (value) {
nextRead(c, value);
}
2008-04-17 02:55:38 +00:00
Assembler::Register base(c->assembler->base());
Assembler::Register stack(c->assembler->stack());
2008-04-17 22:07:32 +00:00
c->assembler->apply(Move, BytesPerWord, RegisterOperand, &base,
RegisterOperand, &stack);
c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &base);
2008-04-17 02:55:38 +00:00
c->assembler->apply(Return);
}
2008-04-17 02:55:38 +00:00
Value* value;
};
void
2008-04-17 22:07:32 +00:00
appendReturn(Context* c, unsigned size, Value* value)
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendReturn\n");
}
2008-04-18 03:47:42 +00:00
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
}
2008-04-17 02:55:38 +00:00
class MoveEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
2008-04-17 02:55:38 +00:00
MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst, Site* srcTarget, VirtualSite* dstTarget):
Event(c), type(type), size(size), src(src), dst(dst), dstTarget(dstTarget)
{
2008-05-06 21:13:02 +00:00
addRead(c, src, size, srcTarget);
2008-03-15 20:24:04 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "MoveEvent.compile\n");
}
2008-03-15 20:24:04 +00:00
2008-07-05 20:21:13 +00:00
bool isLoad = not valid(src->reads->next);
bool isStore = not valid(dst->reads);
2008-07-05 20:21:13 +00:00
Site* target = targetOrRegister(c, dst);
unsigned cost = src->source->copyCost(c, target);
if (cost == 0 and (isLoad or isStore)) {
target = src->source;
}
2008-04-19 00:19:45 +00:00
assert(c, isLoad or isStore or target != src->source);
2008-05-18 01:26:36 +00:00
if (target == src->source) {
removeSite(c, src, target);
2008-05-18 01:26:36 +00:00
}
2008-04-19 00:19:45 +00:00
if (not isStore) {
2008-07-17 23:34:38 +00:00
addSite(c, stack, locals, size, dst, target);
}
2008-05-18 01:26:36 +00:00
if (cost or type != Move) {
if (match(c, target, dstTarget->typeMask, dstTarget->registerMask)) {
apply(c, type, size, src->source, target);
} else {
assert(c, dstTarget->typeMask & (1 << RegisterOperand));
Site* tmpTarget = freeRegisterSite(c, dstTarget->registerMask);
2008-07-17 23:34:38 +00:00
addSite(c, stack, locals, size, dst, tmpTarget);
apply(c, type, size, src->source, tmpTarget);
if (isStore) {
2008-05-18 01:26:36 +00:00
removeSite(c, dst, tmpTarget);
apply(c, Move, size, tmpTarget, target);
} else {
removeSite(c, dst, target);
}
}
}
if (isStore) {
2008-04-20 19:35:36 +00:00
removeSite(c, dst, target);
}
2008-05-18 01:26:36 +00:00
nextRead(c, src);
2007-12-11 21:26:59 +00:00
}
2008-04-17 02:55:38 +00:00
BinaryOperation type;
unsigned size;
2008-04-17 02:55:38 +00:00
Value* src;
Value* dst;
VirtualSite* dstTarget;
2008-02-11 17:21:41 +00:00
};
2007-12-11 21:26:59 +00:00
void
2008-04-17 02:55:38 +00:00
appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst)
2007-12-11 21:26:59 +00:00
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendMove\n");
}
2008-04-18 03:47:42 +00:00
2008-05-06 21:13:02 +00:00
VirtualSite* srcTarget = virtualSite(c, dst);
VirtualSite* dstTarget = virtualSite(c);
bool thunk;
c->assembler->plan(type, size,
&(srcTarget->typeMask), &(srcTarget->registerMask),
&(dstTarget->typeMask), &(dstTarget->registerMask),
&thunk);
assert(c, not thunk); // todo
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent(c, type, size, src, dst, srcTarget, dstTarget);
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
ConstantSite*
findConstantSite(Context* c, Value* v)
{
for (Site* s = v->sites; s; s = s->next) {
if (s->type(c) == ConstantOperand) {
return static_cast<ConstantSite*>(s);
}
}
return 0;
}
2008-04-17 02:55:38 +00:00
class CompareEvent: public Event {
2008-02-11 17:21:41 +00:00
public:
CompareEvent(Context* c, unsigned size, Value* first, Value* second,
Site* firstTarget, Site* secondTarget):
2008-04-17 02:55:38 +00:00
Event(c), size(size), first(first), second(second)
{
addRead(c, first, size, firstTarget);
addRead(c, second, size, secondTarget);
2008-02-11 17:21:41 +00:00
}
2007-12-20 01:42:12 +00:00
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "CompareEvent.compile\n");
}
2008-03-15 20:24:04 +00:00
ConstantSite* firstConstant = findConstantSite(c, first);
ConstantSite* secondConstant = findConstantSite(c, second);
if (firstConstant and secondConstant) {
int64_t d = firstConstant->value.value->value()
- secondConstant->value.value->value();
if (d < 0) {
c->constantCompare = CompareLess;
} else if (d > 0) {
c->constantCompare = CompareGreater;
} else {
c->constantCompare = CompareEqual;
}
} else {
c->constantCompare = CompareNone;
apply(c, Compare, size, first->source, second->source);
}
2008-04-19 00:19:45 +00:00
nextRead(c, first);
nextRead(c, second);
2007-12-11 21:26:59 +00:00
}
2008-02-11 17:21:41 +00:00
2008-04-17 02:55:38 +00:00
unsigned size;
Value* first;
Value* second;
2008-02-11 17:21:41 +00:00
};
2007-12-11 21:26:59 +00:00
void
2008-04-17 02:55:38 +00:00
appendCompare(Context* c, unsigned size, Value* first, Value* second)
2007-12-11 21:26:59 +00:00
{
VirtualSite* firstTarget = virtualSite(c);
VirtualSite* secondTarget = virtualSite(c);
bool thunk;
c->assembler->plan(Compare, size,
&(firstTarget->typeMask), &(firstTarget->registerMask),
&(secondTarget->typeMask), &(secondTarget->registerMask),
&thunk);
assert(c, not thunk); // todo
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendCompare\n");
}
2008-04-18 03:47:42 +00:00
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(CompareEvent)))
CompareEvent(c, size, first, second, firstTarget, secondTarget);
2008-02-11 17:21:41 +00:00
}
void
preserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s,
Read* read)
{
assert(c, v->sites == s);
Site* r = targetOrNull(c, read);
if (r == 0 or r == s) r = freeRegisterSite(c);
2008-07-17 23:34:38 +00:00
addSite(c, stack, locals, size, v, r);
apply(c, Move, size, s, r);
}
void
maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
{
2008-07-05 20:21:13 +00:00
if (valid(v->reads->next) and v->sites->next == 0) {
preserve(c, stack, size, v, s, v->reads->next);
}
}
2008-02-11 17:21:41 +00:00
class CombineEvent: public Event {
public:
2008-04-17 02:55:38 +00:00
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result, Site* firstTarget,
Site* secondTarget):
2008-04-17 02:55:38 +00:00
Event(c), type(type), size(size), first(first), second(second),
result(result)
{
// todo: we should really specify the sizes of each operand
// seperately for binary operations. The following is a hack
// until then.
unsigned firstSize;
switch (type) {
case ShiftLeft:
case ShiftRight:
case UnsignedShiftRight:
firstSize = 4;
break;
default:
firstSize = size;
break;
}
addRead(c, first, firstSize, firstTarget);
addRead(c, second, size, secondTarget);
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "CombineEvent.compile\n");
}
maybePreserve(c, stack, size, second, second->source);
2008-04-17 02:55:38 +00:00
apply(c, type, size, first->source, second->source);
2008-04-19 00:19:45 +00:00
nextRead(c, first);
nextRead(c, second);
2008-04-18 00:39:41 +00:00
removeSite(c, second, second->source);
2008-07-05 20:21:13 +00:00
if (live(result)) {
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, size, result, second->source);
2008-04-21 00:21:48 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
BinaryOperation type;
unsigned size;
2008-04-17 02:55:38 +00:00
Value* first;
Value* second;
2008-04-17 22:07:32 +00:00
Value* result;
2008-02-11 17:21:41 +00:00
};
void
appendStackSync(Context* c);
2008-05-06 21:13:02 +00:00
Value*
value(Context* c, Site* site = 0, Site* target = 0)
{
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
}
2008-02-11 17:21:41 +00:00
void
2008-04-17 02:55:38 +00:00
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result)
2008-02-11 17:21:41 +00:00
{
2008-05-06 21:13:02 +00:00
VirtualSite* firstTarget = virtualSite(c);
VirtualSite* secondTarget = virtualSite(c, result);
bool thunk;
c->assembler->plan(type, size,
&(firstTarget->typeMask), &(firstTarget->registerMask),
&(secondTarget->typeMask), &(secondTarget->registerMask),
&thunk);
if (thunk) {
2008-05-16 00:35:17 +00:00
secondTarget->value = 0;
2008-05-06 21:13:02 +00:00
Stack* oldStack = c->state->stack;
::push(c, size, second);
::push(c, size, first);
2008-04-18 03:47:42 +00:00
2008-05-06 21:13:02 +00:00
Stack* argumentStack = c->state->stack;
c->state->stack = oldStack;
appendCall(c, value(c, constantSite(c, c->client->getThunk(type, size))),
0, 0, result, size, argumentStack, 2);
} else {
if (DebugAppend) {
fprintf(stderr, "appendCombine\n");
}
firstTarget->typeMask &= ~(1 << MemoryOperand);
secondTarget->typeMask &= ~(1 << MemoryOperand);
new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, first, second, result, firstTarget,
secondTarget);
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
class TranslateEvent: public Event {
public:
2008-04-17 02:55:38 +00:00
TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result, Site* target):
2008-04-17 02:55:38 +00:00
Event(c), type(type), size(size), value(value), result(result)
{
addRead(c, value, size, target);
2008-03-15 20:24:04 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "TranslateEvent.compile\n");
}
maybePreserve(c, stack, size, value, value->source);
2008-04-17 02:55:38 +00:00
apply(c, type, size, value->source);
2008-04-19 00:19:45 +00:00
nextRead(c, value);
2008-04-18 00:39:41 +00:00
removeSite(c, value, value->source);
2008-07-05 20:21:13 +00:00
if (live(result)) {
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, size, result, value->source);
2008-04-21 00:21:48 +00:00
}
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
UnaryOperation type;
unsigned size;
2008-04-17 02:55:38 +00:00
Value* value;
Value* result;
2008-02-11 17:21:41 +00:00
};
2008-02-11 17:21:41 +00:00
void
2008-04-17 02:55:38 +00:00
appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result)
2008-02-11 17:21:41 +00:00
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendTranslate\n");
}
2008-04-18 03:47:42 +00:00
2008-05-06 21:13:02 +00:00
VirtualSite* target = virtualSite(c, result);
bool thunk;
c->assembler->plan
(type, size, &(target->typeMask), &(target->registerMask), &thunk);
assert(c, not thunk); // todo
target->typeMask &= ~(1 << MemoryOperand);
2008-02-11 17:21:41 +00:00
new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent(c, type, size, value, result, target);
2008-02-11 17:21:41 +00:00
}
2008-03-15 23:54:20 +00:00
class MemoryEvent: public Event {
public:
2008-04-17 20:48:26 +00:00
MemoryEvent(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result):
Event(c), base(base), displacement(displacement), index(index),
scale(scale), result(result)
2008-03-15 23:54:20 +00:00
{
2008-04-17 02:55:38 +00:00
addRead(c, base, BytesPerWord, anyRegisterSite(c));
if (index) addRead(c, index, BytesPerWord, registerOrConstantSite(c));
2008-03-15 23:54:20 +00:00
}
2008-04-17 22:07:32 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "MemoryEvent.compile\n");
}
2008-04-17 20:48:26 +00:00
int indexRegister;
int displacement = this->displacement;
unsigned scale = this->scale;
2008-04-17 20:48:26 +00:00
if (index) {
ConstantSite* constant = findConstantSite(c, index);
if (constant) {
indexRegister = NoRegister;
displacement += (constant->value.value->value() * scale);
scale = 1;
} else {
assert(c, index->source->type(c) == RegisterOperand);
indexRegister = static_cast<RegisterSite*>
(index->source)->register_.low;
}
2008-04-17 20:48:26 +00:00
} else {
indexRegister = NoRegister;
}
2008-04-18 00:39:41 +00:00
assert(c, base->source->type(c) == RegisterOperand);
int baseRegister = static_cast<RegisterSite*>(base->source)->register_.low;
2008-04-17 20:48:26 +00:00
2008-04-19 00:19:45 +00:00
nextRead(c, base);
if (index) {
if (BytesPerWord == 8 and indexRegister != NoRegister) {
apply(c, Move4To8, 8, index->source, index->source);
}
nextRead(c, index);
2008-04-19 00:19:45 +00:00
}
2008-04-19 21:52:45 +00:00
result->target = memorySite
(c, baseRegister, displacement, indexRegister, scale);
2008-07-17 23:34:38 +00:00
addSite(c, 0, 0, 0, result, result->target);
2008-03-15 23:54:20 +00:00
}
2008-04-17 02:55:38 +00:00
Value* base;
2008-04-17 20:48:26 +00:00
int displacement;
2008-04-17 02:55:38 +00:00
Value* index;
2008-04-17 20:48:26 +00:00
unsigned scale;
2008-04-17 02:55:38 +00:00
Value* result;
2008-03-15 23:54:20 +00:00
};
void
2008-04-17 20:48:26 +00:00
appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result)
2008-04-17 02:55:38 +00:00
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendMemory\n");
}
2008-04-18 03:47:42 +00:00
2008-04-17 02:55:38 +00:00
new (c->zone->allocate(sizeof(MemoryEvent)))
2008-04-17 20:48:26 +00:00
MemoryEvent(c, base, displacement, index, scale, result);
}
2008-07-05 20:21:13 +00:00
Stack*
stack(Context* c, Value* value, StackGeometry* geometry, Stack* next)
{
return new (c->zone->allocate(sizeof(Stack))) Stack(value, geometry, next);
}
2008-04-19 07:03:59 +00:00
Stack*
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
{
2008-07-05 20:21:13 +00:00
return stack(c, value, new (c->zone->allocate(sizeof(StackGeometry)))
StackGeometry(size, index), next);
2008-04-19 07:03:59 +00:00
}
void
resetStack(Context* c)
{
unsigned i = 0;
Stack* p = 0;
for (Stack* s = c->state->stack; s; s = s->next) {
2008-07-05 20:21:13 +00:00
Stack* n = stack(c, value(c), s->geometry, 0);
n->value->sites = n->pushSite = pushSite(c, s);
n->pushed = true;
2008-04-19 07:03:59 +00:00
if (p) {
p->next = n;
} else {
c->state->stack = n;
2008-04-17 22:07:32 +00:00
}
2008-04-19 07:03:59 +00:00
p = n;
2008-07-05 20:21:13 +00:00
i += s->geometry->size;
2008-04-17 22:07:32 +00:00
}
2008-04-20 05:23:08 +00:00
resetLocals(c);
2008-04-20 05:23:08 +00:00
c->stackReset = true;
2008-04-17 22:07:32 +00:00
}
2008-04-17 20:48:26 +00:00
class StackSyncEvent: public Event {
public:
2008-04-18 03:47:42 +00:00
StackSyncEvent(Context* c):
2008-04-17 20:48:26 +00:00
Event(c)
{
for (Stack* s = stack; s; s = s->next) {
if (s->pushEvent) s->pushEvent->active = true;
2008-07-05 20:21:13 +00:00
addRead(c, s->value, s->geometry->size * BytesPerWord, 0);
}
2008-04-17 20:48:26 +00:00
}
StackSyncEvent(Context* c, unsigned sequence, Stack* stack, Local* locals):
Event(c, sequence, stack, locals)
2008-04-17 20:48:26 +00:00
{
for (Stack* s = stack; s; s = s->next) {
if (s->pushEvent) s->pushEvent->active = true;
2008-07-05 20:21:13 +00:00
insertRead
(c, this, sequence, s->value, s->geometry->size * BytesPerWord, 0);
2008-04-17 20:48:26 +00:00
}
}
2008-04-19 00:19:45 +00:00
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "StackSyncEvent.compile\n");
}
2008-04-17 20:48:26 +00:00
cleanStack(c, stack, locals, reads);
2008-04-17 20:48:26 +00:00
}
};
void
2008-04-18 03:47:42 +00:00
appendStackSync(Context* c)
2008-04-17 20:48:26 +00:00
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendStackSync\n");
}
2008-04-18 03:47:42 +00:00
new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c);
2008-04-17 02:55:38 +00:00
}
2008-04-20 05:23:08 +00:00
class BranchEvent: public Event {
public:
BranchEvent(Context* c, UnaryOperation type, Value* address):
Event(c), type(type), address(address)
{
addRead(c, address, BytesPerWord, 0);
}
virtual void compile(Context* c) {
if (DebugCompile) {
fprintf(stderr, "BranchEvent.compile\n");
}
bool jump;
UnaryOperation type = this->type;
if (type != Jump) {
switch (c->constantCompare) {
case CompareLess:
switch (type) {
case JumpIfLess:
case JumpIfLessOrEqual:
case JumpIfNotEqual:
jump = true;
type = Jump;
break;
default:
jump = false;
}
break;
case CompareGreater:
switch (type) {
case JumpIfGreater:
case JumpIfGreaterOrEqual:
case JumpIfNotEqual:
jump = true;
type = Jump;
break;
default:
jump = false;
}
break;
case CompareEqual:
switch (type) {
case JumpIfEqual:
case JumpIfLessOrEqual:
case JumpIfGreaterOrEqual:
jump = true;
type = Jump;
break;
default:
jump = false;
}
break;
case CompareNone:
jump = true;
break;
default: abort(c);
}
} else {
jump = true;
}
if (jump) {
apply(c, type, BytesPerWord, address->source);
}
2008-04-20 05:23:08 +00:00
nextRead(c, address);
}
UnaryOperation type;
Value* address;
};
void
appendBranch(Context* c, UnaryOperation type, Value* address)
{
appendStackSync(c);
if (DebugAppend) {
fprintf(stderr, "appendBranch\n");
}
new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address);
resetStack(c);
}
class PushSite: public AbstractSite {
public:
PushSite(PushEvent* event): event(event) { }
virtual Site* readTarget(Context* c, Read* r) {
if (r->next and (not event->active)) {
return targetOrNull(c, r->next);
} else {
return 0;
}
}
PushEvent* event;
};
Site*
pushSite(Context* c, PushEvent* e)
{
return new (c->zone->allocate(sizeof(PushSite))) PushSite(e);
}
2008-04-19 00:19:45 +00:00
class PopEvent: public Event {
public:
PopEvent(Context* c, unsigned count, bool ignore):
Event(c), count(count), ignore(ignore)
{ }
virtual void compile(Context* c) {
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, "PopEvent.compile\n");
}
2008-04-19 00:19:45 +00:00
popNow(c, stack, count, ignore);
2008-04-19 00:19:45 +00:00
}
2008-04-18 00:39:41 +00:00
2008-04-18 03:47:42 +00:00
unsigned count;
bool ignore;
};
void
appendPop(Context* c, unsigned count, bool ignore)
{
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, "appendPop\n");
}
2008-04-18 03:47:42 +00:00
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
}
class BoundsCheckEvent: public Event {
public:
BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler):
Event(c), object(object), lengthOffset(lengthOffset), index(index),
handler(handler)
{
addRead(c, object, BytesPerWord, anyRegisterSite(c));
addRead(c, index, BytesPerWord, registerOrConstantSite(c));
}
virtual void compile(Context* c) {
if (DebugCompile) {
fprintf(stderr, "BoundsCheckEvent.compile\n");
}
Assembler* a = c->assembler;
ConstantSite* constant = findConstantSite(c, index);
CodePromise* nextPromise = codePromise(c, -1);
CodePromise* outOfBoundsPromise = 0;
if (constant) {
expect(c, constant->value.value->value() >= 0);
} else {
outOfBoundsPromise = codePromise(c, -1);
apply(c, Compare, 4, constantSite(c, resolved(c, 0)), index->source);
Assembler::Constant outOfBoundsConstant(outOfBoundsPromise);
a->apply
(JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant);
}
assert(c, object->source->type(c) == RegisterOperand);
int base = static_cast<RegisterSite*>(object->source)->register_.low;
Site* length = memorySite(c, base, lengthOffset);
length->acquire(c, 0, 0, 0);
apply(c, Compare, 4, index->source, length);
length->release(c);
Assembler::Constant nextConstant(nextPromise);
a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant);
if (constant == 0) {
outOfBoundsPromise->offset = a->length();
}
Assembler::Constant handlerConstant(resolved(c, handler));
a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant);
nextPromise->offset = a->length();
nextRead(c, object);
nextRead(c, index);
}
Value* object;
unsigned lengthOffset;
Value* index;
intptr_t handler;
};
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler)
{
2008-07-05 20:21:13 +00:00
if (DebugAppend) {
2008-06-01 01:40:18 +00:00
fprintf(stderr, "appendBoundsCheck\n");
}
new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent
(c, object, lengthOffset, index, handler);
}
2008-04-18 03:47:42 +00:00
Site*
2008-07-17 23:34:38 +00:00
readSource(Context* c, Stack* stack, Value** locals, Read* r)
2008-04-18 03:47:42 +00:00
{
2008-05-15 20:00:57 +00:00
if (r->value->sites == 0) {
return 0;
}
Site* target = (r->target ? r->target->readTarget(c, r) : 0);
2008-04-30 15:44:17 +00:00
2008-04-18 03:47:42 +00:00
unsigned copyCost;
Site* site = pick(c, r->value->sites, target, &copyCost);
if (target and copyCost) {
2008-07-17 23:34:38 +00:00
addSite(c, stack, locals, r->size, r->value, target);
2008-05-14 22:36:22 +00:00
apply(c, Move, r->size, site, target);
2008-04-30 15:44:17 +00:00
return target;
2008-04-17 02:55:38 +00:00
} else {
2008-04-18 00:39:41 +00:00
return site;
2008-04-17 02:55:38 +00:00
}
2007-12-11 21:26:59 +00:00
}
void
2008-04-17 02:55:38 +00:00
compile(Context* c)
2007-12-11 21:26:59 +00:00
{
2008-04-17 02:55:38 +00:00
Assembler* a = c->assembler;
2008-07-05 20:21:13 +00:00
c->pass = CompilePass;
2008-04-17 02:55:38 +00:00
Assembler::Register base(a->base());
Assembler::Register stack(a->stack());
2008-04-17 22:07:32 +00:00
a->apply(Push, BytesPerWord, RegisterOperand, &base);
a->apply(Move, BytesPerWord, RegisterOperand, &stack,
RegisterOperand, &base);
2008-04-17 02:55:38 +00:00
if (stackOffset(c)) {
Assembler::Constant offset(resolved(c, stackOffset(c) * BytesPerWord));
2008-04-17 22:07:32 +00:00
a->apply(Subtract, BytesPerWord, ConstantOperand, &offset,
RegisterOperand, &stack);
2008-04-17 02:55:38 +00:00
}
2008-04-19 07:03:59 +00:00
for (unsigned i = 0; i < c->logicalCodeLength; ++i) {
LogicalInstruction* li = c->logicalCode + i;
if (li->firstEvent) {
li->machineOffset = a->length();
2008-04-17 02:55:38 +00:00
2008-04-19 21:52:45 +00:00
if (DebugCompile) {
fprintf(stderr, " -- ip: %d\n", i);
}
2008-04-17 02:55:38 +00:00
2008-04-19 07:03:59 +00:00
for (Event* e = li->firstEvent; e; e = e->next) {
2008-04-20 05:23:08 +00:00
if (e->stackReset) {
// fprintf(stderr, "stack reset\n");
2008-04-20 05:23:08 +00:00
for (Stack* s = e->stack; s; s = s->next) {
2008-04-20 19:35:36 +00:00
if (s->value->sites) {
assert(c, s->value->sites->next == 0);
2008-07-05 20:21:13 +00:00
s->value->sites->acquire
(c, 0, s->geometry->size * BytesPerWord, s->value);
2008-04-20 05:23:08 +00:00
}
}
}
Site* sites[e->readCount];
unsigned si = 0;
2008-04-19 07:03:59 +00:00
for (Read* r = e->reads; r; r = r->eventNext) {
2008-07-17 23:34:38 +00:00
r->value->source = readSource(c, e->stack, e->locals, r);
if (r->value->source) {
assert(c, si < e->readCount);
sites[si++] = r->value->source;
r->value->source->freeze(c);
}
}
while (si) {
sites[--si]->thaw(c);
2008-04-19 07:03:59 +00:00
}
2008-04-17 02:55:38 +00:00
2008-04-19 07:03:59 +00:00
e->compile(c);
for (CodePromise* p = e->promises; p; p = p->next) {
p->offset = a->length();
}
}
2008-04-17 02:55:38 +00:00
}
}
}
2008-03-15 20:24:04 +00:00
unsigned
count(Stack* s)
{
unsigned c = 0;
while (s) {
++ c;
s = s->next;
}
return c;
}
void
2008-02-11 17:21:41 +00:00
pushState(Context* c)
{
if (DebugAppend) {
unsigned count = 0; for (State* s = c->state; s; s = s->next) ++ count;
fprintf(stderr, "push at level %d\n", count);
count = 0; for (Stack* s = c->state->stack; s; s = s->next) ++ count;
fprintf(stderr, "stack count: %d\n", count);
}
2008-02-11 17:21:41 +00:00
c->state = new (c->zone->allocate(sizeof(State)))
State(c->state, c->state->stack);
}
2008-04-20 19:35:36 +00:00
void
saveStack(Context* c)
{
if (c->logicalIp >= 0 and not c->logicalCode[c->logicalIp].stackSaved) {
c->logicalCode[c->logicalIp].stackSaved = true;
c->logicalCode[c->logicalIp].stack = c->state->stack;
c->logicalCode[c->logicalIp].locals = c->locals;
if (DebugAppend) {
unsigned count = 0;
for (Stack* s = c->state->stack; s; s = s->next) ++ count;
fprintf(stderr, "stack count after ip %d: %d\n", c->logicalIp, count);
}
2008-04-20 19:35:36 +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->next, c->state->next->stack);
if (DebugAppend) {
unsigned count = 0; for (State* s = c->state; s; s = s->next) ++ count;
fprintf(stderr, "pop to level %d\n", count);
count = 0; for (Stack* s = c->state->stack; s; s = s->next) ++ count;
fprintf(stderr, "stack count: %d\n", count);
}
}
2008-02-17 22:29:04 +00:00
Stack*
2008-04-17 02:55:38 +00:00
stack(Context* c, Value* value, unsigned size, Stack* next)
2008-02-17 22:29:04 +00:00
{
2008-07-05 20:21:13 +00:00
return stack
(c, value, size, (next ? next->geometry->index + next->geometry->size : 0),
next);
2008-02-17 22:29:04 +00:00
}
void
2008-04-17 02:55:38 +00:00
push(Context* c, unsigned size, Value* v)
{
assert(c, ceiling(size, BytesPerWord));
2008-04-17 02:55:38 +00:00
c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack);
2008-04-18 03:47:42 +00:00
appendPush(c);
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
2008-04-17 02:55:38 +00:00
Value*
pop(Context* c, unsigned size UNUSED)
2008-02-11 17:21:41 +00:00
{
Stack* s = c->state->stack;
assert(c, ceiling(size, BytesPerWord) == s->size);
2008-07-05 20:21:13 +00:00
appendPop(c, s->geometry->size, false);
c->state->stack = s->next;
2008-04-17 02:55:38 +00:00
return s->value;
2008-02-11 17:21:41 +00:00
}
2008-02-11 17:21:41 +00:00
void
updateJunctions(Context* c)
{
for (Junction* j = c->junctions; j; j = j->next) {
2008-04-20 05:23:08 +00:00
LogicalInstruction* i = c->logicalCode + j->logicalIp;
2008-04-20 19:35:36 +00:00
LogicalInstruction* p = i->immediatePredecessor;
2008-04-20 05:23:08 +00:00
2008-04-20 19:35:36 +00:00
p->lastEvent = p->lastEvent->next
= new (c->zone->allocate(sizeof(StackSyncEvent)))
StackSyncEvent(c, p->lastEvent->sequence, p->stack, p->locals);
2007-12-11 23:52:28 +00:00
}
2008-02-11 17:21:41 +00:00
}
2007-12-11 23:52:28 +00:00
void
visit(Context* c, unsigned logicalIp)
{
assert(c, logicalIp < c->logicalCodeLength);
if (c->logicalIp >= 0 and (not c->stackReset)) {
assert(c, c->logicalCode[logicalIp].immediatePredecessor == 0);
c->logicalCode[logicalIp].immediatePredecessor
= c->logicalCode + c->logicalIp;
}
}
class Client: public Assembler::Client {
public:
Client(Context* c): c(c) { }
2008-05-06 21:13:02 +00:00
virtual int acquireTemporary(uint32_t mask) {
int r = pickRegister(c, mask)->number;
2008-04-30 15:44:17 +00:00
save(r);
increment(c, r);
return r;
}
virtual void releaseTemporary(int r) {
decrement(c, c->registers[r]);
2008-04-30 15:44:17 +00:00
restore(r);
}
virtual void save(int r) {
if (c->registers[r]->refCount or c->registers[r]->value) {
Assembler::Register operand(r);
c->assembler->apply(Push, BytesPerWord, RegisterOperand, &operand);
c->registers[r]->pushed = true;
}
}
virtual void restore(int r) {
if (c->registers[r]->pushed) {
Assembler::Register operand(r);
c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &operand);
c->registers[r]->pushed = false;
}
}
Context* c;
};
2007-12-08 23:22:13 +00:00
class MyCompiler: public Compiler {
public:
MyCompiler(System* s, Assembler* assembler, Zone* zone,
Compiler::Client* compilerClient):
c(s, assembler, zone, compilerClient), client(&c)
{
assembler->setClient(&client);
}
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() {
2008-03-15 20:24:04 +00:00
::popState(&c);
2007-12-08 23:22:13 +00:00
}
virtual void saveStack() {
::saveStack(&c);
}
virtual void resetStack() {
::resetStack(&c);
}
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
unsigned localFootprint)
{
2008-02-11 17:21:41 +00:00
c.logicalCodeLength = logicalCodeLength;
c.parameterFootprint = parameterFootprint;
c.localFootprint = localFootprint;
2008-02-11 17:21:41 +00:00
c.logicalCode = static_cast<LogicalInstruction*>
(c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength));
memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength);
c.localTable = static_cast<Local**>
(c.zone->allocate(sizeof(Local*) * localFootprint));
memset(c.localTable, 0, sizeof(Local*) * localFootprint);
}
2008-02-11 17:21:41 +00:00
virtual void visitLogicalIp(unsigned logicalIp) {
2008-04-20 19:35:36 +00:00
visit(&c, logicalIp);
2008-04-20 05:23:08 +00:00
c.stackReset = false;
2008-04-20 19:35:36 +00:00
if (c.logicalCode[logicalIp].immediatePredecessor) {
c.junctions = new (c.zone->allocate(sizeof(Junction)))
Junction(logicalIp, c.junctions);
}
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void startLogicalIp(unsigned logicalIp) {
2008-04-19 21:52:45 +00:00
if (DebugAppend) {
fprintf(stderr, " -- ip: %d\n", logicalIp);
}
2008-04-20 19:35:36 +00:00
visit(&c, logicalIp);
::saveStack(&c);
2008-04-20 19:35:36 +00:00
2008-02-11 17:21:41 +00:00
c.logicalIp = logicalIp;
}
2008-02-11 17:21:41 +00:00
virtual Promise* machineIp(unsigned logicalIp) {
return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp);
}
2008-02-11 17:21:41 +00:00
virtual Promise* poolAppend(intptr_t value) {
return poolAppendPromise(resolved(&c, value));
}
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;
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(resolved(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* promiseConstant(Promise* value) {
2008-04-20 19:35:36 +00:00
return ::value(&c, ::constantSite(&c, value));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* address(Promise* address) {
2008-04-20 19:35:36 +00:00
return value(&c, ::addressSite(&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)
2008-02-11 17:21:41 +00:00
{
2008-04-17 22:07:32 +00:00
Value* result = value(&c);
2008-03-15 23:54:20 +00:00
2008-04-17 20:48:26 +00:00
appendMemory(&c, static_cast<Value*>(base), displacement,
static_cast<Value*>(index), scale, result);
2008-03-15 23:54:20 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* stack() {
Site* s = registerSite(&c, c.assembler->stack());
return value(&c, s, s);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* base() {
Site* s = registerSite(&c, c.assembler->base());
return value(&c, s, s);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual Operand* thread() {
Site* s = registerSite(&c, c.assembler->thread());
return value(&c, s, s);
2007-12-08 23:22:13 +00:00
}
virtual Operand* label() {
2008-04-20 19:35:36 +00:00
return value(&c, ::constantSite(&c, static_cast<Promise*>(0)));
2007-12-08 23:22:13 +00:00
}
Promise* machineIp() {
return codePromise(&c, c.logicalCode[c.logicalIp].lastEvent);
}
2007-12-08 23:22:13 +00:00
virtual void mark(Operand* label) {
2008-04-17 20:48:26 +00:00
appendStackSync(&c);
::resetStack(&c);
2008-03-15 23:54:20 +00:00
2008-04-17 22:07:32 +00:00
for (Site* s = static_cast<Value*>(label)->sites; s; s = s->next) {
if (s->type(&c) == ConstantOperand) {
static_cast<ConstantSite*>(s)->value.value = machineIp();
return;
}
}
abort(&c);
2007-12-08 23:22:13 +00:00
}
virtual void push(unsigned size) {
assert(&c, ceiling(size, BytesPerWord));
c.state->stack = ::stack
(&c, value(&c), ceiling(size, BytesPerWord), c.state->stack);
}
virtual void push(unsigned size, Operand* value) {
2008-04-17 20:48:26 +00:00
::push(&c, size, static_cast<Value*>(value));
2007-12-22 00:26:55 +00:00
}
2007-12-09 22:45:43 +00:00
virtual Operand* pop(unsigned size) {
return ::pop(&c, size);
2007-12-08 23:22:13 +00:00
}
2008-07-05 20:21:13 +00:00
virtual void pushed() {
Value* v = value(&c);
c.state->stack = ::stack(&c, v, 1, c.state->stack);
c.state->stack->pushed = true;
appendPushed(&c, c.state->stack);
}
2008-07-05 20:21:13 +00:00
virtual void popped() {
appendPop(&c, c.state->stack->size, true);
2008-03-15 23:54:20 +00:00
2008-07-05 20:21:13 +00:00
c.state->stack = c.state->stack->next;
}
virtual StackElement* top() {
return c.state->stack;
}
virtual unsigned size(StackElement* e) {
return static_cast<Stack*>(e)->geometry->size;
}
virtual unsigned padding(StackElement* e) {
return static_cast<Stack*>(e)->geometry->padding;
2007-12-08 23:22:13 +00:00
}
virtual Operand* peek(unsigned size UNUSED, unsigned index) {
Stack* s = c.state->stack;
for (unsigned i = index; i > 0;) {
2008-07-05 20:21:13 +00:00
i -= s->geometry->size;
s = s->next;
}
2008-07-05 20:21:13 +00:00
assert(&c, s->geometry->size == ceiling(size, BytesPerWord));
2008-04-17 20:48:26 +00:00
return s->value;
}
2008-02-11 17:21:41 +00:00
virtual Operand* call(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
2008-04-18 04:16:20 +00:00
unsigned resultSize,
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;
unsigned size = BytesPerWord;
2008-04-17 20:48:26 +00:00
Value* arguments[argumentCount];
unsigned argumentSizes[argumentCount];
unsigned index = 0;
2008-02-11 17:21:41 +00:00
for (unsigned i = 0; i < argumentCount; ++i) {
2008-04-17 20:48:26 +00:00
Value* o = va_arg(a, Value*);
if (o) {
2008-04-17 20:48:26 +00:00
arguments[index] = o;
argumentSizes[index] = size;
size = BytesPerWord;
2008-04-17 20:48:26 +00:00
++ index;
} else {
size = 8;
}
++ footprint;
}
2007-12-08 23:22:13 +00:00
2008-02-11 17:21:41 +00:00
va_end(a);
2008-04-19 07:03:59 +00:00
for (Stack* s = c.state->stack; s; s = s->next) {
if (s->pushEvent == 0) {
appendPush(&c, s);
}
s->pushEvent->active = true;
}
2008-04-18 03:47:42 +00:00
Stack* oldStack = c.state->stack;
2008-07-05 20:21:13 +00:00
Stack* bottomArgument = 0;
2008-04-18 03:47:42 +00:00
for (int i = index - 1; i >= 0; --i) {
2008-04-18 03:47:42 +00:00
::push(&c, argumentSizes[i], arguments[i]);
2008-07-05 20:21:13 +00:00
if (i == index - 1) {
bottomArgument = c.state->stack;
}
2008-04-18 03:47:42 +00:00
}
2008-04-19 00:19:45 +00:00
Stack* argumentStack = c.state->stack;
2008-04-18 03:47:42 +00:00
c.state->stack = oldStack;
2008-07-05 20:21:13 +00:00
unsigned padding = c->assembler->stackPadding
(c.state->stack->geometry->index + c.state->stack->geometry->size);
if (bottomArgument) {
bottomArgument->geometry->padding = padding;
}
Value* result = value(&c);
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
resultSize, argumentStack, index, argumentCount ? 0 : padding);
return result;
}
virtual Operand* stackCall(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
unsigned argumentFootprint)
{
unsigned padding = c->assembler->stackPadding
(c.state->stack->geometry->index + c.state->stack->geometry->size);
int footprint = argumentFootprint;
for (Stack* s = c.state->stack; s; s = s->next) {
footprint -= s->geometry->size;
if (footprint == 0) {
s->geometry->padding = padding;
}
if (s->pushEvent == 0) {
appendPush(&c, s);
}
s->pushEvent->active = true;
}
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
2008-07-05 20:21:13 +00:00
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
resultSize, c.state->stack, 0, argumentFootprint ? 0 : padding);
2008-02-11 17:21:41 +00:00
return result;
}
virtual void return_(unsigned size, Operand* value) {
2008-04-17 20:48:26 +00:00
appendReturn(&c, size, static_cast<Value*>(value));
}
virtual void storeLocal(unsigned size, Operand* src, unsigned index) {
assert(&c, index < c.localFootprint);
2008-05-20 19:11:42 +00:00
2008-07-17 23:34:38 +00:00
if (c.state->locals[index]) {
appendClobberLocal(&c, size, c.state->locals[index]);
2008-05-20 19:11:42 +00:00
}
2008-07-17 23:34:38 +00:00
Value* v = static_cast<Value*>(memory(base(), localOffset(&c, index)));
store(size, src, v);
2008-05-20 19:11:42 +00:00
2008-07-17 23:34:38 +00:00
c.state->locals[index] = v;
}
virtual Operand* loadLocal(unsigned size, unsigned index) {
assert(&c, index < c.localFootprint);
2008-07-17 23:34:38 +00:00
assert(&c, c.state->locals[index]);
2008-05-20 19:11:42 +00:00
2008-07-17 23:34:38 +00:00
return c.state->locals[index];
}
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler)
{
appendBoundsCheck(&c, static_cast<Value*>(object),
lengthOffset, static_cast<Value*>(index), handler);
}
virtual void store(unsigned size, Operand* src, Operand* dst) {
2008-04-17 20:48:26 +00:00
appendMove(&c, Move, size, static_cast<Value*>(src),
static_cast<Value*>(dst));
}
virtual Operand* load(unsigned size, Operand* src) {
2008-04-17 20:48:26 +00:00
Value* dst = value(&c);
appendMove(&c, Move, size, static_cast<Value*>(src), dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
virtual Operand* loadz(unsigned size, Operand* src) {
2008-04-17 20:48:26 +00:00
Value* dst = value(&c);
appendMove(&c, MoveZ, size, static_cast<Value*>(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-04-17 20:48:26 +00:00
Value* dst = value(&c);
appendMove(&c, Move4To8, 8, static_cast<Value*>(src), dst);
2008-02-11 17:21:41 +00:00
return dst;
2007-12-08 23:22:13 +00:00
}
virtual Operand* lcmp(Operand* a, Operand* b) {
Value* result = value(&c);
appendCombine(&c, LongCompare, 8, static_cast<Value*>(a),
static_cast<Value*>(b), result);
return result;
}
virtual void cmp(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
appendCompare(&c, size, static_cast<Value*>(a),
static_cast<Value*>(b));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jl(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfLess, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jg(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfGreater, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jle(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfLessOrEqual, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void jge(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfGreaterOrEqual, static_cast<Value*>(address));
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
virtual void je(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfEqual, static_cast<Value*>(address));
}
2008-02-11 17:21:41 +00:00
virtual void jne(Operand* address) {
2008-04-17 20:48:26 +00:00
appendBranch(&c, JumpIfNotEqual, static_cast<Value*>(address));
}
2008-02-11 17:21:41 +00:00
virtual void jmp(Operand* address) {
2008-04-17 22:07:32 +00:00
appendBranch(&c, Jump, static_cast<Value*>(address));
2007-12-09 22:45:43 +00:00
}
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Add, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-09 22:45:43 +00:00
}
virtual Operand* sub(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Subtract, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* mul(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Multiply, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* div(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Divide, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-22 00:26:55 +00:00
}
virtual Operand* rem(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Remainder, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* shl(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, ShiftLeft, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* shr(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, ShiftRight, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* ushr(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, UnsignedShiftRight, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* and_(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, And, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* or_(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Or, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
}
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendCombine(&c, Xor, size, static_cast<Value*>(a),
static_cast<Value*>(b), result);
2008-02-11 17:21:41 +00:00
return result;
2007-12-08 23:22:13 +00:00
}
virtual Operand* neg(unsigned size, Operand* a) {
2008-04-17 20:48:26 +00:00
Value* result = value(&c);
appendTranslate(&c, Negate, size, static_cast<Value*>(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() {
return c.constantCount * BytesPerWord;
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-04-20 19:35:36 +00:00
*reinterpret_cast<intptr_t*>(dst + pad(c.assembler->length()) + i)
2008-02-11 17:21:41 +00:00
= n->promise->value();
2008-04-20 19:35:36 +00:00
i += BytesPerWord;
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;
::Client client;
2007-12-08 23:22:13 +00:00
};
} // namespace
namespace vm {
Compiler*
2008-05-06 21:13:02 +00:00
makeCompiler(System* system, Assembler* assembler, Zone* zone,
Compiler::Client* client)
2007-12-08 23:22:13 +00:00
{
return new (zone->allocate(sizeof(MyCompiler)))
MyCompiler(system, assembler, zone, client);
2007-12-08 23:22:13 +00:00
}
2008-02-11 17:21:41 +00:00
} // namespace vm