mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
more work on new compiler; addition now works
This commit is contained in:
parent
5b2f351f01
commit
b9fa7179d9
@ -10,6 +10,8 @@ enum Operation {
|
||||
Return
|
||||
};
|
||||
|
||||
const unsigned OperationCount = Return + 1;
|
||||
|
||||
enum UnaryOperation {
|
||||
Call,
|
||||
Push,
|
||||
@ -23,19 +25,18 @@ enum UnaryOperation {
|
||||
Negate
|
||||
};
|
||||
|
||||
const unsigned UnaryOperationCount = Negate + 1;
|
||||
|
||||
enum BinaryOperation {
|
||||
LoadAddress,
|
||||
Move,
|
||||
Store1,
|
||||
Store2,
|
||||
Store4,
|
||||
Store8,
|
||||
Load1,
|
||||
Load2,
|
||||
Load2z,
|
||||
Load4,
|
||||
Load8,
|
||||
Load4To8,
|
||||
Move1,
|
||||
Move2,
|
||||
Move4,
|
||||
Move8,
|
||||
Move1ToW,
|
||||
Move2ToW,
|
||||
Move2zToW,
|
||||
Move4To8,
|
||||
Compare,
|
||||
Add,
|
||||
Subtract,
|
||||
@ -50,6 +51,10 @@ enum BinaryOperation {
|
||||
Xor
|
||||
};
|
||||
|
||||
const BinaryOperation Move = (BytesPerWord == 8 ? Move8 : Move4);
|
||||
|
||||
const unsigned BinaryOperationCount = Xor + 1;
|
||||
|
||||
enum OperandType {
|
||||
Constant,
|
||||
Address,
|
||||
@ -57,6 +62,8 @@ enum OperandType {
|
||||
Memory
|
||||
};
|
||||
|
||||
const unsigned OperandTypeCount = Memory + 1;
|
||||
|
||||
const int NoRegister = -1;
|
||||
const int AnyRegister = -2;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "vector.h"
|
||||
#include "process.h"
|
||||
#include "assembler.h"
|
||||
#include "compiler2.h"
|
||||
#include "compiler.h"
|
||||
#include "x86.h"
|
||||
|
||||
using namespace vm;
|
||||
@ -17,7 +17,7 @@ vmCall();
|
||||
|
||||
namespace {
|
||||
|
||||
const bool Verbose = false;
|
||||
const bool Verbose = true;
|
||||
const bool DebugNatives = false;
|
||||
const bool DebugTraces = false;
|
||||
const bool DebugFrameMaps = false;
|
||||
@ -403,7 +403,7 @@ class Context {
|
||||
{ }
|
||||
|
||||
~Context() {
|
||||
compiler->dispose();
|
||||
if (compiler) compiler->dispose();
|
||||
assembler->dispose();
|
||||
}
|
||||
|
||||
@ -3414,7 +3414,9 @@ finish(MyThread* t, Assembler* a, const char* name)
|
||||
|
||||
a->writeTo(start);
|
||||
|
||||
logCompile(start, a->length(), 0, name, 0);
|
||||
if (Verbose) {
|
||||
logCompile(start, a->length(), 0, name, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "compiler2.h"
|
||||
#include "compiler.h"
|
||||
#include "assembler.h"
|
||||
|
||||
using namespace vm;
|
||||
@ -527,11 +527,14 @@ class ReturnEvent: public Event {
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
a->value->release(c, a);
|
||||
if (a) {
|
||||
a->value->release(c, a);
|
||||
|
||||
if (not a->target->equals(a->value)) {
|
||||
apply(c, Move, a->size, a->value, a->target);
|
||||
if (not a->target->equals(a->value)) {
|
||||
apply(c, Move, a->size, a->value, a->target);
|
||||
}
|
||||
}
|
||||
|
||||
c->assembler->apply(Return);
|
||||
}
|
||||
|
||||
@ -743,7 +746,11 @@ class MoveEvent: public Event {
|
||||
virtual Value* target(Context* c, MyOperand* v) {
|
||||
assert(c, v == src);
|
||||
|
||||
return v->event->target(c, dst);
|
||||
if (dst->value) {
|
||||
return dst->value;
|
||||
} else {
|
||||
return v->event->target(c, dst);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void replace(Context* c, MyOperand* old, MyOperand* new_) {
|
||||
@ -754,7 +761,11 @@ class MoveEvent: public Event {
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
if (src->target == 0) {
|
||||
src->target = freeRegister(c, src->size);
|
||||
if (dst->value) {
|
||||
src->target = dst->value;
|
||||
} else {
|
||||
src->target = freeRegister(c, src->size);
|
||||
}
|
||||
}
|
||||
|
||||
src->value->release(c, src);
|
||||
@ -1127,8 +1138,14 @@ updateJunctions(Context* c)
|
||||
void
|
||||
compile(Context* c)
|
||||
{
|
||||
for (Event* e = c->logicalCode[0].firstEvent; e; e = e->next) {
|
||||
e->compile(c);
|
||||
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) {
|
||||
fprintf(stderr, "compile ip %d event\n", i);
|
||||
e->compile(c);
|
||||
|
||||
if (e == c->logicalCode[i].lastEvent) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1320,22 +1337,22 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual void store1(Operand* src, Operand* dst) {
|
||||
appendMove(&c, Store1, static_cast<MyOperand*>(src),
|
||||
appendMove(&c, Move1, static_cast<MyOperand*>(src),
|
||||
static_cast<MyOperand*>(dst));
|
||||
}
|
||||
|
||||
virtual void store2(Operand* src, Operand* dst) {
|
||||
appendMove(&c, Store2, static_cast<MyOperand*>(src),
|
||||
appendMove(&c, Move2, static_cast<MyOperand*>(src),
|
||||
static_cast<MyOperand*>(dst));
|
||||
}
|
||||
|
||||
virtual void store4(Operand* src, Operand* dst) {
|
||||
appendMove(&c, Store4, static_cast<MyOperand*>(src),
|
||||
appendMove(&c, Move4, static_cast<MyOperand*>(src),
|
||||
static_cast<MyOperand*>(dst));
|
||||
}
|
||||
|
||||
virtual void store8(Operand* src, Operand* dst) {
|
||||
appendMove(&c, Store8, static_cast<MyOperand*>(src),
|
||||
appendMove(&c, Move8, static_cast<MyOperand*>(src),
|
||||
static_cast<MyOperand*>(dst));
|
||||
}
|
||||
|
||||
@ -1347,37 +1364,39 @@ class MyCompiler: public Compiler {
|
||||
|
||||
virtual Operand* load1(Operand* src) {
|
||||
MyOperand* dst = operand(&c, BytesPerWord);
|
||||
appendMove(&c, Load1, static_cast<MyOperand*>(src), dst);
|
||||
appendMove(&c, Move1ToW, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual Operand* load2(Operand* src) {
|
||||
MyOperand* dst = operand(&c, BytesPerWord);
|
||||
appendMove(&c, Load2, static_cast<MyOperand*>(src), dst);
|
||||
appendMove(&c, Move2ToW, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual Operand* load2z(Operand* src) {
|
||||
MyOperand* dst = operand(&c, BytesPerWord);
|
||||
appendMove(&c, Load2z, static_cast<MyOperand*>(src), dst);
|
||||
appendMove(&c, Move2zToW, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual Operand* load4(Operand* src) {
|
||||
MyOperand* dst = operand(&c, BytesPerWord);
|
||||
appendMove(&c, Load4, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
if (BytesPerWord == 4) {
|
||||
return load(src);
|
||||
} else {
|
||||
return load4To8(src);
|
||||
}
|
||||
}
|
||||
|
||||
virtual Operand* load8(Operand* src) {
|
||||
MyOperand* dst = operand(&c, 8);
|
||||
appendMove(&c, Load8, static_cast<MyOperand*>(src), dst);
|
||||
appendMove(&c, Move8, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
virtual Operand* load4To8(Operand* src) {
|
||||
MyOperand* dst = operand(&c, 8);
|
||||
appendMove(&c, Load4To8, static_cast<MyOperand*>(src), dst);
|
||||
appendMove(&c, Move4To8, static_cast<MyOperand*>(src), dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
400
src/x86.cpp
400
src/x86.cpp
@ -3,9 +3,20 @@
|
||||
|
||||
using namespace vm;
|
||||
|
||||
#define INDEX1(a, b) ((a) + (BinaryOperationCount * (b)))
|
||||
|
||||
#define CAST1(x) reinterpret_cast<UnaryOperationType>(x)
|
||||
|
||||
#define INDEX2(a, b, c) \
|
||||
((a) \
|
||||
+ (BinaryOperationCount * (b)) \
|
||||
+ (BinaryOperationCount * OperandTypeCount * (c)))
|
||||
|
||||
#define CAST2(x) reinterpret_cast<BinaryOperationType>(x)
|
||||
|
||||
namespace {
|
||||
|
||||
enum Register {
|
||||
enum {
|
||||
rax = 0,
|
||||
rcx = 1,
|
||||
rdx = 2,
|
||||
@ -24,20 +35,355 @@ enum Register {
|
||||
r15 = 15,
|
||||
};
|
||||
|
||||
inline bool
|
||||
isInt8(intptr_t v)
|
||||
{
|
||||
return v == static_cast<int8_t>(v);
|
||||
}
|
||||
|
||||
inline bool
|
||||
isInt32(intptr_t v)
|
||||
{
|
||||
return v == static_cast<int32_t>(v);
|
||||
}
|
||||
|
||||
class Task;
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context(System* s, Allocator* a, Zone* zone):
|
||||
s(s), zone(zone), code(s, a, 1024), tasks(0), result(0)
|
||||
{ }
|
||||
|
||||
System* s;
|
||||
Zone* zone;
|
||||
Vector code;
|
||||
Task* tasks;
|
||||
uint8_t* result;
|
||||
};
|
||||
|
||||
inline void NO_RETURN
|
||||
abort(Context* c)
|
||||
{
|
||||
abort(c->s);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline void
|
||||
assert(Context* c, bool v)
|
||||
{
|
||||
assert(c->s, v);
|
||||
}
|
||||
#endif // not NDEBUG
|
||||
|
||||
inline void
|
||||
expect(Context* c, bool v)
|
||||
{
|
||||
expect(c->s, v);
|
||||
}
|
||||
|
||||
class CodePromise: public Promise {
|
||||
public:
|
||||
CodePromise(Context* c, unsigned offset): c(c), offset(offset) { }
|
||||
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>(c->result + offset);
|
||||
}
|
||||
|
||||
abort(c);
|
||||
}
|
||||
|
||||
virtual bool resolved() {
|
||||
return c->result != 0;
|
||||
}
|
||||
|
||||
Context* c;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
CodePromise*
|
||||
codePromise(Context* c, unsigned offset)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
|
||||
}
|
||||
|
||||
class Task {
|
||||
public:
|
||||
Task(Task* next): next(next) { }
|
||||
|
||||
virtual ~Task() { }
|
||||
|
||||
virtual void run(uint8_t* code) = 0;
|
||||
virtual void run(Context* c) = 0;
|
||||
|
||||
Task* next;
|
||||
};
|
||||
|
||||
class OffsetTask: public Task {
|
||||
public:
|
||||
OffsetTask(Task* next, Promise* promise, int instructionOffset,
|
||||
unsigned instructionSize):
|
||||
Task(next),
|
||||
promise(promise),
|
||||
instructionOffset(instructionOffset),
|
||||
instructionSize(instructionSize)
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c) {
|
||||
uint8_t* instruction = c->result + instructionOffset;
|
||||
intptr_t v = reinterpret_cast<uint8_t*>(promise->value())
|
||||
- instruction - instructionSize;
|
||||
|
||||
expect(c, isInt32(v));
|
||||
|
||||
int32_t v4 = v;
|
||||
memcpy(instruction + instructionSize - 4, &v4, 4);
|
||||
}
|
||||
|
||||
Promise* promise;
|
||||
int instructionOffset;
|
||||
unsigned instructionSize;
|
||||
};
|
||||
|
||||
void
|
||||
appendOffsetTask(Context* c, Promise* promise, int instructionOffset,
|
||||
unsigned instructionSize)
|
||||
{
|
||||
c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask
|
||||
(c->tasks, promise, instructionOffset, instructionSize);
|
||||
}
|
||||
|
||||
void
|
||||
encode(Context* c, uint8_t* instruction, unsigned length, int a, int b,
|
||||
int32_t displacement, int index, unsigned scale)
|
||||
{
|
||||
c->code.append(instruction, length);
|
||||
|
||||
uint8_t width;
|
||||
if (displacement == 0 and b != rbp) {
|
||||
width = 0;
|
||||
} else if (isInt8(displacement)) {
|
||||
width = 0x40;
|
||||
} else {
|
||||
width = 0x80;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
c->code.append(width | (a << 3) | b);
|
||||
if (b == rsp) {
|
||||
c->code.append(0x24);
|
||||
}
|
||||
} else {
|
||||
assert(c, b != rsp);
|
||||
c->code.append(width | (a << 3) | 4);
|
||||
c->code.append((log(scale) << 6) | (index << 3) | b);
|
||||
}
|
||||
|
||||
if (displacement == 0 and b != rbp) {
|
||||
// do nothing
|
||||
} else if (isInt8(displacement)) {
|
||||
c->code.append(displacement);
|
||||
} else {
|
||||
c->code.append4(displacement);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rex(Context* c)
|
||||
{
|
||||
if (BytesPerWord == 8) {
|
||||
c->code.append(0x48);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex)
|
||||
{
|
||||
if (b->traceHandler) {
|
||||
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
|
||||
}
|
||||
|
||||
if (rex) {
|
||||
::rex(c);
|
||||
}
|
||||
|
||||
encode(c, &instruction, 1, a, b->base, b->offset, b->index, b->scale);
|
||||
}
|
||||
|
||||
void
|
||||
encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b,
|
||||
bool rex)
|
||||
{
|
||||
if (b->traceHandler) {
|
||||
b->traceHandler->handleTrace(codePromise(c, c->code.length()));
|
||||
}
|
||||
|
||||
if (rex) {
|
||||
::rex(c);
|
||||
}
|
||||
|
||||
uint8_t i[2] = { instruction >> 8, instruction & 0xff };
|
||||
encode(c, i, 2, a, b->base, b->offset, b->index, b->scale);
|
||||
}
|
||||
|
||||
typedef void (*OperationType)(Context*);
|
||||
OperationType
|
||||
Operations[OperationCount];
|
||||
|
||||
typedef void (*UnaryOperationType)(Context*, unsigned, Assembler::Operand*);
|
||||
UnaryOperationType
|
||||
UnaryOperations[UnaryOperationCount * OperandTypeCount];
|
||||
|
||||
typedef void (*BinaryOperationType)
|
||||
(Context*, unsigned, Assembler::Operand*, Assembler::Operand*);
|
||||
BinaryOperationType
|
||||
BinaryOperations[BinaryOperationCount * OperandTypeCount * OperandTypeCount];
|
||||
|
||||
void
|
||||
return_(Context* c)
|
||||
{
|
||||
c->code.append(0xc3);
|
||||
}
|
||||
|
||||
void
|
||||
unconditional(Context* c, unsigned jump, Assembler::Constant* a)
|
||||
{
|
||||
appendOffsetTask(c, a->value, c->code.length(), 5);
|
||||
|
||||
c->code.append(jump);
|
||||
c->code.append4(0);
|
||||
}
|
||||
|
||||
void
|
||||
conditional(Context* c, unsigned condition, Assembler::Constant* a)
|
||||
{
|
||||
appendOffsetTask(c, a->value, c->code.length(), 6);
|
||||
|
||||
c->code.append(0x0f);
|
||||
c->code.append(condition);
|
||||
c->code.append4(0);
|
||||
}
|
||||
|
||||
void
|
||||
callC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
unconditional(c, 0xe8, a);
|
||||
}
|
||||
|
||||
void
|
||||
jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a)
|
||||
{
|
||||
assert(c, size == BytesPerWord);
|
||||
|
||||
c->code.append(0xff);
|
||||
c->code.append(0xd0 | a->low);
|
||||
}
|
||||
|
||||
void
|
||||
moveCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
rex(c);
|
||||
c->code.append(0xb8 | b->low);
|
||||
c->code.appendAddress(a->value->value());
|
||||
}
|
||||
|
||||
void
|
||||
moveCM(Context* c, unsigned size UNUSED, Assembler::Constant* a,
|
||||
Assembler::Memory* b)
|
||||
{
|
||||
assert(c, isInt32(a->value->value())); // todo
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
encode(c, 0xc7, 0, b, true);
|
||||
c->code.append4(a->value->value());
|
||||
}
|
||||
|
||||
void
|
||||
moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
moveRM(c, 4, a, b);
|
||||
|
||||
Assembler::Register ah(a->high);
|
||||
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);
|
||||
moveRM(c, 4, &ah, &bh);
|
||||
} else if (BytesPerWord == 8 and size == 4) {
|
||||
encode(c, 0x89, a->low, b, false);
|
||||
} else {
|
||||
encode(c, 0x89, a->low, b, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
moveRR(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
if (BytesPerWord == 4 and size == 8) {
|
||||
moveRR(c, 4, a, b);
|
||||
|
||||
Assembler::Register ah(a->low);
|
||||
Assembler::Register bh(b->low);
|
||||
moveRR(c, 4, &ah, &bh);
|
||||
} else {
|
||||
rex(c);
|
||||
c->code.append(0x89);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
move4To8MR(Context* c, unsigned, Assembler::Memory* a, Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8); // todo
|
||||
|
||||
encode(c, 0x63, b->low, a, true);
|
||||
}
|
||||
|
||||
void
|
||||
addRR(Context* c, unsigned size, Assembler::Register* a,
|
||||
Assembler::Register* b)
|
||||
{
|
||||
assert(c, BytesPerWord == 8 or size == 4); // todo
|
||||
|
||||
rex(c);
|
||||
c->code.append(0x01);
|
||||
c->code.append(0xc0 | (a->low << 3) | b->low);
|
||||
}
|
||||
|
||||
void
|
||||
populateTables()
|
||||
{
|
||||
Operations[Return] = return_;
|
||||
|
||||
UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC);
|
||||
UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR);
|
||||
|
||||
BinaryOperations[INDEX2(Move4, Constant, Register)] = CAST2(moveCR);
|
||||
BinaryOperations[INDEX2(Move8, Constant, Register)] = CAST2(moveCR);
|
||||
BinaryOperations[INDEX2(Move4, Constant, Memory)] = CAST2(moveCM);
|
||||
BinaryOperations[INDEX2(Move8, Constant, Memory)] = CAST2(moveCM);
|
||||
BinaryOperations[INDEX2(Move4, Register, Memory)] = CAST2(moveRM);
|
||||
BinaryOperations[INDEX2(Move8, Register, Memory)] = CAST2(moveRM);
|
||||
BinaryOperations[INDEX2(Move4, Register, Register)] = CAST2(moveRR);
|
||||
BinaryOperations[INDEX2(Move8, Register, Register)] = CAST2(moveRR);
|
||||
BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR);
|
||||
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
|
||||
}
|
||||
|
||||
class MyAssembler: public Assembler {
|
||||
public:
|
||||
MyAssembler(System* s, Allocator* a): s(s), code(s, a, 1024), tasks(0) { }
|
||||
MyAssembler(System* s, Allocator* a, Zone* zone): c(s, a, zone) {
|
||||
static bool populated = false;
|
||||
if (not populated) {
|
||||
populated = true;
|
||||
populateTables();
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned registerCount() {
|
||||
return BytesPerWord == 4 ? 8 : 16;
|
||||
@ -68,7 +414,7 @@ class MyAssembler: public Assembler {
|
||||
}
|
||||
|
||||
virtual int argumentRegister(unsigned index) {
|
||||
assert(s, BytesPerWord == 8);
|
||||
assert(&c, BytesPerWord == 8);
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
@ -84,7 +430,7 @@ class MyAssembler: public Assembler {
|
||||
case 5:
|
||||
return r9;
|
||||
default:
|
||||
abort(s);
|
||||
abort(&c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +447,7 @@ class MyAssembler: public Assembler {
|
||||
case 4:
|
||||
return rdi;
|
||||
default:
|
||||
abort(s);
|
||||
abort(&c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,42 +469,40 @@ class MyAssembler: public Assembler {
|
||||
b->high = NoRegister;
|
||||
}
|
||||
|
||||
virtual void apply(Operation /*op*/) {
|
||||
// todo
|
||||
abort(s);
|
||||
virtual void apply(Operation op) {
|
||||
Operations[op](&c);
|
||||
}
|
||||
|
||||
virtual void apply(UnaryOperation /*op*/, unsigned /*size*/,
|
||||
OperandType /*type*/, Operand* /*operand*/)
|
||||
virtual void apply(UnaryOperation op, unsigned size,
|
||||
OperandType type, Operand* operand)
|
||||
{
|
||||
// todo
|
||||
abort(s);
|
||||
UnaryOperations[INDEX1(op, type)](&c, size, operand);
|
||||
}
|
||||
|
||||
virtual void apply(BinaryOperation /*op*/, unsigned /*size*/,
|
||||
OperandType /*aType*/, Operand* /*a*/,
|
||||
OperandType /*bType*/, Operand* /*b*/)
|
||||
virtual void apply(BinaryOperation op, unsigned size,
|
||||
OperandType aType, Operand* a,
|
||||
OperandType bType, Operand* b)
|
||||
{
|
||||
// todo
|
||||
abort(s);
|
||||
BinaryOperations[INDEX2(op, aType, bType)](&c, size, a, b);
|
||||
}
|
||||
|
||||
virtual void writeTo(uint8_t* dst) {
|
||||
memcpy(dst, code.data, code.length());
|
||||
c.result = dst;
|
||||
memcpy(dst, c.code.data, c.code.length());
|
||||
|
||||
for (Task* t = tasks; t; t = t->next) {
|
||||
t->run(dst);
|
||||
for (Task* t = c.tasks; t; t = t->next) {
|
||||
t->run(&c);
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned length() {
|
||||
return code.length();
|
||||
return c.code.length();
|
||||
}
|
||||
|
||||
virtual void updateCall(void* returnAddress, void* newTarget) {
|
||||
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
|
||||
assert(s, *instruction == 0xE8);
|
||||
assert(s, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
||||
assert(&c, *instruction == 0xE8);
|
||||
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
|
||||
|
||||
int32_t v = static_cast<uint8_t*>(newTarget)
|
||||
- static_cast<uint8_t*>(returnAddress);
|
||||
@ -166,12 +510,10 @@ class MyAssembler: public Assembler {
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
code.dispose();
|
||||
c.code.dispose();
|
||||
}
|
||||
|
||||
System* s;
|
||||
Vector code;
|
||||
Task* tasks;
|
||||
Context c;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -182,7 +524,7 @@ Assembler*
|
||||
makeAssembler(System* system, Allocator* allocator, Zone* zone)
|
||||
{
|
||||
return new (zone->allocate(sizeof(MyAssembler)))
|
||||
MyAssembler(system, allocator);
|
||||
MyAssembler(system, allocator, zone);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
202
test/Misc.java
202
test/Misc.java
@ -1,120 +1,124 @@
|
||||
public class Misc {
|
||||
private static int alpha;
|
||||
private static int beta;
|
||||
private static byte byte1, byte2, byte3;
|
||||
private int gamma;
|
||||
// private static int alpha;
|
||||
// private static int beta;
|
||||
// private static byte byte1, byte2, byte3;
|
||||
// private int gamma;
|
||||
|
||||
private String foo(String s) {
|
||||
return s;
|
||||
}
|
||||
// private String foo(String s) {
|
||||
// return s;
|
||||
// }
|
||||
|
||||
public String bar(String s) {
|
||||
return s;
|
||||
}
|
||||
// public String bar(String s) {
|
||||
// return s;
|
||||
// }
|
||||
|
||||
private static String baz(String s) {
|
||||
return s;
|
||||
}
|
||||
// private static String baz(String s) {
|
||||
// return s;
|
||||
// }
|
||||
|
||||
private static void expect(boolean v) {
|
||||
if (! v) throw new RuntimeException();
|
||||
}
|
||||
// private static void expect(boolean v) {
|
||||
// if (! v) throw new RuntimeException();
|
||||
// }
|
||||
|
||||
private synchronized byte sync() {
|
||||
byte[] array = new byte[123];
|
||||
return array[42];
|
||||
}
|
||||
// private synchronized byte sync() {
|
||||
// byte[] array = new byte[123];
|
||||
// return array[42];
|
||||
// }
|
||||
|
||||
private static synchronized byte syncStatic(boolean throw_) {
|
||||
byte[] array = new byte[123];
|
||||
if (throw_) {
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
return array[42];
|
||||
}
|
||||
}
|
||||
// private static synchronized byte syncStatic(boolean throw_) {
|
||||
// byte[] array = new byte[123];
|
||||
// if (throw_) {
|
||||
// throw new RuntimeException();
|
||||
// } else {
|
||||
// return array[42];
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void putInt(int val, byte[] dst, int offset) {
|
||||
System.out.println("put " + val);
|
||||
dst[offset] = (byte)((val >> 24) & 0xff);
|
||||
dst[offset+1] = (byte)((val >> 16) & 0xff);
|
||||
dst[offset+2] = (byte)((val >> 8) & 0xff);
|
||||
dst[offset+3] = (byte)((val ) & 0xff);
|
||||
}
|
||||
// public static void putInt(int val, byte[] dst, int offset) {
|
||||
// System.out.println("put " + val);
|
||||
// dst[offset] = (byte)((val >> 24) & 0xff);
|
||||
// dst[offset+1] = (byte)((val >> 16) & 0xff);
|
||||
// dst[offset+2] = (byte)((val >> 8) & 0xff);
|
||||
// dst[offset+3] = (byte)((val ) & 0xff);
|
||||
// }
|
||||
|
||||
public static void putLong(long val, byte[] dst, int offset) {
|
||||
putInt((int)(val >> 32), dst, offset);
|
||||
putInt((int)val, dst, offset + 4);
|
||||
}
|
||||
// public static void putLong(long val, byte[] dst, int offset) {
|
||||
// putInt((int)(val >> 32), dst, offset);
|
||||
// putInt((int)val, dst, offset + 4);
|
||||
// }
|
||||
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
// public String toString() {
|
||||
// return super.toString();
|
||||
// }
|
||||
|
||||
public static void main(String[] args) {
|
||||
byte2 = 0;
|
||||
expect(byte2 == 0);
|
||||
|
||||
Misc m = new Misc();
|
||||
m.toString();
|
||||
|
||||
expect(Long.valueOf(231L) == 231L);
|
||||
|
||||
long x = 231;
|
||||
expect((x >> 32) == 0);
|
||||
expect((x >>> 32) == 0);
|
||||
expect((x << 32) == 992137445376L);
|
||||
|
||||
long y = -231;
|
||||
expect((y >> 32) == 0xffffffffffffffffL);
|
||||
expect((y >>> 32) == 0xffffffffL);
|
||||
|
||||
byte[] array = new byte[8];
|
||||
putLong(231, array, 0);
|
||||
expect((array[0] & 0xff) == 0);
|
||||
expect((array[1] & 0xff) == 0);
|
||||
expect((array[2] & 0xff) == 0);
|
||||
expect((array[3] & 0xff) == 0);
|
||||
expect((array[4] & 0xff) == 0);
|
||||
expect((array[5] & 0xff) == 0);
|
||||
expect((array[6] & 0xff) == 0);
|
||||
expect((array[7] & 0xff) == 231);
|
||||
|
||||
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
||||
buffer.putLong(231);
|
||||
buffer.flip();
|
||||
expect(buffer.getLong() == 231);
|
||||
|
||||
boolean v = Boolean.valueOf("true");
|
||||
|
||||
ClassLoader.getSystemClassLoader().toString();
|
||||
|
||||
int a = 2;
|
||||
int b = 2;
|
||||
int c = a + b;
|
||||
|
||||
String s = "hello";
|
||||
m.foo(s);
|
||||
m.bar(s);
|
||||
baz(s);
|
||||
// byte2 = 0;
|
||||
// expect(byte2 == 0);
|
||||
|
||||
m.sync();
|
||||
syncStatic(false);
|
||||
try {
|
||||
syncStatic(true);
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Misc m = new Misc();
|
||||
// m.toString();
|
||||
|
||||
int d = alpha;
|
||||
beta = 42;
|
||||
alpha = 43;
|
||||
int e = beta;
|
||||
int f = alpha;
|
||||
m.gamma = 44;
|
||||
// expect(Long.valueOf(231L) == 231L);
|
||||
|
||||
expect(beta == 42);
|
||||
expect(alpha == 43);
|
||||
expect(m.gamma == 44);
|
||||
// long x = 231;
|
||||
// expect((x >> 32) == 0);
|
||||
// expect((x >>> 32) == 0);
|
||||
// expect((x << 32) == 992137445376L);
|
||||
|
||||
// long y = -231;
|
||||
// expect((y >> 32) == 0xffffffffffffffffL);
|
||||
// expect((y >>> 32) == 0xffffffffL);
|
||||
|
||||
// byte[] array = new byte[8];
|
||||
// putLong(231, array, 0);
|
||||
// expect((array[0] & 0xff) == 0);
|
||||
// expect((array[1] & 0xff) == 0);
|
||||
// expect((array[2] & 0xff) == 0);
|
||||
// expect((array[3] & 0xff) == 0);
|
||||
// expect((array[4] & 0xff) == 0);
|
||||
// expect((array[5] & 0xff) == 0);
|
||||
// expect((array[6] & 0xff) == 0);
|
||||
// expect((array[7] & 0xff) == 231);
|
||||
|
||||
// java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(8);
|
||||
// buffer.putLong(231);
|
||||
// buffer.flip();
|
||||
// expect(buffer.getLong() == 231);
|
||||
|
||||
// boolean v = Boolean.valueOf("true");
|
||||
|
||||
// ClassLoader.getSystemClassLoader().toString();
|
||||
|
||||
// int a = 2;
|
||||
// int b = 2;
|
||||
// int c = a + b;
|
||||
|
||||
// String s = "hello";
|
||||
// m.foo(s);
|
||||
// m.bar(s);
|
||||
// baz(s);
|
||||
|
||||
// m.sync();
|
||||
// syncStatic(false);
|
||||
// try {
|
||||
// syncStatic(true);
|
||||
// } catch (RuntimeException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
// int d = alpha;
|
||||
// beta = 42;
|
||||
// alpha = 43;
|
||||
// int e = beta;
|
||||
// int f = alpha;
|
||||
// m.gamma = 44;
|
||||
|
||||
// expect(beta == 42);
|
||||
// expect(alpha == 43);
|
||||
// expect(m.gamma == 44);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user