mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +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/value.cpp \
|
||||
$(src)/codegen/compiler/read.cpp \
|
||||
$(src)/codegen/compiler/event.cpp \
|
||||
$(src)/codegen/compiler/promise.cpp \
|
||||
$(src)/codegen/registers.cpp \
|
||||
$(src)/codegen/targets.cpp
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include "codegen/compiler/value.h"
|
||||
#include "codegen/compiler/site.h"
|
||||
#include "codegen/compiler/read.h"
|
||||
#include "codegen/compiler/event.h"
|
||||
#include "codegen/compiler/stack.h"
|
||||
#include "codegen/compiler/promise.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
@ -33,8 +36,6 @@ const bool DebugCompile = false;
|
||||
const bool DebugResources = false;
|
||||
const bool DebugFrame = false;
|
||||
const bool DebugControl = false;
|
||||
const bool DebugReads = false;
|
||||
const bool DebugSites = false;
|
||||
const bool DebugMoves = false;
|
||||
const bool DebugBuddies = false;
|
||||
|
||||
@ -45,7 +46,6 @@ const unsigned StealRegisterReserveCount = 2;
|
||||
const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4);
|
||||
|
||||
class Stack;
|
||||
class Event;
|
||||
class PushEvent;
|
||||
class Read;
|
||||
class MultiRead;
|
||||
@ -73,17 +73,6 @@ class Local {
|
||||
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 {
|
||||
public:
|
||||
Value* value;
|
||||
@ -166,33 +155,6 @@ class PoolPromise: public Promise {
|
||||
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
|
||||
machineOffset(Context* c, int logicalIp)
|
||||
{
|
||||
@ -298,43 +260,6 @@ countSuccessors(Link* link)
|
||||
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
|
||||
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
|
||||
removeSite(Context* c, Value* v, Site* s)
|
||||
{
|
||||
@ -598,7 +509,7 @@ deadWord(Context* c, Value* v)
|
||||
|
||||
if (s->registerSize(c) > TargetBytesPerWord) {
|
||||
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();
|
||||
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
|
||||
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);
|
||||
|
||||
addSite(c, value, dst);
|
||||
value->addSite(c, dst);
|
||||
|
||||
src->thaw(c, value);
|
||||
|
||||
@ -934,7 +837,7 @@ maybeMove(Context* c, Read* read, bool intersectRead, bool includeNextWord,
|
||||
|
||||
Site* tmp = pickTargetSite(c, &tmpRead, true);
|
||||
|
||||
addSite(c, value, tmp);
|
||||
value->addSite(c, tmp);
|
||||
|
||||
move(c, value, src, tmp);
|
||||
|
||||
@ -1027,13 +930,6 @@ generalRegisterOrConstantMask(Context* c)
|
||||
c->regFile->generalRegisters.mask, NoFrameIndex);
|
||||
}
|
||||
|
||||
SiteMask
|
||||
fixedRegisterMask(int number)
|
||||
{
|
||||
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
||||
}
|
||||
|
||||
|
||||
MultiRead*
|
||||
multiRead(Context* c)
|
||||
{
|
||||
@ -1093,7 +989,7 @@ pickSiteOrGrow(Context* c, Value* v, Site* s, unsigned index)
|
||||
}
|
||||
|
||||
n = s->makeNextWord(c, index);
|
||||
addSite(c, v, n);
|
||||
v->addSite(c, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -1260,61 +1156,6 @@ apply(Context* c, lir::TernaryOperation op,
|
||||
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
|
||||
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
|
||||
append(Context* c, Event* e);
|
||||
|
||||
@ -1379,333 +1208,12 @@ saveLocals(Context* c, Event* e)
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
unreachable(Event* event)
|
||||
{
|
||||
@ -1721,8 +1229,9 @@ class ReturnEvent: public Event {
|
||||
Event(c), value(value)
|
||||
{
|
||||
if (value) {
|
||||
addReads(c, this, value, size, fixedRegisterMask(c->arch->returnLow()),
|
||||
fixedRegisterMask(c->arch->returnHigh()));
|
||||
this->addReads(c, value, size,
|
||||
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);
|
||||
|
||||
addSite(c, dst, target);
|
||||
dst->addSite(c, target);
|
||||
|
||||
src->source->thaw(c, src);
|
||||
|
||||
@ -1835,7 +1344,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
|
||||
|
||||
src->source->freeze(c, src);
|
||||
|
||||
addSite(c, dst, tmpTarget);
|
||||
dst->addSite(c, tmpTarget);
|
||||
|
||||
tmpTarget->freeze(c, dst);
|
||||
|
||||
@ -1861,7 +1370,7 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
|
||||
srcb, dstb, src, dst);
|
||||
}
|
||||
|
||||
addSite(c, dst, target);
|
||||
dst->addSite(c, target);
|
||||
|
||||
tmpTarget->freeze(c, dst);
|
||||
|
||||
@ -1968,8 +1477,8 @@ split(Context* c, Value* v)
|
||||
Site* s = it.next();
|
||||
removeSite(c, v, s);
|
||||
|
||||
addSite(c, v, s->copyLow(c));
|
||||
addSite(c, v->nextWord, s->copyHigh(c));
|
||||
v->addSite(c, s->copyLow(c));
|
||||
v->nextWord->addSite(c, s->copyHigh(c));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2001,7 +1510,7 @@ class MoveEvent: public Event {
|
||||
maybeSplit(c, src);
|
||||
}
|
||||
|
||||
addReads(c, this, src, srcSelectSize, srcLowMask, noop ? dst : 0,
|
||||
this->addReads(c, src, srcSelectSize, srcLowMask, noop ? dst : 0,
|
||||
srcHighMask,
|
||||
noop and dstSize > TargetBytesPerWord ? dst->nextWord : 0);
|
||||
}
|
||||
@ -2081,7 +1590,7 @@ class MoveEvent: public Event {
|
||||
|
||||
src->source->freeze(c, src);
|
||||
|
||||
addSite(c, dst, low);
|
||||
dst->addSite(c, low);
|
||||
|
||||
low->freeze(c, dst);
|
||||
|
||||
@ -2105,7 +1614,7 @@ class MoveEvent: public Event {
|
||||
|
||||
low->freeze(c, dst);
|
||||
|
||||
addSite(c, dst->nextWord, high);
|
||||
dst->nextWord->addSite(c, high);
|
||||
|
||||
high->freeze(c, dst->nextWord);
|
||||
|
||||
@ -2203,7 +1712,7 @@ getTarget(Context* c, Value* value, Value* result, const SiteMask& resultMask)
|
||||
r.successor_ = result;
|
||||
s = pickTargetSite(c, &r, true);
|
||||
v = result;
|
||||
addSite(c, result, s);
|
||||
result->addSite(c, s);
|
||||
}
|
||||
|
||||
removeSite(c, v, s);
|
||||
@ -2245,7 +1754,7 @@ class CombineEvent: public Event {
|
||||
secondSize(secondSize), second(second), resultSize(resultSize),
|
||||
result(result)
|
||||
{
|
||||
addReads(c, this, first, firstSize, firstLowMask, firstHighMask);
|
||||
this->addReads(c, first, firstSize, firstLowMask, firstHighMask);
|
||||
|
||||
if (resultSize > TargetBytesPerWord) {
|
||||
grow(c, result);
|
||||
@ -2253,7 +1762,7 @@ class CombineEvent: public Event {
|
||||
|
||||
bool condensed = c->arch->alwaysCondensed(type);
|
||||
|
||||
addReads(c, this, second, secondSize,
|
||||
this->addReads(c, second, secondSize,
|
||||
secondLowMask, condensed ? result : 0,
|
||||
secondHighMask, condensed ? result->nextWord : 0);
|
||||
}
|
||||
@ -2325,9 +1834,9 @@ class CombineEvent: public Event {
|
||||
}
|
||||
|
||||
if (live(c, result)) {
|
||||
addSite(c, result, low);
|
||||
result->addSite(c, low);
|
||||
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);
|
||||
}
|
||||
|
||||
addReads(c, this, value, valueSize, valueLowMask, condensed ? result : 0,
|
||||
this->addReads(c, value, valueSize, valueLowMask, condensed ? result : 0,
|
||||
valueHighMask, condensed ? result->nextWord : 0);
|
||||
}
|
||||
|
||||
@ -2762,9 +2271,9 @@ class TranslateEvent: public Event {
|
||||
}
|
||||
|
||||
if (live(c, result)) {
|
||||
addSite(c, result, low);
|
||||
result->addSite(c, low);
|
||||
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),
|
||||
scale(scale), result(result)
|
||||
{
|
||||
addRead(c, this, base, generalRegisterMask(c));
|
||||
this->addRead(c, base, generalRegisterMask(c));
|
||||
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));
|
||||
|
||||
result->nextWord->target = high;
|
||||
addSite(c, result->nextWord, high);
|
||||
result->nextWord->addSite(c, high);
|
||||
moveIfConflict(c, result->nextWord, high);
|
||||
} else {
|
||||
low = site;
|
||||
}
|
||||
|
||||
result->target = low;
|
||||
addSite(c, result, low);
|
||||
result->addSite(c, low);
|
||||
moveIfConflict(c, result, low);
|
||||
}
|
||||
|
||||
@ -3052,15 +2561,15 @@ class BranchEvent: public Event {
|
||||
Event(c), type(type), size(size), first(first), second(second),
|
||||
address(address)
|
||||
{
|
||||
addReads(c, this, first, size, firstLowMask, firstHighMask);
|
||||
addReads(c, this, second, size, secondLowMask, secondHighMask);
|
||||
this->addReads(c, first, size, firstLowMask, firstHighMask);
|
||||
this->addReads(c, second, size, secondLowMask, secondHighMask);
|
||||
|
||||
uint8_t typeMask;
|
||||
uint64_t registerMask;
|
||||
c->arch->planDestination(type, size, 0, 0, size, 0, 0, TargetBytesPerWord,
|
||||
&typeMask, ®isterMask);
|
||||
|
||||
addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
@ -3183,7 +2692,7 @@ class JumpEvent: public Event {
|
||||
|
||||
assert(c, not thunk);
|
||||
|
||||
addRead(c, this, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
@ -3233,8 +2742,8 @@ class BoundsCheckEvent: public Event {
|
||||
Event(c), object(object), lengthOffset(lengthOffset), index(index),
|
||||
handler(handler)
|
||||
{
|
||||
addRead(c, this, object, generalRegisterMask(c));
|
||||
addRead(c, this, index, generalRegisterOrConstantMask(c));
|
||||
this->addRead(c, object, generalRegisterMask(c));
|
||||
this->addRead(c, index, generalRegisterOrConstantMask(c));
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
@ -3254,7 +2763,7 @@ class BoundsCheckEvent: public Event {
|
||||
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
|
||||
}
|
||||
} else {
|
||||
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
|
||||
outOfBoundsPromise = compiler::codePromise(c, static_cast<Promise*>(0));
|
||||
|
||||
ConstantSite zero(resolved(c, 0));
|
||||
ConstantSite oob(outOfBoundsPromise);
|
||||
@ -3270,7 +2779,7 @@ class BoundsCheckEvent: public Event {
|
||||
lengthOffset, lir::NoRegister, 1);
|
||||
length.acquired = true;
|
||||
|
||||
CodePromise* nextPromise = codePromise(c, static_cast<Promise*>(0));
|
||||
CodePromise* nextPromise = compiler::codePromise(c, static_cast<Promise*>(0));
|
||||
|
||||
freezeSource(c, TargetBytesPerWord, index);
|
||||
|
||||
@ -3322,7 +2831,7 @@ class FrameSiteEvent: public Event {
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
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):
|
||||
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() {
|
||||
@ -3655,7 +3164,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen,
|
||||
}
|
||||
|
||||
Value dummy(0, 0, lir::ValueGeneral);
|
||||
addSite(c, &dummy, s);
|
||||
dummy.addSite(c, s);
|
||||
removeSite(c, &dummy, s);
|
||||
freeze(c, frozen, s, 0);
|
||||
}
|
||||
@ -3806,7 +3315,7 @@ setSites(Context* c, Value* v, Site* s)
|
||||
assert(c, live(c, v));
|
||||
|
||||
for (; s; s = s->next) {
|
||||
addSite(c, v, s->copy(c));
|
||||
v->addSite(c, s->copy(c));
|
||||
}
|
||||
|
||||
if (DebugControl) {
|
||||
@ -3924,7 +3433,8 @@ setStubRead(Context* c, StubReadPair* p, Value* v)
|
||||
if (DebugReads) {
|
||||
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->read = r;
|
||||
@ -4157,7 +3667,8 @@ addForkElement(Context* c, Value* v, ForkState* state, unsigned index)
|
||||
if (DebugReads) {
|
||||
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;
|
||||
p->value = v;
|
||||
@ -4500,7 +4011,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
Promise* machineIp() {
|
||||
return codePromise(&c, c.logicalCode[c.logicalIp]->lastEvent);
|
||||
return c.logicalCode[c.logicalIp]->lastEvent->makeCodePromise(&c);
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 codegen
|
||||
} // namespace avian
|
||||
|
@ -111,6 +111,8 @@ class StubRead: public Read {
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
|
||||
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
|
@ -109,6 +109,12 @@ void SiteIterator::remove(Context* c) {
|
||||
|
||||
|
||||
|
||||
unsigned Site::registerSize(Context*) {
|
||||
return vm::TargetBytesPerWord;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Site* constantSite(Context* c, Promise* value) {
|
||||
return new(c->zone) ConstantSite(value);
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ class SiteMask {
|
||||
|
||||
SiteMask intersectionWith(const SiteMask& b);
|
||||
|
||||
static SiteMask fixedRegisterMask(int number) {
|
||||
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
|
||||
}
|
||||
|
||||
uint8_t typeMask;
|
||||
uint32_t registerMask;
|
||||
int frameIndex;
|
||||
@ -83,7 +87,7 @@ class Site {
|
||||
|
||||
virtual SiteMask nextWordMask(Context*, unsigned) = 0;
|
||||
|
||||
virtual unsigned registerSize(Context*) { return vm::TargetBytesPerWord; }
|
||||
virtual unsigned registerSize(Context*);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 codegen
|
||||
} // namespace avian
|
||||
|
@ -25,6 +25,8 @@ class Site;
|
||||
const int AnyFrameIndex = -2;
|
||||
const int NoFrameIndex = -1;
|
||||
|
||||
const bool DebugSites = false;
|
||||
|
||||
class Value: public Compiler::Operand {
|
||||
public:
|
||||
Read* reads;
|
||||
@ -43,6 +45,8 @@ class Value: public Compiler::Operand {
|
||||
bool findSite(Site* site);
|
||||
|
||||
bool isBuddyOf(Value* b);
|
||||
|
||||
void addSite(Context* c, Site* s);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
|
Loading…
Reference in New Issue
Block a user