Deleting LIR and such, wiring up for HIR->x64.

This commit is contained in:
Ben Vanik
2014-01-24 22:26:15 -08:00
parent 55052b0d92
commit 8ae6053d0f
45 changed files with 538 additions and 2066 deletions

View File

@@ -11,14 +11,13 @@
#include <alloy/backend/x64/x64_backend.h>
#include <alloy/backend/x64/x64_code_cache.h>
#include <alloy/backend/x64/lir/lir_builder.h>
#include <third_party/xbyak/xbyak/xbyak.h>
#include <alloy/backend/x64/lowering/lowering_table.h>
#include <alloy/hir/hir_builder.h>
using namespace alloy;
using namespace alloy::backend;
using namespace alloy::backend::x64;
using namespace alloy::backend::x64::lir;
using namespace alloy::hir;
using namespace alloy::runtime;
using namespace Xbyak;
@@ -28,35 +27,21 @@ namespace alloy {
namespace backend {
namespace x64 {
class XbyakAllocator : public Allocator {
public:
virtual bool useProtect() const { return false; }
};
class XbyakGenerator : public CodeGenerator {
public:
XbyakGenerator(XbyakAllocator* allocator);
virtual ~XbyakGenerator();
void* Emplace(X64CodeCache* code_cache);
int Emit(LIRBuilder* builder);
private:
int EmitInstruction(LIRInstr* instr);
};
static const size_t MAX_CODE_SIZE = 1 * 1024 * 1024;
} // namespace x64
} // namespace backend
} // namespace alloy
X64Emitter::X64Emitter(X64Backend* backend) :
X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) :
backend_(backend),
code_cache_(backend->code_cache()) {
allocator_ = new XbyakAllocator();
generator_ = new XbyakGenerator(allocator_);
code_cache_(backend->code_cache()),
allocator_(allocator),
CodeGenerator(MAX_CODE_SIZE, AutoGrow, allocator) {
}
X64Emitter::~X64Emitter() {
delete generator_;
delete allocator_;
}
@@ -65,28 +50,21 @@ int X64Emitter::Initialize() {
}
int X64Emitter::Emit(
LIRBuilder* builder, void*& out_code_address, size_t& out_code_size) {
HIRBuilder* builder, void*& out_code_address, size_t& out_code_size) {
// Fill the generator with code.
int result = generator_->Emit(builder);
int result = Emit(builder);
if (result) {
return result;
}
// Copy the final code to the cache and relocate it.
out_code_size = generator_->getSize();
out_code_address = generator_->Emplace(code_cache_);
out_code_size = getSize();
out_code_address = Emplace(code_cache_);
return 0;
}
XbyakGenerator::XbyakGenerator(XbyakAllocator* allocator) :
CodeGenerator(1 * 1024 * 1024, AutoGrow, allocator) {
}
XbyakGenerator::~XbyakGenerator() {
}
void* XbyakGenerator::Emplace(X64CodeCache* code_cache) {
void* X64Emitter::Emplace(X64CodeCache* code_cache) {
// To avoid changing xbyak, we do a switcharoo here.
// top_ points to the Xbyak buffer, and since we are in AutoGrow mode
// it has pending relocations. We copy the top_ to our buffer, swap the
@@ -100,7 +78,7 @@ void* XbyakGenerator::Emplace(X64CodeCache* code_cache) {
return new_address;
}
int XbyakGenerator::Emit(LIRBuilder* builder) {
int X64Emitter::Emit(HIRBuilder* builder) {
// Function prolog.
// Must be 16b aligned.
// Windows is very strict about the form of this and the epilog:
@@ -119,6 +97,8 @@ int XbyakGenerator::Emit(LIRBuilder* builder) {
// TODO(benvanik): save registers.
}
auto lowering_table = backend_->lowering_table();
// Body.
auto block = builder->first_block();
while (block) {
@@ -130,18 +110,10 @@ int XbyakGenerator::Emit(LIRBuilder* builder) {
}
// Add instructions.
auto instr = block->instr_head;
while (instr) {
// Stash offset in debug info.
// TODO(benvanik): stash size_ value.
// Emit.
int result = EmitInstruction(instr);
if (result) {
return result;
}
instr = instr->next;
// The table will process sequences of instructions to (try to)
// generate optimal code.
if (lowering_table->ProcessBlock(*this, block)) {
return 1;
}
block = block->next;
@@ -157,67 +129,3 @@ int XbyakGenerator::Emit(LIRBuilder* builder) {
return 0;
}
int XbyakGenerator::EmitInstruction(LIRInstr* instr) {
switch (instr->opcode->num) {
case LIR_OPCODE_NOP:
nop();
break;
case LIR_OPCODE_COMMENT:
break;
case LIR_OPCODE_SOURCE_OFFSET:
break;
case LIR_OPCODE_DEBUG_BREAK:
// TODO(benvanik): replace with debugging primitive.
db(0xCC);
break;
case LIR_OPCODE_TRAP:
// TODO(benvanik): replace with debugging primitive.
db(0xCC);
break;
case LIR_OPCODE_MOV:
if (instr->arg1_type() == LIROperandType::OFFSET) {
// mov [reg+offset], value
mov(ptr[rax + *instr->arg1<intptr_t>()], rbx);
} else if (instr->arg2_type() == LIROperandType::OFFSET) {
// mov reg, [reg+offset]
mov(rbx, ptr[rax + *instr->arg2<intptr_t>()]);
} else {
// mov reg, reg
mov(rax, rbx);
}
break;
case LIR_OPCODE_MOV_ZX:
//mov
break;
case LIR_OPCODE_MOV_SX:
//mov
break;
case LIR_OPCODE_TEST:
if (instr->arg0_type() == LIROperandType::REGISTER) {
if (instr->arg1_type() == LIROperandType::REGISTER) {
//test(instr->arg0<LIRRegister>())
}
}
break;
case LIR_OPCODE_JUMP_EQ: {
auto target = (*instr->arg0<LIRLabel*>());
je(target->name, T_NEAR);
break;
}
case LIR_OPCODE_JUMP_NE: {
auto target = (*instr->arg0<LIRLabel*>());
jne(target->name, T_NEAR);
break;
}
default:
// Unhandled.
break;
}
return 0;
}