mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
move BranchEvent out of compiler.cpp
This commit is contained in:
parent
18e6f28ff4
commit
65b7cf047c
@ -1586,243 +1586,6 @@ register_(Context* c, int number)
|
||||
return value(c, type, s, s);
|
||||
}
|
||||
|
||||
double
|
||||
asFloat(unsigned size, int64_t v)
|
||||
{
|
||||
if (size == 4) {
|
||||
return bitsToFloat(v);
|
||||
} else {
|
||||
return bitsToDouble(v);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
unordered(double a, double b)
|
||||
{
|
||||
return not (a >= b or a < b);
|
||||
}
|
||||
|
||||
bool
|
||||
shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b,
|
||||
int64_t a)
|
||||
{
|
||||
switch (type) {
|
||||
case lir::JumpIfEqual:
|
||||
return a == b;
|
||||
|
||||
case lir::JumpIfNotEqual:
|
||||
return a != b;
|
||||
|
||||
case lir::JumpIfLess:
|
||||
return a < b;
|
||||
|
||||
case lir::JumpIfGreater:
|
||||
return a > b;
|
||||
|
||||
case lir::JumpIfLessOrEqual:
|
||||
return a <= b;
|
||||
|
||||
case lir::JumpIfGreaterOrEqual:
|
||||
return a >= b;
|
||||
|
||||
case lir::JumpIfFloatEqual:
|
||||
return asFloat(size, a) == asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatNotEqual:
|
||||
return asFloat(size, a) != asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatLess:
|
||||
return asFloat(size, a) < asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatGreater:
|
||||
return asFloat(size, a) > asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatLessOrEqual:
|
||||
return asFloat(size, a) <= asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatGreaterOrEqual:
|
||||
return asFloat(size, a) >= asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatLessOrUnordered:
|
||||
return asFloat(size, a) < asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
case lir::JumpIfFloatGreaterOrUnordered:
|
||||
return asFloat(size, a) > asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
case lir::JumpIfFloatLessOrEqualOrUnordered:
|
||||
return asFloat(size, a) <= asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
|
||||
return asFloat(size, a) >= asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
default:
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
lir::TernaryOperation
|
||||
thunkBranch(Context* c, lir::TernaryOperation type)
|
||||
{
|
||||
switch (type) {
|
||||
case lir::JumpIfFloatEqual:
|
||||
return lir::JumpIfEqual;
|
||||
|
||||
case lir::JumpIfFloatNotEqual:
|
||||
return lir::JumpIfNotEqual;
|
||||
|
||||
case lir::JumpIfFloatLess:
|
||||
case lir::JumpIfFloatLessOrUnordered:
|
||||
return lir::JumpIfLess;
|
||||
|
||||
case lir::JumpIfFloatGreater:
|
||||
case lir::JumpIfFloatGreaterOrUnordered:
|
||||
return lir::JumpIfGreater;
|
||||
|
||||
case lir::JumpIfFloatLessOrEqual:
|
||||
case lir::JumpIfFloatLessOrEqualOrUnordered:
|
||||
return lir::JumpIfLessOrEqual;
|
||||
|
||||
case lir::JumpIfFloatGreaterOrEqual:
|
||||
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
|
||||
return lir::JumpIfGreaterOrEqual;
|
||||
|
||||
default:
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
class BranchEvent: public Event {
|
||||
public:
|
||||
BranchEvent(Context* c, lir::TernaryOperation type, unsigned size,
|
||||
Value* first, Value* second, Value* address,
|
||||
const SiteMask& firstLowMask,
|
||||
const SiteMask& firstHighMask,
|
||||
const SiteMask& secondLowMask,
|
||||
const SiteMask& secondHighMask):
|
||||
Event(c), type(type), size(size), first(first), second(second),
|
||||
address(address)
|
||||
{
|
||||
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);
|
||||
|
||||
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
return "BranchEvent";
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
ConstantSite* firstConstant = findConstantSite(c, first);
|
||||
ConstantSite* secondConstant = findConstantSite(c, second);
|
||||
|
||||
if (not this->isUnreachable()) {
|
||||
if (firstConstant
|
||||
and secondConstant
|
||||
and firstConstant->value->resolved()
|
||||
and secondConstant->value->resolved())
|
||||
{
|
||||
int64_t firstValue = firstConstant->value->value();
|
||||
int64_t secondValue = secondConstant->value->value();
|
||||
|
||||
if (size > TargetBytesPerWord) {
|
||||
firstValue |= findConstantSite
|
||||
(c, first->nextWord)->value->value() << 32;
|
||||
secondValue |= findConstantSite
|
||||
(c, second->nextWord)->value->value() << 32;
|
||||
}
|
||||
|
||||
if (shouldJump(c, type, size, firstValue, secondValue)) {
|
||||
apply(c, lir::Jump, TargetBytesPerWord, address->source, address->source);
|
||||
}
|
||||
} else {
|
||||
freezeSource(c, size, first);
|
||||
freezeSource(c, size, second);
|
||||
freezeSource(c, TargetBytesPerWord, address);
|
||||
|
||||
apply(c, type, size, first->source, first->nextWord->source,
|
||||
size, second->source, second->nextWord->source,
|
||||
TargetBytesPerWord, address->source, address->source);
|
||||
|
||||
thawSource(c, TargetBytesPerWord, address);
|
||||
thawSource(c, size, second);
|
||||
thawSource(c, size, first);
|
||||
}
|
||||
}
|
||||
|
||||
for (Read* r = reads; r; r = r->eventNext) {
|
||||
popRead(c, this, r->value);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isBranch() { return true; }
|
||||
|
||||
lir::TernaryOperation type;
|
||||
unsigned size;
|
||||
Value* first;
|
||||
Value* second;
|
||||
Value* address;
|
||||
};
|
||||
|
||||
void
|
||||
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
|
||||
Value* second, Value* address)
|
||||
{
|
||||
bool thunk;
|
||||
uint8_t firstTypeMask;
|
||||
uint64_t firstRegisterMask;
|
||||
uint8_t secondTypeMask;
|
||||
uint64_t secondRegisterMask;
|
||||
|
||||
c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask,
|
||||
size, &secondTypeMask, &secondRegisterMask,
|
||||
TargetBytesPerWord, &thunk);
|
||||
|
||||
if (thunk) {
|
||||
Stack* oldStack = c->stack;
|
||||
|
||||
bool threadParameter;
|
||||
intptr_t handler = c->client->getThunk
|
||||
(type, size, size, &threadParameter);
|
||||
|
||||
assert(c, not threadParameter);
|
||||
|
||||
compiler::push(c, ceilingDivide(size, TargetBytesPerWord), second);
|
||||
compiler::push(c, ceilingDivide(size, TargetBytesPerWord), first);
|
||||
|
||||
Stack* argumentStack = c->stack;
|
||||
c->stack = oldStack;
|
||||
|
||||
Value* result = value(c, lir::ValueGeneral);
|
||||
appendCall
|
||||
(c, value
|
||||
(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4,
|
||||
argumentStack, ceilingDivide(size, TargetBytesPerWord) * 2, 0);
|
||||
|
||||
appendBranch(c, thunkBranch(c, type), 4, value
|
||||
(c, lir::ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
|
||||
result, address);
|
||||
} else {
|
||||
append
|
||||
(c, new(c->zone)
|
||||
BranchEvent
|
||||
(c, type, size, first, second, address,
|
||||
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
||||
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
|
||||
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
|
||||
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
|
||||
}
|
||||
}
|
||||
|
||||
class JumpEvent: public Event {
|
||||
public:
|
||||
JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit,
|
||||
|
@ -1174,6 +1174,241 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
|
||||
MemoryEvent(c, base, displacement, index, scale, result));
|
||||
}
|
||||
|
||||
double asFloat(unsigned size, int64_t v) {
|
||||
if (size == 4) {
|
||||
return vm::bitsToFloat(v);
|
||||
} else {
|
||||
return vm::bitsToDouble(v);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
unordered(double a, double b)
|
||||
{
|
||||
return not (a >= b or a < b);
|
||||
}
|
||||
|
||||
bool
|
||||
shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b,
|
||||
int64_t a)
|
||||
{
|
||||
switch (type) {
|
||||
case lir::JumpIfEqual:
|
||||
return a == b;
|
||||
|
||||
case lir::JumpIfNotEqual:
|
||||
return a != b;
|
||||
|
||||
case lir::JumpIfLess:
|
||||
return a < b;
|
||||
|
||||
case lir::JumpIfGreater:
|
||||
return a > b;
|
||||
|
||||
case lir::JumpIfLessOrEqual:
|
||||
return a <= b;
|
||||
|
||||
case lir::JumpIfGreaterOrEqual:
|
||||
return a >= b;
|
||||
|
||||
case lir::JumpIfFloatEqual:
|
||||
return asFloat(size, a) == asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatNotEqual:
|
||||
return asFloat(size, a) != asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatLess:
|
||||
return asFloat(size, a) < asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatGreater:
|
||||
return asFloat(size, a) > asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatLessOrEqual:
|
||||
return asFloat(size, a) <= asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatGreaterOrEqual:
|
||||
return asFloat(size, a) >= asFloat(size, b);
|
||||
|
||||
case lir::JumpIfFloatLessOrUnordered:
|
||||
return asFloat(size, a) < asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
case lir::JumpIfFloatGreaterOrUnordered:
|
||||
return asFloat(size, a) > asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
case lir::JumpIfFloatLessOrEqualOrUnordered:
|
||||
return asFloat(size, a) <= asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
|
||||
return asFloat(size, a) >= asFloat(size, b)
|
||||
or unordered(asFloat(size, a), asFloat(size, b));
|
||||
|
||||
default:
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
lir::TernaryOperation
|
||||
thunkBranch(Context* c, lir::TernaryOperation type)
|
||||
{
|
||||
switch (type) {
|
||||
case lir::JumpIfFloatEqual:
|
||||
return lir::JumpIfEqual;
|
||||
|
||||
case lir::JumpIfFloatNotEqual:
|
||||
return lir::JumpIfNotEqual;
|
||||
|
||||
case lir::JumpIfFloatLess:
|
||||
case lir::JumpIfFloatLessOrUnordered:
|
||||
return lir::JumpIfLess;
|
||||
|
||||
case lir::JumpIfFloatGreater:
|
||||
case lir::JumpIfFloatGreaterOrUnordered:
|
||||
return lir::JumpIfGreater;
|
||||
|
||||
case lir::JumpIfFloatLessOrEqual:
|
||||
case lir::JumpIfFloatLessOrEqualOrUnordered:
|
||||
return lir::JumpIfLessOrEqual;
|
||||
|
||||
case lir::JumpIfFloatGreaterOrEqual:
|
||||
case lir::JumpIfFloatGreaterOrEqualOrUnordered:
|
||||
return lir::JumpIfGreaterOrEqual;
|
||||
|
||||
default:
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
class BranchEvent: public Event {
|
||||
public:
|
||||
BranchEvent(Context* c, lir::TernaryOperation type, unsigned size,
|
||||
Value* first, Value* second, Value* address,
|
||||
const SiteMask& firstLowMask,
|
||||
const SiteMask& firstHighMask,
|
||||
const SiteMask& secondLowMask,
|
||||
const SiteMask& secondHighMask):
|
||||
Event(c), type(type), size(size), first(first), second(second),
|
||||
address(address)
|
||||
{
|
||||
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, vm::TargetBytesPerWord,
|
||||
&typeMask, ®isterMask);
|
||||
|
||||
this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex));
|
||||
}
|
||||
|
||||
virtual const char* name() {
|
||||
return "BranchEvent";
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
ConstantSite* firstConstant = findConstantSite(c, first);
|
||||
ConstantSite* secondConstant = findConstantSite(c, second);
|
||||
|
||||
if (not this->isUnreachable()) {
|
||||
if (firstConstant
|
||||
and secondConstant
|
||||
and firstConstant->value->resolved()
|
||||
and secondConstant->value->resolved())
|
||||
{
|
||||
int64_t firstValue = firstConstant->value->value();
|
||||
int64_t secondValue = secondConstant->value->value();
|
||||
|
||||
if (size > vm::TargetBytesPerWord) {
|
||||
firstValue |= findConstantSite
|
||||
(c, first->nextWord)->value->value() << 32;
|
||||
secondValue |= findConstantSite
|
||||
(c, second->nextWord)->value->value() << 32;
|
||||
}
|
||||
|
||||
if (shouldJump(c, type, size, firstValue, secondValue)) {
|
||||
apply(c, lir::Jump, vm::TargetBytesPerWord, address->source, address->source);
|
||||
}
|
||||
} else {
|
||||
freezeSource(c, size, first);
|
||||
freezeSource(c, size, second);
|
||||
freezeSource(c, vm::TargetBytesPerWord, address);
|
||||
|
||||
apply(c, type, size, first->source, first->nextWord->source,
|
||||
size, second->source, second->nextWord->source,
|
||||
vm::TargetBytesPerWord, address->source, address->source);
|
||||
|
||||
thawSource(c, vm::TargetBytesPerWord, address);
|
||||
thawSource(c, size, second);
|
||||
thawSource(c, size, first);
|
||||
}
|
||||
}
|
||||
|
||||
for (Read* r = reads; r; r = r->eventNext) {
|
||||
popRead(c, this, r->value);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isBranch() { return true; }
|
||||
|
||||
lir::TernaryOperation type;
|
||||
unsigned size;
|
||||
Value* first;
|
||||
Value* second;
|
||||
Value* address;
|
||||
};
|
||||
|
||||
void
|
||||
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
|
||||
Value* second, Value* address)
|
||||
{
|
||||
bool thunk;
|
||||
uint8_t firstTypeMask;
|
||||
uint64_t firstRegisterMask;
|
||||
uint8_t secondTypeMask;
|
||||
uint64_t secondRegisterMask;
|
||||
|
||||
c->arch->planSource(type, size, &firstTypeMask, &firstRegisterMask,
|
||||
size, &secondTypeMask, &secondRegisterMask,
|
||||
vm::TargetBytesPerWord, &thunk);
|
||||
|
||||
if (thunk) {
|
||||
Stack* oldStack = c->stack;
|
||||
|
||||
bool threadParameter;
|
||||
intptr_t handler = c->client->getThunk
|
||||
(type, size, size, &threadParameter);
|
||||
|
||||
assert(c, not threadParameter);
|
||||
|
||||
compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), second);
|
||||
compiler::push(c, vm::ceilingDivide(size, vm::TargetBytesPerWord), first);
|
||||
|
||||
Stack* argumentStack = c->stack;
|
||||
c->stack = oldStack;
|
||||
|
||||
Value* result = value(c, lir::ValueGeneral);
|
||||
appendCall
|
||||
(c, value
|
||||
(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4,
|
||||
argumentStack, vm::ceilingDivide(size, vm::TargetBytesPerWord) * 2, 0);
|
||||
|
||||
appendBranch(c, thunkBranch(c, type), 4, value
|
||||
(c, lir::ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
|
||||
result, address);
|
||||
} else {
|
||||
append
|
||||
(c, new(c->zone)
|
||||
BranchEvent
|
||||
(c, type, size, first, second, address,
|
||||
SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
||||
SiteMask(firstTypeMask, firstRegisterMask >> 32, AnyFrameIndex),
|
||||
SiteMask(secondTypeMask, secondRegisterMask, AnyFrameIndex),
|
||||
SiteMask(secondTypeMask, secondRegisterMask >> 32, AnyFrameIndex)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
@ -139,6 +139,10 @@ void
|
||||
appendMemory(Context* c, Value* base, int displacement, Value* index,
|
||||
unsigned scale, Value* result);
|
||||
|
||||
void
|
||||
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
|
||||
Value* second, Value* address);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace codegen
|
||||
} // namespace avian
|
||||
|
Loading…
Reference in New Issue
Block a user