mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
move CallEvent out of compiler.cpp
This commit is contained in:
parent
6d265374ec
commit
0f6e098b69
2
makefile
2
makefile
@ -959,6 +959,8 @@ ifeq ($(process),compile)
|
|||||||
$(src)/codegen/compiler/regalloc.cpp \
|
$(src)/codegen/compiler/regalloc.cpp \
|
||||||
$(src)/codegen/compiler/value.cpp \
|
$(src)/codegen/compiler/value.cpp \
|
||||||
$(src)/codegen/compiler/read.cpp \
|
$(src)/codegen/compiler/read.cpp \
|
||||||
|
$(src)/codegen/compiler/event.cpp \
|
||||||
|
$(src)/codegen/compiler/promise.cpp \
|
||||||
$(src)/codegen/registers.cpp \
|
$(src)/codegen/registers.cpp \
|
||||||
$(src)/codegen/targets.cpp
|
$(src)/codegen/targets.cpp
|
||||||
|
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
#include "codegen/compiler/value.h"
|
#include "codegen/compiler/value.h"
|
||||||
#include "codegen/compiler/site.h"
|
#include "codegen/compiler/site.h"
|
||||||
#include "codegen/compiler/read.h"
|
#include "codegen/compiler/read.h"
|
||||||
|
#include "codegen/compiler/event.h"
|
||||||
|
#include "codegen/compiler/stack.h"
|
||||||
|
#include "codegen/compiler/promise.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
@ -33,8 +36,6 @@ const bool DebugCompile = false;
|
|||||||
const bool DebugResources = false;
|
const bool DebugResources = false;
|
||||||
const bool DebugFrame = false;
|
const bool DebugFrame = false;
|
||||||
const bool DebugControl = false;
|
const bool DebugControl = false;
|
||||||
const bool DebugReads = false;
|
|
||||||
const bool DebugSites = false;
|
|
||||||
const bool DebugMoves = false;
|
const bool DebugMoves = false;
|
||||||
const bool DebugBuddies = false;
|
const bool DebugBuddies = false;
|
||||||
|
|
||||||
@ -45,7 +46,6 @@ const unsigned StealRegisterReserveCount = 2;
|
|||||||
const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4);
|
const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4);
|
||||||
|
|
||||||
class Stack;
|
class Stack;
|
||||||
class Event;
|
|
||||||
class PushEvent;
|
class PushEvent;
|
||||||
class Read;
|
class Read;
|
||||||
class MultiRead;
|
class MultiRead;
|
||||||
@ -73,17 +73,6 @@ class Local {
|
|||||||
Value* value;
|
Value* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Stack {
|
|
||||||
public:
|
|
||||||
Stack(unsigned index, Value* value, Stack* next):
|
|
||||||
index(index), value(value), next(next)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
unsigned index;
|
|
||||||
Value* value;
|
|
||||||
Stack* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ForkElement {
|
class ForkElement {
|
||||||
public:
|
public:
|
||||||
Value* value;
|
Value* value;
|
||||||
@ -166,33 +155,6 @@ class PoolPromise: public Promise {
|
|||||||
int key;
|
int key;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CodePromise: public Promise {
|
|
||||||
public:
|
|
||||||
CodePromise(Context* c, CodePromise* next):
|
|
||||||
c(c), offset(0), next(next)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
CodePromise(Context* c, Promise* offset):
|
|
||||||
c(c), offset(offset), next(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual int64_t value() {
|
|
||||||
if (resolved()) {
|
|
||||||
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
|
||||||
}
|
|
||||||
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool resolved() {
|
|
||||||
return c->machineCode != 0 and offset and offset->resolved();
|
|
||||||
}
|
|
||||||
|
|
||||||
Context* c;
|
|
||||||
Promise* offset;
|
|
||||||
CodePromise* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
machineOffset(Context* c, int logicalIp)
|
machineOffset(Context* c, int logicalIp)
|
||||||
{
|
{
|
||||||
@ -298,43 +260,6 @@ countSuccessors(Link* link)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Event {
|
|
||||||
public:
|
|
||||||
Event(Context* c):
|
|
||||||
next(0), stackBefore(c->stack), localsBefore(c->locals),
|
|
||||||
stackAfter(0), localsAfter(0), promises(0), reads(0),
|
|
||||||
junctionSites(0), snapshots(0), predecessors(0), successors(0),
|
|
||||||
visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
|
|
||||||
readCount(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual const char* name() = 0;
|
|
||||||
|
|
||||||
virtual void compile(Context* c) = 0;
|
|
||||||
|
|
||||||
virtual bool isBranch() { return false; }
|
|
||||||
|
|
||||||
virtual bool allExits() { return false; }
|
|
||||||
|
|
||||||
virtual Local* locals() { return localsBefore; }
|
|
||||||
|
|
||||||
Event* next;
|
|
||||||
Stack* stackBefore;
|
|
||||||
Local* localsBefore;
|
|
||||||
Stack* stackAfter;
|
|
||||||
Local* localsAfter;
|
|
||||||
CodePromise* promises;
|
|
||||||
Read* reads;
|
|
||||||
Site** junctionSites;
|
|
||||||
Snapshot* snapshots;
|
|
||||||
Link* predecessors;
|
|
||||||
Link* successors;
|
|
||||||
Cell<Link>* visitLinks;
|
|
||||||
Block* block;
|
|
||||||
LogicalInstruction* logicalInstruction;
|
|
||||||
unsigned readCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
totalFrameSize(Context* c)
|
totalFrameSize(Context* c)
|
||||||
{
|
{
|
||||||
@ -479,20 +404,6 @@ uniqueSite(Context* c, Value* v, Site* s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
addSite(Context* c, Value* v, Site* s)
|
|
||||||
{
|
|
||||||
if (not v->findSite(s)) {
|
|
||||||
if (DebugSites) {
|
|
||||||
char buffer[256]; s->toString(c, buffer, 256);
|
|
||||||
fprintf(stderr, "add site %s to %p\n", buffer, v);
|
|
||||||
}
|
|
||||||
s->acquire(c, v);
|
|
||||||
s->next = v->sites;
|
|
||||||
v->sites = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
removeSite(Context* c, Value* v, Site* s)
|
removeSite(Context* c, Value* v, Site* s)
|
||||||
{
|
{
|
||||||
@ -598,7 +509,7 @@ deadWord(Context* c, Value* v)
|
|||||||
|
|
||||||
if (s->registerSize(c) > TargetBytesPerWord) {
|
if (s->registerSize(c) > TargetBytesPerWord) {
|
||||||
it.remove(c);
|
it.remove(c);
|
||||||
addSite(c, nextWord, s);
|
nextWord->addSite(c, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -631,7 +542,7 @@ deadBuddy(Context* c, Value* v, Read* r UNUSED)
|
|||||||
Site* s = it.next();
|
Site* s = it.next();
|
||||||
it.remove(c);
|
it.remove(c);
|
||||||
|
|
||||||
addSite(c, next, s);
|
next->addSite(c, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,14 +688,6 @@ pickTargetSite(Context* c, Read* read, bool intersectRead = false,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleRead*
|
|
||||||
read(Context* c, const SiteMask& mask, Value* successor = 0)
|
|
||||||
{
|
|
||||||
assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
|
||||||
|
|
||||||
return new(c->zone) SingleRead(mask, successor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
acceptMatch(Context* c, Site* s, Read*, const SiteMask& mask)
|
acceptMatch(Context* c, Site* s, Read*, const SiteMask& mask)
|
||||||
{
|
{
|
||||||
@ -919,7 +822,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
|
|||||||
|
|
||||||
src->freeze(c, value);
|
src->freeze(c, value);
|
||||||
|
|
||||||
addSite(c, value, dst);
|
value->addSite(c, dst);
|
||||||
|
|
||||||
src->thaw(c, value);
|
src->thaw(c, value);
|
||||||
|
|
||||||
@ -934,7 +837,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
|
|||||||
|
|
||||||
Site* tmp = pickTargetSite(c, &tmpRead, true);
|
Site* tmp = pickTargetSite(c, &tmpRead, true);
|
||||||
|
|
||||||
addSite(c, value, tmp);
|
value->addSite(c, tmp);
|
||||||
|
|
||||||
move(c, value, src, tmp);
|
move(c, value, src, tmp);
|
||||||
|
|
||||||
@ -1027,13 +930,6 @@ generalRegisterOrConstantMask(Context* c)
|
|||||||
c->regFile->generalRegisters.mask, NoFrameIndex);
|
c->regFile->generalRegisters.mask, NoFrameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
SiteMask
|
|
||||||
fixedRegisterMask(int number)
|
|
||||||
{
|
|
||||||
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MultiRead*
|
MultiRead*
|
||||||
multiRead(Context* c)
|
multiRead(Context* c)
|
||||||
{
|
{
|
||||||
@ -1093,7 +989,7 @@ pickSiteOrGrow(Context* c, Value* v, Site* s, unsigned index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
n = s->makeNextWord(c, index);
|
n = s->makeNextWord(c, index);
|
||||||
addSite(c, v, n);
|
v->addSite(c, n);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,61 +1156,6 @@ apply(Context* c, lir::TernaryOperation op,
|
|||||||
OperandInfo(s3Size, s3Type, &s3Union));
|
OperandInfo(s3Size, s3Type, &s3Union));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
addRead(Context* c, Event* e, Value* v, Read* r)
|
|
||||||
{
|
|
||||||
if (DebugReads) {
|
|
||||||
fprintf(stderr, "add read %p to %p last %p event %p (%s)\n",
|
|
||||||
r, v, v->lastRead, e, (e ? e->name() : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
r->value = v;
|
|
||||||
if (e) {
|
|
||||||
r->event = e;
|
|
||||||
r->eventNext = e->reads;
|
|
||||||
e->reads = r;
|
|
||||||
++ e->readCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v->lastRead) {
|
|
||||||
// if (DebugReads) {
|
|
||||||
// fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
|
|
||||||
// }
|
|
||||||
|
|
||||||
v->lastRead->append(c, r);
|
|
||||||
} else {
|
|
||||||
v->reads = r;
|
|
||||||
}
|
|
||||||
v->lastRead = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
addRead(Context* c, Event* e, Value* v, const SiteMask& mask,
|
|
||||||
Value* successor = 0)
|
|
||||||
{
|
|
||||||
addRead(c, e, v, read(c, mask, successor));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
addReads(Context* c, Event* e, Value* v, unsigned size,
|
|
||||||
const SiteMask& lowMask, Value* lowSuccessor,
|
|
||||||
const SiteMask& highMask, Value* highSuccessor)
|
|
||||||
{
|
|
||||||
SingleRead* r = read(c, lowMask, lowSuccessor);
|
|
||||||
addRead(c, e, v, r);
|
|
||||||
if (size > TargetBytesPerWord) {
|
|
||||||
r->high_ = v->nextWord;
|
|
||||||
addRead(c, e, v->nextWord, highMask, highSuccessor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
addReads(Context* c, Event* e, Value* v, unsigned size,
|
|
||||||
const SiteMask& lowMask, const SiteMask& highMask)
|
|
||||||
{
|
|
||||||
addReads(c, e, v, size, lowMask, 0, highMask, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
clean(Context* c, Value* v, unsigned popIndex)
|
clean(Context* c, Value* v, unsigned popIndex)
|
||||||
{
|
{
|
||||||
@ -1353,18 +1194,6 @@ clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CodePromise*
|
|
||||||
codePromise(Context* c, Event* e)
|
|
||||||
{
|
|
||||||
return e->promises = new(c->zone) CodePromise(c, e->promises);
|
|
||||||
}
|
|
||||||
|
|
||||||
CodePromise*
|
|
||||||
codePromise(Context* c, Promise* offset)
|
|
||||||
{
|
|
||||||
return new (c->zone) CodePromise(c, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
append(Context* c, Event* e);
|
append(Context* c, Event* e);
|
||||||
|
|
||||||
@ -1379,333 +1208,12 @@ saveLocals(Context* c, Event* e)
|
|||||||
local->value, compiler::frameIndex(c, li), totalFrameSize(c));
|
local->value, compiler::frameIndex(c, li), totalFrameSize(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
addRead(c, e, local->value, SiteMask
|
e->addRead(c, local->value, SiteMask
|
||||||
(1 << lir::MemoryOperand, 0, compiler::frameIndex(c, li)));
|
(1 << lir::MemoryOperand, 0, compiler::frameIndex(c, li)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallEvent: public Event {
|
|
||||||
public:
|
|
||||||
CallEvent(Context* c, Value* address, unsigned flags,
|
|
||||||
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
|
||||||
Stack* argumentStack, unsigned argumentCount,
|
|
||||||
unsigned stackArgumentFootprint):
|
|
||||||
Event(c),
|
|
||||||
address(address),
|
|
||||||
traceHandler(traceHandler),
|
|
||||||
result(result),
|
|
||||||
returnAddressSurrogate(0),
|
|
||||||
framePointerSurrogate(0),
|
|
||||||
popIndex(0),
|
|
||||||
stackArgumentIndex(0),
|
|
||||||
flags(flags),
|
|
||||||
resultSize(resultSize),
|
|
||||||
stackArgumentFootprint(stackArgumentFootprint)
|
|
||||||
{
|
|
||||||
uint32_t registerMask = c->regFile->generalRegisters.mask;
|
|
||||||
|
|
||||||
if (argumentCount) {
|
|
||||||
assert(c, (flags & Compiler::TailJump) == 0);
|
|
||||||
assert(c, stackArgumentFootprint == 0);
|
|
||||||
|
|
||||||
Stack* s = argumentStack;
|
|
||||||
unsigned index = 0;
|
|
||||||
unsigned argumentIndex = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
unsigned footprint
|
|
||||||
= (argumentIndex + 1 < argumentCount
|
|
||||||
and s->value->nextWord == s->next->value)
|
|
||||||
? 2 : 1;
|
|
||||||
|
|
||||||
if (index % (c->arch->argumentAlignment() ? footprint : 1)) {
|
|
||||||
++ index;
|
|
||||||
}
|
|
||||||
|
|
||||||
SiteMask targetMask;
|
|
||||||
if (index + (c->arch->argumentRegisterAlignment() ? footprint : 1)
|
|
||||||
<= c->arch->argumentRegisterCount())
|
|
||||||
{
|
|
||||||
int number = c->arch->argumentRegister(index);
|
|
||||||
|
|
||||||
if (DebugReads) {
|
|
||||||
fprintf(stderr, "reg %d arg read %p\n", number, s->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
targetMask = fixedRegisterMask(number);
|
|
||||||
registerMask &= ~(1 << number);
|
|
||||||
} else {
|
|
||||||
if (index < c->arch->argumentRegisterCount()) {
|
|
||||||
index = c->arch->argumentRegisterCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned frameIndex = index - c->arch->argumentRegisterCount();
|
|
||||||
|
|
||||||
if (DebugReads) {
|
|
||||||
fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
targetMask = SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
addRead(c, this, s->value, targetMask);
|
|
||||||
|
|
||||||
++ index;
|
|
||||||
|
|
||||||
if ((++ argumentIndex) < argumentCount) {
|
|
||||||
s = s->next;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DebugReads) {
|
|
||||||
fprintf(stderr, "address read %p\n", address);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ bool thunk;
|
|
||||||
uint8_t typeMask;
|
|
||||||
uint64_t planRegisterMask;
|
|
||||||
c->arch->plan
|
|
||||||
((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, TargetBytesPerWord,
|
|
||||||
&typeMask, &planRegisterMask, &thunk);
|
|
||||||
|
|
||||||
assert(c, not thunk);
|
|
||||||
|
|
||||||
addRead(c, this, address, SiteMask
|
|
||||||
(typeMask, registerMask & planRegisterMask, AnyFrameIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack* stack = stackBefore;
|
|
||||||
|
|
||||||
if (stackArgumentFootprint) {
|
|
||||||
RUNTIME_ARRAY(Value*, arguments, stackArgumentFootprint);
|
|
||||||
for (int i = stackArgumentFootprint - 1; i >= 0; --i) {
|
|
||||||
Value* v = stack->value;
|
|
||||||
stack = stack->next;
|
|
||||||
|
|
||||||
if ((TargetBytesPerWord == 8
|
|
||||||
and (v == 0 or (i >= 1 and stack->value == 0)))
|
|
||||||
or (TargetBytesPerWord == 4 and v->nextWord != v))
|
|
||||||
{
|
|
||||||
assert(c, TargetBytesPerWord == 8 or v->nextWord == stack->value);
|
|
||||||
|
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i--] = stack->value;
|
|
||||||
stack = stack->next;
|
|
||||||
}
|
|
||||||
RUNTIME_ARRAY_BODY(arguments)[i] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
int returnAddressIndex;
|
|
||||||
int framePointerIndex;
|
|
||||||
int frameOffset;
|
|
||||||
|
|
||||||
if (TailCalls and (flags & Compiler::TailJump)) {
|
|
||||||
assert(c, argumentCount == 0);
|
|
||||||
|
|
||||||
int base = frameBase(c);
|
|
||||||
returnAddressIndex = base + c->arch->returnAddressOffset();
|
|
||||||
if (UseFramePointer) {
|
|
||||||
framePointerIndex = base + c->arch->framePointerOffset();
|
|
||||||
} else {
|
|
||||||
framePointerIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
frameOffset = totalFrameSize(c)
|
|
||||||
- c->arch->argumentFootprint(stackArgumentFootprint);
|
|
||||||
} else {
|
|
||||||
returnAddressIndex = -1;
|
|
||||||
framePointerIndex = -1;
|
|
||||||
frameOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < stackArgumentFootprint; ++i) {
|
|
||||||
Value* v = RUNTIME_ARRAY_BODY(arguments)[i];
|
|
||||||
if (v) {
|
|
||||||
int frameIndex = i + frameOffset;
|
|
||||||
|
|
||||||
if (DebugReads) {
|
|
||||||
fprintf(stderr, "stack arg read %p at %d of %d\n",
|
|
||||||
v, frameIndex, totalFrameSize(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static_cast<int>(frameIndex) == returnAddressIndex) {
|
|
||||||
returnAddressSurrogate = v;
|
|
||||||
addRead(c, this, v, generalRegisterMask(c));
|
|
||||||
} else if (static_cast<int>(frameIndex) == framePointerIndex) {
|
|
||||||
framePointerSurrogate = v;
|
|
||||||
addRead(c, this, v, generalRegisterMask(c));
|
|
||||||
} else {
|
|
||||||
addRead(c, this, v, SiteMask(1 << lir::MemoryOperand, 0, frameIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((not TailCalls) or (flags & Compiler::TailJump) == 0) {
|
|
||||||
stackArgumentIndex = c->localFootprint;
|
|
||||||
if (stackBefore) {
|
|
||||||
stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint;
|
|
||||||
}
|
|
||||||
|
|
||||||
popIndex
|
|
||||||
= c->alignedFrameSize
|
|
||||||
+ c->parameterFootprint
|
|
||||||
- c->arch->frameFooterSize()
|
|
||||||
- stackArgumentIndex;
|
|
||||||
|
|
||||||
assert(c, static_cast<int>(popIndex) >= 0);
|
|
||||||
|
|
||||||
while (stack) {
|
|
||||||
if (stack->value) {
|
|
||||||
unsigned logicalIndex = compiler::frameIndex
|
|
||||||
(c, stack->index + c->localFootprint);
|
|
||||||
|
|
||||||
if (DebugReads) {
|
|
||||||
fprintf(stderr, "stack save read %p at %d of %d\n",
|
|
||||||
stack->value, logicalIndex, totalFrameSize(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
addRead(c, this, stack->value, SiteMask
|
|
||||||
(1 << lir::MemoryOperand, 0, logicalIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
stack = stack->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
saveLocals(c, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* name() {
|
|
||||||
return "CallEvent";
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
|
||||||
lir::UnaryOperation op;
|
|
||||||
|
|
||||||
if (TailCalls and (flags & Compiler::TailJump)) {
|
|
||||||
if (flags & Compiler::LongJumpOrCall) {
|
|
||||||
if (flags & Compiler::Aligned) {
|
|
||||||
op = lir::AlignedLongJump;
|
|
||||||
} else {
|
|
||||||
op = lir::LongJump;
|
|
||||||
}
|
|
||||||
} else if (flags & Compiler::Aligned) {
|
|
||||||
op = lir::AlignedJump;
|
|
||||||
} else {
|
|
||||||
op = lir::Jump;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(c, returnAddressSurrogate == 0
|
|
||||||
or returnAddressSurrogate->source->type(c) == lir::RegisterOperand);
|
|
||||||
assert(c, framePointerSurrogate == 0
|
|
||||||
or framePointerSurrogate->source->type(c) == lir::RegisterOperand);
|
|
||||||
|
|
||||||
int ras;
|
|
||||||
if (returnAddressSurrogate) {
|
|
||||||
returnAddressSurrogate->source->freeze(c, returnAddressSurrogate);
|
|
||||||
|
|
||||||
ras = static_cast<RegisterSite*>
|
|
||||||
(returnAddressSurrogate->source)->number;
|
|
||||||
} else {
|
|
||||||
ras = lir::NoRegister;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fps;
|
|
||||||
if (framePointerSurrogate) {
|
|
||||||
framePointerSurrogate->source->freeze(c, framePointerSurrogate);
|
|
||||||
|
|
||||||
fps = static_cast<RegisterSite*>
|
|
||||||
(framePointerSurrogate->source)->number;
|
|
||||||
} else {
|
|
||||||
fps = lir::NoRegister;
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset
|
|
||||||
= static_cast<int>(c->arch->argumentFootprint(stackArgumentFootprint))
|
|
||||||
- static_cast<int>(c->arch->argumentFootprint(c->parameterFootprint));
|
|
||||||
|
|
||||||
c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps);
|
|
||||||
} else if (flags & Compiler::LongJumpOrCall) {
|
|
||||||
if (flags & Compiler::Aligned) {
|
|
||||||
op = lir::AlignedLongCall;
|
|
||||||
} else {
|
|
||||||
op = lir::LongCall;
|
|
||||||
}
|
|
||||||
} else if (flags & Compiler::Aligned) {
|
|
||||||
op = lir::AlignedCall;
|
|
||||||
} else {
|
|
||||||
op = lir::Call;
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(c, op, TargetBytesPerWord, address->source, address->source);
|
|
||||||
|
|
||||||
if (traceHandler) {
|
|
||||||
traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)),
|
|
||||||
stackArgumentIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TailCalls) {
|
|
||||||
if (flags & Compiler::TailJump) {
|
|
||||||
if (returnAddressSurrogate) {
|
|
||||||
returnAddressSurrogate->source->thaw(c, returnAddressSurrogate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (framePointerSurrogate) {
|
|
||||||
framePointerSurrogate->source->thaw(c, framePointerSurrogate);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsigned footprint = c->arch->argumentFootprint
|
|
||||||
(stackArgumentFootprint);
|
|
||||||
|
|
||||||
if (footprint > c->arch->stackAlignmentInWords()) {
|
|
||||||
c->assembler->adjustFrame
|
|
||||||
(footprint - c->arch->stackAlignmentInWords());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
|
||||||
|
|
||||||
if (resultSize and live(c, result)) {
|
|
||||||
addSite(c, result, registerSite(c, c->arch->returnLow()));
|
|
||||||
if (resultSize > TargetBytesPerWord and live(c, result->nextWord)) {
|
|
||||||
addSite(c, result->nextWord, registerSite(c, c->arch->returnHigh()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool allExits() {
|
|
||||||
return (flags & Compiler::TailJump) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* address;
|
|
||||||
TraceHandler* traceHandler;
|
|
||||||
Value* result;
|
|
||||||
Value* returnAddressSurrogate;
|
|
||||||
Value* framePointerSurrogate;
|
|
||||||
unsigned popIndex;
|
|
||||||
unsigned stackArgumentIndex;
|
|
||||||
unsigned flags;
|
|
||||||
unsigned resultSize;
|
|
||||||
unsigned stackArgumentFootprint;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
appendCall(Context* c, Value* address, unsigned flags,
|
|
||||||
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
|
||||||
Stack* argumentStack, unsigned argumentCount,
|
|
||||||
unsigned stackArgumentFootprint)
|
|
||||||
{
|
|
||||||
append(c, new(c->zone)
|
|
||||||
CallEvent(c, address, flags, traceHandler, result,
|
|
||||||
resultSize, argumentStack, argumentCount,
|
|
||||||
stackArgumentFootprint));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
unreachable(Event* event)
|
unreachable(Event* event)
|
||||||
{
|
{
|
||||||
@ -1721,8 +1229,9 @@ class ReturnEvent: public Event {
|
|||||||
Event(c), value(value)
|
Event(c), value(value)
|
||||||
{
|
{
|
||||||
if (value) {
|
if (value) {
|
||||||
addReads(c, this, value, size, fixedRegisterMask(c->arch->returnLow()),
|
this->addReads(c, value, size,
|
||||||
fixedRegisterMask(c->arch->returnHigh()));
|
SiteMask::fixedRegisterMask(c->arch->returnLow()),
|
||||||
|
SiteMask::fixedRegisterMask(c->arch->returnHigh()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1781,7 +1290,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
|
|||||||
|
|
||||||
src->source->freeze(c, src);
|
src->source->freeze(c, src);
|
||||||
|
|
||||||
addSite(c, dst, target);
|
dst->addSite(c, target);
|
||||||
|
|
||||||
src->source->thaw(c, src);
|
src->source->thaw(c, src);
|
||||||
|
|
||||||
@ -1835,7 +1344,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
|
|||||||
|
|
||||||
src->source->freeze(c, src);
|
src->source->freeze(c, src);
|
||||||
|
|
||||||
addSite(c, dst, tmpTarget);
|
dst->addSite(c, tmpTarget);
|
||||||
|
|
||||||
tmpTarget->freeze(c, dst);
|
tmpTarget->freeze(c, dst);
|
||||||
|
|
||||||
@ -1861,7 +1370,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
|
|||||||
srcb, dstb, src, dst);
|
srcb, dstb, src, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
addSite(c, dst, target);
|
dst->addSite(c, target);
|
||||||
|
|
||||||
tmpTarget->freeze(c, dst);
|
tmpTarget->freeze(c, dst);
|
||||||
|
|
||||||
@ -1968,8 +1477,8 @@ split(Context* c, Value* v)
|
|||||||
Site* s = it.next();
|
Site* s = it.next();
|
||||||
removeSite(c, v, s);
|
removeSite(c, v, s);
|
||||||
|
|
||||||
addSite(c, v, s->copyLow(c));
|
v->addSite(c, s->copyLow(c));
|
||||||
addSite(c, v->nextWord, s->copyHigh(c));
|
v->nextWord->addSite(c, s->copyHigh(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2001,7 +1510,7 @@ class MoveEvent: public Event {
|
|||||||
maybeSplit(c, src);
|
maybeSplit(c, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
addReads(c, this, src, srcSelectSize, srcLowMask, noop ? dst : 0,
|
this->addReads(c, src, srcSelectSize, srcLowMask, noop ? dst : 0,
|
||||||
srcHighMask,
|
srcHighMask,
|
||||||
noop and dstSize > TargetBytesPerWord ? dst->nextWord : 0);
|
noop and dstSize > TargetBytesPerWord ? dst->nextWord : 0);
|
||||||
}
|
}
|
||||||
@ -2081,7 +1590,7 @@ class MoveEvent: public Event {
|
|||||||
|
|
||||||
src->source->freeze(c, src);
|
src->source->freeze(c, src);
|
||||||
|
|
||||||
addSite(c, dst, low);
|
dst->addSite(c, low);
|
||||||
|
|
||||||
low->freeze(c, dst);
|
low->freeze(c, dst);
|
||||||
|
|
||||||
@ -2105,7 +1614,7 @@ class MoveEvent: public Event {
|
|||||||
|
|
||||||
low->freeze(c, dst);
|
low->freeze(c, dst);
|
||||||
|
|
||||||
addSite(c, dst->nextWord, high);
|
dst->nextWord->addSite(c, high);
|
||||||
|
|
||||||
high->freeze(c, dst->nextWord);
|
high->freeze(c, dst->nextWord);
|
||||||
|
|
||||||
@ -2203,7 +1712,7 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask)
|
|||||||
r.successor_ = result;
|
r.successor_ = result;
|
||||||
s = pickTargetSite(c, &r, true);
|
s = pickTargetSite(c, &r, true);
|
||||||
v = result;
|
v = result;
|
||||||
addSite(c, result, s);
|
result->addSite(c, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeSite(c, v, s);
|
removeSite(c, v, s);
|
||||||
@ -2245,7 +1754,7 @@ class CombineEvent: public Event {
|
|||||||
secondSize(secondSize), second(second), resultSize(resultSize),
|
secondSize(secondSize), second(second), resultSize(resultSize),
|
||||||
result(result)
|
result(result)
|
||||||
{
|
{
|
||||||
addReads(c, this, first, firstSize, firstLowMask, firstHighMask);
|
this->addReads(c, first, firstSize, firstLowMask, firstHighMask);
|
||||||
|
|
||||||
if (resultSize > TargetBytesPerWord) {
|
if (resultSize > TargetBytesPerWord) {
|
||||||
grow(c, result);
|
grow(c, result);
|
||||||
@ -2253,7 +1762,7 @@ class CombineEvent: public Event {
|
|||||||
|
|
||||||
bool condensed = c->arch->alwaysCondensed(type);
|
bool condensed = c->arch->alwaysCondensed(type);
|
||||||
|
|
||||||
addReads(c, this, second, secondSize,
|
this->addReads(c, second, secondSize,
|
||||||
secondLowMask, condensed ? result : 0,
|
secondLowMask, condensed ? result : 0,
|
||||||
secondHighMask, condensed ? result->nextWord : 0);
|
secondHighMask, condensed ? result->nextWord : 0);
|
||||||
}
|
}
|
||||||
@ -2325,9 +1834,9 @@ class CombineEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (live(c, result)) {
|
if (live(c, result)) {
|
||||||
addSite(c, result, low);
|
result->addSite(c, low);
|
||||||
if (resultSize > lowSize and live(c, result->nextWord)) {
|
if (resultSize > lowSize and live(c, result->nextWord)) {
|
||||||
addSite(c, result->nextWord, high);
|
result->nextWord->addSite(c, high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2715,7 +2224,7 @@ class TranslateEvent: public Event {
|
|||||||
grow(c, result);
|
grow(c, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
addReads(c, this, value, valueSize, valueLowMask, condensed ? result : 0,
|
this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0,
|
||||||
valueHighMask, condensed ? result->nextWord : 0);
|
valueHighMask, condensed ? result->nextWord : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2762,9 +2271,9 @@ class TranslateEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (live(c, result)) {
|
if (live(c, result)) {
|
||||||
addSite(c, result, low);
|
result->addSite(c, low);
|
||||||
if (resultSize > lowSize and live(c, result->nextWord)) {
|
if (resultSize > lowSize and live(c, result->nextWord)) {
|
||||||
addSite(c, result->nextWord, high);
|
result->nextWord->addSite(c, high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2856,9 +2365,9 @@ class MemoryEvent: public Event {
|
|||||||
Event(c), base(base), displacement(displacement), index(index),
|
Event(c), base(base), displacement(displacement), index(index),
|
||||||
scale(scale), result(result)
|
scale(scale), result(result)
|
||||||
{
|
{
|
||||||
addRead(c, this, base, generalRegisterMask(c));
|
this->addRead(c, base, generalRegisterMask(c));
|
||||||
if (index) {
|
if (index) {
|
||||||
addRead(c, this, index, generalRegisterOrConstantMask(c));
|
this->addRead(c, index, generalRegisterOrConstantMask(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2906,14 +2415,14 @@ class MemoryEvent: public Event {
|
|||||||
low = static_cast<MemorySite*>(site->copyLow(c));
|
low = static_cast<MemorySite*>(site->copyLow(c));
|
||||||
|
|
||||||
result->nextWord->target = high;
|
result->nextWord->target = high;
|
||||||
addSite(c, result->nextWord, high);
|
result->nextWord->addSite(c, high);
|
||||||
moveIfConflict(c, result->nextWord, high);
|
moveIfConflict(c, result->nextWord, high);
|
||||||
} else {
|
} else {
|
||||||
low = site;
|
low = site;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->target = low;
|
result->target = low;
|
||||||
addSite(c, result, low);
|
result->addSite(c, low);
|
||||||
moveIfConflict(c, result, low);
|
moveIfConflict(c, result, low);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3052,15 +2561,15 @@ class BranchEvent: public Event {
|
|||||||
Event(c), type(type), size(size), first(first), second(second),
|
Event(c), type(type), size(size), first(first), second(second),
|
||||||
address(address)
|
address(address)
|
||||||
{
|
{
|
||||||
addReads(c, this, first, size, firstLowMask, firstHighMask);
|
this->addReads(c, first, size, firstLowMask, firstHighMask);
|
||||||
addReads(c, this, second, size, secondLowMask, secondHighMask);
|
this->addReads(c, second, size, secondLowMask, secondHighMask);
|
||||||
|
|
||||||
uint8_t typeMask;
|
uint8_t typeMask;
|
||||||
uint64_t registerMask;
|
uint64_t registerMask;
|
||||||
c->arch->planDestination(type, size, 0, 0, size, 0, 0, TargetBytesPerWord,
|
c->arch->planDestination(type, size, 0, 0, size, 0, 0, TargetBytesPerWord,
|
||||||
&typeMask, ®isterMask);
|
&typeMask, ®isterMask);
|
||||||
|
|
||||||
addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* name() {
|
virtual const char* name() {
|
||||||
@ -3183,7 +2692,7 @@ class JumpEvent: public Event {
|
|||||||
|
|
||||||
assert(c, not thunk);
|
assert(c, not thunk);
|
||||||
|
|
||||||
addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* name() {
|
virtual const char* name() {
|
||||||
@ -3233,8 +2742,8 @@ class BoundsCheckEvent: public Event {
|
|||||||
Event(c), object(object), lengthOffset(lengthOffset), index(index),
|
Event(c), object(object), lengthOffset(lengthOffset), index(index),
|
||||||
handler(handler)
|
handler(handler)
|
||||||
{
|
{
|
||||||
addRead(c, this, object, generalRegisterMask(c));
|
this->addRead(c, object, generalRegisterMask(c));
|
||||||
addRead(c, this, index, generalRegisterOrConstantMask(c));
|
this->addRead(c, index, generalRegisterOrConstantMask(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* name() {
|
virtual const char* name() {
|
||||||
@ -3254,7 +2763,7 @@ class BoundsCheckEvent: public Event {
|
|||||||
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
|
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
|
outOfBoundsPromise = compiler::codePromise(c, static_cast<Promise*>(0));
|
||||||
|
|
||||||
ConstantSite zero(resolved(c, 0));
|
ConstantSite zero(resolved(c, 0));
|
||||||
ConstantSite oob(outOfBoundsPromise);
|
ConstantSite oob(outOfBoundsPromise);
|
||||||
@ -3270,7 +2779,7 @@ class BoundsCheckEvent: public Event {
|
|||||||
lengthOffset, lir::NoRegister, 1);
|
lengthOffset, lir::NoRegister, 1);
|
||||||
length.acquired = true;
|
length.acquired = true;
|
||||||
|
|
||||||
CodePromise* nextPromise = codePromise(c, static_cast<Promise*>(0));
|
CodePromise* nextPromise = compiler::codePromise(c, static_cast<Promise*>(0));
|
||||||
|
|
||||||
freezeSource(c, TargetBytesPerWord, index);
|
freezeSource(c, TargetBytesPerWord, index);
|
||||||
|
|
||||||
@ -3322,7 +2831,7 @@ class FrameSiteEvent: public Event {
|
|||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
if (live(c, value)) {
|
if (live(c, value)) {
|
||||||
addSite(c, value, frameSite(c, index));
|
value->addSite(c, frameSite(c, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3382,7 +2891,7 @@ class BuddyEvent: public Event {
|
|||||||
BuddyEvent(Context* c, Value* original, Value* buddy):
|
BuddyEvent(Context* c, Value* original, Value* buddy):
|
||||||
Event(c), original(original), buddy(buddy)
|
Event(c), original(original), buddy(buddy)
|
||||||
{
|
{
|
||||||
addRead(c, this, original, SiteMask(~0, ~0, AnyFrameIndex), buddy);
|
this->addRead(c, original, SiteMask(~0, ~0, AnyFrameIndex), buddy);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char* name() {
|
virtual const char* name() {
|
||||||
@ -3655,7 +3164,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value dummy(0, 0, lir::ValueGeneral);
|
Value dummy(0, 0, lir::ValueGeneral);
|
||||||
addSite(c, &dummy, s);
|
dummy.addSite(c, s);
|
||||||
removeSite(c, &dummy, s);
|
removeSite(c, &dummy, s);
|
||||||
freeze(c, frozen, s, 0);
|
freeze(c, frozen, s, 0);
|
||||||
}
|
}
|
||||||
@ -3806,7 +3315,7 @@ setSites(Context* c, Value* v, Site* s)
|
|||||||
assert(c, live(c, v));
|
assert(c, live(c, v));
|
||||||
|
|
||||||
for (; s; s = s->next) {
|
for (; s; s = s->next) {
|
||||||
addSite(c, v, s->copy(c));
|
v->addSite(c, s->copy(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DebugControl) {
|
if (DebugControl) {
|
||||||
@ -3924,7 +3433,8 @@ setStubRead(Context* c, StubReadPair* p, Value* v)
|
|||||||
if (DebugReads) {
|
if (DebugReads) {
|
||||||
fprintf(stderr, "add stub read %p to %p\n", r, v);
|
fprintf(stderr, "add stub read %p to %p\n", r, v);
|
||||||
}
|
}
|
||||||
addRead(c, 0, v, r);
|
// TODO: this is rather icky looking... but despite how it looks, it will not cause an NPE
|
||||||
|
((Event*)0)->addRead(c, v, r);
|
||||||
|
|
||||||
p->value = v;
|
p->value = v;
|
||||||
p->read = r;
|
p->read = r;
|
||||||
@ -4157,7 +3667,8 @@ addForkElement(Context* c, Value* v, ForkState* state, unsigned index)
|
|||||||
if (DebugReads) {
|
if (DebugReads) {
|
||||||
fprintf(stderr, "add multi read %p to %p\n", r, v);
|
fprintf(stderr, "add multi read %p to %p\n", r, v);
|
||||||
}
|
}
|
||||||
addRead(c, 0, v, r);
|
// TODO: this is rather icky looking... but despite how it looks, it will not cause an NPE
|
||||||
|
((Event*)0)->addRead(c, v, r);
|
||||||
|
|
||||||
ForkElement* p = state->elements + index;
|
ForkElement* p = state->elements + index;
|
||||||
p->value = v;
|
p->value = v;
|
||||||
@ -4500,7 +4011,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Promise* machineIp() {
|
Promise* machineIp() {
|
||||||
return codePromise(&c, c.logicalCode[c.logicalIp]->lastEvent);
|
return c.logicalCode[c.logicalIp]->lastEvent->makeCodePromise(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void push(unsigned footprint UNUSED) {
|
virtual void push(unsigned footprint UNUSED) {
|
||||||
|
446
src/codegen/compiler/event.cpp
Normal file
446
src/codegen/compiler/event.cpp
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
/* Copyright (c) 2008-2012, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#include "target.h"
|
||||||
|
#include "util/runtime-array.h"
|
||||||
|
|
||||||
|
#include "codegen/compiler/context.h"
|
||||||
|
#include "codegen/compiler/event.h"
|
||||||
|
#include "codegen/compiler/stack.h"
|
||||||
|
#include "codegen/compiler/site.h"
|
||||||
|
#include "codegen/compiler/read.h"
|
||||||
|
#include "codegen/compiler/value.h"
|
||||||
|
#include "codegen/compiler/promise.h"
|
||||||
|
|
||||||
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
|
||||||
|
unsigned frameBase(Context* c);
|
||||||
|
unsigned totalFrameSize(Context* c);
|
||||||
|
int frameIndex(Context* c, int localIndex);
|
||||||
|
|
||||||
|
SiteMask generalRegisterMask(Context* c);
|
||||||
|
SiteMask generalRegisterOrConstantMask(Context* c);
|
||||||
|
|
||||||
|
CodePromise* codePromise(Context* c, Promise* offset);
|
||||||
|
|
||||||
|
void saveLocals(Context* c, Event* e);
|
||||||
|
|
||||||
|
void
|
||||||
|
apply(Context* c, lir::UnaryOperation op,
|
||||||
|
unsigned s1Size, Site* s1Low, Site* s1High);
|
||||||
|
|
||||||
|
void
|
||||||
|
apply(Context* c, lir::BinaryOperation op,
|
||||||
|
unsigned s1Size, Site* s1Low, Site* s1High,
|
||||||
|
unsigned s2Size, Site* s2Low, Site* s2High);
|
||||||
|
|
||||||
|
void
|
||||||
|
apply(Context* c, lir::TernaryOperation op,
|
||||||
|
unsigned s1Size, Site* s1Low, Site* s1High,
|
||||||
|
unsigned s2Size, Site* s2Low, Site* s2High,
|
||||||
|
unsigned s3Size, Site* s3Low, Site* s3High);
|
||||||
|
|
||||||
|
|
||||||
|
void append(Context* c, Event* e);
|
||||||
|
|
||||||
|
|
||||||
|
void clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads,
|
||||||
|
unsigned popIndex);
|
||||||
|
|
||||||
|
Read* live(Context* c UNUSED, Value* v);
|
||||||
|
|
||||||
|
Event::Event(Context* c):
|
||||||
|
next(0), stackBefore(c->stack), localsBefore(c->locals),
|
||||||
|
stackAfter(0), localsAfter(0), promises(0), reads(0),
|
||||||
|
junctionSites(0), snapshots(0), predecessors(0), successors(0),
|
||||||
|
visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
|
||||||
|
readCount(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void Event::addRead(Context* c, Value* v, Read* r) {
|
||||||
|
if (DebugReads) {
|
||||||
|
fprintf(stderr, "add read %p to %p last %p event %p (%s)\n",
|
||||||
|
r, v, v->lastRead, this, (this ? this->name() : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
r->value = v;
|
||||||
|
if (this) {
|
||||||
|
r->event = this;
|
||||||
|
r->eventNext = this->reads;
|
||||||
|
this->reads = r;
|
||||||
|
++ this->readCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->lastRead) {
|
||||||
|
// if (DebugReads) {
|
||||||
|
// fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
|
||||||
|
// }
|
||||||
|
|
||||||
|
v->lastRead->append(c, r);
|
||||||
|
} else {
|
||||||
|
v->reads = r;
|
||||||
|
}
|
||||||
|
v->lastRead = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::addRead(Context* c, Value* v, const SiteMask& mask, Value* successor) {
|
||||||
|
this->addRead(c, v, read(c, mask, successor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::addReads(Context* c, Value* v, unsigned size,
|
||||||
|
const SiteMask& lowMask, Value* lowSuccessor,
|
||||||
|
const SiteMask& highMask, Value* highSuccessor)
|
||||||
|
{
|
||||||
|
SingleRead* r = read(c, lowMask, lowSuccessor);
|
||||||
|
this->addRead(c, v, r);
|
||||||
|
if (size > vm::TargetBytesPerWord) {
|
||||||
|
r->high_ = v->nextWord;
|
||||||
|
this->addRead(c, v->nextWord, highMask, highSuccessor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::addReads(Context* c, Value* v, unsigned size,
|
||||||
|
const SiteMask& lowMask, const SiteMask& highMask)
|
||||||
|
{
|
||||||
|
this->addReads(c, v, size, lowMask, 0, highMask, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePromise* Event::makeCodePromise(Context* c) {
|
||||||
|
return this->promises = new(c->zone) CodePromise(c, this->promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CallEvent: public Event {
|
||||||
|
public:
|
||||||
|
CallEvent(Context* c, Value* address, unsigned flags,
|
||||||
|
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
||||||
|
Stack* argumentStack, unsigned argumentCount,
|
||||||
|
unsigned stackArgumentFootprint):
|
||||||
|
Event(c),
|
||||||
|
address(address),
|
||||||
|
traceHandler(traceHandler),
|
||||||
|
result(result),
|
||||||
|
returnAddressSurrogate(0),
|
||||||
|
framePointerSurrogate(0),
|
||||||
|
popIndex(0),
|
||||||
|
stackArgumentIndex(0),
|
||||||
|
flags(flags),
|
||||||
|
resultSize(resultSize),
|
||||||
|
stackArgumentFootprint(stackArgumentFootprint)
|
||||||
|
{
|
||||||
|
uint32_t registerMask = c->regFile->generalRegisters.mask;
|
||||||
|
|
||||||
|
if (argumentCount) {
|
||||||
|
assert(c, (flags & Compiler::TailJump) == 0);
|
||||||
|
assert(c, stackArgumentFootprint == 0);
|
||||||
|
|
||||||
|
Stack* s = argumentStack;
|
||||||
|
unsigned index = 0;
|
||||||
|
unsigned argumentIndex = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
unsigned footprint
|
||||||
|
= (argumentIndex + 1 < argumentCount
|
||||||
|
and s->value->nextWord == s->next->value)
|
||||||
|
? 2 : 1;
|
||||||
|
|
||||||
|
if (index % (c->arch->argumentAlignment() ? footprint : 1)) {
|
||||||
|
++ index;
|
||||||
|
}
|
||||||
|
|
||||||
|
SiteMask targetMask;
|
||||||
|
if (index + (c->arch->argumentRegisterAlignment() ? footprint : 1)
|
||||||
|
<= c->arch->argumentRegisterCount())
|
||||||
|
{
|
||||||
|
int number = c->arch->argumentRegister(index);
|
||||||
|
|
||||||
|
if (DebugReads) {
|
||||||
|
fprintf(stderr, "reg %d arg read %p\n", number, s->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
targetMask = SiteMask::fixedRegisterMask(number);
|
||||||
|
registerMask &= ~(1 << number);
|
||||||
|
} else {
|
||||||
|
if (index < c->arch->argumentRegisterCount()) {
|
||||||
|
index = c->arch->argumentRegisterCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned frameIndex = index - c->arch->argumentRegisterCount();
|
||||||
|
|
||||||
|
if (DebugReads) {
|
||||||
|
fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
targetMask = SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->addRead(c, s->value, targetMask);
|
||||||
|
|
||||||
|
++ index;
|
||||||
|
|
||||||
|
if ((++ argumentIndex) < argumentCount) {
|
||||||
|
s = s->next;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DebugReads) {
|
||||||
|
fprintf(stderr, "address read %p\n", address);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ bool thunk;
|
||||||
|
uint8_t typeMask;
|
||||||
|
uint64_t planRegisterMask;
|
||||||
|
c->arch->plan
|
||||||
|
((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, vm::TargetBytesPerWord,
|
||||||
|
&typeMask, &planRegisterMask, &thunk);
|
||||||
|
|
||||||
|
assert(c, not thunk);
|
||||||
|
|
||||||
|
this->addRead(c, address, SiteMask
|
||||||
|
(typeMask, registerMask & planRegisterMask, AnyFrameIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack* stack = stackBefore;
|
||||||
|
|
||||||
|
if (stackArgumentFootprint) {
|
||||||
|
RUNTIME_ARRAY(Value*, arguments, stackArgumentFootprint);
|
||||||
|
for (int i = stackArgumentFootprint - 1; i >= 0; --i) {
|
||||||
|
Value* v = stack->value;
|
||||||
|
stack = stack->next;
|
||||||
|
|
||||||
|
if ((vm::TargetBytesPerWord == 8
|
||||||
|
and (v == 0 or (i >= 1 and stack->value == 0)))
|
||||||
|
or (vm::TargetBytesPerWord == 4 and v->nextWord != v))
|
||||||
|
{
|
||||||
|
assert(c, vm::TargetBytesPerWord == 8 or v->nextWord == stack->value);
|
||||||
|
|
||||||
|
RUNTIME_ARRAY_BODY(arguments)[i--] = stack->value;
|
||||||
|
stack = stack->next;
|
||||||
|
}
|
||||||
|
RUNTIME_ARRAY_BODY(arguments)[i] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int returnAddressIndex;
|
||||||
|
int framePointerIndex;
|
||||||
|
int frameOffset;
|
||||||
|
|
||||||
|
if (TailCalls and (flags & Compiler::TailJump)) {
|
||||||
|
assert(c, argumentCount == 0);
|
||||||
|
|
||||||
|
int base = frameBase(c);
|
||||||
|
returnAddressIndex = base + c->arch->returnAddressOffset();
|
||||||
|
if (UseFramePointer) {
|
||||||
|
framePointerIndex = base + c->arch->framePointerOffset();
|
||||||
|
} else {
|
||||||
|
framePointerIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameOffset = totalFrameSize(c)
|
||||||
|
- c->arch->argumentFootprint(stackArgumentFootprint);
|
||||||
|
} else {
|
||||||
|
returnAddressIndex = -1;
|
||||||
|
framePointerIndex = -1;
|
||||||
|
frameOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < stackArgumentFootprint; ++i) {
|
||||||
|
Value* v = RUNTIME_ARRAY_BODY(arguments)[i];
|
||||||
|
if (v) {
|
||||||
|
int frameIndex = i + frameOffset;
|
||||||
|
|
||||||
|
if (DebugReads) {
|
||||||
|
fprintf(stderr, "stack arg read %p at %d of %d\n",
|
||||||
|
v, frameIndex, totalFrameSize(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<int>(frameIndex) == returnAddressIndex) {
|
||||||
|
returnAddressSurrogate = v;
|
||||||
|
this->addRead(c, v, generalRegisterMask(c));
|
||||||
|
} else if (static_cast<int>(frameIndex) == framePointerIndex) {
|
||||||
|
framePointerSurrogate = v;
|
||||||
|
this->addRead(c, v, generalRegisterMask(c));
|
||||||
|
} else {
|
||||||
|
this->addRead(c, v, SiteMask(1 << lir::MemoryOperand, 0, frameIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((not TailCalls) or (flags & Compiler::TailJump) == 0) {
|
||||||
|
stackArgumentIndex = c->localFootprint;
|
||||||
|
if (stackBefore) {
|
||||||
|
stackArgumentIndex += stackBefore->index + 1 - stackArgumentFootprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
popIndex
|
||||||
|
= c->alignedFrameSize
|
||||||
|
+ c->parameterFootprint
|
||||||
|
- c->arch->frameFooterSize()
|
||||||
|
- stackArgumentIndex;
|
||||||
|
|
||||||
|
assert(c, static_cast<int>(popIndex) >= 0);
|
||||||
|
|
||||||
|
while (stack) {
|
||||||
|
if (stack->value) {
|
||||||
|
unsigned logicalIndex = compiler::frameIndex
|
||||||
|
(c, stack->index + c->localFootprint);
|
||||||
|
|
||||||
|
if (DebugReads) {
|
||||||
|
fprintf(stderr, "stack save read %p at %d of %d\n",
|
||||||
|
stack->value, logicalIndex, totalFrameSize(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->addRead(c, stack->value, SiteMask
|
||||||
|
(1 << lir::MemoryOperand, 0, logicalIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
stack = stack->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveLocals(c, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* name() {
|
||||||
|
return "CallEvent";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void compile(Context* c) {
|
||||||
|
lir::UnaryOperation op;
|
||||||
|
|
||||||
|
if (TailCalls and (flags & Compiler::TailJump)) {
|
||||||
|
if (flags & Compiler::LongJumpOrCall) {
|
||||||
|
if (flags & Compiler::Aligned) {
|
||||||
|
op = lir::AlignedLongJump;
|
||||||
|
} else {
|
||||||
|
op = lir::LongJump;
|
||||||
|
}
|
||||||
|
} else if (flags & Compiler::Aligned) {
|
||||||
|
op = lir::AlignedJump;
|
||||||
|
} else {
|
||||||
|
op = lir::Jump;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(c, returnAddressSurrogate == 0
|
||||||
|
or returnAddressSurrogate->source->type(c) == lir::RegisterOperand);
|
||||||
|
assert(c, framePointerSurrogate == 0
|
||||||
|
or framePointerSurrogate->source->type(c) == lir::RegisterOperand);
|
||||||
|
|
||||||
|
int ras;
|
||||||
|
if (returnAddressSurrogate) {
|
||||||
|
returnAddressSurrogate->source->freeze(c, returnAddressSurrogate);
|
||||||
|
|
||||||
|
ras = static_cast<RegisterSite*>
|
||||||
|
(returnAddressSurrogate->source)->number;
|
||||||
|
} else {
|
||||||
|
ras = lir::NoRegister;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fps;
|
||||||
|
if (framePointerSurrogate) {
|
||||||
|
framePointerSurrogate->source->freeze(c, framePointerSurrogate);
|
||||||
|
|
||||||
|
fps = static_cast<RegisterSite*>
|
||||||
|
(framePointerSurrogate->source)->number;
|
||||||
|
} else {
|
||||||
|
fps = lir::NoRegister;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset
|
||||||
|
= static_cast<int>(c->arch->argumentFootprint(stackArgumentFootprint))
|
||||||
|
- static_cast<int>(c->arch->argumentFootprint(c->parameterFootprint));
|
||||||
|
|
||||||
|
c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps);
|
||||||
|
} else if (flags & Compiler::LongJumpOrCall) {
|
||||||
|
if (flags & Compiler::Aligned) {
|
||||||
|
op = lir::AlignedLongCall;
|
||||||
|
} else {
|
||||||
|
op = lir::LongCall;
|
||||||
|
}
|
||||||
|
} else if (flags & Compiler::Aligned) {
|
||||||
|
op = lir::AlignedCall;
|
||||||
|
} else {
|
||||||
|
op = lir::Call;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(c, op, vm::TargetBytesPerWord, address->source, address->source);
|
||||||
|
|
||||||
|
if (traceHandler) {
|
||||||
|
traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)),
|
||||||
|
stackArgumentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TailCalls) {
|
||||||
|
if (flags & Compiler::TailJump) {
|
||||||
|
if (returnAddressSurrogate) {
|
||||||
|
returnAddressSurrogate->source->thaw(c, returnAddressSurrogate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framePointerSurrogate) {
|
||||||
|
framePointerSurrogate->source->thaw(c, framePointerSurrogate);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned footprint = c->arch->argumentFootprint
|
||||||
|
(stackArgumentFootprint);
|
||||||
|
|
||||||
|
if (footprint > c->arch->stackAlignmentInWords()) {
|
||||||
|
c->assembler->adjustFrame
|
||||||
|
(footprint - c->arch->stackAlignmentInWords());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
||||||
|
|
||||||
|
if (resultSize and live(c, result)) {
|
||||||
|
result->addSite(c, registerSite(c, c->arch->returnLow()));
|
||||||
|
if (resultSize > vm::TargetBytesPerWord and live(c, result->nextWord)) {
|
||||||
|
result->nextWord->addSite(c, registerSite(c, c->arch->returnHigh()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool allExits() {
|
||||||
|
return (flags & Compiler::TailJump) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* address;
|
||||||
|
TraceHandler* traceHandler;
|
||||||
|
Value* result;
|
||||||
|
Value* returnAddressSurrogate;
|
||||||
|
Value* framePointerSurrogate;
|
||||||
|
unsigned popIndex;
|
||||||
|
unsigned stackArgumentIndex;
|
||||||
|
unsigned flags;
|
||||||
|
unsigned resultSize;
|
||||||
|
unsigned stackArgumentFootprint;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendCall(Context* c, Value* address, unsigned flags,
|
||||||
|
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
||||||
|
Stack* argumentStack, unsigned argumentCount,
|
||||||
|
unsigned stackArgumentFootprint)
|
||||||
|
{
|
||||||
|
append(c, new(c->zone)
|
||||||
|
CallEvent(c, address, flags, traceHandler, result,
|
||||||
|
resultSize, argumentStack, argumentCount,
|
||||||
|
stackArgumentFootprint));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace codegen
|
||||||
|
} // namespace avian
|
85
src/codegen/compiler/event.h
Normal file
85
src/codegen/compiler/event.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* Copyright (c) 2008-2012, 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. */
|
||||||
|
|
||||||
|
#ifndef AVIAN_CODEGEN_COMPILER_EVENT_H
|
||||||
|
#define AVIAN_CODEGEN_COMPILER_EVENT_H
|
||||||
|
|
||||||
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
class Context;
|
||||||
|
class CodePromise;
|
||||||
|
class Snapshot;
|
||||||
|
class Link;
|
||||||
|
class Site;
|
||||||
|
|
||||||
|
const bool DebugReads = false;
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
public:
|
||||||
|
Event(Context* c);
|
||||||
|
|
||||||
|
virtual const char* name() = 0;
|
||||||
|
|
||||||
|
virtual void compile(Context* c) = 0;
|
||||||
|
|
||||||
|
virtual bool isBranch() { return false; }
|
||||||
|
|
||||||
|
virtual bool allExits() { return false; }
|
||||||
|
|
||||||
|
virtual Local* locals() { return localsBefore; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void addRead(Context* c, Value* v, Read* r);
|
||||||
|
|
||||||
|
void addRead(Context* c, Value* v, const SiteMask& mask,
|
||||||
|
Value* successor = 0);
|
||||||
|
|
||||||
|
void addReads(Context* c, Value* v, unsigned size,
|
||||||
|
const SiteMask& lowMask, Value* lowSuccessor,
|
||||||
|
const SiteMask& highMask, Value* highSuccessor);
|
||||||
|
|
||||||
|
void addReads(Context* c, Value* v, unsigned size,
|
||||||
|
const SiteMask& lowMask, const SiteMask& highMask);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CodePromise* makeCodePromise(Context* c);
|
||||||
|
|
||||||
|
Event* next;
|
||||||
|
Stack* stackBefore;
|
||||||
|
Local* localsBefore;
|
||||||
|
Stack* stackAfter;
|
||||||
|
Local* localsAfter;
|
||||||
|
CodePromise* promises;
|
||||||
|
Read* reads;
|
||||||
|
Site** junctionSites;
|
||||||
|
Snapshot* snapshots;
|
||||||
|
Link* predecessors;
|
||||||
|
Link* successors;
|
||||||
|
Cell<Link>* visitLinks;
|
||||||
|
Block* block;
|
||||||
|
LogicalInstruction* logicalInstruction;
|
||||||
|
unsigned readCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendCall(Context* c, Value* address, unsigned flags,
|
||||||
|
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
||||||
|
Stack* argumentStack, unsigned argumentCount,
|
||||||
|
unsigned stackArgumentFootprint);
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace codegen
|
||||||
|
} // namespace avian
|
||||||
|
|
||||||
|
#endif // AVIAN_CODEGEN_COMPILER_EVENT_H
|
26
src/codegen/compiler/promise.cpp
Normal file
26
src/codegen/compiler/promise.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright (c) 2008-2012, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
#include "codegen/compiler/context.h"
|
||||||
|
#include "codegen/compiler/promise.h"
|
||||||
|
|
||||||
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
CodePromise*
|
||||||
|
codePromise(Context* c, Promise* offset)
|
||||||
|
{
|
||||||
|
return new (c->zone) CodePromise(c, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace codegen
|
||||||
|
} // namespace avian
|
52
src/codegen/compiler/promise.h
Normal file
52
src/codegen/compiler/promise.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Copyright (c) 2008-2012, 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. */
|
||||||
|
|
||||||
|
#ifndef AVIAN_CODEGEN_COMPILER_PROMISE_H
|
||||||
|
#define AVIAN_CODEGEN_COMPILER_PROMISE_H
|
||||||
|
|
||||||
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
|
||||||
|
class CodePromise: public Promise {
|
||||||
|
public:
|
||||||
|
CodePromise(Context* c, CodePromise* next):
|
||||||
|
c(c), offset(0), next(next)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
CodePromise(Context* c, Promise* offset):
|
||||||
|
c(c), offset(offset), next(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual int64_t value() {
|
||||||
|
if (resolved()) {
|
||||||
|
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool resolved() {
|
||||||
|
return c->machineCode != 0 and offset and offset->resolved();
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* c;
|
||||||
|
Promise* offset;
|
||||||
|
CodePromise* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodePromise* codePromise(Context* c, Promise* offset);
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace codegen
|
||||||
|
} // namespace avian
|
||||||
|
|
||||||
|
#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H
|
@ -178,6 +178,14 @@ Read* StubRead::next(Context*) {
|
|||||||
return next_;
|
return next_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
|
||||||
|
assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
|
||||||
|
|
||||||
|
return new(c->zone) SingleRead(mask, successor);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -111,6 +111,8 @@ class StubRead: public Read {
|
|||||||
bool valid_;
|
bool valid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
|
||||||
|
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
|
@ -109,6 +109,12 @@ void SiteIterator::remove(Context* c) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned Site::registerSize(Context*) {
|
||||||
|
return vm::TargetBytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Site* constantSite(Context* c, Promise* value) {
|
Site* constantSite(Context* c, Promise* value) {
|
||||||
return new(c->zone) ConstantSite(value);
|
return new(c->zone) ConstantSite(value);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,10 @@ class SiteMask {
|
|||||||
|
|
||||||
SiteMask intersectionWith(const SiteMask& b);
|
SiteMask intersectionWith(const SiteMask& b);
|
||||||
|
|
||||||
|
static SiteMask fixedRegisterMask(int number) {
|
||||||
|
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t typeMask;
|
uint8_t typeMask;
|
||||||
uint32_t registerMask;
|
uint32_t registerMask;
|
||||||
int frameIndex;
|
int frameIndex;
|
||||||
@ -83,7 +87,7 @@ class Site {
|
|||||||
|
|
||||||
virtual SiteMask nextWordMask(Context*, unsigned) = 0;
|
virtual SiteMask nextWordMask(Context*, unsigned) = 0;
|
||||||
|
|
||||||
virtual unsigned registerSize(Context*) { return vm::TargetBytesPerWord; }
|
virtual unsigned registerSize(Context*);
|
||||||
|
|
||||||
virtual unsigned registerMask(Context*) { return 0; }
|
virtual unsigned registerMask(Context*) { return 0; }
|
||||||
|
|
||||||
|
35
src/codegen/compiler/stack.h
Normal file
35
src/codegen/compiler/stack.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (c) 2008-2012, 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. */
|
||||||
|
|
||||||
|
#ifndef AVIAN_CODEGEN_COMPILER_STACK_H
|
||||||
|
#define AVIAN_CODEGEN_COMPILER_STACK_H
|
||||||
|
|
||||||
|
namespace avian {
|
||||||
|
namespace codegen {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
class Stack {
|
||||||
|
public:
|
||||||
|
Stack(unsigned index, Value* value, Stack* next):
|
||||||
|
index(index), value(value), next(next)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
unsigned index;
|
||||||
|
Value* value;
|
||||||
|
Stack* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace codegen
|
||||||
|
} // namespace avian
|
||||||
|
|
||||||
|
#endif // AVIAN_CODEGEN_COMPILER_STACK_H
|
@ -38,6 +38,18 @@ bool Value::isBuddyOf(Value* b) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Value::addSite(Context* c, Site* s) {
|
||||||
|
if (not this->findSite(s)) {
|
||||||
|
if (DebugSites) {
|
||||||
|
char buffer[256]; s->toString(c, buffer, 256);
|
||||||
|
fprintf(stderr, "add site %s to %p\n", buffer, this);
|
||||||
|
}
|
||||||
|
s->acquire(c, this);
|
||||||
|
s->next = this->sites;
|
||||||
|
this->sites = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace regalloc
|
} // namespace regalloc
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -25,6 +25,8 @@ class Site;
|
|||||||
const int AnyFrameIndex = -2;
|
const int AnyFrameIndex = -2;
|
||||||
const int NoFrameIndex = -1;
|
const int NoFrameIndex = -1;
|
||||||
|
|
||||||
|
const bool DebugSites = false;
|
||||||
|
|
||||||
class Value: public Compiler::Operand {
|
class Value: public Compiler::Operand {
|
||||||
public:
|
public:
|
||||||
Read* reads;
|
Read* reads;
|
||||||
@ -43,6 +45,8 @@ class Value: public Compiler::Operand {
|
|||||||
bool findSite(Site* site);
|
bool findSite(Site* site);
|
||||||
|
|
||||||
bool isBuddyOf(Value* b);
|
bool isBuddyOf(Value* b);
|
||||||
|
|
||||||
|
void addSite(Context* c, Site* s);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
Loading…
Reference in New Issue
Block a user