HIR->LIR flow.
This commit is contained in:
parent
cd9172ed62
commit
08cff81f6a
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_LIR_LIR_BLOCK_H_
|
||||
#define ALLOY_BACKEND_X64_LIR_LIR_BLOCK_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
namespace lir {
|
||||
|
||||
class LIRBuilder;
|
||||
class LIRInstr;
|
||||
class LIRLabel;
|
||||
|
||||
|
||||
class LIRBlock {
|
||||
public:
|
||||
Arena* arena;
|
||||
|
||||
LIRBlock* next;
|
||||
LIRBlock* prev;
|
||||
|
||||
LIRLabel* label_head;
|
||||
LIRLabel* label_tail;
|
||||
|
||||
LIRInstr* instr_head;
|
||||
LIRInstr* instr_tail;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lir
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_LIR_LIR_BLOCK_H_
|
|
@ -16,12 +16,20 @@ using namespace alloy::backend::x64::lir;
|
|||
|
||||
LIRBuilder::LIRBuilder(X64Backend* backend) :
|
||||
backend_(backend) {
|
||||
arena_ = new Arena();
|
||||
Reset();
|
||||
}
|
||||
|
||||
LIRBuilder::~LIRBuilder() {
|
||||
Reset();
|
||||
delete arena_;
|
||||
}
|
||||
|
||||
void LIRBuilder::Reset() {
|
||||
next_label_id_ = 0;
|
||||
block_head_ = block_tail_ = NULL;
|
||||
current_block_ = NULL;
|
||||
arena_->Reset();
|
||||
}
|
||||
|
||||
int LIRBuilder::Finalize() {
|
||||
|
@ -29,4 +37,140 @@ int LIRBuilder::Finalize() {
|
|||
}
|
||||
|
||||
void LIRBuilder::Dump(StringBuffer* str) {
|
||||
uint32_t block_ordinal = 0;
|
||||
auto block = block_head_;
|
||||
while (block) {
|
||||
if (block == block_head_) {
|
||||
str->Append("<entry>:\n");
|
||||
} else if (!block->label_head) {
|
||||
str->Append("<block%d>:\n", block_ordinal);
|
||||
}
|
||||
block_ordinal++;
|
||||
|
||||
auto label = block->label_head;
|
||||
while (label) {
|
||||
if (label->name) {
|
||||
str->Append("%s:\n", label->name);
|
||||
} else {
|
||||
str->Append("label%d:\n", label->id);
|
||||
}
|
||||
label = label->next;
|
||||
}
|
||||
|
||||
auto i = block->instr_head;
|
||||
while (i) {
|
||||
if (i->opcode->flags & LIR_OPCODE_FLAG_HIDE) {
|
||||
i = i->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(benvanik): handle comment
|
||||
|
||||
const LIROpcodeInfo* info = i->opcode;
|
||||
str->Append(" ");
|
||||
if (i->flags) {
|
||||
str->Append("%s.%d", info->name, i->flags);
|
||||
} else {
|
||||
str->Append("%s", info->name);
|
||||
}
|
||||
// TODO(benvanik): args based on signature
|
||||
str->Append("\n");
|
||||
i = i->next;
|
||||
}
|
||||
|
||||
block = block->next;
|
||||
}
|
||||
}
|
||||
|
||||
LIRBlock* LIRBuilder::current_block() const {
|
||||
return current_block_;
|
||||
}
|
||||
|
||||
LIRInstr* LIRBuilder::last_instr() const {
|
||||
if (current_block_ && current_block_->instr_tail) {
|
||||
return current_block_->instr_tail;
|
||||
} else if (block_tail_) {
|
||||
return block_tail_->instr_tail;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIRLabel* LIRBuilder::NewLabel() {
|
||||
LIRLabel* label = arena_->Alloc<LIRLabel>();
|
||||
label->next = label->prev = NULL;
|
||||
label->block = NULL;
|
||||
label->id = next_label_id_++;
|
||||
label->name = NULL;
|
||||
return label;
|
||||
}
|
||||
|
||||
void LIRBuilder::MarkLabel(LIRLabel* label, LIRBlock* block) {
|
||||
if (!block) {
|
||||
if (current_block_ && current_block_->instr_tail) {
|
||||
EndBlock();
|
||||
}
|
||||
if (!current_block_) {
|
||||
AppendBlock();
|
||||
}
|
||||
block = current_block_;
|
||||
}
|
||||
label->block = block;
|
||||
label->prev = block->label_tail;
|
||||
label->next = NULL;
|
||||
if (label->prev) {
|
||||
label->prev->next = label;
|
||||
block->label_tail = label;
|
||||
} else {
|
||||
block->label_head = block->label_tail = label;
|
||||
}
|
||||
}
|
||||
|
||||
LIRBlock* LIRBuilder::AppendBlock() {
|
||||
LIRBlock* block = arena_->Alloc<LIRBlock>();
|
||||
block->arena = arena_;
|
||||
block->next = NULL;
|
||||
block->prev = block_tail_;
|
||||
if (block_tail_) {
|
||||
block_tail_->next = block;
|
||||
}
|
||||
block_tail_ = block;
|
||||
if (!block_head_) {
|
||||
block_head_ = block;
|
||||
}
|
||||
current_block_ = block;
|
||||
block->label_head = block->label_tail = NULL;
|
||||
block->instr_head = block->instr_tail = NULL;
|
||||
return block;
|
||||
}
|
||||
|
||||
void LIRBuilder::EndBlock() {
|
||||
if (current_block_ && !current_block_->instr_tail) {
|
||||
// Block never had anything added to it. Since it likely has an
|
||||
// incoming edge, just keep it around.
|
||||
return;
|
||||
}
|
||||
current_block_ = NULL;
|
||||
}
|
||||
|
||||
LIRInstr* LIRBuilder::AppendInstr(
|
||||
const LIROpcodeInfo& opcode_info, uint16_t flags) {
|
||||
if (!current_block_) {
|
||||
AppendBlock();
|
||||
}
|
||||
LIRBlock* block = current_block_;
|
||||
|
||||
LIRInstr* instr = arena_->Alloc<LIRInstr>();
|
||||
instr->next = NULL;
|
||||
instr->prev = block->instr_tail;
|
||||
if (block->instr_tail) {
|
||||
block->instr_tail->next = instr;
|
||||
}
|
||||
block->instr_tail = instr;
|
||||
if (!block->instr_head) {
|
||||
block->instr_head = instr;
|
||||
}
|
||||
instr->block = block;
|
||||
instr->opcode = &opcode_info;
|
||||
instr->flags = flags;
|
||||
return instr;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#define ALLOY_BACKEND_X64_LIR_LIR_BUILDER_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/backend/x64/lir/lir_block.h>
|
||||
#include <alloy/backend/x64/lir/lir_instr.h>
|
||||
#include <alloy/backend/x64/lir/lir_label.h>
|
||||
#include <alloy/backend/x64/lir/lir_opcodes.h>
|
||||
|
||||
|
||||
|
@ -33,9 +36,28 @@ public:
|
|||
|
||||
Arena* arena() const { return arena_; }
|
||||
|
||||
LIRBlock* first_block() const { return block_head_; }
|
||||
LIRBlock* current_block() const;
|
||||
LIRInstr* last_instr() const;
|
||||
|
||||
LIRLabel* NewLabel();
|
||||
void MarkLabel(LIRLabel* label, LIRBlock* block = 0);
|
||||
|
||||
// TODO(benvanik): allocations
|
||||
|
||||
LIRBlock* AppendBlock();
|
||||
void EndBlock();
|
||||
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags);
|
||||
|
||||
protected:
|
||||
X64Backend* backend_;
|
||||
Arena* arena_;
|
||||
|
||||
uint32_t next_label_id_;
|
||||
|
||||
LIRBlock* block_head_;
|
||||
LIRBlock* block_tail_;
|
||||
LIRBlock* current_block_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,17 +11,85 @@
|
|||
#define ALLOY_BACKEND_X64_LIR_LIR_INSTR_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/backend/x64/lir/lir_block.h>
|
||||
#include <alloy/backend/x64/lir/lir_label.h>
|
||||
#include <alloy/backend/x64/lir/lir_opcodes.h>
|
||||
|
||||
|
||||
namespace alloy { namespace runtime { class FunctionInfo; } }
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
namespace lir {
|
||||
|
||||
|
||||
enum LIRRegister {
|
||||
REG8, REG16, REG32, REG64, REGXMM,
|
||||
|
||||
AL, AX, EAX, RAX,
|
||||
BL, BX, EBX, RBX,
|
||||
CL, CX, ECX, RCX,
|
||||
DL, DX, EDX, RDX,
|
||||
R8B, R8W, R8D, R8,
|
||||
R9B, R9W, R9D, R9,
|
||||
R10B, R10W, R10D, R10,
|
||||
R11B, R11W, R11D, R11,
|
||||
R12B, R12W, R12D, R12,
|
||||
R13B, R13W, R13D, R13,
|
||||
R14B, R14W, R14D, R14,
|
||||
R15B, R15W, R15D, R15,
|
||||
|
||||
SIL, SI, ESI, RSI,
|
||||
DIL, DI, EDI, RDI,
|
||||
|
||||
RBP,
|
||||
RSP,
|
||||
|
||||
XMM0,
|
||||
XMM1,
|
||||
XMM2,
|
||||
XMM3,
|
||||
XMM4,
|
||||
XMM5,
|
||||
XMM6,
|
||||
XMM7,
|
||||
XMM8,
|
||||
XMM9,
|
||||
XMM10,
|
||||
XMM11,
|
||||
XMM12,
|
||||
XMM13,
|
||||
XMM14,
|
||||
XMM15,
|
||||
};
|
||||
|
||||
|
||||
class LIRInstr {
|
||||
public:
|
||||
LIRBlock* block;
|
||||
LIRInstr* next;
|
||||
LIRInstr* prev;
|
||||
|
||||
const LIROpcodeInfo* opcode;
|
||||
uint16_t flags;
|
||||
|
||||
typedef union {
|
||||
runtime::FunctionInfo* symbol_info;
|
||||
LIRLabel* label;
|
||||
LIRRegister reg;
|
||||
int8_t i8;
|
||||
int16_t i16;
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
float f32;
|
||||
double f64;
|
||||
uint64_t offset;
|
||||
} Op;
|
||||
|
||||
// TODO(benvanik): make this variable width?
|
||||
Op arg[4];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_X64_LIR_LIR_LABEL_H_
|
||||
#define ALLOY_BACKEND_X64_LIR_LIR_LABEL_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
namespace lir {
|
||||
|
||||
class LIRBlock;
|
||||
|
||||
|
||||
class LIRLabel {
|
||||
public:
|
||||
LIRBlock* block;
|
||||
LIRLabel* next;
|
||||
LIRLabel* prev;
|
||||
|
||||
uint32_t id;
|
||||
char* name;
|
||||
|
||||
void* tag;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lir
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_X64_LIR_LIR_LABEL_H_
|
|
@ -1,9 +1,11 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'lir_block.h',
|
||||
'lir_builder.cc',
|
||||
'lir_builder.h',
|
||||
'lir_instr.h',
|
||||
'lir_label.h',
|
||||
'lir_opcodes.cc',
|
||||
'lir_opcodes.h',
|
||||
'lir_opcodes.inl',
|
||||
|
|
|
@ -395,46 +395,6 @@ public:
|
|||
#include <alloy/backend/x64/lowering/lowering_lir_opcodes.inl>
|
||||
}
|
||||
|
||||
enum {
|
||||
REG8, REG16, REG32, REG64, REGXMM,
|
||||
|
||||
AL, AX, EAX, RAX,
|
||||
BL, BX, EBX, RBX,
|
||||
CL, CX, ECX, RCX,
|
||||
DL, DX, EDX, RDX,
|
||||
R8B, R8W, R8D, R8,
|
||||
R9B, R9W, R9D, R9,
|
||||
R10B, R10W, R10D, R10,
|
||||
R11B, R11W, R11D, R11,
|
||||
R12B, R12W, R12D, R12,
|
||||
R13B, R13W, R13D, R13,
|
||||
R14B, R14W, R14D, R14,
|
||||
R15B, R15W, R15D, R15,
|
||||
|
||||
SIL, SI, ESI, RSI,
|
||||
DIL, DI, EDI, RDI,
|
||||
|
||||
RBP,
|
||||
RSP,
|
||||
|
||||
XMM0,
|
||||
XMM1,
|
||||
XMM2,
|
||||
XMM3,
|
||||
XMM4,
|
||||
XMM5,
|
||||
XMM6,
|
||||
XMM7,
|
||||
XMM8,
|
||||
XMM9,
|
||||
XMM10,
|
||||
XMM11,
|
||||
XMM12,
|
||||
XMM13,
|
||||
XMM14,
|
||||
XMM15,
|
||||
};
|
||||
|
||||
|
||||
void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
|
||||
Translate<tuple<
|
||||
|
|
|
@ -43,14 +43,60 @@ void LoweringTable::AddSequence(hir::Opcode starting_opcode, FnWrapper* fn) {
|
|||
lookup_[starting_opcode] = fn;
|
||||
}
|
||||
|
||||
int LoweringTable::Process(lir::LIRBuilder* builder) {
|
||||
/*LIRInstr* instr = 0;
|
||||
auto fn = lookup_[instr->opcode->num];
|
||||
while (fn) {
|
||||
if ((*fn)(builder, instr)) {
|
||||
return true;
|
||||
int LoweringTable::Process(
|
||||
hir::HIRBuilder* hir_builder, lir::LIRBuilder* lir_builder) {
|
||||
lir_builder->EndBlock();
|
||||
|
||||
// Translate all labels ahead of time.
|
||||
// We stash them on tags to make things easier later on.
|
||||
auto hir_block = hir_builder->first_block();
|
||||
while (hir_block) {
|
||||
auto hir_label = hir_block->label_head;
|
||||
while (hir_label) {
|
||||
// TODO(benvanik): copy name to LIR label.
|
||||
hir_label->tag = lir_builder->NewLabel();
|
||||
hir_label = hir_label->next;
|
||||
}
|
||||
fn = fn->next;
|
||||
}*/
|
||||
hir_block = hir_block->next;
|
||||
}
|
||||
|
||||
// Process each block.
|
||||
hir_block = hir_builder->first_block();
|
||||
while (hir_block) {
|
||||
// Force a new block.
|
||||
lir_builder->AppendBlock();
|
||||
|
||||
// Mark labels.
|
||||
auto hir_label = hir_block->label_head;
|
||||
while (hir_label) {
|
||||
auto lir_label = (lir::LIRLabel*)hir_label->tag;
|
||||
lir_builder->MarkLabel(lir_label);
|
||||
hir_label = hir_label->next;
|
||||
}
|
||||
|
||||
// Process instructions.
|
||||
auto hir_instr = hir_block->instr_head;
|
||||
while (hir_instr) {
|
||||
bool processed = false;
|
||||
auto fn = lookup_[hir_instr->opcode->num];
|
||||
while (fn) {
|
||||
if ((*fn)(lir_builder, hir_instr)) {
|
||||
processed = true;
|
||||
break;
|
||||
}
|
||||
fn = fn->next;
|
||||
}
|
||||
if (!processed) {
|
||||
// No sequence found!
|
||||
XELOGE("Unable to process HIR opcode %s", hir_instr->opcode->name);
|
||||
return 1;
|
||||
hir_instr = hir_instr->next;
|
||||
}
|
||||
}
|
||||
|
||||
lir_builder->EndBlock();
|
||||
hir_block = hir_block->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -11,15 +11,15 @@
|
|||
#define ALLOY_BACKEND_X64_X64_LOWERING_LOWERING_TABLE_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
#include <alloy/backend/x64/lir/lir_builder.h>
|
||||
#include <alloy/backend/x64/lir/lir_instr.h>
|
||||
#include <alloy/hir/instr.h>
|
||||
#include <alloy/hir/hir_builder.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace x64 {
|
||||
class X64Backend;
|
||||
namespace lir { class LIRBuilder; }
|
||||
namespace lowering {
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
|||
|
||||
int Initialize();
|
||||
|
||||
int Process(lir::LIRBuilder* builder);
|
||||
int Process(hir::HIRBuilder* hir_builder, lir::LIRBuilder* lir_builder);
|
||||
|
||||
public:
|
||||
class FnWrapper {
|
||||
|
|
|
@ -75,7 +75,7 @@ int X64Assembler::Assemble(
|
|||
|
||||
// Lower HIR -> LIR.
|
||||
auto lowering_table = x64_backend_->lowering_table();
|
||||
result = lowering_table->Process(builder_);
|
||||
result = lowering_table->Process(hir_builder, builder_);
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
// Stash raw LIR.
|
||||
|
@ -98,6 +98,15 @@ int X64Assembler::Assemble(
|
|||
|
||||
// Emit machine code.
|
||||
// TODO(benvanik): machine code.
|
||||
//result = emitter_->Emit(builder_, &machine_code, &length);
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
// Stash generated machine code.
|
||||
if (debug_info) {
|
||||
//emitter_->Dump(&string_buffer_);
|
||||
debug_info->set_machine_code_disasm(string_buffer_.ToString());
|
||||
string_buffer_.Reset();
|
||||
}
|
||||
|
||||
X64Function* fn = new X64Function(symbol_info);
|
||||
fn->set_debug_info(debug_info);
|
||||
|
|
|
@ -46,6 +46,7 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
|
|||
|
||||
Backend* backend = frontend->runtime()->backend();
|
||||
assembler_ = backend->CreateAssembler();
|
||||
assembler_->Initialize();
|
||||
}
|
||||
|
||||
PPCTranslator::~PPCTranslator() {
|
||||
|
|
Loading…
Reference in New Issue