mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
handle constant array lengths and indexes properly; various bugfixes
This commit is contained in:
parent
7cd79736c2
commit
406f173982
281
src/compile.cpp
281
src/compile.cpp
@ -948,6 +948,8 @@ class Frame {
|
||||
(context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord)))
|
||||
TraceElement(context, target, virtualCall, context->traceLog);
|
||||
|
||||
fprintf(stderr, "make element %p at ip %d\n", e, ip);
|
||||
|
||||
context->eventLog.append(TraceEvent);
|
||||
context->eventLog.appendAddress(e);
|
||||
|
||||
@ -1573,6 +1575,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
frame->startLogicalIp(ip);
|
||||
|
||||
if (ip == 0) {
|
||||
handleEntrance(t, frame);
|
||||
}
|
||||
|
||||
// fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map));
|
||||
|
||||
unsigned instruction = codeBody(t, code, ip++);
|
||||
@ -1591,17 +1597,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
if (CheckArrayBounds) {
|
||||
Compiler::Operand* load = c->label();
|
||||
Compiler::Operand* throw_ = c->label();
|
||||
Compiler::Operand* throw_ = 0;
|
||||
|
||||
c->cmp(4, c->constant(0), index);
|
||||
c->jl(throw_);
|
||||
if (c->isConstant(index)) {
|
||||
expect(t, c->constantValue(index) >= 0);
|
||||
} else {
|
||||
throw_ = c->label();
|
||||
c->cmp(4, c->constant(0), index);
|
||||
c->jl(throw_);
|
||||
}
|
||||
|
||||
c->cmp(BytesPerWord,
|
||||
c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)),
|
||||
index);
|
||||
c->jl(load);
|
||||
index,
|
||||
c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)));
|
||||
c->jge(load);
|
||||
|
||||
c->mark(throw_);
|
||||
if (not c->isConstant(index)) {
|
||||
c->mark(throw_);
|
||||
}
|
||||
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
|
||||
@ -1614,34 +1627,67 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->mark(load);
|
||||
}
|
||||
|
||||
switch (instruction) {
|
||||
case aaload:
|
||||
frame->pushObject
|
||||
(c->load
|
||||
(BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord)));
|
||||
break;
|
||||
if (c->isConstant(index)) {
|
||||
unsigned i = c->constantValue(index);
|
||||
switch (instruction) {
|
||||
case aaload:
|
||||
frame->pushObject
|
||||
(c->load
|
||||
(BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord))));
|
||||
break;
|
||||
|
||||
case faload:
|
||||
case iaload:
|
||||
frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4)));
|
||||
break;
|
||||
case faload:
|
||||
case iaload:
|
||||
frame->pushInt(c->load(4, c->memory(array, ArrayBody + (i * 4))));
|
||||
break;
|
||||
|
||||
case baload:
|
||||
frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1)));
|
||||
break;
|
||||
case baload:
|
||||
frame->pushInt(c->load(1, c->memory(array, ArrayBody + i)));
|
||||
break;
|
||||
|
||||
case caload:
|
||||
frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
case caload:
|
||||
frame->pushInt(c->loadz(2, c->memory(array, ArrayBody + (i * 2))));
|
||||
break;
|
||||
|
||||
case daload:
|
||||
case laload:
|
||||
frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8)));
|
||||
break;
|
||||
case daload:
|
||||
case laload:
|
||||
frame->pushInt(c->load(8, c->memory(array, ArrayBody + (i * 8))));
|
||||
break;
|
||||
|
||||
case saload:
|
||||
frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
case saload:
|
||||
frame->pushInt(c->load(2, c->memory(array, ArrayBody + (i * 2))));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (instruction) {
|
||||
case aaload:
|
||||
frame->pushObject
|
||||
(c->load
|
||||
(BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord)));
|
||||
break;
|
||||
|
||||
case faload:
|
||||
case iaload:
|
||||
frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4)));
|
||||
break;
|
||||
|
||||
case baload:
|
||||
frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1)));
|
||||
break;
|
||||
|
||||
case caload:
|
||||
frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
|
||||
case daload:
|
||||
case laload:
|
||||
frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8)));
|
||||
break;
|
||||
|
||||
case saload:
|
||||
frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1667,17 +1713,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
if (CheckArrayBounds) {
|
||||
Compiler::Operand* store = c->label();
|
||||
Compiler::Operand* throw_ = c->label();
|
||||
Compiler::Operand* throw_ = 0;
|
||||
|
||||
c->cmp(4, c->constant(0), index);
|
||||
c->jl(throw_);
|
||||
if (c->isConstant(index)) {
|
||||
expect(t, c->constantValue(index) >= 0);
|
||||
} else {
|
||||
throw_ = c->label();
|
||||
c->cmp(4, c->constant(0), index);
|
||||
c->jl(throw_);
|
||||
}
|
||||
|
||||
c->cmp(BytesPerWord,
|
||||
c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)),
|
||||
index);
|
||||
c->jl(store);
|
||||
index,
|
||||
c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)));
|
||||
c->jge(store);
|
||||
|
||||
c->mark(throw_);
|
||||
if (not c->isConstant(index)) {
|
||||
c->mark(throw_);
|
||||
}
|
||||
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
|
||||
@ -1690,38 +1743,74 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->mark(store);
|
||||
}
|
||||
|
||||
switch (instruction) {
|
||||
case aastore: {
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
|
||||
context->indirection,
|
||||
0,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
4, c->thread(), array,
|
||||
c->add(4, c->constant(ArrayBody),
|
||||
c->shl(4, c->constant(log(BytesPerWord)), index)),
|
||||
value);
|
||||
} break;
|
||||
if (c->isConstant(index)) {
|
||||
unsigned i = c->constantValue(index);
|
||||
switch (instruction) {
|
||||
case aastore: {
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
|
||||
context->indirection,
|
||||
0,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
4, c->thread(), array,
|
||||
c->constant(ArrayBody + (i * BytesPerWord)),
|
||||
value);
|
||||
} break;
|
||||
|
||||
case fastore:
|
||||
case iastore:
|
||||
c->store(4, value, c->memory(array, ArrayBody, index, 4));
|
||||
break;
|
||||
case fastore:
|
||||
case iastore:
|
||||
c->store(4, value, c->memory(array, ArrayBody + (i * 4)));
|
||||
break;
|
||||
|
||||
case bastore:
|
||||
c->store(1, value, c->memory(array, ArrayBody, index, 1));
|
||||
break;
|
||||
case bastore:
|
||||
c->store(1, value, c->memory(array, ArrayBody + i));
|
||||
break;
|
||||
|
||||
case castore:
|
||||
case sastore:
|
||||
c->store(2, value, c->memory(array, ArrayBody, index, 2));
|
||||
break;
|
||||
case castore:
|
||||
case sastore:
|
||||
c->store(2, value, c->memory(array, ArrayBody + (i * 2)));
|
||||
break;
|
||||
|
||||
case dastore:
|
||||
case lastore:
|
||||
c->store(8, value, c->memory(array, ArrayBody, index, 8));
|
||||
break;
|
||||
case dastore:
|
||||
case lastore:
|
||||
c->store(8, value, c->memory(array, ArrayBody + (i * 8)));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (instruction) {
|
||||
case aastore: {
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
|
||||
context->indirection,
|
||||
0,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
4, c->thread(), array,
|
||||
c->add(4, c->constant(ArrayBody),
|
||||
c->shl(4, c->constant(log(BytesPerWord)), index)),
|
||||
value);
|
||||
} break;
|
||||
|
||||
case fastore:
|
||||
case iastore:
|
||||
c->store(4, value, c->memory(array, ArrayBody, index, 4));
|
||||
break;
|
||||
|
||||
case bastore:
|
||||
c->store(1, value, c->memory(array, ArrayBody, index, 1));
|
||||
break;
|
||||
|
||||
case castore:
|
||||
case sastore:
|
||||
c->store(2, value, c->memory(array, ArrayBody, index, 2));
|
||||
break;
|
||||
|
||||
case dastore:
|
||||
case lastore:
|
||||
c->store(8, value, c->memory(array, ArrayBody, index, 8));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1755,21 +1844,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
Compiler::Operand* nonnegative = c->label();
|
||||
|
||||
Compiler::Operand* length = frame->popInt();
|
||||
c->cmp(4, c->constant(0), length);
|
||||
c->jge(nonnegative);
|
||||
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
|
||||
context->indirection,
|
||||
Compiler::NoReturn,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
2, c->thread(), length);
|
||||
if (c->isConstant(length)) {
|
||||
expect(t, c->constantValue(length) >= 0);
|
||||
} else{
|
||||
Compiler::Operand* nonnegative = c->label();
|
||||
|
||||
c->mark(nonnegative);
|
||||
c->cmp(4, c->constant(0), length);
|
||||
c->jge(nonnegative);
|
||||
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
|
||||
context->indirection,
|
||||
Compiler::NoReturn,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
2, c->thread(), length);
|
||||
|
||||
c->mark(nonnegative);
|
||||
}
|
||||
|
||||
frame->pushObject
|
||||
(c->call
|
||||
@ -2924,22 +3018,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
case newarray: {
|
||||
uint8_t type = codeBody(t, code, ip++);
|
||||
|
||||
Compiler::Operand* nonnegative = c->label();
|
||||
|
||||
Compiler::Operand* length = frame->popInt();
|
||||
|
||||
c->cmp(4, c->constant(0), length);
|
||||
c->jge(nonnegative);
|
||||
if (c->isConstant(length)) {
|
||||
expect(t, c->constantValue(length) >= 0);
|
||||
} else{
|
||||
Compiler::Operand* nonnegative = c->label();
|
||||
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
|
||||
context->indirection,
|
||||
Compiler::NoReturn,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
2, c->thread(), length);
|
||||
c->cmp(4, c->constant(0), length);
|
||||
c->jge(nonnegative);
|
||||
|
||||
c->mark(nonnegative);
|
||||
c->call
|
||||
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
|
||||
context->indirection,
|
||||
Compiler::NoReturn,
|
||||
frame->trace(0, false),
|
||||
0,
|
||||
2, c->thread(), length);
|
||||
|
||||
c->mark(nonnegative);
|
||||
}
|
||||
|
||||
object (*constructor)(Thread*, uintptr_t, bool);
|
||||
switch (type) {
|
||||
@ -2985,7 +3083,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
0,
|
||||
frame->trace(0, false),
|
||||
BytesPerWord,
|
||||
2, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
|
||||
3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
|
||||
length));
|
||||
} break;
|
||||
|
||||
@ -3463,6 +3561,7 @@ finish(MyThread* t, Context* context)
|
||||
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
||||
|
||||
for (TraceElement* p = context->traceLog; p; p = p->next) {
|
||||
fprintf(stderr, "make node for %p\n", p);
|
||||
object node = makeTraceNode
|
||||
(t, p->address->value(), 0, context->method, p->target,
|
||||
p->virtualCall, mapSize, false);
|
||||
@ -3562,8 +3661,6 @@ compile(MyThread* t, Context* context)
|
||||
}
|
||||
}
|
||||
|
||||
handleEntrance(t, &frame);
|
||||
|
||||
compile(t, &frame, 0);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
|
119
src/compiler.cpp
119
src/compiler.cpp
@ -43,6 +43,8 @@ class Value {
|
||||
virtual void asAssemblerOperand(Context*,
|
||||
OperandType* type,
|
||||
Assembler::Operand** operand) = 0;
|
||||
|
||||
virtual int64_t constantValue(Context*) = 0;
|
||||
};
|
||||
|
||||
class MyOperand: public Compiler::Operand {
|
||||
@ -291,6 +293,10 @@ class ConstantValue: public Value {
|
||||
*operand = &value;
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Context*) {
|
||||
return value.value->value();
|
||||
}
|
||||
|
||||
Assembler::Constant value;
|
||||
};
|
||||
|
||||
@ -300,11 +306,17 @@ constant(Context* c, Promise* value)
|
||||
return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value);
|
||||
}
|
||||
|
||||
ResolvedPromise*
|
||||
resolved(Context* c, int64_t value)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(ResolvedPromise)))
|
||||
ResolvedPromise(value);
|
||||
}
|
||||
|
||||
ConstantValue*
|
||||
constant(Context* c, int64_t value)
|
||||
{
|
||||
return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise)))
|
||||
ResolvedPromise(value));
|
||||
return constant(c, resolved(c, value));
|
||||
}
|
||||
|
||||
class AddressValue: public Value {
|
||||
@ -323,6 +335,10 @@ class AddressValue: public Value {
|
||||
*operand = &address;
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Assembler::Address address;
|
||||
};
|
||||
|
||||
@ -385,6 +401,10 @@ class RegisterValue: public Value {
|
||||
*operand = ®ister_;
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Assembler::Register register_;
|
||||
};
|
||||
|
||||
@ -437,6 +457,10 @@ class MemoryValue: public Value {
|
||||
*operand = &value;
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Assembler::Memory value;
|
||||
};
|
||||
|
||||
@ -467,7 +491,7 @@ class AbstractMemoryValue: public MemoryValue {
|
||||
}
|
||||
|
||||
virtual int index(Context* c) {
|
||||
return index_ ? ::toRegister(c, base_) : NoRegister;
|
||||
return index_ ? ::toRegister(c, index_) : NoRegister;
|
||||
}
|
||||
|
||||
MyOperand* base_;
|
||||
@ -502,6 +526,10 @@ class StackValue: public Value {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Context* c) {
|
||||
abort(c);
|
||||
}
|
||||
|
||||
Stack* stack;
|
||||
};
|
||||
|
||||
@ -514,6 +542,8 @@ stackValue(Context* c, Stack* stack)
|
||||
class Event {
|
||||
public:
|
||||
Event(Context* c): next(0), stack(c->state->stack), promises(0) {
|
||||
assert(c, c->logicalIp >= 0);
|
||||
|
||||
if (c->event) {
|
||||
c->event->next = this;
|
||||
}
|
||||
@ -538,13 +568,37 @@ class Event {
|
||||
CodePromise* promises;
|
||||
};
|
||||
|
||||
class NullEvent: public Event {
|
||||
public:
|
||||
NullEvent(Context* c):
|
||||
Event(c)
|
||||
{ }
|
||||
|
||||
virtual Value* target(Context*, MyOperand*) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void compile(Context*) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
setEvent(Context* c, MyOperand* a, Event* e)
|
||||
{
|
||||
if (a->event) {
|
||||
a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c);
|
||||
} else{
|
||||
a->event = e;
|
||||
}
|
||||
}
|
||||
|
||||
class ArgumentEvent: public Event {
|
||||
public:
|
||||
ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index):
|
||||
Event(c), size(size), a(a), index(index)
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
setEvent(c, a, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
||||
@ -590,8 +644,7 @@ class ReturnEvent: public Event {
|
||||
Event(c), size(size), a(a)
|
||||
{
|
||||
if (a) {
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
setEvent(c, a, this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -643,8 +696,7 @@ class CallEvent: public Event {
|
||||
traceHandler(traceHandler),
|
||||
result(result)
|
||||
{
|
||||
assert(c, address->event == 0);
|
||||
address->event = this;
|
||||
setEvent(c, address, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
||||
@ -855,8 +907,7 @@ class MoveEvent: public Event {
|
||||
MyOperand* dst):
|
||||
Event(c), type(type), size(size), src(src), dst(dst)
|
||||
{
|
||||
assert(c, src->event == 0);
|
||||
src->event = this;
|
||||
setEvent(c, src, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
||||
@ -983,10 +1034,8 @@ class CompareEvent: public Event {
|
||||
CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b):
|
||||
Event(c), size(size), a(a), b(b)
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
assert(c, b->event == 0);
|
||||
b->event = this;
|
||||
setEvent(c, a, this);
|
||||
setEvent(c, b, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
|
||||
@ -1020,8 +1069,7 @@ class BranchEvent: public Event {
|
||||
BranchEvent(Context* c, UnaryOperation type, MyOperand* address):
|
||||
Event(c), type(type), address(address)
|
||||
{
|
||||
assert(c, address->event == 0);
|
||||
address->event = this;
|
||||
setEvent(c, address, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
|
||||
@ -1054,8 +1102,7 @@ class JumpEvent: public Event {
|
||||
Event(c),
|
||||
address(address)
|
||||
{
|
||||
assert(c, address->event == 0);
|
||||
address->event = this;
|
||||
setEvent(c, address, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) {
|
||||
@ -1087,10 +1134,8 @@ class CombineEvent: public Event {
|
||||
MyOperand* b, MyOperand* result):
|
||||
Event(c), type(type), size(size), a(a), b(b), result(result)
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
assert(c, b->event == 0);
|
||||
b->event = this;
|
||||
setEvent(c, a, this);
|
||||
setEvent(c, b, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
@ -1174,8 +1219,7 @@ class TranslateEvent: public Event {
|
||||
MyOperand* result):
|
||||
Event(c), type(type), size(size), a(a), result(result)
|
||||
{
|
||||
assert(c, a->event == 0);
|
||||
a->event = this;
|
||||
setEvent(c, a, this);
|
||||
}
|
||||
|
||||
virtual Value* target(Context* c, MyOperand* v UNUSED) {
|
||||
@ -1356,12 +1400,21 @@ compile(Context* c)
|
||||
a->apply(Push, BytesPerWord, Register, &base);
|
||||
a->apply(Move, BytesPerWord, Register, &stack, Register, &base);
|
||||
|
||||
if (c->stackOffset) {
|
||||
Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord));
|
||||
a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < c->logicalCodeLength; ++ i) {
|
||||
fprintf(stderr, "compile ip %d\n", i);
|
||||
for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) {
|
||||
e->compile(c);
|
||||
|
||||
if (e == c->logicalCode[i].lastEvent) break;
|
||||
|
||||
for (CodePromise* p = e->promises; p; p = p->next) {
|
||||
p->offset = a->length();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1408,8 +1461,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Promise* poolAppend(intptr_t value) {
|
||||
return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise)))
|
||||
ResolvedPromise(value));
|
||||
return poolAppendPromise(resolved(&c, value));
|
||||
}
|
||||
|
||||
virtual Promise* poolAppendPromise(Promise* value) {
|
||||
@ -1432,8 +1484,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Operand* constant(int64_t value) {
|
||||
return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise)))
|
||||
ResolvedPromise(value));
|
||||
return promiseConstant(resolved(&c, value));
|
||||
}
|
||||
|
||||
virtual Operand* promiseConstant(Promise* value) {
|
||||
@ -1468,6 +1519,16 @@ class MyCompiler: public Compiler {
|
||||
return operand(&c, register_(&c, c.assembler->thread()));
|
||||
}
|
||||
|
||||
virtual bool isConstant(Operand* a) {
|
||||
return static_cast<MyOperand*>(a)->value
|
||||
and static_cast<MyOperand*>(a)->value->type(&c) == Constant;
|
||||
}
|
||||
|
||||
virtual int64_t constantValue(Operand* a) {
|
||||
assert(&c, isConstant(a));
|
||||
return static_cast<MyOperand*>(a)->value->constantValue(&c);
|
||||
}
|
||||
|
||||
virtual Operand* label() {
|
||||
return operand(&c, ::constant(&c, static_cast<Promise*>(0)));
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ class Compiler {
|
||||
virtual Operand* base() = 0;
|
||||
virtual Operand* thread() = 0;
|
||||
|
||||
virtual bool isConstant(Operand* value) = 0;
|
||||
virtual int64_t constantValue(Operand* value) = 0;
|
||||
|
||||
virtual Operand* label() = 0;
|
||||
virtual void mark(Operand* label) = 0;
|
||||
|
||||
|
70
src/x86.cpp
70
src/x86.cpp
@ -224,6 +224,7 @@ void
|
||||
encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex)
|
||||
{
|
||||
if (b->traceHandler) {
|
||||
fprintf(stderr, "handle trace %p\n", b->traceHandler);
|
||||
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
|
||||
}
|
||||
|
||||
@ -239,6 +240,7 @@ encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b,
|
||||
bool rex)
|
||||
{
|
||||
if (b->traceHandler) {
|
||||
fprintf(stderr, "handle trace %p\n", b->traceHandler);
|
||||
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
|
||||
}
|
||||
|
||||
@ -331,6 +333,14 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a)
|
||||
c->code.append(0xe0 | a->low);
|
||||
}
|
||||
|
||||
void
|
||||
jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
conditional(c, 0x8d, a);
|
||||
}
|
||||
|
||||
void
|
||||
pushR(Context* c, unsigned size, Assembler::Register* a)
|
||||
{
|
||||
@ -552,6 +562,29 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
int64_t v = a->value->value();
|
||||
if (v) {
|
||||
rex(c);
|
||||
if (isInt8(v)) {
|
||||
c->code.append(0x83);
|
||||
c->code.append(0xe8 | b->low);
|
||||
c->code.append(v);
|
||||
} else if (isInt32(v)) {
|
||||
c->code.append(0x81);
|
||||
c->code.append(0xe8 | b->low);
|
||||
c->code.append4(v);
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
addRR(Context* c, unsigned size UNUSED, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
@ -598,7 +631,23 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 4, b, true);
|
||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true);
|
||||
if (isInt8(a->value->value())) {
|
||||
c->code.append(a->value->value());
|
||||
} else if (isInt32(a->value->value())) {
|
||||
c->code.append4(a->value->value());
|
||||
} else {
|
||||
abort(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Memory* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4);
|
||||
|
||||
encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true);
|
||||
if (isInt8(a->value->value())) {
|
||||
c->code.append(a->value->value());
|
||||
} else if (isInt32(a->value->value())) {
|
||||
@ -614,29 +663,44 @@ populateTables()
|
||||
Operations[Return] = return_;
|
||||
|
||||
UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC);
|
||||
UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC);
|
||||
UnaryOperations[INDEX1(Call, Register)] = CAST1(callR);
|
||||
UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM);
|
||||
|
||||
UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC);
|
||||
|
||||
UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR);
|
||||
|
||||
UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)]
|
||||
= CAST1(jumpIfGreaterOrEqualC);
|
||||
|
||||
UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR);
|
||||
UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM);
|
||||
|
||||
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
|
||||
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
|
||||
|
||||
BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR);
|
||||
|
||||
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
|
||||
BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM);
|
||||
BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM);
|
||||
BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR);
|
||||
BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR);
|
||||
BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR);
|
||||
BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR);
|
||||
|
||||
BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR);
|
||||
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
|
||||
|
||||
BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR);
|
||||
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
||||
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
|
||||
|
||||
BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR);
|
||||
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);
|
||||
|
||||
BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR);
|
||||
|
||||
BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM);
|
||||
}
|
||||
|
||||
class MyAssembler: public Assembler {
|
||||
|
Loading…
Reference in New Issue
Block a user