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-04-27 20:15:18 +00:00
|
|
|
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;
|
2008-04-16 20:58:21 +00:00
|
|
|
class Value;
|
2008-04-17 22:07:32 +00:00
|
|
|
class Stack;
|
|
|
|
class Site;
|
2008-05-15 23:19:23 +00:00
|
|
|
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
|
|
|
|
2008-04-16 20:58:21 +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);
|
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
enum ConstantCompare {
|
|
|
|
CompareNone,
|
|
|
|
CompareLess,
|
|
|
|
CompareGreater,
|
|
|
|
CompareEqual
|
|
|
|
};
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class Site {
|
|
|
|
public:
|
|
|
|
Site(): next(0) { }
|
|
|
|
|
|
|
|
virtual ~Site() { }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Site* readTarget(Context*, Read*) { return this; }
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual unsigned copyCost(Context*, Site*) = 0;
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual void acquire(Context*, Stack*, unsigned, Value*) { }
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
virtual void release(Context*) { }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual void freeze(Context*) { }
|
|
|
|
|
|
|
|
virtual void thaw(Context*) { }
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
virtual OperandType type(Context*) = 0;
|
2008-04-16 20:58:21 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context*) = 0;
|
2008-04-16 20:58:21 +00:00
|
|
|
|
|
|
|
Site* next;
|
|
|
|
};
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
class Stack {
|
|
|
|
public:
|
|
|
|
Stack(Value* value, unsigned size, unsigned index, Stack* next):
|
2008-04-18 03:47:42 +00:00
|
|
|
value(value), size(size), index(index), next(next), pushEvent(0),
|
2008-04-26 20:56:03 +00:00
|
|
|
pushSite(0), pushed(false)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
Value* value;
|
|
|
|
unsigned size;
|
|
|
|
unsigned index;
|
|
|
|
Stack* next;
|
2008-04-18 03:47:42 +00:00
|
|
|
PushEvent* pushEvent;
|
2008-04-19 20:41:31 +00:00
|
|
|
Site* pushSite;
|
2008-04-17 22:07:32 +00:00
|
|
|
bool pushed;
|
|
|
|
};
|
|
|
|
|
|
|
|
class State {
|
|
|
|
public:
|
2008-04-27 21:58:29 +00:00
|
|
|
State(State* next, Stack* stack):
|
|
|
|
stack(stack),
|
|
|
|
next(next)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
Stack* stack;
|
|
|
|
State* next;
|
|
|
|
};
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
class Local {
|
|
|
|
public:
|
2008-05-20 21:24:10 +00:00
|
|
|
Local(unsigned size, unsigned index, Value* value, Site* site, Local* old,
|
|
|
|
Local* next):
|
|
|
|
size(size), index(index), reuse(true), value(value), site(site), old(old),
|
|
|
|
next(next)
|
2008-05-19 04:31:52 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
unsigned size;
|
|
|
|
unsigned index;
|
2008-05-20 19:11:42 +00:00
|
|
|
bool reuse;
|
2008-05-19 04:31:52 +00:00
|
|
|
Value* value;
|
|
|
|
Site* site;
|
2008-05-20 21:24:10 +00:00
|
|
|
Local* old;
|
2008-05-19 04:31:52 +00:00
|
|
|
Local* next;
|
|
|
|
};
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
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-05-19 04:31:52 +00:00
|
|
|
Local* 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:
|
2008-05-12 13:54:47 +00:00
|
|
|
Register(int number):
|
2008-05-15 23:19:23 +00:00
|
|
|
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-05-12 13:54:47 +00:00
|
|
|
{ }
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
Value* value;
|
2008-05-15 23:19:23 +00:00
|
|
|
RegisterSite* site;
|
2008-05-12 13:54:47 +00:00
|
|
|
int number;
|
2008-04-17 22:07:32 +00:00
|
|
|
unsigned size;
|
2008-04-20 00:43:12 +00:00
|
|
|
unsigned refCount;
|
2008-05-12 13:54:47 +00:00
|
|
|
unsigned freezeCount;
|
2008-04-17 22:07:32 +00:00
|
|
|
bool reserved;
|
2008-04-27 20:15:18 +00:00
|
|
|
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:
|
|
|
|
Read(unsigned size, Value* value, Site* target, Read* next, Event* event,
|
|
|
|
Read* eventNext):
|
|
|
|
size(size), value(value), target(target), next(next), event(event),
|
|
|
|
eventNext(eventNext)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
unsigned size;
|
|
|
|
Value* value;
|
|
|
|
Site* target;
|
|
|
|
Read* next;
|
|
|
|
Event* event;
|
|
|
|
Read* eventNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Value: public Compiler::Operand {
|
|
|
|
public:
|
2008-04-26 20:56:03 +00:00
|
|
|
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
|
|
|
};
|
|
|
|
|
|
|
|
class Context {
|
|
|
|
public:
|
2008-05-31 22:14:27 +00:00
|
|
|
Context(System* system, Assembler* assembler, Zone* zone,
|
|
|
|
Compiler::Client* client):
|
2008-04-17 22:07:32 +00:00
|
|
|
system(system),
|
|
|
|
assembler(assembler),
|
|
|
|
zone(zone),
|
2008-05-31 22:14:27 +00:00
|
|
|
client(client),
|
2008-04-17 22:07:32 +00:00
|
|
|
logicalIp(-1),
|
2008-04-27 21:58:29 +00:00
|
|
|
state(new (zone->allocate(sizeof(State))) State(0, 0)),
|
2008-04-17 22:07:32 +00:00
|
|
|
logicalCode(0),
|
|
|
|
logicalCodeLength(0),
|
2008-05-19 04:31:52 +00:00
|
|
|
parameterFootprint(0),
|
|
|
|
localFootprint(0),
|
2008-05-12 13:54:47 +00:00
|
|
|
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),
|
2008-05-19 04:31:52 +00:00
|
|
|
locals(0),
|
|
|
|
localTable(0),
|
2008-06-11 00:17:44 +00:00
|
|
|
stackReset(false),
|
|
|
|
constantCompare(CompareNone)
|
2008-04-17 22:07:32 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +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;
|
2008-05-31 22:14:27 +00:00
|
|
|
Compiler::Client* client;
|
2008-04-17 22:07:32 +00:00
|
|
|
int logicalIp;
|
|
|
|
State* state;
|
|
|
|
LogicalInstruction* logicalCode;
|
|
|
|
unsigned logicalCodeLength;
|
2008-05-19 04:31:52 +00:00
|
|
|
unsigned parameterFootprint;
|
|
|
|
unsigned localFootprint;
|
2008-05-12 13:54:47 +00:00
|
|
|
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-05-19 04:31:52 +00:00
|
|
|
Local* locals;
|
|
|
|
Local** localTable;
|
2008-04-20 05:23:08 +00:00
|
|
|
bool stackReset;
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantCompare constantCompare;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
2008-04-18 17:00:55 +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):
|
2008-05-19 04:31:52 +00:00
|
|
|
next(0), stack(c->state->stack), locals(c->locals), promises(0), reads(0),
|
|
|
|
readCount(0), sequence(c->nextSequence++), stackReset(c->stackReset)
|
2008-04-18 17:00:55 +00:00
|
|
|
{
|
|
|
|
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;
|
2008-04-18 17:00:55 +00:00
|
|
|
} else {
|
2008-04-19 07:03:59 +00:00
|
|
|
i->firstEvent = this;
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
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;
|
|
|
|
}
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
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)
|
2008-04-18 17:00:55 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual ~Event() { }
|
|
|
|
|
|
|
|
virtual void compile(Context* c) = 0;
|
|
|
|
|
2008-04-29 14:59:12 +00:00
|
|
|
virtual bool skipMove(unsigned) { return false; }
|
2008-04-20 02:05:17 +00:00
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
Event* next;
|
|
|
|
Stack* stack;
|
2008-05-19 04:31:52 +00:00
|
|
|
Local* locals;
|
2008-04-18 17:00:55 +00:00
|
|
|
CodePromise* promises;
|
|
|
|
Read* reads;
|
2008-05-15 14:29:19 +00:00
|
|
|
unsigned readCount;
|
2008-04-18 17:00:55 +00:00
|
|
|
unsigned sequence;
|
2008-04-20 05:23:08 +00:00
|
|
|
bool stackReset;
|
2008-04-18 17:00:55 +00:00
|
|
|
};
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
void
|
|
|
|
addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
|
2008-04-19 00:19:45 +00:00
|
|
|
{
|
|
|
|
if (not findSite(c, v, s)) {
|
2008-04-29 16:25:20 +00:00
|
|
|
// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), v);
|
2008-05-12 13:54:47 +00:00
|
|
|
s->acquire(c, stack, 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) {
|
2008-04-29 16:25:20 +00:00
|
|
|
// 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-04-19 00:19:45 +00:00
|
|
|
void
|
|
|
|
nextRead(Context* c, Value* v)
|
|
|
|
{
|
2008-04-20 02:05:17 +00:00
|
|
|
// 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;
|
|
|
|
if (v->reads == 0) {
|
2008-04-19 07:03:59 +00:00
|
|
|
clearSites(c, v);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +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);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return ConstantOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return AddressOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Register*
|
|
|
|
acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize,
|
2008-05-15 23:19:23 +00:00
|
|
|
Value* newValue, RegisterSite* newSite);
|
2008-04-16 20:58:21 +00:00
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
void
|
2008-05-12 13:54:47 +00:00
|
|
|
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,
|
2008-05-15 23:19:23 +00:00
|
|
|
Value* value, RegisterSite* site, Register* current);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class RegisterSite: public Site {
|
|
|
|
public:
|
2008-05-13 17:27:57 +00:00
|
|
|
RegisterSite(uint64_t mask, Register* low = 0, Register* high = 0):
|
|
|
|
mask(mask), low(low), high(high), register_(NoRegister, NoRegister)
|
2008-05-12 13:54:47 +00:00
|
|
|
{ }
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
void sync(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
|
|
|
register_.low = low->number;
|
|
|
|
register_.high = (high? high->number : NoRegister);
|
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
|
|
|
|
virtual unsigned copyCost(Context* c, Site* s) {
|
2008-05-12 13:54:47 +00:00
|
|
|
sync(c);
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
if (s and
|
|
|
|
(this == s or
|
2008-04-17 22:07:32 +00:00
|
|
|
(s->type(c) == RegisterOperand
|
2008-05-12 13:54:47 +00:00
|
|
|
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)))))))
|
2008-04-16 20:58:21 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v) {
|
2008-05-20 22:47:53 +00:00
|
|
|
low = ::validate(c, mask, stack, size, v, this, low);
|
|
|
|
if (size > BytesPerWord) {
|
|
|
|
::freeze(low);
|
|
|
|
high = ::validate(c, mask >> 32, stack, size, v, this, high);
|
|
|
|
::thaw(low);
|
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release(Context* c) {
|
2008-05-12 13:54:47 +00:00
|
|
|
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) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
::freeze(low);
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high) {
|
2008-05-15 00:04:25 +00:00
|
|
|
::freeze(high);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
virtual void thaw(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
::thaw(low);
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high) {
|
2008-05-15 00:04:25 +00:00
|
|
|
::thaw(high);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return RegisterOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
|
|
|
|
sync(c);
|
2008-04-16 20:58:21 +00:00
|
|
|
return ®ister_;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
uint64_t mask;
|
|
|
|
Register* low;
|
|
|
|
Register* high;
|
2008-04-16 20:58:21 +00:00
|
|
|
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()));
|
|
|
|
|
2008-05-13 17:27:57 +00:00
|
|
|
Register* hr;
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high == NoRegister) {
|
2008-05-13 17:27:57 +00:00
|
|
|
hr = 0;
|
2008-05-12 13:54:47 +00:00
|
|
|
} else {
|
2008-05-13 17:27:57 +00:00
|
|
|
hr = c->registers[high];
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite)))
|
2008-05-15 23:19:23 +00:00
|
|
|
RegisterSite(~static_cast<uint64_t>(0), c->registers[low], hr);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
RegisterSite*
|
2008-05-15 23:19:23 +00:00
|
|
|
freeRegisterSite(Context* c, uint64_t mask = ~static_cast<uint64_t>(0))
|
2008-05-12 13:54:47 +00:00
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite)))
|
|
|
|
RegisterSite(mask);
|
|
|
|
}
|
2008-04-17 22:07:32 +00:00
|
|
|
|
2008-05-15 23:19:23 +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);
|
2008-05-15 23:19:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite)))
|
|
|
|
RegisterSite(mask);
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Register*
|
|
|
|
increment(Context* c, int i)
|
2008-04-20 00:43:12 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
Register* r = c->registers[i];
|
|
|
|
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-12 13:54:47 +00:00
|
|
|
fprintf(stderr, "increment %d to %d\n", r->number, r->refCount + 1);
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
2008-05-12 13:54:47 +00:00
|
|
|
|
|
|
|
++ r->refCount;
|
|
|
|
|
|
|
|
return r;
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-05-14 23:19:41 +00:00
|
|
|
decrement(Context* c UNUSED, Register* r)
|
2008-04-20 00:43:12 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, r->refCount > 0);
|
|
|
|
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-15 00:04:25 +00:00
|
|
|
fprintf(stderr, "decrement %d to %d\n", r->number, r->refCount - 1);
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
2008-05-12 13:54:47 +00:00
|
|
|
|
|
|
|
-- r->refCount;
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class MemorySite: public Site {
|
|
|
|
public:
|
2008-04-17 02:55:38 +00:00
|
|
|
MemorySite(int base, int offset, int index, unsigned scale):
|
2008-05-12 13:54:47 +00:00
|
|
|
base(0), index(0), value(base, offset, index, scale)
|
2008-04-16 20:58:21 +00:00
|
|
|
{ }
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
void sync(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, base);
|
|
|
|
|
|
|
|
value.base = base->number;
|
|
|
|
value.index = (index? index->number : NoRegister);
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual unsigned copyCost(Context* c, Site* s) {
|
2008-05-12 13:54:47 +00:00
|
|
|
sync(c);
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
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)))
|
2008-04-16 20:58:21 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual void acquire(Context* c, Stack*, unsigned, Value*) {
|
|
|
|
base = increment(c, value.base);
|
2008-04-19 00:19:45 +00:00
|
|
|
if (value.index != NoRegister) {
|
2008-05-12 13:54:47 +00:00
|
|
|
index = increment(c, value.index);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release(Context* c) {
|
2008-05-12 13:54:47 +00:00
|
|
|
decrement(c, base);
|
|
|
|
if (index) {
|
|
|
|
decrement(c, index);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return MemoryOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
|
|
|
|
sync(c);
|
2008-04-16 20:58:21 +00:00
|
|
|
return &value;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Register* base;
|
|
|
|
Register* index;
|
2008-04-16 20:58:21 +00:00
|
|
|
Assembler::Memory value;
|
|
|
|
};
|
|
|
|
|
|
|
|
MemorySite*
|
2008-05-19 04:31:52 +00:00
|
|
|
memorySite(Context* c, int base, int offset = 0, int index = NoRegister,
|
|
|
|
unsigned scale = 1)
|
2008-04-16 20:58:21 +00:00
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(MemorySite)))
|
|
|
|
MemorySite(base, offset, index, scale);
|
|
|
|
}
|
|
|
|
|
2008-05-04 20:55:34 +00:00
|
|
|
bool
|
2008-05-14 23:19:41 +00:00
|
|
|
matchRegister(Context* c UNUSED, Site* s, uint64_t mask)
|
2008-05-04 20:55:34 +00:00
|
|
|
{
|
|
|
|
assert(c, s->type(c) == RegisterOperand);
|
|
|
|
|
|
|
|
RegisterSite* r = static_cast<RegisterSite*>(s);
|
2008-05-22 17:15:18 +00:00
|
|
|
if (r->low) {
|
|
|
|
r->sync(c);
|
|
|
|
return ((static_cast<uint64_t>(1) << r->register_.low) & mask)
|
|
|
|
and (r->register_.high == NoRegister
|
|
|
|
or ((static_cast<uint64_t>(1) << (r->register_.high + 32)) & mask));
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
match(Context* c, Site* s, uint8_t typeMask, uint64_t registerMask)
|
|
|
|
{
|
|
|
|
OperandType t = s->type(c);
|
|
|
|
return ((1 << t) & typeMask)
|
|
|
|
and (t != RegisterOperand or matchRegister(c, s, registerMask));
|
|
|
|
}
|
|
|
|
|
2008-05-06 21:13:02 +00:00
|
|
|
Site*
|
2008-05-12 13:54:47 +00:00
|
|
|
targetOrNull(Context* c, Read* r)
|
2008-05-06 21:13:02 +00:00
|
|
|
{
|
|
|
|
Value* v = r->value;
|
|
|
|
if (v->target) {
|
|
|
|
return v->target;
|
|
|
|
} else if (r->target) {
|
2008-05-12 13:54:47 +00:00
|
|
|
return r->target->readTarget(c, r);
|
2008-05-06 21:13:02 +00:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Site*
|
2008-05-12 13:54:47 +00:00
|
|
|
targetOrNull(Context* c, Value* v)
|
2008-05-06 21:13:02 +00:00
|
|
|
{
|
|
|
|
if (v->target) {
|
|
|
|
return v->target;
|
|
|
|
} else if (v->reads and v->reads->target) {
|
2008-05-12 13:54:47 +00:00
|
|
|
return v->reads->target->readTarget(c, v->reads);
|
2008-05-06 21:13:02 +00:00
|
|
|
}
|
2008-06-02 16:12:09 +00:00
|
|
|
return 0;
|
2008-05-06 21:13:02 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
class AbstractSite: public Site {
|
2008-04-16 20:58:21 +00:00
|
|
|
public:
|
2008-05-06 21:13:02 +00:00
|
|
|
virtual unsigned copyCost(Context* c, Site*) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void copyTo(Context* c, unsigned, Site*) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual OperandType type(Context* c) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class VirtualSite: public AbstractSite {
|
|
|
|
public:
|
|
|
|
VirtualSite(Value* value, uint8_t typeMask, uint64_t registerMask):
|
2008-05-04 20:55:34 +00:00
|
|
|
value(value), registerMask(registerMask), typeMask(typeMask)
|
|
|
|
{ }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Site* readTarget(Context* c, Read* r) {
|
2008-05-04 20:55:34 +00:00
|
|
|
if (value) {
|
2008-05-12 13:54:47 +00:00
|
|
|
Site* s = targetOrNull(c, value);
|
2008-05-04 20:55:34 +00:00
|
|
|
if (s and match(c, s, typeMask, registerMask)) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Site* site = 0;
|
|
|
|
unsigned copyCost = 0xFFFFFFFF;
|
|
|
|
for (Site* s = r->value->sites; s; s = s->next) {
|
|
|
|
if (match(c, s, typeMask, registerMask)) {
|
|
|
|
unsigned v = s->copyCost(c, 0);
|
|
|
|
if (v < copyCost) {
|
|
|
|
site = s;
|
|
|
|
copyCost = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (site) {
|
|
|
|
return site;
|
|
|
|
} else {
|
2008-05-16 16:01:24 +00:00
|
|
|
assert(c, typeMask & (1 << RegisterOperand));
|
2008-05-15 23:19:23 +00:00
|
|
|
return freeRegisterSite(c, registerMask);
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Value* value;
|
|
|
|
uint64_t registerMask;
|
|
|
|
uint8_t typeMask;
|
2008-04-16 20:58:21 +00:00
|
|
|
};
|
|
|
|
|
2008-05-06 21:13:02 +00:00
|
|
|
VirtualSite*
|
|
|
|
virtualSite(Context* c, Value* v = 0,
|
2008-05-15 20:00:57 +00:00
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0),
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0))
|
2008-05-04 20:55:34 +00:00
|
|
|
{
|
2008-05-06 21:13:02 +00:00
|
|
|
return new (c->zone->allocate(sizeof(VirtualSite)))
|
|
|
|
VirtualSite(v, typeMask, registerMask);
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-05-06 21:13:02 +00:00
|
|
|
VirtualSite*
|
2008-05-04 20:55:34 +00:00
|
|
|
anyRegisterSite(Context* c)
|
|
|
|
{
|
2008-05-06 21:13:02 +00:00
|
|
|
return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast<uint64_t>(0));
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
VirtualSite*
|
|
|
|
registerOrConstantSite(Context* c)
|
|
|
|
{
|
|
|
|
return virtualSite(c, 0, (1 << RegisterOperand) | (1 << ConstantOperand),
|
|
|
|
~static_cast<uint64_t>(0));
|
|
|
|
}
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
Site*
|
2008-05-12 13:54:47 +00:00
|
|
|
targetOrRegister(Context* c, Value* v)
|
2008-04-18 17:00:55 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
Site* s = targetOrNull(c, v);
|
|
|
|
if (s) {
|
2008-04-18 17:00:55 +00:00
|
|
|
return s;
|
|
|
|
} else {
|
2008-05-15 23:19:23 +00:00
|
|
|
return freeRegisterSite(c);
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
unsigned
|
|
|
|
stackOffset(Context* c)
|
|
|
|
{
|
|
|
|
return c->localFootprint - c->parameterFootprint;
|
|
|
|
}
|
|
|
|
|
2008-04-26 20:56:03 +00:00
|
|
|
Site*
|
|
|
|
pushSite(Context* c, unsigned index)
|
|
|
|
{
|
|
|
|
return memorySite
|
|
|
|
(c, c->assembler->base(),
|
2008-05-19 04:31:52 +00:00
|
|
|
- (stackOffset(c) + index + 1) * BytesPerWord, NoRegister, 1);
|
2008-04-26 20:56:03 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
void
|
2008-04-19 20:41:31 +00:00
|
|
|
pushNow(Context* c, Stack* start, unsigned count)
|
2008-04-17 22:07:32 +00:00
|
|
|
{
|
|
|
|
Stack* segment[count];
|
|
|
|
unsigned index = count;
|
|
|
|
for (Stack* s = start; s and index; s = s->next) {
|
|
|
|
segment[--index] = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
Stack* s = segment[i];
|
2008-04-18 03:47:42 +00:00
|
|
|
assert(c, not s->pushed);
|
2008-04-17 22:07:32 +00:00
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
if (s->value and s->value->sites) {
|
2008-04-26 20:56:03 +00:00
|
|
|
Site* source = pick(c, s->value->sites);
|
|
|
|
|
2008-04-30 15:44:17 +00:00
|
|
|
removeMemorySites(c, s->value);
|
|
|
|
|
2008-04-26 20:56:03 +00:00
|
|
|
s->pushSite = pushSite(c, s->index);
|
2008-04-21 00:21:48 +00:00
|
|
|
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
|
2008-04-26 20:56:03 +00:00
|
|
|
|
|
|
|
apply(c, Push, s->size * BytesPerWord, source);
|
2008-04-17 22:07:32 +00:00
|
|
|
} else {
|
|
|
|
Assembler::Register stack(c->assembler->stack());
|
|
|
|
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
|
|
|
|
c->assembler->apply
|
|
|
|
(Subtract, BytesPerWord, ConstantOperand, &offset,
|
|
|
|
RegisterOperand, &stack);
|
|
|
|
}
|
|
|
|
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "pushed %p value: %p sites: %p\n",
|
|
|
|
s, s->value, s->value->sites);
|
|
|
|
}
|
2008-04-18 03:47:42 +00:00
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
s->pushed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-18 03:47:42 +00:00
|
|
|
void
|
2008-04-19 20:41:31 +00:00
|
|
|
pushNow(Context* c, Stack* start)
|
2008-04-18 03:47:42 +00:00
|
|
|
{
|
|
|
|
unsigned count = 0;
|
|
|
|
for (Stack* s = start; s and (not s->pushed); s = s->next) {
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
|
2008-04-19 20:41:31 +00:00
|
|
|
pushNow(c, start, count);
|
2008-04-18 03:47:42 +00:00
|
|
|
}
|
|
|
|
|
2008-04-27 20:15:18 +00:00
|
|
|
bool
|
2008-05-12 13:54:47 +00:00
|
|
|
trySteal(Context* c, Register* r, Stack* stack)
|
2008-04-27 20:15:18 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, r->refCount == 0);
|
2008-04-27 20:15:18 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Value* v = r->value;
|
2008-04-27 20:15:18 +00:00
|
|
|
|
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "try steal %d from %p: next: %p\n",
|
2008-05-12 13:54:47 +00:00
|
|
|
r->number, v, v->sites->next);
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (v->sites->next == 0) {
|
|
|
|
unsigned count = 0;
|
|
|
|
Stack* start = 0;
|
|
|
|
for (Stack* s = stack; s and (not s->pushed); s = s->next) {
|
2008-06-11 00:48:46 +00:00
|
|
|
if (start == 0 and s->value == v) {
|
2008-04-27 20:15:18 +00:00
|
|
|
start = s;
|
|
|
|
}
|
|
|
|
if (start) {
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start) {
|
2008-05-18 01:26:36 +00:00
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "push %p\n", v);
|
|
|
|
}
|
2008-04-27 20:15:18 +00:00
|
|
|
pushNow(c, start, count);
|
|
|
|
} else {
|
2008-05-18 01:26:36 +00:00
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "unable to steal %d from %p\n", r->number, v);
|
|
|
|
}
|
2008-04-27 20:15:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
removeSite(c, v, r->site);
|
2008-04-27 20:15:18 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-04-21 00:21:48 +00:00
|
|
|
bool
|
2008-05-12 13:54:47 +00:00
|
|
|
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)
|
|
|
|
{
|
2008-05-15 23:19:23 +00:00
|
|
|
assert(c, a != b);
|
|
|
|
assert(c, a->number != b->number);
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
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*
|
|
|
|
replace(Context* c, Stack* stack, Register* r)
|
|
|
|
{
|
2008-05-15 23:19:23 +00:00
|
|
|
uint32_t mask = (r->freezeCount? r->site->mask : ~0);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
freeze(r);
|
2008-05-15 20:00:57 +00:00
|
|
|
Register* s = acquire(c, mask, stack, r->size, r->value, r->site);
|
2008-05-15 00:04:25 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
swap(c, r, s);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register*
|
|
|
|
acquire(Context* c, uint32_t mask, Stack* stack, unsigned newSize,
|
2008-05-15 23:19:23 +00:00
|
|
|
Value* newValue, RegisterSite* newSite)
|
2008-04-17 22:07:32 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
Register* r = pickRegister(c, mask);
|
|
|
|
|
|
|
|
if (r->reserved) return r;
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-18 01:26:36 +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-20 00:43:12 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-12 13:54:47 +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))
|
|
|
|
{
|
|
|
|
if (not trySteal(c, r, stack)) {
|
|
|
|
r = replace(c, stack, r);
|
|
|
|
}
|
2008-04-17 22:07:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
r->size = newSize;
|
|
|
|
r->value = newValue;
|
|
|
|
r->site = newSite;
|
2008-04-21 00:21:48 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
return r;
|
2008-04-17 22:07:32 +00:00
|
|
|
}
|
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
void
|
2008-05-12 13:54:47 +00:00
|
|
|
release(Context*, Register* r)
|
2008-04-19 00:19:45 +00:00
|
|
|
{
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-12 13:54:47 +00:00
|
|
|
fprintf(stderr, "release %d\n", r->number);
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
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*
|
|
|
|
validate(Context* c, uint32_t mask, Stack* stack, unsigned size,
|
2008-05-15 23:19:23 +00:00
|
|
|
Value* value, RegisterSite* site, Register* current)
|
2008-05-15 20:00:57 +00:00
|
|
|
{
|
2008-05-15 23:19:23 +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-05-15 23:19:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Register* r = acquire(c, mask, stack, 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);
|
|
|
|
}
|
2008-05-15 23:19:23 +00:00
|
|
|
|
|
|
|
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-02-17 20:57:40 +00:00
|
|
|
|
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-02-17 20:57:40 +00:00
|
|
|
|
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);
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-03-11 16:40:28 +00:00
|
|
|
void
|
2008-05-15 14:29:19 +00:00
|
|
|
insertRead(Context* c, Event* event, int sequence, Value* v,
|
2008-04-17 20:48:26 +00:00
|
|
|
unsigned size, Site* target)
|
2008-03-11 16:40:28 +00:00
|
|
|
{
|
2008-04-17 02:55:38 +00:00
|
|
|
Read* r = new (c->zone->allocate(sizeof(Read)))
|
2008-05-15 14:29:19 +00:00
|
|
|
Read(size, v, target, 0, event, event->reads);
|
|
|
|
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
|
|
|
|
addRead(Context* c, Value* v, unsigned size, Site* target)
|
|
|
|
{
|
2008-04-20 19:35:36 +00:00
|
|
|
insertRead(c, c->logicalCode[c->logicalIp].lastEvent, -1, v, size, target);
|
2008-03-11 16:40:28 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
addRead(c, s->value, s->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) {
|
2008-04-26 20:56:03 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-04-29 14:59:12 +00:00
|
|
|
virtual bool skipMove(unsigned size) {
|
2008-04-29 15:30:41 +00:00
|
|
|
return active and size >= BytesPerWord;
|
2008-04-29 14:59:12 +00:00
|
|
|
}
|
|
|
|
|
2008-04-19 07:03:59 +00:00
|
|
|
Stack* s;
|
2008-04-19 00:19:45 +00:00
|
|
|
bool active;
|
|
|
|
};
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
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;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
|
|
|
clearSites(c, s->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
|
|
|
if (s->pushSite) {
|
|
|
|
addSite(c, 0, s->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;
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:24:04 +00:00
|
|
|
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-04-19 00:19:45 +00:00
|
|
|
Stack* argumentStack, unsigned argumentCount):
|
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-04-19 00:19:45 +00:00
|
|
|
argumentFootprint(0)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
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);
|
2008-05-15 23:19:23 +00:00
|
|
|
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-05-16 16:01:24 +00:00
|
|
|
argumentFootprint += s->size;
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
addRead(c, s->value, s->size * BytesPerWord, target);
|
2008-04-21 00:21:48 +00:00
|
|
|
index += s->size;
|
2008-04-19 00:19:45 +00:00
|
|
|
s = s->next;
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
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;
|
|
|
|
addRead(c, s->value, s->size * BytesPerWord, virtualSite
|
|
|
|
(c, 0, ~0, (static_cast<uint64_t>(mask) << 32) | mask));
|
|
|
|
}
|
2008-05-19 04:31:52 +00:00
|
|
|
|
|
|
|
resetLocals(c);
|
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-04-19 21:52:45 +00:00
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr, "CallEvent.compile\n");
|
|
|
|
}
|
2008-04-20 00:43:12 +00:00
|
|
|
|
|
|
|
pushNow(c, stack);
|
2008-04-17 02:55:38 +00:00
|
|
|
|
|
|
|
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
|
2008-05-31 22:14:27 +00:00
|
|
|
apply(c, type, BytesPerWord, address->source);
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-05-15 23:19:23 +00:00
|
|
|
if (traceHandler) {
|
2008-05-31 22:24:04 +00:00
|
|
|
traceHandler->handleTrace(codePromise(c, c->assembler->length()));
|
2008-05-15 23:19:23 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
cleanStack(c, stack, locals, reads);
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-04-19 07:03:59 +00:00
|
|
|
if (resultSize and result->reads) {
|
2008-04-21 00:21:48 +00:00
|
|
|
addSite(c, 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
|
|
|
}
|
2007-12-23 18:48:22 +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-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-12 22:19:13 +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-04-19 00:19:45 +00:00
|
|
|
Stack* argumentStack, unsigned argumentCount)
|
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-04-19 00:19:45 +00:00
|
|
|
resultSize, argumentStack, argumentCount);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
class ReturnEvent: public Event {
|
2008-02-17 20:57:40 +00:00
|
|
|
public:
|
2008-04-17 02:55:38 +00:00
|
|
|
ReturnEvent(Context* c, unsigned size, Value* value):
|
|
|
|
Event(c), value(value)
|
|
|
|
{
|
|
|
|
if (value) {
|
2008-05-15 23:19:23 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr, "ReturnEvent.compile\n");
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
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-02-17 20:57:40 +00:00
|
|
|
|
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-02-17 20:57:40 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* value;
|
2008-02-17 20:57:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-04-17 22:07:32 +00:00
|
|
|
appendReturn(Context* c, unsigned size, Value* value)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
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-02-17 20:57:40 +00:00
|
|
|
}
|
|
|
|
|
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,
|
2008-05-16 16:01:24 +00:00
|
|
|
Value* dst, Site* srcTarget, VirtualSite* dstTarget):
|
|
|
|
Event(c), type(type), size(size), src(src), dst(dst), dstTarget(dstTarget)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
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-05-19 13:44:39 +00:00
|
|
|
bool isLoad = src->reads->next == 0;
|
|
|
|
bool isStore = dst->reads == 0;
|
|
|
|
|
2008-04-18 17:30:54 +00:00
|
|
|
Site* target;
|
2008-04-26 20:56:03 +00:00
|
|
|
unsigned cost;
|
2008-04-18 17:30:54 +00:00
|
|
|
if (type == Move
|
|
|
|
and dst->reads
|
2008-04-29 14:59:12 +00:00
|
|
|
and next == dst->reads->event
|
|
|
|
and dst->reads->event->skipMove(size))
|
2008-04-18 17:30:54 +00:00
|
|
|
{
|
|
|
|
target = src->source;
|
2008-04-26 20:56:03 +00:00
|
|
|
cost = 0;
|
2008-04-18 17:30:54 +00:00
|
|
|
} else {
|
2008-05-12 13:54:47 +00:00
|
|
|
target = targetOrRegister(c, dst);
|
2008-04-26 20:56:03 +00:00
|
|
|
cost = src->source->copyCost(c, target);
|
2008-05-19 13:44:39 +00:00
|
|
|
if (cost == 0 and (isLoad or isStore)) {
|
2008-05-13 17:27:57 +00:00
|
|
|
target = src->source;
|
|
|
|
}
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-19 14:53:40 +00:00
|
|
|
assert(c, isLoad or isStore or target != src->source);
|
|
|
|
|
2008-05-18 01:26:36 +00:00
|
|
|
if (target == src->source) {
|
2008-05-19 14:53:40 +00:00
|
|
|
removeSite(c, src, target);
|
2008-05-18 01:26:36 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
if (not isStore) {
|
2008-04-28 22:08:31 +00:00
|
|
|
addSite(c, stack, size, dst, target);
|
|
|
|
}
|
|
|
|
|
2008-05-18 01:26:36 +00:00
|
|
|
if (cost or type != Move) {
|
2008-05-16 16:01:24 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
addSite(c, stack, size, dst, tmpTarget);
|
|
|
|
|
|
|
|
apply(c, type, size, src->source, tmpTarget);
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
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);
|
|
|
|
}
|
2008-05-16 16:01:24 +00:00
|
|
|
}
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
if (isStore) {
|
2008-04-20 19:35:36 +00:00
|
|
|
removeSite(c, dst, target);
|
|
|
|
}
|
2008-05-18 01:26:36 +00:00
|
|
|
|
2008-05-19 14:53:40 +00:00
|
|
|
nextRead(c, src);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
BinaryOperation type;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* src;
|
|
|
|
Value* dst;
|
2008-05-16 16:01:24 +00:00
|
|
|
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);
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
|
|
|
c->assembler->plan(type, size,
|
|
|
|
&(srcTarget->typeMask), &(srcTarget->registerMask),
|
|
|
|
&(dstTarget->typeMask), &(dstTarget->registerMask),
|
2008-05-31 22:14:27 +00:00
|
|
|
&thunk);
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
assert(c, not thunk); // todo
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
new (c->zone->allocate(sizeof(MoveEvent)))
|
2008-05-16 16:01:24 +00:00
|
|
|
MoveEvent(c, type, size, src, dst, srcTarget, dstTarget);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-06-11 00:17:44 +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:
|
2008-05-19 13:27:05 +00:00
|
|
|
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)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-05-19 13:27:05 +00:00
|
|
|
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
|
|
|
|
2008-06-11 00:17:44 +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
|
|
|
{
|
2008-05-19 13:27:05 +00:00
|
|
|
VirtualSite* firstTarget = virtualSite(c);
|
|
|
|
VirtualSite* secondTarget = virtualSite(c);
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-05-19 13:27:05 +00:00
|
|
|
|
|
|
|
c->assembler->plan(Compare, size,
|
|
|
|
&(firstTarget->typeMask), &(firstTarget->registerMask),
|
|
|
|
&(secondTarget->typeMask), &(secondTarget->registerMask),
|
2008-05-31 22:14:27 +00:00
|
|
|
&thunk);
|
2008-05-19 13:27:05 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
assert(c, not thunk); // todo
|
2008-05-19 13:27:05 +00:00
|
|
|
|
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)))
|
2008-05-19 13:27:05 +00:00
|
|
|
CompareEvent(c, size, first, second, firstTarget, secondTarget);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 14:53:40 +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);
|
|
|
|
addSite(c, stack, size, v, r);
|
|
|
|
apply(c, Move, size, s, r);
|
|
|
|
}
|
|
|
|
|
2008-04-29 16:25:20 +00:00
|
|
|
void
|
|
|
|
maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
|
|
|
|
{
|
|
|
|
if (v->reads->next and v->sites->next == 0) {
|
2008-05-19 14:53:40 +00:00
|
|
|
preserve(c, stack, size, v, s, v->reads->next);
|
2008-04-29 16:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
2008-05-04 20:55:34 +00:00
|
|
|
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)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-05-16 16:18:36 +00:00
|
|
|
// 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);
|
2008-05-04 20:55:34 +00:00
|
|
|
addRead(c, second, size, secondTarget);
|
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-04-19 21:52:45 +00:00
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr, "CombineEvent.compile\n");
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-04-29 16:25:20 +00:00
|
|
|
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-04-21 00:21:48 +00:00
|
|
|
if (result->reads) {
|
2008-06-12 16:56:48 +00:00
|
|
|
addSite(c, 0, size, result, second->source);
|
2008-04-21 00:21:48 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
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-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
|
|
|
};
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-04-28 22:08:31 +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);
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-04-28 22:08:31 +00:00
|
|
|
|
2008-05-04 20:55:34 +00:00
|
|
|
c->assembler->plan(type, size,
|
|
|
|
&(firstTarget->typeMask), &(firstTarget->registerMask),
|
|
|
|
&(secondTarget->typeMask), &(secondTarget->registerMask),
|
2008-05-31 22:14:27 +00:00
|
|
|
&thunk);
|
2008-04-28 22:08:31 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
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;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-16 16:01:24 +00:00
|
|
|
::push(c, size, second);
|
2008-05-31 22:53:37 +00:00
|
|
|
::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;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
appendCall(c, value(c, constantSite(c, c->client->getThunk(type, size))),
|
|
|
|
0, 0, result, size, argumentStack, 2);
|
2008-05-04 20:55:34 +00:00
|
|
|
} else {
|
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, "appendCombine\n");
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
firstTarget->typeMask &= ~(1 << MemoryOperand);
|
|
|
|
secondTarget->typeMask &= ~(1 << MemoryOperand);
|
|
|
|
|
2008-05-04 20:55:34 +00:00
|
|
|
new (c->zone->allocate(sizeof(CombineEvent)))
|
|
|
|
CombineEvent(c, type, size, first, second, result, firstTarget,
|
|
|
|
secondTarget);
|
|
|
|
}
|
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-04-17 02:55:38 +00:00
|
|
|
TranslateEvent(Context* c, UnaryOperation type, unsigned size, Value* value,
|
2008-05-04 20:55:34 +00:00
|
|
|
Value* result, Site* target):
|
2008-04-17 02:55:38 +00:00
|
|
|
Event(c), type(type), size(size), value(value), result(result)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-05-04 20:55:34 +00:00
|
|
|
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");
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-04-29 16:25:20 +00:00
|
|
|
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-04-21 00:21:48 +00:00
|
|
|
if (result->reads) {
|
2008-06-12 16:56:48 +00:00
|
|
|
addSite(c, 0, size, result, value->source);
|
2008-04-21 00:21:48 +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
|
|
|
UnaryOperation type;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* value;
|
|
|
|
Value* result;
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-12 18:59:45 +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);
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
|
|
|
c->assembler->plan
|
2008-05-31 22:14:27 +00:00
|
|
|
(type, size, &(target->typeMask), &(target->registerMask), &thunk);
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
assert(c, not thunk); // todo
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
target->typeMask &= ~(1 << MemoryOperand);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
new (c->zone->allocate(sizeof(TranslateEvent)))
|
2008-05-04 20:55:34 +00:00
|
|
|
TranslateEvent(c, type, size, value, result, target);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +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));
|
2008-06-10 14:49:13 +00:00
|
|
|
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;
|
2008-06-10 14:49:13 +00:00
|
|
|
int displacement = this->displacement;
|
|
|
|
unsigned scale = this->scale;
|
2008-04-17 20:48:26 +00:00
|
|
|
if (index) {
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantSite* constant = findConstantSite(c, index);
|
2008-06-10 14:49:13 +00:00
|
|
|
|
|
|
|
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) {
|
2008-06-10 14:49:13 +00:00
|
|
|
if (BytesPerWord == 8 and indexRegister != NoRegister) {
|
2008-05-16 16:01:24 +00:00
|
|
|
apply(c, Move4To8, 8, index->source, index->source);
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
2008-05-13 17:27:57 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
addSite(c, 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-04-19 07:03:59 +00:00
|
|
|
Stack*
|
|
|
|
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Stack)))
|
|
|
|
Stack(value, size, index, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
resetStack(Context* c)
|
|
|
|
{
|
|
|
|
unsigned i = 0;
|
|
|
|
Stack* p = 0;
|
|
|
|
for (Stack* s = c->state->stack; s; s = s->next) {
|
2008-04-26 20:56:03 +00:00
|
|
|
Stack* n = stack(c, value(c), s->size, s->index, 0);
|
|
|
|
n->value->sites = n->pushSite = pushSite(c, s->index);
|
|
|
|
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;
|
|
|
|
|
|
|
|
i += s->size;
|
2008-04-17 22:07:32 +00:00
|
|
|
}
|
2008-04-20 05:23:08 +00:00
|
|
|
|
2008-05-19 04:31:52 +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-19 20:41:31 +00:00
|
|
|
void
|
2008-05-12 13:54:47 +00:00
|
|
|
popNow(Context* c, Stack* stack, unsigned count, bool ignore)
|
2008-04-19 20:41:31 +00:00
|
|
|
{
|
|
|
|
Stack* s = stack;
|
|
|
|
unsigned ignored = 0;
|
|
|
|
for (unsigned i = count; i and s;) {
|
|
|
|
if (s->pushed) {
|
2008-05-14 22:36:22 +00:00
|
|
|
removeSite(c, s->value, s->pushSite);
|
|
|
|
s->pushSite = 0;
|
|
|
|
s->pushed = false;
|
|
|
|
|
2008-06-11 14:47:06 +00:00
|
|
|
Value* v = s->value;
|
|
|
|
if (v->reads and v->sites == 0 and (not ignore)) {
|
2008-04-19 20:41:31 +00:00
|
|
|
::ignore(c, ignored);
|
|
|
|
|
2008-06-11 14:47:06 +00:00
|
|
|
Site* target = targetOrRegister(c, v);
|
2008-04-19 20:41:31 +00:00
|
|
|
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "pop %p value: %p target: %p\n",
|
|
|
|
s, s->value, target);
|
|
|
|
}
|
2008-04-19 20:41:31 +00:00
|
|
|
|
2008-06-11 14:47:06 +00:00
|
|
|
addSite(c, stack, s->size * BytesPerWord, v, target);
|
2008-04-26 20:56:03 +00:00
|
|
|
|
|
|
|
apply(c, Pop, BytesPerWord * s->size, target);
|
2008-04-19 20:41:31 +00:00
|
|
|
} else {
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugStack) {
|
2008-06-11 14:47:06 +00:00
|
|
|
fprintf(stderr, "ignore %p value: %p\n", s, v);
|
2008-04-19 21:52:45 +00:00
|
|
|
}
|
2008-04-19 20:41:31 +00:00
|
|
|
|
|
|
|
ignored += s->size;
|
|
|
|
}
|
|
|
|
} else {
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "%p not pushed\n", s);
|
|
|
|
}
|
2008-04-19 20:41:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i -= s->size;
|
|
|
|
s = s->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
::ignore(c, ignored);
|
|
|
|
}
|
|
|
|
|
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) {
|
2008-04-26 20:56:03 +00:00
|
|
|
if (s->pushEvent) s->pushEvent->active = true;
|
|
|
|
addRead(c, s->value, s->size * BytesPerWord, 0);
|
|
|
|
}
|
2008-04-17 20:48:26 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +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) {
|
2008-04-26 20:56:03 +00:00
|
|
|
if (s->pushEvent) s->pushEvent->active = true;
|
|
|
|
insertRead(c, this, sequence, s->value, s->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
|
|
|
|
2008-05-19 04:31:52 +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");
|
|
|
|
}
|
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-04-18 17:30:54 +00:00
|
|
|
class PushSite: public AbstractSite {
|
|
|
|
public:
|
|
|
|
PushSite(PushEvent* event): event(event) { }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Site* readTarget(Context* c, Read* r) {
|
2008-04-18 17:30:54 +00:00
|
|
|
if (r->next and (not event->active)) {
|
2008-05-12 13:54:47 +00:00
|
|
|
return targetOrNull(c, r->next);
|
2008-04-18 17:30:54 +00:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PushEvent* event;
|
|
|
|
};
|
|
|
|
|
|
|
|
Site*
|
|
|
|
pushSite(Context* c, PushEvent* e)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(PushSite))) PushSite(e);
|
|
|
|
}
|
|
|
|
|
2008-04-18 03:47:42 +00:00
|
|
|
void
|
2008-04-19 07:03:59 +00:00
|
|
|
appendPush(Context* c, Stack* s)
|
2008-04-17 02:55:38 +00:00
|
|
|
{
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, "appendPush\n");
|
|
|
|
}
|
2008-04-18 00:39:41 +00:00
|
|
|
|
2008-04-19 07:03:59 +00:00
|
|
|
new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
appendPush(Context* c)
|
|
|
|
{
|
|
|
|
appendPush(c, c->state->stack);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2008-05-12 13:54:47 +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);
|
|
|
|
}
|
|
|
|
|
2008-05-20 19:11:42 +00:00
|
|
|
class ClobberLocalEvent: public Event {
|
2008-05-19 04:31:52 +00:00
|
|
|
public:
|
2008-05-20 19:11:42 +00:00
|
|
|
ClobberLocalEvent(Context* c, unsigned size, Local* local):
|
|
|
|
Event(c), size(size), local(local)
|
2008-05-19 04:31:52 +00:00
|
|
|
{ }
|
|
|
|
|
2008-05-20 19:11:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr, "ClobberLocalEvent.compile\n");
|
|
|
|
}
|
|
|
|
|
2008-05-20 21:24:10 +00:00
|
|
|
for (Local* l = local; l; l = l->old) {
|
|
|
|
Value* v = l->value;
|
|
|
|
Site* s = l->site;
|
|
|
|
if (v->reads
|
|
|
|
and v->sites->next == 0
|
|
|
|
and v->sites == s)
|
|
|
|
{
|
|
|
|
preserve(c, stack, size, v, s, v->reads);
|
|
|
|
}
|
|
|
|
removeSite(c, v, s);
|
2008-05-20 19:11:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned size;
|
|
|
|
Local* local;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendClobberLocal(Context* c, unsigned size, Local* local)
|
|
|
|
{
|
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, "appendClobberLocal\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
new (c->zone->allocate(sizeof(ClobberLocalEvent)))
|
|
|
|
ClobberLocalEvent(c, size, local);
|
|
|
|
}
|
|
|
|
|
|
|
|
class LocalEvent: public Event {
|
|
|
|
public:
|
2008-05-20 21:24:10 +00:00
|
|
|
LocalEvent(Context* c, unsigned size, Local* local):
|
|
|
|
Event(c), size(size), local(local)
|
2008-05-20 19:11:42 +00:00
|
|
|
{
|
2008-05-20 21:24:10 +00:00
|
|
|
if (local->old) {
|
|
|
|
addRead(c, local->old->value, size, 0);
|
2008-05-20 19:11:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
virtual void compile(Context* c) {
|
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr, "LocalEvent.compile\n");
|
|
|
|
}
|
|
|
|
|
2008-05-20 19:11:42 +00:00
|
|
|
Site* sites = 0;
|
2008-05-20 21:24:10 +00:00
|
|
|
if (local->old) {
|
|
|
|
Value* v = local->old->value;
|
|
|
|
if (local->old->reuse and v->reads->next == 0) {
|
2008-05-20 19:11:42 +00:00
|
|
|
sites = v->sites;
|
2008-05-19 14:53:40 +00:00
|
|
|
}
|
2008-05-20 19:11:42 +00:00
|
|
|
|
|
|
|
nextRead(c, v);
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-20 21:24:10 +00:00
|
|
|
Value* v = local->value;
|
2008-05-20 19:11:42 +00:00
|
|
|
if (v->reads) {
|
|
|
|
for (Site* s = sites; s;) {
|
|
|
|
Site* t = s->next;
|
|
|
|
if (s->type(c) != MemoryOperand) {
|
2008-05-20 21:24:10 +00:00
|
|
|
addSite(c, 0, size, v, s);
|
2008-05-20 19:11:42 +00:00
|
|
|
}
|
|
|
|
s = t;
|
|
|
|
}
|
|
|
|
|
2008-05-20 21:24:10 +00:00
|
|
|
addSite(c, 0, size, v, local->site);
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned size;
|
2008-05-20 21:24:10 +00:00
|
|
|
Local* local;
|
2008-05-19 04:31:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-05-20 21:24:10 +00:00
|
|
|
appendLocal(Context* c, unsigned size, Local* local)
|
2008-05-19 04:31:52 +00:00
|
|
|
{
|
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, "appendLocal\n");
|
|
|
|
}
|
|
|
|
|
2008-05-20 21:24:10 +00:00
|
|
|
new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local);
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
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;
|
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantSite* constant = findConstantSite(c, index);
|
2008-05-31 22:14:27 +00:00
|
|
|
CodePromise* nextPromise = codePromise(c, -1);
|
2008-05-31 23:06:45 +00:00
|
|
|
CodePromise* outOfBoundsPromise = 0;
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
apply(c, Compare, 4, index->source, length);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
length->release(c);
|
|
|
|
|
|
|
|
Assembler::Constant nextConstant(nextPromise);
|
|
|
|
a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant);
|
|
|
|
|
|
|
|
if (constant == 0) {
|
|
|
|
outOfBoundsPromise->offset = a->length();
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:53:37 +00:00
|
|
|
Assembler::Constant handlerConstant(resolved(c, handler));
|
2008-05-31 22:14:27 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
if (DebugAppend) {
|
2008-06-01 01:40:18 +00:00
|
|
|
fprintf(stderr, "appendBoundsCheck\n");
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent
|
|
|
|
(c, object, lengthOffset, index, handler);
|
|
|
|
}
|
|
|
|
|
2008-04-18 03:47:42 +00:00
|
|
|
Site*
|
2008-05-12 13:54:47 +00:00
|
|
|
readSource(Context* c, Stack* stack, 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;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
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, ©Cost);
|
|
|
|
|
2008-05-13 17:27:57 +00:00
|
|
|
if (target and copyCost) {
|
|
|
|
addSite(c, stack, 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;
|
|
|
|
|
|
|
|
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
|
|
|
|
2008-05-19 04:31:52 +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) {
|
2008-04-27 20:15:18 +00:00
|
|
|
// 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-05-12 13:54:47 +00:00
|
|
|
s->value->sites->acquire(c, 0, s->size * BytesPerWord, s->value);
|
2008-04-20 05:23:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-15 14:29:19 +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-05-12 13:54:47 +00:00
|
|
|
r->value->source = readSource(c, e->stack, r);
|
2008-05-15 14:29:19 +00:00
|
|
|
|
|
|
|
if (r->value->source) {
|
|
|
|
assert(c, si < e->readCount);
|
|
|
|
sites[si++] = r->value->source;
|
|
|
|
r->value->source->freeze(c);
|
|
|
|
}
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
|
|
|
|
2008-05-15 14:29:19 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2007-12-12 00:27:04 +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;
|
|
|
|
}
|
|
|
|
|
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-04-28 15:53:48 +00:00
|
|
|
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)))
|
2008-04-27 21:58:29 +00:00
|
|
|
State(c->state, c->state->stack);
|
2007-12-14 18:27:56 +00:00
|
|
|
}
|
|
|
|
|
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;
|
2008-05-19 04:31:52 +00:00
|
|
|
c->logicalCode[c->logicalIp].locals = c->locals;
|
2008-04-28 15:53:48 +00:00
|
|
|
|
|
|
|
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)))
|
2008-04-27 21:58:29 +00:00
|
|
|
State(c->state->next->next, c->state->next->stack);
|
|
|
|
|
2008-04-28 15:53:48 +00:00
|
|
|
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 20:57:40 +00:00
|
|
|
}
|
|
|
|
|
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-04-29 20:24:08 +00:00
|
|
|
return stack(c, value, size, (next ? next->index + next->size : 0), next);
|
2008-02-17 22:29:04 +00:00
|
|
|
}
|
|
|
|
|
2007-12-14 00:27:09 +00:00
|
|
|
void
|
2008-04-17 02:55:38 +00:00
|
|
|
push(Context* c, unsigned size, Value* v)
|
2007-12-12 22:19:13 +00:00
|
|
|
{
|
2008-02-17 20:57:40 +00:00
|
|
|
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-05-19 04:31:52 +00:00
|
|
|
void
|
|
|
|
addLocal(Context* c, unsigned size, unsigned index, Value* newValue)
|
|
|
|
{
|
2008-05-20 21:24:10 +00:00
|
|
|
unsigned sizeInWords = ceiling(size, BytesPerWord);
|
|
|
|
|
|
|
|
c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local)))
|
|
|
|
Local(sizeInWords, index, newValue, memorySite
|
|
|
|
(c, c->assembler->base(), localOffset(c, index)),
|
|
|
|
c->localTable[index], c->locals);
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-05-20 21:24:10 +00:00
|
|
|
appendLocal(c, sizeInWords * BytesPerWord, c->locals);
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
Value*
|
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-04-18 03:47:42 +00:00
|
|
|
appendPop(c, s->size, false);
|
2008-03-09 21:27:51 +00:00
|
|
|
|
2008-02-17 20:57:40 +00:00
|
|
|
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-03-11 16:40:28 +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)))
|
2008-05-19 04:31:52 +00:00
|
|
|
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
|
|
|
|
2008-05-04 20:55:34 +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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-13 23:43:11 +00:00
|
|
|
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) {
|
2008-05-12 13:54:47 +00:00
|
|
|
int r = pickRegister(c, mask)->number;
|
2008-04-30 15:44:17 +00:00
|
|
|
save(r);
|
2008-04-20 00:43:12 +00:00
|
|
|
increment(c, r);
|
2008-03-13 23:43:11 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void releaseTemporary(int r) {
|
2008-05-12 13:54:47 +00:00
|
|
|
decrement(c, c->registers[r]);
|
2008-04-30 15:44:17 +00:00
|
|
|
restore(r);
|
2008-03-13 23:43:11 +00:00
|
|
|
}
|
|
|
|
|
2008-04-27 20:15:18 +00:00
|
|
|
virtual void save(int r) {
|
2008-05-12 13:54:47 +00:00
|
|
|
if (c->registers[r]->refCount or c->registers[r]->value) {
|
2008-04-27 20:15:18 +00:00
|
|
|
Assembler::Register operand(r);
|
|
|
|
c->assembler->apply(Push, BytesPerWord, RegisterOperand, &operand);
|
2008-05-12 13:54:47 +00:00
|
|
|
c->registers[r]->pushed = true;
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void restore(int r) {
|
2008-05-12 13:54:47 +00:00
|
|
|
if (c->registers[r]->pushed) {
|
2008-04-27 20:15:18 +00:00
|
|
|
Assembler::Register operand(r);
|
|
|
|
c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &operand);
|
2008-05-12 13:54:47 +00:00
|
|
|
c->registers[r]->pushed = false;
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-13 23:43:11 +00:00
|
|
|
Context* c;
|
|
|
|
};
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
class MyCompiler: public Compiler {
|
|
|
|
public:
|
2008-05-31 22:14:27 +00:00
|
|
|
MyCompiler(System* s, Assembler* assembler, Zone* zone,
|
|
|
|
Compiler::Client* compilerClient):
|
|
|
|
c(s, assembler, zone, compilerClient), client(&c)
|
2008-03-13 23:43:11 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-04-28 15:53:48 +00:00
|
|
|
virtual void saveStack() {
|
|
|
|
::saveStack(&c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void resetStack() {
|
|
|
|
::resetStack(&c);
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
|
|
|
|
unsigned localFootprint)
|
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
c.logicalCodeLength = logicalCodeLength;
|
2008-05-19 04:31:52 +00:00
|
|
|
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);
|
2008-05-19 04:31:52 +00:00
|
|
|
|
|
|
|
c.localTable = static_cast<Local**>
|
|
|
|
(c.zone->allocate(sizeof(Local*) * localFootprint));
|
|
|
|
memset(c.localTable, 0, sizeof(Local*) * localFootprint);
|
2007-12-17 20:55:31 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2008-04-28 15:53:48 +00:00
|
|
|
::saveStack(&c);
|
2008-04-20 19:35:36 +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) {
|
2008-03-13 20:50:56 +00:00
|
|
|
return poolAppendPromise(resolved(&c, 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) {
|
2008-03-13 20:50:56 +00:00
|
|
|
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,
|
2008-04-13 19:48:20 +00:00
|
|
|
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() {
|
2008-04-26 20:56:03 +00:00
|
|
|
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() {
|
2008-04-26 20:56:03 +00:00
|
|
|
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() {
|
2008-04-26 20:56:03 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
Promise* machineIp() {
|
2008-05-31 22:14:27 +00:00
|
|
|
return codePromise(&c, c.logicalCode[c.logicalIp].lastEvent);
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
virtual void mark(Operand* label) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendStackSync(&c);
|
2008-04-28 15:53:48 +00:00
|
|
|
::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
|
|
|
}
|
|
|
|
|
2008-04-26 20:56:03 +00:00
|
|
|
virtual void push(unsigned size) {
|
2008-04-27 20:15:18 +00:00
|
|
|
assert(&c, ceiling(size, BytesPerWord));
|
|
|
|
|
|
|
|
c.state->stack = ::stack
|
|
|
|
(&c, value(&c), ceiling(size, BytesPerWord), c.state->stack);
|
2008-04-26 20:56:03 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
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
|
|
|
|
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) {
|
2008-03-15 23:54:20 +00:00
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
2008-04-20 01:08:26 +00:00
|
|
|
Value* v = value(&c);
|
|
|
|
c.state->stack = ::stack(&c, v, 1, c.state->stack);
|
|
|
|
c.state->stack->pushed = true;
|
2008-06-10 14:49:13 +00:00
|
|
|
c.state->stack->pushSite
|
|
|
|
= v->sites = pushSite(&c, c.state->stack->index);
|
2008-03-15 23:54:20 +00:00
|
|
|
}
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void popped(unsigned count) {
|
2008-04-18 03:47:42 +00:00
|
|
|
appendPop(&c, count, true);
|
2008-03-15 23:54:20 +00:00
|
|
|
|
|
|
|
for (unsigned i = count; i;) {
|
2008-02-17 20:57:40 +00:00
|
|
|
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;) {
|
|
|
|
i -= s->size;
|
2008-04-29 16:55:56 +00:00
|
|
|
s = s->next;
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
|
|
|
assert(&c, s->size == ceiling(size, BytesPerWord));
|
2008-04-17 20:48:26 +00:00
|
|
|
return s->value;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
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;
|
2008-02-12 02:06:12 +00:00
|
|
|
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*);
|
2008-02-12 02:06:12 +00:00
|
|
|
if (o) {
|
2008-04-17 20:48:26 +00:00
|
|
|
arguments[index] = o;
|
|
|
|
argumentSizes[index] = size;
|
2008-02-12 02:06:12 +00:00
|
|
|
size = BytesPerWord;
|
2008-04-17 20:48:26 +00:00
|
|
|
++ index;
|
2008-02-12 02:06:12 +00:00
|
|
|
} 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-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-04-29 16:40:44 +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-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-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
2008-05-06 21:13:02 +00:00
|
|
|
appendCall(&c, static_cast<Value*>(address), flags,
|
2008-04-19 00:19:45 +00:00
|
|
|
traceHandler, result, resultSize, argumentStack,
|
|
|
|
index);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
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) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendReturn(&c, size, static_cast<Value*>(value));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
virtual void storeLocal(unsigned size, Operand* src, unsigned index) {
|
|
|
|
assert(&c, index < c.localFootprint);
|
2008-05-20 19:11:42 +00:00
|
|
|
|
|
|
|
if (c.localTable[index]) {
|
|
|
|
appendClobberLocal(&c, size, c.localTable[index]);
|
|
|
|
c.localTable[index] = 0;
|
|
|
|
}
|
|
|
|
|
2008-05-19 16:14:54 +00:00
|
|
|
store(size, src, memory(base(), localOffset(&c, index)));
|
2008-05-20 19:11:42 +00:00
|
|
|
|
|
|
|
// todo: find out why this doesn't work and fix it:
|
|
|
|
// addLocal(&c, size, index, static_cast<Value*>(src));
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* loadLocal(unsigned size, unsigned index) {
|
|
|
|
assert(&c, index < c.localFootprint);
|
2008-05-20 19:11:42 +00:00
|
|
|
|
|
|
|
Value* v = value(&c);
|
|
|
|
addLocal(&c, size, index, v);
|
|
|
|
return v;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
virtual void checkBounds(Operand* object, unsigned lengthOffset,
|
|
|
|
Operand* index, intptr_t handler)
|
|
|
|
{
|
|
|
|
appendBoundsCheck(&c, static_cast<Value*>(object),
|
|
|
|
lengthOffset, static_cast<Value*>(index), handler);
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
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));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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);
|
2008-04-21 02:50:46 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-06-12 16:56:48 +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;
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
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));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
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));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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;
|
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) {
|
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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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;
|
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) {
|
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;
|
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) {
|
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;
|
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) {
|
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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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;
|
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) {
|
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
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +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() {
|
2008-03-11 16:40:28 +00:00
|
|
|
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;
|
2008-05-31 22:14:27 +00:00
|
|
|
::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,
|
2008-05-31 22:14:27 +00:00
|
|
|
Compiler::Client* client)
|
2007-12-08 23:22:13 +00:00
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
return new (zone->allocate(sizeof(MyCompiler)))
|
2008-05-31 22:14:27 +00:00
|
|
|
MyCompiler(system, assembler, zone, client);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
} // namespace vm
|